LangGraph入门:LCEL详解

前言

LangGraph是LangChain生态系统中的一个重要组件,它扩展了LCEL(LangChain Expression Language)的能力,允许开发者构建有状态、多步骤的复杂AI工作流。与传统的线性链式调用不同,LangGraph支持循环、条件分支等图结构,能够更好地模拟真实世界的复杂决策流程。

本文将深入探讨如何在TypeScript环境中使用LangGraph和LCEL,通过实际示例展示如何构建强大的AI应用。

通过此文档的阅读,你将收获

  • 理解LangGraph的核心概念和架构设计
  • 掌握在TypeScript中使用LCEL构建复杂工作流的方法
  • 学会创建有状态的多步骤AI应用
  • 了解如何调试和优化LangGraph应用
  • 能够构建支持循环、条件分支的智能工作流

适用范围

  • 使用TypeScript的Node.js开发者
  • 需要构建复杂AI工作流的项目
  • 希望实现有状态、多步骤AI交互的应用
  • 对LangChain生态有一定了解的开发者

具体方案

1. 环境设置和基础配置

复制代码
// package.json 依赖
{
  "dependencies": {
    "@langchain/langgraph": "^0.0.13",
    "@langchain/core": "^0.1.0",
    "@langchain/openai": "^0.0.12",
    "zod": "^3.22.0"
  }
}

2. 基础LCEL链构建

复制代码
import { ChatOpenAI } from "@langchain/openai";
import { StringOutputParser } from "@langchain/core/output_parsers";
import { PromptTemplate } from "@langchain/core/prompts";

// 基础LCEL链示例
const createTranslationChain = () => {
  const prompt = PromptTemplate.fromTemplate(
    "将以下文本从{sourceLang}翻译成{targetLang}: {text}"
  );
  
  const model = new ChatOpenAI({
    modelName: "gpt-3.5-turbo",
    temperature: 0.7,
  });
  
  return prompt.pipe(model).pipe(new StringOutputParser());
};

// 使用示例
const translationChain = createTranslationChain();
const result = await translationChain.invoke({
  sourceLang: "英语",
  targetLang: "中文",
  text: "Hello, how are you today?"
});

3. LangGraph状态管理

复制代码
import { StateGraph, END } from "@langchain/langgraph";
import { z } from "zod";

// 定义状态Schema
const AgentState = z.object({
  messages: z.array(z.object({
    role: z.enum(["user", "assistant", "system"]),
    content: z.string()
  })),
  currentStep: z.string().default("start"),
  needsClarification: z.boolean().default(false),
  clarificationQuestion: z.string().optional()
});

type AgentState = z.infer<typeof AgentState>;

// 创建基础节点
const createLLMNode = (systemPrompt: string) => {
  const model = new ChatOpenAI({ temperature: 0.7 });
  
  return async (state: AgentState) => {
    const prompt = [
      { role: "system", content: systemPrompt },
      ...state.messages
    ];
    
    const response = await model.invoke(prompt);
    
    return {
      ...state,
      messages: [
        ...state.messages,
        { role: "assistant", content: response.content as string }
      ]
    };
  };
};

4. 复杂工作流实现

复制代码
// 多步骤对话工作流
class ConversationWorkflow {
  private graph: StateGraph<AgentState>;
  
  constructor() {
    this.graph = new StateGraph<AgentState>({ schema: AgentState });
    this.buildGraph();
  }
  
  private buildGraph() {
    // 添加节点
    this.graph.addNode("start", this.startNode());
    this.graph.addNode("clarify", this.clarifyNode());
    this.graph.addNode("process", this.processNode());
    this.graph.addNode("finalize", this.finalizeNode());
    
    // 设置边和条件
    this.graph.addEdge("start", "process");
    
    this.graph.addConditionalEdges(
      "process",
      this.shouldClarify,
      {
        clarify: "clarify",
        continue: "finalize"
      }
    );
    
    this.graph.addEdge("clarify", "process");
    this.graph.addEdge("finalize", END);
    
    this.graph.setEntryPoint("start");
  }
  
  private startNode() {
    return async (state: AgentState) => {
      const systemPrompt = "你是一个有帮助的助手,请根据用户需求提供帮助。";
      const model = new ChatOpenAI({ temperature: 0.7 });
      
      const response = await model.invoke([
        { role: "system", content: systemPrompt },
        ...state.messages
      ]);
      
      return {
        ...state,
        messages: [
          ...state.messages,
          { role: "assistant", content: response.content as string }
        ],
        currentStep: "process"
      };
    };
  }
  
