当前位置: 首页 > news >正文

深入浅出 LangGraph —— 第2章:环境搭建与第一个Agent

📖 本章学习目标

  • ✅ 掌握 LangGraph TypeScript 开发环境的完整搭建流程
  • ✅ 理解项目依赖结构与版本管理策略
  • ✅ 学会安全管理 API 密钥与环境变量
  • ✅ 构建并运行第一个可对话的 AI Agent
  • ✅ 理解 StateGraph 的基本工作模式
  • ✅ 能够独立排查常见环境配置问题

一、开发环境准备

1、环境要求

在开始之前,确保你的机器满足以下要求:

工具最低版本推荐版本说明
Node.js20.x22.x LTS支持 ES Modules
npm / pnpmnpm 9+pnpm 8+pnpm 更快更省空间
TypeScript5.0+5.4+严格模式支持
VS Code任意最新版推荐 IDE

💡小贴士:推荐使用 nvm(macOS/Linux)或 nvm-windows 管理 Node.js 版本,便于多项目切换。Windows下更推荐使用fnm。

2、检查现有环境

打开终端,运行以下命令验证环境:

node--version# 期望: v20.x.xnpm--version# 期望: 10.x.xnpx tsc--version# 期望: Version 5.x.x

如果 Node.js 版本低于 18,请先升级。

⚠️注意:如果你看到类似SyntaxError: Cannot use import statement的错误,通常是因为 Node.js 版本过低或不支持 ES Modules。


二、创建项目

1、初始化项目结构

# 创建项目目录mkdirmy-langgraph-agentcdmy-langgraph-agent# 初始化 npm 项目npminit-y# 安装 TypeScript 和开发工具npminstall-Dtypescript ts-node @types/node dotenv

代码解读:

  • npm init -y:快速创建 package.json,跳过所有交互问询
  • typescript:TypeScript 编译器核心
  • ts-node:直接运行 .ts 文件,无需手动编译
  • @types/node:Node.js 的类型定义文件
  • dotenv:从 .env 文件加载环境变量

生成 TypeScript 配置:

npx tsc--init

2、配置 tsconfig.json

用以下内容完整替换自动生成的tsconfig.json:

{"compilerOptions":{"target":"ES2022","module":"CommonJS","lib":["ES2022"],"outDir":"./dist","rootDir":"./src","strict":true,"esModuleInterop":true,"skipLibCheck":true,"resolveJsonModule":true,"forceConsistentCasingInFileNames":true},"include":["src/**/*"],"exclude":["node_modules","dist"]}

代码解读:

  • target: ES2022:使用现代 JS 特性(async/await、可选链等)
  • module: CommonJS:Node.js 默认模块系统
  • strict: true:开启所有严格类型检查,推荐生产项目必开
  • esModuleInterop: true:允许 import xxx from ‘xxx’ 导入 CommonJS 模块
  • skipLibCheck: true:跳过第三方库的类型检查,加快编译速度
  • resolveJsonModule: true:允许直接 import JSON 文件
  • forceConsistentCasingInFileNames: true:强制文件名大小写一致

💡小贴士:如果你是初学者,可以先设置"strict": false减少类型错误干扰,等项目跑通后再逐步开启严格模式。

3、安装 LangGraph 核心依赖

# LangGraph 核心包npminstall@langchain/langgraph# LangChain 核心(LangGraph 依赖)npminstall@langchain/core# OpenAI 集成(或其他 LLM)npminstall@langchain/openai# Zod:用于结构化输出(后续章节会用到)npminstallzod

代码解读:

  • @langchain/langgraph:LangGraph 框架核心,提供StateGraphAnnotation
  • @langchain/core:LangChain 基础抽象,LangGraph 内部依赖
  • @langchain/openai:OpenAI 模型的 LangChain 适配器
  • zod:TypeScript 优先的 schema 验证库,用于结构化 LLM 输出

⚠️注意:@langchain/langgraph会自动安装兼容版本的@langchain/core,但建议手动显式声明依赖,避免版本冲突。

如果你想使用其他模型提供商(如 Anthropic、Google Gemini),可以安装对应的包:

  • @langchain/anthropic- Claude 系列模型
  • @langchain/google-genai- Gemini 系列模型
  • @langchain/cohere- Cohere 模型

三、配置 API 密钥

1、创建 .env 文件

在项目根目录创建.env文件:

# .env# OpenAI 官网申请,用于调用 GPT 系列模型OPENAI_API_KEY=sk-your-openai-api-key-here# 国内用户常需要配置代理地址OPENAI_BASE_URL=https://api.openai.com/v1# 可选,国内代理时使用# 可选:LangSmith 追踪(调试神器,第16章详细介绍)LANGCHAIN_TRACING_V2=true# LangSmith 平台的 API KeyLANGCHAIN_API_KEY=ls-your-langsmith-key# 项目名称,用于在 LangSmith 中组织追踪记录LANGCHAIN_PROJECT=my-langgraph-project

