Messages(stock)

HanJu Han·2025년 12월 19일

제1장: Messages

LLM은 과거의 대화를 기억하지 못하는 'Stateless' 특성을 가집니다. 따라서 우리가 이전 대화 내용을 포함해 메시지 객체의 리스트를 전달해야만 모델이 맥락을 이해합니다. LangChain의 메시지는 크게 세 가지 요소로 구성됩니다.

  1. Role (역할): 메시지를 보내는 주체 (시스템, 사용자, AI 등)
  2. Content (내용): 실제 전달할 텍스트, 이미지, 혹은 데이터
  3. Metadata (메타데이터): 메시지 ID, 토큰 사용량, 모델 정보 등 비가시적 데이터

제2장: Message Types

주식 분석 봇을 만들 때 각 메시지 유형이 어떻게 사용되는지 실전 예시와 함께 살펴보겠습니다.

1. SystemMessage (설계자)

모델의 페르소나를 설정합니다. 주식 전문가로서의 윤리 지침이나 분석 스타일을 정의합니다.

2. HumanMessage (사용자)

사용자의 질문이나 요청입니다. "삼성전자의 현재가 알려줘"와 같은 입력입니다.

3. AIMessage (응답자)

모델이 생성한 답변입니다. 여기에는 단순 텍스트뿐만 아니라, 모델이 계산을 위해 도구를 사용하겠다는 'Tool Call' 정보도 포함될 수 있습니다.

4. ToolMessage (조력자)

외부 API(예: Yahoo Finance)에서 가져온 실제 주가 데이터를 모델에게 다시 전달할 때 사용합니다.


제3장: 실전! 주식 데이터 분석 워크플로우

이제 파이썬 코드를 통해 주식 데이터를 처리하는 과정을 단계별로 구현해 보겠습니다.

1. 환경 설정 및 모델 초기화

from langchain.chat_models import init_chat_model
from langchain.messages import SystemMessage, HumanMessage, AIMessage

# 모델 초기화 (예: GPT-4o 또는 gpt-5-nano 설정)
model = init_chat_model("gpt-4o")

2. 메시지 구성을 통한 분석 요청

단순한 질문이 아니라, 전문적인 분석가 페르소나를 부여하여 엔비디아(NVDA)와 테슬라(TSLA)의 데이터를 다뤄보겠습니다.

# 1. 시스템 메시지: 분석 가이드라인 설정
system_msg = SystemMessage(content="""
당신은 월스트리트 출신의 주식 분석가입니다. 
기술적 지표(이동평균선, RSI)와 기본적 분석을 조합하여 답변하세요. 
수치 데이터는 반드시 표 형태로 정리하고, 투자 유의사항을 마지막에 덧붙이세요.
""")

# 2. 사용자 메시지: 구체적인 분석 요청
human_msg = HumanMessage(content="""
엔비디아(NVDA)의 최근 1년 수익률이 테슬라(TSLA)를 압도하고 있습니다. 
이러한 차이가 발생한 핵심 이유 3가지를 데이터 기반으로 설명해 주세요.
""")

# 3. 메시지 리스트 구성 및 호출
messages = [system_msg, human_msg]
response = model.invoke(messages)

print(f"AI 분석관의 답변: {response.content}")

제4장: 메시지 흐름의 시각화

메시지가 시스템 내에서 어떻게 순환하는지 이해하는 것이 중요합니다. 아래 다이어그램은 사용자의 질문이 시스템 메시지와 결합되어 AI의 답변으로 돌아오는 과정을 보여줍니다.


제5장: 메타데이터와 토큰 관리 (고급)

실제 서비스에서는 비용 관리가 필수적입니다. AIMessage에는 모델이 사용한 토큰 정보가 포함되어 있습니다. 이를 시각화하여 분석해 보겠습니다.

# 응답 객체에서 메타데이터 추출 예시
usage = response.response_metadata.get('token_usage', {})
print(f"사용된 토큰: {usage}")

# 시각화 예시 (Python matplotlib 활용)
import matplotlib.pyplot as plt

