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应用提供了强大的工具链,特别是在需要多步骤交互、状态保持和复杂决策逻辑的场景中表现出色。

参考文档

相关推荐
心勤则明13 分钟前
用 Spring AI Alibaba 打造智能查询增强引擎
java·人工智能·spring
njsgcs38 分钟前
图卷积是如何处理不同输入长度的 消息传递
人工智能
哥本哈士奇1 小时前
使用OpenClaw的Skills对接本地系统
人工智能
IT_陈寒1 小时前
SpringBoot实战:3个隐藏技巧让你的应用性能飙升50%
前端·人工智能·后端
. . . . .1 小时前
Claude Code Plugins 目录结构与加载机制
人工智能
GJGCY1 小时前
2026企业级智能体架构:记忆机制、RAG检索与任务规划对比
人工智能·经验分享·ai·智能体
SuniaWang1 小时前
《Spring AI + 大模型全栈实战》学习手册系列 ·专题三:《Embedding 模型选型指南:从 MMTEB 排名到实际应用》
人工智能·学习·spring
爱学习的程序媛1 小时前
“数字孪生”详解与前端技术栈
前端·人工智能·计算机视觉·智慧城市·信息与通信
数业智能心大陆1 小时前
科技赋能心育服务,心大陆 AI 减压舱守护校园心灵健康
人工智能·心理健康
程序员Sunday1 小时前
Claude Code 生态爆发:5个必知的新工具
前端·人工智能·后端