|
|
|
|
|
from __future__ import annotations |
|
|
|
|
|
from typing import Dict, List |
|
|
|
|
|
import streamlit as st |
|
|
|
|
|
|
|
|
def _render_popover_for_item( |
|
|
label: str, |
|
|
ref_nums: List[int], |
|
|
registry: List[Dict[str, object]], |
|
|
) -> None: |
|
|
if not ref_nums: |
|
|
return |
|
|
with st.expander(label, expanded=False): |
|
|
for n in ref_nums: |
|
|
rec = next((r for r in registry if int(r.get("n", r.get("rank", -1))) == int(n)), None) |
|
|
if not rec: |
|
|
continue |
|
|
title = f"[{n}] {rec.get('doc_name','')} β p.{rec.get('page',0)} | score {float(rec.get('score',0.0)):.3f}" |
|
|
st.markdown(f"**{title}**") |
|
|
st.write(rec.get("text", "")) |
|
|
if rec.get("source_path"): |
|
|
st.caption(rec["source_path"]) |
|
|
|
|
|
|
|
|
def _bullets_html(items: List[str]) -> str: |
|
|
if not items: |
|
|
return "_(none)_" |
|
|
return "\n".join([f"- {s}" for s in items]) |
|
|
|
|
|
|
|
|
def build_panel_data(result: Dict[str, object]) -> Dict[str, object]: |
|
|
meta = result.get("meta", {}) if isinstance(result, dict) else {} |
|
|
annotated = meta.get("annotated", {}) if isinstance(meta, dict) else {} |
|
|
claim_mapping = meta.get("claim_mapping", {}) if isinstance(meta, dict) else {} |
|
|
|
|
|
assess_html = annotated.get("assessment_html", []) if isinstance(annotated, dict) else [] |
|
|
plan_html = annotated.get("plan_html", []) if isinstance(annotated, dict) else [] |
|
|
|
|
|
assess_map_items = claim_mapping.get("assessment", {}).get("items", []) if isinstance(claim_mapping, dict) else [] |
|
|
plan_map_items = claim_mapping.get("plan", {}).get("items", []) if isinstance(claim_mapping, dict) else [] |
|
|
|
|
|
return { |
|
|
"assessment_html": assess_html, |
|
|
"plan_html": plan_html, |
|
|
"assessment_map": assess_map_items, |
|
|
"plan_map": plan_map_items, |
|
|
"citations": result.get("citations", []), |
|
|
"timings": meta.get("timings", {}), |
|
|
"map_mode": meta.get("map_mode", "production"), |
|
|
"registry_cap": meta.get("registry_cap", None), |
|
|
"nl_explanation": meta.get("nl_explanation", ""), |
|
|
} |
|
|
|
|
|
|
|
|
def render_reasoning_panel(panel_data: Dict[str, object]) -> None: |
|
|
st.subheader("Reasoning & Evidence") |
|
|
|
|
|
timings = panel_data.get("timings", {}) |
|
|
map_mode = panel_data.get("map_mode", "production") |
|
|
cap = panel_data.get("registry_cap", None) |
|
|
st.caption(f"Evidence mode: **{map_mode}**" + (f" | registry cap: {cap}" if cap else "")) |
|
|
|
|
|
|
|
|
expl = (panel_data.get("nl_explanation", "") or "").strip() |
|
|
if expl: |
|
|
with st.expander("π§© Explain My Reasoning", expanded=False): |
|
|
st.write(expl) |
|
|
|
|
|
registry = panel_data.get("citations", []) |
|
|
|
|
|
col1, col2 = st.columns(2) |
|
|
with col1: |
|
|
st.markdown("**Assessment (annotated)**") |
|
|
st.markdown(_bullets_html(panel_data.get("assessment_html", [])), unsafe_allow_html=True) |
|
|
for i, it in enumerate(panel_data.get("assessment_map", []), start=1): |
|
|
_render_popover_for_item(f"[?] Evidence for Assessment #{i}", it.get("ref_nums", []), registry) |
|
|
|
|
|
with col2: |
|
|
st.markdown("**Plan (annotated)**") |
|
|
st.markdown(_bullets_html(panel_data.get("plan_html", [])), unsafe_allow_html=True) |
|
|
for i, it in enumerate(panel_data.get("plan_map", []), start=1): |
|
|
_render_popover_for_item(f"[?] Evidence for Plan #{i}", it.get("ref_nums", []), registry) |
|
|
|
|
|
st.markdown("---") |
|
|
st.markdown("**Evidence Registry** (global refs)") |
|
|
if not registry: |
|
|
st.caption("No evidence available. Build the FAISS index in Step 1 to enable mapping.") |
|
|
return |
|
|
|
|
|
for r in registry: |
|
|
with st.container(border=True): |
|
|
n = r.get("n", r.get("rank", "?")) |
|
|
doc = r.get("doc_name", "") |
|
|
page = r.get("page", 0) |
|
|
score = r.get("score", r.get("score_max", 0.0)) |
|
|
st.write(f"**[{n}] {doc}** β page {page} | score: {float(score):.3f}") |
|
|
st.write(r.get("text", "")) |
|
|
sp = r.get("source_path", "") |
|
|
if sp: |
|
|
st.caption(sp) |
|
|
|
|
|
if isinstance(timings, dict): |
|
|
st.caption(f"Timings: {timings}") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|