You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

流式输出中yield未修改局部变量致conversation_id传递异常

问题分析

你的问题核心在于生成器函数的执行时机:

  • 当你返回generate_stream, conversation_id时,conversation_id还是初始的None——因为generate_stream是生成器,只有调用它(比如result_stream())并迭代完所有yield语句后,才会执行后续的store_message赋值代码。
  • Flask要求响应头必须在返回response_class对象时就确定,此时生成器还未开始执行,所以拿到的id始终是None。
解决方案

最合理的修复方式是提前生成conversation_id,不要等到流式输出结束才创建对话记录。具体步骤:

  1. 先创建一条空的对话记录,直接拿到有效的conversation_id
  2. 在流式输出完成后,再更新这条记录的内容和token使用量
  3. 这样返回给路由的conversation_id在一开始就是有效整数,能正常放入响应头
代码修改示例

服务层代码调整

full_answer = ""
total_tokens = 0
# 提前创建空消息,获取有效conversation_id
conversation_id = self.store_empty_message(chat_conversation_id)

def generate_stream():
    nonlocal total_tokens, full_answer
    global conversation_id
    current_response = ""
    for chunk in answer_stream:
        if (
            hasattr(chunk, "usage_metadata")
            and chunk.usage_metadata is not None
        ):
            total_tokens = chunk.usage_metadata.get("total_tokens", 0)
        if hasattr(chunk, "content") and chunk.content:
            current_response += chunk.content
            yield chunk.content
    current_response = current_response.strip()
    full_answer = current_response
    # 流式结束后更新消息内容和token数
    self.update_message(
        conversation_id,
        {
            "message": full_answer,
            "tokens_used": total_tokens,
        }
    )
    print(conversation_id)

return generate_stream, conversation_id

需要新增两个业务方法:

  • store_empty_message:创建仅包含chat_conversation_id的空记录,返回生成的conversation_id
  • update_message:根据conversation_id更新记录的内容和token字段

路由层代码无需修改

原路由代码可以保持不变,此时拿到的id已经是有效整数,能正常设置到响应头中:

@search_bp.route("/search", methods=["POST"])
def searchQuery(id):
    data = request.get_json()

    try:
        result_stream, id = search_service.search(data)

        return app.response_class(
            stream_with_context(result_stream()), 
            content_type="application/json", 
            headers={"x-conversation-id": id}
        )

    except Exception as e:
        return error_helper(str(e), status_code=500)
替代方案(若无法提前创建记录)

如果业务不允许提前创建空记录,可以改用**Server-Sent Events(SSE)**格式,在流式输出的最后发送一条包含conversation_id的特殊事件。前端需要监听这个事件来获取ID,但这种方式无法通过响应头传递ID:

def generate_stream():
    # ... 原有流式输出代码 ...
    # 最后发送conversation_id事件
    yield f"event: conversation_id\ndata: {conversation_id}\n\n"

内容的提问来源于stack exchange,提问作者Rhythm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 11:47:36