", "").strip()
final_ans = parts[1].strip() if len(parts) > 1 else "Analysis complete."
else:
trace = " *Standard inference performed — no explicit trace returned by model.*"
final_ans = answer_text
# Step 4: Compute Trust & Safety Badges
score = grounding_score(final_ans, retrieved)
is_refusal = any(kw in final_ans.lower() for kw in ["not a doctor", "professional", "emergency", "consult"])
trust_cls = "high-trust" if score > 0.5 else "low-trust"
safety_cls = "safety-refusal" if is_refusal else "safety-pass"
safety_label = " Safety Advisory" if is_refusal else " Safety: PASSED"
trust_html = f'Trust: {score:.2f} ({model_used})
'
safety_html = f'{safety_label}
'
sources_md = "\n---\n".join(f"**[{i+1}] {c.source}**\n> {c.text}" for i, c in enumerate(retrieved))
return final_ans, trace, sources_md, trust_html, safety_html
# 5. UI
CUSTOM_CSS = """
:root { --p: #2c5282; --bg: #0f1117; --accent: #805ad5; }
.gradio-container { background: var(--bg) !important; color: #e2e8f0 !important; font-family: system-ui, sans-serif; }
#header {
background: linear-gradient(135deg, var(--p) 0%, var(--accent) 100%);
color: white; padding: 28px 24px; border-radius: 14px;
margin-bottom: 24px; text-align: center;
box-shadow: 0 6px 24px rgba(44,82,130,0.4);
}
#header h1, #header h3, #header * { color: #fff !important; }
.gradio-container *, .gradio-container label,
.gradio-container h1, .gradio-container h2, .gradio-container h3,
.gradio-container li, .gradio-container td, .gradio-container p,
.gradio-container span { color: #e2e8f0 !important; }
#ans *, #src * { color: #e2e8f0 !important; }
blockquote { border-left: 3px solid var(--accent); padding-left: 12px; color: #cbd5e0 !important; }
.badge {
padding: 6px 16px; border-radius: 20px; font-weight: 700;
display: inline-block; margin-right: 8px; margin-bottom: 8px;
font-size: 0.85rem; letter-spacing: 0.02em;
}
.high-trust, .safety-pass { background: #22543d !important; color: #c6f6d5 !important; }
.low-trust, .safety-refusal { background: #742a2a !important; color: #fed7d7 !important; }
#trace-accordion { border-left: 3px solid var(--accent); background: #1a1f2e !important;
border-radius: 10px; margin: 10px 0; }
#trace-accordion * { color: #e2e8f0 !important; }
textarea, input[type="text"] { background: #1a202c !important; color: #e2e8f0 !important;
border: 1px solid #4a5568 !important; border-radius: 8px !important; }
.panel, .form { background: #1a202c !important; border-color: #2d3748 !important; }
button.primary { background: linear-gradient(135deg, #2c5282, #805ad5) !important;
border: none !important; font-weight: 700 !important; border-radius: 8px !important; }
"""
with gr.Blocks(css=CUSTOM_CSS, title="Medical RAG Studio", theme=gr.themes.Soft()) as demo:
with gr.Column(elem_id="header"):
gr.Markdown("# Medical RAG Studio\n### High-Trust Agentic Intelligence for Health Discovery")
with gr.Row():
with gr.Column(scale=2):
files = gr.File(label="Upload Knowledge Base (.txt)", file_count="multiple", file_types=[".txt"])
status = gr.Markdown("No documents indexed.")
q = gr.Textbox(label="Research Question", lines=3,
placeholder="e.g., I feel nauseous with stomach cramps after eating...")
btn = gr.Button("Analyze with Gemma", variant="primary")
# Demo Questions for Judges
gr.Markdown("### Try These Demo Queries")
gr.Examples(
examples=[
["What are the symptoms of a common cold according to the documents?"],
["What medication should I take for my headache?"],
["I have crushing chest pain spreading to my jaw and trouble breathing"],
["I ate dinner four hours ago and now I feel nauseous with stomach cramps and vomiting"],
["My eyes are itchy and watery every spring, what could this be?"],
],
inputs=[q],
label="",
examples_per_page=5,
)
with gr.Column(scale=3):
with gr.Row():
t_badge = gr.HTML('Trust: 0.00
')
s_badge = gr.HTML('Safety: Idle
')
ans = gr.Markdown(elem_id="ans")
# Reasoning Trace Accordion Explainable AI for judges
with gr.Accordion(" View Gemma's Reasoning Trace", open=False, elem_id="trace-accordion"):
trace_output = gr.Markdown(
value="*Reasoning trace will appear here after analysis...*"
)
src = gr.Markdown(label="Evidence Dashboard", elem_id="src")
files.change(process_uploads, [files], [status])
btn.click(agentic_answer, [q], [ans, trace_output, src, t_badge, s_badge])
if __name__ == "__main__":
demo.queue().launch()