如何在PHP中正确获取流式API的JSON记录并提取content字段值
如何在PHP中正确获取流式API的JSON记录并提取content字段值
我看了你的问题,发现你踩了流式API处理的常见坑——这个API返回的是Server-Sent Events(SSE)格式的分块数据,不是单个完整的JSON对象,所以直接把整个输出丢给json_decode()肯定解析不出正确的结构,foreach自然拿不到内容。
问题根源
你看到的输出是多个独立的data: {JSON片段}行拼在一起,还有最后一行的data: [DONE]结束标记。这些片段单独都是合法的JSON,但整个拼接起来不是,所以直接解码整个输出会失败,得到的$json是null或者无效数组。
解决步骤
我们需要逐行处理每个数据块:
- 把输出按行分割
- 过滤掉空行和结束标记行
- 去掉每行开头的
data:前缀,拿到纯JSON字符串 - 逐个解码JSON片段,提取
content字段
修正后的完整代码
$url = "https://api.sambanova.ai/v1/chat/completions"; $payload = '{ "stream": true, "model": "Meta-Llama-3.1-8B-Instruct", "messages": [ { "role": "system", "content": "You are a helpful assistant" }, { "role": "user", "content": "hello" } ] }'; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POST, TRUE); curl_setopt($ch, CURLOPT_HTTPHEADER, array("Authorization: Bearer $sambanova_api_keys" , 'Content-Type:application/json')); curl_setopt($ch, CURLOPT_POSTFIELDS, $payload); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); $output = curl_exec($ch); curl_close($ch); // 处理流式返回的SSE数据 $lines = preg_split('/\r\n|\r|\n/', $output); $fullContent = ''; // 可以用这个变量拼接完整内容 foreach ($lines as $line) { // 跳过空行和结束标记行 $trimmedLine = trim($line); if (empty($trimmedLine) || $trimmedLine === 'data: [DONE]') { continue; } // 提取JSON部分(去掉开头的"data: ") if (str_starts_with($trimmedLine, 'data: ')) { $jsonStr = substr($trimmedLine, 6); $chunk = json_decode($jsonStr, true); // 检查解码是否成功,且存在目标字段 if ($chunk && isset($chunk['choices'][0]['delta']['content'])) { $content = $chunk['choices'][0]['delta']['content']; // 输出单个content片段,或者拼接起来 echo $content; $fullContent .= $content; } } } // 如果需要输出完整拼接后的内容,可以用下面这行 // echo "\n\n完整内容:" . $fullContent;
额外说明
- 有的数据块里
content是空字符串(比如你输出的第一个块),代码里会自动跳过输出,如果你需要保留可以去掉空值判断 - 如果你想把所有
content拼接成完整的回复,可以用$fullContent变量存储 - 用
preg_split是为了兼容不同系统的换行符(\n、\r\n、\r)
备注:内容来源于stack exchange,提问作者Nancy Moore
相关产品推荐
相关产品推荐

