
はじめに
LLMを使うアプリケーションを作っていると、開発中に「本物のLLMにつながなくても、とりあえずAPIの接続確認だけしたい」という場面があります。
そこで、OpenAI互換APIのChat Completions風で応答する小さなおもちゃサーバ fake-llm を作りました。
fake-llm はその名のとおり本物のLLMではありません。
中身は、辞書、正規表現、テンプレート、Markov風の短文生成、簡単な感情値を組み合わせたルールベースのいわゆる人工無能です。
考え方や機能は人口無能のバイブル的書籍、「恋するプログラム―Rubyでつくる人工無脳」を参考にしています。
|
| 恋するプログラム: Rubyでつくる人工無脳 |
LLM登場以前から私がずっと作りたかったプログラムでもあります。
X上のある方のポストで思い出しました。
どんなもの?
LLMの代わりに使えて、なんとなく通じてるような、通じてないような会話ができます。
例ではAITuber-kitから接続するLMStudio等のローカルLLMとしてfake-llmを使用しています。
作ったもの
fake-llm は、ローカルで動く小さなPythonプログラムです。
主な機能は次の通りです。
- Chat Completions風の
/v1/chat/completions /v1/models - CLIでの対話
-
random.txtによるランダム応答 -
pattern.tsvによるパターン応答 -
template.tsvによるテンプレート応答 - Janomeによる日本語の単語分割
- Markov風の短文生成
- moodという簡単な感情値
- 会話からの軽い学習
-
state.jsonへの状態保存 state show/state resetによる状態確認と初期化
使い方
私のレポジトリからクローンしてください。
git clone https://github.com/kinkuman/fake-llm
インストールと起動は uv を想定しています。
Pythonのバージョンは3.9以上を想定しています。
uv sync uv run fake-llm --version uv run fake-llm chat
APIサーバとして起動する場合は次のようにします。
uv run fake-llm serve --host 127.0.0.1 --port 8000
呼び出し例です。
curl http://127.0.0.1:8000/v1/chat/completions \
-H 'Content-Type: application/json' \
-d '{
"model": "fake-llm",
"messages": [
{"role": "user", "content": "こんにちは"}
]
}'
互換クライアントから使う場合は、base URL を次のように設定します。
http://127.0.0.1:8000/v1
どんな返答をするのか
例えば /src/data/pattern.tsv に次のような行を書けます。
こんにちは|こんばんは こんにちは。今日は何の話をしますか?|どうも、こんにちは ありがとう|助かった どういたしまして。役に立ったならよかったです 2 バカ|ばか|馬鹿 0##だって無能ですもん|-5##もう少しやさしく話してくれませんか -2
pattern.tsv の基本形式は次の通りです。
regex<TAB>response|response<TAB>mood_delta
3列目の mood_delta は任意です。
正の値なら mood が上がり、負の値なら mood が下がります。
返答候補には need##phrase も書けます。
愛してる 0##はいはい|3##急に優しいですね|6##調子が狂いますね 3
この場合、moodが高い時だけ出る返答を混ぜられます。
愛してると言われた場合に、感情が平常(0)ならば「はいはい」、少し気分が良い(3)ならば「急に優しいですね」、もっと気分が良いと(6)「調子が狂いますね」が選択されます。
state.json
会話から学習した内容は state.json に保存します。
uv run fake-llm state show --state-file ./state.json
学習状況表示例です。
path: state.json version: 1 mood: -6.5 learned random: 17/50 learned patterns: 4/100 learned template groups: 1 learned templates: 6/30 per group markov starts: 29/200 markov word pairs: 119/400
state.json は長期記憶ではなく短期記憶として扱っています。
そのため、保存数には上限を付けています。
状態を初期化したい場合は次のコマンドを使います。
path: state.json uv run fake-llm state reset --state-file ./state.json
作ってみて分かったこと
LLMではないプログラムに会話をさせる場合、コードそのものより辞書の品質がかなり重要でした。
特に効果が高いのは pattern.tsv です。
よく来る入力に対して、外しにくい返答を用意すると、かなり「それっぽく」見えます。
一方で、会話から何でも保存すれば賢くなるわけではありません。
むしろ、無制限に覚えると state.json が肥大化し、変なオウム返しも増えます。
そこで、state.json は短期記憶として扱い、保存数に上限を設けました。
これは何に使えるか
本物のLLMの代わりにはなりません。
ただし、次のような用途には使えます。
- API接続確認
- ローカル開発中の仮サーバ
- LLMクライアントの動作確認
- TTSのテスト
- デスクトップマスコット
- ストリーミング応答の簡易テスト
- 人工無能の仕組みを試す教材
- ちょっとしたジョークプログラム
まとめ
fake-llm は、LLMのふりをする小さな人工無能サーバです。
本物のLLMではありませんが、ローカルで軽く動き、API接続確認や開発中の仮応答には使えます。
なにより、人工無能らしい「話の通じなさ」があります。
そこも含めて、おもちゃとして楽しめるプログラムになりました。