import streamlit as st from rag_pipeline import chunk_text, build_index, retrieve, generate_answer from evaluator import evaluate st.set_page_config( page_title="RAG Evaluator", page_icon="🔍", layout="wide", ) st.markdown(""" """, unsafe_allow_html=True) st.title("🔍 RAG Evaluator") st.markdown( "Paste any document and ask a question. " "Get an AI-generated answer with **live quality scores** — " "faithfulness, relevance, groundedness, and completeness." ) st.markdown("---") with st.sidebar: st.header("⚙️ Configuration") api_key = st.text_input( "OpenAI API Key", type="password", help="Your key is never stored. Used only for this session.", ) st.markdown("---") st.markdown("**About this tool**") st.markdown( "Built by [Faraz Mubeen Haider](https://linkedin.com/in/farazmubeen) " "to demonstrate production RAG evaluation techniques." ) st.markdown("[GitHub](https://github.com/Faraz6180) | " "[LinkedIn](https://linkedin.com/in/farazmubeen)") col1, col2 = st.columns([1, 1], gap="large") with col1: st.subheader("📄 Document") document = st.text_area( "Paste your document here", height=300, placeholder="Paste any text document — a report, article, policy, or knowledge base excerpt...", ) st.subheader("❓ Question") query = st.text_input( "Ask a question about the document", placeholder="e.g. What are the main findings of this report?", ) run = st.button("▶ Evaluate", use_container_width=True, type="primary") with col2: st.subheader("📊 Results") if run: if not api_key: st.error("Please enter your OpenAI API key in the sidebar.") elif not document.strip(): st.error("Please paste a document.") elif not query.strip(): st.error("Please enter a question.") else: with st.spinner("Running RAG pipeline..."): chunks = chunk_text(document) index, _ = build_index(chunks) context_chunks = retrieve(query, chunks, index) answer, context = generate_answer(query, context_chunks, api_key) with st.spinner("Evaluating answer quality..."): scores = evaluate(query, answer, context, api_key) st.markdown("**Answer**") st.info(answer) st.markdown("**Quality Scores**") def color_class(val): if val >= 0.75: return "score-high" elif val >= 0.5: return "score-mid" return "score-low" metrics = [ ("Faithfulness", scores["faithfulness"], "Is every claim supported by the document?"), ("Relevance", scores["relevance"], "Does the answer address the question?"), ("Groundedness", scores["groundedness"], "Does it avoid speculation?"), ("Completeness", scores["completeness"], "Does it cover all aspects of the question?"), ] c1, c2 = st.columns(2) for i, (label, val, tip) in enumerate(metrics): col = c1 if i % 2 == 0 else c2 with col: css_class = color_class(val) st.markdown( f"""
{label}
{val:.2f}
""", unsafe_allow_html=True, ) st.progress(val) st.caption(tip) avg = sum(scores.values()) / len(scores) st.markdown("---") overall_class = color_class(avg) st.markdown( f"""
Overall Quality Score
{avg:.2f}
""", unsafe_allow_html=True, ) with st.expander("🔍 Retrieved context chunks"): for i, chunk in enumerate(context_chunks): st.markdown(f"**Chunk {i+1}:**") st.text(chunk) else: st.markdown( """
Paste a document and question,
then click Evaluate to see results.
""", unsafe_allow_html=True, )