2、添加 .gitignore

⚠️极其重要:绝对不能把 API 密钥提交到代码仓库!

# .gitignorenode_modules/ dist/ .env *.env.local .DS_Store

验证:运行git status,确认.env文件没有出现在待提交列表中。

3、创建环境验证脚本

创建src/check-env.ts:

// 加载 .env 文件中的变量到 process.envimport*asdotenvfrom'dotenv';dotenv.config();functioncheckEnv(){constrequired=['OPENAI_API_KEY'];// 检查必需变量是否都已设置constmissing=required.filter(key=>!process.env[key]);if(missing.length>0){console.error('❌ 缺少必要的环境变量:',missing.join(', '));process.exit(1);// 非零退出码表示错误,方便 CI/CD 检测}console.log('✅ 环境变量配置正确!');// 只显示 Key 前缀,避免泄露完整密钥console.log('API Key 前缀:',process.env.OPENAI_API_KEY?.slice(0,7)+'...');}checkEnv();

运行验证:

npx ts-node src/check-env.ts

期望输出:

✅ 环境变量配置正确! API Key 前缀: sk-proj...

四、构建第一个 Agent

现在进入最激动人心的部分——构建你的第一个 LangGraph Agent!

步骤 1:理解目标

我们要构建一个简单的对话 Agent,它能够:

  • 接收用户输入的问题
  • 调用 LLM 生成回复
  • 保持对话状态(记住上下文)

👤 用户输入

chatbot 节点
(调用 LLM)

AI 回复

继续对话?

结束

步骤 2:定义 State

创建src/first-agent.ts,首先定义状态:

import*asdotenvfrom'dotenv';dotenv.config();import{StateGraph,MessagesAnnotation}from'@langchain/langgraph';import{ChatOpenAI}from'@langchain/openai';import{HumanMessage,AIMessage}from'@langchain/core/messages';// MessagesAnnotation 是 LangGraph 内置的消息状态注解// 它帮我们自动管理对话历史消息列表constmodel=newChatOpenAI({model:'gpt-4o-mini',temperature:0.7,apiKey:process.env.OPENAI_API_KEY,});

代码解读:

  • MessagesAnnotation:LangGraph 预定义的状态注解,内含messages字段,代表消息历史数组,自动处理消息的追加逻辑
  • ChatOpenAI:OpenAI 聊天模型的 LangChain 封装
  • temperature: 0.7:模型温度,用于控制创造性,0=确定性,1=最随机
  • apiKey: process.env.OPENAI_API_KEY:从环境变量读取,避免硬编码

步骤 3:定义节点函数

// 定义 chatbot 节点:接收状态,返回更新后的状态asyncfunctionchatbotNode(state:typeofMessagesAnnotation.State){// 把所有历史消息传给 LLM,实现多轮对话// state.messages包含当前对话的完整消息历史constresponse=awaitmodel.invoke(state.messages);// 返回新增的 AI 消息,LangGraph 会自动追加到 messages 数组return{messages:[response]};}

步骤 4:构建图并运行

// 构建 StateGraphconstgraph=newStateGraph(MessagesAnnotation).addNode('chatbot',chatbotNode)// 添加节点.addEdge('__start__','chatbot')// 起点 → chatbot.addEdge('chatbot','__end__')// chatbot → 终点.compile();// 编译成可执行图

代码解读:

  • StateGraph(MessagesAnnotation):用消息注解创建图,自动处理消息合并
  • addNode:注册节点,第一参数是名称,第二参数是处理函数
  • addEdge:添加边,‘start’ 和 ‘end’ 是内置的起止节点
  • compile():将图定义编译成可执行的 Runnable 对象, 这一步非常关键,未编译的图无法执行

主运行函数:

// 主运行函数asyncfunctionmain(){console.log('🤖 AI Agent 已启动,输入问题开始对话\n');// 传入初始状态,触发图的执行constresult=awaitgraph.invoke({messages:[newHumanMessage('你好!请介绍一下你自己,并说明你能做什么。')],});// 打印最后一条 AI 回复constlastMessage=result.messages[result.messages.length-1]asAIMessage;console.log('AI:',lastMessage.content);}// 捕获并打印异步错误,防止未处理的 Promise rejectionmain().catch(console.error);

步骤 5:运行 Agent

npx ts-node src/first-agent.ts

期望输出:

🤖 AI Agent 已启动,输入问题开始对话 AI: 你好!我是一个AI助手,基于大型语言模型构建。我能够: - 回答各种问题和解释概念 - 协助编写和优化代码 - 进行多轮对话,记住上下文 - 提供分析和建议 ...

