はじめに
遊戯王OCGのカード情報やルールについて、Discord上でサッと質問できるBotを作りました。
バックエンドにローカルLLM(Ollama)を使用しているため、外部APIに依存せず、プライベートな環境で動作します。
システム構成
chatbot_ygo/
├── bot.py # Botのエントリーポイント・ヘルプコマンド
├── config.py # 環境変数の読み込み
├── cogs/
│ ├── card_search.py # /card コマンド(カード情報質問)
│ └── rule_qa.py # /rule コマンド(ルール質問)
├── services/
│ └── llm.py # Ollama APIクライアント(共通)
├── requirements.txt
├── .env.example
└── .gitignore
技術スタック
| 項目 | 技術 |
|---|---|
| Bot フレームワーク | discord.py 2.3+ |
| LLM | Ollama(ローカル実行) |
| LLMモデル | gemma3:4b(変更可能) |
| HTTP通信 | aiohttp(非同期) |
| 言語 | Python 3.11+ |
仕組み
ユーザー ──/card ブルーアイズ──▶ Discord Bot
│
▼
Ollama API (localhost:11434)
│
▼
LLMが回答生成
│
▼
ユーザー ◀──Embedで表示────── Discord Bot
ユーザーがスラッシュコマンドを送ると、Botがシステムプロンプト付きでOllamaのローカルLLMに質問を投げ、回答をDiscordのEmbedで返します。
セットアップ
1. Ollamaのインストールと起動
# Ollamaをインストール(Linux/WSL2)
curl -fsSL https://ollama.com/install.sh | sh
# モデルをダウンロード
ollama pull gemma3:4b
# サーバーを起動(別ターミナルで実行)
ollama serve
2. Botのセットアップ
# リポジトリをクローン後
cd chatbot_ygo
# 依存パッケージをインストール
pip install -r requirements.txt
# 環境変数を設定
cp .env.example .env
.env を編集して、Discord Botトークンを設定します。
DISCORD_TOKEN=your_discord_bot_token_here
OLLAMA_BASE_URL=http://localhost:11434
OLLAMA_MODEL=gemma3:4b
3. 起動
python bot.py
コマンド一覧
| コマンド | 説明 | 使用例 |
|---|---|---|
/card <カード名> |
カード情報をLLMに質問 | /card ブルーアイズ |
/rule <質問> |
ルールについてLLMに質問 | /rule チェーンの処理順序 |
/help |
ヘルプを表示 | /help |
コードの解説
Ollama APIクライアント(services/llm.py)
すべてのLLM呼び出しを担う共通モジュールです。
import aiohttp
import config
async def chat(system_prompt: str, user_message: str) -> str:
payload = {
"model": config.OLLAMA_MODEL,
"messages": [
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_message},
],
"stream": False,
}
async with aiohttp.ClientSession() as session:
async with session.post(
f"{config.OLLAMA_BASE_URL}/api/chat", json=payload
) as resp:
data = await resp.json()
return data["message"]["content"]
ポイント:
-
非同期通信:
aiohttpを使い、discord.pyのイベントループをブロックしない - stream: False: レスポンスを一括で受け取る(ストリーミングだとJSON全体を一度にパースできないため)
- システムプロンプト: コマンドごとに異なる役割を指定できる
カード検索(cogs/card_search.py)
SYSTEM_PROMPT = (
"あなたは遊戯王カード情報に詳しいアシスタントです。"
"ユーザーが指定したカード名について、カード名・カードタイプ・効果テキスト・"
"ATK/DEF・レベル/ランク・属性・種族などの情報をできるだけ正確に回答してください。"
"日本語で回答してください。"
)
システムプロンプトで「遊戯王カード情報の専門家」として振る舞うよう指示しています。
ルールQ&A(cogs/rule_qa.py)
SYSTEM_PROMPT = (
"あなたは遊戯王オフィシャルカードゲームのルールに精通した専門家です。"
"ユーザーのルールに関する質問に対して、正確かつ分かりやすく日本語で回答してください。"
"公式ルールブックやFAQに基づいた回答を心がけてください。"
)
こちらは「ルールの専門家」として指示。同じchat()関数を使いつつ、プロンプトの切り替えだけで異なる用途に対応しています。
モデルの選び方
| モデル | サイズ | 推奨環境 |
|---|---|---|
| gemma3:1b | ~1GB | メモリ4GB以上 |
| gemma3:4b | ~3GB | メモリ8GB以上 |
| gemma3:12b | ~8GB | メモリ16GB以上 |
| gemma3:27b | ~17GB | メモリ32GB以上・GPU推奨 |
モデルの変更は .env の OLLAMA_MODEL を書き換えるだけです。大きいモデルほど回答の精度が上がりますが、応答速度とのトレードオフがあります。
実際に使ってみた
「青眼の白龍」について聞いてみました。応答時間は体感1分くらいです。攻撃力(ATK), 守備力(DEF), 種族, レベルは正解してますが, 他はもうとんちんかんです。
現代で使用されているカード「灰流うらら」についても聞いてみました。やっぱりダメです。
課題
現状応答速度も精度もあまりよくないです。幸い遊戯王にはカードのデータベースが存在するので、
そこから情報を拾ってきてRAGとか実装すると速度も精度も良くなるかもしれないです。
注意点
- LLMの回答には**ハルシネーション(誤情報)**が含まれる可能性があります。特に小さいモデルでは、カード効果やルールの細部が不正確になることがあります
- Ollamaサーバーが起動していないとBotが応答できません
- 初回の質問はモデルのロードに時間がかかる場合があります
まとめ
外部APIに依存せず、ローカルLLMだけで動く遊戯王Botを構築しました。Ollamaを使うことで、モデルの切り替えやカスタマイズが容易で、インターネット接続がなくても動作します。
discord.pyのCogでコマンドを分離し、共通のLLMクライアントを通じてOllamaとやりとりするシンプルな構成なので、他のカードゲームやジャンルへの応用も簡単です。

