# ==========================Factories + Engines========================== # AURA v7 — Neuro‑Symbolic Hybrid Brain # Chunk 1 / 10 # Imports, Utilities, Embedding Service # ========================== import time import re from dataclasses import dataclass, field from typing import List, Dict, Any, Optional, Iterable, Tuple, Callable import torch import networkx as nx from sentence_transformers import SentenceTransformer, util from datasets import load_dataset # ========================== # Device & Embedding Model # ========================== DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu") EMBEDDING_MODEL_NAME = "all-MiniLM-L6-v2" print("Using device:", DEVICE) # ========================== # Utility Functions # ========================== def normalize_text(text: str) -> str: """Lowercase, strip punctuation, collapse whitespace.""" if text is None: return "" text = text.lower().strip() text = re.sub(r"[^\w\s\?]", " ", text) text = re.sub(r"\s+", " ", text) return text def contains_negation(text: str) -> bool: """Detect negation words in natural language.""" neg_words = ["not", "never", "no", "doesnt", "isnt", "arent", "without", "cannot", "can't"] tokens = normalize_text(text).split() return any(w in tokens for w in neg_words) def extract_prob_modifier(text: str) -> float: """ Detect probabilistic language and convert to confidence multipliers. Examples: "always" -> 1.0 "usually" -> 0.8 "often" -> 0.7 "sometimes" -> 0.5 "rarely" -> 0.3 "never" -> 0.0 """ t = normalize_text(text) if "always" in t: return 1.0 if "usually" in t: return 0.8 if "often" in t: return 0.7 if "sometimes" in t: return 0.5 if "rarely" in t: return 0.3 if "never" in t: return 0.0 return 1.0 # default def is_variable(token: Optional[str]) -> bool: """Variables start with ? (e.g., ?x, ?y).""" return isinstance(token, str) and token.startswith("?") and len(token) > 1 # ========================== # Embedding Service # ========================== class EmbeddingService: """Wrapper around SentenceTransformer for consistent encoding.""" def __init__(self, model_name: str = EMBEDDING_MODEL_NAME, device: torch.device = DEVICE): self.model = SentenceTransformer(model_name, device=device) def encode(self, text: str) -> torch.Tensor: return self.model.encode(text, convert_to_tensor=True) def encode_batch(self, texts: Iterable[str]) -> torch.Tensor: return self.model.encode(list(texts), convert_to_tensor=True) # Global embedding service instance embedding_service = EmbeddingService() # ========================== # AURA v7 — Neuro‑Symbolic Hybrid Brain # Chunk 2 / 10 # Core Data Structures # ========================== @dataclass(frozen=True) class Fact: """ A structured fact with: - subject - predicate - object - confidence (0–1) - polarity (+1 = positive, -1 = negated) - source (manual, induced, nl_input, dataset, etc.) """ subject: str predicate: str obj: Optional[str] = None confidence: float = 1.0 polarity: int = 1 verified: bool = True source: str = "unknown" timestamp: float = field(default_factory=time.time) embedding: torch.Tensor = field(init=False, compare=False, repr=False) def __post_init__(self): # Normalize fields object.__setattr__(self, "subject", normalize_text(self.subject)) object.__setattr__(self, "predicate", normalize_text(self.predicate)) if self.obj is not None: object.__setattr__(self, "obj", normalize_text(self.obj)) # Create canonical text for embedding canonical = self.to_text(include_polarity=False) emb = embedding_service.encode(canonical) object.__setattr__(self, "embedding", emb) def to_text(self, include_polarity: bool = True) -> str: """Return human-readable representation.""" base = f"{self.subject} {self.predicate}" if self.obj: base += f" {self.obj}" if include_polarity and self.polarity == -1: base = "NOT " + base return base def key(self) -> str: """Unique key for memory storage.""" pol = "neg" if self.polarity == -1 else "pos" return f"{pol}:{self.to_text(include_polarity=False)}" @dataclass class RulePattern: """ A pattern used in rules, supporting variables (?x, ?y). Includes polarity for negation-aware reasoning. """ subject: str predicate: str obj: Optional[str] = None polarity: int = 1 def normalized(self) -> "RulePattern": return RulePattern( subject=normalize_text(self.subject), predicate=normalize_text(self.predicate), obj=normalize_text(self.obj) if self.obj is not None else None, polarity=self.polarity, ) @dataclass class Rule: """ A rule with: - name - list of condition patterns - conclusion pattern - confidence - source (manual, induced) """ name: str conditions: List[RulePattern] conclusion: RulePattern confidence: float = 1.0 source: str = "manual" def normalized(self) -> "Rule": return Rule( name=self.name, conditions=[c.normalized() for c in self.conditions], conclusion=self.conclusion.normalized(), confidence=self.confidence, source=self.source, ) @dataclass class ReasoningEvent: """ A log entry for meta-memory: - which engine produced it - message - confidence - timestamp """ engine: str message: str confidence: float timestamp: float = field(default_factory=time.time) # ========================== # AURA v7 — Neuro‑Symbolic Hybrid Brain # Chunk 3 / 10 # Retrieval Index + Memory Systems # ========================== # ========================== # Retrieval Index # ========================== class RetrievalIndex: """ Stores embeddings for fast similarity search. Used by semantic memory and analogy engine. """ def __init__(self): self.embeddings: List[torch.Tensor] = [] self.items: List[Any] = [] def add(self, embedding: torch.Tensor, item: Any): self.embeddings.append(embedding) self.items.append(item) def search(self, query_embedding: torch.Tensor, top_k: int = 5) -> List[Tuple[Any, float]]: if not self.embeddings: return [] mat = torch.stack(self.embeddings) sims = util.cos_sim(query_embedding, mat)[0] k = min(top_k, len(sims)) topk = torch.topk(sims, k=k) results = [] for idx in topk.indices: i = idx.item() results.append((self.items[i], sims[i].item())) return results # ========================== # Sensory Memory # ========================== class SensoryMemory: """ Stores raw text entries (e.g., dataset items, Wikipedia text). Used as fallback when structured reasoning fails. """ def __init__(self): self.entries: List[str] = [] self.entry_embeddings: List[torch.Tensor] = [] def add_entry(self, text: str, embedding: Optional[torch.Tensor] = None): self.entries.append(text) if embedding is None: embedding = embedding_service.encode(normalize_text(text)) self.entry_embeddings.append(embedding) # ========================== # Working Memory # ========================== class WorkingMemory: """ Stores active facts used for reasoning. """ def __init__(self): self.facts: Dict[str, Fact] = {} def add_fact(self, fact: Fact): self.facts[fact.key()] = fact def has_fact(self, fact: Fact) -> bool: return fact.key() in self.facts def all_facts(self) -> List[Fact]: return list(self.facts.values()) # ========================== # Semantic Memory # ========================== class SemanticMemory: """ Stores long-term structured knowledge. Uses a graph + retrieval index. """ def __init__(self): self.graph = nx.DiGraph() self.index = RetrievalIndex() self.fact_map: Dict[str, Fact] = {} def add_fact(self, fact: Fact): key = fact.key() # If fact exists, keep the one with higher confidence if key in self.fact_map: existing = self.fact_map[key] if fact.confidence > existing.confidence: self.fact_map[key] = fact return self.fact_map[key] = fact self.graph.add_node(key, data=fact) self.index.add(fact.embedding, fact) def add_relation(self, source: Fact, target: Fact, relation: str, weight: float = 1.0): self.graph.add_edge(source.key(), target.key(), relation=relation, weight=weight) def search_fact(self, query_embedding: torch.Tensor, threshold: float = 0.6) -> Optional[Fact]: results = self.index.search(query_embedding, top_k=5) best = [(f, score) for f, score in results if score >= threshold] if not best: return None best.sort(key=lambda x: x[1], reverse=True) return best[0][0] # ========================== # Episodic Memory # ========================== @dataclass class Episode: description: str facts: List[Fact] timestamp: float = field(default_factory=time.time) class EpisodicMemory: """ Stores episodes: groups of facts tied to a specific event or dataset item. """ def __init__(self): self.episodes: List[Episode] = [] def add_episode(self, description: str, facts: List[Fact]): self.episodes.append(Episode(description=description, facts=facts)) # ========================== # Procedural Memory # ========================== class ProceduralMemory: """ Stores learned procedures (functions). """ def __init__(self): self.procedures: Dict[str, Callable] = {} def add_procedure(self, name: str, func: Callable): self.procedures[name] = func def get_procedure(self, name: str) -> Optional[Callable]: return self.procedures.get(name) # ========================== # Meta-Memory # ========================== class MetaMemory: """ Tracks: - reasoning events - contradictions - engine reliability scores """ def __init__(self): self.contradictions: List[str] = [] self.events: List[ReasoningEvent] = [] self.engine_scores: Dict[str, float] = {} # reliability scores def log(self, engine: str, message: str, confidence: float): self.events.append(ReasoningEvent(engine=engine, message=message, confidence=confidence)) # Update engine reliability self.engine_scores[engine] = self.engine_scores.get(engine, 0.5) * 0.9 + confidence * 0.1 def add_contradiction(self, fact1: Fact, fact2: Fact): msg = f"CONTRADICTION: '{fact1.to_text()}' conflicts with '{fact2.to_text()}'" self.contradictions.append(msg) self.events.append(ReasoningEvent(engine="TMS", message=msg, confidence=0.0)) def recent_trace(self, n: int = 20) -> List[ReasoningEvent]: return self.events[-n:] # ========================== # AURA v7 — Neuro‑Symbolic Hybrid Brain # Chunk 4 / 10 # Unification Engine # ========================== from abc import ABC, abstractmethod class ReasoningEngineBase(ABC): """Abstract base class for all reasoning engines.""" name: str @abstractmethod def reason_forward(self, engine: "CognitiveEngine") -> Tuple[List["Fact"], List[str], float]: pass @abstractmethod def reason_backward(self, engine: "CognitiveEngine", goal: "RulePattern") -> Tuple[List["Fact"], List[str], float]: pass def unify_token(pattern: Optional[str], value: Optional[str], subst: Dict[str, str]) -> Optional[Dict[str, str]]: """ Unify a single token: - If pattern is a variable (?x), bind it. - If pattern is a constant, it must match value. """ if pattern is None and value is None: return subst if pattern is None or value is None: return None pattern = normalize_text(pattern) value = normalize_text(value) # Variable case if is_variable(pattern): var = pattern if var in subst: # Already bound → must match return subst if subst[var] == value else None # Bind new variable new_subst = dict(subst) new_subst[var] = value return new_subst # Constant case if pattern == value: return subst return None def unify_fact(pattern: "RulePattern", fact: "Fact", subst: Dict[str, str]) -> Optional[Dict[str, str]]: """ Unify a rule pattern with a fact. Includes polarity matching. """ # Polarity must match if pattern.polarity != fact.polarity: return None # Subject subst1 = unify_token(pattern.subject, fact.subject, subst) if subst1 is None: return None # Predicate subst2 = unify_token(pattern.predicate, fact.predicate, subst1) if subst2 is None: return None # Object subst3 = unify_token(pattern.obj, fact.obj, subst2) return subst3 def apply_substitution(pattern: "RulePattern", subst: Dict[str, str]) -> "RulePattern": """ Apply variable bindings to a rule pattern. """ def apply_token(token: Optional[str]) -> Optional[str]: if token is None: return None token = normalize_text(token) if is_variable(token) and token in subst: return subst[token] return token return RulePattern( subject=apply_token(pattern.subject), predicate=apply_token(pattern.predicate), obj=apply_token(pattern.obj), polarity=pattern.polarity, ) # ========================== # AURA v7 — Neuro‑Symbolic Hybrid Brain # Chunk 5 / 10 # Deductive Engine (Forward + Backward) # ========================== class DeductiveEngine(ReasoningEngineBase): name = "deductive" # --------------------------------------------------------- # Forward Chaining # --------------------------------------------------------- def reason_forward(self, engine: "CognitiveEngine") -> Tuple[List[Fact], List[str], float]: new_facts: List[Fact] = [] trace: List[str] = [] avg_conf = 0.0 count = 0 facts = engine.working.all_facts() rules = [r.normalized() for r in engine.rules] for rule in rules: matches = self._match_rule(rule, facts) for subst, cond_facts in matches: concl_pattern = apply_substitution(rule.conclusion, subst) # Polarity propagation polarity = concl_pattern.polarity # Confidence propagation conf = self._propagate_confidence(rule, cond_facts) concl_fact = Fact( subject=concl_pattern.subject, predicate=concl_pattern.predicate, obj=concl_pattern.obj, polarity=polarity, confidence=conf, verified=True, source=f"rule:{rule.name}", ) # Contradiction detection self._check_contradictions(engine, concl_fact) if not engine.working.has_fact(concl_fact): new_facts.append(concl_fact) used = ", ".join(f.to_text() for f in cond_facts) msg = ( f"[Deduction] {rule.name} with {used} " f"-> {concl_fact.to_text()} (conf={concl_fact.confidence:.2f})" ) trace.append(msg) avg_conf += concl_fact.confidence count += 1 if count > 0: avg_conf /= count else: avg_conf = 0.0 return new_facts, trace, avg_conf # --------------------------------------------------------- # Backward Chaining # --------------------------------------------------------- def reason_backward(self, engine: "CognitiveEngine", goal: RulePattern) -> Tuple[List[Fact], List[str], float]: trace: List[str] = [] proven_facts: List[Fact] = [] avg_conf = 0.0 count = 0 # 1. Check if goal already exists in working memory for f in engine.working.all_facts(): if unify_fact(goal, f, {}) is not None: proven_facts.append(f) trace.append(f"[Backward-Deduction] Goal already known: {f.to_text()}") avg_conf += f.confidence count += 1 return proven_facts, trace, avg_conf / max(count, 1) # 2. Try to prove goal using rules rules = [r.normalized() for r in engine.rules] for rule in rules: subst = unify_fact(rule.conclusion, Fact(goal.subject, goal.predicate, goal.obj, polarity=goal.polarity), {}) if subst is None: continue # Try to prove all conditions all_proven = True cond_facts: List[Fact] = [] for cond in rule.conditions: cond_goal = apply_substitution(cond, subst) pf, pt, pc = self.reason_backward(engine, cond_goal) trace.extend(pt) if not pf: all_proven = False break cond_facts.extend(pf) avg_conf += pc count += 1 if all_proven: concl_pattern = apply_substitution(rule.conclusion, subst) concl_fact = Fact( subject=concl_pattern.subject, predicate=concl_pattern.predicate, obj=concl_pattern.obj, polarity=concl_pattern.polarity, confidence=self._propagate_confidence(rule, cond_facts), verified=True, source=f"rule:{rule.name}", ) proven_facts.append(concl_fact) trace.append(f"[Backward-Deduction] Proved {concl_fact.to_text()} via {rule.name}") avg_conf += concl_fact.confidence count += 1 break if count > 0: avg_conf /= count else: avg_conf = 0.0 return proven_facts, trace, avg_conf # --------------------------------------------------------- # Rule Matching # --------------------------------------------------------- def _match_rule(self, rule: Rule, facts: List[Fact]) -> List[Tuple[Dict[str, str], List[Fact]]]: results: List[Tuple[Dict[str, str], List[Fact]]] = [] def backtrack(i: int, subst: Dict[str, str], chosen: List[Fact]): if i == len(rule.conditions): results.append((subst, chosen.copy())) return pattern = rule.conditions[i] for fact in facts: new_subst = unify_fact(pattern, fact, subst) if new_subst is not None and fact not in chosen: chosen.append(fact) backtrack(i + 1, new_subst, chosen) chosen.pop() backtrack(0, {}, []) return results # --------------------------------------------------------- # Confidence Propagation # --------------------------------------------------------- def _propagate_confidence(self, rule: Rule, cond_facts: List[Fact]) -> float: conf = rule.confidence for f in cond_facts: conf *= f.confidence return max(min(conf, 1.0), 0.0) # --------------------------------------------------------- # Contradiction Detection # --------------------------------------------------------- def _check_contradictions(self, engine: "CognitiveEngine", new_fact: Fact): """ If a fact with opposite polarity exists, log contradiction. """ opposite_key = ("neg:" if new_fact.polarity == 1 else "pos:") + new_fact.to_text(include_polarity=False) if opposite_key in engine.semantic.fact_map: engine.meta.add_contradiction(new_fact, engine.semantic.fact_map[opposite_key]) # ========================== # AURA v7 — Neuro‑Symbolic Hybrid Brain # Chunk 6 / 10 # Inductive Engine + Analogical Engine # ========================== class InductiveEngine(ReasoningEngineBase): """ Learns new rules from repeated relational patterns. Example: If we see: fire is hot touching_fire causes burn stove is hot touching_stove causes burn → Induce rule: hot things burn """ name = "inductive" def reason_forward(self, engine: "CognitiveEngine") -> Tuple[List[Fact], List[str], float]: trace: List[str] = [] new_facts: List[Fact] = [] avg_conf = 0.0 count = 0 facts = engine.working.all_facts() # Collect patterns hot_map = {} burn_map = {} for f in facts: if f.predicate == "is" and f.obj == "hot" and f.polarity == 1: hot_map[f.subject] = f if f.predicate == "causes" and f.obj == "burn" and f.subject.startswith("touching_") and f.polarity == 1: x = f.subject.replace("touching_", "") burn_map[x] = f # Look for repeated pattern common = set(hot_map.keys()) & set(burn_map.keys()) if len(common) >= 2: # Induce rule rule = Rule( name="induced_hot_things_burn_rule", conditions=[RulePattern(subject="?x", predicate="is", obj="hot", polarity=1)], conclusion=RulePattern(subject="touching_?x", predicate="causes", obj="burn", polarity=1), confidence=0.8, source="induced", ) if rule.name not in [r.name for r in engine.rules]: engine.rules.append(rule) msg = "[Induction] Learned rule: if ?x is hot → touching_?x causes burn" trace.append(msg) avg_conf = 0.8 count = 1 return new_facts, trace, avg_conf def reason_backward(self, engine: "CognitiveEngine", goal: RulePattern): # Induction is forward-only return [], [], 0.0 # ========================== # Analogical Engine # ========================== class AnalogicalEngine(ReasoningEngineBase): """ Structural analogy + embeddings. Example: fire is hot touching_fire causes burn stove is hot → touching_stove causes burn (by analogy) """ name = "analogical" def reason_forward(self, engine: "CognitiveEngine") -> Tuple[List[Fact], List[str], float]: trace = [] new_facts = [] avg_conf = 0.0 count = 0 facts = engine.working.all_facts() hot_subjects = [f for f in facts if f.predicate == "is" and f.obj == "hot" and f.polarity == 1] burn_facts = [f for f in facts if f.predicate == "causes" and f.obj == "burn" and f.subject.startswith("touching_")] for hf in hot_subjects: for bf in burn_facts: x = bf.subject.replace("touching_", "") if x == hf.subject: # Find analogous subjects for hf2 in hot_subjects: if hf2.subject == hf.subject: continue sim = util.cos_sim(hf.embedding, hf2.embedding).item() if sim > 0.6: concl = Fact( subject=f"touching_{hf2.subject}", predicate="causes", obj="burn", polarity=1, confidence=0.7 * sim, verified=False, source="analogical", ) if not engine.working.has_fact(concl): new_facts.append(concl) msg = ( f"[Analogy] From {hf.subject}~{hf2.subject} and {bf.to_text()} " f"→ {concl.to_text()} (sim={sim:.2f})" ) trace.append(msg) avg_conf += concl.confidence count += 1 if count > 0: avg_conf /= count else: avg_conf = 0.0 return new_facts, trace, avg_conf def reason_backward(self, engine: "CognitiveEngine", goal: RulePattern): # Analogy is forward-only return [], [], 0.0 # ========================== # AURA v7 — Neuro‑Symbolic Hybrid Brain # Chunk 7 / 10 # Counterfactual Engine + Meta‑Controller + CognitiveEngine # ========================== class CounterfactualEngine(ReasoningEngineBase): """ Hybrid counterfactual reasoning: - Symbolic intervention: replace a fact and re-run reasoning - Causal-ish graph reasoning via semantic memory """ name = "counterfactual" def reason_forward(self, engine: "CognitiveEngine"): # Counterfactuals are not automatically generated return [], [], 0.0 def reason_backward(self, engine: "CognitiveEngine", goal: RulePattern): # Counterfactuals require explicit user request return [], [], 0.0 def simulate(self, engine: "CognitiveEngine", intervention_fact: Fact) -> Dict[str, Any]: """ Perform a symbolic intervention: - Temporarily add the fact - Re-run forward reasoning - Observe differences """ temp_engine = engine.clone() temp_engine.add_fact(intervention_fact) temp_engine.reason_forward_until_fixpoint(max_iterations=3) return { "intervention": intervention_fact.to_text(), "new_facts": [f.to_text() for f in temp_engine.working.all_facts()], } # ========================== # Meta-Controller # ========================== class MetaController: """ Chooses which reasoning engines to trust based on: - Past performance (engine_scores) - Confidence of recent outputs """ def __init__(self, meta_memory: MetaMemory): self.meta = meta_memory def choose_engines_forward(self, engines: List[ReasoningEngineBase]) -> List[ReasoningEngineBase]: scored = [] for e in engines: score = self.meta.engine_scores.get(e.name, 0.5) scored.append((score, e)) scored.sort(key=lambda x: x[0], reverse=True) return [e for _, e in scored] def choose_engines_backward(self, engines: List[ReasoningEngineBase]) -> List[ReasoningEngineBase]: return self.choose_engines_forward(engines) # ========================== # Cognitive Engine (Core Brain) # ========================== class CognitiveEngine: """ The central orchestrator: - Holds all memory systems - Holds all reasoning engines - Runs forward/backward reasoning - Handles contradictions """ def __init__(self): # Memory systems self.sensory = SensoryMemory() self.working = WorkingMemory() self.semantic = SemanticMemory() self.episodic = EpisodicMemory() self.procedural = ProceduralMemory() self.meta = MetaMemory() # Reasoning engines self.engines: List[ReasoningEngineBase] = [ DeductiveEngine(), InductiveEngine(), AnalogicalEngine(), CounterfactualEngine(), ] # Meta-controller self.meta_controller = MetaController(self.meta) # Rule store self.rules: List[Rule] = [] # ------------------------- # Fact & Rule Management # ------------------------- def add_fact(self, fact: Fact): """ Add fact to working + semantic memory. Check for contradictions. """ # Check for contradictions opposite_key = ("neg:" if fact.polarity == 1 else "pos:") + fact.to_text(include_polarity=False) if opposite_key in self.semantic.fact_map: self.meta.add_contradiction(fact, self.semantic.fact_map[opposite_key]) self.working.add_fact(fact) self.semantic.add_fact(fact) def add_rule(self, rule: Rule): self.rules.append(rule) # ------------------------- # Forward Reasoning Loop # ------------------------- def reason_forward_until_fixpoint(self, max_iterations: int = 5): """ Run forward reasoning until no new facts are produced. """ for _ in range(max_iterations): any_new = False ordered_engines = self.meta_controller.choose_engines_forward(self.engines) for engine in ordered_engines: new_facts, trace, avg_conf = engine.reason_forward(self) if new_facts: any_new = True for f in new_facts: self.add_fact(f) for t in trace: self.meta.log(engine.name, t, avg_conf if avg_conf > 0 else 0.5) if not any_new: break # ------------------------- # Backward Reasoning # ------------------------- def reason_backward(self, goal: RulePattern) -> Tuple[List[Fact], List[str], float]: ordered_engines = self.meta_controller.choose_engines_backward(self.engines) best_facts = [] best_trace = [] best_conf = 0.0 for engine in ordered_engines: facts, trace, conf = engine.reason_backward(self, goal) if facts and conf > best_conf: best_facts = facts best_trace = trace best_conf = conf return best_facts, best_trace, best_conf # ------------------------- # Cloning (for counterfactuals) # ------------------------- def clone(self) -> "CognitiveEngine": """ Create a deep-ish clone of the engine for counterfactual simulation. """ new = CognitiveEngine() # Copy facts for f in self.working.all_facts(): new.add_fact(f) # Copy rules for r in self.rules: new.add_rule(r) return new # ========================== # AURA v7 — Neuro‑Symbolic Hybrid Brain # Chunk 8 / 10 # Natural Language Parser (Hybrid) # ========================== class NLParser: """ Hybrid natural language parser: - Rule-based parsing for simple patterns - Embedding-based fallback - Negation detection - Probabilistic modifier extraction """ def __init__(self, engine: CognitiveEngine): self.engine = engine # --------------------------------------------------------- # Assertion Parsing (creates Facts) # --------------------------------------------------------- def parse_assertion(self, text: str) -> Optional[Fact]: """ Convert natural language assertions into structured Facts. Handles: - "X is Y" - "X causes Y" - Negation ("not", "never", etc.) - Probabilistic modifiers ("usually", "rarely") """ t = normalize_text(text) neg = contains_negation(t) polarity = -1 if neg else 1 prob = extract_prob_modifier(t) # Remove negation words for cleaner parsing t_clean = re.sub(r"\bnot\b|\bnever\b|\bdoesnt\b|\bisnt\b|\barent\b", "", t).strip() # Pattern: "x is y" m = re.match(r"(.+?) is (.+)", t_clean) if m: subj = m.group(1).strip() obj = m.group(2).strip() return Fact( subject=subj, predicate="is", obj=obj, polarity=polarity, confidence=prob, source="nl_input", ) # Pattern: "x causes y" m = re.match(r"(.+?) causes (.+)", t_clean) if m: subj = m.group(1).strip() obj = m.group(2).strip() return Fact( subject=subj, predicate="causes", obj=obj, polarity=polarity, confidence=prob, source="nl_input", ) # Fallback: treat as descriptive fact return Fact( subject=t_clean, predicate="describes", obj=None, polarity=polarity, confidence=prob, source="nl_input", ) # --------------------------------------------------------- # Query Parsing (creates RulePattern) # --------------------------------------------------------- def parse_query_to_goal(self, text: str) -> RulePattern: """ Convert natural language questions into RulePatterns. Handles: - "Is X Y?" - "Does X cause Y?" - Negation ("not", "never") """ t = normalize_text(text) neg = contains_negation(t) polarity = -1 if neg else 1 # Remove negation words for cleaner parsing t_clean = re.sub(r"\bnot\b|\bnever\b|\bdoesnt\b|\bisnt\b|\barent\b", "", t).strip() # Pattern: "is x y?" m = re.match(r"is (.+?) (.+)\??", t_clean) if m: subj = m.group(1).strip() obj = m.group(2).strip() return RulePattern( subject=subj, predicate="is", obj=obj, polarity=polarity, ) # Pattern: "does x cause y?" m = re.match(r"does (.+?) cause (.+)\??", t_clean) if m: subj = m.group(1).strip() obj = m.group(2).strip() return RulePattern( subject=subj, predicate="causes", obj=obj, polarity=polarity, ) # Fallback return RulePattern( subject=t_clean, predicate="describes", obj=None, polarity=polarity, ) # ========================== # AURA v7 — Neuro‑Symbolic Hybrid Brain # Chunk 9 / 10 # Dataset Ingestion (Omniscience) # ========================== def ingest_omniscience(engine: CognitiveEngine, max_items: int = 200): """ Ingests the ArtificialAnalysis/AA-Omniscience-Public dataset into sensory, semantic, and episodic memory. Each dataset item typically contains: - "input": natural language prompt - "output": natural language answer - "metadata": optional """ print("Loading Omniscience dataset...") ds = load_dataset("ArtificialAnalysis/AA-Omniscience-Public") data = ds["train"] parser = NLParser(engine) count = 0 for item in data: text_in = item.get("input", "") text_out = item.get("output", "") if not text_in and not text_out: continue # ------------------------- # Sensory Memory # ------------------------- combined_text = f"{text_in} -> {text_out}" normalized = normalize_text(combined_text) emb = embedding_service.encode(normalized) engine.sensory.add_entry(combined_text, embedding=emb) # ------------------------- # Structured Fact Extraction # ------------------------- fact_in = parser.parse_assertion(text_in) if text_in else None fact_out = parser.parse_assertion(text_out) if text_out else None # Add to semantic + working memory local_facts = [] if fact_in: engine.add_fact(fact_in) local_facts.append(fact_in) if fact_out: engine.add_fact(fact_out) local_facts.append(fact_out) # ------------------------- # Episodic Memory # ------------------------- if local_facts: engine.episodic.add_episode( description="omniscience_item", facts=local_facts ) count += 1 if count >= max_items: break print(f"Ingested {count} items from AA-Omniscience-Public dataset.") # ========================== # AURA v7 — Neuro‑Symbolic Hybrid Brain # Chunk 10 / 10 # AURA Interface + main() # ========================== class AURAInterface: """ High-level interface for interacting with AURA: - assert_fact(text) - query(text) """ def __init__(self, engine: CognitiveEngine): self.engine = engine self.parser = NLParser(engine) # --------------------------------------------------------- # Assertions # --------------------------------------------------------- def assert_fact(self, text: str) -> Fact: fact = self.parser.parse_assertion(text) self.engine.add_fact(fact) return fact # --------------------------------------------------------- # Queries # --------------------------------------------------------- def query(self, text: str) -> Dict[str, Any]: normalized = normalize_text(text) query_embedding = embedding_service.encode(normalized) # Parse into structured goal goal = self.parser.parse_query_to_goal(text) # If negated, require explicit proof if goal.polarity == -1: facts, trace, conf = self.engine.reason_backward(goal) if facts: best = max(facts, key=lambda f: f.confidence) return { "response": "Yes", "explanation": f"Proved negated fact: '{best.to_text()}'", "confidence": float(best.confidence), "trace": trace + [e.message for e in self.engine.meta.recent_trace()], } else: return { "response": "No", "explanation": "No rule or fact supports the negated claim.", "confidence": 0.0, "trace": [e.message for e in self.engine.meta.recent_trace()], } # Try backward reasoning first facts, trace, conf = self.engine.reason_backward(goal) if facts: best = max(facts, key=lambda f: f.confidence) return { "response": "Yes" if best.polarity == 1 else "No", "explanation": f"Proved: '{best.to_text()}' via backward reasoning.", "confidence": float(best.confidence), "trace": trace + [e.message for e in self.engine.meta.recent_trace()], } # Semantic memory fallback fact = self.engine.semantic.search_fact(query_embedding, threshold=0.6) if fact: return { "response": "Yes" if fact.polarity == 1 else "No", "explanation": f"Found in semantic memory: '{fact.to_text()}'", "confidence": float(fact.confidence), "trace": [e.message for e in self.engine.meta.recent_trace()], } # Sensory memory fallback best_idx = None best_score = 0.0 for idx, emb in enumerate(self.engine.sensory.entry_embeddings): sim = util.cos_sim(query_embedding, emb).item() if sim > best_score: best_score = sim best_idx = idx if best_idx is not None and best_score >= 0.35: best_entry = self.engine.sensory.entries[best_idx] return { "response": "Possibly", "explanation": f"Sensory memory match: {best_entry[:200]}...", "confidence": float(best_score), "trace": [e.message for e in self.engine.meta.recent_trace()], } # Unknown return { "response": "Unknown", "explanation": f"No information found for '{text}'", "confidence": 0.0, "trace": [e.message for e in self.engine.meta.recent_trace()], } # ========================== # Core Knowledge Initialization # ========================== def build_core_knowledge(engine: CognitiveEngine): """ Load basic commonsense knowledge + rules. """ fire_hot = Fact(subject="fire", predicate="is", obj="hot", confidence=0.95, polarity=1, source="core") stove_hot = Fact(subject="stove", predicate="is", obj="hot", confidence=0.9, polarity=1, source="core") touching_fire_burn = Fact(subject="touching_fire", predicate="causes", obj="burn", confidence=0.95, polarity=1, source="core") engine.add_fact(fire_hot) engine.add_fact(stove_hot) engine.add_fact(touching_fire_burn) # Manual rules rule1 = Rule( name="hot_things_burn_rule", conditions=[RulePattern(subject="?x", predicate="is", obj="hot", polarity=1)], conclusion=RulePattern(subject="touching_?x", predicate="causes", obj="burn", polarity=1), confidence=0.9, source="manual", ) rule2 = Rule( name="burn_implies_danger_rule", conditions=[RulePattern(subject="touching_?x", predicate="causes", obj="burn", polarity=1)], conclusion=RulePattern(subject="?x", predicate="is", obj="dangerous", polarity=1), confidence=0.9, source="manual", ) # Negation rule example rule3 = Rule( name="cold_things_do_not_burn_rule", conditions=[RulePattern(subject="?x", predicate="is", obj="cold", polarity=1)], conclusion=RulePattern(subject="touching_?x", predicate="causes", obj="burn", polarity=-1), confidence=0.9, source="manual", ) engine.add_rule(rule1) engine.add_rule(rule2) engine.add_rule(rule3) # ========================== # Main REPL # ========================== def main(): engine = CognitiveEngine() api = AURAInterface(engine) # Load core knowledge build_core_knowledge(engine) engine.reason_forward_until_fixpoint(max_iterations=5) # Load Omniscience dataset ingest_omniscience(engine, max_items=50) print("\nAURA v7 ready. Type assertions or questions.") print("Examples:") print(" - 'fire is hot'") print(" - 'ice is cold'") print(" - 'does touching fire cause burn?'") print(" - 'does touching ice cause burn?'") print(" - 'is stove dangerous?'") print(" - 'do hot things NOT burn with fire?'") print("Type 'exit' to quit.\n") while True: try: query = input("You: ") except EOFError: break if query.lower() in {"exit", "quit"}: print("Goodbye.") break # Assertions if query.lower().startswith("assert "): fact = api.assert_fact(query[len("assert "):]) engine.reason_forward_until_fixpoint(max_iterations=3) print(f"AURA: Asserted '{fact.to_text()}' (conf={fact.confidence:.2f})\n") continue # Queries response = api.query(query) print(f"AURA Response: {response['response']}") print(f"Explanation: {response['explanation']}") print(f"Confidence: {response['confidence']:.2f}") if response.get("trace"): print("Recent reasoning trace:") for line in response["trace"][-10:]: print(" -", line) print() if __name__ == "__main__": main()