如何借助StreamingTextResponse传递消息元数据至useChat?
解决方案
服务端修改
问题出在你直接使用BytesOutputParser传递原始流,且提前关闭了StreamData。正确做法是结合LangChain的流式回调,将文本内容与元数据分开处理:
import { NextRequest, NextResponse } from "next/server"; import { experimental_StreamData, Message as VercelChatMessage, StreamingTextResponse } from "ai"; import { ChatOpenAI } from "langchain/chat_models/openai"; import { PromptTemplate } from "langchain/prompts"; export async function POST(req: NextRequest) { try { const body = await req.json(); const messages: VercelChatMessage[] = body.messages ?? []; const currentMessageContent = messages[messages.length - 1].content; const model = new ChatOpenAI({ temperature: 0, streaming: true, }); const prompt = PromptTemplate.fromTemplate(` You are a cheerful bot that should respond to all questions in an upbeat manner. User input: {input} AI response: `); const formattedPrompt = await prompt.format({ input: currentMessageContent }); const data = new experimental_StreamData(); // 发送元数据(可在流开始/过程中随时发送) data.append({ timestamp: new Date().toISOString() }); // 创建可读流处理模型输出 const stream = new ReadableStream({ async start(controller) { const encoder = new TextEncoder(); try { await model.stream(formattedPrompt, { onChunk(chunk) { // 将文本片段写入响应流 controller.enqueue(encoder.encode(chunk.content)); }, onEnd() { // 流结束后关闭元数据通道 data.close(); controller.close(); }, }); } catch (e) { controller.error(e); } }, }); return new StreamingTextResponse(stream, {}, data); } catch (e: any) { return NextResponse.json({ error: e.message }, { status: 500 }); } }
客户端处理
使用useChat时,可通过message.data直接获取传递的元数据:
"use client"; import { useChat } from "ai/react"; export default function ChatComponent() { const { messages, input, handleInputChange, handleSubmit } = useChat({ api: "/api/chat", // 消息更新时获取元数据 onMessageUpdate: (message) => { if (message.data) { console.log("实时元数据:", message.data); } }, // 消息完成时获取元数据 onFinish: (message) => { if (message.data) { console.log("最终元数据:", message.data); } }, }); return ( <div> {messages.map((m) => ( <div key={m.id}> <p>{m.role}: {m.content}</p> {m.data && <p>元数据: {JSON.stringify(m.data)}</p>} </div> ))} <form onSubmit={handleSubmit}> <input value={input} onChange={handleInputChange} placeholder="输入问题..." /> <button type="submit">发送</button> </form> </div> ); }
关键注意点
- 不要提前调用
data.close(),需等到模型流结束后再关闭,保证元数据通道与文本流同步。 - 避免使用
BytesOutputParser,手动处理流式chunk可确保响应格式符合StreamingTextResponse要求。 useChat会自动解析StreamData并挂载到message.data,无需手动处理流的底层格式。
内容的提问来源于stack exchange,提问作者Aram Boyajyan
相关产品推荐
相关产品推荐

