llm-eval-ap / README.md
sha6th's picture
Initial deploy of LLM eval API
7d95632
|
Raw
History Blame Contribute Delete
5.3 kB
---
title: Llm Eval Ap
emoji: πŸƒ
colorFrom: blue
colorTo: pink
sdk: docker
pinned: false
---
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
# LLM Evaluation & Hallucination Detection Framework
A multi-metric evaluation system that automatically detects hallucinations, measures faithfulness, relevance, and fluency in LLM-generated responses β€” built for QA pipelines in RAG and LLM-powered systems.
## Problem
LLMs frequently generate fluent, confident, but factually incorrect responses ("hallucinations") with no built-in way to detect this. This is a critical risk in production systems β€” healthcare Q&A, legal summarization, customer support chatbots, RAG pipelines β€” where a wrong but confident answer can cause real harm.
This framework evaluates any `(context, question, llm_response)` triple and returns a verdict: **Faithful**, **Hallucinated**, **Irrelevant**, or **Unverifiable** β€” backed by 4 independent scoring methods.
## Why 4 Metrics, Not 1
Each metric has a blind spot the others cover:
| Metric | Catches | Misses |
|---|---|---|
| **NLI** (`cross-encoder/nli-deberta-v3-small`) | Direct factual contradictions | Whether the question was actually answered |
| **BERTScore** | Overall semantic drift from context | Subtle single-fact contradictions (high lexical overlap masks them) |
| **Cosine Similarity** (`all-MiniLM-L6-v2`) | Whether response is relevant to the question | Factual correctness |
| **Fluency** (rule-based) | Grammatical/structural quality | Meaning entirely |
Example that demonstrates this in practice β€” tested live in this project:
```
Context: "Virat Kohli won 2 IPL trophies as a player and 0 as captain."
Response: "Virat Kohli won 25 IPL trophies."
BERTScore: 0.89 β†’ "Highly Faithful" ❌ (fooled by lexical overlap)
NLI: contradiction (0.999) βœ… (catches the numeric hallucination)
Final verdict: Hallucinated (correct)
```
This is the core finding the project is built around: no single metric is reliable alone.
## Architecture
```
POST /evaluate { context, question, llm_response }
β”‚
β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 4 evaluators run in parallelβ”‚
β”‚ Cosine | Fluency | BERTScore | NLI β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β–Ό
Aggregator (rule-based verdict logic)
β”‚
β–Ό
SQLite (persisted) ──► GET /history
β”‚
β–Ό
Streamlit Dashboard (manual testing + history view)
```
## Tech Stack
- **FastAPI** β€” REST API (`/evaluate`, `/history`)
- **HuggingFace Transformers** β€” NLI model (`cross-encoder/nli-deberta-v3-small`)
- **bert-score** β€” semantic faithfulness scoring
- **sentence-transformers** β€” cosine similarity (`all-MiniLM-L6-v2`)
- **SQLite** β€” evaluation history storage
- **Streamlit** β€” interactive dashboard
All models are CPU-friendly β€” no GPU required.
## Setup
```bash
git clone <your-repo-url>
cd llm-eval-framework
python -m venv venv
venv\Scripts\activate # Windows
pip install -r requirements.txt
```
## Running
**Start the API:**
```bash
uvicorn main:app --reload
```
API docs: `http://localhost:8000/docs`
**Start the dashboard** (separate terminal):
```bash
streamlit run dashboard/app.py
```
Dashboard: `http://localhost:8501`
## API
### `POST /evaluate`
```json
{
"context": "Photosynthesis converts sunlight into glucose.",
"question": "How do plants make food?",
"llm_response": "Plants use moonlight to produce glucose."
}
```
Response:
```json
{
"final_verdict": "Hallucinated",
"cosine": {"score": 0.52, "verdict": "Partially Relevant"},
"fluency": {"issues": [], "verdict": "Fluent"},
"bert_score": {"score": 0.91, "verdict": "Highly Faithful"},
"nli": {"label": "contradiction", "score": 0.999, "verdict": "Hallucinated"}
}
```
### `GET /history`
Returns all past evaluations with verdicts and timestamps.
## Project Structure
```
llm-eval-framework/
β”œβ”€β”€ main.py # FastAPI app
β”œβ”€β”€ src/
β”‚ β”œβ”€β”€ aggregator.py # Combines all 4 scores β†’ final verdict
β”‚ β”œβ”€β”€ database.py # SQLite persistence
β”‚ └── evaluators/
β”‚ β”œβ”€β”€ nli_evaluator.py
β”‚ β”œβ”€β”€ bert_score_evaluator.py
β”‚ β”œβ”€β”€ cosine_evaluator.py
β”‚ └── fluency_evaluator.py
β”œβ”€β”€ dashboard/
β”‚ └── app.py # Streamlit UI
β”œβ”€β”€ data/ # SQLite DB
└── requirements.txt
```
## Known Limitations
- Verdict aggregation uses fixed thresholds (not learned/calibrated) β€” a clear next step would be calibrating thresholds against a labeled hallucination dataset.
- Models are English-only; no language detection guard yet.
- Evaluators run sequentially, not batched/async β€” fine for single requests, would need optimization for high-throughput production use.
- No authentication on the API β€” would need to add this before any real external exposure.
## Author
Sharath β€” built as a hands-on project to learn FastAPI, NLI, and LLM evaluation techniques from first principles.