30 行代码 langChain.js 开发你的第一个 Agent

大家好,我是双越老师,也是 wangEditor 作者。

我正开发一个 Node 全栈 AIGC 知识库 划水AI,包括 AI 写作、多人协同编辑。复杂业务,真实上线,大家可以去注册试用,围观项目研发过程。

文章同时被发布到【划水AI】欢迎点赞 www.huashuiai.com/pub/langcha...

开始

LangChain 是一个开发 LLM 应用的框架,是目前 LLM 开发最流行的解决方案之一。最早是 Python 开发的,后来也出来 JS 语言的,现在已经更新到 v0.3 版本。

本文将使用 LangChain 开发一个简单的 AI Agent,可使用自然语言来查询天气。再使用 LangGraph 进行自定义流程。

开发第一个 Agent

首先创建一个 nodejs 项目,并安装 langchain 和 dotenv ,后面我们需要使用环境变量。

css 复制代码
npm i langchain dotenv

使用 Tavily 搜索功能

Tavily 是一个搜索引擎,可以让你的 LLM 和 Agent 有联网搜索的能力,例如搜索天气。

你需要注册登录并创建一个 API key ,Tavily 可免费使用 1000 次,足够学习使用。

把 API key 放在代码库 .env 文件中

env 复制代码
TAVILY_API_KEY=xxx

安装 langchain tavily 插件

css 复制代码
npm i @langchain/tavily

然后创建一个 agent.js 文件,代码如下

js 复制代码
import 'dotenv/config'
import { TavilySearch } from '@langchain/tavily'

// 定义 tools
const agentTools = [
    new TavilySearch({
        maxResults: 3 // 最多查询 3 个结果
    })
]

选择一个大模型

langChain 集成了有很多 LLM 可供选择 js.langchain.com/docs/integr...

它默认推荐的是 OpenAI 但是在国内我们没法直接调用它的 API ,所以我当前选择的是 DeepSeek 。

注册登录 DeepSeek 创建一个 API key 并把它放在 .env 文件中

env 复制代码
DEEPSEEK_API_KEY=xxx

安装 langChain deepseek 插件

css 复制代码
npm i @langchain/deepseek

然后继续写 agent.js 代码

javascript 复制代码
import { ChatDeepSeek } from '@langchain/deepseek'


// 定义 llm
const agentModel = new ChatDeepSeek({ model: 'deepseek-chat', temperature: 0 })

使用 langGraph 创建 Agent

langGraph 是基于 langChain 的框架,用于构建可控制的 Agent ,是现代开发 Agent 最流行的解决方案之一。

安装 langGraph 必要插件

bash 复制代码
npm install @langchain/langgraph @langchain/core

然后继续写 agent.js 代码

js 复制代码
import { MemorySaver } from '@langchain/langgraph'
import { createReactAgent } from '@langchain/langgraph/prebuilt'

// Initialize memory to persist state between graph runs
const agentCheckpoint = new MemorySaver()

// Create agent
const agent = createReactAgent({
  llm: agentModel, // 使用之前创建的 llm
  tools: agentTools, // 使用之前创建的 tools
  checkpointSaver: agentCheckpoint, // 记忆,保存状态数据
})

使用 createReactAgent 来创建一个 Re-Act Agent 智能体。Re-Act 即 Reason + Act 推理和执行,它可以使用 llm 自主推理并选择调用哪个 tool 获取结果。这也是 Agent 的特点之一。

agentCheckpoint 可以存储近期对话记录,让 llm 有记忆能力。否则你刚说自己叫张三,再问它我的名字,它就忘了。

调用 Agent

继续写 agent.js 代码,使用 agent.invoke 方法调用 agent ,传入 HumanMessage 即 prompt 提示词

js 复制代码
import { HumanMessage } from '@langchain/core/messages'

// test1
const agentFinalState = await agent.invoke(
  { messages: [new HumanMessage('what is the current weather in sf')] },
  { configurable: { thread_id: '1' } }
)
console.log(
  agentFinalState.messages[agentFinalState.messages.length - 1].content
)

// test2
const agentNextState = await agent.invoke(
  { messages: [new HumanMessage('what about Beijing')] },
  { configurable: { thread_id: '1' } }
)
console.log(agentNextState.messages[agentNextState.messages.length - 1].content)

执行 node agent.js 可以看到控制台打印结果,可以查询到 San Francisco 和 Beijing 的天气。

这里的 { thread_id: '1' } 是 Memory 存储记忆的索引, thread_id 相同的才是同一个对话记录,才能共享记忆。例如这里第二次调用时 prompt 是 'what about Beijing' 并没有问天气,但是 llm 也能根据上一次对话判断出这里是问天气,所以才能给出正确答案。

还可以使用 agent.stream 方式流式输出,配合前端可实现打字效果

javascript 复制代码
// streaming
const stream = await agent.stream(
  { messages: [new HumanMessage('what is the current weather in sf')] },
  { configurable: { thread_id: '1' }, streamMode: 'updates' }
)
for await (const step of stream) {
  console.log(JSON.stringify(step))
}

以上就是一个最基本的 AI ReAct Agent,核心代码不到 30 行。它包含三个要素:llm + tools + memory ,可以根据自然语言自主推理并调用 tool 获取结果,最后组合为自然语言,返回给用户。

