import streamlit as st
from core import audit
from core.config import BIDDER_NAMES
from ui.components import stat_card
def render() -> None:
# Hero — intentional dark gradient, works as a visual anchor in both modes
st.markdown(
"""
CRPF Hackathon · Theme 3
⚖️ TenderIQ
Explainable AI for Government Tender Evaluation — automated eligibility
assessment with criterion-level evidence, three-tier OCR, and a complete
compliance audit trail.
""",
unsafe_allow_html=True,
)
# KPIs
criteria_count = len(st.session_state.get("criteria") or [])
verdicts = st.session_state.get("verdicts", {})
checked = sum(1 for bv in verdicts.values() for _ in bv)
audit_count = len(audit.query())
c1, c2, c3, c4 = st.columns(4)
with c1: stat_card(criteria_count, "Criteria Extracted", "#3B82F6")
with c2: stat_card(len(verdicts), "Bidders Evaluated", "#22C55E")
with c3: stat_card(checked, "Criteria Checked", "#8B5CF6")
with c4: stat_card(audit_count, "Audit Entries", "#F59E0B")
st.divider()
# Pipeline stages
st.markdown(
''
'How it works
',
unsafe_allow_html=True,
)
stages = [
("#3B82F6", "rgba(37,99,235,0.08)", "1", "Extract Criteria",
"DeepSeek reads the tender PDF and returns structured JSON for each criterion — "
"category, mandatory flag, rule, source clause, and query hints."),
("#8B5CF6", "rgba(124,58,237,0.08)", "2", "Three-Tier OCR",
"📄 PyMuPDF for typed PDFs · 🔍 Tesseract for scans · 👁 DeepSeek Vision LLM "
"when Tesseract confidence < 65%. Every page records its tier and confidence."),
("#22C55E", "rgba(34,197,94,0.08)", "3", "Evaluate per Criterion",
"Semantic search retrieves the top-k evidence chunks. DeepSeek returns a verdict "
"with combined confidence. Safety rule: borderline not-eligible is always "
"downgraded to needs-review."),
("#F59E0B", "rgba(245,158,11,0.08)", "4", "Human Review & Audit",
"Flagged verdicts surface with full evidence and source citations. Every action "
"is logged to SQLite with timestamp, model version, actor, and payload."),
]
cols = st.columns(4)
for col, (accent, bg, num, title, body) in zip(cols, stages):
with col:
st.markdown(
f"""""",
unsafe_allow_html=True,
)
st.divider()
col1, col2 = st.columns(2)
with col1:
with st.container(border=True):
st.markdown("**🚀 Pre-computed Demo**")
st.caption("Instantly load realistic results for all 3 bidders — no API key needed.")
if st.button("Load Pre-computed Demo", type="primary", use_container_width=True):
from core.fallback import load_criteria as lc, load_evaluation
criteria = lc()
st.session_state["criteria"] = [c.model_dump() for c in criteria]
vd: dict = {}
for bid in BIDDER_NAMES:
vd[bid] = [load_evaluation(bid, c.id).model_dump() for c in criteria]
st.session_state["verdicts"] = vd
st.success("Loaded — navigate to Bidder Evaluation or Interpretability.")
st.rerun()
with col2:
with st.container(border=True):
st.markdown("**⚡ Live Pipeline**")
st.caption("Set DEEPSEEK_API_KEY in .env, then use the Tender Analysis tab.")
st.info("Sidebar shows 🟢 when the API is reachable.")