  private shouldClarify(state: AgentState) {
    // 简单的模糊检测逻辑
    const lastMessage = state.messages[state.messages.length - 1].content;
    const unclearKeywords = ["可能", "大概", "也许", "不确定"];
    
    const needsClarification = unclearKeywords.some(keyword => 
      lastMessage.includes(keyword)
    );
    
    return needsClarification ? "clarify" : "continue";
  }
  
  private clarifyNode() {
    return async (state: AgentState) => {
      const clarifyPrompt = `
        用户的需求可能不够明确,请提出一个澄清问题来获得更多信息。
        当前对话:${JSON.stringify(state.messages)}
      `;
      
      const model = new ChatOpenAI({ temperature: 0.7 });
      const response = await model.invoke(clarifyPrompt);
      
      return {
        ...state,
        messages: [
          ...state.messages,
          { 
            role: "assistant", 
            content: `为了更好帮助您,我需要了解更多信息:${response.content}` 
          }
        ],
        needsClarification: true,
        clarificationQuestion: response.content as string
      };
    };
  }
  
  getCompiledGraph() {
    return this.graph.compile();
  }
}

5. 循环和条件逻辑

复制代码
// 支持循环的复杂工作流
class IterativeWorkflow {
  private graph: StateGraph<AgentState>;
  private maxIterations = 3;
  
  constructor() {
    this.graph = new StateGraph<AgentState>({ schema: AgentState });
    this.buildGraph();
  }
  
  private buildGraph() {
    this.graph.addNode("analyze", this.analyzeNode());
    this.graph.addNode("refine", this.refineNode());
    this.graph.addNode("finalCheck", this.finalCheckNode());
    
    this.graph.addEdge("analyze", "refine");
    
    this.graph.addConditionalEdges(
      "refine",
      this.shouldContinueRefinement,
      {
        continue: "analyze",
        done: "finalCheck"
      }
    );
    
    this.graph.addEdge("finalCheck", END);
    this.graph.setEntryPoint("analyze");
  }
  
  private shouldContinueRefinement(state: AgentState) {
    const iterationCount = state.messages.filter(msg => 
      msg.role === "assistant" && msg.content.includes("迭代")
    ).length;
    
    return iterationCount < this.maxIterations ? "continue" : "done";
  }
  
  private analyzeNode() {
    return async (state: AgentState) => {
      const analysisPrompt = `
        分析当前内容并提出改进建议。当前内容:${
          state.messages[state.messages.length - 1]?.content || "无"
        }
      `;
      
      const model = new ChatOpenAI({ temperature: 0.7 });
      const response = await model.invoke(analysisPrompt);
      
      return {
        ...state,
        messages: [
          ...state.messages,
          { 
            role: "assistant", 
            content: `分析结果:${response.content}` 
          }
        ]
      };
    };
  }
}

成果展示

1. 完整示例应用

复制代码
// 完整的对话代理实现
class AdvancedChatAgent {
  private workflow: any;
  
  constructor() {
    const workflow = new ConversationWorkflow();
    this.workflow = workflow.getCompiledGraph();
  }
  
  async processMessage(userInput: string, conversationHistory: any[] = []) {
    const initialState: AgentState = {
      messages: [
        ...conversationHistory,
        { role: "user", content: userInput }
      ],
      currentStep: "start",
      needsClarification: false
    };
    
    const result = await this.workflow.invoke(initialState, {
      configurable: {
        thread_id: "user-123"
      }
    });
    
    return {
      response: result.messages[result.messages.length - 1].content,
      needsClarification: result.needsClarification,
      fullHistory: result.messages
    };
  }
}

// 使用示例
const agent = new AdvancedChatAgent();

// 模拟对话
const conversation = async () => {
  console.log("=== 智能对话代理演示 ===");
  
  let history: any[] = [];
  
  // 第一轮对话
  const result1 = await agent.processMessage("我想学习编程,但不知道从哪里开始", history);
  console.log("助手:", result1.response);
  history = result1.fullHistory;
  
  // 第二轮对话(可能需要澄清)
  if (result1.needsClarification) {
    const result2 = await agent.processMessage("我想做网页开发", history);
    console.log("助手:", result2.response);
    history = result2.fullHistory;
  }
  
  // 第三轮对话
  const result3 = await agent.processMessage("请给我具体的学习路线", history);
  console.log("助手:", result3.response);
};

