themis / streamlit_application.py
vg15o2's picture
Moonley backend (HF Space build)
1d9bd9b
Raw
History Blame Contribute Delete
5.98 kB
import streamlit as st
import sys
import os
# Ensure the app can find the local modules
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]
# Initialize chat history
if "messages" not in st.session_state:
st.session_state.messages = []
# Display chat messages from history on app rerun
for message in st.session_state.messages:
if message["role"] != "system":
with st.chat_message(message["role"]):
st.markdown(message["content"])
# React to user input
if prompt := st.chat_input("Ask a legal question... (e.g. 'What is the law on murder under BNS 103?')"):
# Display user message in chat message container
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:
# The prompt is added to history after, so we pass history up to this point
result = ask(prompt, st.session_state.messages, force_intent=force_intent)
# Clear status text
status_text.empty()
# Display the main answer (which uses the markdown table format you requested)
st.markdown(result.get("answer", "No answer generated."))
# Add an expander for the "behind-the-scenes" metadata
with st.expander("πŸ” Retrieval & Verification Details", expanded=True):
# Route, Intent & Speed
st.caption(
f"**Intent:** {result.get('intent', 'LEGAL_RESEARCH')} | **Route Taken:** {result.get('route')} | **Speed:** {result.get('elapsed_seconds')}s")
st.divider()
# Verification Block
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()
# Evidence Block
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."}
# Add user message and assistant message to chat history
st.session_state.messages.append({"role": "user", "content": prompt})
st.session_state.messages.append({"role": "assistant", "content": result.get("answer", "")})