from backend.database.postgres.db import SessionLocal from backend.database.postgres.models import User, Transaction, FinancialProfile, UserConsent, Invoice from layers.layer_1_data.dag_adapter import dag_adapter from layers.layer_1_data.vector_store import SentiVectorStore, SentiEmbeddingFunction from core.market_profiles import get_market_profile from core.legal_intelligence import legal_intelligence import hashlib vector_store = SentiVectorStore() _embedding_fn = SentiEmbeddingFunction() async def get_full_context(user_address: str, country_code: str, db): user_hash = hashlib.sha256(user_address.encode()).hexdigest()[:32] # 1. Market Profile market = get_market_profile(country_code) # 2. Ledger Transactions transactions = dag_adapter.fetch_live_ledger(user_address, days_window=30, max_transactions=500) # 3. User Info user = db.query(User).filter(User.phone_hash == user_hash).first() # 4. Financial Profile profile = db.query(FinancialProfile).filter(FinancialProfile.user_id == user_address).first() # 5. Language Detection (simple heuristic for now) language = "en" if user and user.language_preference: language = user.language_preference return { "user_address": user_address, "user_hash": user_hash, "country_code": country_code, "market": market, "transactions": transactions, "profile": profile, "language": language } async def get_transactions(user_hash: str, db, days: int = 30): return dag_adapter.fetch_live_ledger(user_hash, days_window=days, max_transactions=500) async def get_profile(user_hash: str, transactions, db): profile = db.query(FinancialProfile).filter(FinancialProfile.user_id == user_hash).first() return profile def search_knowledge(query: str, domain: str, language: str, n_results: int = 3): collection_name = "legal_knowledge" if domain in ["TAXATION", "LENDING", "COMPLIANCE"] else "financial_knowledge" try: coll = vector_store.client.get_collection( name=collection_name, embedding_function=_embedding_fn ) res = coll.query( query_texts=[query], n_results=n_results, include=['documents', 'distances', 'metadatas'] ) if res and res.get('documents') and len(res['documents'][0]) > 0: docs = res['documents'][0] distances = res['distances'][0] metas = res['metadatas'][0] if res.get('metadatas') else [{}] * len(docs) return [{"text": doc, "score": 1.0 - dist, "source": meta.get('source', 'unknown')} for doc, dist, meta in zip(docs, distances, metas) if (1.0 - dist) > 0.35] except Exception: pass return [] def get_legal_rules(jurisdiction: str, domain: str): return legal_intelligence.get_rules(jurisdiction, domain)