2. 流式输出实现

复制代码
// 支持流式输出的工作流
class StreamingWorkflow {
  private graph: StateGraph<AgentState>;
  
  constructor() {
    this.graph = new StateGraph<AgentState>({ schema: AgentState });
    this.buildGraph();
  }
  
  private buildGraph() {
    this.graph.addNode("streamResponse", this.streamResponseNode());
    this.graph.addEdge("streamResponse", END);
    this.graph.setEntryPoint("streamResponse");
  }
  
  private streamResponseNode() {
    return async (state: AgentState, options?: { stream?: boolean }) => {
      const model = new ChatOpenAI({ 
        temperature: 0.7,
        streaming: options?.stream ?? true
      });
      
      if (options?.stream) {
        // 流式处理
        const stream = await model.stream(state.messages);
        let fullResponse = "";
        
        for await (const chunk of stream) {
          const content = chunk.content as string;
          fullResponse += content;
          // 在实际应用中,这里可以通过回调函数处理每个chunk
          console.log("流式输出:", content);
        }
        
        return {
          ...state,
          messages: [
            ...state.messages,
            { role: "assistant", content: fullResponse }
          ]
        };
      } else {
        // 普通处理
        const response = await model.invoke(state.messages);
        return {
          ...state,
          messages: [
            ...state.messages,
            { role: "assistant", content: response.content as string }
          ]
        };
      }
    };
  }
  
  async *streamConversation(userInput: string) {
    const initialState: AgentState = {
      messages: [{ role: "user", content: userInput }],
      currentStep: "streamResponse"
    };
    
    const compiledGraph = this.graph.compile();
    
    // 模拟流式处理
    const result = await compiledGraph.invoke(initialState, {
      configurable: { stream: true }
    });
    
    // 在实际实现中,这里应该返回真正的流
    yield result.messages[result.messages.length - 1].content;
  }
}

总结

通过本文的学习,我们深入探讨了如何在TypeScript环境中使用LangGraph和LCEL构建复杂的AI工作流。关键收获包括:

  1. LCEL核心概念:理解了管道操作符和组件组合的思想
  2. 状态管理:学会了使用Zod Schema定义和管理应用状态
  3. 图结构工作流:掌握了如何构建支持条件分支和循环的复杂流程
  4. 实际应用:通过完整示例展示了真实场景下的应用方法

LangGraph和LCEL的结合为构建复杂AI应用提供了强大的工具链,特别是在需要多步骤交互、状态保持和复杂决策逻辑的场景中表现出色。

参考文档

相关推荐
木卫二号Coding5 分钟前
第七十二篇-V100-32G+WebUI+Flux.1-Schnell+Lora+文生图
开发语言·人工智能·python
之歆5 分钟前
Spring AI入门到实战到原理源码-笔记-(上)
java·人工智能·spring
love530love7 分钟前
EPGF 新手教程 11在 PyCharm(中文版 GUI)中创建 uv 环境,并把 uv 做到“项目自包含”(工具本地化为必做环节)
ide·人工智能·python·pycharm·conda·uv·epgf
Fabarta技术团队10 分钟前
响应北京人工智能行动计划,枫清科技共筑AI创新高地
人工智能·科技
得贤招聘官11 分钟前
判断AI招聘系统成熟度的3个硬指标
人工智能
Lkygo11 分钟前
ragflow 构建本地知识库指南
人工智能·python·语言模型
晟诺数字人11 分钟前
数字人、AI数字人、虚拟数字人、3D数字人之间的区别于应用场景
大数据·人工智能·3d·数字人
木卫四科技12 分钟前
【CES 2026】木卫四科技发布R-IDPS,护航具身机器人“Chat GPT时刻”安全落地!
大数据·人工智能
Codebee12 分钟前
# 大厂AI全是黑话?Ooder靠Skill技术3天落地企业级应用,这才是真实用!
人工智能
He_Donglin13 分钟前
Data Mining| 类型变量编码(乳腺癌威斯康星数据集/葡萄酒数据集/鸢尾花数据集)
人工智能·数据挖掘