自定义 Agent 行为

ReAct Agent 可以自主推理并执行,但如果你想自己控制这个流程呢? LangGraph 可以让你自定义 Agent 行为。

定义 toolNode

继续修改你的 agent.js代码。定义一个 toolNode ,并且在创建 model 时绑定 tools 。

js 复制代码
import { ToolNode } from '@langchain/langgraph/prebuilt'

// Define the tools for the agent to use
const tools = [new TavilySearch({ maxResults: 3 })]
const toolNode = new ToolNode(tools)

// Create a model and give it access to the tools
const model = new ChatDeepSeek({
  model: 'deepseek-chat',
  temperature: 0,
}).bindTools(tools)

定义节点函数

然后定义一个函数 shouldContinue 用于判断 llm 是否要发起一个 tool 调用?

js 复制代码
// Define the function that determines whether to continue or not
function shouldContinue({ messages }) {
  const lastMessage = messages[messages.length - 1]

  // If the LLM makes a tool call, then we route to the "tools" node
  if (lastMessage.tool_calls?.length) {
    return 'tools'
  }
  // Otherwise, we stop (reply to the user) using the special "__end__" node
  return '__end__'
}

再定义一个函数 callModel 用于调用 llm 并返回结果

js 复制代码
// Define the function that calls the model
async function callModel(state) {
  const response = await model.invoke(state.messages)

  // We return a list, because this will get added to the existing list
  return { messages: [response] }
}

定义工作流

最后定义工作流 workflow ,并编译为一个 app 。这个 app 可以被触发执行。

js 复制代码
// Define a new graph
const workflow = new StateGraph(MessagesAnnotation)
  .addNode('agent', callModel) // 添加节点 agent ,对应 callModel 函数
  .addEdge('__start__', 'agent') // 添加"边",流程开始就指向 agent 节点
  .addNode('tools', toolNode) // 添加节点 tools ,对应 toolNode
  .addEdge('tools', 'agent') // 添加边,tools 节点指向 agent 节点
  .addConditionalEdges('agent', shouldContinue) // 添加条件边,根据 shouldContinue 函数里的逻辑,有 tool_calls 返回 'tools' 即指向 tools 节点,否则返回 '__end__' 即流程结束

// Finally, we compile it into a LangChain Runnable.
const app = workflow.compile()

工作流的定义过程看以上代码的注释,整体的流程图如下:开始,先执行 agent,再执行 shouldContinue 判断,然后要么结束、要么去执行 tools ,tools 再到 agent 。

arduino 复制代码
/* workflow diagram
           ┌──────────┐
           │ __start__│
               ↓
          ┌──────────┐
          │  agent   │ ←────────┐
          └────┬─────┘          │
               ↓                │
        ┌───────────  ─┐        │
        │shouldContinue│── tools│
        └────┬───────  ┘        │
             ↓                  ↓
         __end__        ┌──────────┐
                        │  tools   │
                        └──────────┘

*/

调用工作流

同样可以使用 invoke 方法触发工作流,传入 HumanMessage 即用户 prompt 信息

js 复制代码
const finalState = await app.invoke({
  messages: [new HumanMessage('what is the weather in sf')],
})
console.log(finalState.messages[finalState.messages.length - 1].content)

const nextState = await app.invoke({
  // Including the messages from the previous run gives the LLM context.
  // This way it knows we're asking about the weather in NY
  messages: [...finalState.messages, new HumanMessage('what about ny')],
})
console.log(nextState.messages[nextState.messages.length - 1].content)

控制台执行 node agent.js 返回结果如下

最后

使用 ReAct Agent 会更加灵活,使用 StateGraph 可以自定义控制 Agent 行为,langChain 提供了强大的 LLM 开发能力。

最后,前端想学全栈 + AI 开发,可以看看我做的 划水AI 项目,AI 写作、多人协同编辑。复杂业务,真实上线,可注册试用。

相关推荐
sell-cloud25 分钟前
Prompt Engineering要凉了?Fable 5.5能“猜“意图,但银行正在封杀AI Agent——企业AI的真正护城河是什么
人工智能·prompt
Navicat中国2 小时前
Navicat 18 内置 AI 助手让数据库开发从繁琐操作迈向智能协作
大数据·人工智能·数据库开发
4SAPI2 小时前
多模型请求路由怎么设计?成本、速度和能力如何平衡
人工智能·python·gateway·php
魔乐社区2 小时前
翼芯・智算测试与适配优化专区,让国产算力“选得准、跑得通、用得好“
人工智能·开源·大模型
XCDoris4 小时前
郴州logo设计机构
大数据·人工智能·python
Goboy5 小时前
一个人带三个Agent,我用全新TRAE从0到1搭了个资讯周刊站
人工智能·trae
俊哥V5 小时前
每日 AI 研究简报 · 2026-10-19
人工智能·ai
AI_AGENT_DEV_AI5 小时前
AI英语教培智能体的开发
人工智能
物联网软硬件开发-轨物科技5 小时前
【技术白皮书】光伏清检一体化机器人系统解决方案技术白皮书
大数据·运维·网络·人工智能·机器人