일반적인 AI 모델은 기본적인 일반 지식을 갖고 있지만, LLM의 경우 실시간 정보(예: 날짜, 주식 가격, 날씨 등)는 알지 못합니다.
이를 해결하기 위해, Function Calling을 사용하면 AI가 필요할 때만 특정 Tool(함수)을 호출하여 최신 정보를 가져올 수 있습니다.
LangChain에서 OpenAI API를 사용하려면, 환경 변수에 API Key를 설정해야 합니다.
아래 코드를 실행하면, API Key를 입력하고 자동으로 환경 변수에 저장할 수 있습니다.
import getpass
import os
def _set_env(key: str):
if key not in os.environ:
os.environ[key] = getpass.getpass(f"{key}:")
_set_env("OPENAI_API_KEY")
📌 설명
os.environ을 사용하여 환경 변수에 OPENAI_API_KEY를 설정합니다. OPENAI_API_KEY: 프롬프트가 나타나며, 사용자의 API Key를 입력할 수 있습니다. from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model='gpt-4o-mini')
response = llm.invoke('오늘 몇년도 몇월 몇일이야?').content
print(response)
오늘은 2023년 10월 2일입니다.
📌 문제점:
💡 해결 방법:
AI가 직접 날짜를 알지 못하더라도, Function Calling을 사용하면 필요할 때만 특정 Tool을 호출하여 정확한 정보를 가져올 수 있습니다.
from langchain_openai import ChatOpenAI
from langchain.tools import tool
from langgraph.prebuilt import create_react_agent
from langchain_core.messages import AIMessage, HumanMessage, SystemMessage, BaseMessage, ToolMessage
from typing import Literal
import yfinance as yf
📌 사용된 주요 라이브러리
ChatOpenAI → OpenAI 기반의 LLM을 사용 tool → Function Calling을 적용하기 위한 데코레이터 create_react_agent → AI가 Tool을 적절히 호출할 수 있도록 설정 AIMessage, HumanMessage, ToolMessage → AI와 Tool 간의 메시지 교환을 추적 AI가 필요할 때 호출할 수 있도록 여러 가지 Tool을 정의합니다.
@tool
def get_today():
"""현재 날짜를 YYYY-MM-DD 형식으로 반환"""
from datetime import datetime
return datetime.now().strftime("%Y-%m-%d")
@tool
def get_exchange_rate(currency: str):
"""yfinance 라이브러리를 활용하여 USD 대비 특정 통화의 환율을 반환"""
import yfinance as yf
exchange_data = yf.Ticker(f"USD{currency}=X")
exchange_rate = exchange_data.history(period="1d")['Close'].iloc[-1]
return f"USD -> {currency} 환율: {exchange_rate:.2f}"
@tool
def get_stock_price(stock_symbol: str):
"""yfinance 라이브러리를 활용하여 특정 주식 종목의 현재 가격을 조회"""
import yfinance as yf
stock = yf.Ticker(stock_symbol)
stock_price = stock.history(period="1d")['Close'].iloc[-1]
return f"{stock_symbol} 현재 주가: {stock_price:.2f} USD"
@tool
def add(a: int, b: int) -> int:
"""두 숫자의 합을 반환"""
return a + b
📌 각 Tool의 역할
get_today → (datetime 활용) 현재 날짜 반환 get_exchange_rate → (yfinance를 활용) 환율 정보 반환 get_stock_price → (yfinance를 활용) 특정 주식의 현재 가격 반환 add → 두 숫자의 합을 반환 각 메시지가 AI, 사용자, 시스템, Tool 중 어디서 온 것인지 분석할 수 있도록 합니다.
def parse_role_from_message(message: BaseMessage) -> Literal['assistant', 'human', 'system', 'tool', 'unknown']:
"""Extract role from a message"""
if isinstance(message, AIMessage):
return 'assistant'
elif isinstance(message, HumanMessage):
return 'human'
elif isinstance(message, SystemMessage):
return 'system'
elif isinstance(message, ToolMessage):
return 'tool'
else:
return 'unknown'
📌 이 함수가 필요한 이유
llm = ChatOpenAI(model='gpt-4o-mini')
# 앞서 정의한 tool들을 기반으로 LLM Agent생성
agent = create_react_agent(
llm,
tools=[get_today,
get_exchange_rate,
get_stock_price,
add
]
)
📌 설명
gpt-4o-mini)을 불러옵니다. create_react_agent를 이용해 필요할 때만 Tool을 호출하도록 설정합니다. def invoke_ai(question: str):
print(f"\n✅ 질문: '{question}' 실행 중...\n")
response = agent.invoke({"messages": question})
# 🔹 전체 response 출력
print("\n📌 Raw Response 출력:")
print(response)
# 사용된 Tool 추출
used_tools = set()
print("\n📌 메시지 분석:")
for message in response['messages']:
role = parse_role_from_message(message)
if role == 'assistant' and hasattr(message, "tool_calls"):
for tool_call in message.tool_calls:
tool_name = tool_call['name']
used_tools.add(tool_name)
print(f"🔹 사용된 Tool: {tool_name}")
elif role == 'tool':
print(f"🔹 ToolMessage - {message.name}: {message.content}")
# ✅ 사용되지 않은 Tool 출력
all_tools = {"get_today", "get_exchange_rate", "get_stock_price", "add"}
unused_tools = all_tools - used_tools
if unused_tools:
print(f"⚠️ 사용되지 않은 Tool: {', '.join(unused_tools)}")
print(f"\n🎯 AI 응답: {response['messages'][-1].content}\n")
📌 이 함수의 역할
1. AI에게 question을 전달하고 agent.invoke()를 실행
2. AI가 실행한 모든 메시지를 분석
3. AI가 호출한 Tool을 출력
4. 사용되지 않은 Tool도 표시
invoke_ai("오늘 애플 주가 얼마야? 달러 및 현재환율 고려해서 원화로도 얼마인지 알려줘")
✅ 질문: '오늘 애플 주가 얼마야? 달러 및 현재환율 고려해서 원화로도 얼마인지 알려줘' 실행 중...
📌 Raw Response 출력:
{
'messages': [
HumanMessage(content='오늘 애플 주가 얼마야? 달러 및 현재환율 고려해서 원화로도 얼마인지 알려줘.'),
AIMessage(content='', tool_calls=[
{'name': 'get_stock_price', 'args': {'stock_symbol': 'AAPL'}},
{'name': 'get_exchange_rate', 'args': {'currency': 'KRW'}}
]),
ToolMessage(content='AAPL 현재 주가: 227.65 USD', name='get_stock_price'),
ToolMessage(content='USD -> KRW 환율: 1453.99', name='get_exchange_rate'),
AIMessage(content='현재 애플(AAPL)의 주가는 227.65 달러입니다. 현재 환율을 기준으로(1 USD = 1453.99 KRW) 애플의 주가는 약 331,927 원입니다.')
]
}
HumanMessage(content='오늘 애플 주가 얼마야? 달러 및 현재환율 고려해서 원화로도 얼마인지 알려줘.')
📌 설명:
tool_calls 발생)AIMessage(content='', tool_calls=[
{'name': 'get_stock_price', 'args': {'stock_symbol': 'AAPL'}},
{'name': 'get_exchange_rate', 'args': {'currency': 'KRW'}}
])
📌 설명:
get_stock_price("AAPL") → 애플 주가를 가져옴 get_exchange_rate("KRW") → USD 대비 원화 환율을 가져옴 ToolMessage(content='AAPL 현재 주가: 227.65 USD', name='get_stock_price'),
ToolMessage(content='USD -> KRW 환율: 1453.99', name='get_exchange_rate')
📌 설명:
get_stock_price("AAPL") 실행 결과 → "AAPL 현재 주가: 227.65 USD" get_exchange_rate("KRW") 실행 결과 → "USD -> KRW 환율: 1453.99" AIMessage(content='현재 애플(AAPL)의 주가는 227.65 달러입니다. 현재 환율을 기준으로(1 USD = 1453.99 KRW) 애플의 주가는 약 331,927 원입니다.')
📌 설명:
| Tool Name | 사용 여부 | 응답 내용 |
|---|---|---|
get_stock_price | ✅ 사용 | AAPL 현재 주가: 227.65 USD |
get_exchange_rate | ✅ 사용 | USD -> KRW 환율: 1453.99 |
get_today | ❌ 미사용 | (오늘 날짜는 필요하지 않았음) |
add | ❌ 미사용 | (덧셈 기능은 필요하지 않았음) |
🎯 AI 최종 응답:
현재 애플(AAPL)의 주가는 227.65 달러입니다.
현재 환율을 기준으로(1 USD = 1453.99 KRW) 애플의 주가는 약 331,927 원입니다.
자동으로 적절한 Tool을 호출하는것을 확인하기 위한, 다른 질문을 수행
예를 들어, 오늘 날짜와 연도/월/일의 합을 계산하는 경우:
invoke_ai("오늘 몇일이지? 오늘의 연도/월/일의 합계 값은?")
✅ 질문: '오늘 몇일이지? 오늘의 연도/월/일의 합계 값은?' 실행 중...
📌 Raw Response 출력:
{
'messages': [
HumanMessage(content='오늘 몇일이지? 오늘의 연도/월/일의 합계 값은?'),
AIMessage(content='', tool_calls=[
{'name': 'get_today'},
]),
ToolMessage(content='2025-02-11', name='get_today'),
AIMessage(content='', tool_calls=[
{'name': 'add', 'args': {'a': 2025, 'b': 2}},
]),
ToolMessage(content='2027', name='add'),
AIMessage(content='', tool_calls=[
{'name': 'add', 'args': {'a': 2027, 'b': 11}},
]),
ToolMessage(content='2038', name='add'),
AIMessage(content='오늘은 2025년 2월 11일입니다. 오늘의 연도, 월, 일의 합계 값은 2038입니다.')
]
}
🎯 AI 최종 응답:
오늘은 2025년 2월 11일입니다. 오늘의 연도, 월, 일의 합계 값은 2038입니다.
해당 질문 예시에서는, get_today, add Tool만 활용된것을 확인할 수 있다.
즉, 다수의 Tool을 정의하더라도, Agent는 필요할 때만 특정 Tool을 호출하는 특성을 갖는다.
✔️ 필요할 때만 특정 Tool을 호출 → 불필요한 호출 방지
✔️ 실시간 정보 제공 가능 → AI가 최신 데이터를 직접 조회하여 응답
✔️ 연산이 필요한 경우에도 적절한 Tool 호출 → 데이터 조회뿐만 아니라 계산까지 수행 가능
✔️ 확장성 우수 → 새로운 Tool을 쉽게 추가하고 활용 가능
✔️ 비효율적인 호출 제거 → 성능 최적화
🚀 Function Calling을 활용하면 AI의 신뢰도를 높이고 더욱 정교한 시스템을 구축할 수 있다!