Phase 05 - Lesson 26

Extração de Relações e Construção de Grafos de Conhecimento

O NER encontrou as entidades. A vinculação de entidades as ancorou. A extração de relações encontra as arestas entre elas. Um grafo de conhecimento é a soma de nós, arestas e sua proveniência.

Tipo: Build Linguagens: Python Pré-requisitos: Fase 5 · 06 (NER), Fase 5 · 25 (Vinculação de Entidades) Tempo: ~60 minutos

O Problema

Um analista lê: "Tim Cook tornou-se CEO da Apple em 2011." Quatro fatos:

  • (Tim Cook, role, CEO)
  • (Tim Cook, employer, Apple)
  • (Tim Cook, start_date, 2011)
  • (Apple, type, Organization)

A Extração de Relações (RE) transforma texto livre em triplas estruturadas (subject, relation, object). Agregue ao longo de um corpus e você tem um grafo de conhecimento. Agregue e consulte e você tem um substrato de raciocínio para RAG, analytics ou auditorias de conformidade.

O problema de 2026: os LLMs extraem relações com entusiasmo. Entusiasmo demais. Eles alucinam triplas que o texto-fonte não sustenta. Sem proveniência, você não consegue distinguir triplas reais de ficção plausível. A resposta de 2026 são os pipelines de ancorar-e-verificar no estilo AEVS.

O Conceito

Texto → triplas → grafo de conhecimento

Forma de tripla. (subject_entity, relation_type, object_entity). As relações vêm de uma ontologia fechada (propriedades do Wikidata, FIBO, UMLS) ou de um conjunto aberto (estilo OpenIE, vale tudo).

Três abordagens de extração.

  1. Baseada em regras / padrões. Padrões de Hearst: "X such as Y" → (Y, isA, X). Mais regex feitas à mão. Frágil, precisa, explicável.
  2. Classificador supervisionado. Dadas duas menções de entidades em uma frase, prediz a relação a partir de um conjunto fixo. Treinado em TACRED, ACE, KBP. Padrão de 2015–2022.
  3. LLM generativo. Faça um prompt para o modelo emitir triplas. Funciona de imediato. Precisa de proveniência, ou alucina lixo de aparência plausível.

AEVS (Anchor-Extraction-Verification-Supplement, 2026). O framework atual de mitigação de alucinações:

  • Anchor (Ancorar). Identifique cada span de entidade e cada span de frase-relação com posições exatas.
  • Extract (Extrair). Gere triplas vinculadas aos spans-âncora.
  • Verify (Verificar). Confronte cada elemento da tripla com o texto-fonte; rejeite qualquer coisa não sustentada.
  • Supplement (Complementar). Uma passagem de cobertura garante que nenhum span ancorado seja descartado.

As alucinações caem drasticamente. Exige mais computação, mas é auditável.

O tradeoff aberto-versus-fechado.

  • Ontologia fechada. Lista fixa de propriedades (por exemplo, as mais de 11.000 propriedades do Wikidata). Previsível. Consultável. Difícil de inventar.
  • IE aberta. Qualquer frase verbal vira uma relação. Alta cobertura. Baixa precisão. Bagunçada de consultar.

KGs de produção geralmente misturam: IE aberta para descoberta, depois canonicalizam as relações em uma ontologia fechada antes de mesclar no grafo principal.

Construa

Passo 1: extração baseada em padrões

PATTERNS = [
    (r"(?P<s>[A-Z]\w+) (?:is|was) (?:a|an|the) (?P<o>[A-Z]?\w+)", "isA"),
    (r"(?P<s>[A-Z]\w+) (?:is|was) born in (?P<o>\w+)", "bornIn"),
    (r"(?P<s>[A-Z]\w+) works? (?:at|for) (?P<o>[A-Z]\w+)", "worksAt"),
    (r"(?P<s>[A-Z]\w+) founded (?P<o>[A-Z]\w+)", "founded"),
]

Veja code/main.py para o extrator de brinquedo completo. Padrões de Hearst ainda estão presentes em pipelines específicos de domínio porque são depuráveis.

Passo 2: classificação supervisionada de relações

from transformers import AutoTokenizer, AutoModelForSequenceClassification

tok = AutoTokenizer.from_pretrained("Babelscape/rebel-large")
model = AutoModelForSequenceClassification.from_pretrained("Babelscape/rebel-large")

text = "Tim Cook was born in Alabama. He later became CEO of Apple."
encoded = tok(text, return_tensors="pt", truncation=True)
output = model.generate(**encoded, max_length=200)
triples = tok.batch_decode(output, skip_special_tokens=False)

O REBEL é um extrator de relações seq2seq: texto na entrada, triplas na saída, já em ids de propriedade do Wikidata. Ajustado com dados de supervisão distante. Baseline padrão de pesos abertos.

Passo 3: extração via prompt de LLM com ancoragem

prompt = f"""Extract (subject, relation, object) triples from the text.
For each triple, include the exact character span in the source text.

Text: {text}

Output JSON:
[{{"subject": {{"text": "...", "span": [start, end]}},
   "relation": "...",
   "object": {{"text": "...", "span": [start, end]}}}}, ...]

Only include triples fully supported by the text. No inference beyond what is stated.
"""

Verifique cada span retornado contra a fonte. Rejeite qualquer coisa em que text[start:end] != triple_entity. Este é o passo "verify" do AEVS em sua forma mínima.

Passo 4: canonicalize em uma ontologia fechada

