Inferência Simbólica sobre Grafos: Transitividade, Herança e Contradições em Python
Se Paris é a capital da França, e a França fica na Europa, então Paris fica na Europa. Você fez essa inferência em milissegundos sem pensar. Mas como ensinar uma máquina a fazer o mesmo de forma confiável? LLMs até conseguem, mas de forma probabilística: às vezes acertam, às vezes inventam, e você nunca sabe qual dos dois aconteceu. A alternativa é implementar regras de inferência simbólica sobre um grafo de conhecimento, onde cada dedução é rastreável, explicável e determinística.
Eu implementei um módulo de raciocínio simbólico com 4 regras que rodam sobre um grafo de crenças: modus ponens generalizado, transitividade, herança de propriedades, e detecção de contradições. Cada inferência carrega a confiança propagada das premissas, e cadeias longas se atenuam naturalmente até serem descartadas. O resultado é um sistema que raciocina de forma previsível e que você consegue debugar olhando qual regra gerou qual conclusão.
Guia de tópicos:
- Por Que Inferência Simbólica se Já Temos LLMs
- As 4 Regras que Cobrem 90% dos Casos
- Propagação de Confiança: Cadeias que se Atenuam
- Detecção de Contradições
- Exemplo Completo em Python
- Considerações Finais
Por Que Inferência Simbólica se Já Temos LLMs
LLMs são incríveis para entender linguagem natural, mas péssimos para raciocínio lógico consistente. Pede para um LLM fazer uma cadeia de 4 inferências transitivas e ele provavelmente vai inventar um atalho ou esquecer uma premissa no meio. Pede para ele detectar uma contradição entre dois fatos que foram mencionados em mensagens separadas há 20 minutos e ele nem vai lembrar que o primeiro fato existe.
Inferência simbólica resolve isso com regras explícitas aplicadas sobre fatos armazenados. O resultado é determinístico (mesma entrada, mesma saída, sempre), rastreável (cada conclusão aponta para a regra e as premissas que a geraram), e barato computacionalmente (microsegundos, não segundos de API).
A combinação ideal é: LLM para extrair fatos de texto livre (ele entende linguagem), simbólico para raciocinar sobre esses fatos (ele é confiável e explicável). Cada um faz o que faz melhor.
As 4 Regras que Cobrem 90% dos Casos
Modus ponens generalizado: certas relações implicam outras. Se algo "pertence" a um grupo, provavelmente tem a "localização" desse grupo. Se algo é "subcategoria" de outro, herda a "definição". Você define uma tabela de implicações com fatores de atenuação (pertence → localização com fator 0.6 significa que a confiança do resultado é 60% da original).
Transitividade: certos verbos são naturalmente transitivos. Se São Paulo está no Brasil e o Brasil está na América do Sul, então São Paulo está na América do Sul. Isso vale para localização, pertencimento, subcategoria. A confiança do resultado é o produto das confianças das duas premissas, o que naturalmente atenua cadeias longas.
Herança de propriedades: se cachorro é definido como animal, e animais respiram oxigênio, então cachorro respira oxigênio. Funciona via o verbo "definição" (relação "é um"): propriedades do pai são herdadas pelo filho com fator de atenuação 0.65. Não é 1.0 porque nem toda propriedade do pai se aplica ao filho (animais voam? nem todos).
Detecção de contradições: se o grafo diz que algo é "vivo" com confiança 0.8 e também "morto" com confiança 0.7, isso é uma contradição. O sistema mantém um mapa de negações (vivo/morto, verdadeiro/falso) e emite alertas quando ambos os lados têm confiança alta. Não resolve automaticamente (quem está certo?), mas sinaliza para investigação.
Propagação de Confiança: Cadeias que se Atenuam
Nenhuma inferência tem confiança 100%. Cada regra multiplica ou atenua a confiança das premissas. Se o fato original tem confiança 0.8 e a transitividade multiplica as confianças, o resultado pode ter 0.64. Se esse resultado for usado em outra inferência, cai para 0.41. Após 3-4 passos, a confiança cai abaixo do threshold mínimo (0.40 no meu caso) e a inferência é descartada.
Isso é crucial porque evita "inferência explosiva": sem atenuação, um único fato poderia gerar milhares de conclusões cada vez mais duvidosas. O sistema é conservador por design. Só propaga o que tem confiança suficiente para ser útil.
Detecção de Contradições
Contradições são inevitáveis em um sistema que aprende de múltiplas fontes. O usuário pode dizer algo errado, a web pode ter informação desatualizada, ou duas fontes podem discordar legitimamente. Em vez de ignorar ou resolver silenciosamente (escolhendo um lado), o sistema detecta e alerta.
O alerta pode disparar o sistema de curiosidade para buscar mais informações e resolver o conflito com evidência adicional. Ou pode ser apresentado ao usuário: "encontrei informações conflitantes sobre X, quer que eu investigue?".
Exemplo Completo em Python
class SymbolicReasoner:
"""Symbolic inference engine over a knowledge graph."""
TRANSITIVE_VERBS = {"localização", "pertence", "subcategoria"}
IMPLIES = [
("pertence", "localização", 0.6),
("subcategoria", "definição", 0.7),
("causa", "precede", 0.5),
]
NEGATIONS = {
"vivo": {"morto", "extinto"},
"morto": {"vivo"},
"verdadeiro": {"falso", "errado"},
"falso": {"verdadeiro"},
}
MIN_CONFIDENCE = 0.40
INHERIT_FACTOR = 0.65
def infer(self, triples: list[dict]) -> list[dict]:
"""Apply all inference rules and return new derived facts."""
inferred = []
triple_map = {(t["s"], t["v"]): (t["o"], t["c"]) for t in triples}
# Rule 1: Modus Ponens — implications between verbs
for (s, v), (o, c) in triple_map.items():
if c < self.MIN_CONFIDENCE:
continue
for src_v, implied_v, factor in self.IMPLIES:
if v == src_v:
new_c = c * factor
if new_c >= self.MIN_CONFIDENCE:
inferred.append({"s": s, "v": implied_v, "o": o,
"c": new_c, "rule": "R1_modus_ponens"})
# Rule 2: Transitivity — A→B, B→C ∴ A→C
for (s, v), (o, c1) in triple_map.items():
if v not in self.TRANSITIVE_VERBS or c1 < self.MIN_CONFIDENCE:
continue
if (o, v) in triple_map:
o2, c2 = triple_map[(o, v)]
new_c = c1 * c2
if new_c >= self.MIN_CONFIDENCE:
inferred.append({"s": s, "v": v, "o": o2,
"c": new_c, "rule": "R2_transitivity"})
# Rule 3: Inheritance — if X is-a Y, X inherits Y's properties
for (s, v), (o, c) in triple_map.items():
if v != "definição" or c < self.MIN_CONFIDENCE:
continue
# Find properties of parent
for (parent, pv), (pobj, pc) in triple_map.items():
if parent == o and pv != "definição":
new_c = c * pc * self.INHERIT_FACTOR
if new_c >= self.MIN_CONFIDENCE:
inferred.append({"s": s, "v": pv, "o": pobj,
"c": new_c, "rule": "R3_inheritance"})
# Rule 4: Contradiction detection
alerts = []
for (s, v), (o, c) in triple_map.items():
negations = self.NEGATIONS.get(o, set())
for (s2, v2), (o2, c2) in triple_map.items():
if s2 == s and v2 == v and o2 in negations:
if c > 0.6 and c2 > 0.6:
alerts.append(f"CONTRADICTION: ({s},{v}) → '{o}' vs '{o2}'")
return inferred, alerts
# Usage
reasoner = SymbolicReasoner()
facts = [
{"s": "são paulo", "v": "localização", "o": "brasil", "c": 0.9},
{"s": "brasil", "v": "localização", "o": "américa do sul", "c": 0.95},
{"s": "cachorro", "v": "definição", "o": "animal", "c": 0.85},
{"s": "animal", "v": "respira", "o": "oxigênio", "c": 0.9},
{"s": "gato", "v": "pertence", "o": "felinos", "c": 0.88},
]
inferred, alerts = reasoner.infer(facts)
print("Inferred facts:")
for i in inferred:
print(f" [{i['rule']}] ({i['s']}, {i['v']}) → {i['o']} c={i['c']:.3f}")
# Output:
# [R1_modus_ponens] (gato, localização) → felinos c=0.528
# [R2_transitivity] (são paulo, localização) → américa do sul c=0.855
# [R3_inheritance] (cachorro, respira) → oxigênio c=0.497
Considerações Finais
Inferência simbólica sobre grafos de conhecimento é uma técnica antiga que ganhou relevância nova na era dos LLMs. Sozinha, ela é limitada (só infere o que as regras permitem). Combinada com extração de fatos via LLM, ela se torna poderosa: o LLM entende linguagem natural e extrai fatos, o simbólico raciocina sobre eles de forma confiável e explicável.
O que eu quero que você leve é que raciocínio não precisa ser probabilístico para tudo. Para transitividade, herança e contradição, regras determinísticas são mais confiáveis, mais rápidas e mais explicáveis que pedir ao LLM para "pensar". Use cada ferramenta para o que ela faz melhor.
Links indicativos:
- Symbolic AI: https://en.wikipedia.org/wiki/Symbolic_artificial_intelligence
- Modus Ponens: https://en.wikipedia.org/wiki/Modus_ponens
- Knowledge Graph Reasoning: https://arxiv.org/abs/2002.00388