CopilotKit × Google ADK 实战:Tool-Based Generative UI(gen-ui-tool-based)端到端 QA 测试指南
2026/9/13 9:39:38 网站建设 项目流程

CopilotKit × Google ADK 实战:Tool-Based Generative UI(gen-ui-tool-based)端到端 QA 测试指南

【免费下载链接】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 仓库中 Google ADK 集成示例的官方 QA 文档(showcase/integrations/google-adk/qa/gen-ui-tool-based.md),系统讲解 Tool-Based Generative UI(工具驱动型生成式 UI)演示的完整验收测试流程。文章会逐条拆解 QA 清单中的前置条件、功能测试与预期结果,并结合仓库内的 Agent 源码、前端注册代码与 Playwright E2E 测试,说明每一步该验证什么、为什么这样验证,帮助测试工程师与开发者快速掌握"Agent 调用工具 → 前端把工具结果渲染为自定义 React 组件"这一核心交互的验收方法。

一、被测对象:gen-ui-tool-based 演示是什么

在开始执行 QA 清单之前,先理解被测页面。gen-ui-tool-based(Tool-Based Generative UI)是 Google ADK 集成演示之一,其核心思想是:Agent 调用一个后端工具,工具返回结构化数据,前端把工具结果渲染为自定义 React 组件(而不是普通文本)

仓库的展示清单 manifest.yaml 中对该演示的定义如下:

  • 名称:Tool-Based Generative UI
  • 描述:Agent uses tools to trigger UI generation(Agent 使用工具触发 UI 生成)
  • 标签:controlled-generative-ui
  • 路由:/demos/gen-ui-tool-based
  • 高亮源码文件:
    • src/agents/gen_ui_tool_based_agent.py(后端 Agent)
    • src/app/demos/gen-ui-tool-based/page.tsx(前端页面)
    • src/app/api/copilotkit/route.ts(运行时代理)

从源码结构看,该演示的"工具驱动"体现在两个层面:

前端(page.tsx)通过@copilotkit/react-core/v2useComponent注册了两个前端工具:

useComponent({ name: "render_bar_chart", description: "Display a bar chart with labeled numeric values.", parameters: barChartPropsSchema, render: BarChart, }); useComponent({ name: "render_pie_chart", description: "Display a pie chart with labeled numeric values.", parameters: pieChartPropsSchema, render: PieChart, });

后端(gen_ui_tool_based_agent.py)是一个基于 Google ADKLlmAgent的"数据可视化助手":

gen_ui_tool_based_agent = LlmAgent( name="GenUiToolBasedAgent", model=get_model(), instruction=_INSTRUCTION, tools=[AGUIToolset()], after_model_callback=stop_on_terminal_text, )

其中的AGUIToolset()会把前端注册的工具注入到模型的每次请求中,让 Agent 在运行时"看得到、调得动"这些渲染工具;after_model_callback=stop_on_terminal_text则是防止 Gemini 在工具调用成功后无限循环重发同一工具调用的终止保护(详见 shared_chat.py)。

Agent 的指令(_INSTRUCTION)对图表工具的使用做了明确约定:

  • 用户请求图表时调用render_bar_chartrender_pie_chart,传入简短的标题、描述以及{label, value}形式的数据数组;
  • 小规模类别间的比较用柱状图,整体构成 / 占比用饼图;
  • 若用户只给了图表主题而没有具体数字(例如"按来源展示网站流量饼图"),不要反问用户要数据,而是自行编造合理的示意性样例值立即渲染图表,并在回复中注明数据是示意性的;
  • 保持聊天回复简短,"让图表本身说话"。

也就是说,QA 清单验证的本质是:前端注册的工具声明 → ADK 中间件注入 → 模型调用工具 → 前端按工具名渲染对应 React 组件这条完整链路是否通畅。

二、前置条件:演示部署与后端健康检查

QA 文档要求执行测试前满足两个前置条件:

  1. Demo 已部署且可访问:即能打开/demos/gen-ui-tool-based页面。
  2. Agent 后端健康:检查/api/health

这两个条件在仓库中都有对应的实现依据。

