Módulos do Código — Referência Detalhada¶
vox_ai.py — Ponto de Entrada Principal¶
Arquivo principal da aplicação Streamlit. Orquestra todos os outros modulos. É o único arquivo executado diretamente pelo Streamlit (configurado como app_file no pyproject.toml).
Fluxo de inicialização:
- Importa
startup_patch(sempre primeiro, para corrigir o problema dotorch.classes). - Chama
configurar_pagina()ecarregar_css()da UI. - Gera o
session_id(uuid4()) e o salva no Supabase se não existir nosession_state. - Renderiza a sidebar com
carregar_sidebar(SIDEBAR_BODY, SIDEBAR_FOOTER). - Configura a API do Gemini com
configurar_api_gemini(). - Inicializa os históricos de chat e o objeto de chat via
inicializar_chat_modelo(). - Renderiza o historico de mensagens existente na sessão (
hist_exibir). - Exibe a mensagem de boas-vindas (
SAUDACAO) na primeira visita e chamast.rerun().
Fluxo de processamento de prompt:
O arquivo gerencia dois tipos de entrada: texto via st.chat_input e áudio via st.audio_input (dentro de um st.popover). O ID do último áudio é salvo em session_state como ultimo_audio_id para evitar reprocessamento ao re-renderizar a página. O bloco try central chama semantica(), gerar_resposta(), salvar_log_chat() e st.rerun(). Em caso de exceção, chama salvar_erro() e exibe o error_id ao usuário.
src/config.py — Configurações Globais¶
Centraliza todas as constantes e configurações do sistema. Importado por praticamente todos os outros modulos.
| Constante | Valor | Descrição |
|---|---|---|
GEMINI_MODEL_NAME |
gemini-3-flash-preview |
Modelo LLM para geracao de respostas |
MODELO_SEMANTICO_NOME |
gemini-embedding-001 |
Modelo de embeddings para o RAG |
TAMANHO_VETOR_SEMANTICO |
1536 |
Dimensão do vetor (DEVE corresponder a coluna do banco) |
SEMANTICA_THRESHOLD |
0.5 |
Similaridade minima para um chunk ser considerado relevante |
LIMITE_TEMAS |
10 |
Quantos chunks são buscados na primeira fase do RAG |
MAX_CHUNCK |
25 |
Maximo de chunks na Estratégia de Contexto Expandido |
CSS_PATH |
static/css/style.css |
Caminho do CSS customizado injetado no Streamlit |
get_secret(key, default=''): Busca credencial com fallback: (1) st.secrets, (2) variáveis de ambiente. Suporta chaves aninhadas com ponto como separador: 'supabase.url' busca st.secrets['supabase']['url'].
StatusConhecimento: Enum para status de aprovação de item da base: PENDENTE = -1, REJEITADO = 0, APROVADO = 1.
src/core/database.py — Camada de Dados¶
Responsável por toda a comunicação com o Supabase. Contém o cliente singleton e todas as funções de leitura/escrita.
get_db_client() -> Client: Cria e retorna o cliente Supabase. Decorado com@st.cache_resource, garantindo uma única instância por execução. RetornaNonese as credenciais não forem encontradas.salvar_sessao(session_id): Insere novo registro na tabelasessions. Chamada uma única vez na inicialização do app.salvar_log_chat(session_id, git_version, prompt, response, fonte_info, lista_kb_ids): Salva o par pergunta-resposta nochat_logse em seguida cria os registros relacionais emchat_logs_kb. O camposimilarityé salvo quando disponivel (busca vetorial) ouNone(Estratégia de Contexto Expandido).salvar_erro(session_id, git_version, error_msg) -> str: Registra exceção na tabelaerror_logs. Geraerror_idcurto (8 chars) viauuid4()[:8]exibido ao usuário. Retorna'ERRO-DB'se a própria gravação falhar.salvar_report(...) -> bool: Salva denuncia emuser_reportscom histórico completo.get_categorias_erro() -> list: Buscareport_categoriespara popular o selectbox do dialog de reporte.buscar_referencias_db(vector_embedding, threshold, limit, filter_topic) -> list: Executa a RPCmatch_knowledge_basevalidando dimensão do vetor antes de enviar.buscar_chunks_por_topico(topico_alvo, limit) -> list: Busca diretamente naknowledge_basetodos os chunks de um tópico especifico. Usado na Estratégia de Contexto Expandido.recuperar_contexto_inteligente(vector_embedding) -> tuple(str, str, list): Função principal do RAG inteligente. Retorna(texto_contexto, nome_da_fonte, lista_ids). Logica: chamabuscar_referencias_db()para 10 resultados, conta ocorrências de cada tópico. Se tópico vencedor tem 3 ou mais votos: busca TODOS os chunks do tópico (Contexto Expandido). Caso contrário: usa os 5 melhores resultados mistos.
src/core/genai.py — Integração com Gemini¶
configurar_api_gemini() -> genai.Client: Cria o cliente da API Gemini. Armazena emst.session_state.gemini_client. Chamast.stop()se falhar.inicializar_chat_modelo() -> chat: Gerencia dois históricos:hist(enviado ao modelo, comeca comINSTRUCOES) ehist_exibir(exibido na UI, começa vazio). Cria objeto de chat do Gemini comGenerateContentConfigcontendosystem_instruction=INSTRUCOES.gerar_resposta(chat, prompt, info_adicional) -> str: Constroi o prompt final diferenciando o prompt do usuário do contexto interno da KB. Usasend_message_stream()para streaming, acumulando chunks de texto.transcrever_audio(audio_file) -> str: Envia áudio como bytes viatypes.Part.from_bytes(mime_type='audio/mp3'). Instrui o modelo a transcrever para português do Brasil. RetornaNoneem caso de erro.
src/core/semantica.py — Pipeline RAG¶
semantica(prompt) -> tuple(str, str, list): Gera o embedding do prompt viagemini-embedding-001comtask_type='RETRIEVAL_QUERY'e delega pararecuperar_contexto_inteligente(). Retorna(fonte, contexto, ids)ou(None, None, None).
Nota: A distinção de
task_typeé critica:RETRIEVAL_QUERYpara o prompt do usuário eRETRIEVAL_DOCUMENTpara os textos da KB. O Gemini otimiza os vetores de forma diferente para cada papel, melhorando a qualidade da busca.
src/app/ui.py — Interface de Usuário¶
configurar_pagina(): Definepage_titleepage_iconviast.set_page_config()e renderiza o cabeçalho.carregar_css(path=CSS_PATH): Lê o arquivostatic/css/style.csse injeta viast.markdown(unsafe_allow_html=True).@st.dialog — dialog_reportar(): Modal de denuncia. Busca categorias viaget_categorias_erro(), exibeselectboxetext_area. Ao confirmar, chamasalvar_report().carregar_sidebar(sidebar_content, sidebar_footer): Renderiza sidebar completa: HTML deSIDEBAR_BODY(links sociais, descrição), botões "Limpar conversa" e "Reportar", eSIDEBAR_FOOTER(links legais, versão git).stream_resposta(resposta) -> generator: Gerador que itera caractere a caractere com delay de 9ms. Usada comst.write_stream()para efeito de digitação.
src/utils.py — Utilitários¶
git_version() -> str: Detecta branch atual. Semain: busca tagsv*. Caso contrário: buscadev-v*. Fallback: le versão doCHANGELOG.mdcom regex.texto_para_audio(texto) -> BytesIO: Converte texto em MP3 via gTTS (pt-br). Aplicalimpeza_texto()antes para remover Markdown e caracteres especiais.limpeza_texto(texto) -> str: Remove caracteres não-alfanuméricos exceto pontuação básica e acentos do português via regex.
startup_patch.py¶
Cria um modulo vazio e o registra em sys.modules['torch.classes']. Evita ImportError em ambientes como o Streamlit Cloud onde dependências indiretas tentam importar torch.classes na inicialização. Deve ser importado como primeira linha do vox_ai.py.
data/prompts/system_prompt.py¶
Contém a constante INSTRUCOES com o system prompt completo. Organizado em seções: Origem e Propósito, Pilares de Conhecimento, Diretrizes de Personalidade, Regras de Ouro (nunca inventar leis/endereços, zero tolerância a pornografia, respeito absoluto a pronomes) e parceria com a Casa de Cultura Marielle Franco.
data/prompts/ui_content.py¶
Define as strings da interface: SAUDACAO (mensagem de boas-vindas), SIDEBAR_BODY (HTML da sidebar com links sociais) e SIDEBAR_FOOTER (HTML do rodapé com links legais e versão git). Usa f-strings com URLs de external_links.py e git_version().