Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Local Knowledge Trainer · Plataforma RAG Estatística

Pipeline ETL de conhecimento com validação estatística via scipy.stats. Ensine documentos para uma IA local e prove matematicamente que o conhecimento foi absorvido.

Python License Tests SciPy Research RAG


Arquitetura validada por pesquisa: A abordagem de validação estatística para RAG é respaldada por 4 papers recentes — VERA (KDD 2024), QuCo-RAG (ACL Findings 2026), IndiaFinBench (2026) e IEEE Signal Processing (2026). Veja Validação Científica.


Por que Local Knowledge Trainer?

Empresas querem "ensinar" documentos para uma IA, mas o fine-tuning tradicional é caro, lento e causa overfitting. O RAG resolve isso mantendo o modelo intacto — mas como saber se a base de conhecimento está realmente boa?

Abordagem Custo Tempo Overfitting Prova de qualidade
Fine-Tuning (OpenAI) $50-500 2-24h Alto Nenhuma
LoRA (GPU A100) $2-10/h 1-8h Médio Nenhuma
RAG simples $0 Minutos Zero Nenhuma
Local Knowledge Trainer $0 Minutos Zero p-value + IC 95% + Cohen's d

O Local Knowledge Trainer não apenas faz RAG — ele prova estatisticamente que cada documento ingerido melhorou (ou piorou) a base de conhecimento, usando scipy.stats.


Pipeline

Documentos → Parser → Knowledge Graph → Embeddings → Validação Estatística → Vector DB → RAG Engine → LLM
  (PDF,MD,    (split     (spaCy NER      (sentence-    (scipy.stats: Shapiro,   (FAISS     (BM25 +
   TXT,PY,     por        + networkx)      transf.)      KS, T-test, ANOVA,      HNSW /    Denso +
   SQL,Java)  heading/                                   Bootstrap, Qui²)        Chroma)    RRF)
              parág.)

Cada documento ingerido passa por:

  1. Parse — extração estruturada por tipo de arquivo
  2. Chunking — segmentação com overlap configurável
  3. Embedding — vetorização com sentence-transformers
  4. Validação pré-ingestão — KS test para detectar viés de distribuição
  5. Armazenamento — FAISS HNSW ou ChromaDB
  6. Validação pós-ingestão — t-test A/B (novo doc melhorou a base?)
  7. Knowledge Graph — entidades e relações via spaCy NER

Funcionalidades

Parser Multi-Formato

