financial-rag-bot / scripts /evaluate_rag.py
Saadiktk's picture
Initial Hugging Face Space deployment
1ae6115
Raw
History Blame Contribute Delete
5.68 kB
import sys
import json
import time
import numpy as np
from pathlib import Path
# Add parent directory to path
sys.path.append(str(Path(__file__).resolve().parent.parent))
from app.main import generate_answer, embed_query, retrieve_chunks
EVAL_OUTPUT_PATH = Path(__file__).resolve().parent.parent / "data" / "eval_results.json"
# Ground Truth Evaluation Dataset
EVAL_DATASET = [
{
"id": 1,
"query": "What is the procedure for early loan repayment?",
"target_doc": "early_repayment.txt",
"expected_keywords": ["bondora.fi", "repay early", "PIN", "repaid in full"]
},
{
"id": 2,
"query": "How are customer complaints handled according to the policy?",
"target_doc": "Complaints-procedure.pdf",
"expected_keywords": ["Complaints", "5 business days", "15 days", "Consumer Disputes Board"]
},
{
"id": 3,
"query": "What support is available during financial hardship or job loss?",
"target_doc": "financial_hardship.txt",
"expected_keywords": ["financial hardship", "payment holiday", "payslips", "reschedule"]
},
{
"id": 4,
"query": "What is B-Secure and what benefits does it offer?",
"target_doc": "what_is_b_secure.txt",
"expected_keywords": ["B-Secure", "10", "restructure", "principal payment holiday"]
},
{
"id": 5,
"query": "What are the rules for debt collection?",
"target_doc": "debt_collection_process.txt",
"expected_keywords": ["debt", "collection"]
},
{
"id": 6,
"query": "What are the total loan amounts and average interest rates by country in the Bondora dataset?",
"target_doc": "bondora_loan_dataset_summary.txt",
"expected_keywords": ["Estonia", "Finland", "Spain", "25.32%"]
},
{
"id": 7,
"query": "How do I change my monthly payment date?",
"target_doc": "change_payment_date.txt",
"expected_keywords": ["payment date", "1st and 27th"]
},
{
"id": 8,
"query": "What is the process for closing an account?",
"target_doc": "closing_account.txt",
"expected_keywords": ["closing", "account"]
},
{
"id": 9,
"query": "What terms apply to automated payments?",
"target_doc": "Terms-and-conditions-for-automated-payments.pdf",
"expected_keywords": ["automated", "payments"]
},
{
"id": 10,
"query": "Where can I find the conflict policy information?",
"target_doc": "Conflict-policy.pdf",
"expected_keywords": ["Conflict", "policy"]
}
]
def run_evaluation():
print("Starting automated RAG evaluation benchmark run...")
hits = 0
faithfulness_scores = []
latencies = []
costs = []
results = []
for item in EVAL_DATASET:
q = item["query"]
target = item["target_doc"]
keywords = item["expected_keywords"]
print(f"Evaluating Q{item['id']}: '{q[:40]}...'")
# Run query (bypassing cache for benchmark accuracy)
res = generate_answer(q, use_cache=False)
latencies.append(res["latency_ms"])
costs.append(res["estimated_cost_usd"])
# Check Hit@10
retrieved_docs = [fn for _, fn, _ in res["chunks"]]
hit = any(target.lower() in fn.lower() for fn in retrieved_docs)
if hit:
hits += 1
# Check Faithfulness / Keyword Coverage
ans = res["answer"]
matched_kw = [kw for kw in keywords if kw.lower() in ans.lower()]
faithfulness = len(matched_kw) / len(keywords) if keywords else 1.0
faithfulness_scores.append(faithfulness)
results.append({
"id": item["id"],
"query": q,
"target_doc": target,
"hit_at_10": hit,
"faithfulness_score": round(faithfulness, 2),
"matched_keywords": matched_kw,
"latency_ms": res["latency_ms"],
"cost_usd": res["estimated_cost_usd"],
"retrieved_count": len(retrieved_docs)
})
time.sleep(0.5)
hit_at_10 = round(hits / len(EVAL_DATASET), 2)
avg_faithfulness = round(float(np.mean(faithfulness_scores)), 2)
p50_latency = round(float(np.percentile(latencies, 50)), 2)
p95_latency = round(float(np.percentile(latencies, 95)), 2)
avg_cost = round(float(np.mean(costs)), 6)
total_cost_1k = round(avg_cost * 1000, 4)
summary = {
"timestamp": time.time(),
"total_test_cases": len(EVAL_DATASET),
"hit_at_10_recall": hit_at_10,
"avg_faithfulness_score": avg_faithfulness,
"p50_latency_ms": p50_latency,
"p95_latency_ms": p95_latency,
"avg_cost_per_query_usd": avg_cost,
"estimated_cost_per_1k_queries_usd": total_cost_1k,
"test_results": results
}
EVAL_OUTPUT_PATH.parent.mkdir(parents=True, exist_ok=True)
with open(EVAL_OUTPUT_PATH, "w", encoding="utf-8") as f:
json.dump(summary, f, indent=2)
print("\n================ EVALUATION BENCHMARK RESULTS ================")
print(f" Hit@10 Recall Rate: {hit_at_10 * 100:.1f}%")
print(f" Avg Faithfulness Score: {avg_faithfulness * 100:.1f}%")
print(f" p50 Latency: {p50_latency} ms")
print(f" p95 Latency: {p95_latency} ms")
print(f" Avg Cost / Request: ${avg_cost:.6f}")
print(f" Cost / 1,000 Queries: ${total_cost_1k:.4f}")
print("==============================================================")
print(f"Saved evaluation results to {EVAL_OUTPUT_PATH}")
if __name__ == "__main__":
run_evaluation()