Biblioteca Python para transformar perguntas em linguagem natural em SQL executada com seguranca em SQLite, com avaliacao automatica e resposta final em linguagem natural.
O namespace oficial do pacote e text_to_insight.
O runtime padrao garante:
- fluxo completo do grafo (planejador -> schema -> agente de codigo -> executor -> critico -> salvar CSV -> roteador grafico -> gerador grafico (quando aplicavel) -> resposta);
- HITL ligado e desligado;
- retomada por
thread_id; - persistencia de metricas em
data/metricas_execucao.csv; - geracao opcional de graficos quando a visualizacao for relevante.
pergunta_original: pergunta inicial da thread, imutavel apos o primeiro set.pergunta_atual: pergunta corrente e fonte de verdade para o fluxo.- Em HITL, se a resposta do usuario for classificada como "nova pergunta",
o sistema atualiza
pergunta_atuale reinicia o ciclo, sem alterar a original.
pip install -r requirements.txt
pip install -e .Configure a chave da API:
echo "GOOGLE_API_KEY=sua_chave_aqui" > .envfrom text_to_insight import InsightEngine
engine = InsightEngine(
api_key="...",
model="gemini-2.5-flash",
db_path="data/olist_relational.db",
hitl=True,
inferir_fks_virtuais=False, # (Opcional) Infere FKs baseadas em colunas _id (ex: tabelas do Spider 2)
usar_schemacrawler=True, # (Opcional) Desative para forçar o fallback ao PRAGMA do SQLite
)
resultado = engine.run(
thread_id="sessao_1",
query="Quantos pedidos existem no banco?",
)
if resultado.get("status") == "AWAITING_USER":
resultado = engine.resume(
thread_id="sessao_1",
user_response="Pode assumir status entregue.",
)API publica congelada do pacote:
text_to_insight.InsightEnginetext_to_insight.Graphtext_to_insight.EstadoTextToInsight
Imports antigos via src nao sao mais suportados.
O arquivo main.py e um adaptador fino da CLI da biblioteca.
# via adaptador local
python main.py --hitl on "Quais categorias vendem mais?"
# modo nao interativo
python main.py --hitl off "Quais categorias vendem mais?"
# desativando schemacrawler e forçando FKs virtuais (Spider 2 local)
python main.py --hitl off --infer-fks on --use-schemacrawler off "Quantos times tem no banco?"
# via entrypoint instalado pelo pacote
text-to-insight --hitl on "Quantos pedidos existem no banco?"Apos a execucao, o resultado da query e exibido no bloco RESULTADO em formato tabular:
----------------------------------------------------------------------
RESULTADO:
----------------------------------------------------------------------
+------------+
| COUNT(*) |
+============+
| 99441 |
+------------+
Total de linhas retornadas: 1
O template de apresentacao usa tabulate para montar as linhas da query:
- Ate 5 linhas: exibe a tabela completa
- Acima de 5 linhas: mostra as 3 primeiras, omite as intermediarias, exibe as 2 ultimas
- Resultado completo e exportado em CSV em
results/automaticamente
Quando o roteador de gráficos decide que a visualização é útil, um grafico é salvo em graphs/ a partir do CSV de resultados.
Camadas atuais:
# Camada 1 - componentes deterministicos (sem API)
pytest tests/test_componentes.py -v -s
# Camada 2 - nos individuais com VCR (replay, sem gravar)
pytest tests/test_nodes.py -v -s --record-mode=none
# Camada 2 - nos individuais com VCR (gravar/atualizar cassetes)
pytest tests/test_nodes.py -v -s --record-mode=new_episodes
# Camada 3 - integracao do grafo com VCR (replay, sem gravar)
pytest tests/test_integracao.py -v -s --record-mode=none
# Camada 3 - integracao do grafo com VCR (gravar/atualizar cassetes)
pytest tests/test_integracao.py -v -s --record-mode=new_episodes
# Integracao dedicada main + InsightEngine
pytest tests/test_main_engine_integracao.py -v -sFluxo recomendado de gravacao VCR:
# gravar/atualizar
pytest tests/test_nodes.py tests/test_integracao.py -v -s --record-mode=new_episodes
# validar replay deterministico
pytest tests/test_nodes.py tests/test_integracao.py -v -s --record-mode=noneAs cassetes ficam em tests/cassettes/.
Para gravar cassetes com um provider/modelo especifico, sobrescreva o ambiente antes de rodar o pytest:
TEXT_TO_INSIGHT_TEST_PROVIDER=google \
TEXT_TO_INSIGHT_TEST_MODEL=gemini-2.5-flash \
pytest tests/test_nodes.py tests/test_integracao.py -v -s --record-mode=new_episodesTEXT_TO_INSIGHT_TEST_PROVIDER=openai \
TEXT_TO_INSIGHT_TEST_MODEL=gpt-4o-mini \
pytest tests/test_nodes.py tests/test_integracao.py -v -s --record-mode=new_episodesSe você preferir definir em comandos separados, use export antes de rodar o pytest. Sem export, a variavel fica apenas no shell atual e os testes nao herdam o valor.
Uso recomendado:
export TEXT_TO_INSIGHT_TEST_PROVIDER=google
export TEXT_TO_INSIGHT_TEST_MODEL=gemini-2.5-flash
pytest tests/test_nodes.py tests/test_integracao.py -v -s --record-mode=new_episodesSe quiser tudo em uma linha só, sem export, use:
TEXT_TO_INSIGHT_TEST_PROVIDER=google TEXT_TO_INSIGHT_TEST_MODEL=gemini-2.5-flash \
pytest tests/test_nodes.py tests/test_integracao.py -v -s --record-mode=new_episodesSem esses overrides, a suite tenta GOOGLE_API_KEY primeiro e depois OPENAI_API_KEY.
Teste opcional com API real (drift provider/modelo):
pytest tests/test_real_api_smoke.py -v -s -m real_apiSpider 1.0 (requer spider_data/ com dev.json e database/):
python scripts/test_spider_eval.py --sample-size 10 --seed 42 --data-dir spider_dataSpider 2.0 Lite (requer spider2-lite/ e bancos em spider2-lite/resource/databases/spider2-localdb):
python scripts/test_spider2_eval.py --sample-size 10 --seed 42 \
--data-dir spider2-lite \
--sqlite-dir spider2-lite/resource/databases/spider2-localdbWorkflow em .github/workflows/ci.yml:
tests-vcr: job padrao em PR/push com execucao deterministica (--record-mode=none);record-vcr-cassettes: job manual emworkflow_dispatchpara gravar/atualizar cassetes e publicar artifact;tests-real-api: job opcional manual/noturno comGOOGLE_API_KEYreal para detectar drift.
python -m build
python -m venv .venv-smoke
source .venv-smoke/bin/activate
pip install dist/*.whl
python -c "from text_to_insight import InsightEngine, Graph; print('import_ok')"