大模型应用正在从"对话式AI"向"行动式AI"演进。如果说ChatGPT代表了生成式AI的第一阶段 ------理解并生成内容,那么基于Agent的自主系统则标志着第二阶段 ------理解、决策并执行行动。
LangChain.js 作为当前最成熟的 TypeScript Agent 开发框架,已经成为构建生产级AI应用的事实标准。但官方文档偏重概念,社区教程零散浅显,从入门到落地之间存在着巨大的工程鸿沟。
本系列将围绕以下问题展开学习讨论
| 模块 | 核心内容 | 产出目标 |
|---|---|---|
| 架构篇 | Agent 核心抽象、Runnable 协议、工具链设计 | 能独立设计复杂 Agent 架构 |
| 工具篇 | 自定义 Tool 开发、Zod Schema 验证、错误处理 | 封装企业级可复用工具库 |
| 记忆篇 | BufferMemory、VectorStore 检索、对话状态机 | 实现长程上下文保持的 Agent |
| 编排篇 | LCEL 链式表达、并行执行、条件路由、Fallback 机制 | 构建高可靠的多 Agent 系统 |
| 实战篇 | ReAct、Plan-and-Execute、Multi-Agent 协作 | 完整项目:自动化数据分析 Agent |
你需要什么基础?
- TypeScript/JavaScript(泛型、异步、装饰器)
- LLM 基础概念(Prompt、Token、上下文窗口)
- 可选但加分:有 Express/nest 等后端开发经验
不需要你读过 LangChain 文档,我们只需要学习最常用的工具appi,以实战演练为目标,用到什么学什么
技术选型说明
选择 LangChain.js 而非 Python 版本,基于三个现实考量:
- 工程化成熟度:TypeScript 的类型系统对大型 Agent 系统的可维护性至关重要
- 生态位差异:Python 版在数据科学场景占优,JS/TS 版在企业服务集成、Web 部署场景更成熟
- 运行时优势:Edge Computing、Serverless 部署的天然适配
最重要的是,作为前端使用js/ts可以无缝衔接,不需要学习过多新知识,技术债最小化,上手即生产
学前准备
薅国内的大模型羊毛很方便,用来学习agent再合适不过了
阿里、腾讯、字节都有大模型接口的免费额度,我们先以字节为例
字节旗下的豆包模型有50万Token的免费额度,足够我们学习测试了
登录火山引擎,去模型广场选择一个模型
console.volcengine.com/ark/region:...

点击API接入

你会得到一个api key,我们在使用代码调用模型时需要使用到

ark.cn-beijing.volces.com/api/v3
在API KEY管理处可以查看自己的key密钥

langChain.js基础
为了方便演示和快速上手学习,我直接使用js
创建一个 test文件夹用来初始化项目
js
mkdir test
cd test
npm init -y
并且修改package.json文件,因为需要使用ES Modules 语法使用import进行导出使用方法,所以要添加
js
"type": "module",

豆包模型以及国内的模型大都兼容OpenAI API,所以我们使用@langchain/openai
js
npm install @langchain/openai
创建 src/index.js文件,写入以下代码
js
import { ChatOpenAI } from '@langchain/openai';
const model = new ChatOpenAI({
modelName: "模型名字",
apiKey: '你的密钥 API Key',
configuration: {
baseURL: 'https://ark.cn-beijing.volces.com/api/v3',
},
});
const response = await model.invoke("你是谁?");
console.log(response.content);
这就完成了一个最小可调用的大模型案例,替换掉你申请的模型密钥和模型名字以及豆包的baseURL
在控制台执行
js
node ./src/index.js
控制台就会生成回答

密钥放到代码里传到github上不安全,所以我们引入dotenv,将这些重要变量放到 .env里
js
npm install dotenv --save
创建.env文件,并在代码里引入
js
import { ChatOpenAI } from '@langchain/openai';
import 'dotenv/config'
const model = new ChatOpenAI({
modelName: process.env.MODEL_NAME,
apiKey: process.env.API_KEY,
configuration: {
baseURL: process.env.BASE_URL,
},
});
const response = await model.invoke("你是谁?");
console.log(response.content);


ChatOpenAI 创建模型对象
ChatOpenAI 是 OpenAI 提供的聊天完成 API 的封装,主要用于与 GPT 模型进行对话交互,配置好模型的基本参数后就可以调用实例进行对话
js
// 基础配置
const model = new ChatOpenAI({
// 必需参数
apiKey: "API Key",
// 模型配置
modelName: "模型名字",
// 自定义配置(如使用代理)
configuration: {
baseURL: "模型基础地址",
timeout: 60000, // 请求超时时间(毫秒)
maxRetries: 2, // 最大重试次数
},
// 请求控制参数
temperature: 0.7, // 平衡的创造性
maxTokens: 1000, // 限制输出长度
topP: 0.9, // 核采样
frequencyPenalty: 0.3, // 减少重复词汇
presencePenalty: 0.3, // 鼓励新话题
// 高级配置
streaming: false, // 非流式输出
});
invoke 与大模型对话
invoke 是 LangChain 中执行模型并获取响应的方法,可以传入单个消息或消息列表
他会将输入字符串 "你是谁?" 转换为 LangChain 的消息格式,并且会返回一个 AIMessage 对象,包含以下属性
js
{
content: "我是 AI 助手...", // 模型的回复内容
additional_kwargs: {}, // 额外信息(如 token 使用量)
response_metadata: {}, // 响应元数据
tool_calls: [], // 工具调用信息(如果有)
usage_metadata: {} // 使用统计信息
}
使用invoke返回的消息是等大模型将全部的信息都生成后才返回。
大多数模型可以在生成时流式传输其输出内容。通过逐步显示输出,流式传输可以显著改善用户体验,特别是对于较长的响应。此时可以使用 stream方法
stream 输出流
js
const response = await model.stream("你是谁?");
for await (const chunk of response) {
if (chunk.text) {
console.log(chunk.text)
}
}

