LangGraph 개발을 위한 LangSmith 설정LangSmith에 가입하여 LangGraph 프로젝트의 문제를 신속하게 파악하고 성능을 개선하세요. LangSmith를 사용하면 트레이스 데이터를 활용하여 LangGraph로 구축한 LLM 앱을 디버깅, 테스트 및 모니터링할 수 있습니다 — 시작하는 방법에 대한 자세한 내용은 여기에서 확인하세요.
서브그래프를 구현하는 간단한 방법은 다른 그래프의 노드 내부에서 그래프를 호출하는 것입니다. 이 경우 서브그래프는 부모 그래프와 완전히 다른 스키마를 가질 수 있습니다(공유 키 없음). 예를 들어, 멀티 에이전트 시스템의 각 에이전트에 대해 비공개 메시지 히스토리를 유지하고 싶을 수 있습니다.애플리케이션에서 이러한 경우에 해당한다면, 서브그래프를 호출하는 노드 함수를 정의해야 합니다. 이 함수는 서브그래프를 호출하기 전에 입력(부모) 상태를 서브그래프 상태로 변환하고, 결과를 다시 부모 상태로 변환한 후 노드에서 상태 업데이트를 반환해야 합니다.
Copy
import { StateGraph, START } from "@langchain/langgraph";import * as z from "zod";const SubgraphState = z.object({ bar: z.string(),});// Subgraphconst subgraphBuilder = new StateGraph(SubgraphState) .addNode("subgraphNode1", (state) => { return { bar: "hi! " + state.bar }; }) .addEdge(START, "subgraphNode1");const subgraph = subgraphBuilder.compile();// Parent graphconst State = z.object({ foo: z.string(),});// Transform the state to the subgraph state and backconst builder = new StateGraph(State) .addNode("node1", async (state) => { const subgraphOutput = await subgraph.invoke({ bar: state.foo }); return { foo: subgraphOutput.bar }; }) .addEdge(START, "node1");const graph = builder.compile();
전체 예제: 다른 상태 스키마
Copy
import { StateGraph, START } from "@langchain/langgraph";import * as z from "zod";// Define subgraphconst SubgraphState = z.object({ // note that none of these keys are shared with the parent graph state bar: z.string(), baz: z.string(),});const subgraphBuilder = new StateGraph(SubgraphState) .addNode("subgraphNode1", (state) => { return { baz: "baz" }; }) .addNode("subgraphNode2", (state) => { return { bar: state.bar + state.baz }; }) .addEdge(START, "subgraphNode1") .addEdge("subgraphNode1", "subgraphNode2");const subgraph = subgraphBuilder.compile();// Define parent graphconst ParentState = z.object({ foo: z.string(),});const builder = new StateGraph(ParentState) .addNode("node1", (state) => { return { foo: "hi! " + state.foo }; }) .addNode("node2", async (state) => { const response = await subgraph.invoke({ bar: state.foo }); // (1)! return { foo: response.bar }; // (2)! }) .addEdge(START, "node1") .addEdge("node1", "node2");const graph = builder.compile();for await (const chunk of await graph.stream( { foo: "foo" }, { subgraphs: true })) { console.log(chunk);}
부모 그래프와 서브그래프가 스키마의 공유 상태 키(채널)를 통해 통신할 수 있는 경우, 그래프를 다른 그래프의 노드로 추가할 수 있습니다. 예를 들어, 멀티 에이전트 시스템에서는 에이전트들이 종종 공유된 메시지 키를 통해 통신합니다.서브그래프가 부모 그래프와 상태 키를 공유하는 경우, 다음 단계에 따라 그래프에 추가할 수 있습니다:
서브그래프 워크플로우(아래 예제의 subgraphBuilder)를 정의하고 컴파일합니다
부모 그래프 워크플로우를 정의할 때 .addNode 메서드에 컴파일된 서브그래프를 전달합니다
Copy
import { StateGraph, START } from "@langchain/langgraph";import * as z from "zod";const State = z.object({ foo: z.string(),});// Subgraphconst subgraphBuilder = new StateGraph(State) .addNode("subgraphNode1", (state) => { return { foo: "hi! " + state.foo }; }) .addEdge(START, "subgraphNode1");const subgraph = subgraphBuilder.compile();// Parent graphconst builder = new StateGraph(State) .addNode("node1", subgraph) .addEdge(START, "node1");const graph = builder.compile();
전체 예제: 공유 상태 스키마
Copy
import { StateGraph, START } from "@langchain/langgraph";import * as z from "zod";// Define subgraphconst SubgraphState = z.object({ foo: z.string(), // (1)! bar: z.string(), // (2)!});const subgraphBuilder = new StateGraph(SubgraphState) .addNode("subgraphNode1", (state) => { return { bar: "bar" }; }) .addNode("subgraphNode2", (state) => { // note that this node is using a state key ('bar') that is only available in the subgraph // and is sending update on the shared state key ('foo') return { foo: state.foo + state.bar }; }) .addEdge(START, "subgraphNode1") .addEdge("subgraphNode1", "subgraphNode2");const subgraph = subgraphBuilder.compile();// Define parent graphconst ParentState = z.object({ foo: z.string(),});const builder = new StateGraph(ParentState) .addNode("node1", (state) => { return { foo: "hi! " + state.foo }; }) .addNode("node2", subgraph) .addEdge(START, "node1") .addEdge("node1", "node2");const graph = builder.compile();for await (const chunk of await graph.stream({ foo: "foo" })) { console.log(chunk);}
영속성을 활성화하면, 적절한 메서드를 통해 그래프 상태를 검사(체크포인트)할 수 있습니다. 서브그래프 상태를 보려면 subgraphs 옵션을 사용할 수 있습니다.graph.getState(config)를 통해 그래프 상태를 검사할 수 있습니다. 서브그래프 상태를 보려면 graph.getState(config, { subgraphs: true })를 사용할 수 있습니다.
중단되었을 때만 사용 가능
서브그래프 상태는 서브그래프가 중단되었을 때만 볼 수 있습니다. 그래프를 재개하면 서브그래프 상태에 액세스할 수 없습니다.
중단된 서브그래프 상태 보기
Copy
import { StateGraph, START, MemorySaver, interrupt, Command } from "@langchain/langgraph";import * as z from "zod";const State = z.object({ foo: z.string(),});// Subgraphconst subgraphBuilder = new StateGraph(State) .addNode("subgraphNode1", (state) => { const value = interrupt("Provide value:"); return { foo: state.foo + value }; }) .addEdge(START, "subgraphNode1");const subgraph = subgraphBuilder.compile();// Parent graphconst builder = new StateGraph(State) .addNode("node1", subgraph) .addEdge(START, "node1");const checkpointer = new MemorySaver();const graph = builder.compile({ checkpointer });const config = { configurable: { thread_id: "1" } };await graph.invoke({ foo: "" }, config);const parentState = await graph.getState(config);const subgraphState = (await graph.getState(config, { subgraphs: true })).tasks[0].state; // (1)!// resume the subgraphawait graph.invoke(new Command({ resume: "bar" }), config);