必须用agentkit的runtime adapter统一处理sse流式事件,否则工具调用中断、上下文丢失、消息乱序;需部署langchain+qdrant rag服务并暴露/rag/query接口,前端通过adapter解析sse、映射事件类型、透传source_docs,再用useagent调用generate发送问题并渲染带来源的答案。
☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 多模态理解力帮你轻松跨越从0到1的创作门槛☜☜☜

要让前端智能体直接对接RAG知识库并实现自然问答,不是靠改后端API地址就能完事——必须用AgentKit的Runtime Adapter统一处理流式事件,否则工具调用中断、上下文丢失、消息乱序会立刻暴露。
准备可运行的RAG服务端
先确认Python侧已部署好LangChain V1.3 + Qdrant向量库的RAG服务,暴露/rag/query接口,支持POST JSON请求,返回格式为SSE流(event: message → data: {"type":"thinking","content":"检索中..."})。这一步不能跳过,AgentKit的Adapter只认标准流协议,非SSE响应会导致前端卡死在loading状态。
启动命令示例:uvicorn rag_server:app --reload --port 8001。确保本地能curl -N http://localhost:8001/rag/query成功收到逐行data块。
安装并初始化AgentKit前端库
执行:npm install @vapd/agentkit。
在App.tsx顶部引入:import { AgentProvider, useAgent } from '@vapd/agentkit';
将根组件包裹进
构造Runtime Adapter对接RAG服务
创建adapter.ts文件,导出一个符合RuntimeAdapter接口的对象:
第一步:定义generateResponse方法,使用fetch发起POST请求,手动解析SSE流。注意必须设置headers: {'Content-Type': 'application/json'},否则FastAPI后端会拒绝解析body。
第二步:对每个data行做JSON.parse(),再根据type字段映射为标准AgentStreamEvent类型。例如当data.type === 'answer'时,必须设event.type = 'assistant_message',否则前端useAgent钩子无法识别该消息为最终回答。
第三步:在event.data中嵌入source_docs字段(来自RAG返回的metadata),这样后续UI才能渲染引用来源。不传这个字段,用户就看不到答案出自哪份PDF第几页。
UP 简历 AI 求职助手。创建专业简历、搜索校招/社招/实习岗位、JD 对照优化、简历诊断、每日求职监控、智能投递指导。当用户说"创建简历"、"编辑简历"、"搜索校招"、"找工作"、"优化简历"、"投递"、"监控校招"时使用。
在组件中调用RAG问答
方法一:使用useAgent Hook直接发送问题
const { messages, generate, isLoading } = useAgent();
调用generate({ input: "公司差旅报销最新流程是什么?" }),输入字符串即可,无需构造复杂payload——AgentKit自动补全threadId和runId。
方法二:手动控制消息流,适合需要插入自定义Loading态的场景
创建const controller = new AbortController();,传入generate参数的signal字段,可在用户点击取消时立即中断HTTP连接,避免后端继续浪费算力检索。
【注意】调用generate前必须确保messages数组为空或已清空历史,否则RAG上下文会混入无关对话,导致检索结果偏移。
渲染带来源标记的回答
遍历messages数组,当msg.type === 'assistant_message'且msg.data?.source_docs存在时,用map()渲染每个doc的title + page_number。
来源链接必须用target="_blank" rel="noopener"打开,否则在iOS WebView里会触发白屏——这是鸿蒙与iOS双端实测踩出的坑。
这一步操作起来很简单,直接把source_docs.map()结果塞进JSX就行,但漏掉rel属性会导致移动端页面崩溃。










