A comprehensive guide and implementation for evaluating Large Language Model (LLM) outputs.
This project teaches you about:
- Evaluation Frameworks: How to systematically measure LLM performance
- Output Quality Metrics: Relevance, accuracy, and hallucination detection
- LLMs-as-Judges: Using LLMs to evaluate other LLMs
- Text Similarity Metrics: ROUGE and BLEU scores
- Custom Metrics: Building domain-specific evaluation criteria
- Cost & Latency Tracking: Understanding the trade-offs between different prompts
Relevance measures how well the LLM's response addresses the question. A relevant answer:
- Directly answers the question
- Stays on topic
- Provides appropriate detail level
Accuracy measures factual correctness. An accurate answer:
- Contains correct information
- Doesn't contradict known facts
- Provides verifiable claims
Hallucinations are when LLMs generate:
- Factually incorrect information
- Information not present in the training data
- Contradictory statements
- Fabricated details
ROUGE measures overlap between generated and reference text:
- ROUGE-1: Unigram overlap (word-level)
- ROUGE-2: Bigram overlap (phrase-level)
- ROUGE-L: Longest common subsequence (sentence structure)
Use Case: Best for summarization, translation, and text generation tasks.
BLEU measures precision of n-grams:
- Compares generated text to reference text
- Scores range from 0 to 1 (higher is better)
- Penalizes overly short or repetitive outputs
Use Case: Best for translation and text generation where precision matters.
Using a judge LLM to evaluate another LLM's output:
- Advantages: Understands context, can evaluate nuanced quality
- Approach: Provide question, answer, and reference to judge LLM
- Output: Numerical score or categorical rating
Use Case: When you need semantic understanding beyond n-gram matching.
LLM_Evaluation/
├── README.md # This file
├── requirements.txt # Python dependencies
├── metrics/ # Evaluation metrics
│ ├── __init__.py
│ ├── rouge_bleu.py # ROUGE and BLEU implementations
│ ├── llm_judge.py # LLM-as-judge evaluator
│ └── custom_metrics.py # Custom evaluation functions
├── pipeline/ # Evaluation pipeline
│ ├── __init__.py
│ ├── evaluator.py # Main evaluation orchestrator
│ └── prompt_templates.py # Different prompt variations
├── data/ # Datasets
│ ├── qa_dataset.json # 100 Q&A pairs
│ └── generate_dataset.py # Script to generate sample data
├── dashboard/ # Visualization
│ ├── __init__.py
│ └── visualizer.py # Dashboard generator
└── main.py # Main execution script
- Install dependencies:
pip install -r requirements.txt
python -m nltk.downloader punkt- Set up API keys (create
.envfile):
OPENAI_API_KEY=your_key_here
ANTHROPIC_API_KEY=your_key_here
- Run evaluation:
python main.py- View dashboard:
The dashboard will be generated as
evaluation_dashboard.html
The pipeline evaluates 5 different prompts on 100 Q&A pairs:
- Baseline Prompt: Simple, direct question
- Detailed Prompt: Asks for comprehensive answer
- Few-Shot Prompt: Includes examples
- Chain-of-Thought Prompt: Asks for reasoning steps
- Structured Prompt: Requests formatted output
For each prompt, we measure:
- Accuracy: LLM-as-judge score (0-1)
- Relevance: ROUGE-L score
- Latency: Time to generate response (seconds)
- Cost: Estimated API cost per response
- 0.0-0.3: Low overlap, likely irrelevant
- 0.3-0.5: Moderate overlap, somewhat relevant
- 0.5-0.7: Good overlap, relevant
- 0.7-1.0: High overlap, very relevant
- 0.0-0.3: Low precision, many errors
- 0.3-0.5: Moderate precision
- 0.5-0.7: Good precision
- 0.7-1.0: High precision, very close to reference
- 0.0-0.4: Poor quality (inaccurate, irrelevant, or hallucinated)
- 0.4-0.6: Acceptable quality
- 0.6-0.8: Good quality
- 0.8-1.0: Excellent quality
Different metrics capture different aspects:
- ROUGE: Word/phrase overlap (surface-level similarity)
- BLEU: Precision of n-grams (translation quality)
- LLM Judge: Semantic understanding (human-like evaluation)
- ROUGE: Summarization, abstractive tasks
- BLEU: Translation, generation tasks
- LLM Judge: When you need nuanced quality assessment
- Custom Metrics: Domain-specific requirements
- Longer prompts = more tokens = higher cost
- More detailed responses = higher latency
- Balance quality vs. efficiency
- Fact-checking: Compare against knowledge base
- Consistency checks: Verify internal consistency
- Confidence scores: Ask LLM for confidence level
- Multi-model verification: Compare across models
Build metrics for:
- Domain-specific terminology
- Style consistency
- Safety and bias
- Task-specific success criteria
from pipeline.evaluator import Evaluator
from metrics.rouge_bleu import calculate_rouge, calculate_bleu
from metrics.llm_judge import llm_judge_score
# Initialize evaluator
evaluator = Evaluator()
# Evaluate a single Q&A pair
question = "What is machine learning?"
reference = "Machine learning is a subset of AI..."
response = evaluator.get_llm_response(question, prompt_template)
# Calculate metrics
rouge_score = calculate_rouge(response, reference)
bleu_score = calculate_bleu(response, reference)
judge_score = llm_judge_score(question, response, reference)- Experiment with different prompt templates
- Add more evaluation metrics
- Test on your own datasets
- Implement hallucination detection
- Build domain-specific evaluators