AI 에이전트와 함수 호출: LLM을 위한 도구 구축
실시간 데이터를 가져오거나 계산을 수행하거나 외부 API와 상호작용해야 하는 AI 에이전트를 구축하고 있습니다. 하지만 LLM의 텍스트 생성과 실제 코드 실행 사이의 간극을 어떻게 메울까요? 함수 호출(도구 사용이라고도 함)이 그 답입니다. 이를 통해 LLM이 특정 작업을 요청하고, 여러분의 코드가 이를 실행합니다. 이 가이드는 AI 에이전트를 위한 함수 호출을 설계, 구현, 디버깅하는 과정을 안내합니다.
함수 호출이란 무엇인가?
함수 호출은 LLM이 여러분이 정의한 함수를 호출하도록 구조화된 요청을 출력할 수 있는 메커니즘입니다. 모델은 자유 텍스트를 생성하는 대신 함수 이름과 인수를 담은 JSON 객체를 반환합니다. 그러면 애플리케이션이 함수를 실행하고 결과를 모델에 다시 전달합니다. 이를 통해 에이전트는 텍스트 생성 이상의 작업을 수행할 수 있습니다. 예를 들어 데이터베이스 쿼리, 이메일 전송, API 호출 등이 가능합니다.
OpenAI, Anthropic, Google과 같은 주요 LLM 제공업체는 함수 호출을 지원합니다. 핵심 개념은 일관됩니다. 여러분이 사용 가능한 도구를 설명하면, 모델이 언제 사용할지 결정하고, 여러분이 실행을 처리합니다.
LLM을 위한 도구 설계
잘 설계된 도구는 안정적인 에이전트 동작에 필수적입니다. 다음 원칙을 따르세요:
- 명확한 이름과 설명: 설명적인 함수 이름과 상세한 설명을 사용하세요. LLM은 이를 바탕으로 올바른 도구를 선택합니다.
- 단순한 매개변수: 매개변수를 최소화하고 표준 타입(string, number, boolean, array, object)을 사용하세요. 가능하면 복잡한 중첩 구조를 피하세요.
- 멱등성: 가능하면 도구를 멱등성 있게(재시도해도 안전하게) 설계하여 실패를 원활하게 처리하세요.
- 오류 처리: LLM이 접근 방식을 조정할 수 있도록 유익한 오류 메시지를 반환하세요.
예제: 날씨 도구
다음은 OpenAI API에서 흔히 사용되는 JSON 스키마 형식의 간단한 도구 정의입니다:
{
"name": "get_weather",
"description": "Get the current weather for a given city",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "The city name, e.g., San Francisco"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "Temperature unit"
}
},
"required": ["city"]
}
}
함수 호출 구현: 단계별 가이드
OpenAI API를 사용하여 최소한의 에이전트 루프를 구축해 보겠습니다(패턴은 다른 제공업체에도 적용됩니다).
1. 도구 정의하기
도구 스키마 목록과 함수 이름을 실제 Python 함수에 매핑하는 매핑을 생성하세요.
import json
import openai
# Tool schemas
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get current weather for a city",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string"},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
},
"required": ["city"]
}
}
}
]
# Actual functions
def get_weather(city: str, unit: str = "celsius") -> dict:
# In reality, call a weather API
return {"city": city, "temperature": 22, "unit": unit, "condition": "sunny"}
# Map names to functions
function_map = {
"get_weather": get_weather
}
2. 에이전트 루프 생성하기
에이전트 루프는 LLM에 메시지를 보내고, 도구 호출을 확인하고, 실행한 후, 모델이 최종 답변을 반환할 때까지 반복합니다.
def run_agent(user_message: str):
messages = [{"role": "user", "content": user_message}]
while True:
response = openai.ChatCompletion.create(
model="gpt-4",
messages=messages,
tools=tools,
tool_choice="auto"
)
message = response.choices[0].message
messages.append(message)
# If no tool calls, return the content
if not message.get("tool_calls"):
return message["content"]
# Execute each tool call
for tool_call in message.tool_calls:
function_name = tool_call.function.name
arguments = json.loads(tool_call.function.arguments)
if function_name in function_map:
result = function_map[function_name](**arguments)
else:
result = {"error": f"Unknown function: {function_name}"}
# Append tool result to messages
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": json.dumps(result)
})
이 루프는 LLM이 도구 호출 없이 응답을 생성할 때까지 계속되며, 이는 충분한 정보를 얻었음을 의미합니다.
3. 오류 및 예외 상황 처리하기
실제 에이전트는 다음을 처리해야 합니다:
- 잘못된 인수: 인수를 파싱하거나 함수를 호출할 때 예외를 잡으세요.
- 알 수 없는 도구: LLM이 스스로 수정할 수 있도록 오류 메시지를 반환하세요.
- 시간 초과: 외부 API 호출에 시간 초과를 설정하여 멈춤을 방지하세요.
- 속도 제한: 지수 백오프를 사용한 재시도를 구현하세요.
안정적인 에이전트를 위한 모범 사례
- 도구 수 제한: 도구가 너무 많으면 모델이 혼란스러워합니다. 관련 함수를 그룹화하거나 라우터를 사용하세요.
- 입력 검증: 실행 전에 모든 인수를 정제하고 검증하세요.
- 모든 것 로깅: 디버깅과 감사를 위해 도구 호출과 결과를 로깅하세요.
- 다양한 프롬프트로 테스트: 다양한 시나리오에서 에이전트가 올바른 도구를 선택하는지 확인하세요.
- 대체 수단 제공: 도구가 실패하면 에이전트가 대안을 시도하거나 명확한 설명을 요청해야 합니다.
함수 호출 지원 비교
| 제공업체 | 기능 이름 | 형식 |
|---|---|---|
| OpenAI | Function Calling | JSON Schema |
| Anthropic | Tool Use | JSON Schema |
| Function Calling | OpenAPI Schema |
고급 패턴
에이전트가 성장함에 따라 다음 패턴을 고려하세요:
- 병렬 도구 호출: 일부 모델은 여러 도구를 한 번에 요청할 수 있습니다. 속도를 위해 동시에 실행하세요.
- 휴먼 인 더 루프: 민감한 작업(예: 송금)의 경우 실행 전에 사람의 승인이 필요합니다.
- 메모리: 긴 세션에서 컨텍스트를 제공하기 위해 대화 기록과 도구 결과를 저장하세요.
- 도구 라우팅: 메인 LLM을 호출하기 전에 가벼운 분류기를 사용하여 관련 도구를 선택하세요.
함수 호출 디버깅
문제가 발생하면 다음을 확인하세요:
- 도구 설명이 명확하고 모호하지 않은가?
- 매개변수 이름과 타입이 올바른가?
- 모델이 올바른 도구를 선택할 만큼 충분한 컨텍스트를 가지고 있는가?
- 도구 결과를 올바르게 처리하고 있는가(예: JSON 직렬화)?
전체 메시지 기록과 도구 호출을 캡처하려면 로깅을 사용하세요. 종종 문제는 예상 인수와 실제 인수 간의 불일치입니다.
FAQ
함수 호출과 도구 사용의 차이점은 무엇인가요?
둘은 같은 개념을 가리킵니다. OpenAI는 "함수 호출"이라고 부르고, Anthropic은 "도구 사용"이라고 부릅니다. 둘 다 LLM이 외부 함수 실행을 요청할 수 있게 합니다.
오픈소스 모델과 함께 함수 호출을 사용할 수 있나요?
네, Llama 3.1과 같은 일부 오픈소스 모델은 함수 호출을 지원하며, LangChain과 같은 프레임워크가 추상화를 제공합니다. 하지만 지원 수준은 다양하며, 미세 조정이 필요하거나 특정 프롬프트 형식을 사용해야 할 수 있습니다.
LLM이 위험한 함수를 호출하지 못하게 하려면 어떻게 해야 하나요?
위험한 함수를 직접 노출하지 마세요. 허용 목록을 사용하고, 입력을 검증하며, 권한 검사를 구현하세요. 민감한 작업의 경우 실행 전에 사람의 확인을 요구하세요.
자체 AI 에이전트를 구축할 준비가 되셨나요? 간단한 도구를 정의하고 에이전트 루프를 테스트하는 것부터 시작하세요. 더 많은 개발자 도구를 보려면 도구 호출 페이로드를 디버깅할 수 있는 JSON Formatter를 확인하세요.