75 lines
2.6 KiB
Python
75 lines
2.6 KiB
Python
|
|
"""Sovereign Intersymbolic Memory Layer.
|
||
|
|
|
||
|
|
Bridges Neural (LLM) and Symbolic (Graph) reasoning by extracting
|
||
|
|
structured triples from unstructured text and performing graph lookups.
|
||
|
|
"""
|
||
|
|
|
||
|
|
import logging
|
||
|
|
import json
|
||
|
|
from typing import List, Dict, Any
|
||
|
|
from agent.gemini_adapter import GeminiAdapter
|
||
|
|
from tools.graph_store import GraphStore
|
||
|
|
|
||
|
|
logger = logging.getLogger(__name__)
|
||
|
|
|
||
|
|
class SymbolicMemory:
|
||
|
|
def __init__(self):
|
||
|
|
self.adapter = GeminiAdapter()
|
||
|
|
self.store = GraphStore()
|
||
|
|
|
||
|
|
def ingest_text(self, text: str):
|
||
|
|
"""Extracts triples from text and adds them to the graph."""
|
||
|
|
prompt = f"""
|
||
|
|
Extract all meaningful entities and their relationships from the following text.
|
||
|
|
Format the output as a JSON list of triples: [{{"s": "subject", "p": "predicate", "o": "object"}}]
|
||
|
|
|
||
|
|
Text:
|
||
|
|
{text}
|
||
|
|
|
||
|
|
Guidelines:
|
||
|
|
- Use clear, concise labels for entities and predicates.
|
||
|
|
- Focus on stable facts and structural relationships.
|
||
|
|
- Predicates should be verbs or descriptive relations (e.g., 'is_a', 'works_at', 'collaborates_with').
|
||
|
|
"""
|
||
|
|
try:
|
||
|
|
result = self.adapter.generate(
|
||
|
|
model="gemini-3.1-pro-preview",
|
||
|
|
prompt=prompt,
|
||
|
|
system_instruction="You are Timmy's Symbolic Extraction Engine. Extract high-fidelity knowledge triples.",
|
||
|
|
response_mime_type="application/json"
|
||
|
|
)
|
||
|
|
|
||
|
|
triples = json.loads(result["text"])
|
||
|
|
if isinstance(triples, list):
|
||
|
|
count = self.store.add_triples(triples)
|
||
|
|
logger.info(f"Ingested {count} new triples into symbolic memory.")
|
||
|
|
return count
|
||
|
|
except Exception as e:
|
||
|
|
logger.error(f"Symbolic ingestion failed: {e}")
|
||
|
|
return 0
|
||
|
|
|
||
|
|
def get_context_for(self, topic: str) -> str:
|
||
|
|
"""Performs a 2-hop graph search to find related context for a topic."""
|
||
|
|
# 1. Find direct relations
|
||
|
|
direct = self.store.query(subject=topic) + self.store.query(object=topic)
|
||
|
|
|
||
|
|
# 2. Find 2nd hop
|
||
|
|
related_entities = set()
|
||
|
|
for t in direct:
|
||
|
|
related_entities.add(t['s'])
|
||
|
|
related_entities.add(t['o'])
|
||
|
|
|
||
|
|
extended = []
|
||
|
|
for entity in related_entities:
|
||
|
|
if entity == topic: continue
|
||
|
|
extended.extend(self.store.query(subject=entity))
|
||
|
|
|
||
|
|
all_triples = direct + extended
|
||
|
|
if not all_triples:
|
||
|
|
return ""
|
||
|
|
|
||
|
|
context = "Symbolic Knowledge Graph Context:\n"
|
||
|
|
for t in all_triples:
|
||
|
|
context += f"- {t['s']} --({t['p']})--> {t['o']}\n"
|
||
|
|
return context
|