使用TextDecoderStream读取OpenAI API流时截断,如何获取完整块?
解决OpenAI流式响应读取时最后一行截断的问题
标签:openai-api
在读取OpenAI Completions的流式响应时,直接用TextDecoderStream配合读取器循环读取,常会遇到最后一行数据被截断的情况——这是因为字节流的分片是随机的,reader.read()返回的内容不一定刚好在换行符处结束,导致最后一次读取的是不完整的JSON片段。
要确保接收完整数据块,核心思路是维护一个缓冲区缓存未完成的行,具体实现如下:
- 初始化一个空字符串作为缓冲区,每次读取到内容后先追加到缓冲区中。
- 按换行符
\n分割缓冲区,只处理分割后的完整行,把最后一段可能不完整的内容重新放回缓冲区。 - 当读取器标记
done为true时,处理缓冲区中剩余的最后一行内容(这就是之前被截断的部分)。
示例代码:
let buffer = ''; const reader = response.body.pipeThrough(new TextDecoderStream()).getReader(); while (true) { const { done, value } = await reader.read(); if (done) { // 处理最后剩余的未完成行 if (buffer.trim()) { processIncompleteLine(buffer); } break; } buffer += value; const lines = buffer.split('\n'); // 把最后一行(可能不完整)留回缓冲区 buffer = lines.pop() || ''; // 处理所有完整的行 for (const line of lines) { const trimmedLine = line.trim(); if (!trimmedLine) continue; // 跳过空行 if (trimmedLine.startsWith('data:')) { const jsonContent = trimmedLine.slice(5).trim(); if (jsonContent === '[DONE]') continue; // 忽略结束标记 try { const chunk = JSON.parse(jsonContent); // 这里替换成你的chunk处理逻辑 console.log('完整chunk:', chunk); } catch (err) { console.error('JSON解析失败:', err); } } } } function processIncompleteLine(line) { const trimmedLine = line.trim(); if (trimmedLine.startsWith('data:')) { const jsonContent = trimmedLine.slice(5).trim(); try { const chunk = JSON.parse(jsonContent); console.log('最后一行完整chunk:', chunk); } catch (err) { console.error('最后一行解析失败:', err); } } }
注意事项:
- 必须处理
done状态下的缓冲区剩余内容,这是解决截断问题的关键。 - OpenAI流式响应的每行以
data:开头,最后会返回data: [DONE]作为结束信号,需要过滤该标记。 - 分割行时要处理空行,避免无效解析。
内容的提问来源于stack exchange,提问作者Luc Gagan
相关产品推荐
相关产品推荐

