Vercel AI-SDK streamUI组件流式传输异常及相关技术疑问
Vercel AI-SDK streamUI 使用问题排查与疑问解答
正在学习Vercel AI-SDK,开发人物角色生成器——输入品牌上下文,按指定Zod schema生成人物角色属性。用streamObject实现的personaSchemaGeneration能正常返回文本流并展示,但改用streamUI实现personaSchemaGenerationUI时遇到以下问题:
遇到的问题
- 文本流完成后返回的对象不符合定义的
personaSchema类型; - 无法将LLM输出的符合
personaSchema格式的数据正确传入React组件并展示; - 通用疑问:
- streamUI是否仅支持返回单个组件?生成10个不同人物角色是否需要独立调用10次?
- streamUI是否仅支持调用一个工具?添加多个工具时总是默认使用第一个。
相关代码
基于streamObject的实现代码(personaSchemaGeneration)
export async function personaSchemaGeneration(context: string) { 'use server'; const stream = createStreamableValue(); (async () => { const { partialObjectStream } = await streamObject({ model: openai('gpt-3.5-turbo'), system: 'You generate a persona basis the brand context.', prompt: 'Generate a persona for the brand in line with the following context: ' + context, schema: personaSchema, }); for await (const partialObject of partialObjectStream) { stream.update(partialObject); } stream.done(); })(); return { object: stream.value }; }
前端调用代码
const { object } = await personaSchemaGeneration(brandContext); for await (const partialObject of readStreamableValue(object)) { console.log("Partial Obj",partialObject, " ", object) if (partialObject) { setGeneration( JSON.stringify(partialObject, null, 2), ); } } console.log("Final Obj",object)
基于streamUI的实现代码(personaSchemaGenerationUI)
export async function personaSchemaGenerationUI(context: string) { 'use server'; const result = await streamUI({ model: openai('gpt-3.5-turbo'), system: 'You generate a persona basis the brand context.', prompt: 'Generate a persona for the brand in line with the following context: ' + context, schema: personaSchema, text:({ content }) => <Persona3 {...content} /> }, ); return result.value; }
问题解答
1. 返回对象不符合schema类型
streamUI的text回调接收的content是LLM输出的原始文本,而非经过schema验证解析后的对象。需要手动将文本解析为JSON后,再用personaSchema验证:
text: ({ content }) => { try { const parsedPersona = personaSchema.parse(JSON.parse(content)); return <Persona3 {...parsedPersona} />; } catch (e) { return <div>生成格式错误,请重试</div>; } }
同时要修改prompt,明确要求LLM输出严格符合schema的纯JSON格式,避免多余文本干扰解析。
2. 无法正确传入React组件
- 确保LLM输出无多余前缀/后缀文本,仅返回符合schema的JSON;
- 按上述代码先解析验证数据,再将合法的属性传递给组件;
- 若需流式更新组件,可在
text回调中根据部分解析结果逐步渲染内容。
3. 通用疑问解答
a) streamUI是否仅支持返回单个组件?
streamUI单次调用返回一个流式组件输出,但生成多个角色有两种方案:
- 方案一:调用10次
streamUI,每次生成一个角色,并行或串行渲染结果; - 方案二:让LLM一次性输出包含10个角色的JSON数组,在
text回调中解析后返回多组件容器:
需同步修改prompt,明确要求输出包含10个角色的JSON数组。text: ({ content }) => { const parsedList = personaSchema.array().parse(JSON.parse(content)); return <div className="persona-grid">{parsedList.map(p => <Persona3 key={p.id} {...p} />)}</div>; }
b) streamUI是否仅支持调用一个工具?
streamUI支持多工具调用,需通过tools配置项传入工具列表,并优化prompt引导模型选择合适工具:
await streamUI({ model: openai('gpt-3.5-turbo'), system: '根据需求选择工具生成角色:需要行业数据用工具1,需要创意标签用工具2', prompt: `基于上下文生成角色:${context}`, schema: personaSchema, tools: [tool1, tool2], text: ({ content }) => <Persona3 {...content} /> });
模型默认选第一个工具通常是因为prompt未明确工具适用场景,补充场景说明即可解决。
内容的提问来源于stack exchange,提问作者blaziken105
相关产品推荐
相关产品推荐

