9
13

ollama-python のストリーム機能

Last updated at Posted at 2024-08-07

Ollama の公式 Python ライブラリ ollama-python を使用すれば、LLM からの応答をストリームで受け取ることができます。これにより、応答が生成されるたびに小さなチャンクで受け取ることができ、リアルタイムで処理や表示が可能になります。

基本的な使い方

ライブラリをインストールします。

pip install ollama

ollama.chat() 関数によりストリームモードでチャットを開始して、返されたオブジェクトを反復処理して、各チャンクにアクセスします。

import ollama
stream = ollama.chat(
    model="gemma2:2b",
    messages=[{"role": "user", "content": "hi"}],
    stream=True
)
for chunk in stream:
    print(chunk["message"]["content"], end="", flush=True)
実行結果
Hello! 👋

What can I do for you today? 🙂

実行結果は毎回変わります。

チャンク

各チャンクの内容を確認します。

for chunk in stream:
    print(chunk)
出力(抜粋)
{'model': 'gemma2:2b', 'created_at': '2024-08-07T03:57:33.0365888Z', 'message': {'role': 'assistant', 'content': 'Hello'}, 'done': False}
{'model': 'gemma2:2b', 'created_at': '2024-08-07T03:57:33.2801449Z', 'message': {'role': 'assistant', 'content': '!'}, 'done': False}
(中略)
{'model': 'gemma2:2b', 'created_at': '2024-08-07T03:57:37.0774624Z', 'message': {'role': 'assistant', 'content': ''}, 'done_reason': 'stop', 'done': True, 'total_duration': 4353619900, 'load_duration': 63915300, 'prompt_eval_count': 10, 'prompt_eval_duration': 246847000, 'eval_count': 17, 'eval_duration': 4032296000}

チャンクを整形して示します。created_atISO 8601 形式です。

{
    'model': 'gemma2:2b',
    'created_at': '2024-08-07T03:57:33.0365888Z',
    'message': {'role': 'assistant', 'content': 'Hello'},
    'done': False
}

最後のチャンクには、追加の情報が含まれます。

{
    'model': 'gemma2:2b',
    'created_at': '2024-08-07T03:57:37.0774624Z',
    'message': {'role': 'assistant', 'content': ''},
    'done_reason': 'stop',
    'done': True,
    'total_duration': 4353619900,
    'load_duration': 63915300,
    'prompt_eval_count': 10,
    'prompt_eval_duration': 246847000,
    'eval_count': 17,
    'eval_duration': 4032296000
}
  • done_reason: 応答が終了した理由
  • total_duration: 全体の処理時間(ナノ秒単位)
  • load_duration: モデルのロードにかかった時間(ナノ秒単位)
  • prompt_eval_count: 評価されたプロンプトのトークン数
  • prompt_eval_duration: プロンプトの評価にかかった時間(ナノ秒単位)
  • eval_count: 生成されたトークン数
  • eval_duration: 生成にかかった時間(ナノ秒単位)

ナノ秒は 10 億分の 1 秒です。

パフォーマンス統計の表示

最後のチャンクから取得した情報を表示する例を示します。

eval_count = last_chunk["eval_count"]
eval_duration = last_chunk["eval_duration"] / 1e9  # ナノ秒から秒に変換
tokens_per_second = eval_count / eval_duration

print(f"生成されたトークン数: {eval_count}")
print(f"生成にかかった時間: {eval_duration:.2f}")
print(f"トークン生成速度: {tokens_per_second:.2f}トークン/秒")

まとめ

ストリーム、応答の表示、およびパフォーマンス統計の計算を組み合わせた例です。

import ollama
from datetime import timedelta

def stream(model, prompt):
    stream = ollama.chat(
        model=model,
        messages=[{"role": "user", "content": prompt}],
        stream=True
    )
    for chunk in stream:
        print(chunk["message"]["content"], end="", flush=True)
    
    count = chunk["eval_count"]
    duration = chunk["eval_duration"] / 1e9
    delta = timedelta(seconds=duration)
    tps = count / duration
    print(f"[count={count}, duration={delta}, tps={tps:.2f}]")

stream("gemma2:2b", "hi")
実行例
Hi! 👋  How can I help you today? 😊
[count=15, duration=0:00:03.439581, tps=4.36]

計測は 2012 年製の第 3 世代 Core i5-3320M (2.60GHz) で行っています。

9
13
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
9
13