Function Calling tutorial
Function Calling je klíčová technologie, která umožňuje LLM modelům a AI agentům vykonávat konkrétní funkce a interagovat s externími systémy. Tento tutoriál vás provede od základů až po pokročilé techniky implementace.
Úvod do Function Calling v Large Language Models
Function Calling (také známé jako Tool Use) představuje revoluční přístup k rozšíření schopností velkých jazykových modelů. Místo pouhého generování textu mohou LLM modely nyní aktivně volat externí funkce, API nebo nástroje, což jim umožňuje provádět konkrétní akce a získávat real-time data.
Tato technologie transformuje statické chatboty na dynamické agenty schopné interagovat s externím světem - od získávání aktuálních informací z databází po ovládání IoT zařízení.
Jak Function Calling funguje
Proces Function Calling probíhá v několika krocích:
- Definice funkcí - Specifikujeme dostupné funkce včetně jejich parametrů
- Požadavek uživatele - LLM analyzuje dotaz a rozhodne, zda potřebuje zavolat funkci
- Výběr a volání - Model vybere vhodnou funkci a vygeneruje správné parametry
- Zpracování výsledku - Aplikace provede funkci a vrátí výsledek modelu
- Finální odpověď - LLM formuluje odpověď na základě získaných dat
Praktická implementace s OpenAI API
Podívejme se na konkrétní příklad implementace Function Calling pomocí OpenAI API v Pythonu:
import openai
import json
import requests
# Definice funkcí, které může LLM volat
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Získá aktuální počasí pro zadané město",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "Název města"
},
"units": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "Teplotní jednotky"
}
},
"required": ["city"]
}
}
}
]
def get_weather(city, units="celsius"):
"""Simulace API call pro počasí"""
# V reálné aplikaci by zde byl call na weather API
return {
"city": city,
"temperature": "22°C" if units == "celsius" else "72°F",
"condition": "slunečno",
"humidity": "65%"
}
Hlavní komunikační loop
def chat_with_functions(user_message):
# Inicializace konverzace
messages = [
{"role": "system", "content": "Jsi užitečný asistent s přístupem k funkcím."},
{"role": "user", "content": user_message}
]
# První request s definicí funkcí
response = openai.chat.completions.create(
model="gpt-4-1106-preview",
messages=messages,
tools=tools,
tool_choice="auto"
)
response_message = response.choices[0].message
messages.append(response_message)
# Kontrola, zda model chce volat funkci
if response_message.tool_calls:
for tool_call in response_message.tool_calls:
function_name = tool_call.function.name
function_args = json.loads(tool_call.function.arguments)
# Volání příslušné funkce
if function_name == "get_weather":
function_response = get_weather(**function_args)
# Přidání výsledku do konverzace
messages.append({
"tool_call_id": tool_call.id,
"role": "tool",
"name": function_name,
"content": json.dumps(function_response)
})
# Druhý request s výsledky funkcí
final_response = openai.chat.completions.create(
model="gpt-4-1106-preview",
messages=messages
)
return final_response.choices[0].message.content
return response_message.content
# Použití
result = chat_with_functions("Jaké je počasí v Praze?")
print(result)
Pokročilé techniky a best practices
Validace parametrů
Klíčové je implementovat robustní validaci parametrů, protože LLM může někdy generovat neplatné hodnoty:
from pydantic import BaseModel, ValidationError
from typing import Literal
class WeatherRequest(BaseModel):
city: str
units: Literal["celsius", "fahrenheit"] = "celsius"
def validate_city(cls, v):
if len(v.strip()) < 2:
raise ValueError("Město musí mít alespoň 2 znaky")
return v.strip().title()
def safe_get_weather(tool_call):
try:
args = json.loads(tool_call.function.arguments)
validated_args = WeatherRequest(**args)
return get_weather(validated_args.city, validated_args.units)
except (ValidationError, json.JSONDecodeError) as e:
return {"error": f"Neplatné parametry: {str(e)}"}
Error handling a fallbacks
def robust_function_call(tool_call, max_retries=3):
for attempt in range(max_retries):
try:
function_name = tool_call.function.name
if function_name == "get_weather":
return safe_get_weather(tool_call)
return {"error": f"Neznámá funkce: {function_name}"}
except Exception as e:
if attempt == max_retries - 1:
return {"error": f"Funkce selhala po {max_retries} pokusech: {str(e)}"}
continue
Konkrétní use case: Database agent
Praktický příklad agenta pro práci s databází:
database_tools = [
{
"type": "function",
"function": {
"name": "execute_query",
"description": "Provede SQL SELECT dotaz na databázi",
"parameters": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "SQL SELECT dotaz"
},
"table": {
"type": "string",
"description": "Název tabulky pro validaci"
}
},
"required": ["query", "table"]
}
}
}
]
def execute_query(query, table):
"""Bezpečné provedení SQL dotazu s validací"""
# Základní SQL injection prevence
forbidden_keywords = ["DROP", "DELETE", "UPDATE", "INSERT", "ALTER"]
if any(keyword in query.upper() for keyword in forbidden_keywords):
return {"error": "Dotaz obsahuje nepovolené operace"}
# Simulace DB call
if "users" in table.lower():
return {
"results": [
{"id": 1, "name": "Jan Novák", "email": "[email protected]"},
{"id": 2, "name": "Marie Svobodová", "email": "[email protected]"}
],
"count": 2
}
return {"results": [], "count": 0}
Optimalizace a monitoring
Pro produkční nasazení je důležité implementovat monitoring a optimalizace:
import time
import logging
from functools import wraps
def monitor_function_calls(func):
@wraps(func)
def wrapper(*args, **kwargs):
start_time = time.time()
function_name = func.__name__
try:
result = func(*args, **kwargs)
execution_time = time.time() - start_time
logging.info(f"Function {function_name} executed in {execution_time:.2f}s")
return result
except Exception as e:
logging.error(f"Function {function_name} failed: {str(e)}")
raise
return wrapper
@monitor_function_calls
def get_weather_monitored(city, units="celsius"):
# Implementace s monitoringem
return get_weather(city, units)
Bezpečnostní aspekty
Function Calling přináší nové bezpečnostní výzvy, které je třeba řešit:
- Sandboxing - Izolace funkcí od kritických systémových operací
- Rate limiting - Omezení počtu volání funkcí na časovou jednotku
- Whitelisting - Explicitní seznam povolených operací
- Input validation - Důsledná validace všech parametrů
- Audit logging - Logování všech volání funkcí pro analýzu
Shrnutí
Function Calling představuje zásadní evoluci v oblasti LLM aplikací, umožňující vytváření skutečně interaktivních AI agentů. Úspěšná implementace vyžaduje pečlivé navrhování funkcí, robustní error handling a důsledné zabezpečení. S rostoucí adopcí této technologie můžeme očekávat vznik stále sofistikovanějších AI systémů schopných komplexních interakcí s reálným světem. Klíčem k úspěchu je vyvážení funkčnosti s bezpečností a udržení kontroly nad tím, co AI agent může a nemůže dělat.