| import streamlit as st |
| import sys |
| import os |
|
|
| |
| BASE_DIR = os.path.dirname(os.path.abspath(__file__)) |
| if BASE_DIR not in sys.path: |
| sys.path.insert(0, BASE_DIR) |
|
|
| from unified_legal_rag import ask |
|
|
| st.set_page_config( |
| page_title="LegalAIapex", |
| page_icon="βοΈ", |
| layout="wide" |
| ) |
|
|
| st.title("βοΈ LegalAIapex: Unified Statute + Judgment RAG") |
| st.markdown(""" |
| Welcome to the Unified Legal RAG system. This system dynamically routes your query to **Statutes** (IPC, BNS, CrPC, BNSS, IEA, BSA) and **Supreme Court Judgments**. It features a dual-layer verification system to ensure zero hallucinations. |
| """) |
|
|
| with st.sidebar: |
| st.header("βοΈ Settings") |
| intent_mode = st.selectbox( |
| "Response Format", |
| options=[ |
| "βοΈ General Legal Research (Default)", |
| "β¨ Auto-Detect Format (AI decides)", |
| "π Analyze My Story (Legal Advice)", |
| "π Brief Case/Statute Summary", |
| "π In-Depth Case Study", |
| "π Compare Laws/Cases" |
| ], |
| index=0, |
| help="Choose the structure of the answer. By default, it provides a clean Citation Table." |
| ) |
|
|
| INTENT_MAP = { |
| "βοΈ General Legal Research (Default)": "LEGAL_RESEARCH", |
| "β¨ Auto-Detect Format (AI decides)": "AUTO", |
| "π Analyze My Story (Legal Advice)": "STORY_EVALUATION", |
| "π Brief Case/Statute Summary": "CASE_SUMMARY", |
| "π In-Depth Case Study": "COMPREHENSIVE_CASE_STUDY", |
| "π Compare Laws/Cases": "CASE_COMPARISON" |
| } |
| force_intent = INTENT_MAP[intent_mode] |
|
|
| |
| if "messages" not in st.session_state: |
| st.session_state.messages = [] |
|
|
| |
| for message in st.session_state.messages: |
| if message["role"] != "system": |
| with st.chat_message(message["role"]): |
| st.markdown(message["content"]) |
|
|
| |
| if prompt := st.chat_input("Ask a legal question... (e.g. 'What is the law on murder under BNS 103?')"): |
| |
| st.chat_message("user").markdown(prompt) |
|
|
| with st.chat_message("assistant"): |
| status_text = st.empty() |
| status_text.text("Retrieving legal evidence and generating response...") |
|
|
| with st.spinner("Searching the legal database..."): |
| try: |
| |
| result = ask(prompt, st.session_state.messages, force_intent=force_intent) |
|
|
| |
| status_text.empty() |
|
|
| |
| st.markdown(result.get("answer", "No answer generated.")) |
|
|
| |
| with st.expander("π Retrieval & Verification Details", expanded=True): |
| |
| st.caption( |
| f"**Intent:** {result.get('intent', 'LEGAL_RESEARCH')} | **Route Taken:** {result.get('route')} | **Speed:** {result.get('elapsed_seconds')}s") |
|
|
| st.divider() |
|
|
| |
| v = result.get("verification", {}) |
| if v: |
| grounded = v.get("grounded", None) |
| if grounded: |
| st.success("β
**FULLY GROUNDED:** All citations perfectly match retrieved evidence.") |
| else: |
| st.warning( |
| "β οΈ **HALLUCINATED CITATIONS DETECTED:** The LLM cited sections/cases not found anywhere in the local database.") |
|
|
| if v.get("unverified_sections"): |
| st.write(f"π **Hallucinated Sections (NOT in DB):** {', '.join(v['unverified_sections'])}") |
| if v.get("retrieval_miss_sections"): |
| st.info( |
| f"π **Retrieval Miss (in DB, not retrieved this query):** {', '.join(v['retrieval_miss_sections'])} β These sections exist in the database but were not surfaced by the search engine for this query. The LLM cited them from its training memory.") |
| if v.get("citations_confirmed_via_live_lookup"): |
| st.info( |
| f"π’ **Confirmed via Bharat-Courts (Live):** {', '.join(v['citations_confirmed_via_live_lookup'])}") |
| if v.get("citations_likely_fabricated"): |
| st.error(f"β **Likely Fabricated:** {', '.join(v['citations_likely_fabricated'])}") |
| if v.get("citations_could_not_verify"): |
| st.write(f"β **Could not verify:** {', '.join(v['citations_could_not_verify'])}") |
|
|
| st.divider() |
|
|
| |
| st.write("**Top Evidence Used for Context:**") |
| evidence_list = result.get("evidence", []) |
| if evidence_list: |
| for ev in evidence_list: |
| type_icon = "π" if ev['type'] == 'statute' else "ποΈ" |
| st.write(f"{type_icon} `[{ev['type']}]` **Score:** {ev['score']:+.3f} β {ev['label']}") |
| else: |
| st.write("No evidence retrieved.") |
|
|
| except Exception as e: |
| status_text.empty() |
| st.error(f"An error occurred: {str(e)}") |
| result = {"answer": "Error generating response."} |
|
|
| |
| st.session_state.messages.append({"role": "user", "content": prompt}) |
| st.session_state.messages.append({"role": "assistant", "content": result.get("answer", "")}) |
|
|