labels = ['Prompt Tokens', 'Completion Tokens']
sizes = [usage.get('prompt_tokens', 0), usage.get('completion_tokens', 0)]

plt.figure(figsize=(7, 5))
plt.pie(sizes, labels=labels, autopct='%1.1f%%', startangle=140, colors=['#ff9999','#66b3ff'])
plt.title('Stock Analysis Request Token Usage')
plt.show()

(위 그래프는 사용자가 보낸 질문(Prompt)과 AI가 생성한 답변(Completion)의 비중을 보여주며, 주식 분석처럼 데이터 양이 많을 경우 입력 토큰의 비중이 어떻게 변화하는지 모니터링하는 데 유용합니다.)


제6장: 요약

  1. 문자열보다는 객체를 사용하세요: model.invoke("질문")도 작동하지만, 복잡한 대화 기록 관리를 위해서는 [HumanMessage(content="...")] 형태의 리스트 사용이 권장됩니다.
  2. SystemMessage의 힘: 주식 데이터는 민감합니다. "모르는 데이터는 추측하지 말고 모른다고 답하라"는 지침을 SystemMessage에 반드시 포함하세요.
  3. Dictionary Format 활용: OpenAI API에 익숙하다면 {"role": "user", "content": "..."} 형태의 딕셔너리 리스트를 그대로 model.invoke()에 넣어도 LangChain이 알아서 처리해 줍니다.

『LangChain으로 구축하는 차세대 AI 애플리케이션』의 저자입니다.

지난 장에서 메시지의 기본 구조를 배웠다면, 이번 장에서는 AI가 실제로 사고하고 외부 세계와 소통하는 핵심 메커니즘AIMessageToolMessage를 깊이 있게 다뤄보겠습니다. 특히 실시간 주식 데이터를 조회하고 분석하는 시나리오를 통해 이들의 상호작용을 완벽히 이해해 봅시다.


제7장: AI의 응답과 사고의 흔적 (AIMessage)

AIMessage는 모델이 생성한 모든 결과물을 담는 그릇입니다. 단순히 텍스트만 주는 것이 아니라, "내가 어떤 도구를 쓸 것인가?"라는 계획과 "이 답변에 비용이 얼마나 들었나?"라는 메타데이터를 함께 전달합니다.

1. 주식 분석가의 답변 구조

사용자가 "엔비디아(NVDA)의 현재 상태를 알려줘"라고 했을 때, AI는 내부적으로 다음과 같은 AIMessage를 생성합니다.

from langchain.messages import AIMessage

# AI가 생성한 응답 객체 (예시)
ai_msg = AIMessage(
    content="엔비디아(NVDA)는 현재 AI 반도체 수요 증가로 인해 강력한 상승세를 보이고 있습니다.",
    usage_metadata={
        "input_tokens": 50,
        "output_tokens": 120,
        "total_tokens": 170
    },
    response_metadata={"model_name": "gpt-5-nano", "finish_reason": "stop"}
)

print(f"AI의 분석: {ai_msg.content}")
print(f"소모된 비용(토큰): {ai_msg.usage_metadata['total_tokens']}")

AI의 분석: 엔비디아(NVDA)는 현재 AI 반도체 수요 증가로 인해 강력한 상승세를 보이고 있습니다.
소모된 비용(토큰): 170

2. 도구 호출 (Tool Calls)

현대적인 AI는 단순히 아는 대로 말하지 않습니다. 최신 주가를 알기 위해 "주가 조회 도구를 실행해줘"라고 요청합니다. 이것이 tool_calls 속성입니다.


제8장: 외부 데이터와의 연결 고리 (ToolMessage)

AI는 인터넷에 직접 접속하지 못합니다. 우리가 대신 데이터를 가져다줘야 하는데, 이때 사용하는 것이 ToolMessage입니다.

핵심 규칙: ToolMessage는 반드시 앞선 AIMessage가 요청한 tool_call_id와 짝이 맞아야 합니다.

