AI Engineer 공간 "사부작 사부작"

Langgraph(LangChain)으로 멀티 LLM 에이전트 비용 추적하기: response_metadata 완벽 분석 본문

Code/Langgraph

Langgraph(LangChain)으로 멀티 LLM 에이전트 비용 추적하기: response_metadata 완벽 분석

ChoYongHo 2025. 7. 3. 08:13
728x90

Langgraph(LangChain)으로 멀티 LLM 에이전트 비용 추적하기: response_metadata 완벽 분석

AI 에이전트, 특히 여러 LLM이 협력하는 멀티 에이전트 시스템을 개발하다 보면 필연적으로 마주하는 질문이 있습니다. "그래서, 이 작업에 비용이 얼마나 들었지?" OpenAI, Anthropic, Google 등 다양한 LLM을 오가며 최적의 결과를 만드는 LangGraph의 유연성은 강력한 무기이지만, 동시에 비용 추적을 복잡하게 만드는 요인이 되기도 합니다. 어떤 모델이 얼마만큼의 토큰을 사용했는지 정확히 알아야만 서비스의 운영 비용을 산정하고 최적화할 수 있기 때문입니다. 이 복잡한 비용 추적의 실마리를 풀어줄 핵심 열쇠가 바로 LangChain의 response_metadata에 숨어있습니다. 이것은 단순히 부가 정보가 아니라, 각 LLM 호출의 비용을 투명하게 들여다볼 수 있는 '상세 영수증'과도 같습니다. 이번 글에서는 response_metadata의 개념을 알아보고, 실제 코드를 통해 각 LLM 제공사별로 어떻게 토큰 사용량을 추적하고 비용을 산정할 수 있는지 자세히 살펴보겠습니다.


LLM의 '영수증', response_metadata란?

LLM을 개발할 때 우리는 보통 모델이 생성한 텍스트 답변에만 집중합니다. 하지만 모델 제공사들은 답변과 함께 다양한 추가 정보를 반환하는데, LangChain은 이 정보를 AIMessage 객체의 response_metadata 속성에 담아 제공합니다.

  • 개념: response_metadata는 LLM 호출 후 반환되는 딕셔너리(Dict) 형태의 데이터입니다. 여기에는 사용된 토큰 수, 응답 생성 이유(e.g., 'stop'), 사용된 모델 이름 등 LLM 제공사별 고유 정보가 포함됩니다.
  • 비유: response_metadata를 온라인 쇼핑 후 받는 '주문 상세 내역서'라고 생각해 보세요. 최종적으로 받은 물건(LLM의 답변) 외에도, 주문 번호(ID), 판매자 정보(모델 이름), 그리고 가장 중요한 가격 정보(토큰 사용량)가 상세히 적혀있습니다. 여러 상점(LLM 제공사)에서 물건을 사도, 이 내역서만 잘 모아두면 전체 지출을 쉽게 파악할 수 있는 것과 같습니다.

LangChain의 가장 큰 장점 중 하나는 다양한 LLM 제공사를 동일한 인터페이스로 다룰 수 있다는 점입니다. response_metadata는 각기 다른 포맷을 가진 제공사들의 '영수증'을 일관된 방식으로 접근할 수 있게 해주는 통로 역할을 합니다.


제공사별 response_metadata 파헤치기 (Feat. 토큰 사용량)

그렇다면 실제 response_metadata는 어떻게 생겼을까요? OpenAI, Anthropic, Google VertexAI의 예시를 통해 토큰 사용량을 확인하는 방법을 알아보겠습니다.

1. OpenAI

OpenAI 모델은 token_usage라는 매우 직관적인 키를 통해 토큰 정보를 제공합니다. token_usage 객체 안의 prompt_tokens 입력 토큰, completion_tokens 출력 토큰에 해당합니다. 이 외에도 모델이 추론(Reasoning)을 할 때 사용되는 reasoning_tokens 등의 값도 존재하는 것을 확인 할 수 있습니다.

from langchain_openai import ChatOpenAI

llm = ChatOpenAI(model="gpt-4o-mini")
msg = llm.invoke("What's the oldest known example of cuneiform")
msg.response_metadata


