前言
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工作流。关键收获包括:
- LCEL核心概念:理解了管道操作符和组件组合的思想
- 状态管理:学会了使用Zod Schema定义和管理应用状态
- 图结构工作流:掌握了如何构建支持条件分支和循环的复杂流程
- 实际应用:通过完整示例展示了真实场景下的应用方法
LangGraph和LCEL的结合为构建复杂AI应用提供了强大的工具链,特别是在需要多步骤交互、状态保持和复杂决策逻辑的场景中表现出色。
参考文档
- LangGraph官方文档:https://docs.langchain.com/oss/python/langgraph/overview
- LangChain.js文档:https://js.langchain.com/docs/
- TypeScript官方文档:https://www.typescriptlang.org/docs/
- OpenAI API文档:https://platform.openai.com/docs/api-reference