stream()在模型响应后返回单个 AIMessage ,它返回多个 AIMessageChunk 对象,每个对象包含输出文本的一部分。
js
AIMessageChunk {
"id": "021770099910687b6043c5851c0a2627b25b78c406cf3041f4436",
"content": "呀",
"additional_kwargs": {},
"response_metadata": {
"prompt": 0,
"completion": 0,
"model_provider": "openai",
"usage": {}
},
"tool_calls": [],
"tool_call_chunks": [],
"invalid_tool_calls": []
}
Messages 消息类型
在使用 model.stream("你是谁?");和 model.invoke("你是谁?")直接传入文本字符串时,langChain会自动转为 HumanMessage信息格式
js
"你是谁?" → HumanMessage({ content: "你是谁?" })
在只传入简单的文本字符串时,只适用于不需要保留对话历史的简单的生成任务
langChain有四种消息格式:SystemMessage、HumanMessage、AIMessage、ToolMessage
- SystemMessage:系统消息 - 告知模型如何行为并提供交互上下文。简单来说就是给AI设置一个角色,能干什么,有什么能力
- HumanMessage:人类消息 - 代表用户输入和与模型的交互。用户输入的信息
- AIMessage:AI 消息 - 模型生成的响应,包括文本内容、工具调用和元数据
- ToolMessage:工具消息 - 表示工具调用的输出
首先安装@langchain/core
js
npm install @langchain/core
js
import { ChatOpenAI } from '@langchain/openai';
import 'dotenv/config'
import { HumanMessage, SystemMessage } from "@langchain/core/messages";
const model = new ChatOpenAI({
modelName: process.env.MODEL_NAME,
apiKey: process.env.API_KEY,
configuration: {
baseURL: process.env.BASE_URL,
},
});
let messages = [
new SystemMessage({
content: "你是一个专业的程序员",
}),
new HumanMessage({
content: "你是谁?",
}),
]
const response = await model.invoke(messages);
console.log(response.content);

js
new HumanMessage({
content: "你是谁?",
}),
只是一个最基础的信息输入,我们还可以传入更多更详细的信息,还可以传入图片,视频音频作为数据
这是一个图片地址:c-ssl.duitang.com/uploads/blo...

我们把这个图片地址传给大模型,让他描述这个图片
js
let messages = [
new HumanMessage({
content: [
{ type: "text", text: "描述下这张图片的内容" },
{
type: "image",
source_type: "url",
url: "https://c-ssl.duitang.com/uploads/blog/202212/04/20221204173347_946b0.jpg"
},
],
}),
]
const response = await model.invoke(messages);
console.log(response.content);


实战演练
根据上面学习的langChain基础,开发一个可交互的命令行助手
js
import { ChatOpenAI } from '@langchain/openai';
import 'dotenv/config'
import { HumanMessage, SystemMessage } from "@langchain/core/messages";
import readline from 'node:readline';
const model = new ChatOpenAI({
modelName: process.env.MODEL_NAME,
apiKey: process.env.API_KEY,
configuration: {
baseURL: process.env.BASE_URL,
},
});
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
const messages = [
new SystemMessage('你是一个有用的助手,可以帮助用户解答问题。')
];
async function chat() {
console.log('\n=== AI 助手 ===');
console.log('输入您的问题(输入 "exit" 退出):\n');
while (true) {
const userInput = await new Promise((resolve) => {
rl.question('用户: ', resolve);
});
if (userInput.toLowerCase() === 'exit' || userInput.toLowerCase() === 'quit') {
console.log('\n再见!');
rl.close();
break;
}
if (userInput.trim() === '') {
continue;
}
messages.push(new HumanMessage(userInput));
try {
console.log('助手: ');
let fullResponse = '';
const stream = await model.stream(messages);
for await (const chunk of stream) {
const content = chunk.content || '';
if (content) {
process.stdout.write(content);
fullResponse += content;
}
}
console.log('\n');
messages.push({ content: fullResponse, role: 'assistant' });
} catch (error) {
console.error(`\n错误: ${error.message}\n`);
}
}
}
chat().catch(console.error);
readline 是 Node.js 的 内置模块 ,用于从可读流(如标准输入)逐行读取数据。
- process.stdin : 可以从键盘读取用户输入
- process.stdout: 向终端显示提示符和输出


我们已经能让 AI "说话"了,但真正的 Agent 需要使用工具。