minh-4T commited on
Commit
75f2cf3
·
1 Parent(s): 7ec7351

compile regex and multi-threaded

Browse files
Files changed (3) hide show
  1. core/qa_pipeline.py +11 -8
  2. core/rerank.py +8 -3
  3. core/text_utils.py +17 -7
core/qa_pipeline.py CHANGED
@@ -12,6 +12,7 @@ from .prompting import create_advanced_prompt
12
  from .retriever import HybridRetriever
13
  from .analyze_and_expand import analyze_and_expand_query
14
  from .llm_utils import safe_invoke, safe_stream
 
15
 
16
  logger = logging.getLogger(__name__)
17
 
@@ -315,22 +316,24 @@ def ask_ai_stream_delta(message: str, history: List, hybrid_retriever) -> Genera
315
  def fetch_docs(year_hint):
316
  docs_temp = []
317
  seen_temp = set()
318
- for query in queries:
 
319
  current_alpha = 0.4 if "CNTT" in query.upper() else 0.5
320
- retrieved = hybrid_retriever.search(
321
- query,
322
- k=TOP_K_RESULTS,
323
- alpha=current_alpha,
324
- year_scope=year_hint
325
- )
 
326
  for doc in retrieved:
 
327
  content_hash = hashlib.sha256(doc.page_content.encode("utf-8")).hexdigest()
328
  if content_hash not in seen_temp:
329
  docs_temp.append(doc)
330
  seen_temp.add(content_hash)
331
  return docs_temp
332
  # Tìm tài liệu
333
-
334
  # Cố gắng tìm tài liệu khớp chính xác với năm học người dùng nhắc đến
335
  all_docs = fetch_docs(year_scope_hint)
336
 
 
12
  from .retriever import HybridRetriever
13
  from .analyze_and_expand import analyze_and_expand_query
14
  from .llm_utils import safe_invoke, safe_stream
15
+ import concurrent.futures
16
 
17
  logger = logging.getLogger(__name__)
18
 
 
316
  def fetch_docs(year_hint):
317
  docs_temp = []
318
  seen_temp = set()
319
+
320
+ def single_search(query):
321
  current_alpha = 0.4 if "CNTT" in query.upper() else 0.5
322
+ return hybrid_retriever.search(query, k=TOP_K_RESULTS, alpha=current_alpha, year_scope=year_hint)
323
+
324
+ # Bắn đồng loạt các truy vấn cùng 1 lúc
325
+ with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:
326
+ results = executor.map(single_search, queries)
327
+
328
+ for retrieved in results:
329
  for doc in retrieved:
330
+ # Tối ưu: Dùng id của Qdrant (nếu có) hoặc hash nội dung
331
  content_hash = hashlib.sha256(doc.page_content.encode("utf-8")).hexdigest()
332
  if content_hash not in seen_temp:
333
  docs_temp.append(doc)
334
  seen_temp.add(content_hash)
335
  return docs_temp
336
  # Tìm tài liệu
 
337
  # Cố gắng tìm tài liệu khớp chính xác với năm học người dùng nhắc đến
338
  all_docs = fetch_docs(year_scope_hint)
339
 
core/rerank.py CHANGED
@@ -8,10 +8,15 @@ logger = logging.getLogger(__name__)
8
  def advanced_rerank(question: str, docs: List, top_k: int = 5) -> List:
9
  if not docs:
10
  return []
11
- logger.info("Đang rerank %s tài liệu với Cross-Encoder...", len(docs))
12
- pairs = [(question, (doc.page_content or "")[:MAX_RERANK_CHARS]) for doc in docs]
 
 
 
 
13
  scores = cross_encoder.predict(pairs, show_progress_bar=False)
14
- ranked = sorted(zip(scores, docs), key=lambda x: x[0], reverse=True)
 
15
  logger.info("Top 3 điểm: %s", [f"{s:.3f}" for s, _ in ranked[:3]])
16
  return [doc for score, doc in ranked[:top_k]]
17
 
 
8
  def advanced_rerank(question: str, docs: List, top_k: int = 5) -> List:
9
  if not docs:
10
  return []
