WorldNodes: Organizando Conhecimento em Mundos que Evoluem
Como organizar o conhecimento de uma IA que conversa sobre programação, culinária, investimentos e história no mesmo dia? Se você jogar tudo em um único grafo, vira uma sopa onde "Python" (linguagem) se mistura com "Python" (cobra) e "receita" (culinária) se confunde com "receita" (médica). A solução que encontrei é separar o conhecimento em mundos temáticos que evoluem independentemente, cada um com seu próprio grafo, centroide vetorial e maturidade.
Chamo esses mundos de WorldNodes. Cada um representa um domínio de conhecimento. Eles nascem quando o sistema encontra um tema novo que não se encaixa em nenhum mundo existente, crescem conforme recebem informação, estabilizam quando amadurecem, e podem até se fundir quando ficam similares demais. É uma organização orgânica que não precisa de taxonomia pré-definida.
Guia de tópicos:
- O Problema do Grafo Único
- Anatomia de um WorldNode
- Como Escolher o Mundo Certo para uma Mensagem
- Centroide Adaptativo: Mundos que Estabilizam
- Ciclo de Vida: Nascimento, Crescimento, Fusão, Morte
- Exemplo Prático em Python
- Considerações Finais
O Problema do Grafo Único
Se todo conhecimento vive em um único grafo, você tem dois problemas sérios. Primeiro, ambiguidade: "Java" é uma linguagem de programação ou uma ilha na Indonésia? Sem contexto, o grafo não sabe qual "Java" você quer. Segundo, poluição de contexto: quando o usuário pergunta sobre programação, você não quer que fatos sobre culinária apareçam como contexto relevante. Um grafo único não tem noção de "relevância contextual".
Mundos resolvem ambos: "Java" no mundo de Programação é a linguagem. "Java" no mundo de Geografia é a ilha. E quando o usuário pergunta sobre programação, só o mundo de Programação é consultado. A desambiguação é automática pelo contexto semântico da mensagem.
Anatomia de um WorldNode
Um WorldNode tem: um ID único (8 caracteres), um centroide (vetor de 384 dimensões que representa o "significado médio" de tudo que foi dito sobre aquele tema), um nome de tópico (gerado pelo LLM na criação), contagem de acessos, timestamp de criação, e um KnowledgeGraph interno com todas as crenças daquele domínio.
O centroide é a peça mais importante: é ele que permite encontrar o mundo certo para uma mensagem nova em milissegundos via busca vetorial. Quando o usuário fala sobre "variáveis em Python", o embedding dessa frase é comparado com os centroides de todos os mundos, e o mais similar (provavelmente "Programação Python") é selecionado.
Como Escolher o Mundo Certo para uma Mensagem
A busca usa um índice HNSW para encontrar os mundos mais próximos do embedding da mensagem em tempo O(log n). Para cada candidato, calcula a similaridade coseno e compara com um threshold dinâmico.
O threshold dinâmico é o detalhe inteligente: threshold = 0.60 + maturidade × 0.10. Mundos maduros (com muitas crenças de alta confiança) exigem similaridade maior para aceitar mensagens novas. Um mundo maduro sobre "Python programação" com maturidade 0.9 exige similaridade > 0.69. Um mundo jovem com maturidade 0.1 aceita similaridade > 0.61.
Isso evita que mundos maduros e específicos absorvam mensagens tangencialmente relacionadas. Se nenhum mundo passa o threshold, um novo é criado. É preferível criar um mundo novo do que forçar associação com um inadequado.
Centroide Adaptativo: Mundos que Estabilizam
Quando um mundo recebe uma mensagem nova, seu centroide é atualizado com média ponderada: centroide_novo = (1 - α) × centroide_antigo + α × embedding_mensagem. O α diminui conforme o mundo amadurece.
A fórmula: α = 1/(access_count + 1) × (1 - maturidade × 0.7). Um mundo com 100 acessos e maturidade 0.8 tem α ≈ 0.003 (praticamente não muda). Um mundo com 2 acessos e maturidade 0.1 tem α ≈ 0.31 (muda bastante).
Isso simula como conhecimento se estabiliza: no começo, cada informação nova pode mudar significativamente o que o mundo "é sobre". Com o tempo, o tema se consolida e novas informações são absorvidas sem mudar a identidade do mundo. É convergência natural.
Ciclo de Vida: Nascimento, Crescimento, Fusão, Morte
Nascimento: mensagem chega, nenhum mundo é similar o suficiente, novo WorldNode é criado com centroide = embedding da mensagem e nome gerado pelo LLM.
Crescimento: mensagens subsequentes sobre o mesmo tema são associadas ao mundo, triplas são adicionadas, centroide é refinado, maturidade sobe gradualmente.
Fusão: periodicamente, o sistema verifica se existem pares de mundos com similaridade > 0.94. Se existem, são fundidos em um único mundo mais completo. Isso resolve fragmentação natural (o usuário falou sobre "machine learning" e "aprendizado de máquina" separadamente).
Morte: mundos sem triplas (criados por engano ou esvaziados por decay temporal) são removidos na inicialização. Limpeza automática sem intervenção.
Exemplo Prático em Python
import numpy as np
import uuid
class WorldNode:
def __init__(self, vector, topic="unknown"):
self.id = str(uuid.uuid4())[:8]
self.centroid = np.array(vector, dtype=float)
self.topic = topic
self.access_count = 1
self.triples = []
@property
def maturity(self):
"""Maturity based on number and confidence of beliefs."""
if not self.triples:
return 0.0
avg_conf = np.mean([t.get("c", 0.5) for t in self.triples])
return float(np.clip(avg_conf * min(len(self.triples) / 10, 1.0), 0, 1))
def absorb(self, new_vector, new_triples):
"""Absorb new information. Mature worlds change less."""
alpha = (1.0 / (self.access_count + 1)) * (1.0 - self.maturity * 0.7)
self.centroid = (1 - alpha) * self.centroid + alpha * np.array(new_vector)
self.access_count += 1
self.triples.extend(new_triples)
def similarity_threshold(self):
"""Dynamic threshold: mature worlds are more selective."""
return 0.60 + self.maturity * 0.10
def find_best_world(query_vector, worlds: list['WorldNode']):
"""Find the best matching world for a query, or None if no match."""
best, highest_sim = None, -1.0
for world in worlds:
n = np.linalg.norm(query_vector) * np.linalg.norm(world.centroid)
if n == 0:
continue
sim = float(np.dot(query_vector, world.centroid) / n)
threshold = world.similarity_threshold()
if sim > threshold and sim > highest_sim:
best, highest_sim = world, sim
return best, highest_sim
# Demo: creating and evolving worlds
np.random.seed(42)
base_programming = np.random.randn(384)
base_cooking = np.random.randn(384)
worlds = [
WorldNode(base_programming, "Programação"),
WorldNode(base_cooking, "Culinária"),
]
# Simulate messages about programming (similar to programming world)
for i in range(10):
msg_vector = base_programming + np.random.randn(384) * 0.2
world, sim = find_best_world(msg_vector, worlds)
if world:
world.absorb(msg_vector, [{"s": f"concept_{i}", "v": "is", "o": "code", "c": 0.8}])
print("After 10 programming messages:")
for w in worlds:
print(f" [{w.topic}] access={w.access_count}, maturity={w.maturity:.3f}, "
f"threshold={w.similarity_threshold():.3f}")
# New message about cooking — should NOT go to programming world
cooking_msg = base_cooking + np.random.randn(384) * 0.1
world, sim = find_best_world(cooking_msg, worlds)
print(f"\nCooking message matched: {world.topic if world else 'None'} (sim={sim:.3f})")
Considerações Finais
WorldNodes são a resposta para o problema de organização de conhecimento em sistemas conversacionais. Em vez de um grafo monolítico, você tem uma coleção de mundos especializados que nascem, crescem, se fundem e morrem organicamente. Cada mundo é um especialista em seu domínio, e o sistema sabe qual especialista consultar para cada pergunta.
O conceito é inspirado em como humanos organizam conhecimento: não temos um único "banco de dados" mental. Temos contextos, domínios, áreas de expertise que se ativam conforme o assunto da conversa muda. WorldNodes são a implementação computacional dessa ideia.
Links indicativos:
- Word Embeddings: https://en.wikipedia.org/wiki/Word_embedding
- Cosine Similarity: https://en.wikipedia.org/wiki/Cosine_similarity
- HNSW: https://arxiv.org/abs/1603.09320