使用LangChain实现OpenAI流式响应,无法通过Flask API返回给用户求解决方案
问题分析
你当前的自定义MyCustomSyncHandler存在两个核心问题:
on_llm_new_token是LangChain的回调方法,不能直接通过yield返回内容,LangChain不会处理这个生成器;- 混淆了回调逻辑与Flask流式响应的生成逻辑,回调方法的执行上下文和Flask响应的上下文不兼容。
解决方案
通过线程安全的token收集容器+Flask流式响应生成器的组合实现需求,具体步骤如下:
1. 修正自定义回调Handler
用线程安全的队列收集LLM生成的每个token,同时标记LLM任务结束状态:
from langchain.callbacks.base import BaseCallbackHandler from queue import Queue from typing import Any class StreamingCallbackHandler(BaseCallbackHandler): def __init__(self): self.token_queue = Queue() self.task_done = False def on_llm_new_token(self, token: str, **kwargs: Any) -> None: # 收集每个新生成的token self.token_queue.put(token) def on_llm_end(self, response: Any, **kwargs: Any) -> None: # 标记LLM任务完成 self.task_done = True def generate_stream(self): # 生成Flask需要的流式响应内容 while not self.task_done or not self.token_queue.empty(): token = self.token_queue.get() # 包装成SSE(Server-Sent Events)格式,兼容前端流式接收 yield f'data: {{"stream": "{token}"}}\n\n'.encode("utf-8")
2. 编写Flask流式响应接口
在视图函数中异步执行LLM请求,同时通过Handler的生成器返回流式内容:
from flask import Flask, Response from langchain.chat_models import ChatOpenAI import threading import os app = Flask(__name__) # 配置OpenAI API密钥 os.environ["OPENAI_API_KEY"] = "your-openai-api-key" @app.route("/stream-chat") def stream_chat_response(): handler = StreamingCallbackHandler() # 初始化支持流式的ChatOpenAI实例 llm = ChatOpenAI( streaming=True, callbacks=[handler], temperature=0.7 ) # 异步执行LLM请求,避免阻塞Flask响应生成 def run_llm(): llm.predict("请详细介绍LangChain的流式响应机制") threading.Thread(target=run_llm).start() # 返回流式响应,指定SSE类型的MIME return Response(handler.generate_stream(), mimetype="text/event-stream") if __name__ == "__main__": app.run(debug=True, threaded=True)
关键要点说明
- 用
queue.Queue实现线程安全的token传递,因为LLM的流式生成和Flask响应生成在不同线程执行; - 采用SSE格式返回内容,这是Web端接收流式响应的标准格式,前端可通过
EventSource直接监听; - 必须异步启动LLM请求,否则Flask会等待LLM执行完成后才开始返回响应,失去流式效果。
内容的提问来源于stack exchange,提问作者Syed Mujeeb H
相关产品推荐
相关产品推荐

