DEV Community

matias yoon
matias yoon

Posted on

LangGraph 워크플로우 템플릿 (v17)

LangGraph 워크플로우 템플릿 (v17)

소개

이 가이드는 Python 개발자들이 LangChain/LangGraph를 사용하여 AI 에이전트를 구축할 때 활용할 수 있는 실질적인 워크플로우 템플릿들을 제공합니다. 각 템플릿은 실제 문제를 해결하도록 설계되었으며, $3-$7 범위의 가격으로도 충분히 가치 있는 실용성을 가지고 있습니다.

1. LangGraph 아키텍처 개요

LangGraph는 상태 기반의 워크플로우 시스템으로, 다음과 같은 핵심 구성 요소로 이루어져 있습니다:

  • Nodes: 워크플로우의 각 단계
  • Edges: 노드 간의 전이 조건
  • State: 모든 노드가 접근할 수 있는 공유 상태
  • Checkpointing: 상태를 저장하고 복구하는 기능
from langgraph.graph import StateGraph
from typing import TypedDict, Annotated
import operator

class State(TypedDict):
    messages: Annotated[list, operator.add]

# 그래프 생성
workflow = StateGraph(State)
Enter fullscreen mode Exit fullscreen mode

2. 템플릿 1: 간단한 RAG 에이전트 (Retrieve → Generate → Validate)

이 템플릿은 문서 검색 후 생성 후 유효성 검사를 수행하는 기본적인 RAG 워크플로우입니다.

from langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_openai import ChatOpenAI

class RAGState(TypedDict):
    query: str
    retrieved_docs: list
    generated_answer: str
    validation_result: bool

def retrieve_node(state: RAGState):
    # 문서 검색 로직 (예: FAISS 또는 Pinecone)
    vector_store = FAISS.load_local("vector_store", OpenAIEmbeddings())
    docs = vector_store.similarity_search(state["query"])
    return {"retrieved_docs": docs}

def generate_node(state: RAGState):
    # 검색된 문서를 기반으로 답변 생성
    prompt = PromptTemplate.from_template(
        "문서: {docs}\n질문: {query}\n답변:"
    )
    chain = prompt | ChatOpenAI(model="gpt-4") | StrOutputParser()
    answer = chain.invoke({
        "docs": "\n".join([doc.page_content for doc in state["retrieved_docs"]]),
        "query": state["query"]
    })
    return {"generated_answer": answer}

def validate_node(state: RAGState):
    # 답변 유효성 검사 (예: LLM 기반)
    validation_prompt = PromptTemplate.from_template(
        "질문: {query}\n답변: {answer}\n정확한 답변인가? (예/아니오)"
    )
    validation_chain = validation_prompt | ChatOpenAI(model="gpt-4") | StrOutputParser()
    result = validation_chain.invoke({
        "query": state["query"],
        "answer": state["generated_answer"]
    })
    return {"validation_result": result.strip().lower() == ""}

# 그래프 구성
workflow = StateGraph(RAGState)
workflow.add_node("retrieve", retrieve_node)
workflow.add_node("generate", generate_node)
workflow.add_node("validate", validate_node)

workflow.set_entry_point("retrieve")
workflow.add_edge("retrieve", "generate")
workflow.add_edge("generate", "validate")

# 유효성 검사 결과에 따라 전이
workflow.add_conditional_edges(
    "validate",
    lambda state: "valid" if state["validation_result"] else "invalid",
    {
        "valid": "generate",
        "invalid": "retrieve"
    }
)

# 컴파일 및 실행
app = workflow.compile()
result = app.invoke({"query": "Python의 상속 개념은 무엇인가?"})
Enter fullscreen mode Exit fullscreen mode

3. 템플릿 2: 멀티-도구 에이전트 (Plan → Execute → Observe → Decide)

이 템플릿은 도구 사용 계획을 세우고 실행, 관찰 후 결정을 내리는 에이전트입니다.

from langchain.tools import Tool
from langchain_core.messages import HumanMessage

class ToolAgentState(TypedDict):
    plan: str
    execution_results: list
    observation: str
    decision: str
    tools: list

def plan_node(state: ToolAgentState):
    # 실행 계획 생성
    planning_prompt = PromptTemplate.from_template(
        "사용자의 요청: {request}\n도구 목록: {tools}\n계획 생성:"
    )
    plan_chain = planning_prompt | ChatOpenAI(model="gpt-4") | StrOutputParser()
    plan = plan_chain.invoke({
        "request": state["request"],
        "tools": [tool.name for tool in state["tools"]]
    })
    return {"plan": plan}

