rag-evaluator / app.py
Faraz618's picture
Create app.py
6061290 verified
Raw
History Blame Contribute Delete
5.26 kB
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("""
<style>
.metric-card {
background: #f8fafc;
border: 1px solid #e2e8f0;
border-radius: 10px;
padding: 1rem 1.25rem;
text-align: center;
}
.metric-label {
font-size: 12px;
color: #64748b;
text-transform: uppercase;
letter-spacing: 0.05em;
margin-bottom: 0.25rem;
}
.metric-value {
font-size: 28px;
font-weight: 600;
}
.score-high { color: #16a34a; }
.score-mid { color: #d97706; }
.score-low { color: #dc2626; }
</style>
""", 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"""<div class="metric-card" title="{tip}">
<div class="metric-label">{label}</div>
<div class="metric-value {css_class}">{val:.2f}</div>
</div>""",
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"""<div class="metric-card">
<div class="metric-label">Overall Quality Score</div>
<div class="metric-value {overall_class}">{avg:.2f}</div>
</div>""",
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(
"""<div style='padding:2rem;text-align:center;color:#94a3b8;border:1px dashed #e2e8f0;border-radius:10px;'>
Paste a document and question,<br>then click <b>Evaluate</b> to see results.
</div>""",
unsafe_allow_html=True,
)