howard9963 commited on
Commit
dde2f3c
·
verified ·
1 Parent(s): cfaf4a9

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +62 -5
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
- gen_text = extract_model_reply(full_text, prompt)
 
 
 
 
 
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
- data = safe_parse_json(full_text)
255
- logs.append("[LOCAL LLM] JSON 解析成功")
 
 
 
 
 
 
 
 
 
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}")