LangGraph Node & Edge ์ค๊ณ ์ค์ ํ
์ข์ ์ํฌํ๋ก์ฐ๋ ์ข์ ๋ ธ๋์์ ์์๋๋ค
LangGraph์ ๋ฌธ๋ฒ ์์ฒด๋ ์ด๋ ต์ง ์๋ค. ํต์ฌ์ โ์ข์ ํ์ง์ ๋ ธ๋โ ๋ฅผ ์ด๋ป๊ฒ ์ค๊ณํ๋๋์ ์๋ค. Node๋ ์ต๋ํ ์ธ๋ถํํด์ ์ค๊ณํ๋ ๊ฒ์ด ์ ๋ฆฌํ๋ค.
์๋ฅผ ๋ค์ด, ์ง๋ฌธ ์ดํด, ๋ฌธ์ ๊ฒ์, ๋ต๋ณ ์์ฑ, ๋ต๋ณ ํ๊ฐ ๋ฅผ ํ๋์ ๋
ธ๋์์ ์ฒ๋ฆฌํ๋ ๊ฒ๋ณด๋ค, ๊ฐ task๋ฅผ ๋ณ๋ ๋
ธ๋๋ก ๋ถ๋ฆฌํ๋ฉด ๋๋ฒ๊น
๋ ์ฌ์์ง๊ณ , ํ๋ฆ ์ ์ด ๋ฐ ํ๋๋ ๋ ์ ๋ฐํด์ง๋ค.
**LangGraph์์๋ โ์๊ฒ ์ชผ๊ฐ Nodeโ๊ฐ ์ต๊ณ ์ ๋ฌด๊ธฐ๋ค.
โ ๊ธฐ๋ณธ ์์ : ๋ฌธ์ ๊ฒ์ ๋ ธ๋ ๋ง๋ค๊ธฐ
def retrieve_document(state: GraphState) -> GraphState:
retrieved_docs = pdf_retriever.invoke(state["question"])
return GraphState(context=format_docs(retrieved_docs))- ์
๋ ฅ๋
GraphState, ์ถ๋ ฅ๋GraphState - context์ ํ์ํ ์ ๋ณด๋ฅผ ์ ์ฅํ์ฌ ๋ค์ ๋ ธ๋์ ๋๊ธด๋ค
๐ State ํ์ ๊ตฌ์ฑ ์ ์ฃผ์ํ ์
from typing import TypedDict, Annotated, List
from langchain_core.documents import Document
from operator import add
class GraphState(TypedDict):
context: Annotated[List[Document], add]
answer: Annotated[List[Document], add]
# question: Annotated[str, add] โ โ ๋ฌธ์์ด์ add Reducer ์ฌ์ฉ ๋ถ๊ฐ
question: Annotated[str, "user_question"]โ ๏ธ
addReducer๋ ๋ฌธ์์ด์๋ ์ ์ฉํ ์ ์๋ค.
๐ ์ถ์ฒ
from langgraph.graph.message import add_messagesoperator.add๋์add_messages๋ฅผ ์ฐ๋ ๊ฒ์ด ๋ช ์์ ์ด๊ณ ์์ ํ๋ค.
๐ง ๋ ธ๋ ๋ฐํ ๋ฐฉ์: ์ด๋ค ์คํ์ผ์ ์ธ๊น?
LangGraph ํํ ๋ฆฌ์ผ์์ ๋ง์ด ๋ณด์ด๋ ๋ ๊ฐ์ง ๋ฐฉ์์ด ์๋ค.
โ ๋ฐฉ์ 1: ๋์ ๋๋ฆฌ ๋ฐํ
def retrieve(state: GraphState) -> GraphState:
documents = "๊ฒ์๋ ๋ฌธ์"
return {"context": documents}โ ๋ฐฉ์ 2: GraphState ํ์ ๋ฐํ
def retrieve(state: GraphState) -> GraphState:
documents = "๊ฒ์๋ ๋ฌธ์"
return GraphState(context=documents)๋ ๋ฐฉ์ ๋ชจ๋ ๊ธฐ๋ฅ์ ์ผ๋ก ๋์ผํ์ง๋ง,
ํ์ ํํ + ์ผ๊ด์ฑ ์๋ ์ฝ๋ ์ ์ง๋ฅผ ์ํด 2๋ฒ ๋ฐฉ์ ์ฌ์ฉ์ ๊ถ์ฅํ๋ค.
โ๏ธ ๊ทธ๋ํ ์์ฑ ๋ฐฉ์: ์ด๋ค ๊ฒ ๋ ์ข์๊น?
LangGraph์์๋ ๋ ๊ฐ์ง ๋ฐฉ์์ผ๋ก ๊ทธ๋ํ๋ฅผ ์ ์ํ ์ ์๋ค.
๐ ๋ฐฉ์ 1: START ๋ช
์
from langgraph.graph import START, StateGraph
workflow = StateGraph(state_schema=GraphState)
workflow.add_node("retrieve", retrieve)
workflow.add_edge(START, "retrieve")๐ ๋ฐฉ์ 2: set_entry_point ์ฌ์ฉ
from langgraph.graph import StateGraph
workflow = StateGraph(state_schema=GraphState)
workflow.add("retrieve", retrieve)
workflow.set_entry_point("retrieve")โ ๊ธฐ๋ฅ์ ์ผ๋ก๋ ๋์ผํ๋ฉฐ, ๋ ์ค ์ด๋ค ๊ฑธ ์ฌ์ฉํด๋ ๊ฒฐ๊ณผ๋ ๊ฐ๋ค.
โ ์ทจํฅ ๋๋ ์ฝ๋ ์คํ์ผ์ ๋ง์ถฐ ์ ํํ๋ฉด ๋๋ค.
๐ ์ค๊ณ ํ: ๊ทธ๋ํ ๊ตฌ์กฐ๋ ๋จผ์ ์ข ์ด์ ๊ทธ๋ ค๋ผ
์ง์ ๊ตฌํ์ ๋ค์ด๊ฐ๊ธฐ ์ ์,
์ง๋ฌธ ํ๋ฆ, ๋ถ๊ธฐ ์กฐ๊ฑด, ๋ ธ๋ ์์ ๋ฑ์ ๋ฉ๋ชจ์ฅ์ด๋ ๋ค์ด์ด๊ทธ๋จ ํด์ ๊ทธ๋ ค๋ณด๋ ๊ฒ์ ๊ฐ๋ ฅ ์ถ์ฒํ๋ค.
- ๋ถํ์ํ ๋ถ๊ธฐ ์ ๊ฑฐ
- ๋ณ๋ ฌ ์ฒ๋ฆฌ ๊ฐ๋ฅํ ์ง์ ํ์ธ
- ๋์ค์ LangGraph ์๊ฐํ ๊ธฐ๋ฅ๊ณผ 1:1 ๋งคํํ๊ธฐ ์ฌ์
๐ RAG ์ฌ์ฉ ์ ์ถ๊ฐ ํ: ๋ฌธ์ ํฌ๋งท ์ฒ๋ฆฌ
LLM์ List[Document] ๊ฐ์ฒด๋ฅผ ๋๊ธฐ๊ธฐ๋ณด๋ค๋,
๋ฌธ์๋ค์ ํฌ๋งทํ ํด์ ํ๋์ ๋ฌธ์์ด๋ก ๋ณํํ๋ ๊ฒ์ด ์ฑ๋ฅ์ ํจ์ฌ ์ ๋ฆฌํ๋ค.
formatted_context = format_docs(retrieved_docs)๐ฏ ์ด์
- LLM์ด ์ดํดํ๊ธฐ ์ฌ์ด ํํ๋ก ์ ์
- ๋ถํ์ํ
metadata์ ๊ฑฐ - ๋ฌธ์ ๊ฒฝ๊ณ์ ํ๊ทธ ์ถ๊ฐ (์:
### ๋ฌธ์ 1 ###,<document></document>๋ฑ)