Metadata-Version: 2.4
Name: colsemantics
Version: 0.1.0
Summary: Inferência semântica de colunas: descobre o papel (o que a coluna é) e o domínio (do que ela fala) a partir do nome, de abreviações corporativas e do conteúdo.
Author: Caio
License-Expression: MIT
Project-URL: Homepage, https://github.com/Caio-Analytics/colsemantics
Keywords: semantic,data-profiling,column-inference,pii,etl,pandas
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: rapidfuzz>=3.0
Requires-Dist: unidecode>=1.3
Provides-Extra: dev
Requires-Dist: pytest>=8; extra == "dev"
Requires-Dist: mypy>=1.10; extra == "dev"
Requires-Dist: ruff>=0.6; extra == "dev"
Dynamic: license-file

# colsemantics

**Descobre o que uma coluna *é* e do que ela *fala* — a partir do nome, de
abreviações corporativas e do conteúdo.**

`cd_dpto_lot` não está em nenhum dicionário. Mas a abreviatura reconstrói
`codigo` / `departamento` / `lotacao`, o conteúdo confirma baixa
cardinalidade, e o resultado é uma coluna com **papel** "Chave Identificadora"
e **domínio** "Estrutura Organizacional" — com a confiança e a evidência que
levaram a essa conclusão.

```python
from colsemantics import inferir_semantica

inferir_semantica("cd_dpto_lot")
# {
#   "semantica": "Chave Identificadora (ID)",
#   "papel": "Chave Identificadora (ID)",
#   "dominio": "Estrutura Organizacional",
#   "confianca_score": 0.87,
#   "origem": "abreviatura 'cd' → 'codigo' + abreviatura 'lot' → 'lotacao'",
#   "conclusiva": True,
#   "hipoteses": [...],
# }
```

## Por que isso é diferente de inferir `dtype`

Toda ferramenta de profiling te diz que uma coluna é `int64` ou `object`.
Nenhuma te diz que `f27` é geografia porque os valores são siglas de UF, ou
que `DEPARTMENT_NAME` não é dado pessoal mesmo terminando em `_NAME`. É essa
segunda pergunta — **papel** (o que a coluna é: chave, data, valor
financeiro...) e **domínio** (do que ela fala: estrutura organizacional,
cargo, localidade...) — que `colsemantics` responde.

## Como funciona

A inferência é uma **cascata de detectores independentes**, não um
`if/elif` em que o primeiro match vence:

1. **Padrão de conteúdo validado** (CPF, CNPJ, e-mail...) — a pista mais forte que existe.
2. **Token forte** — match exato contra um dicionário curado, com abreviações expandidas (`vl` → `valor`).
3. **Fuzzy (Jaro-Winkler)** — nome parecido com uma palavra-chave de domínio, tolera erro de digitação.
4. **Gazetteer de conteúdo** — os valores da coluna batem com um conjunto fechado conhecido (UFs, meses, sexo/gênero...), independente do nome.
5. **Assinatura estrutural** — a *forma* dos dados (inteiro crescente e único, decimal de 2 casas assimétrico à direita...) sugere o papel.
6. **Contexto da tabela** — colunas vizinhas já resolvidas desambiguam abreviaturas ambíguas (`dep` é departamento, dependente ou depósito — sozinho é insolúvel, trivial se a tabela já fala de RH).

Cada detector emite evidência com peso; a combinação é **noisy-OR**
(`1 - Π(1 - peso)`), não "o primeiro que responder". Pistas fracas se somam.

## Instalação

```bash
pip install colsemantics
```

## Uso

### Uma coluna isolada

```python
from colsemantics import inferir_semantica

inferir_semantica("nome_departamento")
# semântica = "Estrutura Organizacional" (domínio vence: "nome" é só a forma)

inferir_semantica("uf")
# semântica = "Localização Geográfica"
```

### Com o conteúdo da coluna (resolve nomes opacos)

```python
from colsemantics import PerfilConteudo, inferir_semantica

perfil = PerfilConteudo(
    tipo_dados="Texto",
    valores_distintos=["SP", "RJ", "MG", "BA"],
    n_unicos=4,
    ratio_unicidade=4 / 40,
)
inferir_semantica("f27", perfil=perfil)["semantica"]
# "Localização Geográfica" — nenhuma análise do nome chegaria lá
```

`PerfilConteudo` é um dataclass simples — todos os campos são opcionais além
dos primeiros, então passe só o que você já sabe sobre a coluna:

| campo | o que é |
|---|---|
| `tipo_dados` | `"Texto"`, `"Número Inteiro"`, `"Número Decimal"`, `"Booleano"`... |
| `valores_distintos` | amostra de valores únicos (usada pelo gazetteer) |
| `n_unicos`, `ratio_unicidade` | cardinalidade |
| `str_len_media`, `comprimento_fixo` | forma do texto |
| `assimetria`, `minimo`, `casas_decimais_fixas` | forma do número |
| `monotonica_crescente` | sinal de chave sequencial |

### Uma tabela inteira (desambiguação por contexto)

```python
from colsemantics import inferir_semanticas_da_tabela

resultados = inferir_semanticas_da_tabela([
    {"nome": "matricula", "padrao": "Nenhum", "perfil": None},
    {"nome": "nome_func", "padrao": "Nenhum", "perfil": None},
    {"nome": "cod_dep",   "padrao": "Nenhum", "perfil": None},
    {"nome": "diretoria", "padrao": "Nenhum", "perfil": None},
])
# "cod_dep" sozinho é ambíguo (departamento? dependente? depósito?).
# Com "diretoria" na mesma tabela, o contexto resolve para "Estrutura Organizacional".
```

`padrao` é o que seu próprio detector de padrão estruturado encontrou no
conteúdo (`"CPF"`, `"CNPJ"`, `"UUID"`, `"E-mail"`, `"Telefone"`, `"CEP"` ou
`"Nenhum"`) — `colsemantics` não faz essa detecção, só consome o resultado.

## O que a saída traz

```python
{
    "semantica": str,       # papel estrutural, ou domínio quando o papel é só formal
    "papel": str | None,
    "dominio": str | None,
    "confianca_score": float,   # 0-1, noisy-OR das evidências
    "origem": str,               # por que — as evidências que decidiram
    "conclusiva": bool,          # False = havia ambiguidade, olhe "hipoteses"
    "hipoteses": list[dict],     # até 4 alternativas ranqueadas, com evidência cada
}
```

## Licença

MIT. Extraído do módulo de inferência semântica do
[Recon](https://github.com/Caio-Analytics/Recon), ferramenta de profiling de
dados desconhecidos.
