Carlexxx
para.AI beta
8a646ad

👨‍💻 DEV.md — Guia para Desenvolvedores

Para.AI Assuntos Jurídicos API


Stack

Camada Tech Versão
API FastAPI 0.115.12
Search Elasticsearch 8.12.0
Validação Pydantic 2.x
Cliente ES elasticsearch-py 8.17.0
Serialização orjson 3.10.14
Retry tenacity 9.x
Logging rich 13.x
Deploy Docker Compose 2.20+
Python CPython 3.11+

Estrutura do Código

app/
  __init__.py      # importa router
  main.py          # FastAPI app + lifespan (setup_es no startup)
  config.py        # Settings via pydantic-settings (ES_HOST, ES_INDEX, …)
  schemas.py       # Todos os modelos Pydantic  (Assunto, FichaAssunto,
                   #   BuscaQRequest, FICHA_CAMPOS_RETORNO, …)
  es_client.py     # Singleton ES + query builders + buscar/autocomplete/…
  builders.py      # Response builders: raw ES → Pydantic
  routes.py        # APIRouter com todos os endpoints

data/
  es_mapping.json  # Mapping ES com analyzer juridico_pt + edge n-gram

scripts/
  test_api.py      # Suite de testes HTTP (13 testes contra API live)
  split_merge_bulk.py  # utilitário para split/merge do bulk NDJSON
  purge_and_push.sh    # limpa e re-push dos dados no GitHub

Dockerfile         # python:3.11-slim + uvicorn
docker-compose.yml # elasticsearch:8.12.0 + app
entrypoint.sh      # aguarda ES → download bulk_assuntos.ndjson → uvicorn

Setup Rápido

git clone https://github.com/para-ai/assuntos-juridicos.git
cd assuntos-juridicos

# Sobe ES + API (primeira vez baixa ~18MB de dados)
docker-compose up -d

# Acompanha indexação inicial (~30s)
docker-compose logs -f app

# Testa
curl "http://localhost:8000/health"
curl "http://localhost:8000/busca?q=aposentadoria&size=3"

# Docs interativas
open http://localhost:8000/docs

Fluxo de Dados Resumido

Request GET /busca?q=aposentadoria
  → routes.busca_get()
  → es_client.buscar()           # executa build_busca_query() + ES search
  → builders.build_busca_response()  # raw ES → BuscaResponse Pydantic
  → ORJSONResponse               # serialização rápida
Request POST /busca-q  {q, campos, retornar, topk}
  → routes.busca_q_post()
  → es_client.busca_q()          # build_busca_q_query() + ES search
  → builders.build_busca_q_response()
    → _src_to_ficha()            # ← FIX #1 aplicado aqui
  → BuscaQResponse

Campos — Mapa Semântico ES ↔ Ficha

Nome na Ficha (retornar=) Campo ES Boost
titulo nome_assunto 4.0
titulo_curto titulo_curto 3.0
caminho classes_path 2.5
introducao breve_sintese 2.0
normas dispositivos_legais 1.5
artigos artigos 1.5
definicao glossario 1.2
ramo ramo
nivel1/2/3 classes_nivel1/2/3
texto texto_completo 1.0
cod_assunto cod_assunto

Testes

# Testes HTTP contra API em execução (13 testes)
python scripts/test_api.py http://localhost:8000

# Resultado esperado após FIX #1:
# 13/13 passou 🎉

Variáveis de Ambiente

Variável Default Descrição
ES_HOST http://elasticsearch:9200 URL do ES
ES_INDEX assuntos_juridicos Nome do índice
ES_TIMEOUT 30 Timeout (segundos)
ES_MAX_RETRIES 3 Retries automáticos
APP_PORT 8000 Porta da API
APP_VERSION 1.0.0 Versão da API

Contribuindo

  1. git checkout -b fix/meu-fix
  2. Implemente + adicione teste em scripts/test_api.py
  3. python scripts/test_api.py → 100% passando
  4. Pull Request com descrição do fix

Convenções: PEP8, type hints, docstrings Google, Conventional Commits.