本文较长,建议点赞收藏。更多AI大模型应用开发学习视频及资料,在智泊AI。

作为前端开发者,你是否也有这样的纠结:想入门 AI,却被一堆 Python 教程劝退?用过 ChatGPT、Stable Diffusion,却觉得只是 "用工具" 而非 "懂原理"?尝试过 RAG、Agent 这些概念,却不知道如何用 JavaScript 落地?
今天就从前端视角出发,用 LangGraph(JS 版)手把手实现一个 ReAct 智能体 ------ 这是 AI Agent 的基础模式,也是掌握复杂智能体的第一步。哪怕你只懂基础 JS,跟着步骤走也能做出来。
前端学 AI 应该学什么?
学 AI 最痛苦的是 "找不到方向":到底该从哪入手?学完怎么算 "真懂"?我刚开始接触 AI 时,走了不少弯路:先玩 Stable Diffusion 生成图片,再用各种大模型聊天,甚至用 AI 插件写代码。看似学了很多,却总觉得 "没抓住核心"------ 因为这些都是 "用工具",没搞懂背后的逻辑,换个场景就懵了。
直到接触 RAG(检索增强生成)、MCP(多智能体协作)、LangChain 这些技术,才慢慢明白:前端学 AI,核心要学 "如何开发 Agent(智能体)"。
Agent 是 AI 的 "应用形态"------ 比如能自动查资料写报告的 AI 助手、能帮你处理重复工作的智能工具,本质都是 Agent。而网上关于 Agent 的教程,90% 以上用 Python,前端开发者想入门难上加难。
所以接下来,我会用 JS 语言,基于 LangGraph 做一系列 AI 项目,从基础到进阶,帮前端同学真正 "落地 AI 开发",而不是停留在 "用工具" 的层面。
开发 Agent 一定要用 LangGraph 吗?
答案是:完全不用!
你可以用纯 JS 写逻辑(比如用循环实现 "思考 - 行动" 流程),也可以用 Coze、百度千帆这些云平台(拖拖拽拽搭 Agent),甚至能用纯提示词(比如给 ChatGPT 写指令,让它模拟智能体)。
那为什么推荐 LangGraph?有两个核心原因:
- 降低 "理解成本":它把 Agent 的核心能力(比如记忆管理、决策逻辑、工具调用)都封装成了 "可复用模块",不用你从零写复杂逻辑;
- 贴近前端思维:用 "节点""边" 定义工作流,像画流程图一样开发,前端同学对 "组件化、模块化" 的理解能直接复用;
- debug 友好 :搭配 LangStudio 能实时看流程运行,哪里错了一眼就懂,比自己写纯 JS 逻辑排错快 10 倍。
简单说:LangGraph 不是 "唯一选择",却是前端入门 Agent 的 "最优选择"------ 它帮你把精力放在 "理解 AI 逻辑" 上,而不是 "写重复代码"。
ReAct 智能体:前端最易上手的 Agent 模式
为什么先学 ReAct?
对前端开发者来说,ReAct 是最 "接地气" 的 Agent 模式 ------ 它的逻辑和 "人解决问题的思路" 几乎一样:
比如你想知道 "今天上海天气要不要带伞",会先 "思考"(要不要查实时天气?),再 "行动"(打开天气 APP),最后 "总结"(多云,不用带伞)。
ReAct 的核心就是 "推理(Reason)+ 行动(Act)" 的循环,源自论文《ReAct: Synergizing Reasoning and Acting in Language Models》。它没有复杂的数学公式,全是 "逻辑判断",用 JS 就能轻松实现。
更重要的是:所有复杂 Agent(比如能写报告、能处理业务的 AI),底层都是 ReAct 的延伸。学会它,后续学多智能体、长记忆智能体,都会像 "搭积木" 一样简单。
项目概述:技术栈与效果预览
用什么技术?
核心技术栈:LangGraph(JS 版)+ LangStudio(调试工具)+ LangSmith(日志追踪)
- LangGraph:负责构建智能体的 "思考 - 行动" 流程;
- LangStudio:可视化调试,实时看每一步运行状态;
- LangSmith:记录模型调用、工具执行的日志,方便排查问题。
这些工具都有免费额度,个人开发完全够用,不用担心收费问题。
最终效果是什么样?
你不用写复杂代码,启动项目后会自动打开 LangStudio,输入问题就能看到:
- 智能体先 "思考":"用户问上海天气,我需要调用搜索工具查实时数据";
- 再 "行动":自动调用 Tavily 搜索(类似百度),获取天气信息;
- 最后 "总结":把搜索结果整理成自然语言,输出 "今天上海多云转晴,气温 22-28℃,不用带伞"。
整个过程不用你手动干预,智能体自己完成 "思考 - 行动 - 输出",像个 "迷你 AI 助手"。
目录结构:3 分钟看懂文件分工
项目叫 "react-agent",文件不多,每个文件的职责都很明确,前端同学一看就懂:
arduino
react-agent/
├─ graph.ts // 核心!定义智能体的工作流(节点、边、循环逻辑)
├─ configuration.ts// 配置参数(用什么模型、系统提示词是什么)
├─ prompts.ts // 系统提示模板(告诉智能体"该怎么思考、怎么行动")
├─ tools.ts // 工具定义(比如搜索工具、计算器工具)
├─ utils.ts // 辅助函数(比如加载模型、处理错误)
└─ README.md // 启动步骤(复制命令就能跑,不用配置环境)
不用怕文件多,核心逻辑全在graph.ts
里,其他文件都是 "配置或辅助",改改参数就能用。
核心实现:从流程到代码,前端能看懂的细节
先记住一个核心逻辑:整个智能体就是 "循环做 3 件事"------ 思考→判断要不要用工具→用工具 / 输出答案。
下面拆成 "状态管理、工作流、节点函数" 三部分,每个部分都附 "前端能懂的解释" 和 "可复制的代码"。
- 状态管理:智能体的 "记忆本"
前端同学都懂 "组件状态"(比如 React 的 useState),智能体的 "状态" 其实就是它的 "记忆"------ 比如用户问了什么、之前思考了什么、工具返回了什么,都存在这里。
LangGraph 用MessagesAnnotation管理状态,简单说就是 "一个存消息的数组",类似前端的 "聊天记录数组"。
在graph.ts
里,状态的使用方式如下:
javascript
// graph.ts
import { MessagesAnnotation } from "@langchain/langgraph";
import { RunnableConfig } from "@langchain/core/runnables";
import { ensureConfiguration } from "./configuration";
import { loadChatModel } from "./utils";
import { TOOLS } from "./tools";
// callModel:智能体的"思考节点",输入状态,返回新的状态(新增思考结果)
async function callModel(
state: typeof MessagesAnnotation.State, // 当前状态(比如聊天记录)
config: RunnableConfig, // 配置参数(比如用什么模型)
): Promise<typeof MessagesAnnotation.Update> { // 返回更新后的状态
// 1. 获取配置(用什么模型、系统提示词)
const configuration = ensureConfiguration(config);
// 2. 加载模型,并告诉模型"能用哪些工具"
const model = (await loadChatModel(configuration.model)).bindTools(TOOLS);
// 3. 给模型发消息:系统提示 + 历史聊天记录
const response = await model.invoke([
{
role: "system",
content: configuration.systemPromptTemplate.replace(
"{system_time}",
new Date().toISOString(), // 注入当前时间,方便模型处理"时效性问题"
),
},
...state.messages, // 带上之前的聊天记录,避免智能体"失忆"
]);
// 4. 返回更新后的状态:把模型的思考结果加入"记忆本"
return { messages: [response] };
}
前端视角解读:
state
就像 React 组件的state
,存着所有 "历史数据";Update
就像setState
的参数,告诉 LangGraph "要更新哪些数据";- 整个函数的逻辑:拿历史记录→问模型→把模型回复存起来,和前端 "请求接口→更新 UI" 的逻辑几乎一样。
- 工作流构建:像画流程图一样写代码
智能体的 "思考 - 行动" 流程,用 LangGraph 的StateGraph
定义,就像用 Visio 画流程图,前端同学很容易理解。
核心代码在graph.ts
里:
typescript
// graph.ts
import { StateGraph } from "@langchain/langgraph";
import { ToolNode } from "@langchain/langgraph/prebuilt";
import { ConfigurationSchema } from "./configuration";
// 1. 定义"决策函数":思考后该做什么?(用工具还是输出答案?)
function routeModelOutput(state: typeof MessagesAnnotation.State): string {
// 取最新的模型回复
const lastMessage = state.messages[state.messages.length - 1];
// 如果模型说"要用工具"(返回了tool_calls),就去工具节点;否则结束
if ((lastMessage as any)?.tool_calls?.length > 0) {
return "tools"; // 去执行工具
} else {
return "__end__"; // 结束流程,输出答案
}
}
// 2. 构建工作流
const workflow = new StateGraph(MessagesAnnotation, ConfigurationSchema)
// 加"思考节点":调用模型分析问题
.addNode("callModel", callModel)
// 加"行动节点":执行工具(用LangGraph的ToolNode,不用自己写逻辑)
.addNode("tools", new ToolNode(TOOLS))
// 起点→先思考:用户提问后,第一步是让模型分析问题
.addEdge("__start__", "callModel")
// 思考后→决策:根据模型回复,决定去工具节点还是结束
.addConditionalEdges("callModel", routeModelOutput)
// 行动后→再思考:用工具获取数据后,回到模型继续分析
.addEdge("tools", "callModel");
// 3. 导出智能体,供外部调用
export const reactAgent = workflow.compile();
用流程图简化理解:

前端同学应该很熟悉这种逻辑:就像 "组件间跳转",用 "条件判断" 决定下一步去哪,完全不用写复杂的循环和分支。
- 工具调用:给智能体加 "外挂"
智能体自己不会 "查天气、算数学题",需要靠 "工具" 实现。就像前端项目需要 "调用接口" 获取数据,智能体需要 "调用工具" 扩展能力。
在tools.ts
里,我们定义一个 "搜索工具"(用 Tavily,类似百度搜索):
javascript
// tools.ts
import { TavilySearchResults } from "@langchain/community/tools/tavily_search";
import dotenv from "dotenv";
dotenv.config();
// 1. 初始化搜索工具,设置最多返回3条结果
const searchTavily = new TavilySearchResults({
maxResults: 3,
// 填入申请到的API key
apiKey: process.env.TAVILY_API_KEY,
});
// 2. 导出工具列表,供其他文件使用
export const TOOLS = [searchTavily];
前端视角解读:
- 工具就像 "封装好的 API 函数",智能体调用时,会自动传参数(比如搜索关键词),并返回结果;
- 后续想加 "计算器工具",只需新增一个工具类,加入
TOOLS
数组即可,不用改核心流程,符合 "开闭原则"。
- 配置与提示词:让智能体 "听话"
想让智能体按你的要求工作,需要两个关键配置:"用什么模型" 和 "系统提示词"。
在configuration.ts
里定义配置项:
typescript
// configuration.ts
import { Annotation } from "@langchain/langgraph";
import { SYSTEM_PROMPT_TEMPLATE } from "./prompts";
// 1. 定义配置 schema(类似前端的PropTypes)
export const ConfigurationSchema = Annotation.Root({
// 系统提示词模板(告诉智能体"该怎么思考、怎么行动")
systemPromptTemplate: Annotation.string({
default: SYSTEM_PROMPT_TEMPLATE,
}),
// 选用的大模型(默认用deepseek,免费且支持中文)
model: Annotation.string({
default: "deepseek/deepseek-chat",
}),
});
// 2. 工具函数:确保配置有默认值,避免报错
export function ensureConfiguration(
config: { configurable?: Record<string, any> } = {}
) {
const configurable = config.configurable ?? {};
return {
systemPromptTemplate: configurable.systemPromptTemplate ?? SYSTEM_PROMPT_TEMPLATE,
model: configurable.model ?? "deepseek/deepseek-chat",
};
}
在prompts.ts
里写系统提示词(核心是 "告诉智能体规则"):
javascript
// prompts.ts
// 系统提示词:明确智能体的"角色、规则、思考方式"
export const SYSTEM_PROMPT_TEMPLATE = `
你是一个前端开发者助手,擅长用ReAct模式解决问题。请按以下规则工作:
1. 先思考:用户的问题需要调用工具吗?如果需要,用什么工具?
2. 再行动:如果需要工具,必须调用TOOLS里的工具,不要自己编答案;
3. 后总结:工具返回结果后,整理成自然语言回答,不要遗漏关键信息;
4. 注意:如果问题不需要工具(比如"1+1等于几"),直接回答,不用调用工具。
当前系统时间:{system_time}
`;
前端视角解读:
- 系统提示词就像 "组件的说明书",告诉智能体 "该做什么、不该做什么";
- 配置项用
Annotation
定义,类似前端用TypeScript
做类型校验,避免传错参数。
完整运行流程:一步一步看智能体工作
以 "用户问:今天上海天气怎么样?" 为例,整个流程如下:
用户输入问题:调用reactAgent.invoke({ messages: [{ role: "user", content: "今天上海天气怎么样?" }] })
;
第一步:思考(callModel):
- 模型收到问题,结合系统提示词,判断 "需要调用搜索工具查实时天气";
- 返回
tool_calls: [{ name: "tavily_search_results", parameters: { query: "2024年上海今日天气" } }]
;
第二步:决策(routeModelOutput):
检测到tool_calls
,决定跳转到 "tools" 节点;
第三步:行动(tools):
调用 Tavily 搜索,获取结果:"上海今日多云转晴,气温 22-28℃,风力 3 级";
第四步:再思考(callModel):
模型分析搜索结果,判断 "不需要再调用工具,可直接整理答案";
第五步:结束(end):
模型返回自然语言回答:"今天上海多云转晴,气温 22-28℃,适合外出,不用带伞~";
输出结果:前端拿到回答,展示给用户。
整个过程不用你手动干预,智能体自己完成 "思考 - 行动 - 总结",和人解决问题的逻辑完全一致。
如何启动项目?3 步搞定(附命令)
第一步:准备环境
- 安装 Node.js(18 + 版本,前端同学应该都有);
- 克隆项目(或下载压缩包):
git clone [你的仓库地址]
(如果没有仓库,可直接新建文件夹,复制上面的代码); - 安装依赖:
npm install @langchain/langgraph @langchain/core @langchain/community dotenv
。
第二步:配置 API key(可选)
- 去 Tavily 官网免费申请 API key(tavily.com/);
- 新建
.env
文件,写入:TAVILY_API_KEY=你的API key
; - 在
tools.ts
里引入 dotenv:import dotenv from "dotenv"; dotenv.config();
,并给TavilySearchResults
加apiKey: process.env.TAVILY_API_KEY
。
第三步:启动项目并调试
- 新建启动文件:在项目根目录新建
index.ts
,写入调用智能体的代码(复制即可用):
javascript
// index.ts
import { reactAgent } from "./graph";
import readline from "readline";
// 初始化命令行交互,方便输入问题
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
prompt: "请输入你的问题(比如"今天上海天气怎么样?"):\n"
});
// 启动LangStudio调试(会自动打开浏览器)
async function startAgent() {
rl.prompt();
for await (const line of rl) {
if (line.trim() === "exit") {
console.log("退出智能体~");
rl.close();
break;
}
// 调用智能体,传入用户问题
const result = await reactAgent.invoke(
{
messages: [
{
role: "user",
content: line.trim()
}
]
},
{
// 启用LangStudio调试,会自动打开http://localhost:3000
streamMode: "debug"
}
);
// 输出智能体的回答
console.log("\n智能体回答:");
console.log(result.messages[result.messages.length - 1].content + "\n");
rl.prompt();
}
}
// 启动项目
startAgent().catch(err => {
console.error("启动失败:", err.message);
});
配置运行脚本:打开package.json
,在scripts
里加启动命令:
json
"scripts": {
"start": "ts-node index.ts"
}
(如果没装ts-node
,先执行npm install ts-node typescript -D
,并新建tsconfig.json
,用默认配置即可)
启动并调试:
要是遇到报错(比如 "模型连接失败"),先看 LangStudio 的 "Logs" 面板,里面会显示具体错误原因(比如 API key 无效、网络问题),按提示修改即可。
- 执行命令:
npm start
; - 此时会自动打开浏览器,进入 LangStudio 调试页面(默认http://localhost:3000);
- 在命令行输入问题(比如 "今天上海天气怎么样?"),就能在 LangStudio 里实时看到:
- 智能体先进入
callModel
节点,输出 "需要调用搜索工具"; - 接着跳转到
tools
节点,显示搜索过程和结果; - 最后回到
callModel
节点,整理结果并输出回答。
如何扩展?3 个前端能落地的方向
学会基础 ReAct 智能体后,你可以轻松扩展功能,把它变成 "实用工具",比如:
- 加 "计算器工具":解决数学问题
在tools.ts
里新增计算器工具,让智能体能算加减乘除:
typescript
// tools.ts 新增代码
import { Tool } from "@langchain/core/tools";
// 定义计算器工具
class CalculatorTool extends Tool {
name = "calculator"; // 工具名称,模型会用这个名称调用
description = "用来计算数学问题,比如加减乘除、平方、开方等,输入格式为数学表达式(如"2+3*4")";
// 工具执行逻辑
async _call(input: string): Promise<string> {
try {
// 用eval计算(实际项目可换更安全的计算库,如math.js)
const result = eval(input);
return `计算结果:${input} = ${result}`;
} catch (err) {
return `计算失败:${(err as Error).message},请输入正确的数学表达式(如"2+3*4")`;
}
}
}
// 把计算器工具加入工具列表
export const TOOLS = [searchTavily, new CalculatorTool()];
启动后输入 "3.14 乘以 5 的平方是多少",智能体会自动调用计算器工具,返回正确结果。
- 对接前端项目:做个 "AI 助手组件"
把智能体集成到 React/Vue 项目里,做一个可嵌入的 AI 助手组件:
- 用 Node.js 写个后端接口(比如用 Express),封装智能体调用逻辑;
- 前端用 React 写个聊天组件,用户输入问题后调用后端接口;
- 把结果实时展示在页面上,像 ChatGPT 一样交互。
这样你就能拥有一个 "自己开发的 AI 助手",嵌入到个人项目或作品集里,比单纯写 Demo 更有亮点。
- 加 "长期记忆":让智能体记住历史对话
目前的智能体 "聊完就忘",你可以用 LangGraph 的Memory
模块,让它记住历史对话:
- 在
graph.ts
里引入MemorySaver
; - 构建工作流时加入记忆配置:
javascript
import { MemorySaver } from "@langchain/langgraph";
// 编译智能体时加入记忆
export const reactAgent = workflow.compile({
checkpointer: new MemorySaver()
});
调用时传入configurable: { sessionId: "用户唯一ID" }
,智能体就会按用户 ID 保存历史对话。
后续就能实现 "连续对话",比如先问 "上海天气怎么样",再问 "那明天适合穿什么衣服",智能体能结合前一个问题的答案回答。
常见问题:踩过的坑帮你避开
- 启动后 LangStudio 打不开?
- 先检查命令行是否有 "端口被占用" 的提示,若有,执行
lsof -i:3000
(Mac)或netstat -ano | findstr "3000"
(Windows),找到占用端口的进程并关闭; - 若还是打不开,直接访问http://localhost:3000,手动输入
sessionId
(随便填,比如 "test123"),再点击 "Load" 即可。
- 模型调用失败?
- 若用默认的
deepseek/deepseek-chat
,先检查网络(需能访问外网,或用国内模型如 "通义千问"); - 换国内模型:在
configuration.ts
里把model
改成 "qwen-max"(通义千问),并安装对应的依赖npm install @langchain/aliyun
; - 若提示 "API key 无效",检查
.env
文件里的 key 是否正确,或重新申请一个。
- 工具调用没反应?
- 先看 LangStudio 的 "Tools" 面板,是否显示 "Tool Called";
- 若没显示,检查
routeModelOutput
函数,确保tool_calls
的判断逻辑正确(比如是否漏了as any
类型断言); - 若显示 "Tool Failed",检查工具的 API key 是否有效(比如 Tavily key 是否过期)。
动手试试,你已经超过 80% 的前端!
很多前端同学对 AI 望而却步,其实不是技术难,而是没找到 "适合前端的入门路径"。
你现在已经掌握了:
- ReAct 智能体的核心逻辑(思考 - 行动 - 循环);
- LangGraph 的基础用法(节点、边、工作流);
- 工具调用、模型配置、调试排错的实用技巧。
这些能力已经能帮你落地很多小项目:比如自动查资料的脚本、个人 AI 助手、嵌入项目的交互组件。
接下来,你可以:
- 先按步骤跑通项目,感受智能体的工作流程;
- 试着加一个自己想要的工具(比如 "翻译工具""天气查询工具");
- 把它集成到你的前端项目里,做一个可视化的交互界面。
下一篇,我们会深入 "多智能体协作"------ 让多个智能体分工合作(比如一个负责搜索,一个负责写报告,一个负责校对),实现更复杂的任务。关注不迷路,前端学 AI,咱们一步一个脚印来~
互动时间
你已经用 JS 实现了 ReAct 智能体,接下来最想给它加什么功能?是 "计算器""长期记忆",还是集成到前端项目里?
评论区聊聊你的想法,抽 1 位同学送【LangGraph 官方中文文档 + 前端 AI 开发手册】(整理了我踩坑的所有笔记)~
"需要完整代码 + 启动视频教程的同学,评论区扣 1,我私发给你~"
学习资源推荐
如果你想更深入地学习大模型,以下是一些非常有价值的学习资源,这些资源将帮助你从不同角度学习大模型,提升你的实践能力。
本文较长,建议点赞收藏。更多AI大模型应用开发学习视频及资料,在智泊AI。