Documentação do processo de evolução de um agente de voz LiveKit do…
INEMA
Criando o V4
Aqui está a sugestão de melhoria conceitual que transformará o seu basic_agent_v3.py em um Agente LiveKit v4 inteligente e modular, com roteamento automático e expansão futura garantida.
Depois desta etapa, eu preparo a instrução completa de implementação para o dev.
🌐 SUGESTÃO DE MELHORIA – AGENTE LIVEKIT v4⌗
Objetivo⌗
Evoluir o Agente v3 de um modelo linear (voz → LLM → resposta) para um modelo cognitivo modular, com tomada de decisão inteligente sobre o tipo de ação necessária.
🔁 Estrutura Proposta⌗
/agente_v4/
│
├── basic_agent_v4.py ← orquestra voz, STT, TTS, sessão e integração geral
├── router_llm.py ← agente LLM de decisão inteligente (ações / conhecimento / conversa)
├── agente_actions.py ← ações executáveis (email, calendário, tarefas, etc.)
├── agente_know.py ← consultas (RAG, SQL, JSON, API)
└── agente_assistente.py ← diálogo natural e estilo de fala
🔧 Principais Melhorias⌗
1️⃣ Roteamento Inteligente (Router LLM)⌗
- Novo agente
router_llm.pycom prompt avançado. -
Interpreta a intenção da frase do usuário e retorna:
-
"ação"→ executa funções doagente_actions.py "conhecimento"→ consultaagente_know.py"conversa"→ envia paraagente_assistente.py
2️⃣ System Prompt Cognitivo⌗
- Cria contexto global no
RouterLLMpara entender intenção, prioridade e contexto anterior. - Responde em formato JSON estruturado, ex:
{"tipo": "ação", "alvo": "agendar_reuniao", "contexto": "usuário quer marcar um horário amanhã"}
3️⃣ Modularização Real⌗
- Cada módulo (
actions,know,assistente) pode ser desenvolvido, atualizado e testado independentemente. - Suporte futuro para múltiplos “subagentes” especializados.
4️⃣ Contexto Dinâmico⌗
- O
router_llmpode manter histórico curto (últimas 3 mensagens) para compreender sequência de intenções. - Exemplo: “Agende amanhã às 10h” → entende que se refere à reunião anterior.
5️⃣ Logs e Aprendizado⌗
- Registra todas as decisões do roteador em
logs/router_decisions.jsonpara aprimorar comportamento.
6️⃣ Preparado para Expansão⌗
- Facilmente integrável com bancos vetoriais (RAG), Pinecone, Notion API, ou Google Calendar.
- Permite adicionar novos módulos (por exemplo:
agente_pagamentos.py) sem alterar o core.
🔍 Resultado Esperado⌗
- O agente passa a entender o tipo de pedido e agir conforme a intenção real.
- Responde mais rápido, de forma contextual e com menos dependência do LLM central.
- Sistema mais escalável, com separação clara entre: voz / decisão / ação / conhecimento / diálogo.
Exemplo de Fluxo Real⌗
Usuário: “Quantos produtos temos em estoque do tipo sabonete?”
- O LLM interpreta a intenção → “consulta de produto”.
- Chama
buscar_informacao("sabonete"). - O
KnowledgeRouterescolhefrom_sql. - Retorna: “Produto: Sabonete de Lavanda, R$12,00, 45 unidades.”
A base pronta para evoluir o basic_agent_v3.py (que já faz STT, TTS e usa o GPT-4o-mini) em direção ao modelo dinâmico de integração universal, onde o agente pode buscar informações em qualquer tipo de base (RAG, SQL, API, etc.) conforme o contexto da conversa.
Abaixo está um plano prático e modular para atingir isso:
1️⃣ Estrutura Conceitual⌗
A meta é que, durante a conversa, o agente consiga:
- Detectar intenção de busca (ex: “qual o preço do produto X?”);
- Escolher fonte de dados apropriada (RAG, SQL, API, arquivo etc.);
- Executar a busca e retornar a resposta contextualizada.
Para isso, o ideal é adicionar uma camada de “roteamento de conhecimento”, que decide dinamicamente de onde buscar a informação.
2️⃣ Módulo de Integração Dinâmica⌗
Crie um arquivo novo chamado knowledge_router.py:
```# knowledge_router.py from typing import Optional import json import sqlite3 import chromadb import httpx
class KnowledgeRouter: def init(self): self.chroma_client = chromadb.Client() self.sql_conn = sqlite3.connect("base.db")
async def query(self, query_text: str) -> str:
"""Determina automaticamente qual fonte usar"""
if "manual" in query_text.lower():
return await self.from_json("manual.json", query_text)
elif "produto" in query_text.lower():
return await self.from_sql(query_text)
elif "documento" in query_text.lower() or "relatório" in query_text.lower():
return await self.from_rag(query_text)
elif "clima" in query_text.lower():
return await self.from_api(query_text)
else:
return "Desculpe, não encontrei uma base correspondente."
async def from_json(self, filename: str, query_text: str) -> str:
with open(filename, "r", encoding="utf-8") as f:
data = json.load(f)
for k, v in data.items():
if k.lower() in query_text.lower():
return v
return "Nada encontrado no arquivo JSON."
async def from_sql(self, query_text: str) -> str:
cur = self.sql_conn.cursor()
cur.execute("SELECT nome, preco, estoque FROM produtos WHERE nome LIKE ?", (f"%{query_text}%",))
result = cur.fetchone()
if result:
return f"Produto: {result[0]}, Preço: R${result[1]}, Estoque: {result[2]}"
return "Produto não encontrado."
async def from_rag(self, query_text: str) -> str:
collection = self.chroma_client.get_collection("documentos")
results = collection.query(query_texts=[query_text], n_results=2)
if results and results['documents']:
return "\n".join(results['documents'][0])
return "Nada relevante encontrado na base semântica."
async def from_api(self, query_text: str) -> str:
async with httpx.AsyncClient() as client:
r = await client.get("https://api.open-meteo.com/v1/forecast", params={"latitude": -23.55, "longitude": -46.63})
return f"Dados meteorológicos recebidos: {r.status_code}"```
3️⃣ Conectando ao Agente (basic_agent_v3.py)⌗
Dentro da classe Assistant, adicione um método de ferramenta:
```from knowledge_router import KnowledgeRouter
router = KnowledgeRouter()
@function_tool async def buscar_informacao(self, context: RunContext, consulta: str) -> str: """Busca informação de forma dinâmica em várias bases.""" resposta = await router.query(consulta) return resposta```
Agora o agente pode responder a perguntas como:
- “O que diz o manual sobre devolução?”
- “Qual o estoque do produto Sabonete?”
- “Mostre documentos sobre atendimento técnico.”
Ele automaticamente escolhe a base correta.
4️⃣ Mecanismo de Contexto Dinâmico⌗
Para torná-lo autoaprendente, adicione um “modo inteligente”:
- Ao detectar falha de busca, o LLM pode gerar sugestões de novas fontes.
- O agente pode armazenar logs e adaptar o roteamento (ex: salvar em
router_history.json).
5️⃣ Próximos Passos (para escalar)⌗
|
Consultas Toda conversa passa pelo LLM — entre o áudio chegar (STT) e a resposta voltar (TTS), você pode interceptar e rotear a consulta para qualquer fonte (RAG, SQL, API etc.) antes de enviar a resposta final.
Ação
Se a pessoa disser algo como “quero agendar uma reunião”, o item 5 (roteamento de ação) identifica a intenção e direciona o fluxo para a função agendar_reuniao() — o agente não pergunta mais nada ao LLM, apenas executa a ação e retorna o resultado.
- Captura de voz (microfone ou WebRTC)
- Transcrição STT (Deepgram ou OpenAI Whisper)
- Interpretação LLM (OpenAI GPT-4o-mini)
- Roteamento de intenção (decisão: ação, consulta ou resposta)
- Execução de ferramenta (
[@function_tool](https://t.me/function_tool)) - Consulta de dados (RAG, SQL, JSON, API etc.)
- Retorno de resultado ao LLM
- Geração de texto final
- Conversão TTS (OpenAI TTS)
- Envio de áudio de volta (LiveKit)
Criando Acoes entre as conversas
- Captura de voz (microfone via LiveKit)
- Transcrição STT (Deepgram – modelo nova-2, idioma pt-BR)
- Interpretação LLM (OpenAI GPT-4o-mini)
- Geração de resposta textual direta (sem roteamento dinâmico)
- Conversão TTS (OpenAI TTS – voz alloy)
- Envio de áudio ao usuário (LiveKit)
Versão Funcional do V2 e V3 (v2 ingles, v3 adaptado a portugues)
LiveKit - Funcionamento
1