はじめに
この記事は、タイトルにも書いた gpt-oss-120b(OpenAI のオープンなモデル「gpt-oss」の 2種類あるうちの 1つ)の話です。
それを OpenAI公式のプレイグラウンド(ログイン不要でブラウザで gpt-oss が使える環境)で試した話です(※ そのお試しの様子を動画にしたものが以下です)。
gpt-oss について
gpt-oss は、OpenAI が公開したオープンなモデルで、「gpt-oss-120b」と「gpt-oss-20b」の 2種類が公開されています。
公式の記事
以下は gpt-oss がリリースされたタイミングで出た、公式の記事のうちの 1つです。
●OpenAI が提供するオープンモデル | OpenAI
https://openai.com/ja-JP/open-models/
公式のプレイグラウンド(ログイン不要でブラウザで利用可能なもの)
この gpt-oss について、OpenAI が公式でプレイグラウンド(ログイン不要でブラウザで利用可能なもの ⇒ https://gpt-oss.com/ )を出しています。
公式のプレイグラウンドの画面
https://gpt-oss.com/ にアクセスすると、以下のようなページになっています。
2つのモデルを切り替えられたり、推論のレベルを変えられたりするようです。
試した内容
冒頭の動画は、とりあえず上記のプレイグラウンドで、雑に「p5.jsのパーティクルのプログラム
」というプロンプトで試してみたものです。
回答の生成は、かなり速いスピードで行われていた印象でした。
ちなみに、今回のプロンプトを入力した冒頭の部分は以下のとおりです。
簡単な説明の後に、コード全体が示されています(その後に、さらに解説なども続いています)。
今回生成された内容
以下に折りたたみで、公式プレイグラウンドで生成された内容全体を掲載してみます。
【折りたたみ】公式プレイグラウンドで生成された内容全体
以下は p5.js で動くシンプルなパーティクルシステムのサンプルです。
- マウスをクリック(またはドラッグ)するとその位置から粒子が放出されます。
- 粒子は速度・加速度(重力)・寿命・フェードアウトを持ち、色や大きさはランダムに決まります。
-
Particle
クラスとParticleSystem
クラスでオブジェクト指向的に実装しているので、拡張しやすい構造です。
1️⃣ コード全体(HTML + JavaScript)
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>p5.js パーティクルデモ</title>
<!-- p5.js CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.9.0/p5.min.js"></script>
<!-- 任意で p5.sound が必要なら追加 -->
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.9.0/addons/p5.sound.min.js"></script> -->
<style>
body { margin:0; overflow:hidden; background:#111; } /* 背景を暗くすると粒子が映える */
</style>
</head>
<body>
<script>
// ---------------------------------------------------
// 1. Particle クラス(1粒の粒子)
// ---------------------------------------------------
class Particle {
/**
* @param {p5.Vector} position 初期位置
* @param {p5.Color} col 粒子の色
*/
constructor(position, col) {
// 位置・速度・加速度はベクトルで管理
this.pos = position.copy();
// ランダムな初速(円形に放射)
const angle = random(TWO_PI);
const speed = random(1, 5);
this.vel = p5.Vector.fromAngle(angle).mult(speed);
// 重力(y方向の加速度)を少しだけ入れて自然に落ちるようにする
this.acc = createVector(0, 0.05);
// 見た目・寿命
this.lifespan = 255; // 255 がフル、0 になると消える
this.size = random(4, 12);
this.col = col;
}
// 更新処理
update() {
this.vel.add(this.acc);
this.pos.add(this.vel);
// 寿命を徐々に減らす(フェードアウト)
this.lifespan -= 4;
}
// 描画処理
draw() {
// 寿命が減ると透明度も減らす
const alpha = map(this.lifespan, 0, 255, 0, 255);
noStroke();
fill(red(this.col), green(this.col), blue(this.col), alpha);
ellipse(this.pos.x, this.pos.y, this.size);
}
// 生きているか判定(寿命が残っているか)
isAlive() {
return this.lifespan > 0;
}
}
// ---------------------------------------------------
// 2. ParticleSystem クラス(粒子の集合体)
// ---------------------------------------------------
class ParticleSystem {
/**
* @param {p5.Vector} origin 発生源座標
*/
constructor(origin) {
this.origin = origin.copy(); // パーティクル生成時の基準点
this.particles = []; // Particle インスタンスの配列
// 発生させる粒子の色はここで決めておくと統一感が出る
this.baseColor = color(random(200, 255), random(100, 200), random(0, 150));
}
// 新しい粒子を n 個生成
addParticle(n = 5) {
for (let i = 0; i < n; i++) {
const p = new Particle(this.origin, this.baseColor);
this.particles.push(p);
}
}
// すべての粒子を更新・描画し、死んだものは配列から除去
run() {
// 逆順に走査しながら削除するとインデックスがずれない
for (let i = this.particles.length - 1; i >= 0; i--) {
const p = this.particles[i];
p.update();
p.draw();
if (!p.isAlive()) {
this.particles.splice(i, 1);
}
}
}
// 発生源を任意の位置に変更(マウスドラッグ時に便利)
setOrigin(x, y) {
this.origin.set(x, y);
}
}
// ---------------------------------------------------
// 3. p5.js のスケッチ本体
// ---------------------------------------------------
let system; // 1つだけシステムを作る(単純化のため)
function setup() {
createCanvas(windowWidth, windowHeight);
// 初期発生源は画面中心
system = new ParticleSystem(createVector(width / 2, height / 2));
background(0);
}
function draw() {
// 背景のフェードアウトで軌跡を残す
// (0,0,0,25) の黒い半透明矩形を描画して徐々に暗くする
fill(0, 0, 0, 25);
rect(0, 0, width, height);
// パーティクルシステムの更新・描画
system.run();
}
// マウスをクリックしたら新たに粒子を放出
function mousePressed() {
// 発生源をクリック位置に移動
system.setOrigin(mouseX, mouseY);
// 30 個くらい一気に放出すると見栄えが良い
system.addParticle(30);
}
// マウスをドラッグすると連続で放出
function mouseDragged() {
system.setOrigin(mouseX, mouseY);
system.addParticle(5);
}
// ウインドウがリサイズされたらキャンバスもサイズ変更
function windowResized() {
resizeCanvas(windowWidth, windowHeight);
}
</script>
</body>
</html>
2️⃣ コードのポイント解説
項目 | 説明 |
---|---|
Particle クラス | 1粒の粒子を表す。位置・速度・加速度・色・サイズ・寿命を持ち、update() → 位置・速度を更新、draw() → 描画、isAlive() → 寿命が残っているかを判定。 |
ParticleSystem クラス | 複数の Particle を管理。addParticle() でまとめて生成し、run() で全粒子を更新・描画し、寿命が尽きたものは配列から削除。 |
重力 |
acc = createVector(0, 0.05); として y 軸方向に一定の加速度を与えている。好きな方向に変えると斜め落下や逆重力も実装可能。 |
色・透明度 |
fill(r,g,b,alpha) で寿命に比例した透明度(フェードアウト)を付与。baseColor をシステムごとに決めると統一感が出る。 |
背景のフェード |
fill(0,0,0,25); rect(...); として半透明の黒で毎フレーム覆うと、過去の軌跡が徐々に消えていく効果が得られる。 |
インタラクション |
mousePressed() でクリック位置から大量に放出、mouseDragged() でドラッグしながら少量放出。 setOrigin() で発生源をマウス位置に追従させている。 |
ウインドウリサイズ |
windowResized() でキャンバスサイズを自動調整(ブラウザのサイズ変更に対応)。 |
3️⃣ カスタマイズ例(自由に試してみてください)
変更点 | 実装例 |
---|---|
粒子の数 |
system.addParticle(50); のように数値を増やすと一度に出る粒子が多くなる。 |
重力・風 |
this.acc = createVector(0.02, 0.05); とすれば右方向に風がかかる。 |
色のバリエーション |
this.baseColor = color(random(255), random(255), random(255)); にすれば虹色がランダムに生成。 |
形状 |
ellipse() を rect() や point() に変えると形が変わる。 |
サイズの変化 |
this.size *= 0.97; のように毎フレーム小さくすれば、遠ざかるように見える。 |
テクスチャ |
loadImage() で画像を読み込み、image(img, this.pos.x, this.pos.y, this.size, this.size); と描画すればスプライト粒子にできる。 |
音 |
p5.sound ライブラリを追加し、mousePressed() で sound.play(); すればクリック音やパーティクルが出たときの効果音を付けられる。 |
4️⃣ 実行方法
- 上記の HTML コード全体をコピーします。
- 任意のテキストエディタで
particle_demo.html
という名前で保存。 - ブラウザでそのファイルを開くか、p5.js Web Editor に貼り付けて Run ボタンを押すだけで動作します。
(Web Editor を使う場合は、index.html
の <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.9.0/p5.min.js"></script>
の行は不要です。エディタが自動で p5.js を読み込んでくれます。)
🎉 まとめ
- Particle と ParticleSystem の 2 クラスでシンプルかつ拡張性の高いパーティクルエンジンが完成。
- マウス操作や背景フェードでインタラクティブかつ美しいビジュアルが手軽に作れます。
- コード中のコメントやテーブルに書いたヒントを参考に、色・形・動き・音など自由にカスタマイズしてみてください。
質問や「別のエフェクト」・「物理的にもっとリアルに」など、追加で実装したいことがあれば遠慮なく聞いてくださいね! 🚀
その他
今回の記事では、OpenAI公式のプレイグラウンドで試しましたが、その他の利用方法のうちの 1つを掲載してみます。
Ollama関連
gpt-oss を使う方法の 1つに Ollamaを使ったものがあります。
Ollama上で使えるもの
Ollama では gpt-oss のモデルが既に利用可能になっています。
gpt-oss に関する Ollama のページ(モデルの情報のページ)では、以下のような情報が確認できます。
モデルサイズは、65GB(gpt-oss-120b)と 14GB(gpt-oss-20b)で、どちらもコンテキストウィンドウは 128K になるようです。
OpenAI から出ている情報
また、OpenAI から出ている Ollama関連の情報も見てみます。
例えば、OpenAI公式のクックブックに、使い方(ローカルサーバーでの API利用や ADKインテグレーションの話なども含む)が出ています。
中を見てみると、 ollama run
コマンドで使う方法の話以外に、ローカルサーバーで API を使う話や、Agents SDK と組み合わせて使う話なども書かれているようでした。
●How to run gpt-oss locally with Ollama
https://cookbook.openai.com/articles/gpt-oss/run-locally-ollama
【追記】 Ollama を使ったローカルLLM を試してみた
その後、自宅にある M4 の Mac mini(ユニファイドメモリ 24GB) + Ollama で、gpt-oss-20b を使ったローカルLLM も試してみました。
【追記】 Hugging Face Inference Providers を使った API利用
Hugging Face Inference Providers を使って、gpt-oss-120b を API経由で試してみて、その流れを記事にもしてみました。
●【Node.js】 Hugging Face の「How to use OpenAI’s GPT OSS」に書かれている内容を試してみた(OpenAI の gpt-oss-120b を API で使う) - Qiita
https://qiita.com/youtoy/items/8a6fed0448a9a2cfb180
Node.js実装で、ストリーミング出力させた時の様子は以下のような感じだったのですが、出力速度が良い感じでした!
【追記】 LM Studio を使ったローカルLLM を試してみた
自宅にある M4 の Mac mini(ユニファイドメモリ 24GB) + LM Studio で、gpt-oss-20b を使ったローカルLLM も試してみました。