def execute_node(state: ToolAgentState):
    # 계획에 따라 도구 실행
    results = []
    for tool in state["tools"]:
        if tool.name in state["plan"]:
            try:
                result = tool.run(state["request"])
                results.append({"tool": tool.name, "result": result})
            except Exception as e:
                results.append({"tool": tool.name, "error": str(e)})
    return {"execution_results": results}

def observe_node(state: ToolAgentState):
    # 실행 결과 관찰
    observation_prompt = PromptTemplate.from_template(
        "계획: {plan}\n실행 결과: {results}\n관찰:"
    )
    obs_chain = observation_prompt | ChatOpenAI(model="gpt-4") | StrOutputParser()
    observation = obs_chain.invoke({
        "plan": state["plan"],
        "results": str(state["execution_results"])
    })
    return {"observation": observation}

def decide_node(state: ToolAgentState):
    # 결정 생성
    decision_prompt = PromptTemplate.from_template(
        "관찰 내용: {observation}\n최종 결정:"
    )
    dec_chain = decision_prompt | ChatOpenAI(model="gpt-4") | StrOutputParser()
    decision = dec_chain.invoke({"observation": state["observation"]})
    return {"decision": decision}

# 도구 정의
tools = [
    Tool(name="search_web", func=lambda x: f"웹 검색 결과: {x}"),
    Tool(name="calculate", func=lambda x: f"계산 결과: {eval(x)}"),
    Tool(name="lookup_info", func=lambda x: f"정보 조회: {x}")
]

# 그래프 구성
workflow = StateGraph(ToolAgentState)
workflow.add_node("plan", plan_node)
workflow.add_node("execute", execute_node)
workflow.add_node("observe", observe_node)
workflow.add_node("decide", decide_node)

workflow.set_entry_point("plan")
workflow.add_edge("plan", "execute")
workflow.add_edge("execute", "observe")
workflow.add_edge("observe", "decide")

app = workflow.compile()
result = app.invoke({
    "request": "3+5*2의 결과는?",
    "tools": tools
})
Enter fullscreen mode Exit fullscreen mode

4. 템플릿 3: 인간-인터페이스 워크플로우 (Pause → Review → Continue)

이 템플릿은 인간의 검토를 포함한 워크플로우입니다.


python
import asyncio
from datetime import datetime

class HumanLoopState(TypedDict):
    task: str
    generated_output: str
    human_review: str
    final_output: str
    review_status: str  # pending, approved, rejected

def generate_node(state: HumanLoopState):
    # 작업 생성
    prompt = PromptTemplate.from_template("작업 설명: {task}\n생성된 내용:")
    chain = prompt | ChatOpenAI(model="gpt-4") | StrOutputParser()
    output = chain.invoke({"task": state["task"]})
    return {"generated_output": output}

def human_review_node(state: HumanLoopState):
    # 인간 검토 (실제로는 외부 시스템 또는 사용자 입력 필요)
    # 여기서는 가상의 검토 결과를 반환
    review_prompt = PromptTemplate.from_template(
        "작업: {task}\n생성된 내용: {output}\n검토 요청:"
    )
    review_chain = review_prompt | ChatOpenAI(model="gpt-4") | StrOutputParser()
    review = review_chain.invoke({
        "task": state["task"],
        "output": state["generated_output"]
    })

    # 검토 상태를 설정 (실제 구현에서는 사용자 입력 기다림)
    status = "approved"  # 또는 "rejected"
    return {
        "human_review": review,
        "review_status": status
    }

def finalize_node(state: HumanLoopState):
    # 최종 결과 생성
    if state["review_status"] == "approved":
        return {"final_output": state["generated_output"]}
    else:
        # 재생성 로직
        return {"final_output": "재작성된 내용"}

# 그래프 구성
workflow = StateGraph(HumanLoopState)
workflow.add_node("generate", generate_node)
workflow.add_node("human_review", human_review_node)
workflow.add_node("finalize", finalize_node)

workflow.set_entry_point("generate")
workflow.add_edge("generate

---

📥 **Get the full guide on Gumroad**: https://gumroad.com/l/auto ($5)
Enter fullscreen mode Exit fullscreen mode

Top comments (0)