Tool Use Patterns
Velké jazykové modely a AI agenti revolucionizují způsob, jak interagujeme s nástroji a automatizujeme složité úkoly. Správné pochopení vzorů jejich používání je klíčové pro maximalizaci efektivity a minimalizaci chyb.
Tool Use Patterns: Efektivní využití nástrojů v LLM agentech
Moderní jazykové modely získaly schopnost využívat externí nástroje – od API volání přes databázové dotazy až po složité systémové operace. Klíčem k úspěchu není jen technická implementace, ale zejména správné návrhové vzory (patterns), které zajistí spolehlivost a efektivitu celého systému.
ReAct Pattern: Základní stavební kámen
ReAct (Reasoning + Acting) představuje fundamentální vzor pro tool use. Model postupuje v cyklech: analyzuje situaci, rozhodne se pro akci, provede ji a vyhodnotí výsledek. Tento pattern zajišťuje transparentnost rozhodovacích procesů a umožňuje debugging.
class ReActAgent:
def __init__(self, llm, tools):
self.llm = llm
self.tools = {tool.name: tool for tool in tools}
def run(self, task):
context = f"Task: {task}\n"
max_iterations = 10
for i in range(max_iterations):
# Reasoning phase
response = self.llm.generate(
f"{context}\nWhat should I do next? Think step by step."
)
if "FINAL_ANSWER:" in response:
return self.extract_final_answer(response)
# Acting phase
if "ACTION:" in response:
action, args = self.parse_action(response)
result = self.tools[action].execute(args)
context += f"Action: {action}({args})\nResult: {result}\n"
return "Max iterations reached"
Chain of Tools Pattern
Při složitějších úkolech potřebujeme řetězit více nástrojů dohromady. Chain of Tools pattern definuje explicitní pořadí operací a předávání dat mezi jednotlivými kroky.
class ToolChain:
def __init__(self, steps):
self.steps = steps
async def execute(self, initial_data):
current_data = initial_data
for step in self.steps:
try:
current_data = await step.process(current_data)
self.log_step(step.name, current_data)
except Exception as e:
return self.handle_chain_failure(step, e, current_data)
return current_data
# Použití pro data pipeline
pipeline = ToolChain([
DatabaseQuery("SELECT * FROM users WHERE active=1"),
DataTransform("normalize_emails"),
APICall("send_newsletter"),
LogResults("newsletter_campaign")
])
result = await pipeline.execute({"campaign_id": "2024-01"})
Tool Selection Pattern
Když máme k dispozici více nástrojů pro stejný typ úkolu, potřebujeme inteligentní mechanismus výběru. Tool Selection pattern kombinuje metadata nástrojů s kontextovým rozhodováním modelu.
class ToolSelector:
def __init__(self, tools):
self.tools = tools
self.usage_stats = defaultdict(lambda: {"success": 0, "failure": 0})
def select_tool(self, task_description, context):
# Získání kandidátů podle capability
candidates = [t for t in self.tools if t.can_handle(task_description)]
if len(candidates) == 1:
return candidates[0]
# LLM rozhodnutí s metrikami
tool_info = []
for tool in candidates:
stats = self.usage_stats[tool.name]
success_rate = stats["success"] / (stats["success"] + stats["failure"] + 1)
tool_info.append({
"name": tool.name,
"description": tool.description,
"success_rate": success_rate,
"avg_latency": tool.avg_latency
})
selection_prompt = f"""
Task: {task_description}
Context: {context}
Available tools:
{json.dumps(tool_info, indent=2)}
Select the most appropriate tool and explain why.
"""
response = self.llm.generate(selection_prompt)
return self.parse_tool_selection(response, candidates)
Error Recovery Pattern
Robustní tool use systémy musí elegantně zvládat chyby. Error Recovery pattern implementuje hierarchii fallback strategií – od simple retry přes alternativní nástroje až po graceful degradation.
class ResilientToolExecutor:
def __init__(self, primary_tool, fallback_tools=None):
self.primary_tool = primary_tool
self.fallback_tools = fallback_tools or []
self.retry_config = {"max_attempts": 3, "backoff": 2}
async def execute_with_recovery(self, args):
# Pokus s primárním nástrojem
for attempt in range(self.retry_config["max_attempts"]):
try:
result = await self.primary_tool.execute(args)
return {"success": True, "result": result, "tool_used": self.primary_tool.name}
except RetryableError as e:
if attempt < self.retry_config["max_attempts"] - 1:
await asyncio.sleep(self.retry_config["backoff"] ** attempt)
continue
except NonRetryableError:
break
# Fallback nástroje
for fallback_tool in self.fallback_tools:
if fallback_tool.can_substitute(self.primary_tool):
try:
adapted_args = self.adapt_args(args, fallback_tool)
result = await fallback_tool.execute(adapted_args)
return {
"success": True,
"result": result,
"tool_used": fallback_tool.name,
"fallback": True
}
except Exception:
continue
return {"success": False, "error": "All recovery attempts failed"}
Parallel Tool Execution
Pro performance-kritické aplikace je klíčová paralelizace. Tento pattern umožňuje současné spuštění nezávislých nástrojů s inteligentním řízením resources a dependency management.
class ParallelToolManager:
def __init__(self, max_concurrency=5):
self.max_concurrency = max_concurrency
self.semaphore = asyncio.Semaphore(max_concurrency)
async def execute_parallel(self, tool_tasks):
# Rozdělení podle dependencies
independent_tasks = []
dependent_tasks = []
for task in tool_tasks:
if task.dependencies:
dependent_tasks.append(task)
else:
independent_tasks.append(task)
# Paralelní spuštění nezávislých úkolů
results = {}
independent_results = await asyncio.gather(*[
self._execute_with_semaphore(task) for task in independent_tasks
], return_exceptions=True)
# Aktualizace výsledků
for task, result in zip(independent_tasks, independent_results):
results[task.id] = result
# Sekvenční zpracování dependent úkolů
for task in dependent_tasks:
if self._dependencies_satisfied(task, results):
result = await self._execute_with_semaphore(task)
results[task.id] = result
return results
async def _execute_with_semaphore(self, task):
async with self.semaphore:
return await task.tool.execute(task.args)
Praktické tipy pro implementaci
Při implementaci tool use patterns doporučujeme:
- Monitoring a logging: Logujte všechna tool volání včetně latence a error rates
- Tool versioning: Implementujte verzování pro backward compatibility
- Resource management: Používejte connection pooling a rate limiting
- Testing: Mockujte externí nástroje pro unit testy
- Security: Validujte všechny inputs a implementujte sandboxing
Shrnutí
Tool Use Patterns představují kritickou součást moderních LLM aplikací. ReAct pattern poskytuje základ pro reasoning, zatímco pokročilé vzory jako Chain of Tools, Tool Selection a Error Recovery zajišťují robustnost a škálovatelnost. Správná implementace těchto patterns, kombinovaná s důkladným monitoringem a testováním, vytváří spolehlivé systémy schopné zvládat komplexní real-world úkoly. Klíčem k úspěchu je vyvážení flexibility s předvídatelností a vždy mít připraven plán B pro situace, kdy primary nástroje selžou.