Spaces:
Sleeping
Sleeping
Upload app.py
Browse files
app.py
CHANGED
|
@@ -208,6 +208,49 @@ def extract_model_reply(full_text, prompt):
|
|
| 208 |
except Exception as e:
|
| 209 |
print(f"[extract_model_reply 錯誤] {e}")
|
| 210 |
return full_text.strip()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 211 |
|
| 212 |
def call_llm(messages: List[dict], model: str, logs: List[str]) -> dict:
|
| 213 |
"""
|
|
@@ -244,15 +287,29 @@ def call_llm(messages: List[dict], model: str, logs: List[str]) -> dict:
|
|
| 244 |
print("torch.no_grad")
|
| 245 |
# 解碼生成內容後
|
| 246 |
full_text = _hf_tok.decode(out_ids[0], skip_special_tokens=True)
|
| 247 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 248 |
logs.append(f"[LOCAL LLM] raw_len={len(gen_text)}")
|
| 249 |
logs.append(f"[LOCAL LLM] gen_text={gen_text}")
|
| 250 |
logs.append(f"[LOCAL LLM] prompt={prompt}")
|
| 251 |
logs.append(f"[LOCAL LLM] full_text={full_text}")
|
| 252 |
-
|
| 253 |
-
|
| 254 |
-
|
| 255 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 256 |
return data
|
| 257 |
except Exception as e:
|
| 258 |
logs.append(f"[LOCAL LLM] JSON 解析失敗:{e}")
|
|
|
|
| 208 |
except Exception as e:
|
| 209 |
print(f"[extract_model_reply 錯誤] {e}")
|
| 210 |
return full_text.strip()
|
| 211 |
+
|
| 212 |
+
# === 放在 safe_parse_json 之後:用「正則」擷取 full_text 中最後一個完整 JSON 物件 ===
|
| 213 |
+
try:
|
| 214 |
+
import regex as re2 # 第三方 regex,支援遞迴 (?R)
|
| 215 |
+
except Exception:
|
| 216 |
+
re2 = None
|
| 217 |
+
|
| 218 |
+
def extract_last_json_block(text: str) -> Optional[str]:
|
| 219 |
+
"""
|
| 220 |
+
以 regex 擷取最後一個平衡的大括號 JSON 物件:
|
| 221 |
+
- 優先使用第三方 `regex` 的遞迴 (?R) 來比對平衡大括號
|
| 222 |
+
- 若無法使用 `regex`,改用手動堆疊法做 fallback
|
| 223 |
+
回傳:最後一個 JSON 物件字串;若找不到回傳 None
|
| 224 |
+
"""
|
| 225 |
+
try:
|
| 226 |
+
s = _strip_code_fences(text)
|
| 227 |
+
|
| 228 |
+
# 1) 使用 regex (?R) 遞迴:{\n ... { ... } ... \n}
|
| 229 |
+
if re2 is not None:
|
| 230 |
+
pattern = re2.compile(r"\{(?:[^{}]|(?R))*\}", flags=re2.DOTALL)
|
| 231 |
+
matches = [m.group(0) for m in pattern.finditer(s)]
|
| 232 |
+
return matches[-1] if matches else None
|
| 233 |
+
|
| 234 |
+
# 2) 無 regex 模組 → 手動掃描平衡大括號
|
| 235 |
+
blocks = []
|
| 236 |
+
depth = 0
|
| 237 |
+
start = None
|
| 238 |
+
for i, ch in enumerate(s):
|
| 239 |
+
if ch == "{":
|
| 240 |
+
if depth == 0:
|
| 241 |
+
start = i
|
| 242 |
+
depth += 1
|
| 243 |
+
elif ch == "}":
|
| 244 |
+
if depth > 0:
|
| 245 |
+
depth -= 1
|
| 246 |
+
if depth == 0 and start is not None:
|
| 247 |
+
blocks.append(s[start:i+1])
|
| 248 |
+
start = None
|
| 249 |
+
return blocks[-1] if blocks else None
|
| 250 |
+
except Exception as e:
|
| 251 |
+
print(f"[JSON-EXTRACT][ERROR] {e}")
|
| 252 |
+
return None
|
| 253 |
+
|
| 254 |
|
| 255 |
def call_llm(messages: List[dict], model: str, logs: List[str]) -> dict:
|
| 256 |
"""
|
|
|
|
| 287 |
print("torch.no_grad")
|
| 288 |
# 解碼生成內容後
|
| 289 |
full_text = _hf_tok.decode(out_ids[0], skip_special_tokens=True)
|
| 290 |
+
|
| 291 |
+
|
| 292 |
+
|
| 293 |
+
# ★ 使用 regex/堆疊法:從 full_text 擷取「最後一個」完整 JSON 物件
|
| 294 |
+
candidate = extract_last_json_block(full_text)
|
| 295 |
+
gen_text = candidate if candidate is not None else full_text # 若找不到就用原文(後續 safe_parse_json 仍會嘗試)
|
| 296 |
logs.append(f"[LOCAL LLM] raw_len={len(gen_text)}")
|
| 297 |
logs.append(f"[LOCAL LLM] gen_text={gen_text}")
|
| 298 |
logs.append(f"[LOCAL LLM] prompt={prompt}")
|
| 299 |
logs.append(f"[LOCAL LLM] full_text={full_text}")
|
| 300 |
+
# 強韌解析
|
| 301 |
+
try:
|
| 302 |
+
data = safe_parse_json(gen_text)
|
| 303 |
+
logs.append("[LOCAL LLM] JSON 解析成功")
|
| 304 |
+
return data
|
| 305 |
+
except Exception as jerr:
|
| 306 |
+
logs.append(f"[LOCAL LLM] JSON 解析失敗:{jerr}")
|
| 307 |
+
return {
|
| 308 |
+
"符合情況": "部分符合",
|
| 309 |
+
"原因": [f"模型輸出非合法 JSON:{str(jerr)}"],
|
| 310 |
+
"改進建議": ["請調整提示詞,要求嚴格輸出 JSON(雙引號、無註解、無多餘文字)。"],
|
| 311 |
+
"規則逐點檢核": []
|
| 312 |
+
}
|
| 313 |
return data
|
| 314 |
except Exception as e:
|
| 315 |
logs.append(f"[LOCAL LLM] JSON 解析失敗:{e}")
|