0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Python標準ライブラリだけでOllamaのチャットをストリーミング表示する

0
Posted at

はじめに

Ollamaには公式の ollama Pythonライブラリがあるが、「pipを入れたくない」「単発のスクリプトに依存を増やしたくない」場面では、標準ライブラリの urllib だけで十分にチャットできる。この記事では、標準ライブラリのみでストリーミング(生成されながら順次表示)するチャットCLIを書いて動かす。

環境

  • Windows 11 / Python 3.11(標準ライブラリのみ。追加インストールなし)
  • Ollama 0.40.4(http://127.0.0.1:11434)
  • モデル: qwen2.5:0.5b

やったこと

スクリプト

chat_stream.py:

import json
import sys
import urllib.request


def stream_chat(model: str, prompt: str) -> None:
    req = urllib.request.Request(
        "http://127.0.0.1:11434/api/chat",
        data=json.dumps({
            "model": model,
            "messages": [{"role": "user", "content": prompt}],
            "stream": True,
        }).encode("utf-8"),
        headers={"Content-Type": "application/json"},
        method="POST",
    )
    with urllib.request.urlopen(req) as res:
        for line in res:
            chunk = json.loads(line)
            piece = chunk.get("message", {}).get("content", "")
            print(piece, end="", flush=True)
            if chunk.get("done"):
                break
    print()


if __name__ == "__main__":
    stream_chat(
        sys.argv[1] if len(sys.argv) > 1 else "qwen2.5:0.5b",
        sys.argv[2] if len(sys.argv) > 2 else "自己紹介を1文で。",
    )

実行

python chat_stream.py qwen2.5:0.5b "Count from 1 to 5, separated by spaces, nothing else."

実行結果:

1 2 3 4 5

文字が順に出力されていく(パイプにリダイレクトした場合は一括表示になるが、ターミナル上では生成の進み具合が見える)。

仕組み

/api/chat に stream: true(既定)でリクエストすると、応答はNDJSON(1行1JSON)で届く。各行は次のような構造だ。

{"model":"...","message":{"role":"assistant","content":"1"},"done":false}
{"model":"...","message":{"role":"assistant","content":" "},"done":false}
...
{"model":"...","message":{"role":"assistant","content":""},"done":true, ...}

そのため、for line in res: で1行ずつ読み、message.content を取り出して print(..., end="", flush=True) するだけでストリーミング表示になる。最後は done: true のチャンクが来るので、それを合図にループを抜ける。統計情報(トークン数など)もこの最終チャンクに含まれる。

ハマった点

  1. 初回はモデルのロードで待たされる。urllib の既定ではタイムアウトが無制限なので問題になりにくいが、独自にタイムアウトを付けている場合は長めに設定すること(実測では0.5Bモデルの初回リクエストに約30秒かかった)。
  2. res をイテレートすると行単位で読める。urllib のレスポンスはバイナリ行を返すので、通常のJSONパース前にUTF-8の扱いでつまずかないよう、json.loads は bytes のまま渡してよい(Python 3.6以降はUTF-8を自動判定する)。
  3. ollama ライブラリは不要だが、あってもよい。会話履歴の管理やトークン統計の整形まで自前でやるのが手間なら、公式ライブラリの利用も検討する。この記事の目的は「依存ゼロで動かすこと」だ。

まとめ

  • urllib + json だけでOllamaのストリーミングチャットが実装できる。
  • ポイントは /api/chat の stream: true が返すNDJSONを1行ずつ処理すること。
  • done: true を終了条件にすると、統計情報も取り逃さない。

関連する本

ストリーミングの続きとして、毎朝のダイジェスト自動作成までを一冊にまとめました。第1章・第2章は無料で読めます。

Windowsで動かすローカルLLM自動化:Ollama実測ガイド

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?