Formato Estratégia O que extrai
PDF pdfplumber página a página Texto + número de página
Markdown / RST Segmenta por headings (#) Texto por seção com nome da seção
Python ast.parse() Funções, classes e docstrings
Java Regex de classe/método Declarações de classe e método
SQL Split por ; Statements DDL/DML com nome da tabela
TXT Split por parágrafo (\n\n) Blocos de texto

IDs de chunk são hashes SHA-256 (16 chars) de (source, text[:100]) — determinísticos e reproduzíveis.

Knowledge Graph Builder

  • Entidades: Extração via spaCy NER — PT-BR (pt_core_news_sm) e EN (en_core_web_sm)
  • Relacionamentos: Co-ocorrência entre entidades no mesmo chunk (co_occurs)
  • Grafo: networkx.DiGraph com atributos label, frequency, weight, source_doc
  • Exportação: RDF/XML, GraphML, GML, GEXF

Requer pip install -e ".[nlp]" para ativar (sem spaCy, o Knowledge Graph é silenciosamente ignorado).

Validação Estatística (scipy.stats) — O Diferencial

Teste Função scipy O que valida Quando roda
Shapiro-Wilk scipy.stats.shapiro() Normalidade dos scores de embedding validate_knowledge_base()
Kolmogorov-Smirnov scipy.stats.ks_2samp() Viés de distribuição entre documentos ingest(hypothesis_test="ks")
T-test Independente scipy.stats.ttest_ind() A/B test: novo documento melhorou a base? ingest(hypothesis_test="ttest")
ANOVA one-way scipy.stats.f_oneway() Conflito entre tópicos test_topic_conflict()
Qui-Quadrado scipy.stats.chi2_contingency() Impacto do chunk size na recuperação optimize_chunking()
Bootstrap CI Resampling empírico (VERA, 10K) Intervalo de confiança robusto (não assume normalidade) bootstrap_confidence_interval()
Bootstrap Permutation Resampling 10K (IndiaFinBench) p-value robusto para A/B testing bootstrap_ab_test()
Cohen's d Cálculo próprio Tamanho do efeito (não apenas significância) ingest() + query()
Bonferroni Correção manual Controle de falsos positivos em múltiplos testes validator.bonferroni_correct()
IQR Outlier Removal Quartis + 1.5×IQR Remove outliers antes dos testes validate_knowledge_base()

RAG Engine Híbrido

Pipeline de recuperação em 3 etapas:

Query
  │
  ├─► 1. Dense (FAISS HNSW cosine)  ─────┐
  │                                       ├─► 3. RRF Fusion ─► Top-K chunks ─► LLM
  └─► 2. Sparse (BM25 lexical)      ─────┘
         (rank_bm25)
  • Dense: cosine similarity com FAISS HNSW (k=20 candidatos)
  • Sparse: BM25 Okapi com tokenização por whitespace
  • Fusão RRF: score = Σ 1/(k + rank) com k=60, combina listas sem normalização de escala
  • Top-K final: configurável via query(k=N), padrão k=5

Vector Store

Dois backends suportados, com fallback automático para numpy se a dependência não estiver instalada:

Backend Instalação Características
FAISS HNSW (padrão) incluído no base Rápido, in-memory, salvo via persist_dir
ChromaDB pip install chromadb Persistência nativa, filtros por metadata
numpy (fallback) sempre disponível Busca linear por cosine similarity

Detecção de Contradições (QuCo-RAG)

  • Registra co-ocorrência de entidades no Knowledge Graph
  • Detecta relações conflitantes entre documentos (conflicting_relation)
  • Identifica gaps de conhecimento — entidades sem co-ocorrência prévia (zero_cooccurrence)
  • Score de contradição: contradictions / total_pairs — flag automático se > 0.3

Início Rápido

Requisitos

Requisito Mínimo Recomendado
Python 3.10+ 3.11+
RAM 4 GB 16 GB
Disco 500 MB 10 GB (para modelos de embedding)
GPU Não requer NVIDIA (para FAISS GPU)

Instalação

# Clonar
git clone https://github.com/IA-PlayGround/local-knowledge-trainer.git
cd local-knowledge-trainer

# Instalação base (FAISS + BM25 + embeddings + PDF)
pip install -e .

# Com NLP para Knowledge Graph (spaCy PT-BR + EN)
pip install -e ".[nlp]"
python -m spacy download pt_core_news_sm
python -m spacy download en_core_web_sm

# Com suporte GPU (FAISS GPU)
pip install -e ".[gpu]"

# Desenvolvimento (pytest)
pip install -e ".[dev]"

Parâmetros do construtor

KnowledgeTrainer(
    embedding_model = "all-MiniLM-L6-v2",  # modelo sentence-transformers
    vector_store    = "faiss",              # "faiss" | "chromadb"
    language        = "pt",                 # "pt" | "en" (para Knowledge Graph)
    device          = "cpu",                # "cpu" | "cuda"
    chunk_size      = 512,                  # palavras por chunk
    chunk_overlap   = 64,                   # palavras de overlap entre chunks
    persist_dir     = "",                   # "" = in-memory | "/path/to/dir" = salva no disco
)

Sobre persist_dir: quando especificado, o vector store é salvo em persist_dir/vector_store/. Na próxima inicialização com o mesmo caminho, os dados são recarregados. Útil para bases grandes que não devem ser re-indexadas a cada execução.

Uso Básico

from local_knowledge_trainer import KnowledgeTrainer

# Inicializa
trainer = KnowledgeTrainer(
    embedding_model="all-MiniLM-L6-v2",
    language="pt",
    persist_dir="/tmp/minha_base",   # persiste no disco
)

# Ingere documentos com validação estatística
resultado = trainer.ingest(
    "docs/",
    hypothesis_test="all",     # "ttest" | "ks" | "all"
    chunk_size=512,
    chunk_overlap=64,
)
print(f"Chunks ingeridos: {resultado.chunks}")
print(f"Aprovados (p<0.05): {resultado.approved_docs}")
print(f"Rejeitados: {resultado.rejected_docs}")
print(f"Relatório estatístico: {resultado.statistical_report}")

Integrando um LLM

O KnowledgeTrainer aceita qualquer função com assinatura (str) -> str como LLM. Sem LLM configurado, a query retorna o contexto recuperado como texto bruto.

# Exemplo com OpenAI
from openai import OpenAI
client = OpenAI()

def meu_llm(prompt: str) -> str:
    resp = client.chat.completions.create(
        model="gpt-4o",
        messages=[{"role": "user", "content": prompt}],
    )
    return resp.choices[0].message.content

trainer.set_llm(meu_llm)

# Exemplo com Ollama (local)
import requests

def ollama_llm(prompt: str) -> str:
    r = requests.post("http://localhost:11434/api/generate",
                      json={"model": "llama3", "prompt": prompt, "stream": False})
    return r.json()["response"]

trainer.set_llm(ollama_llm)

Query com métricas de confiança

resposta = trainer.query(
    "Explique o módulo de autenticação",
    return_confidence=True,
    k=5,                         # número de chunks recuperados
)

print(resposta.text)
print(f"Confiança: {resposta.confidence:.1%}")       # 1 - p_value
print(f"IC 95%: [{resposta.ci_lower:.3f}, {resposta.ci_upper:.3f}]")
print(f"p-value: {resposta.p_value:.4f}")             # probabilidade de ser aleatório
print(f"Cohen's d: {resposta.cohens_d:.2f}")          # tamanho do efeito vs baseline
print(f"Chunks usados: {len(resposta.source_chunks)}")
for chunk in resposta.source_chunks:
    print(f"  [{chunk['score']:.3f}] {chunk['source']}: {chunk['text'][:80]}...")

Sem LLM configurado, resposta.text contém o contexto recuperado formatado:

[Sem LLM configurado] Contexto:
<texto dos top-K chunks>

Validação completa da base

validacao = trainer.validate_knowledge_base()
print(f"Normalidade (Shapiro): p={validacao.shapiro_p:.4f}")
print(f"Distribuição normal: {validacao.distribution_normal}")
print(f"Homogeneidade (KS): p={validacao.ks_p:.4f}")
print(f"Outliers removidos: {validacao.outlier_count}")
for w in validacao.warnings:
    print(f"  AVISO: {w}")

Otimização de Chunking Baseada em Dados

# Testa estatisticamente qual chunk_size é melhor via Qui-Quadrado
otimizacao = trainer.optimize_chunking(
    strategies=[256, 512, 1024],
    metric="hit_rate",
)
print(f"Melhor tamanho: {otimizacao.best_size}")
print(f"χ² = {otimizacao.chi2:.2f}, p = {otimizacao.p_value:.4f}")
print(f"Significativo: {otimizacao.p_value < 0.05}")
print(f"Resultados por estratégia: {otimizacao.strategy_results}")

Detecção de Contradições (QuCo-RAG)

# 1. Registra pares de entidades do Knowledge Graph
pares = trainer.register_entity_pairs()
print(f"{pares} pares de entidades registrados")

# 2. Detecta contradições em novo documento antes de ingerir
contradicoes = trainer.detect_contradictions(
    "Python foi criado por Brendan Eich em 1995."
)
if contradicoes["flagged"]:
    print(f"ALERTA: {contradicoes['contradiction_count']} contradições detectadas")
    print(f"Score: {contradicoes['contradiction_score']:.2f} (threshold: 0.30)")
    for c in contradicoes["contradictions"]:
        print(f"  {c['entity1']}{c['entity2']}: {c['type']}")

Bootstrap e Métricas Avançadas (VERA)

# Intervalo de confiança via bootstrap (não assume normalidade)
ci = trainer.bootstrap_confidence_interval(confidence=0.95)
print(f"Bootstrap CI: [{ci['ci_lower']:.3f}, {ci['ci_upper']:.3f}]")
print(f"Método: {ci['method']}")        # "bootstrap_percentile"
print(f"N resamples: {ci['n_bootstrap']}")

# Score composto multi-métrica
qualidade = trainer.compute_quality_score("Explique a arquitetura do sistema")
print(f"Score composto: {qualidade['composite_score']:.2f}")
print(f"Tier: {qualidade['quality_tier']}")  # excellent | good | fair | poor
print(f"Componentes: {qualidade['components']}")
print(f"IC do score: [{qualidade['ci_lower']:.3f}, {qualidade['ci_upper']:.3f}]")

# Bootstrap A/B test (mais robusto que t-test para dados não-normais)
import numpy as np
scores_antes = np.array([0.5, 0.48, 0.52, 0.51])
scores_depois = np.array([0.72, 0.69, 0.74, 0.71])
ab = trainer.bootstrap_ab_test(scores_antes, scores_depois)
print(f"Bootstrap p-value: {ab['bootstrap_pvalue']:.4f}")
print(f"Significativo: {ab['significant']}")

# Export do Knowledge Graph
trainer.export_graph("grafo.graphml", format="graphml")  # ou "rdf", "gml", "gexf"

Stats

print(trainer.stats)
# {
#   "chunks": 1247,
#   "entities": 83,
#   "relations": 412,
#   "embedding_model": "all-MiniLM-L6-v2",
#   "dim": 384
# }

Referência da API

KnowledgeTrainer

Método Parâmetros Retorno Descrição
ingest(path, hypothesis_test, chunk_size, chunk_overlap) path: str, test: "ttest"|"ks"|"all" IngestResult Ingere arquivo ou diretório com validação estatística
query(question, return_confidence, k) question: str, k: int=5 QueryResponse Busca híbrida + resposta LLM opcional
optimize_chunking(strategies, metric) strategies: list[int] ChunkOptimizationResult Qui-Quadrado sobre hit/miss por chunk size
validate_knowledge_base() ValidationReport Shapiro + KS + IQR sobre a base atual
bootstrap_confidence_interval(confidence) confidence: float=0.95 dict Bootstrap CI empírico (VERA)
compute_quality_score(query) query: str dict Score composto multi-métrica com CI
bootstrap_ab_test(scores_before, scores_after) arrays numpy dict Bootstrap permutation test (IndiaFinBench)
register_entity_pairs() int Registra pares do KG para contradição
detect_contradictions(text) text: str dict Detecta contradições vs KG existente
export_graph(path, format) format: "graphml"|"rdf"|"gml"|"gexf" None Exporta Knowledge Graph
set_llm(llm_fn) fn: (str) -> str None Configura função LLM para geração
stats dict chunks, entities, relations, dim, model

Tipos de Dados

Tipo Campos principais
IngestResult total_docs, chunks, approved_docs, rejected_docs, statistical_report, errors
QueryResponse text, source_chunks, confidence, p_value, ci_lower, ci_upper, cohens_d, chunk_scores
ChunkOptimizationResult best_size, chi2, p_value, strategy_results
ValidationReport shapiro_stat, shapiro_p, ks_stat, ks_p, outlier_count, total_chunks, distribution_normal, warnings
Chunk id (SHA-256 16c), text, metadata, source, page, section

Estrutura do Projeto

local-knowledge-trainer/
├── .gitignore
├── README.md
├── pyproject.toml
├── src/local_knowledge_trainer/
│   ├── __init__.py                # exporta KnowledgeTrainer
│   ├── core/
│   │   ├── trainer.py             # KnowledgeTrainer — orquestrador principal
│   │   └── types.py               # Dataclasses: Chunk, IngestResult, QueryResponse, ...
│   ├── parser/
│   │   └── parser.py              # DocumentParser — PDF, MD, TXT, PY, Java, SQL
│   ├── knowledge/
│   │   └── graph.py               # KnowledgeGraphBuilder — spaCy NER + networkx
│   ├── rag/
│   │   ├── vector_store.py        # VectorStore — FAISS HNSW / ChromaDB / numpy fallback
│   │   └── engine.py              # RAGEngine — BM25 + Dense + RRF
│   ├── validation/
│   │   └── hypothesis.py          # HypothesisValidator — scipy.stats + Bootstrap
│   └── api/                       # placeholder para API REST futura
└── tests/
    ├── test_parser.py             # 7 testes
    ├── test_validation.py         # 11 testes
    ├── test_trainer.py            # 8 testes
    └── test_research_features.py  # 8 testes (Bootstrap, Contradição, VERA)

Testes

# Instalar dependências de dev
pip install -e ".[dev]"

# Todos os testes
pytest tests/ -v

# Por módulo
pytest tests/test_validation.py -v        # testes scipy.stats
pytest tests/test_research_features.py -v # Bootstrap, Contradição, VERA
pytest tests/test_parser.py -v            # parser multi-formato
pytest tests/test_trainer.py -v           # pipeline completo

Saída esperada:

tests/test_parser.py          7 passed
tests/test_validation.py     11 passed
tests/test_trainer.py         8 passed
tests/test_research_features.py  8 passed
============================== 34 passed ==============================

Validação Científica

A camada de validação estatística é respaldada por 4 papers recentes:

Paper Veículo Contribuição Implementação
VERA (arXiv:2409.03759) KDD 2024 Bootstrap CI empírico + score multi-métrica (relevância, fidelidade, cobertura) bootstrap_confidence_interval() + compute_multi_metric_score()
QuCo-RAG (arXiv:2512.19134) ACL Findings 2026 Co-ocorrência de entidades para detectar contradições e long-tail knowledge gaps detect_contradiction() + register_entity_cooccurrence()
IndiaFinBench (arXiv:2604.19298) 2026 Bootstrap permutation 10K para significância robusta em dados não-normais bootstrap_pvalue()
AI Teaching Assistant (arXiv:2604.04670) IEEE SP 2026 ANOVA + Bonferroni para validação de impacto de ferramentas RAG em domínios educacionais test_topic_conflict() + bonferroni_correct()

Mapeamento Funcionalidade → Paper

┌──────────────────────────────────────────────────────────────┐
│           VALIDAÇÃO ESTATÍSTICA DO LOCAL KNOWLEDGE TRAINER    │
│                                                               │
│  Bootstrap CI ──────────────► VERA (KDD 2024)                │
│  Multi-Metric Score ────────► VERA (KDD 2024)                │
│  Bootstrap Permutation ─────► IndiaFinBench (2026)           │
│  Contradiction Detection ───► QuCo-RAG (ACL 2026)            │
│  Entity Co-occurrence ──────► QuCo-RAG (ACL 2026)            │
│  ANOVA + Bonferroni ────────► IEEE SP (2026)                 │
│  Shapiro-Wilk + KS ─────────► Validação clássica + VERA      │
└──────────────────────────────────────────────────────────────┘

Fórmulas e Fundamentação Matemática

p-value da Resposta

Dado um conjunto de n chunks recuperados com similaridades s₁, s₂, ..., sₙ:

μ = (1/n) Σ sᵢ           # média amostral
σ = √(Σ(sᵢ - μ)²/(n-1))  # desvio padrão amostral
SE = σ / √n               # erro padrão

z = (μ - μ_global) / (σ_global / √n)

p = 2 × (1 - Φ(|z|))      # onde Φ é a CDF da normal padrão
confiança = 1 - p

Bootstrap CI (VERA)

Para i = 1 até B (padrão: 10.000):
    amostra* ← reamostragem com reposição de tamanho n
    média*[i] ← média(amostra*)

CI inferior = percentil(α/2, médias*)
CI superior = percentil(1-α/2, médias*)

Cohen's d

d = (μ₁ - μ₂) / s_pooled

s_pooled = √(((n₁-1)s₁² + (n₂-1)s₂²) / (n₁+n₂-2))

Interpretação: |d| < 0.2 desprezível | 0.2–0.5 pequeno | 0.5–0.8 médio | > 0.8 grande

Reciprocal Rank Fusion

RRF(chunk) = Σ_{lista ∈ {dense, sparse}} 1 / (k + rank(chunk, lista))

k = 60  (suavização para penalizar menos os itens mais baixos)

Comparação com outros frameworks

Funcionalidade Local Knowledge Trainer LangChain LlamaIndex Haystack
Parser multi-formato ✅ PDF, MD, PY, Java, SQL
Knowledge Graph ✅ spaCy NER + export RDF/GraphML Parcial
Validação estatística ✅ 9 testes scipy
Bootstrap CI ✅ VERA (10K amostras)
Detecção de contradições ✅ QuCo-RAG
Confiança na resposta ✅ IC 95% + p-value + Cohen's d
Otimização de chunking ✅ χ² estatístico
Funciona 100% offline
LLM plugável ✅ qualquer (str) -> str

Roadmap

Fase Status Funcionalidades
Fase 1 — MVP ✅ Entregue Parser PDF/TXT, embeddings, FAISS, RAG simples, T-test + Shapiro-Wilk
Fase 2 — Validação ✅ Atual Knowledge Graph, RAG híbrido (BM25+Dense+RRF), KS + ANOVA + Chi² + Bonferroni + Bootstrap CI + Contradição
Fase 2.5 — Robustez 🔲 Q3 2026 Cross-Encoder real, Optuna para hyperparameter tuning, cache de validação, dashboard Streamlit
Fase 3 — Maturidade 🔲 Q4 2026 CUDA para estatística (CuPy), multi-idioma unificado no KG, exportação ONNX, benchmark suite

Licença

Licença MIT.

Citação

@software{local_knowledge_trainer_2026,
  title = {Local Knowledge Trainer: Plataforma RAG com Validação Estatística},
  year = {2026},
  url = {https://github.com/IA-PlayGround/local-knowledge-trainer}
}

About

Plataforma RAG com validação estatística scipy.stats — prova matematicamente a qualidade do conhecimento ingerido

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages