
GraphRAG:基于PolarDB+通义千问api+LangChain的知识图谱定制实践
随着大语言模型(LLM)在各种应用中的广泛使用,如何高效地从服务器获取模型生成的长文本响应成为一个重要问题。传统的HTTP请求模式通常等待服务器生成完整的响应内容再返回给客户端。然而,流式调用(streaming)通过分段传输部分响应,能提高实时性和用户体验。在此场景中,HTTP流式调用被广泛应用,尤其是在与LLM(如通义千问等)进行交互时。
本文将介绍LLM的HTTP API流式调用的机制,并深入探讨前端如何处理流式响应,以实现实时的、渐进式的结果呈现。
HTTP API流式调用(HTTP Streaming)是一种传输方式,服务器不会等待所有的数据生成完毕再返回给客户端,而是将响应数据逐步分段发送。当大语言模型生成内容时,服务器可以通过流式传输,将文本按块传递给前端,前端可以立即呈现这些部分内容,无需等待完整响应。
这种方式特别适合用于大语言模型的文本生成任务,因为大规模模型生成的内容可能会很长,逐步输出可以改善用户的等待体验。
以一个调用LLM的流式HTTP API为例,下面是一个使用fetch来发起流式调用的典型前端实现流程。国内的各个大模型,调用方式差不多,参数也类似,甚至还会有openai兼容的openapi接口。
const fetchStreamData = async (prompt) => {
const response = await fetch('https://api.openai.com/v1/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer YOUR_API_KEY`
},
body: JSON.stringify({
model: 'gpt-4',
prompt: prompt,
stream: true // 启用流式响应
})
});
// 检查响应状态
if (!response.ok) {
throw new Error('Network response was not ok');
}
// 获取响应的可读流并处理流数据
const reader = response.body.getReader();
const decoder = new TextDecoder('utf-8');
let done = false;
while (!done) {
// 读取流中的下一个数据块
const {
value, done: readerDone } = await reader.read();
done = readerDone;
// 将数据块解码为字符串
const chunk = decoder.decode(value, {
stream: true });
console.log(chunk); // 处理或显示每一块数据
// ***** 这需要注意,各个大模型的分块数据结构可能不一样,甚至会有可能出现部分数据的情况,要单独兼容和处理哦
// 以及有些模型内容的路径不一样,一次性响应在content,但是流式在delta字段下
}
};
当后端返回流式响应时,前端可以逐步接收并更新UI,提供更好的用户交互体验。以下是前端处理流式响应的关键步骤。
每当接收到一个新的数据块,前端可以立即将其更新到UI上,而不必等待完整的响应。这种实时更新的机制对于聊天机器人、搜索建议等场景尤为重要。例如:
const chatBox = document.getElementById('chat-box');
const updateChat = (text) => {
// 将新数据块追加到界面上
chatBox.innerHTML += `<p>${
text}</p>`;
};
// 在逐块接收时更新
while (!done) {
const {
value, done: readerDone } = await reader.read();
const chunk = decoder.decode(value, {
stream: true });
updateChat(chunk); // 实时更新聊天框
}
通过这种方式,用户能够看到模型生成内容的部分结果,即使整个请求尚未完成,提升了用户体验。
在流式调用中,网络连接可能会中断,或者服务器可能会返回错误。前端应该做好错误处理,例如:
if (!response.ok) {
console.error('Error with the request');
return;
}
reader.read().then(processStream).catch(error => {
console.error('Error while reading stream:', error);
});
在中断时,前端可以选择显示错误消息,或尝试重新发起请求以重新建立连接。
由于流传输的数据是分块发送的,前端可能需要将这些分段数据拼接起来,形成完整的响应。例如:
let fullResponse = '';
while (!done) {
const {
value, done: readerDone } = await reader.read();
const chunk = decoder.decode(value, {
stream: true });
fullResponse += chunk; // 拼接完整响应
}
对于聊天机器人或类似应用,前端可以设置自动滚动,使得用户在流式数据逐步加载时能够始终看到最新的内容。
const scrollToBottom = () => {
chatBox.scrollTop = chatBox.scrollHeight;
};
updateChat(chunk);
scrollToBottom(); // 更新后自动滚动
HTTP API流式调用为大语言模型的响应提供了更高效和实时的交互方式。通过流式调用,前端可以逐步接收模型生成的部分数据,并即时呈现,从而提升用户体验。前端在实现流式调用时,需要处理数据分块的拼接、实时更新界面和处理可能的中断错误。通过这种方式,可以在交互密集的应用场景(如聊天机器人、自动化助手等)中大幅改善用户的使用体验。
文章转自微信公众号@阿里云开发者