# LLM-as-Judge 实现模式 本文档提供了构建生产级 LLM 评估系统的详细实现模式。 ## 模式 1:结构化评估流水线 最可靠的评估系统遵循结构化的流水线来分离关注点: ``` Input Validation → Criteria Loading → Scoring → Bias Mitigation → Output Formatting ``` ### 输入验证层 在评估开始之前,验证以下内容: 1. **响应存在性**:待评估的响应不能为空 2. **提示词存在性**:用于提供上下文的原始提示词不能为空 3. **标准有效性**:至少有一条标准,且包含名称和描述 4. **权重归一化**:权重之和为 1.0(或对其进行归一化) ```python def validate_input(response, prompt, criteria): if not response or not response.strip(): raise ValueError("Response cannot be empty") if not prompt or not prompt.strip(): raise ValueError("Prompt cannot be empty") if not criteria or len(criteria) == 0: raise ValueError("At least one criterion required") # Normalize weights total_weight = sum(c.get('weight', 1) for c in criteria) for c in criteria: c['weight'] = c.get('weight', 1) / total_weight ``` ### 标准加载层 标准应从配置中加载,而非硬编码: ```python class CriteriaLoader: def __init__(self, rubric_path=None): self.rubrics = self._load_rubrics(rubric_path) def get_criteria(self, task_type): return self.rubrics.get(task_type, self.default_criteria) def get_rubric(self, criterion_name): return self.rubrics.get(criterion_name, {}).get('levels', []) ``` ### 评分层 评分层负责实际的 LLM 调用: ```python async def score_response(response, prompt, criteria, rubric, model): system_prompt = build_system_prompt(criteria, rubric) user_prompt = build_user_prompt(response, prompt, criteria) result = await generate_text( model=model, system=system_prompt, prompt=user_prompt, temperature=0.3 # Lower temperature for consistency ) return parse_scores(result.text) ``` ### 偏差缓解层 对于成对比较,始终包含位置交换: ```python async def compare_with_bias_mitigation(response_a, response_b, prompt, criteria, model): # First pass: A first pass1 = await compare_pair(response_a, response_b, prompt, criteria, model) # Second pass: B first pass2 = await compare_pair(response_b, response_a, prompt, criteria, model) # Map pass2 winner back pass2_mapped = map_winner(pass2.winner) # A→B, B→A, TIE→TIE # Check consistency if pass1.winner == pass2_mapped: return { 'winner': pass1.winner, 'confidence': (pass1.confidence + pass2.confidence) / 2, 'consistent': True } else: return { 'winner': 'TIE', 'confidence': 0.5, 'consistent': False } ``` ## 模式 2:分层评估 对于复杂的评估,使用分层方法: ``` Quick Screen (cheap model) → Detailed Evaluation (expensive model) → Human Review (edge cases) ``` ### 快速筛选实现 ```python async def quick_screen(response, prompt, threshold=0.7): """Fast, cheap screening for obvious passes/fails.""" result = await generate_text( model='gpt-5.2', # Cheaper model prompt=f"Rate 0-1 if this response adequately addresses the prompt:\n\nPrompt: {prompt}\n\nResponse: {response}", temperature=0 ) score = float(result.text.strip()) return score, score > threshold ``` ### 详细评估 ```python async def detailed_evaluation(response, prompt, criteria): """Full evaluation for borderline or important cases.""" result = await generate_text( model='gpt-5.2', # More capable model system=DETAILED_EVALUATION_PROMPT, prompt=build_detailed_prompt(response, prompt, criteria), temperature=0.3 ) return parse_detailed_scores(result.text) ``` ## 模式 3:LLM 评委专家组(PoLL) 对于高风险评估,使用多个模型: ```python async def poll_evaluation(response, prompt, criteria, models): """Aggregate judgments from multiple LLM judges.""" results = await asyncio.gather(*[ score_with_model(response, prompt, criteria, model) for model in models ]) # Aggregate scores aggregated = aggregate_scores(results) # Calculate agreement agreement = calculate_agreement(results) return { 'scores': aggregated, 'agreement': agreement, 'individual_results': results } def aggregate_scores(results): """Aggregate scores using median (robust to outliers).""" scores = {} for criterion in results[0]['scores'].keys(): criterion_scores = [r['scores'][criterion] for r in results] scores[criterion] = { 'score': statistics.median(criterion_scores), 'std': statistics.stdev(criterion_scores) if len(criterion_scores) > 1 else 0 } return scores ``` ## 模式 4:置信度校准 置信度得分应与实际可靠性相匹配: ```python def calibrate_confidence(raw_confidence, position_consistent, evidence_count): """Calibrate confidence based on multiple signals.""" # Base confidence from model output calibrated = raw_confidence # Position consistency is a strong signal if not position_consistent: calibrated *= 0.6 # Significant reduction # More evidence = higher confidence evidence_factor = min(evidence_count / 3, 1.0) # Cap at 3 pieces calibrated *= (0.7 + 0.3 * evidence_factor) return min(calibrated, 0.99) # Never 100% confident ``` ## 模式 5:输出格式化 始终使用一致的 Schema 返回结构化输出: ```python @dataclass class ScoreResult: criterion: str score: float max_score: float justification: str evidence: List[str] improvement: str @dataclass class EvaluationResult: success: bool scores: List[ScoreResult] overall_score: float weighted_score: float summary: Dict[str, Any] metadata: Dict[str, Any] def format_output(scores, metadata) -> EvaluationResult: """Format evaluation results consistently.""" return EvaluationResult( success=True, scores=scores, overall_score=sum(s.score for s in scores) / len(scores), weighted_score=calculate_weighted_score(scores), summary=generate_summary(scores), metadata=metadata ) ``` ## 错误处理模式 ### 优雅降级 ```python async def evaluate_with_fallback(response, prompt, criteria): try: return await full_evaluation(response, prompt, criteria) except RateLimitError: # Fall back to simpler evaluation return await simple_evaluation(response, prompt, criteria) except ParseError as e: # Return partial results with error flag return { 'success': False, 'partial_results': e.partial_data, 'error': str(e) } ``` ### 重试逻辑 ```python async def evaluate_with_retry(response, prompt, criteria, max_retries=3): for attempt in range(max_retries): try: result = await evaluate(response, prompt, criteria) if is_valid_result(result): return result except TransientError: await asyncio.sleep(2 ** attempt) # Exponential backoff raise EvaluationError("Max retries exceeded") ``` ## 测试模式 ### 解析单元测试 ```python def test_score_parsing(): raw_output = '{"scores": [{"criterion": "Accuracy", "score": 4}]}' result = parse_scores(raw_output) assert result.scores[0].criterion == "Accuracy" assert result.scores[0].score == 4 def test_malformed_output(): raw_output = 'Invalid JSON' with pytest.raises(ParseError): parse_scores(raw_output) ``` ### 集成测试(使用真实 API) ```python @pytest.mark.integration async def test_full_evaluation_pipeline(): result = await evaluate( response="Water boils at 100°C at sea level.", prompt="At what temperature does water boil?", criteria=[{"name": "Accuracy", "description": "Factual correctness", "weight": 1}] ) assert result.success assert len(result.scores) == 1 assert result.scores[0].score >= 4 # Should score high for accurate response ``` ### 偏差检测测试 ```python async def test_position_bias_mitigation(): # Same response in both positions should tie result = await compare( response_a="Same response", response_b="Same response", prompt="Test prompt", criteria=["quality"], swap_positions=True ) assert result.winner == "TIE" assert result.consistent == True ```