Spaces:
Running
Running
File size: 5,434 Bytes
ee56f8e | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | """
Tool for validating that responses are properly grounded in context.
"""
import re
from typing import Dict, List, Any
from ..models.agent_models import GroundedResponse, RetrievedContext
class GroundingValidatorTool:
"""
Tool for validating that responses are properly grounded in provided context.
"""
def __call__(self, response: str, context: str, sources: List[str]) -> Dict[str, Any]:
"""
Validate that the response is properly grounded in the provided context.
Args:
response: The response to validate
context: The context that was provided to generate the response
sources: List of sources used in the response
Returns:
Dictionary with validation results
"""
# Check if response contains information from the context
context_present = self._check_context_presence(response, context)
# Check for hallucinations (information not in context)
hallucinations = self._detect_hallucinations(response, context)
# Validate source citations
citations_valid = self._validate_citations(response, sources)
# Calculate confidence score based on validation
confidence_score = self._calculate_confidence_score(
context_present, hallucinations, citations_valid
)
return {
"is_valid": context_present and not hallucinations and citations_valid,
"validation_details": {
"context_present": context_present,
"hallucinations_detected": len(hallucinations) > 0,
"hallucinations": hallucinations,
"citations_valid": citations_valid,
"sources_mentioned": sources
},
"confidence_score": confidence_score
}
def _check_context_presence(self, response: str, context: str) -> bool:
"""
Check if the response contains information from the provided context.
Args:
response: The response to validate
context: The context that was provided
Returns:
True if response appears to contain information from context
"""
# Convert to lowercase for comparison
response_lower = response.lower()
context_lower = context.lower()
# Check if key terms from context appear in response
context_words = set(context_lower.split())
response_words = set(response_lower.split())
# Find intersection of words
common_words = context_words.intersection(response_words)
# If there's a meaningful intersection, consider context present
return len(common_words) > 3 # arbitrary threshold
def _detect_hallucinations(self, response: str, context: str) -> List[str]:
"""
Detect potential hallucinations in the response.
Args:
response: The response to validate
context: The context that was provided
Returns:
List of potential hallucinations (claims not supported by context)
"""
# For simplicity, this is a basic implementation
# A more sophisticated implementation would use semantic similarity
# or other advanced techniques
hallucinations = []
# Look for claims that are not supported by the context
# This is a simplified approach - in practice, this would be more complex
response_sentences = re.split(r'[.!?]+', response)
context_lower = context.lower()
for sentence in response_sentences:
sentence = sentence.strip()
if sentence and sentence.lower() not in context_lower:
# This is a simplified check - in reality, we'd need more sophisticated
# semantic analysis to determine if the sentence is supported by context
pass # Skip this basic check for now, as it's too simplistic
return hallucinations
def _validate_citations(self, response: str, sources: List[str]) -> bool:
"""
Validate that sources are properly cited in the response.
Args:
response: The response to validate
sources: List of sources that should be cited
Returns:
True if sources are properly cited in the response
"""
response_lower = response.lower()
cited_sources = 0
for source in sources:
if source.lower() in response_lower:
cited_sources += 1
# Require at least one source to be cited
return cited_sources > 0
def _calculate_confidence_score(self, context_present: bool, hallucinations: List[str], citations_valid: bool) -> float:
"""
Calculate a confidence score based on validation results.
Args:
context_present: Whether context is present in response
hallucinations: List of detected hallucinations
citations_valid: Whether citations are valid
Returns:
Confidence score between 0 and 1
"""
score = 0.0
if context_present:
score += 0.4 # 40% for context presence
if not hallucinations:
score += 0.4 # 40% for no hallucinations
if citations_valid:
score += 0.2 # 20% for valid citations
return min(score, 1.0) # Cap at 1.0 |