ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

CopilotKit 集成 CrewAI Flows:用 Hashbrown 流式渲染声明式生成式 UI 的完整实践指南

CopilotKit 集成 CrewAI Flows:用 Hashbrown 流式渲染声明式生成式 UI 的完整实践指南 CopilotKit 集成 CrewAI Flows用 Hashbrown 流式渲染声明式生成式 UI 的完整实践指南【免费下载链接】CopilotKitThe Frontend Stack for Agents Generative UI. React, Angular, Mobile, Slack, and more. Makers of the AG-UI Protocol项目地址: https://gitcode.com/GitHub_Trending/co/CopilotKit本文以 CopilotKit 仓库中showcase/integrations/crewai-crews的 BYOCBring Your Own ComponentsHashbrown 集成示例为蓝本系统讲解如何让一个极简的 CrewAI 单 Agent Crew 输出符合 Hashbrown schema 的 JSON 信封envelope并借助hashbrownai/react的前端解析器把流式 JSON 逐步组装成 MetricCard、饼图、柱状图、交易卡片与 Markdown 混排的销售仪表盘。读完本文你将掌握该集成的端到端调用链CrewAI Crew → FastAPI → CopilotRuntime → React 渲染器、纯 JSON 输出的系统提示词约束技巧以及完整的前端渲染与 E2E 验证方法。背景为什么需要 BYOC 与 Hashbrown在大模型驱动的对话应用中常规做法是让 LLM 输出自然语言文本再由前端把文本展示给用户。但在销售分析、数据看板这类场景中用户期望的不是一段话而是结构化的可视化 UI——KPI 卡片、饼图、柱状图等。Hashbrown 正是为此设计的组件目录 结构化输出方案LLM 不再输出自由文本而是输出一份受 schema 约束的 JSON 信封前端拿到后按组件目录逐块渲染。本示例名为 BYOCBring Your Own Components核心思想是前端自己定义组件目录catalog并暴露给 LLMLLM 只负责输出符合目录的 JSON 结构渲染完全由前端组件完成。与之相对的是qa/declarative-json-render.md这类通用 JSON 渲染路径——两者区别在于Hashbrown 方案有严格的组件 props schema 约束与流式逐块组装能力而通用 JSON 渲染则更自由但缺少目录校验。在 CopilotKit 生态中这一集成落在 CrewAI 集成 showcase 内对应的 QA 文档为 qa/declarative-hashbrown.md本文即围绕该文档及其源码实现展开。架构总览四层调用链从整体上看这个演示由四层组成它们协同完成用户点击 → 流式 JSON → 逐步渲染 UI的完整链路CrewAI 后端src/agents/byoc_hashbrown_agent.py定义一个专门输出 Hashbrown JSON 信封的 Crew通过 agent_server.py 挂载到 FastAPI 端点/byoc-hashbrown。CopilotRuntime 代理层src/app/api/copilotkit-byoc-hashbrown/route.ts在 Next.js 侧创建一个CopilotRuntime把请求代理到后端的AGENT_URL默认http://localhost:8000。React 前端src/app/demos/declarative-hashbrown/page.tsx渲染CopilotKit包装的聊天界面hashbrown-renderer.tsx注册组件目录并用useJsonParser解析流式 JSON。E2E 测试tests/e2e/declarative-hashbrown.spec.ts用 Playwright 验证三类建议词触发的渲染结果。调用链对应的关键文件与行号如下后文逐一展开层文件职责Crew 定义byoc_hashbrown_agent.py纯 JSON 输出的系统提示词 单 Agent Crew后端挂载agent_server.pyadd_crewai_crew_fastapi_endpoint(app, ByocHashbrown(), /byoc-hashbrown)Runtime 代理route.tsHttpAgent指向${AGENT_URL}/byoc-hashbrown前端页面page.tsxCopilotKitHashBrownDashboard布局渲染器hashbrown-renderer.tsxuseUiKit定义组件目录、useJsonParser流式解析聊天组件chat.tsxCopilotChat接入自定义 assistant 消息槽一、CrewAI 后端让 Crew 只输出 JSON1.1 系统提示词Hashbrown JSON 信封规范后端核心是 byoc_hashbrown_agent.py 中的BYOC_HASHBROWN_SYSTEM_PROMPT。它告诉 LLM每次回复必须是一个单一的 JSON 对象且形如{ui: [...]}信封其中ui数组中的每个元素是组件名到{ props: {...} }的映射{ ui: [ { metric: { props: { label: Total Revenue, value: $1.2M } } }, { pieChart: { props: { title: ..., data: [{...}] } } }, { barChart: { props: { ... } } }, { dealCard: { props: { ... } } }, { Markdown: { props: { children: ... } } } ] }这里有一个关键设计源码注释中特别强调CrewAI 驱动的 LLM 必须直接输出原始 schema 形状而不是 Hashbrown 官方的 XMLui.../uiDSL。那个 XML DSL 是当 Hashbrown 自己驱动 LLM 时由它把 DSL 编译成 schema 文档使用的本示例通过 CrewAI 驱动所以必须直接输出 JSON schema 本身。各组件 props 规范如下均出自系统提示词原文组件props说明metriclabel: string,value: stringKPI 卡片value为预格式化字符串如$1.2M或248pieCharttitle: string,data: string环形图data是JSON 编码的字符串内嵌 JSON为至少 3 段的{label, value}数组barCharttitle: string,data: string垂直柱状图data同上至少 3 根柱通常按时间排序dealCardtitle: string,stage: string,value: number单笔销售交易stage必须属于六个枚举值之一value为裸数字不含货币符号与逗号Markdownchildren: string简短说明文字用于小标题与过渡句支持标准 Markdown提示词还规定了硬性约束不包代码围栏、不输出 JSON 对象之外的任何前言或解释、不调用任何工具、不询问澄清性输入图表数据优先给出 36 行合理样本数据标签保持简短data必须是 JSON 字符串内层引号需要转义。提示词末尾还附了一个完整的销售仪表盘示例响应供 LLM few-shot 参考。1.2 为何要绕过CrewAI 的默认系统提示词CrewAI 有一个让开发者头疼的默认行为ChatWithCrewFlow.build_system_message会用固定的 CrewAI platform 样板包装 Crew 描述这段样板会主动怂恿 LLM 自我介绍、询问澄清输入——这恰好与只输出一个 JSON 对象的需求直接冲突。源码 byoc_hashbrown_agent.py 的模块 docstring 明确指出了这一点并给出了两条解决路径预播种系统提示词preseed_system_prompt把我们的提示词注册为crew_description同时跳过启动时的二次 AI 调用CrewAI 默认会用 LLM 探测来生成 crew 描述让 Crew 构建保持同步、廉价、快速。安装硬覆盖install_custom_system_messagemonkey-patchChatWithCrewFlow.__init__在实例构造完成后立刻把自定义系统消息写回self.system_message覆盖掉上游代码组装的那一份。这两者的实现都在 _chat_flow_helpers.py 中且都通过crew_name作为 key 注册未注册的 Crew 会回落到默认行为互不干扰。1.3 最小 Crew 的搭建与端点挂载由于聊天行为完全由自定义系统消息驱动Crew 本身只需要一个躯壳即可——源码注释把它描述为The agent body is only here becauseChatWithCrewFlowrequires a crew with at least one agent task。实际创建如下见 byoc_hashbrown_agent.pyagent Agent( llmgpt-5.4, roleHashbrown JSON Emitter, goalEmit hashbrown-shaped JSON responses., backstoryBYOC_HASHBROWN_SYSTEM_PROMPT, verboseFalse, tools[], ) task Task( descriptionRespond with a single hashbrown-shaped JSON object., expected_outputA JSON object matching the hashbrown schema., agentagent, ) return Crew( nameCREW_NAME, agents[agent], tasks[task], processProcess.sequential, verboseFalse, chat_llmgpt-5.4, )随后在 agent_server.py 中将其挂载为 FastAPI 端点add_crewai_crew_fastapi_endpoint(app, ByocHashbrown(), /byoc-hashbrown)其中ByocHashbrown是实现了name属性与crew()方法的适配器类crew()使用模块级缓存_cached_crew保证只构建一次 Crew见 byoc_hashbrown_agent.py。二、Runtime 代理层把前端请求转发给 CrewAI在 Next.js 一侧route.ts 创建了一个专用的 CopilotRuntimeconst AGENT_URL process.env.AGENT_URL || http://localhost:8000; function createAgent() { return new HttpAgent({ url: ${AGENT_URL}/byoc-hashbrown }); } const agents: Recordstring, AbstractAgent { byoc-hashbrown-demo: createAgent(), default: createAgent(), }; const runtime new CopilotRuntime({ agents });关键点AGENT_URL环境变量默认指向http://localhost:8000即本地 agent_server 的监听地址可通过环境变量覆盖指向远程部署的后端。两个 agent 别名byoc-hashbrown-demo与default指向同一个HttpAgent前端页面通过agentbyoc-hashbrown-demo显式选中该 agent。导出 POST 处理器使用createCopilotRuntimeHandler并以mode: single-route、basePath: /api/copilotkit-byoc-hashbrown挂载捕获异常后返回结构化{ error, stack }JSON500 状态码。三、React 前端组件目录注册与流式 JSON 渲染3.1 页面组装page.tsx 使用CopilotKit组件包裹整个页面指定runtimeUrl/api/copilotkit-byoc-hashbrown与agentbyoc-hashbrown-demo内部再套一层自定义的HashBrownDashboardproviderCopilotKit runtimeUrl/api/copilotkit-byoc-hashbrown agentbyoc-hashbrown-demo HashBrownDashboard {/* 页面布局与 Chat / */} /HashBrownDashboard /CopilotKit页面头部标题为 Declarative UI: Hashbrown副标题说明这是通过hashbrownai/react实现的流式结构化输出。聊天区由 chat.tsx 渲染CopilotChat并把默认的CopilotChatAssistantMessage槽替换为自定义的HashBrownRenderMessage需要类型断言以满足 slot 签名。3.2 组件目录useUiKit exposeComponenthashbrown-renderer.tsx 是本方案的核心。它调用hashbrownai/react的useUiKit声明组件目录function useSalesDashboardKit() { return useUiKit({ examples: prompt..., components: [ exposeMarkdown(), exposeComponent(MetricCard, { name: metric, description: A KPI metric card with label, value, and optional trend, props: { label: s.string(The metric label/name), value: s.string(The metric value (formatted)), }, }), exposeComponent(PieChartWithStringData, { name: pieChart, description: A donut/pie chart. data is a JSON-encoded string ..., props: { title: s.string(Chart title), data: s.string(JSON array of {label, value} segments), }, }), // barChart、dealCard 同理 ... ], }); }值得注意的工程细节examples中使用 Hashbrown 的prompt模板字面量写一段ui.../ui的示例混合展示Markdown标题、metric、pieChart、barChart、dealCard并附 hint 提示图表必须包含title与datadata是 JSON 编码的{label, value}数组字符串——这与后端系统提示词的约定完全一致。dealCard的stage用s.enumeration声明枚举值正好是后端提示词中规定的六个管道阶段prospect/qualified/proposal/negotiation/closed-won/closed-lost前后端 schema 严格对齐。3.3 图表 data 字符串化流式解析下的稳定性设计前端组件PieChartWithStringData与BarChartWithStringData都接收data: string内部用parseChartData做JSON.parse解析失败流式中途的截断 JSON则渲染null成功才把真实数组交给图表组件。源码注释解释了这样做的原因The LLM streams JSON as text anyway, so we modeldataas a string and parse inside the wrapper。这保证了 schema 在部分流式状态下保持稳定避免中途的非法 props 触发渲染崩溃——这是 Hashbrown 流式方案的基石。HashBrownDashboard通过useUiKit拿到kit内含schema与render后放入 Context供消息渲染器使用。若在 provider 之外使用会抛出HashBrownRenderMessage must be used within HashBrownDashboard错误。3.4 消息槽渲染useJsonParser 渐进式组装AssistantMessage组件对每条 assistant 消息调用useJsonParser(content, kit.schema)const { value } useJsonParser(content, kit.schema); if (!value) return null; return div contenteditable="false">【免费下载链接】CopilotKitThe Frontend Stack for Agents Generative UI. React, Angular, Mobile, Slack, and more. Makers of the AG-UI Protocol项目地址: https://gitcode.com/GitHub_Trending/co/CopilotKit创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表