Files
tia_regional_xai_tts_pool/README.md
2026-08-21 08:37:51 -03:00

11 KiB

TIA Voice API

Este repositorio contem a stack de voz-to-voz do projeto TIA.

Estrutura

  • src/app: gateway WebSocket, runtime LiveKit, providers e utilitarios
  • src/agent: pipeline e estagios do agente
  • tests: testes automatizados
  • docs: documentacao viva do projeto
  • k8s/livekit: imagem e manifest do pod dedicado do LiveKit
  • k8s/tia: imagem e manifest do pod da aplicacao com bridge e agent
  • requirements.txt: dependencias Python da aplicacao
  • livekit.yaml: configuracao local do servidor LiveKit

Setup local

make setup

O alvo make setup faz o bootstrap do ambiente local:

  • cria .venv priorizando python3.13, python3.12, python3.11, python3.10, python3.9, python3 e python
  • instala as dependencias de requirements.txt
  • cria .env.dev a partir de .env.example se o arquivo ainda nao existir

O projeto hoje exige Python 3.9 ate 3.13. Python 3.14 nao e aceito pelas dependencias atuais de livekit-agents==1.3.10.

Se voce tiver mais de um Python instalado e quiser forcar uma versao especifica no bootstrap:

make BOOTSTRAP_PY=python3.12 setup

Se voce preferir fazer manualmente ou quiser depurar o bootstrap, use:

python3.12 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -r requirements.txt
cp .env.example .env.dev

Se make test, make agent ou make bridge falharem com erro de virtualenv ausente, rode make setup primeiro.

Teste local

make test

O makefile executa os testes com .venv/bin/python e injeta PYTHONPATH=src, entao o comando deve ser chamado a partir da raiz do repositorio.

Execucao local

O .env.dev de desenvolvimento pode ser configurado em dois modos:

  • smoke test local: AGENT_BACKEND=remote_ws_fake, STT_PROVIDER=fake e TTS_PROVIDER=fake
  • integracao real: ajuste AGENT_BACKEND, STT_PROVIDER, TTS_PROVIDER e as credenciais externas necessarias

No modo fake, o agent nao depende de STT HTTP, ElevenLabs ou backend LLM externo. O STT fake consome uma sequencia configurada em FAKE_STT_TRANSCRIPTS e o TTS fake gera um tom PCM local para validar o pipeline de audio.

Importante: LIVEKIT_API_KEY e LIVEKIT_API_SECRET do .env.dev precisam ser identicos ao bloco keys de livekit.yaml. Se esses valores divergirem, o bridge falha ao conectar/publicar no LiveKit e o dispatch do agent retorna erro de autenticacao.

Para usar o STT HTTP real, configure no .env.dev:

  • STT_PROVIDER=internal_http
  • STT_URL=http://10.152.95.27:8100
  • STT_KEY=... se o servico exigir o header x-api-key
  • STT_LANG=portuguese

Observacao: o provider faz POST exatamente na URL configurada em STT_URL. Se o seu servico expuser uma rota especifica, use a URL completa, por exemplo http://10.152.95.27:8100/transcribe.

Para usar Azure Speech TTS com o plugin oficial do LiveKit, configure no .env.dev:

  • TTS_PROVIDER=azure
  • AZURE_SPEECH_KEY=...
  • AZURE_SPEECH_REGION=... ou AZURE_SPEECH_ENDPOINT=https://...cognitiveservices.azure.com/
  • AZURE_SPEECH_VOICE=pt-BR-FranciscaNeural
  • AZURE_SPEECH_LANGUAGE=pt-BR
  • AZURE_SPEECH_DEPLOYMENT_ID=... apenas para Custom Voice

Para usar xAI TTS, configure no .env.dev:

  • TTS_PROVIDER=xai
  • XAI_API_KEY=...
  • XAI_WEBSOCKET_URL=https://cloud9.api.x.ai/v1/tts
  • XAI_TTS_READINESS_MODE=connect opcional para validar apenas o handshake do WebSocket; default synthesize
  • XAI_TTS_VOICE=ara opcional
  • XAI_TTS_LANGUAGE=pt-BR opcional
  • TTS_FRAME_GAP_TIMEOUT_S=2 limite entre deltas de audio do xAI; quando estoura, o runtime registra Falha TTS, toca o audio de conforto e reenvia o texto