/api/health端点在 src/app/api/copilotkit/route.ts 中实现,它返回:

{ "status": "ok", "agent_url": "http://localhost:8000", "agent_status": "reachable", "agent_count": 47, "env": { "GOOGLE_API_KEY": "set", "NODE_ENV": "development" } }

其中agent_status是对后端AGENT_URL/health的实际探活结果(超时 3 秒),GOOGLE_API_KEY字段用于确认 Gemini 凭据是否已配置。如果GOOGLE_API_KEY显示为NOT SETagent_statusunreachable,则测试不会通过,应先修复后端。

后端健康检查还有一层:Python 侧 agent_server.py 通过HealthMiddleware在路由解析前直接短路返回/health,确保即使某个 Agent 挂载异常,健康探针依然可达。

建议:在浏览器中打开/api/health确认上述 JSON 返回后再开始执行功能测试,这能提前隔离"前端问题"与"后端问题"。

三、基础功能测试:页面加载与基本对话

QA 文档的第一步是验证页面基础功能:

  • 导航到 gen-ui-tool-based 演示页面
  • 验证 CopilotSidebar 默认打开,标题为 "Haiku Generator"
  • 验证主区域显示占位俳句卡片
  • 通过侧边栏发送一条基础消息
  • 验证 Agent 有响应

需要特别说明的是:QA 文档中关于 "Haiku Generator" 侧边栏、占位俳句卡片的描述与当前仓库源码已不一致。从源码看,该演示页面如今没有侧边栏,而是渲染一个居中的CopilotChat聊天组件(见 page.tsx):

return ( <div className="flex justify-center items-center h-screen w-full"> <div className="h-full w-full max-w-4xl"> <CopilotChat agentId="gen-ui-tool-based" className="h-full rounded-2xl" /> </div> </div> );

同时,仓库中的共享探针测试 d5-gen-ui-custom.test.ts 明确记载:旧版的generate_haiku/ HaikuCard 路径已被移除,全部 21 个 gen-ui-tool-based 页面现在统一注册render_bar_chart+render_pie_chart,共享契约就是"饼图契约"。

因此,执行本条测试时应按当前实现验证:

  • 打开/demos/gen-ui-tool-based,页面加载一个居中的CopilotChat聊天界面(无侧边栏/无页头装饰)
  • 消息输入框可见(textarea 或含 message placeholder 的输入控件)
  • 发送一条基础消息(如 "Hello")
  • 验证 Agent 在合理时间内返回助理消息

对应地,仓库 E2E 测试 gen-ui-tool-based.spec.ts 正是这样断言的:

test("sends message and gets assistant response", async ({ page }) => { const input = page.locator('textarea, [placeholder*="message"]').first(); await input.fill("Hello"); await input.press("Enter"); await expect( page.locator('[data-testid="copilot-assistant-message"]').first(), ).toBeVisible({ timeout: 30000 }); });

四、特性专项检查

4.1 Suggestions(建议提示)

QA 文档要求验证 "Nature Haiku"、"Ocean Haiku"、"Spring Haiku" 三个建议按钮可见。当前实现中,建议按钮由 suggestions.ts 通过useConfigureSuggestions配置,主题已从俳句替换为图表:

useConfigureSuggestions({ suggestions: [ { title: "Sales bar chart", message: "Show me a bar chart of quarterly sales for Q1, Q2, Q3, Q4.", }, { title: "Traffic pie chart", message: "Show me a pie chart of website traffic by source.", }, { title: "Market share", message: "Show a pie chart of smartphone market share by brand.", }, ], available: "always", });

对应测试步骤(按当前实现调整):

  • 验证 "Sales bar chart" 建议按钮可见
  • 验证 "Traffic pie chart" 建议按钮可见
  • 验证 "Market share" 建议按钮可见

E2E 测试 gen-ui-tool-based.spec.ts 对建议按钮的断言使用选择器[data-testid="copilot-suggestion"]并按标题文本过滤,可作为手工测试时定位元素的参考。

4.2 工具驱动的图表生成(核心链路)