11
+ MAX_DOCS_TO_RERANK = 15
12
+ pruned_docs = docs[:MAX_DOCS_TO_RERANK]
13
+
14
+ logger.info("Đang rerank %s tài liệu với Cross-Encoder...", len(pruned_docs))
15
+ pairs = [(question, (doc.page_content or "")[:MAX_RERANK_CHARS]) for doc in pruned_docs]
16
+
17
  scores = cross_encoder.predict(pairs, show_progress_bar=False)
18
+ ranked = sorted(zip(scores, pruned_docs), key=lambda x: x[0], reverse=True)
19
+
20
  logger.info("Top 3 điểm: %s", [f"{s:.3f}" for s, _ in ranked[:3]])
21
  return [doc for score, doc in ranked[:top_k]]
22
 
core/text_utils.py CHANGED
@@ -1,24 +1,34 @@
1
  import re
2
 
 
 
 
 
 
 
 
 
 
 
3
  def clean_text(text: str) -> str:
4
  if not text or not text.strip():
5
  return ""
6
 
7
  # Nối các từ bị gãy ngang do xuống dòng
8
- text = re.sub(r'(\w+)-\s*\n\s*(\w+)', r'\1\2', text)
9
 
10
  # \| và < > vào để bảo vệ khung Bảng Markdown và các Placeholder
11
- text = re.sub(r'[^\w\s\.,;:!?\-$$\"\'\À-ỹ\n\|<>]', ' ', text)
12
 
13
  # Chuẩn hóa khoảng trắng
14
- text = re.sub(r'[ \t]+', ' ', text)
15
- text = re.sub(r' +\n', '\n', text)
16
- text = re.sub(r'\n +', '\n', text)
17
 
18
  # Giới hạn tối đa 2 dòng trống liên tiếp
19
- text = re.sub(r'\n{3,}', '\n\n', text)
20
 
21
  # Sửa lỗi dư khoảng trắng trước dấu câu
22
- text = re.sub(r'\s+([.,;:!?])', r'\1', text)
23
 
24
  return text.strip()
 
1
  import re
2
 
3
+ #Compile regex patterns một lần toàn cục - tránh recompile mỗi lần gọi
4
+ _HYPHENATED_WORD_PATTERN = re.compile(r'(\w+)-\s*\n\s*(\w+)')
5
+ _INVALID_CHARS_PATTERN = re.compile(r'[^\w\s\.,;:!?\-$$\"\'\À-ỹ\n\|<>]')
6
+ _MULTIPLE_SPACES_PATTERN = re.compile(r'[ \t]+')
7
+ _SPACE_BEFORE_NEWLINE_PATTERN = re.compile(r' +\n')
8
+ _SPACE_AFTER_NEWLINE_PATTERN = re.compile(r'\n +')
9
+ _MULTIPLE_NEWLINES_PATTERN = re.compile(r'\n{3,}')
10
+ _SPACE_BEFORE_PUNCTUATION_PATTERN = re.compile(r'\s+([.,;:!?])')
11
+
12
+
13
  def clean_text(text: str) -> str:
14
  if not text or not text.strip():
15
  return ""
16
 
17
  # Nối các từ bị gãy ngang do xuống dòng
18
+ text = _HYPHENATED_WORD_PATTERN.sub(r'\1\2', text)
19
 
20
  # \| và < > vào để bảo vệ khung Bảng Markdown và các Placeholder
21
+ text = _INVALID_CHARS_PATTERN.sub(' ', text)
22
 
23
  # Chuẩn hóa khoảng trắng
24
+ text = _MULTIPLE_SPACES_PATTERN.sub(' ', text)
25
+ text = _SPACE_BEFORE_NEWLINE_PATTERN.sub('\n', text)
26
+ text = _SPACE_AFTER_NEWLINE_PATTERN.sub('\n', text)
27
 
28
  # Giới hạn tối đa 2 dòng trống liên tiếp
29
+ text = _MULTIPLE_NEWLINES_PATTERN.sub('\n\n', text)
30
 
31
  # Sửa lỗi dư khoảng trắng trước dấu câu
32
+ text = _SPACE_BEFORE_PUNCTUATION_PATTERN.sub(r'\1', text)
33
 
34
  return text.strip()