| """ |
| FRANKENSTEIN HANDS β Sovereign Knowledge Retrieval Sidecar |
| Port 5433 |
| |
| Pipeline: |
| query |
| β spaCy + NLTK (NLP parse: entities, POS, intent, key concepts) |
| β FAISS (vector similarity β top-K corpus chunks) |
| β Neo4j (graph traversal β expand related nodes) |
| β RDF / rdflib (semantic triples for extracted entities) |
| β NetworkX (rank by PageRank / betweenness centrality) |
| β tagged context β Frankenstein Brain |
| |
| Each layer degrades gracefully if its backend is offline. |
| Every retrieval is WORM-tagged with source metadata. |
| |
| SnapKitty Collective 2026 Β· Apache 2.0 Β· Evidence or Silence |
| """ |
|
|
| import hashlib, json, os, time |
| from datetime import datetime |
| from typing import Optional |
| from fastapi import FastAPI |
| from pydantic import BaseModel |
|
|
| |
| try: |
| import spacy |
| nlp = spacy.load("en_core_web_sm") |
| SPACY_OK = True |
| except Exception: |
| SPACY_OK = False |
|
|
| try: |
| import nltk |
| from nltk.corpus import wordnet, stopwords |
| from nltk.tokenize import word_tokenize |
| nltk.download("punkt", quiet=True) |
| nltk.download("wordnet", quiet=True) |
| nltk.download("stopwords", quiet=True) |
| nltk.download("averaged_perceptron_tagger", quiet=True) |
| NLTK_OK = True |
| STOPS = set(stopwords.words("english")) |
| except Exception: |
| NLTK_OK = False |
| STOPS = set() |
|
|
| try: |
| import faiss |
| import numpy as np |
| FAISS_OK = True |
| except Exception: |
| FAISS_OK = False |
|
|
| try: |
| from neo4j import GraphDatabase |
| NEO4J_URI = os.getenv("NEO4J_URI", "bolt://localhost:7687") |
| NEO4J_USER = os.getenv("NEO4J_USER", "neo4j") |
| NEO4J_PASS = os.getenv("NEO4J_PASS", "sovereign") |
| neo4j_driver = GraphDatabase.driver(NEO4J_URI, auth=(NEO4J_USER, NEO4J_PASS)) |
| NEO4J_OK = True |
| except Exception: |
| NEO4J_OK = False |
|
|
| try: |
| from rdflib import Graph as RDFGraph, URIRef, Literal, Namespace |
| from rdflib.namespace import RDF, RDFS, OWL |
| rdf_g = RDFGraph() |
| SKC = Namespace("https://snapkitty.io/ontology#") |
| rdf_g.bind("skc", SKC) |
| RDF_OK = True |
| except Exception: |
| RDF_OK = False |
|
|
| try: |
| import networkx as nx |
| NETX_OK = True |
| except Exception: |
| NETX_OK = False |
|
|
| try: |
| from sentence_transformers import SentenceTransformer |
| embed_model = SentenceTransformer("all-MiniLM-L6-v2") |
| EMBED_OK = True |
| except Exception: |
| EMBED_OK = False |
|
|
| |
| faiss_index = None |
| faiss_texts: list[str] = [] |
| faiss_meta: list[dict] = [] |
|
|
| |
| nx_graph = nx.DiGraph() if NETX_OK else None |
|
|
| |
| worm_prev = "HANDS_GENESIS" |
| worm_count = 0 |
|
|
| def worm_seal(event: str) -> str: |
| global worm_prev, worm_count |
| msg = f"{worm_prev}|{event}|{int(time.time()*1000)}" |
| h = hashlib.sha256(msg.encode()).hexdigest() |
| worm_prev = h |
| worm_count += 1 |
| return h[:16] |
|
|
| |
| app = FastAPI(title="FRANKENSTEIN HANDS", version="1.0.0") |
|
|
| class RetrieveRequest(BaseModel): |
| query: str |
| k: int = 5 |
|
|
| class IndexRequest(BaseModel): |
| texts: list[str] |
| metas: list[dict] = [] |
|
|
| class NeoIngestRequest(BaseModel): |
| nodes: list[dict] |
| edges: list[dict] |
|
|
| |
| def nlp_parse(query: str) -> dict: |
| result = {"entities": [], "concepts": [], "pos_tags": [], "wordnet": [], "intent": "query"} |
|
|
| if SPACY_OK: |
| doc = nlp(query) |
| result["entities"] = [ |
| {"text": ent.text, "label": ent.label_, "start": ent.start_char, "end": ent.end_char} |
| for ent in doc.ents |
| ] |
| result["concepts"] = [ |
| tok.lemma_ for tok in doc |
| if tok.pos_ in ("NOUN", "VERB", "PROPN") and not tok.is_stop and len(tok.text) > 2 |
| ] |
| result["pos_tags"] = [{"text": tok.text, "pos": tok.pos_} for tok in doc] |
|
|
| |
| for tok in doc: |
| if tok.dep_ == "ROOT": |
| if tok.pos_ == "VERB": |
| result["intent"] = tok.lemma_ |
| break |
|
|
| if NLTK_OK: |
| tokens = word_tokenize(query) |
| content = [t for t in tokens if t.lower() not in STOPS and t.isalpha()] |
| result["nltk_tokens"] = content |
|
|
| |
| wn_hits = [] |
| for word in content[:4]: |
| syns = wordnet.synsets(word) |
| if syns: |
| wn_hits.append({ |
| "word": word, |
| "definition": syns[0].definition(), |
| "examples": syns[0].examples()[:1], |
| "hypernyms": [h.name() for h in syns[0].hypernyms()[:2]], |
| }) |
| result["wordnet"] = wn_hits |
|
|
| return result |
|
|
| |
| def faiss_retrieve(query: str, k: int) -> list[dict]: |
| if not FAISS_OK or not EMBED_OK or faiss_index is None: |
| return [{"text": "FAISS_OFFLINE β no index loaded", "score": 0.0, "meta": {}}] |
|
|
| vec = embed_model.encode([query], normalize_embeddings=True).astype("float32") |
| scores, idxs = faiss_index.search(vec, min(k, len(faiss_texts))) |
| return [ |
| { |
| "text": faiss_texts[i], |
| "score": float(scores[0][n]), |
| "meta": faiss_meta[i] if i < len(faiss_meta) else {}, |
| } |
| for n, i in enumerate(idxs[0]) if i >= 0 |
| ] |
|
|
| |
| def neo4j_expand(concepts: list[str], k: int) -> list[dict]: |
| if not NEO4J_OK or not concepts: |
| return [{"node": "NEO4J_OFFLINE", "rels": []}] |
| try: |
| with neo4j_driver.session() as s: |
| results = [] |
| for concept in concepts[:3]: |
| q = ( |
| "MATCH (n)-[r]->(m) " |
| "WHERE toLower(n.name) CONTAINS toLower($c) " |
| "RETURN n.name AS src, type(r) AS rel, m.name AS tgt, m.description AS desc " |
| "LIMIT $k" |
| ) |
| rows = s.run(q, c=concept, k=k).data() |
| results.extend([{ |
| "node": r["src"], "rel": r["rel"], |
| "target": r["tgt"], "desc": r.get("desc","") |
| } for r in rows]) |
| return results or [{"node": "NO_MATCH", "concept": concepts}] |
| except Exception as e: |
| return [{"node": f"NEO4J_ERR: {e}"}] |
|
|
| |
| def rdf_triples(entities: list[str]) -> list[dict]: |
| if not RDF_OK or not entities: |
| return [] |
| results = [] |
| for ent in entities[:4]: |
| subj = URIRef(f"https://snapkitty.io/ontology#{ent.replace(' ','_')}") |
| for _, pred, obj in rdf_g.triples((subj, None, None)): |
| results.append({"subject": ent, "predicate": str(pred), "object": str(obj)}) |
| return results or [{"rdf": "NO_TRIPLES_YET β load an ontology via /ingest/rdf"}] |
|
|
| |
| def netx_rank(faiss_hits: list[dict], neo4j_hits: list[dict]) -> list[dict]: |
| if not NETX_OK: |
| return faiss_hits |
|
|
| |
| G = nx.DiGraph() |
| for h in faiss_hits: |
| G.add_node(h["text"][:64], score=h["score"], type="corpus") |
| for h in neo4j_hits: |
| src = h.get("node","?") |
| tgt = h.get("target","?") |
| if src and tgt and src != "NEO4J_OFFLINE": |
| G.add_edge(src, tgt, rel=h.get("rel","RELATED")) |
|
|
| if len(G.nodes) == 0: |
| return faiss_hits |
|
|
| try: |
| pr = nx.pagerank(G, alpha=0.85) |
| except Exception: |
| pr = {} |
|
|
| ranked = sorted(faiss_hits, key=lambda h: pr.get(h["text"][:64], h["score"]), reverse=True) |
| return ranked |
|
|
| |
| import asyncio |
| from concurrent.futures import ThreadPoolExecutor |
|
|
| _pool = ThreadPoolExecutor(max_workers=8, thread_name_prefix="hands") |
|
|
| async def _run(fn, *args): |
| loop = asyncio.get_running_loop() |
| return await loop.run_in_executor(_pool, fn, *args) |
|
|
| async def _safe(label: str, coro): |
| """Run a coroutine with error isolation β never lets one layer kill the rest.""" |
| try: |
| return label, await coro |
| except asyncio.TimeoutError: |
| return label, {"error": f"{label}_TIMEOUT"} |
| except Exception as e: |
| return label, {"error": f"{label}_ERR: {type(e).__name__}: {e}"} |
|
|
| |
| @app.post("/retrieve") |
| async def retrieve(req: RetrieveRequest): |
| t0 = time.time() |
|
|
| |
| parse = await _run(nlp_parse, req.query) |
| concepts = parse.get("concepts", []) |
| ent_texts = [e["text"] for e in parse.get("entities", [])] |
|
|
| |
| |
| layer_results = {} |
|
|
| async def _faiss(): |
| return await asyncio.wait_for(_run(faiss_retrieve, req.query, req.k), timeout=5.0) |
|
|
| async def _neo4j(): |
| return await asyncio.wait_for(_run(neo4j_expand, concepts, req.k), timeout=8.0) |
|
|
| async def _rdf(): |
| return await asyncio.wait_for(_run(rdf_triples, ent_texts), timeout=3.0) |
|
|
| |
| faiss_r, neo4j_r, rdf_r = await asyncio.gather( |
| _faiss(), _neo4j(), _rdf(), |
| return_exceptions=True |
| ) |
|
|
| |
| def safe_result(r, default): |
| if isinstance(r, Exception): |
| return [{"error": f"{type(r).__name__}: {r}"}] |
| return r if r else default |
|
|
| chunks = safe_result(faiss_r, [{"text": "FAISS_OFFLINE", "score": 0, "meta": {}}]) |
| neo4j = safe_result(neo4j_r, [{"node": "NEO4J_OFFLINE"}]) |
| triples = safe_result(rdf_r, []) |
|
|
| |
| ranked = await _run(netx_rank, chunks, neo4j) |
|
|
| |
| seal = worm_seal(f"RETRIEVE|{req.query[:32]}") |
|
|
| |
| context_lines = [] |
| for i, r in enumerate(ranked[:req.k]): |
| text = r.get("text","") |
| if text and not text.startswith("FAISS_OFFLINE"): |
| context_lines.append(f"[{i+1}] (score={r.get('score',0):.3f}) {text}") |
| for g in neo4j[:3]: |
| if "node" in g and g["node"] not in ("NEO4J_OFFLINE","NO_MATCH"): |
| context_lines.append(f"[GRAPH] {g.get('node','')} --{g.get('rel','')}β {g.get('target','')}: {g.get('desc','')}") |
| for t in triples[:2]: |
| context_lines.append(f"[RDF] {t.get('subject','')} {t.get('predicate','').split('#')[-1]} {t.get('object','')}") |
|
|
| results = [{"text": r["text"], "score": r.get("score",0), "meta": r.get("meta",{})} for r in ranked] |
|
|
| return { |
| "query": req.query, |
| "results": results, |
| "context": "\n".join(context_lines) if context_lines else "NO_CONTEXT", |
| "nlp": parse, |
| "graph": neo4j[:5], |
| "rdf": triples[:5], |
| "layers": { |
| "spacy": SPACY_OK, |
| "nltk": NLTK_OK, |
| "faiss": FAISS_OK and faiss_index is not None, |
| "neo4j": NEO4J_OK, |
| "rdf": RDF_OK, |
| "networkx": NETX_OK, |
| "embed": EMBED_OK, |
| }, |
| "worm": seal, |
| "ms": round((time.time() - t0) * 1000, 1), |
| } |
|
|
| |
| @app.post("/index") |
| async def index_corpus(req: IndexRequest): |
| global faiss_index, faiss_texts, faiss_meta |
| if not FAISS_OK or not EMBED_OK: |
| return {"error": "FAISS or sentence-transformers not installed"} |
|
|
| vecs = embed_model.encode(req.texts, normalize_embeddings=True).astype("float32") |
| dim = vecs.shape[1] |
| faiss_index = faiss.IndexFlatIP(dim) |
| faiss_index.add(vecs) |
| faiss_texts = req.texts |
| faiss_meta = req.metas or [{} for _ in req.texts] |
|
|
| seal = worm_seal(f"INDEX|{len(req.texts)}_docs") |
| return {"indexed": len(req.texts), "dim": dim, "worm": seal} |
|
|
| |
| @app.post("/ingest/rdf") |
| async def ingest_rdf(payload: dict): |
| if not RDF_OK: |
| return {"error": "rdflib not installed"} |
| triples_added = 0 |
| for triple in payload.get("triples", []): |
| s = URIRef(triple["subject"]) |
| p = URIRef(triple["predicate"]) |
| o = Literal(triple["object"]) if triple.get("literal") else URIRef(triple["object"]) |
| rdf_g.add((s, p, o)) |
| triples_added += 1 |
| return {"added": triples_added, "total": len(rdf_g)} |
|
|
| |
| @app.post("/ingest/graph") |
| async def ingest_graph(req: NeoIngestRequest): |
| results = {"neo4j": "offline", "networkx": 0} |
| if NEO4J_OK: |
| try: |
| with neo4j_driver.session() as s: |
| for node in req.nodes: |
| s.run( |
| "MERGE (n:Entity {id: $id}) SET n.name=$name, n += $props", |
| id=node["id"], name=node.get("label",""), props=node.get("props",{}) |
| ) |
| for edge in req.edges: |
| s.run( |
| f"MATCH (a:Entity {{id:$f}}),(b:Entity {{id:$t}}) MERGE (a)-[:{edge['rel']}]->(b)", |
| f=edge["from"], t=edge["to"] |
| ) |
| results["neo4j"] = f"ok β {len(req.nodes)} nodes, {len(req.edges)} edges" |
| except Exception as e: |
| results["neo4j"] = f"error: {e}" |
|
|
| if NETX_OK: |
| for node in req.nodes: |
| nx_graph.add_node(node["id"], **node.get("props",{})) |
| for edge in req.edges: |
| nx_graph.add_edge(edge["from"], edge["to"], rel=edge["rel"]) |
| results["networkx"] = nx_graph.number_of_nodes() |
|
|
| return results |
|
|
| |
| @app.get("/health") |
| async def health(): |
| return { |
| "ok": True, |
| "service": "frankenstein-hands", |
| "version": "1.0.0", |
| "worm_seals": worm_count, |
| "layers": { |
| "spacy": SPACY_OK, |
| "nltk": NLTK_OK, |
| "faiss": FAISS_OK, |
| "neo4j": NEO4J_OK, |
| "rdf": RDF_OK, |
| "networkx": NETX_OK, |
| "embed": EMBED_OK, |
| "index_loaded": faiss_index is not None, |
| } |
| } |
|
|
| if __name__ == "__main__": |
| import uvicorn |
| print("⬑ FRANKENSTEIN HANDS β http://localhost:5433") |
| print(" FAISS + Neo4j + RDF + NetworkX + spaCy + NLTK") |
| uvicorn.run(app, host="0.0.0.0", port=5433) |
|
|