garibel / brain_api.py
wamaraga's picture
FIX: working brain (resolve jw_quarantine_filter/garifuna_bench imports — proven bundle layout) + C's reshuffling prompts
827bb9d verified
Raw
History Blame Contribute Delete
3.17 kB
"""GARÍBEL brain API (FastAPI) — wraps the grounded Orchestrator for C's Next UI.
POST /garibel {message, intent?, level?, session_id?} -> {answer, sources, audio?}.
Reuses the EXACT orchestrator/brain/RAG/TTS bundle the Gradio Space proved (foundry + LILA NISAMINA +
full corpus + anti-fabrication + greetings/numbers + mms-tts-cab)."""
import os, sys, base64
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
_BR = os.path.join(os.path.dirname(__file__), "brain")
# Match the proven Gradio bundle layout: modules live at brain/ root; bare imports (jw_quarantine_filter)
# live in 30_lexicon/. Add every dir a bare/package import may resolve from.
for _p in (_BR, os.path.join(_BR,"30_lexicon"), os.path.join(_BR,"99_publish"), os.path.join(_BR,"nisamina_mcp")):
if os.path.isdir(_p) and _p not in sys.path: sys.path.insert(0, _p)
app = FastAPI(title="GARIBEL brain")
_ORCH = None; _SESS = {}
def _orch():
global _ORCH
if _ORCH is None:
from orchestrator import Orchestrator
from brain import load_brain
rm = os.getenv("NISAMINA_REAL_BRAIN", "1") == "1"
b = load_brain(real_mode=rm)
tts = None
if rm:
try:
from tts_garifuna import GarifunaTTS; tts = GarifunaTTS()
except Exception as e:
print("[tts] mock:", e)
_ORCH = Orchestrator(brain=b, tts=tts, audio_enabled=True)
return _ORCH
def _sess(sid):
from orchestrator import SessionState
if sid not in _SESS: _SESS[sid] = SessionState()
return _SESS[sid]
@app.get("/health")
def health(): return {"ok": True}
@app.post("/garibel")
async def garibel(req: Request):
b = await req.json()
msg = (b.get("message") or b.get("text") or "").strip()
if not msg: return JSONResponse({"error": "empty"}, status_code=400)
sid = str(b.get("session_id") or "default")
intent = b.get("intent"); level = b.get("level")
pre = ""
if intent == "translate": pre = "[Just translate, concisely.] "
elif intent == "simpler": pre = "[Explain more simply.] "
elif intent == "sentence": pre = "[Use it in a sentence.] "
if level == "beginner": pre += "[Beginner level.] "
try:
ss = _sess(sid)
resp = _orch().orchestrate(pre + msg, ss)
_SESS[sid] = resp.session_state
srcs = []
if resp.citations:
try:
from nisamina_mcp.source_attribution import cite_record
for rec in resp.citations[:6]:
for c in cite_record(rec, limit=2):
if c not in srcs: srcs.append(c)
except Exception: pass
out = {"answer": resp.text, "sources": srcs[:6], "blocked": resp.blocked_reason}
if resp.audio_garifuna_wav:
out["audio_b64"] = base64.b64encode(resp.audio_garifuna_wav).decode()
out["audio_attribution"] = resp.audio_attribution
out["audio_text"] = resp.audio_synthesized_text
return out
except Exception as e:
import traceback; traceback.print_exc()
return JSONResponse({"error": "brain_error", "detail": str(e)}, status_code=500)