davidtran999 commited on
Commit
3969e44
·
verified ·
1 Parent(s): 4ecab36

Upload backend/hue_portal/chatbot/chatbot.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. backend/hue_portal/chatbot/chatbot.py +109 -24
backend/hue_portal/chatbot/chatbot.py CHANGED
@@ -13,7 +13,7 @@ from hue_portal.core.chatbot import Chatbot as CoreChatbot, get_chatbot as get_c
13
  from hue_portal.chatbot.router import decide_route, IntentRoute, RouteDecision, DOCUMENT_CODE_PATTERNS
14
  from hue_portal.chatbot.context_manager import ConversationContext
15
  from hue_portal.chatbot.llm_integration import LLMGenerator
16
- from hue_portal.core.models import LegalSection
17
  from hue_portal.chatbot.exact_match_cache import ExactMatchCache
18
  from hue_portal.chatbot.slow_path_handler import SlowPathHandler
19
 
@@ -172,33 +172,118 @@ class Chatbot(CoreChatbot):
172
  # - Nếu user chưa chọn và không có mã trong query → bật wizard để user chọn
173
  # - Nếu có mã trong query → không bật wizard, đi thẳng vào slow_path
174
  if intent == "search_legal" and not selected_doc_code and not has_doc_code_in_query:
175
- print("[WIZARD] ✅ Chatbot layer wizard triggered, returning options")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
176
  intro_message = (
177
  "Tôi tìm thấy một số nhóm văn bản có thể liên quan đến câu hỏi của bạn.\n\n"
178
  "Bạn hãy chọn văn bản muốn tra cứu trước, sau đó tôi sẽ trả lời chi tiết hơn:"
179
  )
