claude-code/claude-zh/skills/regex-vs-llm-structured-text/SKILL.md

199 lines
6.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
name: regex-vs-llm-structured-text
description: 解析結構化文字時,選擇使用正規表示式 (Regex) 或大型語言模型 (LLM) 的決策框架 — 优先使用 Regex僅針對低信心度的邊緣案例引入 LLM。
---
# 結構化文字解析Regex 與 LLM 之爭
這是一個在解析結構化文字(如測驗、表單、發票、文件)時的實踐決策框架。核心洞察在於:正規表示式 (Regex) 能以極低成本且具備確定性地處理 95-98% 的案例。應將昂貴的 LLM 呼叫保留給剩餘的邊緣案例 (Edge cases)。
## 何時啟用
- 解析包含重複模式的結構化文字(題目、表單、表格)。
- 在文字擷取任務中抉擇應使用 Regex 還是 LLM。
- 建構同時結合兩者優點的混合處理管線 (Hybrid Pipelines)。
- 優化文字處理過程中的成本與準確度權衡。
## 決策框架
```
文字格式是否具備一致性且重複出現?
├── 是 (>90% 遵循特定規律) → 優先使用 Regex
│ ├── Regex 能處理 95% 以上案例 → 完成,不需要 LLM
│ └── Regex 能處理比例 < 95% → 僅針對邊緣案例添加 LLM
└── 否 (非結構化、高度變動) → 直接使用 LLM
```
## 架構模式
```
原始文字內容
[Regex 解析器] ─── 擷取結構化數據 (95-98% 準確度)
[文字清理器] ─── 移除噪音(標記、頁碼、人工痕跡)
[信心度評分器] ─── 標記低信心度的擷取結果
├── 高信心度 (≥0.95) → 直接輸出
└── 低信心度 (<0.95) → [LLM 驗證器] → 最終輸出
```
## 實作範例
### 1. Regex 解析器 (處理絕大部分案例)
```python
import re
from dataclasses import dataclass
@dataclass(frozen=True)
class ParsedItem:
id: str
text: str
choices: tuple[str, ...]
answer: str
confidence: float = 1.0
def parse_structured_text(content: str) -> list[ParsedItem]:
"""使用 Regex 模式解析結構化文字。"""
pattern = re.compile(
r"(?P<id>\d+)\.\s*(?P<text>.+?)\n"
r"(?P<choices>(?:[A-D]\..+?\n)+)"
r"答案:\s*(?P<answer>[A-D])",
re.MULTILINE | re.DOTALL,
)
items = []
for match in pattern.finditer(content):
choices = tuple(
c.strip() for c in re.findall(r"[A-D]\.\s*(.+)", match.group("choices"))
)
items.append(ParsedItem(
id=match.group("id"),
text=match.group("text").strip(),
choices=choices,
answer=match.group("answer"),
))
return items
```
### 2. 信心度評分 (Confidence Scoring)
標記需要 LLM 介入審查的項目:
```python
@dataclass(frozen=True)
class ConfidenceFlag:
item_id: str
score: float
reasons: tuple[str, ...]
def score_confidence(item: ParsedItem) -> ConfidenceFlag:
"""評估擷取信心度並標記潛在問題。"""
reasons = []
score = 1.0
if len(item.choices) < 3:
reasons.append("選項過少")
score -= 0.3
if not item.answer:
reasons.append("缺少答案")
score -= 0.5
if len(item.text) < 10:
reasons.append("題目過短")
score -= 0.2
return ConfidenceFlag(
item_id=item.id,
score=max(0.0, score),
reasons=tuple(reasons),
)
```
### 3. LLM 驗證器 (僅針對邊緣案例)
```python
def validate_with_llm(
item: ParsedItem,
original_text: str,
client,
) -> ParsedItem:
"""利用 LLM 修正低信心度的擷取結果。"""
response = client.messages.create(
model="claude-haiku-4-5-20251001", # 選用最便宜的模型進行驗證
max_tokens=500,
messages=[{
"role": "user",
"content": (
f"請從以下文字中擷取問題、選項與答案。\n\n"
f"原始文字:{original_text}\n\n"
f"目前擷取結果:{item}\n\n"
f"如果需要請回傳修正後的 JSON若正確無誤請回傳 'CORRECT'。"
),
}],
)
# 解析 LLM 回應並回傳修正後的項目...
return corrected_item
```
### 4. 混合管線 (Hybrid Pipeline)
```python
def process_document(
content: str,
*,
llm_client=None,
confidence_threshold: float = 0.95,
) -> list[ParsedItem]:
"""完整管線Regex -> 信心度檢查 -> 針對邊緣案例使用 LLM。"""
# 步驟 1Regex 擷取 (處理 95-98% 的情況)
items = parse_structured_text(content)
# 步驟 2信心度評分
low_confidence = identify_low_confidence(items, confidence_threshold)
if not low_confidence or llm_client is None:
return items
# 步驟 3僅針對標記為低信心度的項目進行 LLM 驗證
result = []
for item in items:
if item.id in {f.item_id for f in low_confidence}:
result.append(validate_with_llm(item, content, llm_client))
else:
result.append(item)
return result
```
## 實踐之最佳實踐
- **從 Regex 開始**:即便是未臻完美的 Regex也能為你提供優化的基準線。
- **使用信心度評分**:透過程式化方式識別哪些部分真正需要 LLM 的協助。
- **選用最廉價的 LLM**:驗證任務通常使用輕量級模型(如 Haiku 系列)即已足夠。
- **不可變性 (Immutability)**:在清理或驗證步驟中始終回傳新的實例。
- **測試驅動開發 (TDD)**:優先為已知模式編寫測試,再逐步加入邊緣案例。
- **記錄指標**:追蹤 Regex 成功率與 LLM 呼叫次數,以監控管線的健康狀況。
## 應避免的反模式
- 在 Regex 能處理 95% 以上案例時,依然將所有文字傳送給 LLM既昂貴又緩慢
- 對於非結構化、變動極大的文字強行使用 Regex。
- 跳過信心度評估,一味寄望 Regex「總是有效」。
- 在清理或驗證過程中直接修改原始解析物件。
- 未測試邊緣案例(如格式錯誤的輸入、缺失欄位、編碼問題)。
## 適用情境
- 測驗/考試題目解析。
- 表單數據擷取。
- 發票/收據處理。
- 文件結構解析(標題、章節、表格)。
- 任何具有重複模式且對成本敏感的結構化文字處理。