LangChain Frontend 10 大核心模式完整总结
本文基于 LangChain 官方前端文档覆盖Markdown 渲染、工具调用、人机协同、分支对话、推理 Token、结构化输出、消息队列、断连重连、时光回溯、生成式 UI10 大场景用通俗语言 核心逻辑 代码要点 最佳实践完整还原官方用法不删减、不跳步。一、Markdown Messages流式渲染富文本 Markdown核心作用把 LLM 输出的标题、列表、代码块、表格等 Markdown 格式实时流式渲染成富文本不浪费模型输出的结构化信息。渲染三步骤接收useStream 实时累积流式文本到 msg.text响应式更新解析Markdown 库把纯文本转成 HTML/React 元素聊天长度 5ms渲染插入 DOMReact 用虚拟 DOMVue/Svelte/Angular 用净化后 HTML各框架选型框架推荐库关键说明Reactreact-markdown remark-gfm直接转 React 元素无需 XSS 净化Vuemarked dompurify转 HTML 后必须净化Sveltemarked dompurify同 Vue用 {html}Angularmarked dompurify同 Vue用 [innerHTML]关键代码Reactimport ReactMarkdown from react-markdown; import remarkGfm from remark-gfm; // 通用Markdown组件 function Markdown({ children }) { return ( div classNamemarkdown-content ReactMarkdown remarkPlugins{[remarkGfm]}{children}/ReactMarkdown /div ); } // 聊天流中使用 {stream.messages.map(msg ( AIMessage.isInstance(msg) ? Markdown key{msg.id}{msg.text}/Markdown : p key{msg.id}{msg.text}/p ))}安全与优化XSS 防护Vue/Svelte/Angular 必须用 DOMPurify 净化移除 script、onclick 等流式优化长消息50KB用 requestAnimationFrame 节流渲染样式建议紧凑间距、小字号适配聊天气泡最佳实践必开 GFM 支持表格、删除线、任务列表开启 breaks: true把单换行转空内容判断避免渲染空容器测试富内容标题、嵌套列表、长代码、宽表格二、Tool Calling工具调用富卡片渲染核心作用把 Agent 调用天气、计算器、搜索、数据库等工具的 JSON 结果渲染成带加载 / 成功 / 失败状态的可视化卡片。工作流程Agent 发出工具调用name/args/id→ 2. 后端执行 → 3. useStream 同步 toolCalls 数组 → 4. 前端渲染状态卡片核心类型ToolCallWithResultinterface ToolCallWithResult { call: { id: string; name: string; args: object }; result: ToolMessage | undefined; state: pending | completed | error; // 三状态 }关键代码消息绑定工具调用function Message({ message, toolCalls }) { // 按消息匹配工具调用 const messageToolCalls toolCalls.filter(tc message.tool_calls?.find(t t.id tc.call.id) ); return ( div p{message.content}/p {messageToolCalls.map(tc ( ToolCard key{tc.call.id} toolCall{tc} / ))} /div ); }工具卡片分发function ToolCard({ toolCall }) { if (toolCall.state pending) return LoadingCard /; if (toolCall.state error) return ErrorCard /; // 按工具名渲染专属卡片 switch (toolCall.call.name) { case get_weather: return WeatherCard /; case calculator: return CalculatorCard /; default: return GenericToolCard /; } }最佳实践必处理三状态pending/completed/error不空白安全解析JSON.parse 包 try/catch加载态显式显示工具名 参数让用户知道在做什么卡片紧凑不挤占聊天区域三、Human-in-the-Loop人机协同审批流核心作用Agent 执行发邮件、删数据、转账等高危操作前暂停等待人工审批通过后再继续。中断流程Agent 触发中断 → 2. stream.interrupt 抛出待办动作 → 3. UI 渲染审批卡片 → 4. 用户决定同意 / 拒绝 / 编辑→ 5. stream.submit 恢复执行中断数据结构interface HITLRequest { actionRequests: { action: string; args: object; description?: string }[]; reviewConfigs: { allowedDecisions: (approve|reject|edit)[] }[]; }三种决策Approve同意直接执行stream.submit(null, { command: { resume: { decision: approve } } });Reject拒绝带原因退回stream.submit(null, { command: { resume: { decision: reject, reason } } });Edit编辑修改参数后执行stream.submit(null, { command: { resume: { decision: edit, args } } });最佳实践清晰上下文显示动作 参数 说明一键同意同意最简拒绝 / 编辑多步编辑校验JSON 格式校验持久化中断刷新页面不丢失审计日志记录所有决策四、Branching Chat分支对话编辑 / 重生成 / 回溯核心作用把对话变成树结构编辑消息、重生成回答会创建分支不丢失历史可自由切换版本。核心能力编辑任意用户消息从该点重跑重生成任意 AI 回答分支切换查看不同对话路径关键配置// 必须开启历史获取 const stream useStream({ apiUrl: AGENT_URL, assistantId: branching_chat, fetchStateHistory: true, // 关键 });核心操作编辑消息function handleEdit(stream, originalMsg, metadata, newText) { const checkpoint metadata.firstSeenState?.parent_checkpoint; stream.submit( { messages: [{ ...originalMsg, content: newText }] }, { checkpoint } ); }重生成回答function handleRegenerate(stream, metadata) { const checkpoint metadata.firstSeenState?.parent_checkpoint; stream.submit(undefined, { checkpoint }); }分支切换// 分支切换器 function BranchSwitcher({ metadata, onSwitch }) { const { branch, branchOptions } metadata; // 渲染前后箭头 当前版本/总版本 }最佳实践必开 fetchStateHistory分支器仅多版本时显示悬停显示编辑 / 重生成按钮保持界面整洁切换分支保留滚动位置流式中禁用操作五、Reasoning Tokens推理过程可视化核心作用展示 OpenAI o1/o3、Claude 等模型的思考过程把推理块和最终回答分开渲染提升透明感。两种内容块// 推理块思考过程 { type: reasoning, reasoning: 一步步分析... } // 文本块最终答案 { type: text, text: 答案是42 }提取逻辑function extractBlocks(msg) { const reasoning msg.contentBlocks .filter(b b.type reasoning) .map(b b.reasoning).join(); const text msg.contentBlocks .filter(b b.type text) .map(b b.text).join(); return { reasoning, text }; }思考气泡组件默认折叠点击展开流式中显示加载动画显示字符数提示思考量最佳实践默认折叠不干扰阅读视觉区分淡紫色背景独立样式支持展开 / 收起动画处理空推理、多轮推理六、Structured Output结构化输出渲染核心作用让 Agent 直接输出JSON 结构化数据而非纯文本前端映射为卡片、表格、步骤等定制 UI。实现原理Agent 用一个纯数据工具返回结构化参数无实际执行逻辑只做数据载体。提取函数function extractStructuredOutputT(messages, requiredFields []) { const lastAI messages.filter(AIMessage.isInstance).at(-1); const toolCall lastAI?.tool_calls?.[0]; if (!toolCall?.args) return null; // 校验必填字段 const hasRequired requiredFields.every(f toolCall.args[f] ! null); return hasRequired ? (toolCall.args as T) : null; }渐进式渲染流式中字段到达即渲染不用等完整数据提升体验。最佳实践必校验必填字段通用提取函数适配多 schema扁平 schema易流式渲染提供降级方案富文本 ↔ 结构化七、Message Queues消息队列批量发送核心作用支持用户连续发多条消息不用等上一条回复服务端顺序排队执行前端可查看 / 取消队列。核心能力批量提交自动排队实时显示待处理列表单条 / 清空取消链式提交onCreated队列 APIstream.queue { entries: QueueEntry[], // 待办列表 size: number, // 数量 cancel: (id) Promisevoid, // 取消单条 clear: () Promisevoid, // 清空全部 };关键代码// 提交消息自动入队 function handleSubmit(text) { stream.submit({ messages: [{ type: human, content: text }] }); } // 队列展示与取消 {stream.queue.entries.map(entry ( li key{entry.id} {entry.values.messages[0].content} button onClick{() stream.queue.cancel(entry.id)}取消/button /li ))}最佳实践显示消息预览方便识别取消仅影响未开始任务新线程清空队列处理高并发提交八、Join Rejoin Streams断连重连核心作用客户端断网 / 切页 / 后台时Agent 继续服务端执行重连后无缝恢复不丢失进度。核心配置// 提交时开启可恢复 stream.submit( { messages }, { onDisconnect: continue, // 断连后继续执行 streamResumable: true, // 允许重连 } );核心 APIstream.stop ()断开客户端不停止 Agentstream.joinStream (runId)用运行 ID 重连onCreated保存 runId本地存储持久化重连逻辑// 保存 runId const stream useStream({ onCreated(run) { localStorage.setItem(runId, run.run_id); } }); // 重连 stream.joinStream(localStorage.getItem(runId));最佳实践必存 runId状态 本地存储显式连接状态指示器切页自动重连清理过期 runId重连失败友好提示九、Time Travel时光回溯检查点回滚核心作用Agent 每步执行生成检查点可查看任意时刻状态、从历史点恢复执行相当于对话级别的 Git 回溯。检查点结构interface ThreadState { checkpoint: { checkpoint_id, timestamp }; // 快照ID values: AgentState; // 完整状态消息自定义数据 tasks: { name, interrupts }[]; // 执行节点 next: string[]; // 下一步节点 }时光旅行操作// 从检查点恢复执行 stream.submit(null, { checkpoint: selectedCheckpoint.checkpoint });界面建议左右分栏左侧聊天右侧时间线点击切换检查点查看状态并恢复。最佳实践懒加载历史避免大量检查点卡顿显示节点名 消息数不展示裸 ID恢复前二次确认高亮当前检查点支持键盘步进十、Generative UI生成式 UIAI 直接画界面核心作用AI 不输出文本直接生成 UI 描述前端用组件库安全渲染表单、卡片、仪表盘。三步流程定义组件目录声明 AI 可用组件 Props 校验ZodAI 生成 SpecJSON 描述组件树安全渲染json-render 按目录渲染杜绝非法组件组件目录示例const catalog defineCatalog(schema, { components: { Card: { description: 带标题的卡片, props: z.object({ title: z.string().optional() }) }, Button: { description: 按钮, props: z.object({ label: z.string(), variant: z.enum(...) }) } } });流式渲染// 流式中渐进渲染只渲染完整组件 const spec useMemo(() { if (!rawSpec?.root || !rawSpec.elements) return null; // 过滤有效元素 const safeElements Object.entries(rawSpec.elements) .filter(([_, el]) el.type el.props ! null) .reduce((acc, [k, v]) ({ ...acc, [k]: v }), {}); return { root: rawSpec.root, elements: safeElements }; }, [rawSpec, stream.isLoading]);最佳实践组件描述清晰引导 AI 正确使用流式传 loadingtrue平滑渲染用设计令牌适配明暗主题必包 JSONUIProvider小目录更精准避免大而全通用基础useStream 统一配置所有模式都基于 useStream通用模板import type { BaseMessage } from langchain/core/messages; // 1. 定义状态接口 interface AgentState { messages: BaseMessage[] } // 2. 初始化流 const stream useStreamtypeof myAgent({ apiUrl: http://localhost:2024, assistantId: 你的助手ID, fetchStateHistory?: true, // 分支/时光旅行用 });整体总结这 10 大模式覆盖了AI 聊天前端从基础渲染到高级交互的全场景基础渲染Markdown Messages能力扩展Tool Calling、Structured Output、Generative UI交互增强Branching Chat、Reasoning Tokens流程控制Human-in-the-Loop、Message Queues稳定性Join Rejoin调试 / 回溯Time Travel全部遵循流式优先、安全可控、体验优雅的官方设计理念可直接用于生产级 AI 聊天前端开发。