Para enviar logs estruturados ao Google Pub/Sub, configure:

  • GCP_PROJECT_ID=...
  • AGENT_PUBSUB_TOPIC=agent-logs ou projects/.../topics/agent-logs

Se uma dessas variaveis nao existir, os eventos estruturados continuam indo apenas para o log local. O ambiente tambem precisa ter credenciais Google disponiveis via Application Default Credentials ou service account com permissao de publicacao no topico.

Para subir o fluxo local de voz:

make local-up

Depois abra http://127.0.0.1:8000/voice-client. O cliente web agora vem com remote_ws_fake, fake STT e fake TTS por padrao para smoke test local.

Para rodar o teste operacional com STT Sofya, TTS xAI, Bridge e LiveKit reais:

make local-stresstest

O alvo sobe o ambiente local se necessario, executa python -m app.tools.local_stresstest e gera os artefatos em .run/local-stresstest/:

  • report.md: resumo em Markdown com tabelas e diagramas Mermaid
  • summary.json: resultado estruturado completo
  • stt_results.csv, tts_results.csv, e2e_results.csv: planilhas dos cenarios
  • timeline_excerpt.jsonl: eventos relevantes da timeline da chamada E2E
  • diagrams/*.svg: imagens estaticas dos fluxos, boas para preview no VSCode
  • diagrams/*.mmd: fontes Mermaid dos fluxos
  • stt_dumps/*.wav e stt_dumps/*.pcm: audio efetivamente enviado ao STT
  • WAVs gerados para baseline, variacoes, TTS e audio recebido do Bridge

Por padrao, o alvo habilita dumps de audio do STT e logs de VAD do agent (FLOW_LOG_VAD_DECISIONS=1, FLOW_LOG_VAD_ACTIVITY=1). O agent local e reiniciado antes do teste para garantir que esses flags entrem no processo.

Se STRESS_AUDIO nao for informado, o runner gera um baseline sintetico com xAI TTS usando STRESS_SYNTH_TEXT, ou STRESS_EXPECTED_TEXT quando STRESS_SYNTH_TEXT nao for definido. Quando houver uma gravacao humana, rode:

STRESS_AUDIO=/caminho/audio_16k_mono.wav make local-stresstest

Variaveis uteis:

  • STRESS_EXPECTED_TEXT: frase esperada para calculo de WER
  • STRESS_SYNTH_TEXT: frase usada na sintese do baseline xAI TTS, default igual a STRESS_EXPECTED_TEXT
  • STRESS_CRITICAL_TERMS: termos obrigatorios separados por virgula
  • STRESS_WER_THRESHOLD: limite de WER, default 0.20
  • STRESS_REPEAT: repeticoes dos cenarios STT, default 1; com os 25 cenarios atuais, gera 25 chamadas ao STT. Use STRESS_REPEAT=2 para 50 chamadas
  • STRESS_CONCURRENCY: concorrencia dos cenarios STT, default 2
  • STRESS_PREFIX_TEXT: prefixo que precisa aparecer no inicio da transcricao, default primeiras palavras de STRESS_EXPECTED_TEXT
  • STRESS_PREFIX_WORDS: quantidade de palavras usadas no prefixo automatico, default 2
  • STRESS_VAD_PROXY_DBFS: limiar RMS usado na analise local de VAD proxy, default -45
  • STRESS_VAD_PREFIX_PADDING_MS: padding usado na analise local de VAD proxy, default vem de VAD_PREFIX_PADDING_DURATION
  • STRESS_VAD_MIN_SPEECH_MS: fala minima usada na analise local de VAD proxy, default 100
  • VAD_PREFIX_PADDING_DURATION: pre-roll do LiveKit VAD, default 2.0 segundos
  • VAD_PREFIX_PADDING_MIN_DURATION: piso aplicado tambem sobre override de call_config, default 2.0 segundos
  • STT_INPUT_PREFIX_PADDING_MS: silencio curto adicionado antes do WAV enviado ao STT HTTP, default 250
  • STT_DUMP_DIR: diretorio dos WAV/PCM enviados ao STT, default .run/local-stresstest/stt_dumps
  • FLOW_LOG_VAD_DECISIONS: habilita logs vad_speech_start/vad_speech_end, default 1 no alvo
  • FLOW_LOG_VAD_ACTIVITY: habilita logs vad_activity, default 1 no alvo
  • STRESS_RESTART_AGENT_FOR_DIAGNOSTICS: reinicia o agent antes do teste, default 1
  • STRESS_STARTUP_WAIT_S: tempo maximo para aguardar Bridge e agent runtime, default 180
  • STRESS_STARTUP_POLL_S: intervalo entre probes de prontidao, default 3
  • STRESS_SKIP_LOCAL_WAIT: use 1 para pular a espera inicial
  • STRESS_BRIDGE_HEALTH_URL: URL de health do Bridge, derivada de STRESS_BRIDGE_URL por padrao
  • STRESS_AGENT_HEALTH_URL: URL de health do agent runtime, default http://127.0.0.1:18081/
  • STRESS_REPORT_DIR: diretorio de saida, default .run/local-stresstest

Comandos auxiliares do modo local:

make local-status
make local-logs
make bridge-logs
make agent-logs
make local-down

Se o agent falhar com worker process is not responding.. worker crashed? e o log mostrar erro de bind na porta 18081, existe um worker antigo preso nessa porta. Nesse caso, rode make agent-down e depois make agent-up ou make local-up novamente.

Kubernetes

A pasta k8s agora esta organizada em dois blocos:

  • k8s/livekit/Dockerfile: usa a imagem oficial livekit/livekit-server como base para publicacao no registro privado da empresa
  • k8s/livekit/deployment.yaml: deployment e service do pod exclusivo do LiveKit
  • k8s/tia/Dockerfile: mesma imagem da aplicacao Python da raiz do repo, mantida ao lado do manifest para facilitar pipeline de build/publicacao
  • k8s/tia/deployment.yaml: deployment e service do pod tia-app, com dois containers na mesma imagem: tia-bridge e tia-agent

Os dois Dockerfiles devem ser buildados a partir da raiz do repositorio, porque dependem do contexto raiz para copiar requirements.txt, src/ e livekit.yaml.

Exemplos:

docker build -f k8s/livekit/Dockerfile -t registry.example.com/tia/livekit:TAG .
docker build -f k8s/tia/Dockerfile -t registry.example.com/tia/app:TAG .

Depois do push para o registry privado, ajuste as imagens em k8s/livekit/deployment.yaml e k8s/tia/deployment.yaml ou substitua os placeholders via pipeline:

  • LIVEKIT_IMAGE_REPOSITORY:LIVEKIT_IMAGE_TAG
  • TIA_IMAGE_REPOSITORY:TIA_IMAGE_TAG

Aplicacao dos manifests:

kubectl apply -f k8s/livekit/deployment.yaml
kubectl apply -f k8s/tia/deployment.yaml

Observacoes:

  • k8s/livekit/Dockerfile embute o arquivo livekit.yaml dentro da imagem; se a configuracao do LiveKit mudar, a imagem precisa ser rebuildada
  • k8s/tia/deployment.yaml ainda usa envs inline de placeholder para LIVEKIT_API_KEY e LIVEKIT_API_SECRET; o passo seguinte natural e migrar isso para Secret e demais configs para ConfigMap
  • o bridge atende na porta 8000 e o agent expõe a porta interna 18081

Comandos uteis

make test
make agent
make bridge
make livekit

Todos os comandos assumem o codigo em src, portanto a raiz do projeto deve ser usada como diretorio de execucao.

Documentacao

  • docs/README.md: indice das docs do projeto
  • docs/refactor-plan.md: plano do refactor incremental
  • docs/refactor-log.md: registro das mudancas por etapa
  • docs/api-overview.md: documentacao viva da API e do comportamento atual

Regional xAI TTS pool (Kubernetes)

Esta versão inclui uma arquitetura opcional para alta disponibilidade do TTS xAI com Pods TIA regionais, pool WebSocket pré-aquecido por Pod, readiness orientada a capacidade e failover via Service/Load Balancer.

Documentação:

  • docs/regional/ARQUITETURA_TIA_XAI_REGIONAL.md
  • docs/regional/DEPLOYMENT_TIA_XAI_REGIONAL.md
  • docs/regional/TESTES_TIA_XAI_REGIONAL.md

Código principal:

  • src/app/livekit/adapters/xai_pool_proxy.py

Manifests e scripts:

  • k8s/regional/
  • scripts/render-regional-k8s.sh
  • scripts/validate-regional-k8s.sh
  • scripts/deploy-regional-k8s.sh

O modo antigo de conexão direta com xAI foi preservado. O deployment regional é opt-in.