RELATION_MAP = {
    "is the CEO of": "P169",       # "chief executive officer"
    "was born in":   "P19",         # "place of birth"
    "founded":        "P112",       # "founded by" (inverted subject/object)
    "works at":       "P108",       # "employer"
}


def canonicalize(relation):
    rel_low = relation.lower().strip()
    if rel_low in RELATION_MAP:
        return RELATION_MAP[rel_low]
    return None   # drop unmapped open relations or route to manual review

A canonicalização costuma ser 60-80% do trabalho de engenharia. Reserve orçamento para ela.

Passo 5: construa um pequeno grafo e consulte

triples = extract(text)
graph = {}
for s, r, o in triples:
    graph.setdefault(s, []).append((r, o))


def neighbors(node, relation=None):
    return [(r, o) for r, o in graph.get(node, []) if relation is None or r == relation]


print(neighbors("Tim Cook", relation="P108"))    # -> [(P108, Apple)]

Este é o átomo de todo sistema de RAG-sobre-KG. Escale com triple stores RDF (Blazegraph, Virtuoso), grafos de propriedades (Neo4j) ou stores de grafo aumentados por vetores.

Armadilhas

  • Correferência antes da RE. "He founded Apple" — a RE precisa saber quem é "he". Execute a correferência primeiro (lição 24).
  • Canonicalização de entidades. "Apple Inc" e "Apple" precisam resolver para o mesmo nó. Vinculação de entidades primeiro (lição 25).
  • Triplas alucinadas. Os LLMs emitem triplas que o texto não sustenta. Imponha a verificação de spans.
  • Deriva na canonicalização de relações. As relações de IE aberta são inconsistentes ("was born in", "came from", "is a native of"). Reduza a ids canônicos ou o grafo fica não consultável.
  • Erros temporais. "Tim Cook is CEO of Apple" — verdade agora, falso em 2005. Muitas relações são limitadas no tempo. Use qualificadores (P580 tempo de início, P582 tempo de fim no Wikidata).
  • Incompatibilidade de domínio. O REBEL foi treinado na Wikipédia. Textos jurídicos, médicos e científicos frequentemente precisam de modelos de RE ajustados ao domínio.

Use

A stack de 2026:

Situação Escolha
Produção rápida, domínio geral REBEL ou LlamaPred com canonicalização do Wikidata
Específico de domínio (biomédico, jurídico) Ajuste de domínio estilo SciREX + ontologia customizada
Saída via prompt de LLM, auditada Pipeline AEVS: ancorar → extrair → verificar → complementar
IE de notícias em alto volume Híbrido baseado em padrões + supervisionado
Construir um KG do zero IE aberta + passagem de canonicalização manual
KG temporal Extrair com qualificadores (tempo de início/fim, ponto no tempo)

O padrão de integração: NER → correferência → vinculação de entidades → extração de relações → mapeamento de ontologia → carga no grafo. Cada estágio é um potencial portão de qualidade.

Entregue

Salve como outputs/skill-re-designer.md:

---
name: re-designer
description: Design a relation extraction pipeline with provenance and canonicalization.
version: 1.0.0
phase: 5
lesson: 26
tags: [nlp, relation-extraction, knowledge-graph]
---

Given a corpus (domain, language, volume) and downstream use (KG-RAG, analytics, compliance), output:

1. Extractor. Pattern-based / supervised / LLM / AEVS hybrid. Reason tied to precision vs recall target.
2. Ontology. Closed property list (Wikidata / domain) or open IE with canonicalization pass.
3. Provenance. Every triple carries source char-span + doc id. Non-negotiable for audit.
4. Merge strategy. Canonical entity id + relation id + temporal qualifiers; dedup policy.
5. Evaluation. Precision / recall on 200 hand-labelled triples + hallucination-rate on LLM-extracted sample.

Refuse any LLM-based RE pipeline without span verification (source provenance). Refuse open-IE output flowing into a production graph without canonicalization. Flag pipelines with no temporal qualifier on time-bounded relations (employer, spouse, position).

Exercícios

  1. Fácil. Execute o extrator de padrões em code/main.py em 5 frases de artigos de notícias. Confira a precisão à mão.
  2. Médio. Use o REBEL (ou um LLM pequeno) nas mesmas frases. Compare as triplas. Qual extrator tem maior precisão? Maior cobertura?
  3. Difícil. Construa o pipeline AEVS: extraia com LLM + verifique os spans contra a fonte. Meça a taxa de alucinação antes versus depois do passo de verificação em 50 frases ao estilo da Wikipédia.

Termos-Chave

Termo O que as pessoas dizem O que realmente significa
Tripla Sujeito-relação-objeto Tupla (s, r, o) que é a unidade atômica de um KG.
IE aberta Extrai qualquer coisa Frases-relação de vocabulário aberto; alta cobertura, baixa precisão.
Ontologia fechada Esquema fixo Conjunto limitado de tipos de relação (Wikidata, UMLS, FIBO).
Canonicalização Normaliza tudo Mapeia nomes/relações de superfície para ids canônicos.
AEVS Extração ancorada Pipeline Anchor-Extraction-Verification-Supplement (2026).
Proveniência Link de fonte-da-verdade Cada tripla carrega um doc id + char-span até sua fonte.
Supervisão distante Rótulos baratos Alinha texto com um KG existente para criar dados de treino.

Leitura Adicional

0 lifetime access. Curriculum based on AI Engineering from Scratch by Rohit Ghumare (MIT, used under attribution).