함수 호출의 기초
함수 호출의 기초 (Basics of Function Calling)
함수 호출(Function Calling)은 Mistral 모델을 외부 도구에 연결할 수 있게 해줘요. 사용자가 정의한 함수나 API 같은 외부 도구와 Mistral 모델을 통합하면, 특정 유스케이스와 실제 문제를 다루는 애플리케이션을 쉽게 만들 수 있어요. 이 가이드에서는 결제 상태와 결제 날짜를 조회하는 두 함수를 예로 들어, 그 두 도구로 결제 관련 질문에 답하는 전체 흐름을 살펴봐요.
출처: 문서
본문
함수 호출에는 크게 네 단계가 있어요.
- User: 도구와 쿼리 지정
- Model: 가능하다면 함수 인자 생성
- User: 도구 결과를 얻기 위해 함수 실행
- Model: 최종 답변 생성
이 가이드에서는 결제 트랜잭션으로 구성된 데이터프레임이 있다고 가정해요. 사용자가 이 데이터프레임에 대해 질문하면 특정 도구로 답할 수 있게 해보죠. 이는 LLM이 직접 접근할 수 없는 외부 데이터베이스를 흉내 낸 예시예요.
!pip install pandas mistralai
import pandas as pd
# Assuming we have the following data
data = {
'transaction_id': ['T1001', 'T1002', 'T1003', 'T1004', 'T1005'],
'customer_id': ['C001', 'C002', 'C003', 'C002', 'C001'],
'payment_amount': [125.50, 89.99, 120.00, 54.30, 210.20],
'payment_date': ['2021-10-05', '2021-10-06', '2021-10-07', '2021-10-05', '2021-10-08'],
'payment_status': ['Paid', 'Unpaid', 'Paid', 'Paid', 'Pending']
}
# Create DataFrame
df = pd.DataFrame(data)
Step 1. User: 도구와 쿼리 지정
사용자는 유스케이스에 필요한 모든 도구를 정의할 수 있어요. 보통 여러 도구를 갖게 되죠. 여기서는 트랜잭션 ID가 주어졌을 때 결제 상태와 결제 날짜를 조회하는 함수 두 개(retrieve_payment_status, retrieve_payment_date)를 도구로 삼아요.
def retrieve_payment_status(df: data, transaction_id: str) -> str:
if transaction_id in df.transaction_id.values:
return json.dumps({'status': df[df.transaction_id == transaction_id].payment_status.item()})
return json.dumps({'error': 'transaction id not found.'})
def retrieve_payment_date(df: data, transaction_id: str) -> str:
if transaction_id in df.transaction_id.values:
return json.dumps({'date': df[df.transaction_id == transaction_id].payment_date.item()})
return json.dumps({'error': 'transaction id not found.'})
Mistral 모델이 함수를 이해하려면 함수 스펙을 JSON 스키마로 정리해야 해요. 구체적으로 함수의 타입, 함수 이름, 함수 설명, 함수 파라미터, 그리고 필수 파라미터를 기술해요. 여기서는 함수가 두 개이므로 스펙 두 개를 리스트로 나열해요.
tools = [
{
"type": "function",
"function": {
"name": "retrieve_payment_status",
"description": "Get payment status of a transaction",
"parameters": {
"type": "object",
"properties": {
"transaction_id": {
"type": "string",
"description": "The transaction id.",
}
},
"required": ["transaction_id"],
},
},
},
{
"type": "function",
"function": {
"name": "retrieve_payment_date",
"description": "Get payment date of a transaction",
"parameters": {
"type": "object",
"properties": {
"transaction_id": {
"type": "string",
"description": "The transaction id.",
}
},
"required": ["transaction_id"],
},
},
}
]
그다음 두 함수를 함수 이름을 키로, df가 정의된 함수를 값으로 하는 딕셔너리로 정리해요. 이러면 함수 이름으로 각 함수를 호출할 수 있어요.
import functools
names_to_functions = {
'retrieve_payment_status': functools.partial(retrieve_payment_status, df=df),
'retrieve_payment_date': functools.partial(retrieve_payment_date, df=df)
}
사용자가 이런 질문을 한다고 가정해 봐요: "What's the status of my transaction?" 단독 LLM은 필요한 데이터를 얻기 위해 비즈니스 로직 백엔드를 조회해야 하므로 이 질문에 답하지 못해요. 하지만 정확한 도구가 있다면 답할 수 있어요!
messages = [{"role": "user", "content": "What's the status of my transaction T1001?"}]
Step 2. Model: 함수 인자 생성
Mistral 모델은 어떻게 함수를 알고 어떤 함수를 쓸지 결정할까요? 사용자 쿼리와 도구 스펙을 모두 Mistral 모델에 제공해요. 이 단계의 목표는 모델이 함수를 직접 실행하는 것이 아니에요. 1) 적절한 함수를 결정하고, 2) 함수에 필수 정보가 빠졌는지 식별하며, 3) 선택한 함수에 필요한 인자를 생성하는 것이에요.
import os
from mistralai.client import Mistral
api_key = os.environ["MISTRAL_API_KEY"]
model = "mistral-large-latest"
client = Mistral(api_key=api_key)
response = client.chat.complete(
model = model,
messages = messages,
tools = tools,
tool_choice = "any",
)
response
messages.append(response.choices[0].message)
messages
Step 3. User: 도구 결과를 얻기 위해 함수 실행
함수를 어떻게 실행할까요? 현재는 함수 실행이 사용자 책임이며 사용자 측에서 이뤄져요. 나중에는 서버 측에서 실행 가능한 유용한 함수를 도입할 수도 있어요. 모델 응답에서 함수 이름(function_name)과 함수 파라미터(function_params) 같은 유용한 정보를 추출해 볼게요. 여기서 Mistral 모델이 transaction_id를 T1001로 설정해 retrieve_payment_status 함수를 선택한 게 분명해요.
import json
tool_call = response.choices[0].message.tool_calls[0]
function_name = tool_call.function.name
function_params = json.loads(tool_call.function.arguments)
print("\nfunction_name: ", function_name, "\nfunction_params: ", function_params)
function_result = names_to_functions[function_name](**function_params)
function_result
messages.append({"role":"tool", "name":function_name, "content":function_result, "tool_call_id":tool_call.id})
messages
Step 4. Model: 최종 답변 생성
이제 도구의 출력을 Mistral 모델에 제공할 수 있고, 모델은 특정 사용자에 맞춘 최종 응답을 생성해요.
response = client.chat.complete(
model = model,
messages = messages
)
response.choices[0].message.content
이렇게 네 단계(Function Calling의 기본)를 따르면, Mistral 모델이 외부 도구에 연결되어 실제 데이터 질문에도 답할 수 있어요.
더 알아보기 (Learn more)
- 함수 호출 가이드 — 기초 개념과 설정
- 기본 RAG 쿡북 — RAG 파이프라인
- LlamaIndex 에이전트 쿡북 — 에이전트로 도구 활용