Les configurations de codage multi-agents locales utilisant Pi, llama-swap ou des outils similaires génèrent du code dans un environnement privé et hors ligne. Le problème : ils hallucinent des signatures d'API, inventent des packages inexistants et utilisent des motifs obsolètes. Ajouter un outil de recherche qui vérifie la documentation actuelle avant de générer du code résout ce problème. Ce tutoriel connecte votre configuration multi-agents locale à l'API Scavio (0,005 $/recherche) afin que les agents puissent vérifier les API, consulter les versions des packages et référencer la documentation actuelle.
Prérequis
- Une configuration multi-agents locale (Pi, llama-swap ou similaire)
- Python 3.9+ installé
- bibliothèque requests installée
- Une clé API Scavio depuis scavio.dev
Parcours
Étape 1: Créer l'outil de recherche de documentation
Créez une fonction de recherche optimisée pour les consultations de documentation de code. Elle cible des sites de documentation spécifiques et formate les résultats pour le contexte du code.
import os, requests
SCAVIO_KEY = os.environ['SCAVIO_API_KEY']
URL = 'https://api.scavio.dev/api/v1/search'
H = {'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json'}
def search_docs(query: str, language: str = 'python') -> str:
"""Search for code documentation and API references."""
# Add language context
doc_sites = {
'python': 'docs.python.org OR pypi.org OR readthedocs.io',
'javascript': 'developer.mozilla.org OR npmjs.com OR nodejs.org',
'typescript': 'typescriptlang.org OR npmjs.com',
'rust': 'docs.rs OR crates.io',
}
site_filter = doc_sites.get(language, '')
full_query = f'{query} {language} {site_filter}'.strip()
resp = requests.post(URL, headers=H,
json={'query': full_query, 'country_code': 'us', 'num_results': 5})
results = resp.json().get('organic_results', [])
if not results:
return f'No documentation found for: {query}'
return '\n\n'.join(
f'[{i+1}] {r["title"]}\n{r.get("snippet", "")}\nURL: {r["link"]}'
for i, r in enumerate(results)
)
# Test: search for API documentation
print(search_docs('requests post json headers', 'python'))
print('---')
print(search_docs('fetch api post request', 'javascript'))Étape 2: Ajouter la vérification des versions des packages
Avant d'utiliser un package dans le code généré, vérifiez qu'il existe et consultez la version actuelle. Cela empêche l'agent d'importer des packages inexistants.
def check_package(name: str, language: str = 'python') -> dict:
"""Verify a package exists and get current version info."""
if language == 'python':
query = f'pypi.org {name} package'
elif language in ('javascript', 'typescript'):
query = f'npmjs.com {name} package'
else:
query = f'{name} package {language}'
resp = requests.post(URL, headers=H,
json={'query': query, 'country_code': 'us', 'num_results': 3})
results = resp.json().get('organic_results', [])
if not results:
return {'name': name, 'exists': False}
# Check if pypi/npm appears in results
registry_hit = any('pypi.org' in r.get('link', '') or 'npmjs.com' in r.get('link', '')
for r in results)
return {
'name': name,
'exists': registry_hit,
'top_result': results[0]['title'],
'snippet': results[0].get('snippet', '')[:150],
'url': results[0]['link'],
}
# Test packages
for pkg in ['requests', 'fastapi', 'nonexistent-fake-pkg-xyz']:
result = check_package(pkg)
status = 'EXISTS' if result['exists'] else 'NOT FOUND'
print(f'[{status}] {pkg}: {result.get("top_result", "N/A")[:50]}')Étape 3: Créer l'interface des outils de l'agent
Définissez les outils que votre système multi-agents peut appeler. Les outils search_docs et check_package s'intègrent à toute configuration d'appel d'outils compatible OpenAI.
import json
AGENT_TOOLS = [
{
'type': 'function',
'function': {
'name': 'search_docs',
'description': 'Search for programming documentation, API references, and code examples. Use BEFORE writing code that uses external libraries or APIs.',
'parameters': {
'type': 'object',
'properties': {
'query': {'type': 'string', 'description': 'What to search for (e.g., "fastapi dependency injection")'},
'language': {'type': 'string', 'enum': ['python', 'javascript', 'typescript', 'rust'], 'description': 'Programming language context'}
},
'required': ['query']
}
}
},
{
'type': 'function',
'function': {
'name': 'check_package',
'description': 'Verify a package exists before importing it. Prevents hallucinated package names.',
'parameters': {
'type': 'object',
'properties': {
'name': {'type': 'string', 'description': 'Package name'},
'language': {'type': 'string', 'enum': ['python', 'javascript'], 'description': 'Package ecosystem'}
},
'required': ['name']
}
}
}
]
def handle_tool_call(name: str, args: dict) -> str:
if name == 'search_docs':
return search_docs(args['query'], args.get('language', 'python'))
elif name == 'check_package':
result = check_package(args['name'], args.get('language', 'python'))
return json.dumps(result)
return 'Unknown tool'
print('Agent tools defined:', [t['function']['name'] for t in AGENT_TOOLS])Étape 4: Intégrer dans la boucle multi-agents
Connectez les outils à votre système multi-agents local. L'agent de codage recherche la documentation avant d'écrire le code, et l'agent de révision vérifie les packages avant d'approuver.
def coding_agent_loop(task: str, model: str = 'llama3') -> str:
"""A coding agent that searches docs before generating code."""
llm_url = 'http://localhost:11434/v1/chat/completions'
messages = [
{'role': 'system', 'content': (
'You are a coding assistant. ALWAYS use search_docs to check API '
'signatures before writing code. ALWAYS use check_package to verify '
'packages exist before importing them. Write working, tested code.'
)},
{'role': 'user', 'content': task}
]
for turn in range(5):
resp = requests.post(llm_url, json={
'model': model, 'messages': messages,
'tools': AGENT_TOOLS, 'max_tokens': 1024
})
msg = resp.json()['choices'][0]['message']
messages.append(msg)
if not msg.get('tool_calls'):
return msg.get('content', '')
for tc in msg['tool_calls']:
args = json.loads(tc['function']['arguments']) if isinstance(tc['function']['arguments'], str) else tc['function']['arguments']
result = handle_tool_call(tc['function']['name'], args)
messages.append({'role': 'tool', 'tool_call_id': tc['id'], 'content': result})
return messages[-1].get('content', 'Max turns reached')
# Test the coding agent
code = coding_agent_loop('Write a Python function that fetches JSON from an API using httpx')
print(code[:500])Exemple Python
import os, requests, json
SCAVIO_KEY = os.environ['SCAVIO_API_KEY']
H = {'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json'}
def search_docs(query, lang='python'):
resp = requests.post('https://api.scavio.dev/api/v1/search', headers=H,
json={'query': f'{query} {lang} documentation', 'country_code': 'us', 'num_results': 3})
return '\n'.join(f'[{i+1}] {r["title"]}: {r.get("snippet","")}'
for i, r in enumerate(resp.json().get('organic_results', [])))
def check_pkg(name, lang='python'):
registry = 'pypi.org' if lang == 'python' else 'npmjs.com'
resp = requests.post('https://api.scavio.dev/api/v1/search', headers=H,
json={'query': f'{registry} {name}', 'country_code': 'us', 'num_results': 1})
results = resp.json().get('organic_results', [])
exists = any(registry in r.get('link', '') for r in results)
print(f"{'EXISTS' if exists else 'NOT FOUND'}: {name}")
print(search_docs('httpx async client'))
check_pkg('httpx')
check_pkg('fake-nonexistent-pkg')Exemple JavaScript
const SCAVIO_KEY = process.env.SCAVIO_API_KEY;
async function searchDocs(query, lang = 'javascript') {
const resp = await fetch('https://api.scavio.dev/api/v1/search', {
method: 'POST',
headers: { 'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({ query: `${query} ${lang} documentation`, country_code: 'us', num_results: 3 })
});
return ((await resp.json()).organic_results || []).map((r, i) => `[${i+1}] ${r.title}: ${r.snippet || ''}`).join('\n');
}
async function checkPkg(name) {
const resp = await fetch('https://api.scavio.dev/api/v1/search', {
method: 'POST',
headers: { 'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({ query: `npmjs.com ${name}`, country_code: 'us', num_results: 1 })
});
const results = (await resp.json()).organic_results || [];
console.log(`${results.some(r => r.link.includes('npmjs.com')) ? 'EXISTS' : 'NOT FOUND'}: ${name}`);
}
searchDocs('fetch api post').then(console.log);
checkPkg('express');Sortie attendue
[EXISTS] requests: requests 2.32.0 - PyPI
[EXISTS] fastapi: fastapi - PyPI - A modern, fast web framework
[NOT FOUND] nonexistent-fake-pkg-xyz
Agent tools defined: ['search_docs', 'check_package']
[1] requests - PyPI: HTTP library for Python
Requests allows you to send HTTP requests extremely easily...
URL: https://pypi.org/project/requests/