File size: 3,904 Bytes
aec8693
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# 👨‍💻 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

```bash
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

```bash
# 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.