QA 文档的本节标题为 "Haiku Generation (useFrontendTool)",期望点击建议按钮后渲染一张data-testid="haiku-card"的卡片,内含三行日文(haiku-japanese-line)与三行英文(haiku-english-line)。与 4.1 同理,当前实现已从"俳句生成"演化为"图表渲染":Agent 通过工具调用返回结构化数据,前端将其渲染为 SVG 图表组件。

点击 "Traffic pie chart" 建议(或直接输入 "Show me a pie chart of revenue by category")后,应当验证:

  • 助理消息内渲染出 SVG 可视化(饼图/环形图)
  • 图表包含标题与描述文本
  • 图例区域展示各分片的标签、数值与百分比
  • Agent 的随附文字简述了图表结论(例如哪个类别占比最大)

两个渲染组件的实现细节值得测试时留意:

  • 饼图 pie-chart.tsx:纯 SVG 手绘环形图,通过strokeDasharray/strokeDashoffset计算每个扇区,颜色取自固定调色板;数据为空时展示 "No data available" 的空态卡片。
  • 柱状图 bar-chart.tsx:基于 Recharts 的ResponsiveContainer,柱体高度 280px,带有barSlideIn入场动画——只有新到达的柱子才播放动画(通过useRef记录已渲染索引)。

两组件的 props 均由 zod schema 约束(titledescriptiondata: {label, value}[]),这就是 Agent 必须返回的结构化数据契约:

export const pieChartPropsSchema = z.object({ title: z.string().describe("Chart title"), description: z.string().describe("Brief description or subtitle"), data: z.array( z.object({ label: z.string(), value: z.number(), }), ), });

E2E 对图表渲染的断言方式(gen-ui-tool-based.spec.ts):

test("pie chart request renders SVG visualization", async ({ page }) => { const input = page.locator('textarea, [placeholder*="message"]').first(); await input.fill("Show me a pie chart of revenue by category"); await input.press("Enter"); const assistantMessage = page .locator('[data-testid="copilot-assistant-message"]') .first(); await expect(assistantMessage.locator("svg").first()).toBeVisible({ timeout: 60000, }); });

4.3 多张图表的堆叠与替换

QA 文档要求:生成第二首俳句后,新卡片出现在顶部、旧卡片仍保留在下方、初始占位卡片被移除。对应到当前图表实现:

  • 生成第一张图表(如 "Sales bar chart"),确认图表卡片出现
  • 再生成第二张图表(如 "Traffic pie chart"),确认新的图表卡片出现在消息流顶部
  • 确认上一条图表消息仍在其下可见(历史消息不被清除)
  • 确认初始的占位内容(如果有)已被移除

这一行为本质上是聊天消息流本身的追加语义——每条工具渲染结果附着在对应助理消息中,新消息追加在顶部,旧消息保留。手工测试时重点观察消息顺序组件是否随消息一起持久化

4.4 空消息与错误处理

QA 文档的错误处理部分:

  • 发送空消息,应被优雅处理(不崩溃、不报错)
  • 正常使用过程中控制台无报错(no console errors)

执行建议:

  • 在输入框为空时直接按回车,确认界面不抛异常、不出现未捕获的错误
  • 打开浏览器 DevTools Console,在完成一次完整的"发消息 → 生成图表"流程后检查是否有红色错误输出;服务端侧的错误会被 route.ts 记录为含errorId的结构化日志,且不会把内部堆栈回显给客户端——若控制台出现internal runtime error响应,可到服务端日志按errorId关联排查。

五、预期结果与验收标准

QA 文档给出的最终验收标准如下:

预期结果说明
侧边栏 3 秒内加载当前实现为聊天界面,可理解为页面与聊天组件在 3 秒内就绪
Agent 10 秒内响应并生成俳句当前实现为 10 秒内响应并渲染图表
俳句卡片同时显示日文与英文当前实现为图表卡片正确渲染标题/描述/数据
生成的俳句按最新在上堆叠当前实现为多条图表消息按最新在上堆叠
无 UI 错误或布局破损无报错、无错位、无空态异常

