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

如何仅返回vLLM流式输出的新增文本?Flask+RAG场景问题

解决vLLM流式输出重复历史文本问题

问题根源

vLLM的流式响应里,每个JSON对象的text字段返回的是累计的完整生成文本,而非本次新增内容。比如第一次返回"你好",第二次返回"你好,我是",第三次返回"你好,我是AI",直接返回会重复输出历史内容。

解决方案

在单个请求的生命周期内维护一个变量,记录已返回的文本长度,每次只截取并返回超出上次长度的增量内容。

修改后的代码

1. 调整解析函数(返回原始文本,方便增量计算)

def parse_json_stream(line):
    decoded_line = line.decode('utf-8')
    decoder = json.JSONDecoder()
    pos = 0
    while pos < len(decoded_line):
        try:
            result, json_end = decoder.raw_decode(decoded_line[pos:])
            if "text" in result and result["text"]:
                # 返回原始字符串,而非编码后的字节
                yield result["text"][0]
            pos += json_end
        except json.JSONDecodeError:
            pos += 1

2. 在generate函数中跟踪增量内容

def generate():
    try:
        prompt_len, response = process_and_respond(file_path, question)
        # 维护当前请求的已返回文本长度,初始为0
        previous_length = 0
        for line in response.iter_lines():
            if line:
                for full_text in parse_json_stream(line):
                    # 计算本次新增的文本内容
                    incremental_text = full_text[previous_length:]
                    if incremental_text:
                        # 编码后返回
                        yield incremental_text.encode("utf-8")
                        # 更新已返回长度
                        previous_length = len(full_text)
    finally:
        print(f"Deleting File {file_path}")
        os.remove(file_path)

关键改动说明

  • generate函数新增previous_length变量,每个请求独立维护该值,避免多请求间状态冲突。
  • parse_json_stream改为返回原始字符串,简化后续增量计算逻辑。
  • 每次拿到完整文本后,仅截取并返回full_text[previous_length:]的增量部分,空内容直接跳过。
  • 返回增量后立即更新previous_length为当前完整文本长度,确保下一次计算准确。

额外提示

如果prompt_len是提问文本的长度,可将初始previous_length设为prompt_len,直接跳过提问内容,只返回AI生成的部分。

内容的提问来源于stack exchange,提问作者Cihan Yalçın

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 16:15:16