文章
LangChain.js 完全指南:前端视角的 AI 应用开发
LangChain.js 完全指南:前端视角的 AI 应用开发 从零开始构建 AI Agent,JavaScript/TypeScript 开发者的实用入门手册 目录 1. 核心概念 2. 基础使用 3. 进阶用法 4....
LangChain.js 完全指南:前端视角的 AI 应用开发 #
从零开始构建 AI Agent,JavaScript/TypeScript 开发者的实用入门手册
目录 #
一、核心概念 #
1.1 什么是 LangChain.js?(大白话解释) #
想象一下,你要做一个 AI 助手。最原始的方式是:直接调用 OpenAI 的 API,发一条消息,等回复。这就像打电话问客服一个问题,挂断,结束。
但真实场景要复杂得多:
- 多轮对话 — 用户说"帮我查天气",AI 问"哪个城市?",用户说"北京",AI 再调用天气 API...
- 需要工具 — AI 光会说话没用,还得能查数据库、调用 API、读写文件
- 记住上下文 — 用户之前说了什么,AI 得记住,不能每次都从头问
LangChain.js 就是帮你解决这些问题的框架。
打个比方:
- 直接调用 AI API ≈ 用原生 JavaScript 写网页
- 用 LangChain.js ≈ 用 React/Vue 写应用
它帮你把"模型调用 → 工具执行 → 状态管理 → 对话记忆"这套流程封装好了,你只需要声明式地描述"我要什么",而不是命令式地写一堆异步回调。
1.2 为什么需要 LangChain.js? #
| 问题 | 直接调用 API | 用 LangChain.js |
|---|---|---|
| 模型切换 | 每个提供商 API 不同,要改代码 | 改一个字符串就行 "openai:gpt-4" → "anthropic:claude" |
| 工具调用 | 手写解析逻辑、处理回调、错误处理 | createAgent({ tools: [getWeather] }) 一行搞定 |
| 多轮对话 | 自己维护 message 数组、实现记忆 | 内置 Memory,自动管理 |
| 结构化输出 | 手写 JSON 解析、校验 | 用 Zod 定义 schema,自动校验 |
| 调试追踪 | 加 console.log,没有可视化 | LangSmith 一键追踪 |
一句话总结:LangChain.js 让你从"写 AI 调用代码"变成"配置 AI Agent"。
1.3 LangChain.js 的核心名词 #
| 名词 | 是什么 | 前端类比 |
|---|---|---|
| Model | LLM 模型(GPT、Claude 等) | 相当于"后端服务",提供推理能力 |
| Tool | AI 能调用的函数(查天气、搜数据库) | 相当于"API 封装",给 AI 用 |
| Agent | AI + 工具 + 记忆的组合体 | 相当于"一个完整的 App" |
| Prompt | 给 AI 的指令(角色设定、任务描述) | 相当于"组件 props",告诉 AI 干什么 |
| Memory | 对话历史、用户偏好等记忆 | 相当于"Redux state",持久化数据 |
| Structured Output | 强制 AI 返回 JSON 格式 | 相当于"TypeScript 类型定义" |
| LangSmith | 调试/追踪工具 | 相当于"React DevTools" |
1.4 LangChain vs LangGraph vs Deep Agents #
这是三个不同的层级:
| 产品 | 定位 | 什么时候用 |
|---|---|---|
| LangChain | 基础框架 | 快速搭建一个 Agent |
| LangGraph | 低级编排框架 | 需要精细控制流程、复杂工作流 |
| Deep Agents | "开箱即用"的高级 Agent | 生产级 Agent,自动压缩对话、文件系统、子 Agent |
新手建议:先用 LangChain,熟练后再看 LangGraph。
二、基础使用 #
2.1 安装 #
# 核心包
npm install langchain @langchain/core
# 模型提供商(选你用的)
npm install @langchain/openai # OpenAI
npm install @langchain/anthropic # Claude
npm install @langchain/google-genai # Gemini
# 工具依赖
npm install zod # schema 定义要求:Node.js 20+
2.2 最简单的例子:直接调用模型 #
import { initChatModel } from "langchain";
// 设置 API Key(实际项目中用环境变量)
process.env.OPENAI_API_KEY = "your-api-key";
// 初始化模型
const model = await initChatModel("gpt-4o-mini");
// 调用
const response = await model.invoke("为什么鹦鹉会说话?");
console.log(response.content);
// "鹦鹉会说话是因为它们有很强的模仿能力..."这就是最基础的用法 —— 和直接调用 OpenAI API 差不多。
2.3 第一个 Agent:带工具的 AI #
import { createAgent, tool } from "langchain";
import * as z from "zod";
// 定义一个工具:查天气
const getWeather = tool(
// 工具的执行逻辑
({ city }) => `今天 ${city} 天气晴朗,温度 25°C`,
{
name: "get_weather", // 工具名称
description: "查询指定城市的天气", // AI 看到的描述
schema: z.object({
city: z.string().describe("城市名称,如:北京、上海")
})
}
);
// 创建 Agent
const agent = createAgent({
model: "gpt-4o-mini",
tools: [getWeather]
});
// 使用
const result = await agent.invoke({
messages: [{ role: "user", content: "北京今天天气怎么样?" }]
});
console.log(result.messages[result.messages.length - 1].content);
// "根据查询结果,北京今天天气晴朗,温度 25°C。适合出门散步!"发生了什么?
- 用户问"北京天气"
- AI 判断需要调用
get_weather工具 - AI 生成工具调用参数
{ city: "北京" } - 工具执行,返回结果
- AI 根据工具结果,生成最终回复
整个过程自动完成,你只需要定义工具。
2.4 使用不同的模型提供商 #
LangChain 的核心优势:切换模型只需改字符串。
// OpenAI
const agent1 = createAgent({
model: "openai:gpt-4o-mini",
tools: []
});
// Anthropic Claude
const agent2 = createAgent({
model: "anthropic:claude-sonnet-4-6",
tools: []
});
// Google Gemini
const agent3 = createAgent({
model: "google-genai:gemini-2.0-flash",
tools: []
});
// Azure OpenAI
const agent4 = createAgent({
model: "azure_openai:gpt-4o",
tools: []
});对应的环境变量:
OPENAI_API_KEY=xxx
ANTHROPIC_API_KEY=xxx
GOOGLE_API_KEY=xxx
AZURE_OPENAI_API_KEY=xxx
AZURE_OPENAI_ENDPOINT=xxx2.5 配置模型参数 #
import { initChatModel } from "langchain";
const model = await initChatModel("gpt-4o-mini", {
temperature: 0.7, // 创造性:0-1,越高越随机
maxTokens: 1000, // 最大输出长度
timeout: 30, // 超时时间(秒)
maxRetries: 3 // 失败重试次数
});
const agent = createAgent({
model,
tools: []
});| 参数 | 作用 | 推荐值 |
|---|---|---|
temperature |
0 = 确定性回答,1 = 创造性 | 工具调用用 0,聊天用 0.7 |
maxTokens |
输出上限 | 根据任务调整 |
timeout |
超时 | 网络不稳时增大 |
maxRetries |
重试次数 | 生产环境 10-15 |
三、进阶用法 #
3.1 定义系统提示词(System Prompt) #
系统提示词定义 Agent 的"角色"和"行为规则"。
const agent = createAgent({
model: "gpt-4o-mini",
tools: [getWeather],
systemPrompt: `你是一个专业的天气预报助手。
你的职责:
1. 查询用户指定城市的天气
2. 用轻松幽默的语气回复
3. 给出穿衣建议
如果用户没有指定城市,询问他们的位置。`
});
// 使用
await agent.invoke({
messages: [{ role: "user", content: "今天要穿什么?" }]
});
// AI 会先问 "你在哪个城市?"写提示词的技巧:
- 具体比笼统好("你是一个天气助手" > "你是一个助手")
- 列出可用工具,AI 才知道能干什么
- 设定边界("只回答天气相关的问题")
3.2 结构化输出(Structured Output) #
让 AI 返回 JSON,而不是自由文本。
import * as z from "zod";
// 定义输出格式
const WeatherReport = z.object({
city: z.string(),
temperature: z.number(),
condition: z.enum(["晴", "雨", "多云", "雪"]),
suggestion: z.string().describe("穿衣建议")
});
const agent = createAgent({
model: "gpt-4o-mini",
tools: [getWeather],
responseFormat: WeatherReport // 强制输出这个格式
});
const result = await agent.invoke({
messages: [{ role: "user", content: "北京天气" }]
});
// 直接拿到结构化数据
console.log(result.structuredResponse);
// {
// city: "北京",
// temperature: 25,
// condition: "晴",
// suggestion: "建议穿短袖,带个薄外套"
// }好处:
- 可以直接存数据库
- 前端可以直接渲染
- 类型安全,不会出现奇怪格式
3.3 添加对话记忆(Memory) #
没有记忆的 Agent,每次对话都是独立的,不会记住用户之前说了什么。
import { MemorySaver } from "@langchain/langgraph";
// 创建记忆存储
const checkpointer = new MemorySaver();
const agent = createAgent({
model: "gpt-4o-mini",
tools: [getWeather],
checkpointer // 启用记忆
});
// 第一次对话
await agent.invoke(
{ messages: [{ role: "user", content: "我叫小明" }] },
{ configurable: { thread_id: "user-123" } } // thread_id 区分不同用户
);
// 第二次对话(同一个 thread_id)
const result = await agent.invoke(
{ messages: [{ role: "user", content: "我叫什么名字?" }] },
{ configurable: { thread_id: "user-123" } }
);
console.log(result.messages[result.messages.length - 1].content);
// "你叫小明,你刚才告诉我的。"关键概念:
thread_id— 会话标识符,同一个 ID 共享记忆checkpointer— 记忆存储器,MemorySaver是内存版本
生产环境:用数据库存储记忆。
import { PostgresSaver } from "@langchain/langgraph-checkpoint-postgres";
const checkpointer = PostgresSaver.fromConnString(
"postgresql://user:pass@localhost:5432/mydb"
);3.4 工具访问上下文(Context) #
工具可以访问用户信息、会话数据。
import { tool, type ToolRuntime } from "langchain";
// 定义上下文类型
type MyContext = { user_id: string; user_name: string };
const getUserInfo = tool(
async (_, config: ToolRuntime<unknown, MyContext>) => {
// 从 config.context 获取上下文
const { user_id, user_name } = config.context;
// 模拟查询数据库
return `用户 ${user_name}(ID: ${user_id})已登录 3 天`;
},
{
name: "get_user_info",
description: "获取当前用户信息",
schema: z.object({})
}
);
const agent = createAgent({
model: "gpt-4o-mini",
tools: [getUserInfo],
contextSchema: z.object({
user_id: z.string(),
user_name: z.string()
})
});
// 调用时传入上下文
await agent.invoke(
{ messages: [{ role: "user", content: "我是谁?" }] },
{ context: { user_id: "abc123", user_name: "张三" } }
);3.5 流式输出(Streaming) #
实时显示 AI 回复,而不是等全部生成完。
const agent = createAgent({
model: "gpt-4o-mini",
tools: []
});
const stream = await agent.stream(
{ messages: [{ role: "user", content: "讲一个笑话" }] },
{ streamMode: "values" }
);
// 逐块输出
for await (const chunk of stream) {
const lastMessage = chunk.messages[chunk.messages.length - 1];
if (lastMessage.role === "assistant") {
console.log(lastMessage.content); // 逐步打印
}
}前端应用场景:聊天界面实时显示回复。
3.6 工具返回不同类型 #
工具可以返回三种类型:
// 1. 返回字符串(最常见)
const search = tool(
({ query }) => `找到 3 条关于 "${query}" 的结果`,
{ name: "search", schema: z.object({ query: z.string() }) }
);
// 2. 返回对象(结构化数据)
const getWeatherData = tool(
({ city }) => ({
city,
temperature: 25,
humidity: 60,
wind: "东北风 3级"
}),
{ name: "get_weather_data", schema: z.object({ city: z.string() }) }
);
// 3. 返回 Command(更新 Agent 状态)
import { Command } from "@langchain/langgraph";
import { ToolMessage } from "@langchain/core/messages";
const setLanguage = tool(
async ({ language }, config) => {
return new Command({
update: {
preferredLanguage: language,
messages: [
new ToolMessage({
content: `语言已切换为 ${language}`,
tool_call_id: config.toolCallId
})
]
}
});
},
{
name: "set_language",
schema: z.object({ language: z.string() })
}
);四、实战场景 #
场景 1:智能客服助手 #
一个能查询订单、处理退款的客服 Agent。
import { createAgent, tool } from "langchain";
import * as z from "zod";
import { MemorySaver } from "@langchain/langgraph";
// 查询订单工具
const queryOrder = tool(
async ({ orderId }) => {
// 模拟数据库查询
const orders = {
"12345": { status: "已发货", items: ["iPhone 15", "AirPods"], total: 9999 },
"67890": { status: "待支付", items: ["MacBook Pro"], total: 19999 }
};
const order = orders[orderId as keyof typeof orders];
return order
? `订单 ${orderId}: ${order.status}, 商品: ${order.items.join(", ")}, 总价: ¥${order.total}`
: `未找到订单 ${orderId}`;
},
{
name: "query_order",
description: "查询订单状态和详情",
schema: z.object({
orderId: z.string().describe("订单号")
})
}
);
// 申请退款工具
const requestRefund = tool(
async ({ orderId, reason }) => {
// 模拟退款处理
return `退款申请已提交:订单 ${orderId}, 原因: ${reason}。预计 3-5 个工作日处理。`;
},
{
name: "request_refund",
description: "申请订单退款",
schema: z.object({
orderId: z.string().describe("订单号"),
reason: z.string().describe("退款原因")
})
}
);
// 创建客服 Agent
const customerServiceAgent = createAgent({
model: "gpt-4o-mini",
tools: [queryOrder, requestRefund],
systemPrompt: `你是电商平台的客服助手。
你的职责:
1. 查询用户订单状态
2. 处理退款申请
3. 解答常见问题
规则:
- 用户询问订单时,先查订单状态再回复
- 退款需要用户提供订单号和原因
- 保持礼貌、专业的语气`,
checkpointer: new MemorySaver() // 启用记忆
});
// 使用示例
const config = { configurable: { thread_id: "customer-001" } };
// 用户查订单
await customerServiceAgent.invoke(
{ messages: [{ role: "user", content: "帮我查一下订单 12345" }] },
config
);
// 用户申请退款(Agent 会记住订单号)
await customerServiceAgent.invoke(
{ messages: [{ role: "user", content: "我想退款,东西不喜欢" }] },
config
);场景 2:代码助手 #
一个能解释代码、生成代码、查文档的 Agent。
// 执行代码工具(模拟)
const runCode = tool(
async ({ code, language }) => {
// 实际项目中可以用沙箱执行
if (language === "javascript") {
try {
const result = eval(code);
return `执行结果: ${result}`;
} catch (e) {
return `错误: ${e.message}`;
}
}
return `暂不支持 ${language}`;
},
{
name: "run_code",
description: "执行代码并返回结果",
schema: z.object({
code: z.string().describe("要执行的代码"),
language: z.enum(["javascript", "python"]).describe("编程语言")
})
}
);
// 搜索文档工具(模拟)
const searchDocs = tool(
async ({ query }) => {
// 实际项目中调用搜索引擎
const docs = {
"react useState": "useState 是 React 的状态管理 Hook...",
"vue computed": "computed 是 Vue 的计算属性..."
};
return docs[query as keyof typeof docs] || `未找到 "${query}" 相关文档`;
},
{
name: "search_docs",
description: "搜索技术文档",
schema: z.object({
query: z.string().describe("搜索关键词")
})
}
);
const codeAgent = createAgent({
model: "gpt-4o-mini",
tools: [runCode, searchDocs],
systemPrompt: `你是一个代码助手。
职责:
1. 解释代码逻辑
2. 生成代码示例
3. 搜索技术文档
4. 执行简单代码
规则:
- 生成代码后,询问是否需要执行
- 解释要清晰、有注释
- 推荐最佳实践`
});
// 使用
await codeAgent.invoke({
messages: [{
role: "user",
content: "帮我写一个 React 计数器组件"
}]
});场景 3:数据分析师 Agent #
从数据库提取数据、生成分析报告。
// 定义输出格式:分析报告
const AnalysisReport = z.object({
summary: z.string().describe("数据摘要"),
trends: z.array(z.string()).describe("发现趋势"),
recommendations: z.array(z.string()).describe("建议"),
confidence: z.number().min(0).max(1).describe("置信度")
});
// 查询数据库工具
const queryDatabase = tool(
async ({ table, conditions }) => {
// 模拟数据库查询
return `查询 ${table} 表,条件: ${conditions.join(", ")}。返回 100 条记录。`;
},
{
name: "query_database",
description: "查询数据库",
schema: z.object({
table: z.string().describe("表名"),
conditions: z.array(z.string()).describe("查询条件")
})
}
);
// 生成图表工具
const generateChart = tool(
async ({ type, data, title }) => {
// 实际项目中生成真实图表
return `已生成 ${type} 图表:"${title}"。数据包含 ${data.length} 个点。`;
},
{
name: "generate_chart",
description: "生成数据图表",
schema: z.object({
type: z.enum(["bar", "line", "pie"]),
data: z.array(z.number()),
title: z.string()
})
}
);
const dataAnalystAgent = createAgent({
model: "gpt-4o-mini",
tools: [queryDatabase, generateChart],
responseFormat: AnalysisReport, // 强制输出结构化报告
systemPrompt: `你是数据分析助手。
工作流程:
1. 理解用户分析需求
2. 查询相关数据
3. 分析数据趋势
4. 生成可视化图表
5. 输出结构化报告
报告必须包含:摘要、趋势、建议、置信度。`
});
// 使用
const result = await dataAnalystAgent.invoke({
messages: [{
role: "user",
content: "分析最近一周的用户注册数据"
}]
});
console.log(result.structuredResponse);场景 4:多工具协作 Agent #
一个 Agent 同时使用多个工具完成复杂任务。
import { createAgent, tool } from "langchain";
import * as z from "zod";
// 天气查询
const getWeather = tool(
({ city }) => `${city}: 晴, 28°C`,
{ name: "get_weather", schema: z.object({ city: z.string() }) }
);
// 餐厅推荐
const searchRestaurants = tool(
({ city, cuisine }) => `${city} 有 5 家 ${cuisine} 餐厅推荐`,
{
name: "search_restaurants",
schema: z.object({
city: z.string(),
cuisine: z.string().optional()
})
}
);
// 电影查询
const getMovies = tool(
({ genre }) => `推荐 3 部 ${genre} 电影`,
{ name: "get_movies", schema: z.object({ genre: z.string() }) }
);
// 日程安排
const scheduleEvent = tool(
({ date, time, event }) => `已安排:${date} ${time} - ${event}`,
{
name: "schedule_event",
schema: z.object({
date: z.string(),
time: z.string(),
event: z.string()
})
}
);
// 万能助手
const superAgent = createAgent({
model: "gpt-4o-mini",
tools: [getWeather, searchRestaurants, getMovies, scheduleEvent],
systemPrompt: `你是万能助手,可以帮用户:
- 查天气
- 推荐餐厅
- 推荐电影
- 安排日程
根据用户需求,自动选择合适的工具组合。
例如用户说"周末安排",你可以:
1. 查周末天气
2. 推荐餐厅
3. 推荐电影
4. 生成日程安排`,
checkpointer: new MemorySaver()
});
// 使用:用户一句话,Agent 自动调用多个工具
const result = await superAgent.invoke({
messages: [{ role: "user", content: "帮我安排北京这周末的活动" }]
});场景 5:前端集成 —— React 聊天组件 #
把 LangChain Agent 接到前端 React 应用。
// backend.ts - 后端 API
import { createAgent, tool } from "langchain";
import { MemorySaver } from "@langchain/langgraph";
const chatAgent = createAgent({
model: "gpt-4o-mini",
tools: [],
checkpointer: new MemorySaver()
});
// Express API
app.post("/chat", async (req, res) => {
const { message, threadId } = req.body;
const stream = await chatAgent.stream(
{ messages: [{ role: "user", content: message }] },
{ configurable: { thread_id: threadId }, streamMode: "values" }
);
// 返回流式响应
res.setHeader("Content-Type", "text/event-stream");
for await (const chunk of stream) {
const msg = chunk.messages[chunk.messages.length - 1];
if (msg.role === "assistant") {
res.write(`data: ${JSON.stringify({ content: msg.content })}\n\n`);
}
}
res.end();
});// frontend.tsx - React 组件
import { useState } from "react";
function ChatComponent() {
const [messages, setMessages] = useState<Array<{role: string, content: string}>>([]);
const [input, setInput] = useState("");
const threadId = "user-" + Math.random().toString(36).slice(2);
async function sendMessage() {
setMessages(prev => [...prev, { role: "user", content: input }]);
setInput("");
// 流式接收
const response = await fetch("/chat", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ message: input, threadId })
});
const reader = response.body?.getReader();
const decoder = new TextDecoder();
let aiMessage = "";
while (reader) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
const lines = chunk.split("\n").filter(l => l.startsWith("data:"));
for (const line of lines) {
const data = JSON.parse(line.slice(5));
aiMessage += data.content;
setMessages(prev => {
const last = prev[prev.length - 1];
if (last?.role === "assistant") {
return [...prev.slice(0, -1), { role: "assistant", content: aiMessage }];
}
return [...prev, { role: "assistant", content: aiMessage }];
});
}
}
}
return (
<div className="chat">
{messages.map((msg, i) => (
<div key={i} className={`message ${msg.role}`}>
{msg.content}
</div>
))}
<input
value={input}
onChange={e => setInput(e.target.value)}
onKeyDown={e => e.key === "Enter" && sendMessage()}
/>
<button onClick={sendMessage}>发送</button>
</div>
);
}五、常见问题 #
Q1: Agent 调用工具时报错怎么办? #
import { ToolNode } from "@langchain/langgraph/prebuilt";
// 默认:错误会中断执行
const toolNode = new ToolNode(tools);
// 捕获错误,继续执行
const toolNode = new ToolNode(tools, {
handleToolErrors: true // 或传自定义消息
});
const toolNode = new ToolNode(tools, {
handleToolErrors: "工具执行失败,请稍后重试"
});Q2: 如何控制对话长度? #
长对话会超出模型上下文限制,需要裁剪。
import { createMiddleware } from "langchain";
import { RemoveMessage, REMOVE_ALL_MESSAGES } from "@langchain/langgraph";
const trimMessages = createMiddleware({
name: "TrimMessages",
beforeModel: (state) => {
const messages = state.messages;
if (messages.length <= 5) return;
// 保留第一条 + 最近 4 条
const firstMsg = messages[0];
const recent = messages.slice(-4);
const newMessages = [firstMsg, ...recent];
return {
messages: [
new RemoveMessage({ id: REMOVE_ALL_MESSAGES }),
...newMessages
]
};
}
});
const agent = createAgent({
model: "gpt-4o-mini",
middleware: [trimMessages],
checkpointer: new MemorySaver()
});Q3: 如何在 Node.js 和浏览器中使用? #
Node.js — 正常使用,设置环境变量。
process.env.OPENAI_API_KEY = "xxx";
const agent = createAgent({ model: "gpt-4o-mini", tools: [] });浏览器 — 需要处理 CORS 和 API Key 安全问题。
// 方案 1:通过后端代理
const response = await fetch("/api/chat", {
method: "POST",
body: JSON.stringify({ message })
});
// 方案 2:使用边缘函数(Vercel/Cloudflare)
// API Key 在边缘函数中,不暴露给前端不建议在前端直接调用 API —— Key 会暴露。
Q4: 如何调试 Agent 执行过程? #
使用 LangSmith 追踪工具。
# 设置环境变量
LANGSMITH_TRACING=true
LANGSMITH_API_KEY=xxx然后在 LangSmith 网站 查看:
- 模型调用日志
- 工具执行过程
- Token 使用统计
- 错误追踪
Q5: 为什么 Agent 不调用工具? #
常见原因:
- 工具描述不清晰 — AI 不知道什么时候用
- 模型不支持工具调用 — 换支持 tool calling 的模型
- 提示词冲突 — 提示词里说了"不要用工具"
解决:
// 改进工具描述
const search = tool(
({ query }) => `结果`,
{
name: "web_search",
description: "当用户询问实时信息、新闻、天气时使用此工具", // 明确触发条件
schema: z.object({ query: z.string() })
}
);
// 确认模型支持工具调用
// OpenAI: gpt-4o, gpt-4o-mini, gpt-4-turbo
// Anthropic: claude-3.5-sonnet, claude-3-opus
// Gemini: gemini-1.5-pro, gemini-2.0-flashQ6: 如何动态选择工具? #
根据用户权限、状态动态过滤工具。
import { createMiddleware } from "langchain";
const dynamicTools = createMiddleware({
name: "DynamicTools",
wrapModelCall: (request, handler) => {
const userRole = request.runtime?.context?.userRole;
let filteredTools = request.tools;
if (userRole === "guest") {
// 游客只能用查询工具
filteredTools = request.tools.filter(
t => t.name.startsWith("query_")
);
} else if (userRole === "admin") {
// 管理员可以用所有工具
}
return handler({ ...request, tools: filteredTools });
}
});
const agent = createAgent({
model: "gpt-4o-mini",
tools: [queryTool, deleteTool, updateTool],
middleware: [dynamicTools]
});Q7: 如何使用 Zod 定义复杂 Schema? #
import * as z from "zod";
// 基础类型
const BasicSchema = z.object({
name: z.string(),
age: z.number(),
email: z.string().email()
});
// 可选字段
const OptionalSchema = z.object({
title: z.string(),
subtitle: z.string().optional(),
tags: z.array(z.string()).optional()
});
// 嵌套对象
const NestedSchema = z.object({
user: z.object({
name: z.string(),
address: z.object({
city: z.string(),
zip: z.string()
})
}),
orders: z.array(z.object({
id: z.string(),
amount: z.number()
}))
});
// 带描述(AI 看得到)
const DescribedSchema = z.object({
query: z.string().describe("搜索关键词,最多 50 字"),
limit: z.number().min(1).max(100).describe("返回结果数量,1-100")
});
// 枚举
const EnumSchema = z.object({
status: z.enum(["pending", "completed", "cancelled"]),
priority: z.enum(["low", "medium", "high"])
});六、总结速记 #
核心概念速记表 #
| 概念 | 一句话 | 关键代码 |
|---|---|---|
| Model | AI 大脑 | initChatModel("gpt-4o-mini") |
| Tool | AI 的手 | tool(fn, { name, schema }) |
| Agent | AI + 工具 + 记忆 | createAgent({ model, tools }) |
| Memory | 对话历史 | checkpointer: new MemorySaver() |
| Structured Output | JSON 输出 | responseFormat: z.object({...}) |
| Streaming | 实时输出 | agent.stream({ messages }, { streamMode }) |
模型选择速记 #
| 任务 | 推荐 | 原因 |
|---|---|---|
| 工具调用 | gpt-4o-mini | 快、便宜、支持好 |
| 复杂推理 | claude-sonnet-4-6 | 推理能力强 |
| 大量请求 | gemini-2.0-flash | 最便宜 |
| 中文场景 | gpt-4o / claude | 中文理解好 |
常用代码模板 #
// 最小 Agent
const agent = createAgent({
model: "gpt-4o-mini",
tools: [myTool]
});
// 带 Memory
const agent = createAgent({
model: "gpt-4o-mini",
tools: [],
checkpointer: new MemorySaver()
});
// 带结构化输出
const agent = createAgent({
model: "gpt-4o-mini",
tools: [],
responseFormat: z.object({ result: z.string() })
});
// 带提示词
const agent = createAgent({
model: "gpt-4o-mini",
tools: [],
systemPrompt: "你是..."
});
// 调用
await agent.invoke({ messages: [{ role: "user", content: "..." }] });附录 #
命令速查表 #
| 命令 | 作用 |
|---|---|
npm install langchain @langchain/core |
安装核心包 |
npm install @langchain/openai |
安装 OpenAI 集成 |
npm install zod |
安装 schema 库 |
LANGSMITH_TRACING=true |
启用追踪 |
API 速查 #
| API | 作用 |
|---|---|
initChatModel(model, options) |
初始化模型 |
createAgent(config) |
创建 Agent |
tool(fn, config) |
定义工具 |
agent.invoke(input, config) |
调用 Agent |
agent.stream(input, config) |
流式调用 |
官方资源 #
| 资源 | 链接 |
|---|---|
| 官方文档 | https://js.langchain.com/docs |
| GitHub | https://github.com/langchain-ai/langchainjs |
| LangSmith | https://smith.langchain.com |
| 集成列表 | https://js.langchain.com/docs/integrations |
最后更新:2026-03-29
继续阅读
返回文章列表