fix reranking error
Browse files- app/reranker.py +35 -22
app/reranker.py
CHANGED
|
@@ -143,12 +143,17 @@ class Reranker:
|
|
| 143 |
content = (doc.get("fullcontent") or "").strip()
|
| 144 |
docs_content.append(f"{i+1}. {content}")
|
| 145 |
|
|
|
|
| 146 |
batch_prompt = (
|
| 147 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 148 |
f"Câu hỏi: {query}\n\n"
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
f"Ví dụ: 8,5,7,3,9"
|
| 152 |
)
|
| 153 |
|
| 154 |
try:
|
|
@@ -162,31 +167,38 @@ class Reranker:
|
|
| 162 |
)
|
| 163 |
logger.info(f"[RERANK] Got batch scores from Gemini: {response}")
|
| 164 |
|
| 165 |
-
# --- START: Cải thiện logic trích xuất điểm ---
|
| 166 |
scores_text = str(response).strip()
|
| 167 |
scores_line = ""
|
| 168 |
score_strings = []
|
| 169 |
|
| 170 |
-
#
|
| 171 |
-
|
| 172 |
-
|
| 173 |
-
|
| 174 |
-
|
| 175 |
-
)
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
|
| 179 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 180 |
)
|
| 181 |
-
else:
|
| 182 |
-
# Fallback: tìm dòng cuối cùng chỉ chứa số, dấu phẩy, và khoảng trắng
|
| 183 |
-
lines = scores_text.split("\n")
|
| 184 |
for line in reversed(lines):
|
| 185 |
line = line.strip()
|
| 186 |
-
|
| 187 |
-
|
|
|
|
| 188 |
logger.debug(
|
| 189 |
-
f"[RERANK] Found scores line using
|
| 190 |
)
|
| 191 |
break
|
| 192 |
|
|
@@ -194,11 +206,12 @@ class Reranker:
|
|
| 194 |
# Trích xuất tất cả các số từ dòng đã tìm thấy
|
| 195 |
score_strings = re.findall(r"\b\d+(?:\.\d+)?\b", scores_line)
|
| 196 |
else:
|
|
|
|
| 197 |
logger.warning(
|
| 198 |
"[RERANK] Could not find a dedicated score line. Falling back to parsing all numbers from response."
|
| 199 |
)
|
| 200 |
score_strings = re.findall(r"\b\d+(?:\.\d+)?\b", scores_text)
|
| 201 |
-
# --- END: Cải thiện logic trích xuất điểm ---
|
| 202 |
|
| 203 |
scores = []
|
| 204 |
for s in score_strings:
|
|
|
|
| 143 |
content = (doc.get("fullcontent") or "").strip()
|
| 144 |
docs_content.append(f"{i+1}. {content}")
|
| 145 |
|
| 146 |
+
# Sửa: Prompt được làm chặt chẽ hơn để yêu cầu LLM chỉ trả về điểm số.
|
| 147 |
batch_prompt = (
|
| 148 |
+
"Bạn là một hệ thống đánh giá. Đánh giá mức độ liên quan giữa câu hỏi và các đoạn luật được đánh số sau đây.\n"
|
| 149 |
+
"QUY TẮC:\n"
|
| 150 |
+
"1. Chỉ trả về MỘT DÒNG DUY NHẤT.\n"
|
| 151 |
+
"2. Dòng đó CHỈ chứa danh sách các điểm số (từ 0 đến 10), mỗi điểm tương ứng với một đoạn luật.\n"
|
| 152 |
+
"3. Các điểm số phải được phân cách bởi dấu phẩy.\n"
|
| 153 |
+
"4. KHÔNG giải thích, KHÔNG định dạng markdown, KHÔNG thêm bất kỳ văn bản nào khác.\n\n"
|
| 154 |
f"Câu hỏi: {query}\n\n"
|
| 155 |
+
"Các đoạn luật:\n" + "\n".join(docs_content) + "\n\n"
|
| 156 |
+
"ĐIỂM SỐ:"
|
|
|
|
| 157 |
)
|
| 158 |
|
| 159 |
try:
|
|
|
|
| 167 |
)
|
| 168 |
logger.info(f"[RERANK] Got batch scores from Gemini: {response}")
|
| 169 |
|
| 170 |
+
# --- START: Cải thiện logic trích xuất điểm (Sửa lỗi) ---
|
| 171 |
scores_text = str(response).strip()
|
| 172 |
scores_line = ""
|
| 173 |
score_strings = []
|
| 174 |
|
| 175 |
+
# Tách response thành các dòng
|
| 176 |
+
lines = scores_text.split("\n")
|
| 177 |
+
|
| 178 |
+
# Ưu tiên 1: Tìm dòng cuối cùng chỉ chứa số, dấu phẩy, khoảng trắng.
|
| 179 |
+
# Đây là trường hợp lý tưởng khi LLM tuân thủ prompt nghiêm ngặt.
|
| 180 |
+
for line in reversed(lines):
|
| 181 |
+
line = line.strip()
|
| 182 |
+
if line and re.fullmatch(r"[0-9.,\s]+", line):
|
| 183 |
+
scores_line = line
|
| 184 |
+
logger.debug(
|
| 185 |
+
f"[RERANK] Found pure score line (best case): '{scores_line}'"
|
| 186 |
+
)
|
| 187 |
+
break
|
| 188 |
+
|
| 189 |
+
# Ưu tiên 2: Nếu không tìm thấy, tìm dòng có chứa keyword và điểm số.
|
| 190 |
+
# Regex này linh hoạt hơn để xử lý markdown và các biến thể keyword.
|
| 191 |
+
if not scores_line:
|
| 192 |
+
keyword_regex = (
|
| 193 |
+
r"(?i)(?:Kết quả|Scores|Trả về|Điểm số)[\s\*:]*([0-9.,\s]+)$"
|
| 194 |
)
|
|
|
|
|
|
|
|
|
|
| 195 |
for line in reversed(lines):
|
| 196 |
line = line.strip()
|
| 197 |
+
match = re.search(keyword_regex, line)
|
| 198 |
+
if match:
|
| 199 |
+
scores_line = match.group(1).strip()
|
| 200 |
logger.debug(
|
| 201 |
+
f"[RERANK] Found scores line using keyword regex: '{scores_line}'"
|
| 202 |
)
|
| 203 |
break
|
| 204 |
|
|
|
|
| 206 |
# Trích xuất tất cả các số từ dòng đã tìm thấy
|
| 207 |
score_strings = re.findall(r"\b\d+(?:\.\d+)?\b", scores_line)
|
| 208 |
else:
|
| 209 |
+
# Fallback cuối cùng: tìm số trong toàn bộ response nếu các phương pháp trên thất bại.
|
| 210 |
logger.warning(
|
| 211 |
"[RERANK] Could not find a dedicated score line. Falling back to parsing all numbers from response."
|
| 212 |
)
|
| 213 |
score_strings = re.findall(r"\b\d+(?:\.\d+)?\b", scores_text)
|
| 214 |
+
# --- END: Cải thiện logic trích xuất điểm (Sửa lỗi) ---
|
| 215 |
|
| 216 |
scores = []
|
| 217 |
for s in score_strings:
|