其中"10 秒内响应"与"60 秒内图表可见"的时间口径在 E2E 测试中也有体现:助理消息可见的超时设置为 30000ms(gen-ui-tool-based.spec.ts),SVG 图表可见的超时设置为 60000ms(同文件 L41-L43)。手工测试时可参考这些阈值判断"慢"是 Agent 推理慢还是链路故障。

六、QA 文档与当前实现的差异说明(重要)

由于 qa/gen-ui-tool-based.md 中多处描述(Haiku Generator 侧边栏、Nature/Ocean/Spring 俳句建议、haiku-cardhaiku-japanese-linehaiku-english-linehaiku-image/images/图片渲染)与仓库当前源码不一致,特此汇总差异清单,避免测试者按过时步骤误判:

QA 文档描述当前源码实现依据
CopilotSidebar,标题 "Haiku Generator"居中的CopilotChat聊天界面page.tsx
Nature/Ocean/Spring 俳句建议Sales bar chart / Traffic pie chart / Market sharesuggestions.ts
useFrontendTool生成俳句卡片Agent 调用render_bar_chart/render_pie_chart,前端渲染 SVG 图表gen_ui_tool_based_agent.py
haiku-image图片渲染无图片渲染逻辑源码无/images/图片引用
俳句卡片日文/英文行图表的标题、描述、图例pie-chart.tsx

这一差异也得到仓库探针测试的佐证:d5-gen-ui-custom.test.ts 明确指出旧generate_haiku路径"is GONE",所有集成统一走饼图契约,且探针断言要求渲染出<svg>且 SVG 绘制子元素数量健康(5 个 circle,对应环形图扇区)。

七、如何复用这套 QA 方法论

7.1 自动化层面:两条可复用的验证路径

仓库为这个演示提供了两层自动化验证,手工 QA 之外可以对照使用:

  1. 集成级 E2E(tests/e2e/gen-ui-tool-based.spec.ts):Playwright 驱动真实页面,验证页面加载、三个建议按钮、饼图/柱状图 SVG 渲染、基础对话四条用例。
  2. 跨集成探针(d5-gen-ui-custom.test.ts):作为所有集成的共享契约,固定发送 "Show me a pie chart of revenue by category",断言 SVG 形状与助理回复中的关键 token(如提及占比最大的类别),防止某个集成在图表渲染上退化。

7.2 测试视角:本用例覆盖的验收要点

从测试设计角度,本 QA 清单实际覆盖了工具驱动型生成式 UI 的五个关键风险点:

  1. 工具注册与注入:前端useComponent注册的工具名能否被后端AGUIToolset()注入到模型请求(对应 4.1/4.2 的建议与生成用例);
  2. 结构化参数契约:zod schema 定义的{title, description, data}能否被 Agent 正确填满(对应 4.2 的图表内容校验);
  3. 渲染状态:工具结果从"调用中"到"渲染完成"的状态切换是否正确(README 提到useRenderTool会把argsresultstatus传给渲染器以展示加载与完成态,参见 gen-ui-tool-based/README.md);
  4. 消息流语义:多轮工具渲染结果的堆叠与顺序(对应 4.3);
  5. 健壮性:空输入、异常路径不产生崩溃与控制台错误(对应 4.4)。

对于想要在自建项目上复刻该模式的开发者,后端设置可参考 docs/setup/frontend-tools-setup.mdx,其中给出了AGUIToolset()的接入方式与完整的stop_on_terminal_text终止回调实现——这是让 Gemini 在工具调用后正确结束 agentic loop 的关键一环;前端则只需像本文 4.1/4.2 所示,用useComponent注册工具并绑定 React 渲染组件即可。

结语

Tool-Based Generative UI 是 CopilotKit 生成式 UI 体系中最经典的一条实现路径:Agent 不直接"生成界面",而是调用工具、返回结构化数据,由前端把数据渲染成丰富的自定义组件。本文以 Google ADK 集成的官方 QA 清单为主线,逐项说明了前置条件、功能验证、错误处理与验收标准,并结合仓库源码澄清了文档与当前实现的差异。测试人员可据此清单直接执行验收,开发者则可从这些用例反推该模式落地时最值得关注的工程细节——工具注入、参数契约与消息流语义。

【免费下载链接】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),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询