langgraph / / 2024. 12. 1. 18:08

[langgraph] 동시에 여러 스트리밍 모드를 구성하는 방법

LangGraph 공식문서를 번역한 내용입니다. 필요한 경우 부연 설명을 추가하였고 이해하기 쉽게 예제를 일부 변경하였습니다. 문제가 되면 삭제하겠습니다.

https://langchain-ai.github.io/langgraph/how-tos/stream-multiple/

이 가이드는 여러 스트리밍 모드를 동시에 구성하는 방법에 대한 내용이다.

준비

우선, 필요한 패키지를 설치하자.

pip install langgraph langchain-openai langchain-community

그래프 정의

이 가이드에서는 간단한 ReAct 에이전트를 사용한다.

import asyncio
from typing import Literal

from dotenv import load_dotenv
from langchain_core.tools import tool
from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent

load_dotenv()


@tool
def get_weather(city: Literal["서울", "부산"]):
    """Use this to get weather information."""
    if city == "서울":
        return "맑아요~"
    elif city == "부산":
        return "비와요~"
    else:
        raise AssertionError("Unknown city")


tools = [get_weather]

model = ChatOpenAI(model_name="gpt-4o-mini", temperature=0)
graph = create_react_agent(model, tools)

Stream multiple

inputs = {"messages": [("human", "서울 날씨 어때?")]}


async def stream_content():
    async for event, chunk in graph.astream(inputs, stream_mode=["updates", "debug"]):
        print(f"Receiving new event of type: {event}...")
        print(chunk)
        print("\n\n")


asyncio.run(stream_content())
Receiving new event of type: debug...
{'type': 'task', 'timestamp': '2024-11-27T00:35:04.046999+00:00', 'step': 1, 'payload': {'id': 'd1c5e661-e559-344a-57f6-4f92ca28a48d', 'name': 'agent', 'input': {'messages': [HumanMessage(content='서울 날씨 어때?', additional_kwargs={}, response_metadata={}, id='c36b4f94-3157-44a2-9f65-b74b30ae8fb5')], 'is_last_step': False, 'remaining_steps': 24}, 'triggers': ['start:agent']}}



