davidtran999 commited on
Commit
aa4e737
·
verified ·
1 Parent(s): 5848515

Upload backend/hue_portal/core/query_reformulation.py with huggingface_hub

Browse files
backend/hue_portal/core/query_reformulation.py ADDED
@@ -0,0 +1,269 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Query reformulation strategies for handling difficult queries.
3
+ """
4
+ from typing import List, Optional, Dict, Any
5
+ import re
6
+
7
+
8
+ def simplify_query(query: str) -> str:
9
+ """
10
+ Simplify query by removing stopwords and keeping only key terms.
11
+
12
+ Args:
13
+ query: Original query string.
14
+
15
+ Returns:
16
+ Simplified query string.
17
+ """
18
+ # Vietnamese stopwords
19
+ stopwords = {
20
+ "là", "gì", "bao nhiêu", "như thế nào", "ở đâu", "của", "và", "hoặc",
21
+ "tôi", "bạn", "có", "không", "được", "một", "các", "với", "cho",
22
+ "theo", "thì", "sao", "như", "về", "trong", "nào", "để", "mà"
23
+ }
24
+
25
+ words = query.lower().split()
26
+ key_words = [w for w in words if w not in stopwords and len(w) > 2]
27
+
28
+ return " ".join(key_words) if key_words else query
29
+
30
+
31
+ def extract_key_terms(query: str) -> List[str]:
32
+ """
33
+ Extract key terms from query (document codes, numbers, important nouns).
34
+
35
+ Args:
36
+ query: Original query string.
37
+
38
+ Returns:
39
+ List of key terms.
40
+ """
41
+ key_terms = []
42
+
43
+ # Extract document codes
44
+ doc_code_patterns = [
45
+ r'QD[-\s]?69',
46
+ r'QD[-\s]?264',
47
+ r'264[-\s]?QD',
48
+ r'TT[-\s]?02',
49
+ r'QUYET[-\s]?DINH[-\s]?69',
50
+ r'QUYET[-\s]?DINH[-\s]?264',
51
+ r'THONG[-\s]?TU[-\s]?02',
52
+ ]
53
+
54
+ for pattern in doc_code_patterns:
55
+ matches = re.findall(pattern, query.upper())
56
+ key_terms.extend(matches)
57
+
58
+ # Extract numbers (likely article numbers)
59
+ numbers = re.findall(r'\d+', query)
60
+ key_terms.extend(numbers)
61
+
62
+ # Extract important legal terms
63
+ legal_terms = [
64
+ "kỷ luật", "đảng viên", "cán bộ", "xử lý", "hình thức",
65
+ "điều lệnh", "quy định", "quyết định", "thông tư"
66
+ ]
67
+
68
+ query_lower = query.lower()
69
+ for term in legal_terms:
70
+ if term in query_lower:
71
+ key_terms.append(term)
72
+
73
+ return list(set(key_terms))
74
+
75
+
76
+ def reformulate_query_multiple_ways(query: str) -> List[str]:
77
+ """
78
+ Generate multiple reformulations of the query.
79
+
80
+ Args:
81
+ query: Original query string.
82
+
83
+ Returns:
84
+ List of reformulated queries.
85
+ """
86
+ reformulations = [query] # Always include original
87
+
88
+ # 1. Simplified version (remove stopwords)
89
+ simplified = simplify_query(query)
90
+ if simplified != query and len(simplified) > 3:
91
+ reformulations.append(simplified)
92
+
93
+ # 2. Key terms only
94
+ key_terms = extract_key_terms(query)
95
+ if key_terms:
96
+ key_terms_query = " ".join(key_terms)
97
+ if key_terms_query not in reformulations:
98
+ reformulations.append(key_terms_query)
99
+
100
+ # 3. Remove question words
101
+ question_words = ["là gì", "như thế nào", "bao nhiêu", "ở đâu", "sao", "thế nào"]
102
+ query_lower = query.lower()
103
+ for qw in question_words:
104
+ if qw in query_lower:
105
+ reformulated = query_lower.replace(qw, "").strip()
106
+ if reformulated and reformulated not in reformulations:
107
+ reformulations.append(reformulated)
108
+
109
+ # 4. Expand abbreviations
110
+ abbreviations = {
111
+ "qd": "quyết định",
112
+ "tt": "thông tư",
113
+ "cand": "công an nhân dân",
114
+ }
115
+ expanded = query_lower
116
+ for abbr, full in abbreviations.items():
117
+ expanded = expanded.replace(abbr, full)
118
+ if expanded != query_lower and expanded not in reformulations:
119
+ reformulations.append(expanded)
120
+
121
+ return reformulations
122
+
123
+
124
+ def create_fallback_queries(query: str, intent: str) -> List[str]:
125
+ """
126
+ Create fallback queries for when primary search fails.
127
+
128
+ Args:
129
+ query: Original query string.
130
+ intent: Detected intent.
131
+
132
+ Returns:
133
+ List of fallback queries ordered by priority.
134
+ """
135
+ fallbacks = []
136
+
137
+ # Strategy 1: Extract only document codes and key legal terms
138
+ key_terms = extract_key_terms(query)
139
+ if key_terms:
140
+ fallbacks.append(" ".join(key_terms))
141
+
142
+ # Strategy 2: Simplified query
143
+ simplified = simplify_query(query)
144
+ if simplified != query:
145
+ fallbacks.append(simplified)
146
+
147
+ # Strategy 3: Intent-specific keywords
148
+ if intent == "search_legal":
149
+ # Extract document code if present
150
+ doc_codes = []
151
+ if "69" in query or "quyết định 69" in query.lower():
152
+ doc_codes.append("QD-69-TW")
153
+ if "264" in query or "quyết định 264" in query.lower():
154
+ doc_codes.append("264-QD-TW")
155
+ if "thông tư 02" in query.lower() or "tt 02" in query.lower():
156
+ doc_codes.append("TT-02-CAND")
157
+
158
+ # Add legal keywords
159
+ legal_keywords = []
160
+ if "kỷ luật" in query.lower():
161
+ legal_keywords.append("kỷ luật")
162
+ if "đảng viên" in query.lower():
163
+ legal_keywords.append("đảng viên")
164
+ if "xử lý" in query.lower():
165
+ legal_keywords.append("xử lý")
166
+
167
+ if doc_codes or legal_keywords:
168
+ fallback = " ".join(doc_codes + legal_keywords)
169
+ if fallback not in fallbacks:
170
+ fallbacks.append(fallback)
171
+
172
+ return fallbacks
173
+
174
+
175
+ def reformulate_with_llm(query: str, intent: str, llm_generator=None) -> List[str]:
176
+ """
177
+ Use LLM to reformulate complex queries into simpler, more searchable forms.
178
+
179
+ Args:
180
+ query: Original query string.
181
+ intent: Detected intent.
182
+ llm_generator: Optional LLM generator instance.
183
+
184
+ Returns:
185
+ List of reformulated queries.
186
+ """
187
+ if not llm_generator:
188
+ return []
189
+
190
+ try:
191
+ # Create prompt for query reformulation
192
+ reformulation_prompt = f"""Bạn là trợ lý tìm kiếm văn bản pháp luật. Nhiệm vụ của bạn là chuyển đổi câu hỏi phức tạp thành các câu hỏi đơn giản hơn, dễ tìm kiếm hơn.
193
+
194
+ Câu hỏi gốc: "{query}"
195
+
196
+ Hãy tạo 3-5 phiên bản đơn giản hóa của câu hỏi này, tập trung vào:
197
+ 1. Mã văn bản (nếu có): QD-69-TW, 264-QD-TW, TT-02-CAND, TT-02-BIEN-SOAN
198
+ 2. Từ khóa chính: kỷ luật, đảng viên, xử lý, hình thức, quy định
199
+ 3. Số điều/khoản (nếu có)
200
+
201
+ Trả về mỗi câu hỏi trên một dòng, không đánh số, không giải thích thêm.
202
+ Chỉ trả về các câu hỏi, không có tiêu đề hay format khác."""
203
+
204
+ response = llm_generator.generate_answer(
205
+ reformulation_prompt,
206
+ context=None,
207
+ documents=[]
208
+ )
209
+
210
+ if response:
211
+ # Parse response into list of queries
212
+ reformulated = [
213
+ line.strip()
214
+ for line in response.split('\n')
215
+ if line.strip() and not line.strip().startswith(('#', '-', '*', '1.', '2.', '3.'))
216
+ ]
217
+ # Filter out queries that are too similar to original or too short
218
+ reformulated = [
219
+ q for q in reformulated
220
+ if len(q) > 5 and q.lower() != query.lower()
221
+ ]
222
+ return reformulated[:5] # Limit to 5 reformulations
223
+ except Exception as e:
224
+ print(f"[Query Reformulation] ⚠️ LLM reformulation failed: {e}", flush=True)
225
+
226
+ return []
227
+
228
+
229
+ def suggest_query_improvements(query: str, intent: str, found_documents: int = 0) -> str:
230
+ """
231
+ Generate helpful suggestions for users when query is too difficult.
232
+
233
+ Args:
234
+ query: Original query string.
235
+ intent: Detected intent.
236
+ found_documents: Number of documents found.
237
+
238
+ Returns:
239
+ Suggestion message for user.
240
+ """
241
+ suggestions = []
242
+
243
+ if intent == "search_legal":
244
+ if found_documents == 0:
245
+ suggestions.append("• Thử sử dụng mã văn bản cụ thể (ví dụ: QD-69-TW, 264-QD-TW)")
246
+ suggestions.append("• Nhắc đến số điều/khoản nếu bạn biết (ví dụ: Điều 5, Khoản 2)")
247
+ suggestions.append("• Sử dụng từ khóa chính: kỷ luật, đảng viên, xử lý, hình thức")
248
+
249
+ # Check if query has document code
250
+ has_code = any(code in query.upper() for code in ["QD-69", "264-QD", "TT-02", "QUYET DINH 69", "QUYET DINH 264"])
251
+ if not has_code:
252
+ suggestions.append("• Thêm mã văn bản vào câu hỏi để tìm kiếm chính xác hơn")
253
+
254
+ elif intent == "search_fine":
255
+ if found_documents == 0:
256
+ suggestions.append("• Mô tả rõ loại vi phạm (ví dụ: vượt đèn đỏ, không đội mũ bảo hiểm)")
257
+ suggestions.append("• Sử dụng từ khóa: mức phạt, vi phạm, xử phạt")
258
+
259
+ elif intent == "search_procedure":
260
+ if found_documents == 0:
261
+ suggestions.append("• Nêu rõ tên thủ tục hành chính bạn cần")
262
+ suggestions.append("• Sử dụng từ khóa: thủ tục, hồ sơ, giấy tờ")
263
+
264
+ if suggestions:
265
+ return "\n".join(suggestions)
266
+
267
+ return "• Thử diễn đạt câu hỏi theo cách khác\n• Sử dụng từ khóa cụ thể hơn"
268
+
269
+