Spaces:
Sleeping
Sleeping
| """ | |
| Advanced features for chatbot: follow-up suggestions, ambiguity detection, explanations. | |
| """ | |
| from typing import List, Dict, Any, Optional | |
| from hue_portal.core.models import Fine, Procedure, Office, Advisory | |
| def suggest_follow_up_questions(query: str, results: List[Any], intent: str) -> List[str]: | |
| """ | |
| Suggest follow-up questions based on query and results. | |
| Args: | |
| query: Original query. | |
| results: Retrieved results. | |
| intent: Detected intent. | |
| Returns: | |
| List of suggested follow-up questions. | |
| """ | |
| suggestions = [] | |
| if intent == "search_fine": | |
| if results: | |
| # Suggest questions about related fines | |
| suggestions.append("Còn mức phạt nào khác không?") | |
| suggestions.append("Điều luật liên quan là gì?") | |
| suggestions.append("Biện pháp khắc phục như thế nào?") | |
| else: | |
| suggestions.append("Bạn có thể cho biết cụ thể loại vi phạm không?") | |
| elif intent == "search_procedure": | |
| if results: | |
| suggestions.append("Hồ sơ cần chuẩn bị gì?") | |
| suggestions.append("Lệ phí là bao nhiêu?") | |
| suggestions.append("Thời hạn xử lý là bao lâu?") | |
| suggestions.append("Nộp hồ sơ ở đâu?") | |
| else: | |
| suggestions.append("Bạn muốn tìm thủ tục nào cụ thể?") | |
| elif intent == "search_office": | |
| if results: | |
| suggestions.append("Số điện thoại liên hệ?") | |
| suggestions.append("Giờ làm việc như thế nào?") | |
| suggestions.append("Địa chỉ cụ thể ở đâu?") | |
| else: | |
| suggestions.append("Bạn muốn tìm đơn vị nào?") | |
| elif intent == "search_advisory": | |
| if results: | |
| suggestions.append("Còn cảnh báo nào khác không?") | |
| suggestions.append("Cách phòng tránh như thế nào?") | |
| else: | |
| suggestions.append("Bạn muốn tìm cảnh báo về chủ đề gì?") | |
| return suggestions[:3] # Return top 3 suggestions | |
| def detect_ambiguity(query: str, results_count: int, confidence: float) -> Tuple[bool, Optional[str]]: | |
| """ | |
| Detect if query is ambiguous. | |
| Args: | |
| query: User query. | |
| results_count: Number of results found. | |
| confidence: Confidence score. | |
| Returns: | |
| Tuple of (is_ambiguous, ambiguity_reason). | |
| """ | |
| query_lower = query.lower() | |
| query_words = query.split() | |
| # Very short queries are often ambiguous | |
| if len(query_words) <= 2: | |
| return (True, "Câu hỏi quá ngắn, cần thêm thông tin") | |
| # Low confidence and many results suggests ambiguity | |
| if results_count > 10 and confidence < 0.5: | |
| return (True, "Kết quả quá nhiều, cần cụ thể hơn") | |
| # Very generic queries | |
| generic_queries = ["thông tin", "tìm kiếm", "hỏi", "giúp"] | |
| if any(gq in query_lower for gq in generic_queries) and len(query_words) <= 3: | |
| return (True, "Câu hỏi chung chung, cần cụ thể hơn") | |
| return (False, None) | |
| def generate_explanation(result: Any, query: str, score: Optional[float] = None) -> str: | |
| """ | |
| Generate explanation for why a result is relevant. | |
| Args: | |
| result: Result object. | |
| result_type: Type of result. | |
| query: Original query. | |
| score: Relevance score. | |
| Returns: | |
| Explanation string. | |
| """ | |
| result_type = type(result).__name__.lower() | |
| explanation_parts = [] | |
| if "fine" in result_type: | |
| name = getattr(result, "name", "") | |
| code = getattr(result, "code", "") | |
| explanation_parts.append(f"Kết quả này phù hợp vì:") | |
| if code: | |
| explanation_parts.append(f"- Mã vi phạm: {code}") | |
| if name: | |
| explanation_parts.append(f"- Tên vi phạm: {name}") | |
| if score: | |
| explanation_parts.append(f"- Độ phù hợp: {score:.0%}") | |
| elif "procedure" in result_type: | |
| title = getattr(result, "title", "") | |
| explanation_parts.append(f"Kết quả này phù hợp vì:") | |
| if title: | |
| explanation_parts.append(f"- Tên thủ tục: {title}") | |
| if score: | |
| explanation_parts.append(f"- Độ phù hợp: {score:.0%}") | |
| elif "office" in result_type: | |
| unit_name = getattr(result, "unit_name", "") | |
| explanation_parts.append(f"Kết quả này phù hợp vì:") | |
| if unit_name: | |
| explanation_parts.append(f"- Tên đơn vị: {unit_name}") | |
| if score: | |
| explanation_parts.append(f"- Độ phù hợp: {score:.0%}") | |
| elif "advisory" in result_type: | |
| title = getattr(result, "title", "") | |
| explanation_parts.append(f"Kết quả này phù hợp vì:") | |
| if title: | |
| explanation_parts.append(f"- Tiêu đề: {title}") | |
| if score: | |
| explanation_parts.append(f"- Độ phù hợp: {score:.0%}") | |
| return "\n".join(explanation_parts) if explanation_parts else "Kết quả này phù hợp với câu hỏi của bạn." | |
| def compare_results(results: List[Any], result_type: str) -> str: | |
| """ | |
| Compare multiple results and highlight differences. | |
| Args: | |
| results: List of result objects. | |
| result_type: Type of results. | |
| Returns: | |
| Comparison summary string. | |
| """ | |
| if len(results) < 2: | |
| return "" | |
| comparison_parts = ["So sánh các kết quả:"] | |
| if result_type == "fine": | |
| # Compare fine amounts | |
| fine_amounts = [] | |
| for result in results[:3]: | |
| if hasattr(result, "min_fine") and hasattr(result, "max_fine"): | |
| if result.min_fine and result.max_fine: | |
| fine_amounts.append(f"{result.name}: {result.min_fine:,.0f} - {result.max_fine:,.0f} VNĐ") | |
| if fine_amounts: | |
| comparison_parts.extend(fine_amounts) | |
| elif result_type == "procedure": | |
| # Compare procedures by domain/level | |
| for result in results[:3]: | |
| title = getattr(result, "title", "") | |
| domain = getattr(result, "domain", "") | |
| level = getattr(result, "level", "") | |
| if title: | |
| comp = f"- {title}" | |
| if domain: | |
| comp += f" ({domain})" | |
| if level: | |
| comp += f" - Cấp {level}" | |
| comparison_parts.append(comp) | |
| return "\n".join(comparison_parts) | |