Receiving new event of type: updates...
{'agent': {'messages': [AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_Ad1RpabSXM0INTtUYX5xjh3A', 'function': {'arguments': '{"city":"서울"}', 'name': 'get_weather'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 14, 'prompt_tokens': 57, 'total_tokens': 71, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_0705bf87c0', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-b29218eb-e8b9-40ba-95fc-568915962cec-0', tool_calls=[{'name': 'get_weather', 'args': {'city': '서울'}, 'id': 'call_Ad1RpabSXM0INTtUYX5xjh3A', 'type': 'tool_call'}], usage_metadata={'input_tokens': 57, 'output_tokens': 14, 'total_tokens': 71, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}})]}}



Receiving new event of type: debug...
{'type': 'task_result', 'timestamp': '2024-11-27T00:35:04.984570+00:00', 'step': 1, 'payload': {'id': 'd1c5e661-e559-344a-57f6-4f92ca28a48d', 'name': 'agent', 'error': None, 'result': [('messages', [AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_Ad1RpabSXM0INTtUYX5xjh3A', 'function': {'arguments': '{"city":"서울"}', 'name': 'get_weather'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 14, 'prompt_tokens': 57, 'total_tokens': 71, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_0705bf87c0', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-b29218eb-e8b9-40ba-95fc-568915962cec-0', tool_calls=[{'name': 'get_weather', 'args': {'city': '서울'}, 'id': 'call_Ad1RpabSXM0INTtUYX5xjh3A', 'type': 'tool_call'}], usage_metadata={'input_tokens': 57, 'output_tokens': 14, 'total_tokens': 71, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}})])], 'interrupts': []}}



Receiving new event of type: debug...
{'type': 'task', 'timestamp': '2024-11-27T00:35:04.984892+00:00', 'step': 2, 'payload': {'id': '5293ddcf-64f8-d3fb-5246-522be23f48e9', 'name': 'tools', 'input': {'messages': [HumanMessage(content='서울 날씨 어때?', additional_kwargs={}, response_metadata={}, id='c36b4f94-3157-44a2-9f65-b74b30ae8fb5'), AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_Ad1RpabSXM0INTtUYX5xjh3A', 'function': {'arguments': '{"city":"서울"}', 'name': 'get_weather'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 14, 'prompt_tokens': 57, 'total_tokens': 71, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_0705bf87c0', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-b29218eb-e8b9-40ba-95fc-568915962cec-0', tool_calls=[{'name': 'get_weather', 'args': {'city': '서울'}, 'id': 'call_Ad1RpabSXM0INTtUYX5xjh3A', 'type': 'tool_call'}], usage_metadata={'input_tokens': 57, 'output_tokens': 14, 'total_tokens': 71, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}})], 'is_last_step': False, 'remaining_steps': 23}, 'triggers': ['branch:agent:should_continue:tools']}}



Receiving new event of type: updates...
{'tools': {'messages': [ToolMessage(content='맑아요~', name='get_weather', id='558f617f-7799-48a0-89e7-d9e8236b0723', tool_call_id='call_Ad1RpabSXM0INTtUYX5xjh3A')]}}



Receiving new event of type: debug...
{'type': 'task_result', 'timestamp': '2024-11-27T00:35:04.986756+00:00', 'step': 2, 'payload': {'id': '5293ddcf-64f8-d3fb-5246-522be23f48e9', 'name': 'tools', 'error': None, 'result': [('messages', [ToolMessage(content='맑아요~', name='get_weather', id='558f617f-7799-48a0-89e7-d9e8236b0723', tool_call_id='call_Ad1RpabSXM0INTtUYX5xjh3A')])], 'interrupts': []}}



Receiving new event of type: debug...
{'type': 'task', 'timestamp': '2024-11-27T00:35:04.986942+00:00', 'step': 3, 'payload': {'id': '1f656d31-38af-9f99-65fc-8afe476228d9', 'name': 'agent', 'input': {'messages': [HumanMessage(content='서울 날씨 어때?', additional_kwargs={}, response_metadata={}, id='c36b4f94-3157-44a2-9f65-b74b30ae8fb5'), AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_Ad1RpabSXM0INTtUYX5xjh3A', 'function': {'arguments': '{"city":"서울"}', 'name': 'get_weather'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 14, 'prompt_tokens': 57, 'total_tokens': 71, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_0705bf87c0', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-b29218eb-e8b9-40ba-95fc-568915962cec-0', tool_calls=[{'name': 'get_weather', 'args': {'city': '서울'}, 'id': 'call_Ad1RpabSXM0INTtUYX5xjh3A', 'type': 'tool_call'}], usage_metadata={'input_tokens': 57, 'output_tokens': 14, 'total_tokens': 71, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}}), ToolMessage(content='맑아요~', name='get_weather', id='558f617f-7799-48a0-89e7-d9e8236b0723', tool_call_id='call_Ad1RpabSXM0INTtUYX5xjh3A')], 'is_last_step': False, 'remaining_steps': 22}, 'triggers': ['tools']}}



Receiving new event of type: updates...
{'agent': {'messages': [AIMessage(content='서울의 날씨는 맑습니다!', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 10, 'prompt_tokens': 83, 'total_tokens': 93, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_0705bf87c0', 'finish_reason': 'stop', 'logprobs': None}, id='run-7d2999d5-7e4e-465d-b725-a8d84988c3be-0', usage_metadata={'input_tokens': 83, 'output_tokens': 10, 'total_tokens': 93, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}})]}}



Receiving new event of type: debug...
{'type': 'task_result', 'timestamp': '2024-11-27T00:35:05.655691+00:00', 'step': 3, 'payload': {'id': '1f656d31-38af-9f99-65fc-8afe476228d9', 'name': 'agent', 'error': None, 'result': [('messages', [AIMessage(content='서울의 날씨는 맑습니다!', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 10, 'prompt_tokens': 83, 'total_tokens': 93, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_0705bf87c0', 'finish_reason': 'stop', 'logprobs': None}, id='run-7d2999d5-7e4e-465d-b725-a8d84988c3be-0', usage_metadata={'input_tokens': 83, 'output_tokens': 10, 'total_tokens': 93, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}})])], 'interrupts': []}}

LangGraph 참고 자료

반응형
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유