Spaces:
Runtime error
Runtime error
File size: 7,367 Bytes
eeb0f9c |
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 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 |
"""
Response Validator - Ensures LLM responses follow quality standards
Shared validation logic for all agents
"""
from typing import Dict, List, Tuple
class ResponseValidator:
"""
Base validator with common rules + agent-specific rules
"""
# Common bad phrases across all agents
COMMON_BAD_PHRASES = [
"Dựa trên thông tin bạn cung cấp",
"Dựa vào thông tin",
"Theo thông tin bạn đưa ra",
"Từ thông tin trên",
"Với tư cách",
"Tôi là chuyên gia"
]
@staticmethod
def validate_common(response: str) -> Tuple[bool, List[str]]:
"""
Common validation rules for all agents
Returns: (is_valid, list_of_issues)
"""
issues = []
# Check for formal phrases
for phrase in ResponseValidator.COMMON_BAD_PHRASES:
if phrase.lower() in response.lower():
issues.append(f"Formal phrase: '{phrase}'")
break
# Check for excessive length (>500 words)
word_count = len(response.split())
if word_count > 500:
issues.append(f"Too long: {word_count} words (max 500)")
# Check for empty response
if len(response.strip()) < 10:
issues.append("Response too short or empty")
return len(issues) == 0, issues
@staticmethod
def validate_symptom_response(response: str, context: Dict) -> Tuple[bool, List[str]]:
"""
Symptom-specific validation
"""
issues = []
stage = context.get('conversation_stage', 0)
# Assessment phase: should ask, not advise
if stage <= 1:
advice_indicators = [
"khuyến nghị", "nên", "hãy", "bạn thử",
"giải pháp", "cách xử lý"
]
has_advice = any(ind in response.lower() for ind in advice_indicators)
has_question = '?' in response
if has_advice and not has_question:
issues.append("Đưa lời khuyên quá sớm (assessment phase)")
# Check if both asking and advising
if '?' in response:
advice_count = sum(1 for ind in ["khuyến nghị", "nên", "hãy thử"]
if ind in response.lower())
if advice_count >= 2:
issues.append("Vừa hỏi vừa khuyên")
return len(issues) == 0, issues
@staticmethod
def validate_nutrition_response(response: str, context: Dict, chat_history: List) -> Tuple[bool, List[str]]:
"""
Nutrition-specific validation
"""
issues = []
# Check if asking for info already provided
if chat_history:
all_user_text = " ".join([msg[0].lower() for msg in chat_history if msg[0]])
# Check if asking for age when already provided
if "tuổi" in all_user_text or "năm" in all_user_text:
if "bao nhiêu tuổi" in response.lower() or "tuổi của bạn" in response.lower():
issues.append("Hỏi lại tuổi đã được cung cấp")
# Check if asking for weight when already provided
if "kg" in all_user_text or "cân nặng" in all_user_text:
if "cân nặng" in response.lower() and "?" in response:
issues.append("Hỏi lại cân nặng đã được cung cấp")
# Check for too theoretical (should be practical)
theory_indicators = ["lý thuyết", "nghiên cứu cho thấy", "theo khoa học"]
if any(ind in response.lower() for ind in theory_indicators):
practical_indicators = ["bạn thử", "có thể", "ví dụ", "thực đơn"]
if not any(ind in response.lower() for ind in practical_indicators):
issues.append("Quá lý thuyết, thiếu practical advice")
return len(issues) == 0, issues
@staticmethod
def validate_exercise_response(response: str, context: Dict) -> Tuple[bool, List[str]]:
"""
Exercise-specific validation
"""
issues = []
# Check if workout plan is too generic
if "lịch tập" in response.lower() or "kế hoạch" in response.lower():
# Should have specific days or progression
has_specifics = any(word in response.lower() for word in [
"thứ", "ngày", "tuần 1", "tuần 2", "tháng"
])
if not has_specifics:
issues.append("Lịch tập quá generic, thiếu chi tiết")
# Check for progression
if "tập" in response.lower():
has_progression = any(word in response.lower() for word in [
"tăng dần", "progression", "tuần 1", "giai đoạn"
])
if not has_progression and len(response) > 200:
issues.append("Thiếu hướng dẫn progression")
return len(issues) == 0, issues
@staticmethod
def validate_mental_health_response(response: str, context: Dict) -> Tuple[bool, List[str]]:
"""
Mental health-specific validation
"""
issues = []
# Should have empathy/validation
empathy_indicators = [
"cảm giác", "hiểu", "bình thường", "nhiều người",
"không phải lỗi của bạn"
]
if len(response) > 100: # Only check for longer responses
has_empathy = any(ind in response.lower() for ind in empathy_indicators)
if not has_empathy:
issues.append("Thiếu empathy/validation")
# Check for too clinical
clinical_indicators = ["chẩn đoán", "bệnh", "rối loạn"]
if any(ind in response.lower() for ind in clinical_indicators):
if "không phải bác sĩ" not in response.lower():
issues.append("Quá clinical, cần disclaimer")
return len(issues) == 0, issues
@staticmethod
def validate_response(response: str, agent_type: str, context: Dict, chat_history: List = None) -> Tuple[bool, List[str]]:
"""
Main validation method - routes to appropriate validator
"""
# Common validation first
is_valid_common, common_issues = ResponseValidator.validate_common(response)
# Agent-specific validation
agent_issues = []
if agent_type == 'symptom':
_, agent_issues = ResponseValidator.validate_symptom_response(response, context)
elif agent_type == 'nutrition':
_, agent_issues = ResponseValidator.validate_nutrition_response(response, context, chat_history or [])
elif agent_type == 'exercise':
_, agent_issues = ResponseValidator.validate_exercise_response(response, context)
elif agent_type == 'mental_health':
_, agent_issues = ResponseValidator.validate_mental_health_response(response, context)
# Combine all issues
all_issues = common_issues + agent_issues
is_valid = len(all_issues) == 0
return is_valid, all_issues
|