23-高阶组合Recipes
核对日期:2026-05-18
官方资料:Middleware https://docs.langchain.com/oss/javascript/langchain/middleware/overview;Context engineering https://docs.langchain.com/oss/javascript/langchain/context-engineering;Guardrails https://docs.langchain.com/oss/javascript/langchain/guardrails;HITL https://docs.langchain.com/oss/javascript/langchain/human-in-the-loop;MCP https://docs.langchain.com/oss/javascript/langchain/mcp;LangSmith https://docs.langchain.com/langsmith/observability-quickstart。
官方概念
LangChain 的高级能力不是孤立 API,而是组合模式。生产系统通常同时使用 Agent、Tools、Middleware、Runtime context、Structured output、Memory、Retrieval、Guardrails、HITL、Streaming 和 LangSmith。难点不是“会不会调用”,而是“这些组件如何组合且不互相污染边界”。
机制
Recipe 1:按任务复杂度动态选择模型
适用场景:大多数请求很简单,但少数请求需要更强模型或更长上下文。
实现步骤:
- 在 runtime context 中传入用户等级、成本预算、任务类型。
- middleware 读取 messages 和 context。
- 简单任务走低成本模型,复杂任务走高能力模型。
- trace 记录模型选择原因。
- eval 分模型统计质量和成本。
TypeScript 伪代码:
const modelRouter = createMiddleware({
name: "ModelRouter",
wrapModelCall: (request, handler) => {
const complexity = estimateComplexity(request.messages);
const model = complexity > 0.7 ? advancedModel : cheapModel;
return handler({ ...request, model });
},
});
验收:
- 同一 eval dataset 分别统计 cheap/advanced 命中率。
- 复杂任务确实进入 advanced。
- 成本预算超限时降级或拒绝。
Recipe 2:按权限动态暴露工具
适用场景:不同角色能使用不同工具,或同一用户在不同租户权限不同。
实现步骤:
- 认证服务先生成 runtime context。
- middleware 根据 roles/tenant/filter 过滤工具。
- 工具执行层再次校验权限。
- 记录“哪些工具暴露给模型”。
不要只过滤 UI。模型拿到的 tools 列表才是实际暴露面。
验收:
| 用例 | 预期 |
|---|---|
| viewer 请求删除数据 | 不暴露 delete 工具 |
| operator 请求更新工单 | 暴露 update 工具且执行层二次鉴权 |
| admin 跨租户请求 | 检索和工具都拒绝 |
Recipe 3:RAG + Structured Output + Citation
适用场景:知识库问答、政策解释、报告生成。
组合方式:
query -> ACL -> retrieval -> rerank -> prompt context -> structured answer -> citation validation
必须做的二次校验:
- 每条 citation 是否来自 retrieved docs。
- answer 中是否引用了无权限文档。
refused=false时 citations 是否非空。- conflict 是否被暴露。
结构化 schema:
const answerSchema = z.object({
answer: z.string(),
citations: z.array(citationSchema),
refused: z.boolean(),
refusalReason: z.enum(["NO_EVIDENCE", "NO_PERMISSION", "INJECTION_RISK"]).optional(),
conflicts: z.array(z.string()),
});
Recipe 4:长对话摘要 + 长期记忆
适用场景:学习助手、客服、项目协作 Agent。
组合方式:
| 组件 | 职责 |
|---|---|
| short-term memory | 保存当前 thread 的消息和状态 |
| summarize middleware | 对过长历史做摘要 |
| long-term store | 保存稳定用户偏好和事实 |
| context builder | 本轮只注入相关记忆 |
| guardrail | 防止隐私自动写入 |
失败模式:
- 摘要把事实写错。
- 长期记忆写入未经确认的推断。
- 所有记忆每轮都注入,造成上下文污染。
验收:
- 用户要求删除偏好后不再注入。
- 敏感内容不会进入 store。
- 摘要前后的关键任务约束一致。
Recipe 5:高风险工具 + HITL + Checkpointer
适用场景:发邮件、付款、删除、外发报告、生产变更。
实现步骤:
- 工具 metadata 标记 risk。
- HITL middleware 对高风险工具 interrupt。
- checkpointer 保存 thread state。
- 审批 UI 提供 approve/edit/reject/respond。
- 审批结果绑定 tool input hash。
- 恢复执行并写 audit。
审批记录:
interface ApprovalRecord {
approvalId: string;
threadId: string;
toolName: string;
toolInputHash: string;
decision: "approve" | "edit" | "reject" | "respond";
approverId: string;
decidedAt: string;
}
Recipe 6:MCP 工具接入 + 最小权限
适用场景:需要连接文件系统、浏览器、数据库、内部工具或第三方服务。
治理原则:
- MCP server 不等于可信工具。
- 每个 server 做能力白名单。
- tools/resources/prompts 分别授权。
- MCP tool output 视为不可信输入。
- 对外部 MCP server 做超时、限流和审计。
验收:
| 检查 | 通过标准 |
|---|---|
| 工具清单 | 只有任务需要的工具 |
| 资源权限 | 无法读取非授权路径 |
| 输出净化 | 外部工具返回不会覆盖 system prompt |
| trace | 记录 server、tool、latency、error |
Recipe 7:Streaming + 工具进度 + 前端协议
适用场景:长任务、Agent 多步执行、RAG 报告生成。
事件协议建议:
type AgentStreamEvent =
| { type: "token"; text: string }
| { type: "tool_start"; toolName: string }
| { type: "tool_progress"; toolName: string; message: string }
| { type: "tool_end"; toolName: string; ok: boolean }
| { type: "interrupt"; threadId: string; actions: unknown[] }
| { type: "error"; message: string; recoverable: boolean }
| { type: "done"; runId: string };
前端不应该只消费 token。Agent 应用需要展示工具状态、审批中断、错误和最终 run id。
Recipe 8:LangSmith Trace + Eval 闭环
适用场景:任何准备上线的 Agent。
闭环:
- trace 记录 messages、model、tools、retrieved docs、structured output。
- 从失败 trace 沉淀 dataset。
- eval 覆盖工具、RAG、结构化输出、安全、成本。
- CI 中跑关键 eval。
- 线上监控 drift 和失败样本。
指标:
| 维度 | 指标 |
|---|---|
| Tool | 正确工具调用率、缺参率、工具失败率 |
| RAG | recall、citation validity、拒答正确率 |
| Output | schema pass rate、parse retry count |
| Safety | prompt injection pass rate、PII leak rate |
| Ops | latency、tokens、cost、timeout、retry |
Python 差异
Python 组合方式类似,但 middleware、HITL、store、MCP 和 provider 包 API 名称不同。Recipes 的验收标准不应随语言改变;变的是代码实现。
工程边界
- Recipe 是组合,不是单个函数;每个边界都要有测试。
- Middleware 顺序改变会改变行为,要记录和评审。
- HITL 和 streaming 都需要协议,不只是 SDK 调用。
- LangSmith 能记录和评估,但不能替代你的断言设计。
常见反模式
| 反模式 | 后果 |
|---|---|
| 动态模型无 trace | 成本和质量无法归因 |
| 动态工具只靠前端隐藏 | 模型仍可能调用后端工具 |
| RAG citation 由模型编造 | 审计失败 |
| HITL 不持久化 | 中断后无法恢复 |
| streaming 事件无版本 | 前端升级困难 |
练习任务
- 在
LangChain/src/middleware/pipeline.ts旁写一份 middleware 顺序说明。 - 在
LangChain/src/api/streaming.ts中对照本章事件协议,标注缺口。 - 为
LangChain/scripts/run-eval.ts增加一个按能力分类统计的输出表。