外观
在自定义工作流架构中,你使用 LangGraph 定义自己的定制执行流程。你对图结构拥有完全的控制权——包括顺序步骤、条件分支、循环和并行执行。
关键特征
- 对图结构的完全控制
- 混合确定性逻辑与智能体行为
- 支持顺序步骤、条件分支、循环和并行执行
- 将其他模式作为节点嵌入你的工作流
何时使用
当标准模式(子智能体、技能等)不适合你的需求、你需要混合确定性逻辑与智能体行为,或者你的用例需要复杂的路由或多阶段处理时,请使用自定义工作流。
你工作流中的每个节点都可以是一个简单函数、一次 LLM 调用,或一个配备 工具 的完整 智能体。你还可以在自定义工作流中组合其他架构——例如,将多智能体系统作为单个节点嵌入。
自定义工作流的完整示例请参见下面的教程。
- 教程:使用路由构建多源知识库 — 路由器模式 就是自定义工作流的一个示例。本教程演示了如何构建一个并行查询 GitHub、Notion 和 Slack,然后综合结果的路由器。 >
基本实现
核心见解是,你可以在任何 LangGraph 节点内直接调用 LangChain 智能体,将自定义工作流的灵活性与预构建智能体的便捷性结合起来:
python
from langchain.agents import create_agent
from langgraph.graph import StateGraph, START, END
agent = create_agent(model="openai:gpt-5.5", tools=[...])
def agent_node(state: State) -> dict:
"""A LangGraph node that invokes a LangChain agent."""
result = agent.invoke({
"messages": [{"role": "user", "content": state["query"]}]
})
return {"answer": result["messages"][-1].content}
# 构建一个简单的工作流
workflow = (
StateGraph(State)
.add_node("agent", agent_node)
.add_edge(START, "agent")
.add_edge("agent", END)
.compile()
)typescript
import { z } from "zod";
import { createAgent } from "langchain";
import { StateGraph, START, END, StateSchema, MessagesValue } from "@langchain/langgraph";
const agent = createAgent({ model: "openai:gpt-5.5", tools: [...] });
const AgentState = new StateSchema({
messages: MessagesValue,
query: z.string(),
});
const agentNode: GraphNode<typeof AgentState> = (state) => {
// 调用 LangChain 智能体的 LangGraph 节点
const result = await agent.invoke({
messages: [{ role: "user", content: state.query }]
});
return { answer: result.messages.at(-1)?.content };
}
// 构建一个简单的工作流
const workflow = new StateGraph(State)
.addNode("agent", agentNode)
.addEdge(START, "agent")
.addEdge("agent", END)
.compile();示例:RAG 流水线
一个常见用例是将 检索 与智能体结合。此示例构建了一个 WNBA 统计助手,它从知识库中检索信息,并能获取实时新闻。
自定义 RAG 工作流
该工作流演示了三种类型的节点:
- 模型节点(改写):使用 结构化输出 改写用户查询以获得更好的检索效果。
- 确定性节点(检索):执行向量相似度搜索——不涉及 LLM。
- 智能体节点(智能体):对检索到的上下文进行推理,并可以通过工具获取额外的信息。
TIP
你可以使用 LangGraph 状态在工作流步骤之间传递信息。这允许工作流的每个部分读取和更新结构化字段,从而轻松地在节点之间共享数据和上下文。
python
from typing import TypedDict
from pydantic import BaseModel
from langgraph.graph import StateGraph, START, END
from langchain.agents import create_agent
from langchain.tools import tool
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_core.vectorstores import InMemoryVectorStore
class State(TypedDict):
question: str
rewritten_query: str
documents: list[str]
answer: str
# WNBA 知识库:包含球队名单、比赛结果和球员数据
embeddings = OpenAIEmbeddings()
vector_store = InMemoryVectorStore(embeddings)
vector_store.add_texts([
# 球队名单
"New York Liberty 2024 roster: Breanna Stewart, Sabrina Ionescu, Jonquel Jones, Courtney Vandersloot.",
"Las Vegas Aces 2024 roster: A'ja Wilson, Kelsey Plum, Jackie Young, Chelsea Gray.",
"Indiana Fever 2024 roster: Caitlin Clark, Aliyah Boston, Kelsey Mitchell, NaLyssa Smith.",
# 比赛结果
"2024 WNBA Finals: New York Liberty defeated Minnesota Lynx 3-2 to win the championship.",
"June 15, 2024: Indiana Fever 85, Chicago Sky 79. Caitlin Clark had 23 points and 8 assists.",
"August 20, 2024: Las Vegas Aces 92, Phoenix Mercury 84. A'ja Wilson scored 35 points.",
# 球员数据
"A'ja Wilson 2024 season stats: 26.9 PPG, 11.9 RPG, 2.6 BPG. Won MVP award.",
"Caitlin Clark 2024 rookie stats: 19.2 PPG, 8.4 APG, 5.7 RPG. Won Rookie of the Year.",
"Breanna Stewart 2024 stats: 20.4 PPG, 8.5 RPG, 3.5 APG.",
])
retriever = vector_store.as_retriever(search_kwargs={"k": 5})
@tool
def get_latest_news(query: str) -> str:
"""Get the latest WNBA news and updates."""
# 在此填入你的新闻 API
return "Latest: The WNBA announced expanded playoff format for 2025..."
agent = create_agent(
model="openai:gpt-5.5",
tools=[get_latest_news],
)
model = ChatOpenAI(model="gpt-5.5")
class RewrittenQuery(BaseModel):
query: str
def rewrite_query(state: State) -> dict:
"""Rewrite the user query for better retrieval."""
system_prompt = """Rewrite this query to retrieve relevant WNBA information.
The knowledge base contains: team rosters, game results with scores, and player statistics (PPG, RPG, APG).
Focus on specific player names, team names, or stat categories mentioned."""
response = model.with_structured_output(RewrittenQuery).invoke([
{"role": "system", "content": system_prompt},
{"role": "user", "content": state["question"]}
])
return {"rewritten_query": response.query}
def retrieve(state: State) -> dict:
"""Retrieve documents based on the rewritten query."""
docs = retriever.invoke(state["rewritten_query"])
return {"documents": [doc.page_content for doc in docs]}
def call_agent(state: State) -> dict:
"""Generate answer using retrieved context."""
context = "\n\n".join(state["documents"])
prompt = f"Context:\n{context}\n\nQuestion: {state['question']}"
response = agent.invoke({"messages": [{"role": "user", "content": prompt}]})
return {"answer": response["messages"][-1].content_blocks}
workflow = (
StateGraph(State)
.add_node("rewrite", rewrite_query)
.add_node("retrieve", retrieve)
.add_node("agent", call_agent)
.add_edge(START, "rewrite")
.add_edge("rewrite", "retrieve")
.add_edge("retrieve", "agent")
.add_edge("agent", END)
.compile()
)
result = workflow.invoke({"question": "Who won the 2024 WNBA Championship?"})
print(result["answer"])INFO
在生产环境中,请使用持久化的向量数据库,例如 Valkey、Databricks Vector Search 或 MongoDB Atlas,而不是 InMemoryVectorStore。参见 所有向量数据库。
typescript
import { StateGraph, Annotation, START, END } from "@langchain/langgraph";
import { createAgent, tool } from "langchain";
import { ChatOpenAI, OpenAIEmbeddings } from "@langchain/openai";
import { MemoryVectorStore } from "@langchain/classic/vectorstores/memory";
import * as z from "zod";
const State = Annotation.Root({
question: Annotation<string>(),
rewrittenQuery: Annotation<string>(),
documents: Annotation<string[]>(),
answer: Annotation<string>(),
});
// WNBA 知识库:包含球队名单、比赛结果和球员数据
const embeddings = new OpenAIEmbeddings();
const vectorStore = await MemoryVectorStore.fromTexts(
[
// 球队名单
"New York Liberty 2024 roster: Breanna Stewart, Sabrina Ionescu, Jonquel Jones, Courtney Vandersloot.",
"Las Vegas Aces 2024 roster: A'ja Wilson, Kelsey Plum, Jackie Young, Chelsea Gray.",
"Indiana Fever 2024 roster: Caitlin Clark, Aliyah Boston, Kelsey Mitchell, NaLyssa Smith.",
// 比赛结果
"2024 WNBA Finals: New York Liberty defeated Minnesota Lynx 3-2 to win the championship.",
"June 15, 2024: Indiana Fever 85, Chicago Sky 79. Caitlin Clark had 23 points and 8 assists.",
"August 20, 2024: Las Vegas Aces 92, Phoenix Mercury 84. A'ja Wilson scored 35 points.",
// 球员数据
"A'ja Wilson 2024 season stats: 26.9 PPG, 11.9 RPG, 2.6 BPG. Won MVP award.",
"Caitlin Clark 2024 rookie stats: 19.2 PPG, 8.4 APG, 5.7 RPG. Won Rookie of the Year.",
"Breanna Stewart 2024 stats: 20.4 PPG, 8.5 RPG, 3.5 APG.",
],
[{}, {}, {}, {}, {}, {}, {}, {}, {}],
embeddings
);
const retriever = vectorStore.asRetriever({ k: 5 });
const getLatestNews = tool(
async ({ query }) => {
// 在此填入你的新闻 API
return "Latest: The WNBA announced expanded playoff format for 2025...";
},
{
name: "get_latest_news",
description: "Get the latest WNBA news and updates",
schema: z.object({ query: z.string() }),
}
);
const agent = createAgent({
model: "openai:gpt-5.5",
tools: [getLatestNews],
});
const model = new ChatOpenAI({ model: "gpt-5.5" });
const RewrittenQuery = z.object({ query: z.string() });
async function rewriteQuery(state: typeof State.State) {
const systemPrompt = `Rewrite this query to retrieve relevant WNBA information.
The knowledge base contains: team rosters, game results with scores, and player statistics (PPG, RPG, APG).
Focus on specific player names, team names, or stat categories mentioned.`;
const response = await model.withStructuredOutput(RewrittenQuery).invoke([
{ role: "system", content: systemPrompt },
{ role: "user", content: state.question },
]);
return { rewrittenQuery: response.query };
}
async function retrieve(state: typeof State.State) {
const docs = await retriever.invoke(state.rewrittenQuery);
return { documents: docs.map((doc) => doc.pageContent) };
}
async function callAgent(state: typeof State.State) {
const context = state.documents.join("\n\n");
const prompt = `Context:\n${context}\n\nQuestion: ${state.question}`;
const response = await agent.invoke({
messages: [{ role: "user", content: prompt }],
});
return { answer: response.messages.at(-1)?.contentBlocks };
}
const workflow = new StateGraph(State)
.addNode("rewrite", rewriteQuery)
.addNode("retrieve", retrieve)
.addNode("agent", callAgent)
.addEdge(START, "rewrite")
.addEdge("rewrite", "retrieve")
.addEdge("retrieve", "agent")
.addEdge("agent", END)
.compile();
const result = await workflow.invoke({
question: "Who won the 2024 WNBA Championship?",
});
console.log(result.answer);INFO
在生产环境中,请使用持久化的向量数据库,例如 Weaviate、Pinecone 或 MongoDB Atlas,而不是 MemoryVectorStore。参见 所有向量数据库。