🎉 恭喜!你已经成功运行了第一个 LangGraph Agent!


五、升级为多轮对话

单次问答并不够有趣,让我们升级成真正的多轮对话:

import*asreadlinefrom'readline';asyncfunctionmultiTurnChat(){constrl=readline.createInterface({input:process.stdin,output:process.stdout,});letmessages:HumanMessage[]=[];console.log('🤖 多轮对话 Agent 启动!输入 exit 退出\n');constaskQuestion=()=>{rl.question('你: ',async(userInput)=>{if(userInput.toLowerCase()==='exit'){console.log('再见!👋');rl.close();return;}messages.push(newHumanMessage(userInput));constresult=awaitgraph.invoke({messages});messages=result.messages;// 保存完整历史constlastMsg=messages[messages.length-1]asAIMessage;console.log('AI:',lastMsg.content,'\n');askQuestion();// 继续对话});};askQuestion();}multiTurnChat().catch(console.error);

代码解读:

  • readline:Node.js 内置模块,用于读取命令行输入
  • messages:在循环中累积对话历史,实现上下文记忆
  • messages = result.messages:每轮对话后更新本地消息历史, 这是实现多轮记忆的关键!
  • 递归调用askQuestion():实现持续对话循环

注意:这种方式适合演示,生产环境应使用数据库持久化

运行多轮对话:

npx ts-node src/first-agent.ts

示例对话:

🤖 多轮对话 Agent 启动!输入 exit 退出 你: 你好! AI: 你好!很高兴见到你。有什么我可以帮助你的吗? 你: 你能帮我写一段 Python 代码吗? AI: 当然可以!请告诉我你需要什么功能的 Python 代码? 你: 计算斐波那契数列 AI: 这是一个计算斐波那契数列的 Python 函数: def fibonacci(n): if n <= 0: return [] elif n == 1: return [0] ... 你: exit 再见!👋

六、最佳实践和踩坑指南

💡 实践 1:环境变量的正确加载方式

❌ 不好的做法:

// 硬编码 API Key —— 绝对禁止!constmodel=newChatOpenAI({apiKey:'sk-abc123...'});

✅ 推荐做法:

// 程序入口处立即加载 .envimport*asdotenvfrom'dotenv';dotenv.config();// 必须在其他 import 之前或程序最顶部调用constmodel=newChatOpenAI({apiKey:process.env.OPENAI_API_KEY});

原因:硬编码的密钥极易通过代码仓库泄露,造成严重安全风险和经济损失。

💡 实践 2:模型版本的显式声明

❌ 不好的做法:

constmodel=newChatOpenAI();// 使用默认模型,版本不透明

✅ 推荐做法:

constmodel=newChatOpenAI({model:'gpt-4o-mini',// 显式声明模型版本temperature:0.7,// 显式声明参数maxTokens:2048,// 控制最大输出长度});

原因:默认模型可能随 SDK 版本升级而改变,显式声明确保行为稳定可预期。

💡 实践 3:项目结构的规范化

❌ 不好的做法:

my-project/ ├── agent.ts# 所有代码堆在一个文件├── utils.ts └── .env

✅ 推荐做法:

my-project/ ├── src/ │ ├── agent.ts# Agent 定义│ ├── nodes/# 节点函数│ │ ├── chatbot.ts │ │ └── router.ts │ ├── tools/# 自定义工具│ │ └── search.ts │ └── index.ts# 入口文件├── .env ├── .gitignore ├── package.json └── tsconfig.json

原因:随着项目复杂度增加,模块化结构能大幅提升可维护性。

⚠️ 常见问题

问题现象解决方案
dotenv 未在顶部加载process.env.OPENAI_API_KEYundefined确保dotenv.config()在所有使用环境变量的代码之前执行
TypeScript 严格模式报错大量类型错误无法运行先设strict: false跑通后逐步修复,或使用类型断言
Node.js 版本过低SyntaxError: Cannot use...升级至 Node.js 18+,使用nvm use 20
pnpm/npm 混用依赖冲突、幽灵依赖项目统一使用一种包管理器,删除混用的 lock 文件
忘记.compile()调用invoke()时报错"not a function"构建图后必须调用.compile()才能执行
消息被覆盖对话历史丢失,只保留最后一条使用MessagesAnnotation而非普通数组,它的 reducer 是追加语义

📝 本章小结

核心知识点回顾

知识点关键要点应用场景
项目初始化npm init+tsconfig.json配置所有 TS 项目的起点
依赖安装@langchain/langgraph+@langchain/openaiLangGraph 核心能力
环境变量.env+dotenv+.gitignoreAPI 密钥安全管理
MessagesAnnotation内置消息状态注解对话历史管理
StateGraph图定义 → 编译 → 执行所有 LangGraph 应用的基础
节点函数接收 State,返回 Partial图的处理单元

🎯 动手练习

练习 1:更换语言模型

  • 目标:将 OpenAI 替换为其他模型(如 Anthropic Claude)
  • 要求:
    1. 安装@langchain/anthropic
    2. 修改模型初始化代码,使用ChatAnthropic
    3. .env中添加ANTHROPIC_API_KEY
  • 验收标准:Agent 能正常对话,返回 Claude 的回复风格

练习 2:添加系统提示词

  • 目标:给 Agent 设定一个角色(如"你是一个代码助手")
  • 要求:
    1. messages数组首位插入SystemMessage
    2. SystemMessage 内容描述 Agent 的角色和行为准则
    3. 测试不同角色的效果差异
  • 验收标准:Agent 的回复风格符合设定的角色,如代码助手会主动提供代码示例

练习 3:多轮对话历史限制

  • 目标:防止 Token 超限,只保留最近 10 条消息
  • 要求:
    1. 在调用graph.invoke前,截取messages数组的最后 10 条
    2. 添加日志输出当前消息数量
    3. 测试长对话场景(超过 10 轮)
  • 验收标准:长对话不报错,且 Agent 仍能正常回复,Token 消耗可控

练习 4:错误处理增强

  • 目标:为 Agent 添加完善的错误处理
  • 要求:
    1. 捕获 API 调用失败(网络错误、配额不足等)
    2. 提供友好的错误提示
    3. 实现重试机制(最多 3 次)
  • 验收标准:模拟网络故障时,Agent 能优雅降级而非崩溃

📚 延伸阅读

  • LangGraph.js 官方文档
  • LangGraph.js GitHub 仓库
  • OpenAI 模型列表
  • dotenv 使用指南
  • TypeScript 官方手册

下一章:第3章 —— 图的核心概念:节点、边与状态

http://www.jsqmd.com/news/699172/

相关文章:

  • 为什么你的AI语音处理项目需要ClearerVoice-Studio?5个核心场景深度解析
  • 北京金发钹祥金属材料贸易:朝阳区不锈钢焊接电话 - LYL仔仔
  • 2026浏览器指纹追踪的合规边界与隐私优先的反检测技术落地框架
  • 上海泽固新型建材:宝山聚合物砂浆批发厂家推荐 - LYL仔仔
  • 千问 LeetCode 1739.放置盒子 public int minimumBoxes(int n)
  • Gitee:中国本土DevOps平台如何重塑企业研发管理范式
  • 【路径规划】基于遗传算法确定山路补给无人机的最佳路线Matlab代码
  • Newtonsoft.Json 架构解析:高性能JSON序列化框架的技术实现与调优
  • TestDisk PhotoRec:专业级数据恢复工具如何拯救你的丢失文件与分区
  • 河南加之固建筑:惠济区房屋改造公司 - LYL仔仔
  • 廊坊山美供应链管理:专业的廊坊库存货架公司 - LYL仔仔
  • 【VSCode 2026嵌入式烧录终极指南】:零配置实现STM32/ESP32/RP2040一键烧录,实测烧录速度提升3.8倍
  • 搜索系列·连通块问题
  • 用multiset的upper_bound/lower_bound优化你的LeetCode刷题:以‘数据流的中位数’和‘滑动窗口最大值’为例
  • rk3568 uboot图形化界面操作以及保存配置
  • CVPR 2026 Accepted?来预讲会做主角
  • 2026熙琦科技迷你手持打印设备常见选购问题解答干货分享 - 热敏感科技蜂
  • 泉州鼎盛拆除:靠谱的泉州墙体拆除哪家专业 - LYL仔仔
  • GLM-OCR API调用详解:Python示例,助你快速集成到项目
  • 常州环之宇再生资源:常州废品上门回收哪家专业 - LYL仔仔
  • Poe.com网页版深度体验:不装App,用浏览器同时“白嫖”GPT-3.5和Claude是什么体验?
  • ICode Python 2级闯关:从循环嵌套到多角色协同的综合编程思维训练
  • 力扣hot100(9-找到字符串中所有字母异位词;10-和为K的子数组)
  • Cursor Pro免费激活工具:跨平台设备标识重置技术方案
  • 2026年湖南长沙短视频运营与GEO豆包AI搜索推广深度横评|企业获客新赛道完全指南 - 年度推荐企业名录
  • 别再为音频格式发愁了!一个Java工具类搞定WAV转MP3、AMR转码(附完整代码和依赖配置)
  • 宪意(山东)建筑拆除:济南拆门窗服务商 - LYL仔仔
  • BarrageGrab:全平台直播弹幕抓取架构设计与企业级应用解决方案
  • 实测分享:3家在线平面设计公司对比,2026传媒/广告店线上设计辅助首选
  • open-xiaoai-bridge:让小爱同学语音控制任意智能设备