joseph njoroge kariuki
Deploy Senti AI to Hugging Face Spaces
021e065
import os
import torch
import torch.nn as nn
import torch.nn.functional as F
from typing import Dict, Any
class CommunitySaccoClassifier(nn.Module):
def __init__(self, input_dim=10, hidden_dim=24):
super().__init__()
self.net = nn.Sequential(
nn.Linear(input_dim, hidden_dim),
nn.ReLU(),
nn.Linear(hidden_dim, 3) # 3 classes: Stable, Caution, At Risk
)
def forward(self, x):
return self.net(x)
class SentiCommunityEngine:
def __init__(self, weights_path: str):
self.model = CommunitySaccoClassifier()
if os.path.exists(weights_path):
self.model.load_state_dict(torch.load(weights_path, map_location=torch.device('cpu')))
self.model.eval()
def predict(self, text: str) -> Dict[str, Any]:
raw = text.lower()
feat = [
len(raw) / 10000.0,
1.0 if "sacco" in raw else 0.0,
1.0 if "dividend" in raw else 0.0,
1.0 if "microfinance" in raw else 0.0,
1.0 if "literacy" in raw else 0.0,
1.0 if "expenditure" in raw else 0.0,
1.0 if "budget" in raw else 0.0,
1.0 if "swahili" in raw else 0.0,
1.0 if "sheng" in raw else 0.0,
1.0 if "behavioral" in raw else 0.0
]
with torch.no_grad():
x = torch.tensor([feat], dtype=torch.float32)
logits = self.model(x)
probs = F.softmax(logits, dim=1).numpy()[0]
pred_class = int(logits.argmax(dim=1).item())
health_states = ["Stable / Liquid", "Caution / Review dividend payouts", "At Risk / High NPLs"]
nudge = "Weka akiba leo kwa maisha bora ya baadaye."
if pred_class == 2:
nudge = "Chunga mfuko wako! Punguza madeni na ongeza hisa zako katika SACCO."
elif pred_class == 1:
nudge = "Tenga bajeti vizuri ili uweze kulipa mkopo wako bila shida."
return {
"sacco_health_status": health_states[pred_class],
"nudge_message": nudge,
"confidence": float(probs[pred_class]),
"framework": "SASRA Sacco Regulations & Financial Literacy Guidelines"
}
# ── RLM Integration ──────────────────────────────────────────────
class SentiCommunityRLM:
"""
SentiCommunityRLM wraps the shared RLMEngine to provide deep reasoning capabilities
using a dedicated Ollama specialist model (senti-community-rlm).
"""
def __init__(self, model_name: str = "senti-community-rlm"):
import sys
import os
base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
if base_dir not in sys.path:
sys.path.insert(0, base_dir)
from senti.core.engines.superpacks.rlm_engine import RLMEngine
self.engine = RLMEngine(model=model_name)
async def predict_deep(self, text: str, tier: str = "C") -> dict:
import time
context = {
"tier": tier,
"domain": "senticommunity",
"timestamp": time.time(),
}
system_suffix = (
"Focus on SACCO dividend planning, public budget expenditure explainers, financial literacy teaching, and Sheng/Swahili cognitive behavioral spend nudges."
)
rlm_response = await self.engine.reason(
query=text,
context=context,
system_suffix=system_suffix
)
res = rlm_response.to_dict()
# Map RLM decision to legacy SML fields for backward compatibility
decision = res.get("decision", "stable").lower()
health_status = "Stable / Liquid"
nudge = "Weka akiba leo kwa maisha bora ya baadaye."
if any(w in decision for w in ["risk", "poor", "insolvent", "alert"]):
health_status = "At Risk / High NPLs"
nudge = "Chunga mfuko wako! Punguza madeni na ongeza hisa zako katika SACCO."
elif any(w in decision for w in ["caution", "review", "moderate"]):
health_status = "Caution / Review dividend payouts"
nudge = "Tenga bajeti vizuri ili uweze kulipa mkopo wako bila shida."
res["sacco_health_status"] = health_status
res["nudge_message"] = nudge if "swahili" in res.get("justification", "").lower() or "sheng" in res.get("justification", "").lower() else res.get("justification", nudge)
res["confidence"] = res.get("confidence", 0.5)
res["framework"] = "SASRA Sacco Regulations & Financial Literacy Guidelines"
return res