File size: 5,976 Bytes
1d9bd9b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | 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", "")})
|