실전 예시: 실시간 주가 조회 프로세스

from langchain.messages import HumanMessage, AIMessage, ToolMessage

# 1. 사용자의 질문
user_input = HumanMessage(content="애플(AAPL) 현재가 조회해줘.")

# 2. AI의 판단 (Tool Call 생성)
# 모델은 직접 답하는 대신 'get_stock_price'라는 도구를 쓰겠다고 선언합니다.
ai_tool_call = AIMessage(
    content="",
    tool_calls=[{
        "name": "get_stock_price",
        "args": {"ticker": "AAPL"},
        "id": "call_stock_001" # 이 ID가 중요합니다!
    }]
)

# 3. 실제 외부 API 호출 결과 (ToolMessage)
# 우리가 API(예: Yahoo Finance)에서 가져온 데이터를 ToolMessage에 담습니다.
stock_data_result = ToolMessage(
    content="227.63 USD (전일 대비 +1.2%)",
    tool_call_id="call_stock_001", # AI가 요청한 ID와 일치시켜야 함
    artifact={"raw_json": {"symbol": "AAPL", "price": 227.63, "currency": "USD"}} # 부가 데이터
)

# 4. 최종 답변을 위한 메시지 리스트
messages = [user_input, ai_tool_call, stock_data_result]
# 이제 이 리스트를 다시 모델에 보내면, 모델이 데이터를 해석해서 최종 답변을 합니다.

제9장: 데이터 흐름 시각화 (The Tool Loop)

주식 데이터를 가져와서 사용자에게 전달하기까지의 복잡한 과정을 시각화하면 다음과 같습니다.


제10장: 고급 기법 - 스트리밍과 아티팩트

1. 실시간 주가 전광판 (Streaming)

주식 앱처럼 글자가 한 글자씩 출력되게 하려면 AIMessageChunk를 사용합니다.

# 모델이 데이터를 조금씩 보낼 때마다 조각(Chunk)을 합쳐서 완성합니다.
full_analysis = None
for chunk in model.stream("엔비디아 향후 전망 분석해줘"):
    if full_analysis is None:
        full_analysis = chunk
    else:
        full_analysis += chunk
    print(chunk.content, end="|", flush=True)

2. 아티팩트(Artifact)의 활용

ToolMessageartifact 필드는 매우 유용합니다. AI에게는 "주가가 227달러다"라는 텍스트만 보여주고, 우리 프로그램 내부에서는 차트를 그리기 위한 Raw JSON 데이터artifact에 숨겨서 전달할 수 있습니다. AI의 컨텍스트를 어지럽히지 않으면서 풍부한 정보를 관리하는 비결입니다.


제11장: 토큰 사용량 시각화 (비용 분석)

주식 분석 봇을 운영할 때 비용이 얼마나 발생하는지 파이썬으로 시각화해 보겠습니다.

import matplotlib.pyplot as plt

# 실제 모델 응답에서 추출한 데이터 예시
usage_data = {
    'Input (질문+데이터)': 450,
    'Reasoning (추론)': 200,
    'Output (답변)': 300
}

plt.figure(figsize=(10, 6))
bars = plt.bar(usage_data.keys(), usage_data.values(), color=['#3498db', '#e67e22', '#2ecc71'])

plt.title('Stock Analysis Token Usage Breakdown', fontsize=15)
plt.ylabel('Number of Tokens')
for bar in bars:
    yval = bar.get_height()
    plt.text(bar.get_x() + bar.get_width()/2, yval + 5, yval, ha='center', va='bottom')

plt.show()

조언

ToolMessage를 작성할 때 가장 흔히 하는 실수는 tool_call_id를 누락하거나 틀리는 것입니다. 이것은 마치 택배 송장 번호가 틀려 물건이 주인에게 가지 못하는 것과 같습니다. AI의 요청 ID와 도구의 응답 ID를 반드시 일치시키세요. 그것이 LangChain 에이전트 구축의 핵심입니다.

profile
시리즈를 기반으로 작성하였습니다.

0개의 댓글