Skip to content

Instantly share code, notes, and snippets.

@anpigon
Last active September 28, 2024 01:45
Show Gist options
  • Select an option

  • Save anpigon/717df1cba9329260b0e1f3c9b4c025e3 to your computer and use it in GitHub Desktop.

Select an option

Save anpigon/717df1cba9329260b0e1f3c9b4c025e3 to your computer and use it in GitHub Desktop.
Langgraph 기본적인 그래프 만들어보기
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 38,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 38,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import os\n",
"from dotenv import load_dotenv\n",
"\n",
"load_dotenv()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## StateGraph 상태 만들기\n"
]
},
{
"cell_type": "code",
"execution_count": 39,
"metadata": {},
"outputs": [],
"source": [
"import operator\n",
"from typing import TypedDict, Annotated\n",
"from langgraph.graph import StateGraph, START, END"
]
},
{
"cell_type": "code",
"execution_count": 40,
"metadata": {},
"outputs": [],
"source": [
"class State(TypedDict):\n",
" \"\"\"StateGraph의 상태를 정의하는 클래스\"\"\"\n",
"\n",
" counter: int\n",
" alphabet: Annotated[list[str], operator.add]\n",
"\n",
"\n",
"graph_builder = StateGraph(State)"
]
},
{
"cell_type": "code",
"execution_count": 41,
"metadata": {},
"outputs": [],
"source": [
"# 노드 정의\n",
"def node_a(state: State):\n",
" state['counter'] += 1\n",
" state['alphabet'] = [\"hello\"]\n",
" return state"
]
},
{
"cell_type": "code",
"execution_count": 42,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<langgraph.graph.state.StateGraph at 0x12ec8d850>"
]
},
"execution_count": 42,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 노드 추가\n",
"graph_builder.add_node(\"chat_bot\", node_a)"
]
},
{
"cell_type": "code",
"execution_count": 43,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<langgraph.graph.state.StateGraph at 0x12ec8d850>"
]
},
"execution_count": 43,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 노드 연결\n",
"graph_builder.add_edge(START, \"chat_bot\")\n",
"graph_builder.add_edge(\"chat_bot\", END)"
]
},
{
"cell_type": "code",
"execution_count": 44,
"metadata": {},
"outputs": [],
"source": [
"graph = graph_builder.compile()"
]
},
{
"cell_type": "code",
"execution_count": 45,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Graph(nodes={'__start__': Node(id='__start__', name='__start__', data=<class 'pydantic.v1.main.LangGraphInput'>, metadata=None), 'chat_bot': Node(id='chat_bot', name='chat_bot', data=chat_bot(tags=None, recurse=True, func_accepts_config=False, func_accepts={'writer': False}), metadata=None), '__end__': Node(id='__end__', name='__end__', data=<class 'pydantic.v1.main.LangGraphOutput'>, metadata=None)}, edges=[Edge(source='__start__', target='chat_bot', data=None, conditional=False), Edge(source='chat_bot', target='__end__', data=None, conditional=False)])"
]
},
"execution_count": 45,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"graph.get_graph()"
]
},
{
"cell_type": "code",
"execution_count": 46,
"metadata": {},
"outputs": [
{
"data": {
"image/jpeg": "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",
"text/plain": [
"<IPython.core.display.Image object>"
]
},
"execution_count": 46,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from IPython.display import Image\n",
"\n",
"Image(graph.get_graph().draw_mermaid_png())"
]
},
{
"cell_type": "code",
"execution_count": 47,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'counter': 1, 'alphabet': ['hello']}\n",
"{'counter': 2, 'alphabet': ['hello', 'hello']}\n",
"{'counter': 3, 'alphabet': ['hello', 'hello', 'hello']}\n"
]
}
],
"source": [
"initial_state: State = {\"counter\": 0, \"alphabet\": []}\n",
"\n",
"state = initial_state\n",
"for _ in range(3):\n",
" state = graph.invoke(state)\n",
" print(state)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Message를 담는 그래프 만들기"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"from typing import TypedDict, Annotated\n",
"\n",
"from langgraph.graph import StateGraph, START, END\n",
"from langchain_google_genai import ChatGoogleGenerativeAI\n",
"from typing_extensions import TypedDict\n",
"\n",
"from langgraph.graph import StateGraph\n",
"from langgraph.graph.message import add_messages\n",
"\n",
"from langchain_core.messages import ChatMessage"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"class State(TypedDict):\n",
" \"\"\"State of the chat.\"\"\"\n",
" messages: Annotated[list[ChatMessage], add_messages]"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
"# 상태 그래프(State Graph) 생성\n",
"graph_builder = StateGraph(State)"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [],
"source": [
"# LLM 생성\n",
"llm = ChatGoogleGenerativeAI(model=\"gemini-1.5-flash\")"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [],
"source": [
"def chatbot(state: State):\n",
" answer = llm.invoke(state[\"messages\"])\n",
" return {\"messages\": [answer]}"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [],
"source": [
"graph_builder.add_node(\"chatbot\", chatbot)\n",
"graph_builder.set_entry_point(\"chatbot\") # add_edge(START, \"chatbot\")\n",
"graph_builder.set_finish_point(\"chatbot\") # add_edge(\"chatbot\", END)\n",
"\n",
"graph = graph_builder.compile()\n"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"data": {
"image/jpeg": "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",
"text/plain": [
"<IPython.core.display.Image object>"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from IPython import display\n",
"\n",
"display.Image(graph.get_graph().draw_mermaid_png())"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"User: 안녕\n",
"Chatbot: 안녕하세요! 무엇을 도와드릴까요? \n",
"\n",
"User: 1+1은 뭘까?\n",
"Chatbot: 1 + 1은 2입니다. \n",
"\n",
"User: 잘가~\n",
"Chatbot: 안녕히 가세요! 다음에 또 만나요! \n",
"\n",
"User: bye\n",
"Chatbot: Bye! It was nice talking to you. Have a great day! \n",
"\n",
"Chatbot: Bye!\n"
]
}
],
"source": [
"while True:\n",
" user_input = input(\"User: \")\n",
" if user_input.lower() in [\"exit\", \"quit\", \"q\"]:\n",
" print(\"Chatbot: Bye!\")\n",
" break\n",
"\n",
" print(f\"User: {user_input}\")\n",
" for event in graph.stream({\"messages\": {\"role\": \"user\", \"content\": user_input}}):\n",
" for value in event.values():\n",
" print(f\"Chatbot: {value.get('messages')[-1].content}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Langgraph의 MessageState 사용하기\n",
"\n",
"랭그래프에서 제공하는 MessageState는 단순한 챗봇 구현에 사용할 수 있다."
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {},
"outputs": [],
"source": [
"from typing import TypedDict\n",
"\n",
"from langgraph.graph import StateGraph\n",
"from langchain_google_genai import ChatGoogleGenerativeAI\n",
"\n",
"from langgraph.graph import StateGraph, MessagesState\n",
"from langgraph.graph.message import add_messages\n",
"\n",
"\n",
"graph_builder = StateGraph(MessagesState)\n",
"\n",
"llm = ChatGoogleGenerativeAI(model=\"gemini-1.5-flash\")\n",
"\n",
"def chatbot(state: State):\n",
" return {\"messages\": [llm.invoke(state[\"messages\"])]}\n",
"\n",
"graph_builder.add_node(\"chatbot\", chatbot)\n",
"graph_builder.set_entry_point(\"chatbot\") \n",
"graph_builder.set_finish_point(\"chatbot\") \n",
"\n",
"graph = graph_builder.compile()"
]
},
{
"cell_type": "code",
"execution_count": 66,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'messages': [HumanMessage(content='안녕하세요!', additional_kwargs={}, response_metadata={}, id='62c825ff-e6a2-43ef-8abe-69bbb4577841'),\n",
" AIMessage(content='안녕하세요! 무엇을 도와드릴까요? \\n', additional_kwargs={}, response_metadata={'prompt_feedback': {'block_reason': 0, 'safety_ratings': []}, 'finish_reason': 'STOP', 'safety_ratings': [{'category': 'HARM_CATEGORY_SEXUALLY_EXPLICIT', 'probability': 'NEGLIGIBLE', 'blocked': False}, {'category': 'HARM_CATEGORY_HATE_SPEECH', 'probability': 'NEGLIGIBLE', 'blocked': False}, {'category': 'HARM_CATEGORY_HARASSMENT', 'probability': 'NEGLIGIBLE', 'blocked': False}, {'category': 'HARM_CATEGORY_DANGEROUS_CONTENT', 'probability': 'NEGLIGIBLE', 'blocked': False}]}, id='run-02dc7bd2-071e-487a-b8a8-11dbc02c7eca-0', usage_metadata={'input_tokens': 5, 'output_tokens': 14, 'total_tokens': 19})],\n",
" 'counter': 1}"
]
},
"execution_count": 66,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from langchain_core.messages import HumanMessage\n",
"\n",
"# TypedDict 대신 MessagesState를 상속하여 새로운 State를 만들어보자\n",
"class State(MessagesState):\n",
" counter: int = 0\n",
"\n",
"graph_builder = StateGraph(State)\n",
"\n",
"llm = ChatGoogleGenerativeAI(model=\"gemini-1.5-flash\")\n",
"\n",
"def chatbot(state: State):\n",
" return {\n",
" 'counter': state.get('counter', 0) + 1,\n",
" 'messages': [llm.invoke(state['messages'])]\n",
" }\n",
"\n",
"graph_builder.add_node(\"chatbot\", chatbot)\n",
"graph_builder.set_entry_point(\"chatbot\") \n",
"graph_builder.set_finish_point(\"chatbot\") \n",
"\n",
"graph = graph_builder.compile()\n",
"\n",
"\n",
"# 초기 상태 설정\n",
"initial_state = {\n",
" \"messages\": [HumanMessage(\"안녕하세요!\")],\n",
" \"counter\": 0\n",
"}\n",
"\n",
"# 그래프 실행\n",
"result = graph.invoke(initial_state)\n",
"result"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": ".venv",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.9"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment