如何仅返回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
相关产品推荐
相关产品推荐