180
- clarification_options = [
181
- {
182
- "code": "264-QD-TW",
183
- "title": "Quyết định 264-QĐ/TW về kỷ luật đảng viên",
184
- "reason": "Quy định chung về xử lý kỷ luật đối với đảng viên vi phạm.",
185
- },
186
- {
187
- "code": "QD-69-TW",
188
- "title": "Quy định 69-QĐ/TW về kỷ luật tổ chức đảng, đảng viên",
189
- "reason": "Quy định chi tiết về các hành vi vi phạm và hình thức kỷ luật.",
190
- },
191
- {
192
- "code": "TT-02-CAND",
193
- "title": "Thông tư 02/2021/TT-BCA về điều lệnh CAND",
194
- "reason": "Quy định về điều lệnh, lễ tiết, tác phong trong CAND.",
195
- },
196
- {
197
- "code": "__other__",
198
- "title": "Khác",
199
- "reason": "Tôi muốn hỏi văn bản hoặc ch�� đề pháp luật khác.",
200
- },
201
- ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
202
  response = {
203
  "message": intro_message,
204
  "intent": intent,
 
13
  from hue_portal.chatbot.router import decide_route, IntentRoute, RouteDecision, DOCUMENT_CODE_PATTERNS
14
  from hue_portal.chatbot.context_manager import ConversationContext
15
  from hue_portal.chatbot.llm_integration import LLMGenerator
16
+ from hue_portal.core.models import LegalSection, LegalDocument
17
  from hue_portal.chatbot.exact_match_cache import ExactMatchCache
18
  from hue_portal.chatbot.slow_path_handler import SlowPathHandler
19
 
 
172
  # - Nếu user chưa chọn và không có mã trong query → bật wizard để user chọn
173
  # - Nếu có mã trong query → không bật wizard, đi thẳng vào slow_path
174
  if intent == "search_legal" and not selected_doc_code and not has_doc_code_in_query:
175
+ print("[WIZARD] ✅ Chatbot layer wizard triggered, using AI to generate options")
176
+ # Load canonical documents từ DB
177
+ canonical_candidates = []
178
+ try:
179
+ canonical_docs = list(
180
+ LegalDocument.objects.filter(
181
+ code__in=["264-QD-TW", "QD-69-TW", "TT-02-CAND"]
182
+ )
183
+ )
184
+ for doc in canonical_docs:
185
+ summary = getattr(doc, "summary", "") or ""
186
+ metadata = getattr(doc, "metadata", {}) or {}
187
+ if not summary and isinstance(metadata, dict):
188
+ summary = metadata.get("summary", "")
189
+ canonical_candidates.append(
190
+ {
191
+ "code": doc.code,
192
+ "title": getattr(doc, "title", "") or doc.code,
193
+ "summary": summary,
194
+ "doc_type": getattr(doc, "doc_type", "") or "",
195
+ "section_title": "",
196
+ }
197
+ )
198
+ except Exception as exc:
199
+ logger.warning("[WIZARD] Failed to load canonical documents: %s", exc)
200
+
201
+ # Fallback nếu không load được từ DB
202
+ if not canonical_candidates:
203
+ canonical_candidates = [
204
+ {
205
+ "code": "264-QD-TW",
206
+ "title": "Quyết định 264-QĐ/TW về kỷ luật đảng viên",
207
+ "summary": "Quy định chung về xử lý kỷ luật đối với đảng viên vi phạm.",
208
+ "doc_type": "",
209
+ "section_title": "",
210
+ },
211
+ {
212
+ "code": "QD-69-TW",
213
+ "title": "Quy định 69-QĐ/TW về kỷ luật tổ chức đảng, đảng viên",
214
+ "summary": "Quy định chi tiết về các hành vi vi phạm và hình thức kỷ luật.",
215
+ "doc_type": "",
216
+ "section_title": "",
217
+ },
218
+ {
219
+ "code": "TT-02-CAND",
220
+ "title": "Thông tư 02/2021/TT-BCA về điều lệnh CAND",
221
+ "summary": "Quy định về điều lệnh, lễ tiết, tác phong trong CAND.",
222
+ "doc_type": "",
223
+ "section_title": "",
224
+ },
225
+ ]
226
+
227
+ # Dùng LLM để đề xuất options dựa trên câu hỏi
228
+ clarification_options = []
229
  intro_message = (
230
  "Tôi tìm thấy một số nhóm văn bản có thể liên quan đến câu hỏi của bạn.\n\n"
231
  "Bạn hãy chọn văn bản muốn tra cứu trước, sau đó tôi sẽ trả lời chi tiết hơn:"
232
  )
233
+
234
+ if self.llm_generator:
235
+ try:
236
+ llm_payload = self.llm_generator.suggest_clarification_topics(
237
+ query,
238
+ canonical_candidates,
239
+ max_options=3,
240
+ )
241
+ if llm_payload:
242
+ intro_message = llm_payload.get("message") or intro_message
243
+ raw_options = llm_payload.get("options")
244
+ if isinstance(raw_options, list) and len(raw_options) > 0:
245
+ clarification_options = [
246
+ {
247
+ "code": (opt.get("code") or candidate.get("code", "")).upper(),
248
+ "title": opt.get("title") or opt.get("document_title") or candidate.get("title", ""),
249
+ "reason": opt.get("reason")
250
+ or opt.get("summary")
251
+ or candidate.get("summary")
252
+ or candidate.get("section_title")
253
+ or "",
254
+ }
255
+ for opt, candidate in zip(
256
+ raw_options,
257
+ canonical_candidates[: len(raw_options)],
258
+ )
259
+ if (opt.get("code") or candidate.get("code"))
260
+ and (opt.get("title") or opt.get("document_title") or candidate.get("title"))
261
+ ]
262
+ print(f"[WIZARD] ✅ LLM generated {len(clarification_options)} options")
263
+ except Exception as exc:
264
+ logger.warning("[WIZARD] LLM suggestion failed: %s, using fallback", exc)
265
+
266
+ # Fallback nếu LLM không trả về options hợp lệ
267
+ if not clarification_options:
268
+ clarification_options = [
269
+ {
270
+ "code": candidate["code"].upper(),
271
+ "title": candidate["title"],
272
+ "reason": candidate.get("summary") or candidate.get("section_title") or "",
273
+ }
274
+ for candidate in canonical_candidates[:3]
275
+ ]
276
+ print("[WIZARD] Using fallback options (LLM unavailable or failed)")
277
+
278
+ # Thêm option "Khác" nếu chưa có
279
+ if not any(opt.get("code") == "__other__" for opt in clarification_options):
280
+ clarification_options.append(
281
+ {
282
+ "code": "__other__",
283
+ "title": "Khác",
284
+ "reason": "Tôi muốn hỏi văn bản hoặc chủ đề pháp luật khác.",
285
+ }
286
+ )
287
  response = {
288
  "message": intro_message,
289
  "intent": intent,