๋ฐ์ํ
๐ง LangChain๊ณผ LangGraph๋ฅผ ํ์ฉํ AI ์์ด์ ํธ ๊ตฌํ ๊ฐ์ด๋
๐งฉ ์๋๋ฆฌ์ค
"๊ณ ๊ฐ ๋ฐ์ดํฐ์์ VIP ๊ณ ๊ฐ์ ์ ๋ณํ๊ณ , ๊ฐ ๊ณ ๊ฐ์๊ฒ ๋ง์ถค ์ด๋ฉ์ผ์ ์์ฑํ ๋ค, ์ด๋ฅผ ๊ฒํ ํ๊ณ ๋ฐ์ก ๋๊ธฐ ๋ฆฌ์คํธ์ ์ฌ๋ ค๋ผ."
โ ์ ์ฒด ๊ตฌ์ฑ ํ๋ฆ
[1] Goal ์ค์
↓
[2] LLM Reasoning → ์ด๋ค ๊ณ ๊ฐ์ด VIP์ธ์ง ํ๋จ
↓
[3] Tool ์ฌ์ฉ → Google Sheets์์ ๊ณ ๊ฐ ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ
↓
[4] Tool ์ฌ์ฉ → OpenAI๋ก ์ด๋ฉ์ผ ์์ฑ
↓
[5] Tool ์ฌ์ฉ → ์ด๋ฉ์ผ ํ์ง ๊ฒํ (Self-critique)
↓
[6] ์ ์ฅ ๋๋ ์ ์ก ์ค๋น
๐ ๏ธ ์ฌ์ฉ ๊ธฐ์
- LangChain (์์ด์ ํธ ํ๋ ์์ํฌ)
- OpenAI GPT-4 API
- Google Sheets API (๋๋ ์์ CSV)
- @tool ๋ฐ์ฝ๋ ์ดํฐ๋ฅผ ํตํ ํจ์ ๋ฑ๋ก
- Python
๐ง๐ป ์์ ์ฝ๋ (LangChain Agent)
from langchain.agents import initialize_agent, Tool
from langchain.agents.agent_types import AgentType
from langchain.chat_models import ChatOpenAI
# Step 1: ๋๊ตฌ ์ ์
def get_vip_customers():
# ์์ : 100๋ง ์ ์ด์ ๊ตฌ๋งค ๊ณ ๊ฐ๋ง ์ถ์ถ
return ["ํ๊ธธ๋", "๊น์ฒ ์"]
def write_email(name: str) -> str:
return f"{name}๋ ์๋
ํ์ธ์. VIP ๊ณ ๊ฐ๋๊ป ๊ฐ์ฌ ์ธ์ฌ ๋๋ฆฝ๋๋ค!"
def review_email(content: str) -> str:
# ๊ฐ๋จํ ์์: ๋๋ฌด ์งง์ผ๋ฉด ์์ ๊ถ์ฅ
if len(content) < 50:
return content + " ๋ค์ ํ๋ฒ ๊ฐ์ฌ๋๋ฆฝ๋๋ค."
return content
tools = [
Tool(name="Get VIP Customers", func=get_vip_customers, description="VIP ๊ณ ๊ฐ ๋ฆฌ์คํธ๋ฅผ ๊ฐ์ ธ์จ๋ค."),
Tool(name="Write Email", func=write_email, description="๊ณ ๊ฐ ์ด๋ฆ์ผ๋ก ์ด๋ฉ์ผ์ ์์ฑํ๋ค."),
Tool(name="Review Email", func=review_email, description="์ด๋ฉ์ผ ๋ด์ฉ์ ๊ฒํ ํ๊ณ ๊ฐ์ ํ๋ค."),
]
# Step 2: ์์ด์ ํธ ์ด๊ธฐํ
llm = ChatOpenAI(model="gpt-4", temperature=0)
agent_executor = initialize_agent(
tools,
llm,
agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
verbose=True,
)
# Step 3: ๋ชฉํ ์ง์
agent_executor.run("VIP ๊ณ ๊ฐ์๊ฒ ๋ณด๋ผ ๊ฐ์ฌ ์ด๋ฉ์ผ์ ์์ฑํ๊ณ ๊ฒํ ํด์ค.")
๐ ์ค๋ช ์์ฝ
์ปดํฌ๋ํธ | ์ค๋ช |
---|---|
Tool | LLM์ด ์ฌ์ฉํ ์ ์๋๋ก ๋ฑ๋ก๋ ๊ธฐ๋ฅ (ex. DB ์กฐํ, ์ด๋ฉ์ผ ์์ฑ) |
initialize_agent | ํด๊ณผ LLM์ ์ฐ๊ฒฐํ๋ ๊ตฌ์ฑ ํจ์ |
ZERO_SHOT_REACT_DESCRIPTION | ํด ์ค๋ช ๋ง์ผ๋ก ํ๋์ ๊ฒฐ์ ํ๋ ์์ด์ ํธ ํ์ |
agent_executor.run() | ์ค์ ์คํ – ๋ชฉํ(Goal)๋ฅผ LLM์ด ์ดํดํ๊ณ ํด์ ์ ํ & ์คํ |
๐ง LangGraph ๊ธฐ๋ฐ FSM AI ์์ด์ ํธ ๊ตฌ์ฑ ์์
๐ก ์๋๋ฆฌ์ค
"๊ณ ๊ฐ ๋ฐ์ดํฐ์์ VIP ๊ณ ๊ฐ์ ์ ๋ณํ๊ณ ,
๊ฐ ๊ณ ๊ฐ์๊ฒ ๋ง์ถคํ ์ด๋ฉ์ผ์ ์์ฑํ ๋ค,
๊ทธ ์ด๋ฉ์ผ์ AI๊ฐ ๋ฆฌ๋ทฐํ๊ณ ,
์ต์ข
์น์ธ๋ ์ด๋ฉ์ผ๋ง ๋ฐ์ก ๋๊ธฐ ๋ฆฌ์คํธ์ ์ ์ฅํ๋ค."
๋๊ตฌ๊ฐ ๋ง์์ง๊ณ , ๋จ๊ณ๋ณ๋ก ๊ฒฐ์ ํ๋ฆ์ด ๋ถ๊ธฐ๋๋ฏ๋ก FSM ๊ตฌ์กฐ๊ฐ ์ ํฉํฉ๋๋ค.
๐ ๊ตฌ์ฑ ๊ฐ์
LangGraph๋ฅผ ์ฌ์ฉํ๋ฉด FSM์ฒ๋ผ ๋ค์๊ณผ ๊ฐ์ ํํ๋ก ๊ตฌ์ฑ๋ฉ๋๋ค:
[Start] → [GetVIPs] → [GenerateEmail] → [ReviewEmail]
โ๏ธ โ๏ธ โ๏ธ ↓
[Error] [Retry] [Done] ← [RewriteEmail]
๐ ๊ธฐ์ ์คํ
- LangGraph – ์ํ ๊ทธ๋ํ ์ ์
- ChatOpenAI – Reasoning ๋ด๋น
- @tool ๋๋ LangChain Tool – ์ธ๋ถ ๊ธฐ๋ฅ ํธ์ถ
- Python – FSM ์ ์ ๋ฐ ์คํ
๐ง๐ป ์์ ์ฝ๋: LangGraph FSM ๊ตฌ์ฑ
from langgraph.graph import StateGraph, END
from langchain.chat_models import ChatOpenAI
from typing import TypedDict, List
# ์ํ ์ ์
class AgentState(TypedDict):
customers: List[str]
email: str
approved: bool
# LLM ์ด๊ธฐํ
llm = ChatOpenAI(model="gpt-4", temperature=0)
# ์ํ ์ฒ๋ฆฌ ํจ์๋ค
def fetch_vips(state):
# ์์: DB๋ API์์ VIP ๊ณ ๊ฐ ์ถ์ถ
return {"customers": ["ํ๊ธธ๋", "๊น์ํฌ"]}
def generate_email(state):
name = state["customers"][0]
email = f"{name}๋ ์๋
ํ์ธ์. VIP ๊ฐ์ฌ๋๋ฆฝ๋๋ค!"
return {"email": email}
def review_email(state):
email = state["email"]
if "๊ฐ์ฌ" not in email:
return {"approved": False}
return {"approved": True}
def rewrite_email(state):
email = state["email"]
return {"email": email + " ๋ค์ ํ๋ฒ ๊ฐ์ฌ๋๋ฆฝ๋๋ค!"}
# ์ํ ๊ทธ๋ํ ์ ์
workflow = StateGraph(AgentState)
workflow.add_node("GetVIPs", fetch_vips)
workflow.add_node("GenerateEmail", generate_email)
workflow.add_node("ReviewEmail", review_email)
workflow.add_node("RewriteEmail", rewrite_email)
# ์ํ ์ ์ด ์ ์
workflow.set_entry_point("GetVIPs")
workflow.add_edge("GetVIPs", "GenerateEmail")
workflow.add_edge("GenerateEmail", "ReviewEmail")
workflow.add_conditional_edges(
"ReviewEmail",
{
"approved": END,
"default": "RewriteEmail"
}
)
workflow.add_edge("RewriteEmail", "ReviewEmail")
# ์คํ
app = workflow.compile()
result = app.invoke({})
print(result)
๐งฉ ๊ตฌ์กฐ ์ค๋ช
๊ตฌ์ฑ ์์ | ์ญํ |
---|---|
StateGraph() | ์ ์ฒด ์์ด์ ํธ ํ๋ฆ ์ ์ |
add_node() | ๊ฐ๊ฐ์ ํจ์(๋ ธ๋)๋ฅผ FSM์ ์ถ๊ฐ |
add_edge() | ๋ค์ ์ํ๋ก์ ์ ์ด ์ ์ |
add_conditional_edges() | ์ํ ์กฐ๊ฑด์ ๋ฐ๋ผ ๋ถ๊ธฐ |
invoke() | ๊ทธ๋ํ ์คํ (state ์ ๋ ฅ ๊ฐ๋ฅ) |
โ ์ฌ์ฉ ์ฅ์
- ๋จ๊ณ๋ณ ์ ์ด/๋ถ๊ธฐ/์ฌ์๋ ๋ก์ง์ด ๋ช ํํ๊ฒ ๋ณด์
- ์์ด์ ํธ์ ๊ฐ ํ๋ ์ํ๊ฐ ์ถ์ ๊ฐ๋ฅ
- ์ถํ์ Tool ์ฌ์ฉ ์ ์ฆ๊ฐ ์ ํ์ฅ์ฑ ์ฐ์
๋ฐ์ํ