response_modeをblockingからstreamingにする
requests.postの呼び出しでstream=Trueを設定。これにより、レスポンス全体がダウンロードされるのを待たずに、すぐにチャンクの読み込みを開始する
import requests
import json
import os
import time
from dotenv import load_dotenv
load_dotenv()
# --- 設定(変更なし) ---
API_KEY = os.environ.get("DIFY_API_KEY")
APP_ID = os.environ.get("APP_ID")
# BASE_URLはDify Cloud (dify.ai) の場合です。セルフホストの場合は適宜変更してください。
BASE_URL = "https://api.dify.ai/v1"
CHAT_ENDPOINT = f"{BASE_URL}/chat-messages"
user_input = "おはようございます。今日の天気と、何か面白いニュースがあれば教えてください。"
# --- 1. ペイロードの変更 ---
payload = {
"query": user_input,
"inputs": {
"context": "Null"
},
"user": "user_python_script_001",
# ストリーミングを有効にする
"response_mode": "streaming",
}
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
}
print("✅ ワークフローの出力 (ストリーミング回答):")
print("-" * 30)
try:
# --- 2. API呼び出しの変更 (stream=True) ---
response = requests.post(
CHAT_ENDPOINT,
headers=headers,
data=json.dumps(payload),
stream=True # ストリーミング応答を有効にする
)
response.raise_for_status() # HTTPエラーが発生した場合に例外を発生させる
# --- 3. 応答の処理ロジックの変更 ---
# iter_lines() でチャンクごとに処理
for line in response.iter_lines():
if line:
# SSE形式の行をデコード
decoded_line = line.decode('utf-8')
# SSEのデータ行は 'data: ' で始まる
if decoded_line.startswith('data: '):
# 'data: ' の部分を削除し、JSONとしてパース
json_str = decoded_line[6:].strip()
try:
data = json.loads(json_str)
except json.JSONDecodeError:
# JSONデコードエラーはスキップまたはログに記録
continue
# タイプに応じて処理
event_type = data.get('event')
# 'message' イベントが回答のテキストチャンクを含む
if event_type == 'message':
# 'answer' フィールドにテキストの断片が含まれる
text_chunk = data.get('answer', '')
# ターミナルにテキストを逐次出力(flush=Trueで即時表示)
print(text_chunk, end='', flush=True)
# 'message_end' イベントは回答の終了を示す
elif event_type == 'message_end':
# 処理終了後、改行してループを抜ける
print("\n" + "-" * 30)
print("✅ ストリーミング終了")
break
except requests.exceptions.HTTPError as errh:
print(f"\nHTTP エラーが発生しました: {errh}")
# エラーが発生した場合、response.text を表示(非ストリームとして再取得が必要な場合あり)
# ストリームモードでエラーがすぐに発生しないこともあるため、これはシンプルなエラー表示
try:
print(response.json())
except:
print(response.text)
except requests.exceptions.RequestException as err:
print(f"\nリクエスト中にエラーが発生しました: {err}")
finally:
# 接続が成功した場合でも、エラーで中断した場合でも、最後に改行してプロンプトをきれいに表示
print()
なるほど、レスポンスモードが変わるのね。了解!