世の中ChatGPT-5で盛り上がっていますが、今回は2週間前にリリースされたgpt-oss-20bの話題です。
私のMac-miniは32Gbyteメモリーがあるので、リリース直後にgpt-oss-20bをダウンロードし動かてみましました。
しかし、VS CodeプラグインのClineやRoo Codeからの利用は上手く行かなかったので評価が止まっていました。
ところが、gpt-oss-20bのプロンプト(正確にはローカルLLMツールOllamaのプロンプト)に「・・・のNext.jsコードを書いて」と依頼すると当然プロジェクトやファイルは作成されませんが、app/page.tsx
のコード等は表示されるので、その内容をコピペして行けばNext.jsのプロジェクトが作れ、gpt-oss-20bのプログラミング能力が調べられる事が判りました!
Bing Image Creatorが生成した画像を使っています
以前Qwen3に作ってもらったコードを作ってもらった
以前のブログでQwen3に作ってもらった簡単なジャンケンアプリを作ってもらいました。プロンプトは以下です。
# ジャンケンを行うReactアプリを作って下さい
## 画面仕様
- 人間はグー、チョキ、パーのボタンを押し、コンピューターは乱数でジャンケンの手を作り対戦します
- 勝敗(勝ち、負け、引き分け)はコンピューターが判定します
- 対戦の結果(人間の手、コンピューターの手、勝敗)を表形式で表示します
## 環境
- プロジェクトを新規に作成してください
- フレームワークはNext.js
- TypeScript を使ってください
- スタイリングはTailwind CSS を使ってください
gpt-oss-20bが作ったアプリの画面は以下のようになりました。
なぜか、対戦結果が英語になっていますね。😅
Qwen3で作ったものは以下のようでした。
こちらは、対戦結果が最新の結果しか表示されていません(これはプロンプトが曖昧なのかもしれません)。😅
実はQwen3では作成に10分(バグ対応の時間を入れると20分)くらいかかったのですが、gpt-oss-20bは2分くらいで出来ました。早いです❗
簡単なアプリとはいえ、2分で出来たのは素晴らしいですね。
メモリー(VRAM)使用量は18Gbyte でした、32GメモリーのMacなら楽勝ですね。
Thinkingのログは以下で(一部改行を削除)、それなりに考えているようです。
Thinking...
The user wants a Next.js TypeScript React app implementing rock-paper-scissors, with user buttons, random computer choice, outcome
determined by computer, and display in a table. They want the code for a new project. Likely want to provide steps to create
project, install dependencies, code for pages/index.tsx, components, maybe styles. Provide instructions. Provide code for tailwind
config, etc.
We should give instructions: npx create-next-app ... with --typescript, add tailwind, set up tailwind config, then create
components. Provide a minimal page: buttons, state, random, compute result, display table.
Also show tailwind config and globals.css. Provide final folder structure. Provide explanation.
Let's produce step-by-step guide.
We'll create a Next.js 14 app with app router? Maybe simpler use pages. But Next.js 14 uses app router. But the requirement doesn't
specify version. We can choose Next.js 13+ with app folder.
Let's produce code for app/page.tsx. Use useState.
Implementation: enum Hand = 'Rock' | 'Scissors' | 'Paper', mapping to numbers 0-2. Random with Math.floor(Math.random()*3). Outcome
function: if same -> tie; else if (human +1)%3 === computer -> human wins? But need mapping: 0: Rock, 1: Scissors, 2: Paper. Let's
define logic: rock beats scissors, scissors beats paper, paper beats rock. We can use map.
Compute result string: "Win" "Lose" "Draw".
Display table with columns: Human, Computer, Result. Each row is a game.
Use useState to hold array of games.
Button clicks call handleClick with hand.
Add Tailwind styling.
Also include tailwind config and postcss.
Also instruct to run dev.
We should provide minimal package.json? We can skip.
Also show adding tailwind:
npx tailwindcss init -p.
Add content paths: "./app/**/*.{js,ts,jsx,tsx}", etc.
Add css file: globals.css with @tailwind base; etc.
Thus provide full code.
We'll output explanation in Japanese.
Let's produce answer.
...done thinking.
## 🎉 Next.js + TypeScript + Tailwind で「ジャンケン」アプリを作ろう
以下の手順で **新規プロジェクト** を作成し、
「人間(ユーザー)とコンピューターのジャンケンを行い、結果を表に表示」する最小構成のアプリを作ります。
> 使う技術
> - Next.js(App Router)
> - TypeScript
> - Tailwind CSS
> - React hooks(useState など)
ただし、出来たコードには以下の問題がありました。
"use client"
が無い- Tailwind CSSの設定がV3
- V4で作ってと指定してもV3用で作ってました 😅
もう少し複雑なジャンケンアプリを作ってもらった
このブログによく出てくる、対戦結果と対戦成績が表示できるNext.js + Jotai + Tailwind CSSのアプリを作ってもらいました。 以下の画面は今回gpt-oss-20bが作ってくれたアプリの画面です。
1. 要求仕様の作成
gpt-oss-20bに渡す仕様ですが、これは私が作ったアプリをClaudeCodeに調査・作成してもらいました、私の最近の得意技です。😄 出来た仕様はブログの最後に置きました。
2. コード生成
生成された仕様をgpt-oss-20bのプロンプトに渡しコードを生成してもらいました。 前回のアプリの比べ生成するファイルが多いので時間が掛かるかと思ったのですが、なんと2分30秒で終了しました。 早い ❗❗❗
3. コード修正
しかし、直ぐには動きませんでした。修正したのは以下の点でした。
- 前回と同じく
"use client"
が無い - 前回と同じく Tailwind CSSの設定がV3
- 各コンポーネントが
export default
しなければいけないのにexport
になっていた - Next.jsの
<Link>
タグを使っているのにタグ内に<a>
タグが使われていた - これはワーニングですが、
handlePlay = (human: Te) =>
とすべきところがhandlePlay = (human: number) =>
になっていた - これはワーニングですが、不要な
import { ReactNode } from 'react'
があった
まとめ
ネット上には gpt-oss-20b + Clineで動いたという発言と、私のように動かないという発言の両方があります。いずれは解決する問題だと思います、これは待ちましょう。
以前試したQwen3では簡単なコードでも10分もかかり実用的ではありませんでしたが、今回のgpt-oss-20bは2分くらいで生成出来ていてローカルで動くLLMの可能性を感じました。出来たコードは最新のClaude等に比較すると見劣りしますが、新人レベルくらいですかね。
ちなみに、AI(Perplexity)に聞いたところコーディング能力を測るベンチマーク(SWE-bench Verified)のgpt-oss-20bのスコアーはClaude 3.5 SonnetとClaude 3.7 Sonnetの間くらいだそうです。私が最初に使ったClaudeは3.5 Sonnetでしたが、感覚的にはこの結果は納得できます。
今回は、gpt-oss-20bにはAIに作ってもらった詳細な仕様を渡しコーディングしてもらいました。たぶん、最初のジャンケンアプリのような荒い仕様ではコードは出来なかったかもしれませんね?(これは人間でも同じですね)
仕様作成には高性能なAIを使えば、コーディングは少しレベルの低いAIでも良いのかもしれませんね。
今までは遠くにあるGPUを満載したデータセンターで動いているAIが、私の持っている現在15万円くらいで買えるMacでまともにAIが動くのを間近で見ると、AI時代がまた一歩進んだのだと感じました。😊
# じゃんけんアプリ仕様書
## プロジェクト概要
### アプリケーション名
nx15_jyanken
### 概要
コンピューターと対戦できるじゃんけんゲームのWebアプリケーション。ユーザーはグー、チョキ、パーのいずれかを選択してコンピューターと対戦し、対戦結果と成績を確認できる。
## 技術スタック
### フレームワーク・ライブラリ
- **Next.js**: 15.4.6 (App Router)
- **React**: 19.1.0
- **TypeScript**: 5.x
- **Jotai**: 2.13.1 (状態管理)
- **Tailwind CSS**: 4.x (スタイリング)
### 開発環境
- **Node.js**: 最新LTS
- **パッケージマネージャー**: npm
- **ESLint**: 9.x
- **ビルドツール**: Next.js (Turbopack使用)
## アプリケーション構造
### ディレクトリ構成
```
nx15_jyanken/
├── app/ # Next.js App Router
│ ├── layout.tsx # ルートレイアウト
│ ├── page.tsx # ホーム(/scoresにリダイレクト)
│ ├── scores/
│ │ └── page.tsx # 対戦結果ページ
│ ├── status/
│ │ └── page.tsx # 対戦成績ページ
│ └── globals.css # グローバルスタイル
├── components/ # Reactコンポーネント
│ ├── ApplicationBar.tsx # ナビゲーションバー
│ ├── JyankenBox.tsx # じゃんけん選択ボタン
│ ├── ScoreList.tsx # 対戦結果一覧テーブル
│ └── StatusBox.tsx # 対戦成績サマリーテーブル
├── libs/ # ビジネスロジック・ユーティリティ
│ ├── jyanken.ts # ゲームロジック・型定義
│ └── jyankenAtom.ts # Jotai状態管理
└── public/ # 静的ファイル
```
## データ型定義
### 手の種類 (Te)
```typescript
export const Te = {
Guu: 0, // グー
Choki: 1, // チョキ
Paa: 2 // パー
} as const;
export type Te = (typeof Te)[keyof typeof Te];
```
### 勝敗判定 (Judgment)
```typescript
export const Judgment = {
Draw: 0, // 引き分け
Win: 1, // 勝ち
Lose: 2 // 負け
} as const;
export type Judgment = (typeof Judgment)[keyof typeof Judgment];
```
### 対戦結果 (Score)
```typescript
export type Score = {
human: Te; // プレイヤーの手
computer: Te; // コンピューターの手
judgment: Judgment; // 勝敗判定(プレイヤー視点)
matchDate: Date; // 対戦日時
};
```
### 対戦成績 (Status)
```typescript
export type Status = {
draw: number; // 引き分け回数
win: number; // 勝利回数
lose: number; // 敗北回数
};
```
## ビジネスロジック関数
### randomHand(): Te
コンピューターの手をランダムに生成
### judge(humanHand: Te, computerHand: Te): Judgment
プレイヤー視点の勝敗を判定
- アルゴリズム: `(computerHand - humanHand + 3) % 3`
### calcStatus(scores: Score[]): Status
対戦履歴から勝敗統計を計算
## 状態管理
### Jotaiアトム
- **scoresAtom**: `atom<Score[]>([])`
- 全対戦結果を配列で管理
- 新しい結果は配列の先頭に追加
- ページ間で状態を共有
## ページ仕様
### ルートページ (/)
- `/scores`へ自動リダイレクト
### 対戦結果ページ (/scores)
**機能:**
- じゃんけん対戦の実行
- 対戦結果の一覧表示
**レイアウト:**
- ApplicationBar(ナビゲーション)
- ページタイトル「対戦結果」
- JyankenBox(グー・チョキ・パーボタン)
- ScoreList(対戦結果テーブル)
**対戦フロー:**
1. ユーザーがボタン(グー/チョキ/パー)をクリック
2. コンピューターの手をランダム生成
3. 勝敗判定を実行
4. 結果をscoresAtomに追加(配列先頭)
5. テーブルに新しい結果を表示
### 対戦成績ページ (/status)
**機能:**
- 対戦成績のサマリー表示
- じゃんけん対戦の実行
**レイアウト:**
- ApplicationBar(ナビゲーション)
- ページタイトル「対戦成績」
- JyankenBox(グー・チョキ・パーボタン)
- StatusBox(勝敗統計テーブル)
## コンポーネント仕様
### ApplicationBar
**責務:** サイト全体のナビゲーション
**機能:**
- アプリタイトル「じゃんけん ポン!」
- 「対戦結果」ボタン → `/scores`に遷移
- 「対戦成績」ボタン → `/status`に遷移
**スタイル:**
- 青色背景 (`bg-blue-600`)
- レスポンシブデザイン対応
### JyankenBox
**責務:** じゃんけんの手選択UI
**Props:**
- `pon: (human: Te) => void` - 対戦実行コールバック
**機能:**
- 3つのボタン(グー・チョキ・パー)
- ボタンクリックで`pon`関数を呼び出し
**スタイル:**
- 青色ボタン (`bg-blue-600`、ホバー時`bg-blue-700`)
- 中央配置、等間隔配置
### ScoreList
**責務:** 対戦結果の一覧表示
**Props:**
- `scores: Score[]` - 対戦結果配列
**機能:**
- テーブル形式で対戦履歴を表示
- カラム: 時間、人間、コンピュータ、結果
- 新しい結果が上部に表示
**表示仕様:**
- 時間: HH:MM:SS形式
- 手: 「グー」「チョキ」「パー」
- 結果: 「勝ち」「負け」「引き分け」
- 勝敗に応じた色分け
- 引き分け: 黒 (`text-[#000]`)
- 勝ち: 青 (`text-[#2979ff]`)
- 負け: 赤 (`text-[#ff1744]`)
### StatusBox
**責務:** 対戦成績のサマリー表示
**Props:**
- `status: Status` - 勝敗統計
**機能:**
- 勝ち・負け・引き分けの回数を表示
- 勝敗に応じた色分け(ScoreListと同じ)
## スタイリング
### Tailwind CSS設定
- バージョン: 4.x
- PostCSS設定あり
- ダークモード対応(CSS変数使用)
### デザインシステム
**カラーパレット:**
- プライマリ: 青色系 (`bg-blue-600`, `bg-blue-700`)
- 勝ち: `text-[#2979ff]`
- 負け: `text-[#ff1744]`
- 引き分け: `text-[#000]`
**レスポンシブ:**
- モバイルファースト
- タブレット・デスクトップ対応 (`md:` プレフィックス)
## 開発・ビルド
### スクリプト
- `npm run dev`: 開発サーバー起動(Turbopack使用)
- `npm run build`: プロダクションビルド
- `npm run start`: プロダクション開始
- `npm run lint`: ESLintチェック
### 設定ファイル
- `next.config.ts`: Next.js設定
- `tsconfig.json`: TypeScript設定
- `eslint.config.mjs`: ESLint設定
- `postcss.config.mjs`: PostCSS設定
## 機能要件
### 基本機能
1. **じゃんけん対戦**
- ユーザーは3つの選択肢から手を選択
- コンピューターはランダムに手を選択
- 勝敗判定を自動実行
- 結果をリアルタイムで表示
2. **対戦結果記録**
- 全対戦結果をメモリに保存
- 時系列順(新しい順)で表示
- 対戦時刻、双方の手、勝敗を記録
3. **対戦成績統計**
- 勝ち・負け・引き分けの回数集計
- リアルタイムで統計更新
4. **ナビゲーション**
- 対戦結果ページと対戦成績ページ間の切り替え
- 両ページでじゃんけん対戦可能
### 非機能要件
- **レスポンシブデザイン**: モバイル・タブレット・デスクトップ対応
- **アクセシビリティ**: 適切なセマンティックHTML使用
- **パフォーマンス**: React 19の新機能活用
- **開発体験**: Turbopack、TypeScript、ESLint
## データ永続化
現在はクライアントサイドのメモリのみ(ページリロードで消失)
将来的にはlocalStorageまたはサーバーサイド保存の検討可能
## 国際化
- 日本語UI
- HTMLのlang属性: "ja"
## ブラウザ対応
- モダンブラウザ(ES2020+)
- React 19対応ブラウザ
- CSS Grid・Flexbox対応ブラウザ