ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

CopilotKit CrewAI Conversational Flows 多模态附件 QA 指南:图片与 PDF 的端到端验证

CopilotKit CrewAI Conversational Flows 多模态附件 QA 指南:图片与 PDF 的端到端验证 CopilotKit CrewAI Conversational Flows 多模态附件 QA 指南图片与 PDF 的端到端验证【免费下载链接】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 仓库中 CrewAI Conversational Flows 集成示例的 Multimodal Attachments多模态附件演示单元以 QA 文档 的验收清单为主线深入拆解其「图片 / PDF 上传 → AG-UI 附件管线 → CrewAI Flow → 视觉模型」的完整链路。读者将掌握该演示的界面元素定位、示例附件注入与手动拖拽上传的验证方法、后端多模态 Flow 与独立 Runtime 路由的架构设计以及 E2E 测试所钉住的各类回归场景可直接用于复测或参考实现。一、演示单元概览验证入口与功能边界该 QA 文档针对的是示例仓库中一个名为Multimodal AttachmentsWave 2b的独立演示单元其在 manifest.yaml 中的注册信息如下- id: multimodal name: Multimodal Attachments description: Image and PDF uploads routed through the AG-UI attachment pipeline tags: - chat-ui route: /demos/multimodal演示页面位于src/app/demos/multimodal/page.tsx路由为/demos/multimodal。它专门验证「图片与 PDF 附件通过 AG-UI 附件管线进入对话并由视觉能力模型理解内容」这一核心能力涉及三块主要代码职责关键文件前端演示页与聊天容器page.tsx、multimodal-chat.tsx示例附件按钮样本注入sample-attachment-buttons.tsx后端 CrewAI Flow 与 Runtimemultimodal_flow.py、route.ts二、验收步骤详解从页面加载到附件回复步骤 1导航到演示页面启动示例应用后CrewAI 后端位于AGENT_URL默认http://localhost:8000在浏览器中访问/demos/multimodal。页面由MultimodalDemoPage渲染外层通过CopilotKit runtimeUrl/api/copilotkit-multimodal agentmultimodal-demo将运行时和 Agent 绑定内层为MultimodalChatexport default function MultimodalDemoPage() { return ( CopilotKit runtimeUrl/api/copilotkit-multimodal agentmultimodal-demo MultimodalChat / /CopilotKit ); }见 page.tsx步骤 2验证样本行与两个示例按钮页面顶部渲染SampleAttachmentButtons其根容器带有data-testidmultimodal-sample-row内部包含两个按钮data-testidmultimodal-sample-image-button—— “Try with sample image”data-testidmultimodal-sample-pdf-button—— “Try with sample PDF”E2E 用例page loads with sample row, sample buttons, composer, and paperclip见 multimodal.spec.ts同时断言了聊天输入框copilot-chat-textarea与回形针上传按钮copilot-add-menu-button可见。按钮样式的两个样本定义如下按钮filenamemimeTypefetchUrl自动提示词Try with sample imagesample.pngimage/png/demo-files/sample.pngcan you tell me what is in this demo image I just attachedTry with sample PDFsample.pdfapplication/pdf/demo-files/sample.pdfcan you tell me what is in this demo pdf I just attached样本文件存放在 public/demo-files/要求以二进制形式提交仓库根目录.gitattributes控制sample.png为小于 50 KB 的 PNGCopilotKit 标识等可识别图形为宜sample.pdf为小于 50 KB 的单页 PDF且内容需包含 “CopilotKit” 字样以满足 E2E 软断言。若样本文件缺失页面仍可正常渲染只是样本按钮会抛出 fetch 错误回形针与拖拽路径不受影响。步骤 3点击 “Try with sample image” 并验证附件 chip点击后组件通过useAgent({ agentId })拿到 Agent 实例用agent.addMessage(...)直接构造一条包含文本与图片内容部分content parts的完整用户消息再通过copilotkit.runAgent({ agent })分发执行agent.addMessage({ id: generateMessageId(), role: user, content: [ { type: text, text: spec.autoPrompt }, { type: partType, // image 或 document source: { type: data, value: sample.base64, mimeType: spec.mimeType }, metadata: { filename: spec.filename, size: sample.size }, }, ], } as Parameterstypeof agent.addMessage[0]); await copilotkit.runAgent({ agent });见 sample-attachment-buttons.tsx该路径刻意绕开 DOM与CopilotChat.onSubmitInput的内部实现使用相同的数据结构与运行时但由前端自行构建已 base64 化的内容部分因此不存在“附件仍在上传中却被拒绝发送”的竞态。附件 chip 随即出现在 composer输入区内用户消息气泡同时携带自动提示词。步骤 4提问 “What do you see?” 并验证 Agent 引用图片发送后消息经 Runtime 路由转发至 CrewAI 后端的MultimodalFlow。该 Flow 以系统提示词约束输出You are a concise multimodal assistant. Inspect attached images and document text carefully, describe the relevant contents, and explicitly name the attachment modality in your answer.见 multimodal_flow.pyE2E 对助手回复的断言是toContainText(/copilotkit|logo|image/i)即视觉模型应能描述出样本图片中的可识别元素。运行时内置aimock缓存了样本自动提示词的固定回复见 crewai-conversational-flows/multimodal.json保证演示在无真实模型调用时也可复现。步骤 5 与 6点击 “Try with sample PDF” 并验证 PDF chip 与总结回复点击 PDF 按钮后走同一条注入路径但内容部分的type为document、mimeType为application/pdf。验证要点输入区出现 PDF chip用户消息中以DocumentAttachment图标 文件名形式渲染而非img用户气泡中不得出现[Attached document]之类的 PDF 展平文本见下文回归说明提问 “Summarize this document” 后助手应引用 PDF 正文内容E2E 断言助手回复包含copilotkit因为样本 PDF 内容约定提及 “CopilotKit”。步骤 7手动拖拽图片到聊天窗口验证 chip 出现OS 文件选择器无法在 Playwright 中稳定自动化因此拖拽路径以手动方式验收将图片拖入聊天区域应出现与回形针路径一致的附件 chip。拖拽、回形针、样本按钮三条路径最终都汇入同一个onUpload回调行为完全一致。三、前端实现AttachmentsConfig 与样本注入的单一代码路径AttachmentsConfig 的关键参数MultimodalChat通过CopilotChat的attachments配置开启附件能力见 multimodal-chat.tsxconst MAX_FILE_SIZE_BYTES 10 * 1024 * 1024; // 10 MB const ACCEPT_MIME image/*,application/pdf; CopilotChat agentIdmultimodal-demo attachments{{ enabled: true, accept: ACCEPT_MIME, // 允许 image/* 与 application/pdf maxSize: MAX_FILE_SIZE_BYTES, // 单文件上限 10 MB onUpload, onUploadFailed: (err) { console.warn([multimodal-demo] attachment rejected, err); }, }} /onUpload指向fileToDataAttachment见 file-to-data-attachment.ts用FileReader.readAsDataURL将文件读为data:mime;base64,payload去掉data:前缀后返回{ type: data, value: base64, mimeType, metadata: { filename, size } }——即AttachmentUploadResult的data变体。该演示不将文件上传到外部存储而是在浏览器内联 base64属于自包含的 Wave 2b 规格实现。样本注入为何走 Agent 表面而非 DOM组件头注释记录了一次真实的实现迭代见 sample-attachment-buttons.tsx早期版本通过DataTransfer 合成change事件驱动聊天组件的隐藏input typefile让样本走与回形针完全相同的onUpload/useAttachments管线。但自动发送后续提示词时附件仍处于status: uploadingCopilotChat.onSubmitInput会以Cannot send while attachments are uploading拒绝发送并清空输入而从外部探测上传完成状态又需要轮询 spinner 覆盖层慢渲染下极易竞态。于是最终版完全跳过 DOM直接通过 V2 Agent 表面构建“文本 附件内容部分”的完整消息再runAgent。这正是 QA 步骤 3 中“点击样本按钮即自动发送”行为的由来。样本文件的魔法字节校验为避免构建/部署时 Git LFS 未拉取导致 Next.js 把 LFS 指针文件以version https://git-lfs...开头的纯文本 stub以image/png的 Content-Type 误服务出去fetchSample在注入前校验了文件头PNG 要求前 4 字节为0x89 0x50 0x4E 0x47PDF 要求前 4 字节为0x25 0x50 0x44 0x46即%PDF命中 LFS 指针前缀时给出可操作的错误提示运行git lfs pull或设置GIT_LFS_ENABLED1。见 sample-attachment-buttons.tsx四、前端 shimlegacy 格式镜像与媒体去重legacy-converter-shim.tsxLegacyConverterShim是保障 QA 步骤 36 界面断言成立的关键补丁通过useAgent订阅同一 Agent 实例解决三个已知问题1. 现代附件部分对 agent 不可见。已发布的ag-ui/langgraph转换器只识别 legacy 形态{ type: binary, mimeType, data | url }会静默丢弃现代{ type: image | document, source: {...} }部分。shim 在onRunInitialized中为每个现代媒体部分追加而非替换一个 legacybinary镜像——因为CopilotChatUserMessage的getMediaParts只渲染image|audio|video|document替换会让附件在 run 快照回写后从聊天界面消失。同时保留两种形态保证幂等。2. 回程媒体双重化且类型错乱。转换器把binary部分转成 LangChainimage_url发出又把返回的image_url一律还原成 AG-UIimage——因此 PDF 会以type: imagemimeType: application/pdf的形式回来落入ImageAttachment渲染出破损img同时用户原始的现代部分仍残留在 state 中出现“一个附件两个 chip”。shim 在onMessagesSnapshotEvent与onRunFinalized中按source.value去重并按 mimeType 重写typeimage/*→imageaudio/*→audiovideo/*→video其余 →document使 PDF 正确落到DocumentAttachment图标 文件名图片落到ImageAttachment。3. PDF 展平文本泄漏进 UI。曾经_PdfFlattenMiddleware在before_model阶段把[Attached document]\npdf body写回 state聊天界面会原样渲染。改用wrap_model_call后改写只作用于模型请求本身QA 步骤 6 中“用户气泡不出现[Attached document]”的断言即钉住此回归。五、后端独立 Runtime 路由与视觉能力 Flow独立 Runtime多模态模型范围隔离演示使用专用 API 路由/api/copilotkit-multimodal见 route.ts。其设计动机在文件头注释中明确将附件管线base64 图片 / PDF 转发、视觉内容块限制在这一独立 cell 内其他演示的运行时保持精简、聊天 LLM 不受影响。该路由把multimodal-demo与default两个 agent 名映射到同一个HttpAgent指向 CrewAI 后端的/conversational_flows/multimodal端点const AGENT_URL process.env.AGENT_URL || http://localhost:8000; function createAgent() { return new HttpAgent({ url: ${AGENT_URL}/conversational_flows/multimodal }); } const agents: Recordstring, AbstractAgent { multimodal-demo: createAgent(), default: createAgent(), };CrewAI Flow按附件模态分流模型调用后端MultimodalFlowmultimodal_flow.py是一个专门的视觉能力 Flow由ag_ui_crewai提供的CopilotKitState与copilotkit_stream驱动。CrewAI 桥接层会在 Flow 启动前把 AG-UI 附件部分标准化为 LiteLLM / OpenAI 内容块。chat方法按附件模态分流包含 PDF 时通过_pdf_responses_input将桥接标准化后的 PDF 块转换为 OpenAI Responses 的input_file部分file_data为data:application/pdf;base64,...再调用aresponses(modelopenai/gpt-5.4, input..., streamTrue)图片则以input_image部分处理detail: auto不包含 PDF 时走常规acompletion补全路径messages中混入系统提示词与对话历史同时携带toolsself.state.copilotkit.actions保持工具能力。两条路径的响应都会经copilotkit_stream流式返回并追加到state.messages。系统提示词要求模型“明确说出附件模态”因此助手回复会自然提及“image / PDF”这与 QA 步骤 4、6 中“Agent 引用图片 / PDF 内容”的预期一致。前端到后端的消息形态image|document与binary并存综合前几节可以画出一条完整链路前端 agent.addMessage现代 image|document 部分 → LegacyConverterShim 追加 legacy binary 镜像 → /api/copilotkit-multimodal RuntimeHttpAgent → CrewAI 后端 /conversational_flows/multimodal → ag_ui_crewai 桥接标准化内容块 → MultimodalFlow 按模态调用 gpt-5.4Responses 或 Completion → 流式回复 → 前端去重/归一化 shim → 渲染单个正确 chip六、E2E 测试五条回归断言与验证方法multimodal.spec.ts 覆盖了 QA 文档的自动化部分测试集中在样本注入路径OS 文件选择器不可自动化故拖拽留作手动步骤。每个用例都是实际回归的钉板测试用例钉住的回归点关键断言页面加载元素样本行、两个样本按钮、textarea、回形针可见multimodal-sample-row、按钮 enabled样本图片自动发送提示词用户消息恰好一个图片 chip无破损图片img数量为 1无Failed to load image助手回复匹配/copilotkit\|logo\|image/i样本 PDFPDF 渲染为DocumentAttachment而非破损imgPDF 展平文本不泄漏无img、无Failed to load image、可见PDF标签、无[Attached document]、助手回复含copilotkit图片后接 PDF同会话第一条消息不被二次发送污染各消息保持自己的单个 chip第一条仍 1 个img第二条为干净的 PDF chipPDF 后接图片同会话对称场景PDF chip 不消失、图片不翻倍第一条保持 PDF 标签第二条恰好 1 个img测试依赖 aimock 预置的固定回复crewai-conversational-flows/multimodal.json两条userMessage与样本按钮的自动提示词逐字一致因此无需真实 LLM 即可稳定复测。七、执行验收清单可直接复用的 QA 流程综合以上分析可把原 QA 文档整理为可执行的完整清单访问/demos/multimodal确认data-testidmultimodal-sample-row渲染出图片 / PDF 两个按钮点击 “Try with sample image”确认 composer 内出现图片附件 chip输入 “What do you see?” 发送确认 Agent 回复引用图片内容并声明模态点击 “Try with sample PDF”确认出现 PDF chip且用户气泡以文档图标而非图片形式渲染输入 “Summarize this document” 发送确认 Agent 回复引用 PDF 正文 6.手动将图片拖拽到聊天窗口确认出现与回形针一致的 chip 7.回归同一会话内交替发送图片与 PDF确认每条用户消息各自保持恰好一个类型正确的 chip无双重化、无破损图片、无[Attached document]泄漏。结语多模态附件的难点从来不在“上传”而在消息形态在 AG-UI 现代部分、legacy 桥接、CrewAI 内容块、渲染组件之间的多次转换与往返。CopilotKit 的 Multimodal Attachments 演示用“独立 Runtime 路由 专用视觉 Flow 前端 shim 补丁 E2E 回归钉板”四层结构把图片与 PDF 的端到端链路收敛成一套可复测、可复用的参考实现——这正是本 QA 文档背后最值得借鉴的工程实践。相关阅读QA 文档、multimodal-chat.tsx、multimodal_flow.py、E2E 测试。【免费下载链接】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),仅供参考
返回列表