Conecte a un agente de voz con hechos en tiempo real insertando una llamada API de búsqueda entre la consulta hablada del usuario y el paso de generación de respuesta. Los agentes de voz sin conexión a tierra afirman con confianza información obsoleta o fabricada porque no tienen ningún mecanismo para verificar los hechos con fuentes actuales. Agregar un paso de búsqueda toma la consulta del usuario transcrita, recupera los resultados principales de Google u otras plataformas y los inyecta como contexto en el mensaje de respuesta. Este tutorial construye la capa base para canales de voz personalizados y de estilo VAPI utilizando la API de Scavio.
Requisitos previos
- Una plataforma de agente de voz (VAPI, Bland, Retell o personalizada)
- Python 3.8+ o Node.js 18+ instalado
- Una clave API de Scavio de scavio.dev
- Comprensión básica de la arquitectura del agente de voz (STT -> LLM -> TTS)
Guia paso a paso
Paso 1: Construya la función de búsqueda de conexión a tierra
Cree una función de búsqueda rápida optimizada para la latencia de voz: tiempo de espera de 5 segundos, solo los 3 primeros resultados, reducidos a los campos esenciales.
import requests, os
API_KEY = os.environ['SCAVIO_API_KEY']
def ground_search(query: str, max_results: int = 3) -> str:
"""Fast search optimized for voice agent grounding."""
try:
resp = requests.post('https://api.scavio.dev/api/v1/search',
headers={'x-api-key': API_KEY},
json={'platform': 'google', 'query': query}, timeout=5)
results = resp.json().get('organic_results', [])[:max_results]
context = []
for r in results:
context.append(f"{r.get('title', '')}: {r.get('snippet', '')}")
return '\n'.join(context)
except Exception:
return '' # Fail silently to avoid blocking the voice responsePaso 2: Clasificar consultas que necesitan fundamento
No todas las consultas de voz necesitan una búsqueda en la web. Clasifique cuáles se benefician de la conexión a tierra para ahorrar latencia en respuestas simples.
GROUND_PATTERNS = [
'what is', 'how much', 'when did', 'where is', 'who is',
'latest', 'current', 'today', 'price', 'hours', 'open',
'weather', 'news', 'score', 'status', 'schedule',
]
def needs_grounding(transcript: str) -> bool:
text = transcript.lower().strip()
if '?' in text:
return True
return any(p in text for p in GROUND_PATTERNS)
# Examples:
print(needs_grounding('What time does Target close today?')) # True
print(needs_grounding('Thanks, that sounds good')) # FalsePaso 3: Inyecte contexto de conexión a tierra en el mensaje LLM
Cree el mensaje de respuesta que incluya contexto básico cuando esté disponible, con instrucciones para preferir los datos de búsqueda al conocimiento de capacitación.
def build_grounded_prompt(transcript: str, system_prompt: str = '') -> str:
prompt = system_prompt + '\n\n' if system_prompt else ''
if needs_grounding(transcript):
context = ground_search(transcript)
if context:
prompt += f'LIVE SEARCH CONTEXT (prefer this over your training data):\n{context}\n\n'
prompt += f'User said: {transcript}\n'
prompt += 'Respond naturally and conversationally. Keep it under 3 sentences for voice delivery.'
return prompt
# Example:
prompt = build_grounded_prompt(
'What are the current gas prices in Austin?',
'You are a helpful voice assistant.'
)
print(prompt)Paso 4: Integre con su canal de voz
Inserte el paso de conexión a tierra en el proceso de procesamiento de su agente de voz, entre la conversión de voz a texto y la generación de LLM.
# Voice pipeline integration:
# STT -> grounding_middleware -> LLM -> TTS
def voice_middleware(transcript: str, voice_config: dict) -> dict:
"""Middleware that adds grounding to voice agent responses."""
prompt = build_grounded_prompt(transcript, voice_config.get('system_prompt', ''))
grounded = needs_grounding(transcript)
return {
'prompt': prompt,
'grounded': grounded,
'transcript': transcript,
}
# VAPI-style webhook handler:
def handle_vapi_webhook(payload: dict) -> dict:
transcript = payload.get('transcript', '')
result = voice_middleware(transcript, {'system_prompt': 'You are a helpful assistant.'})
return {'prompt': result['prompt']}
# Test:
result = voice_middleware('What is the current price of Bitcoin?', {'system_prompt': 'You are a crypto assistant.'})
print(f'Grounded: {result["grounded"]}')
print(result['prompt'][:300])Ejemplo en Python
import requests, os
H = {'x-api-key': os.environ['SCAVIO_API_KEY']}
def ground(query):
try:
data = requests.post('https://api.scavio.dev/api/v1/search', headers=H,
json={'platform': 'google', 'query': query}, timeout=5).json()
return '\n'.join(f"{r['title']}: {r.get('snippet', '')}" for r in data.get('organic_results', [])[:3])
except: return ''
def voice_prompt(transcript):
context = ground(transcript)
return f'Context:\n{context}\n\nUser: {transcript}\nRespond in 2-3 sentences.' if context else f'User: {transcript}\nRespond in 2-3 sentences.'
print(voice_prompt('What are gas prices in Austin today?'))Ejemplo en JavaScript
const H = {'x-api-key': process.env.SCAVIO_API_KEY, 'Content-Type': 'application/json'};
async function ground(query) {
try {
const r = await fetch('https://api.scavio.dev/api/v1/search', {
method: 'POST', headers: H, body: JSON.stringify({platform: 'google', query}),
signal: AbortSignal.timeout(5000)
});
const results = (await r.json()).organic_results || [];
return results.slice(0, 3).map(r => `${r.title}: ${r.snippet || ''}`).join('\n');
} catch { return ''; }
}
async function voicePrompt(transcript) {
const ctx = await ground(transcript);
return ctx ? `Context:\n${ctx}\n\nUser: ${transcript}` : `User: ${transcript}`;
}
voicePrompt('What are gas prices in Austin?').then(console.log);Salida esperada
A grounding layer for voice agents that classifies queries, runs fast search lookups, and injects live context into the LLM prompt before response generation.