{'token_usage': {'completion_tokens': 110,
  'prompt_tokens': 16,
  'total_tokens': 126,
  '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_b8bc95a0ac',
 'id': 'chatcmpl-BDrISvLar6AqcZngBmhajFZXVc2u9',
 'finish_reason': 'stop',
 'logprobs': None}

2. Anthropic

Anthropic 모델은 usage라는 키를 사용하며, 입력과 출력을 명확히 구분합니다. usage 객체 안의 input_tokens와 output_tokens를 통해 각각 입력출력 토큰 수를 알 수 있습니다. 

from langchain_anthropic import ChatAnthropic

llm = ChatAnthropic(model="claude-3-5-sonnet-latest")
msg = llm.invoke("What's the oldest known example of cuneiform")
msg.response_metadata


{'id': 'msg_01JHnvPqgERY7MZwrvfkmq52',
 'model': 'claude-3-5-sonnet-20241022',
 'stop_reason': 'end_turn',
 'stop_sequence': None,
 'usage': {'cache_creation_input_tokens': 0,
  'cache_read_input_tokens': 0,
  'input_tokens': 17,
  'output_tokens': 221},
 'model_name': 'claude-3-5-sonnet-20241022'}

3. Google VertexAI

Google VertexAI는 usage_metadata라는 키 아래에 토큰 정보를 저장합니다. usage_metadata 객체에서 prompt_token_count가 입력 토큰, candidates_token_count가 출력 토큰을 의미합니다.

from langchain_google_vertexai import ChatVertexAI

llm = ChatVertexAI(model="gemini-2.0-flash-001")
msg = llm.invoke("What's the oldest known example of cuneiform")
msg.response_metadata


{'is_blocked': False,
 'safety_ratings': [],
 'usage_metadata': {'prompt_token_count': 10,
  'candidates_token_count': 55,
  'total_token_count': 65,
  'prompt_tokens_details': [{'modality': 1, 'token_count': 10}],
  'candidates_tokens_details': [{'modality': 1, 'token_count': 55}],
  'cached_content_token_count': 0,
  'cache_tokens_details': []},
 'finish_reason': 'STOP',
 'avg_logprobs': -0.251378042047674,
 'model_name': 'gemini-2.0-flash-001'}

이처럼 제공사마다 키의 이름(token_usage, usage, usage_metadata)은 조금씩 다르지만, 입력과 출력 토큰이라는 핵심 정보는 모두 얻을 수 있다는 공통점이 있습니다. 이를 통해 어떤 LLM을 사용하든 일관된 로직으로 비용을 계산할 수 있게 됩니다.


LangGraph와 Checkpoint를 활용한 자동 비용 추적 시스템

response_metadata의 진정한 진가는 LangGraph의 Checkpoint 기능과 만났을 때 발휘됩니다. LangGraph 에이전트의 모든 실행 단계를 기록하는 Checkpointresponse_metadata를 자동으로 저장하여 정교한 비용 추적 시스템을 구축할 수 있게 해줍니다.

  • 개념: LangGraph에서 PostgresSaver와 같은 Checkpointer를 사용하면, 각 단계의 실행 정보가 데이터베이스에 기록됩니다. 이때 LLM을 호출한 노드의 결과, 즉 AIMessage에 포함된 response_metadatacheckpoints 테이블의 metadata 칼럼에 jsonb 형식으로 함께 저장됩니다.
  • 비유: 이것은 마치 '자동 가계부' 시스템을 구축하는 것과 같습니다. LangGraph라는 에이전트가 OpenAI, Anthropic 등 여러 '가게'를 돌아다니며 작업을 수행할 때마다, PostgresSaver라는 비서가 자동으로 영수증(response_metadata)을 모아 데이터베이스라는 '장부'에 꼼꼼히 기록해주는 셈입니다. 우리는 나중에 이 장부만 열어보면 모든 지출 내역을 한눈에 파악하고 분석할 수 있습니다.

이렇게 데이터베이스에 쌓인 metadata를 쿼리하여 각 모델별 토큰 사용량을 집계하고, 모델별 단가를 곱해주면 에이전트가 실행될 때마다 발생한 총비용을 정확하게 계산할 수 있습니다.


마무리하며

response_metadata는 Langgraph(LangChain)을 사용해 복잡한 AI 멀티 에이전트를 개발하는 엔지니어에게 선택이 아닌 필수적인 도구입니다. 단순히 숨겨진 데이터가 아니라, 서비스의 운영 상태를 진단하고 비용을 최적화하며 안정성을 높이는 데 결정적인 역할을 하는 '운영 데이터의 핵심'입니다. 멀티 LLM 에이전트의 비용이 안개 속에 가려진 것처럼 느껴진다면, 지금 바로 response_metadata를 출력해 보세요. 그 안에 여러분의 서비스를 한 단계 더 발전시킬 명확한 숫자와 단서들이 담겨 있을 것입니다. 이 '상세 영수증'을 적극적으로 활용하여 더 똑똑하고 효율적인 멀티 에이전트 AI 서비스를 만들어나가시길 바랍니다. 


https://python.langchain.com/docs/how_to/response_metadata/

 

Response metadata | 🦜️🔗 LangChain

Many model providers include some metadata in their chat generation responses. This metadata can be accessed via the AIMessage.responsemetadata: Dict attribute. Depending on the model provider and model configuration, this can contain information like toke

python.langchain.com

https://langchain-ai.github.io/langgraph/reference/checkpoints/#langgraph.checkpoint.postgres.PostgresSaver

 

Checkpointing

The ID of the checkpoint. This is both unique and monotonically increasing, so can be used for sorting checkpoints from first to last.

langchain-ai.github.io

 

728x90