tw-legal-rag 詳細教學 — Taiwan Legal RAG CLI
Open-source CLI for semantic Taiwan legal judgment retrieval。由法律偵探(Dr.Lawbot)建置 22M+ 台灣裁判語義檢索後端 → 開源 CLI 接 retrieval-only endpoint → 打包 bundle 交給你自己的 AI → 對 AI 答案做 bundle 層級引用檢查。
1. 專案定位
1.1 它是什麼
twlegalrag 是一個 retrieval-only 的 Python CLI 工具,做三件事:
- search — 用自然語言查 ~22M 筆台灣裁判書(hybrid / keyword / phrase 三種模式)
- pack — 把檢索結果打包成
bundle.json,含 stable citation_id(J1, J2, …)、判決理由全文片段(excerpt)、verification_instructions - check — 對 AI 產生的答案做 bundle 層級 字串檢查(引用是否在 bundle 內、引文是否出現在 bundle 文字某處)
1.2 它不是什麼
- ❌ 不呼叫 LLM(無 OpenAI / Anthropic / Google SDK 依賴)
- ❌ 不生成法律意見(不背書任何模型輸出)
- ❌ 不做語義 faithfulness 驗證(不能判斷見解讀對 / paraphrase 幻覺 / 當事人主張被當成法院見解)
- ❌ 不開源判決庫 / embedding / 向量索引(後端 TLR 服務私有,本 CLI 只是 client)
1.3 跟一般關鍵字搜尋差在哪
| 維度 | 司法院判決搜尋 | tw-legal-rag |
|---|---|---|
| 查詢方式 | 案號 / 法院 / 關鍵字 | 自然語言(語義模糊匹配) |
| 後端規模 | 全資料庫但無語義 | 22M+ 經結構化 + 向量化 |
| 引用檢查 | 無 | bundle 層級保守檢查 |
| AI 整合 | 無 | bundle 設計給任意 LLM 用 |
1.4 使用情境
- 律師助理:先用 CLI 找出相關判決 → bundle 丟給 ChatGPT 整理見解 →
check驗 ChatGPT 沒有捏造判決字號 - 學術研究:批次檢索某類型案件 → 帶 bundle 到本地 LLM 做主題分析
- 內部知識管理:retrieval-only 設計避免合規風險,模型輸出責任在使用者
2. 安裝指南
2.1 環境需求
- Python ≥ 3.9(官方測過 3.9 / 3.10 / 3.11 / 3.12)
- 網路可達
https://tlr.dr-lawbot.com - 不需任何 LLM API key
2.2 標準安裝
1pip install twlegalrag
只裝三個套件:httpx>=0.27 / typer>=0.12 / rich>=13.7。
2.3 開發模式(從 source)
1git clone https://github.com/aa0101181514/tw-legal-rag
2cd tw-legal-rag
3pip install -e ".[dev]"
4pytest # 跑 offline tests(無網路依賴)
2.4 驗證安裝
1twlegalrag --version # 顯示 twlegalrag 0.1.0
2twlegalrag health # 檢查 TLR 後端可達
health 命令會 GET https://tlr.dr-lawbot.com/v1/health,回 panel 顯示 status: ok / retrieval: ok。若紅框就是後端不可達或 kill switch 開啟(HTTP 503)。
2.5 設定 API key(選用)
預設 authless。若服務方發給你 key:
1# 方式 A:環境變數(推薦)
2export TWLEGALRAG_TLR_API_KEY=your_key_here
3
4# 方式 B:config 檔(git-ignored)
5mkdir -p ~/.twlegalrag
6cat > ~/.twlegalrag/config.toml <<'EOF'
7[tlr]
8api_key = "your_key_here"
9EOF
3. 核心架構解析
3.1 模組關係圖
flowchart TD
USER["使用者 / CLI 呼叫"]
CLI["twlegalrag/cli.py
(typer app)"]
CONFIG["twlegalrag/config.py
env vars + ~/.twlegalrag/config.toml"]
RETR["twlegalrag/retrieval.py
TLRClient (httpx)"]
BUNDLE["twlegalrag/bundle.py
build_bundle()"]
VERIFY["twlegalrag/verify.py
citation_check()"]
FAITHFUL["twlegalrag/faithful/
VENDORED 純函式快照
citation_utils + verifier"]
TLR_API["TLR 後端 (private)
tlr.dr-lawbot.com
/v1/search /v1/fulltext /v1/health"]
USER --> CLI
CLI --> CONFIG
CLI --> RETR
CLI --> BUNDLE
CLI --> VERIFY
RETR -->|httpx POST| TLR_API
VERIFY --> FAITHFUL
BUNDLE -->|Judgment dataclass| RETR
3.2 資料流(pack 主流程)
flowchart LR
Q["自然語言問題
例: 車禍對方全責能求償什麼?"]
S["search()
POST /v1/search
→ Layer-1 listing + result_token"]
F["fetch_fulltext()
POST /v1/fulltext
→ 判決理由 excerpt"]
B["build_bundle()
citation_id=J1..Jn
+ verification_instructions"]
O["bundle.json"]
AI["你的 LLM
(ChatGPT/Claude/Gemini)"]
ANS["AI 答案"]
C["check()
bundle 層級引用驗證"]
Q --> S --> F --> B --> O
O --> AI --> ANS
O --> C
ANS --> C
3.3 重要設計決策
- strict=False JSON 解析(
retrieval.py:69-74)— TLR 回傳的判決文字含全形空白與未跳脫換行,嚴格 JSON 解析會拒收。CLI 用json.loads(text, strict=False)容忍,這也是 OpenAI Actions 層常見的失敗點之一。 - result_token 重用 —
/v1/search回單一 token 編碼整個結果集;/v1/fulltext必須帶原 token 才取得對應 excerpt。 - VENDORED 快照邊界(
faithful/VENDORED.md)—twlegalrag/faithful/是法律偵探內部程式的純函式快照。檔案內含check_party_as_court/run_all_checks等函式,CLI 並沒有用到。這是有意保留以追蹤上游版本,但措辭明確警告「檔案清單 ≠ 功能清單」。 - 保守判定 —
verify.py設計上「不確定回needs_review而非fail」,壓低誤報率(README §citation check 如何運作)。 - per-judgment excerpt 上限 6000 字元(
bundle.py:21)— 控制 bundle 大小落在主流 LLM context window 內。
3.4 三個輸出狀態
| 狀態 | 意義 | 處置建議 |
|---|---|---|
🟢 pass | 引用字號身份與 bundle 對得上 | 仍須讀判決全文驗見解 |
🟡 needs_review | 識別線索不足或部分匹配 | 人工介入 |
🔴 fail | 引用了不在 bundle 的字號 / 引文整段不存在於 bundle | 高度疑似捏造,不可採信 |
4. Helper Scripts 詳細用法
本 repo 沒有額外的 helper scripts,所有功能都透過 twlegalrag 這個 console script 統一入口。下列為四個子命令的完整用法。
4.1 twlegalrag search — 純檢索
1twlegalrag search "勞資 加班費" # 預設 5 筆,hybrid 模式
2twlegalrag search "車禍" -n 10 # 取 10 筆(server cap=10)
3twlegalrag search "侵權" --type keyword # 切到 keyword-only
4twlegalrag search "侵權" --type phrase # 切到 phrase(精確)
5twlegalrag search "侵權" --read # 同步抓判決理由全文片段
回 rich.Table,欄位:# / 字號 / 摘要(含 --read 時加「全文字數」)。
4.2 twlegalrag pack — 打包 bundle ★主流程
1# 預設:印 JSON 到 stdout,AI USE NOTICE 印到 stderr
2twlegalrag pack "車禍對方全責,我可以求償什麼?"
3
4# 推薦:寫檔,stderr 顯示寫入摘要
5twlegalrag pack "車禍對方全責" -o bundle.json
6
7# 控制 fulltext 抓取深度(省 server 流量)
8twlegalrag pack "車禍對方全責" -o bundle.json --read-top 3 # 只抓前 3 筆全文
bundle.json 結構(簡化):
1{
2 "schema": "twlegalrag.bundle/v1",
3 "query": "...",
4 "source": "Taiwan Legal RAG (TLR) retrieval endpoint",
5 "retrieval_only": true,
6 "allowed_citations": ["J1", "J2", "J3"],
7 "judgments": [
8 {
9 "citation_id": "J1",
10 "doc_id": "...",
11 "citation_text": "最高法院 100 年度台上字第 1 號",
12 "citation_url": "https://dr-lawbot.com/...",
13 "fulltext_excerpt": "...",
14 "warning": "Use only the court's reasoning as authority..."
15 }
16 ],
17 "verification_instructions": {
18 "required": true,
19 "rules": ["Only cite judgments included in this bundle.", "..."]
20 }
21}
4.3 twlegalrag check — bundle 層級引用檢查
1# 把 AI 答案存成文字檔
2cat > answer.txt <<EOF
3根據最高法院 100 年度台上字第 1 號判決,車禍全責者應賠償...
4EOF
5
6# 對 bundle 跑檢查
7twlegalrag check bundle.json answer.txt
輸出三個區塊:
- 整體 panel —
pass / needs_review / fail+ 引用統計(總數 / 在 bundle 內 / 不在 bundle) - 每筆引用 verdict 表 — 狀態 / 引用字號 / 對應判決 / 原因
- bundle 引文存在性檢查 — 「答案宣稱『法院說…』的逐字句,是否出現在 bundle 任一篇文字裡」
4.4 twlegalrag health — 後端健康檢查
1twlegalrag health
2# → status: ok / retrieval: ok (綠框)
3# → status: degraded(紅框)→ 後端有問題或 kill switch 開
4.5 環境變數一覽
| 變數 | 預設 | 用途 |
|---|---|---|
TWLEGALRAG_TLR_BASE_URL | https://tlr.dr-lawbot.com | 切換後端 endpoint(測試 / staging) |
TWLEGALRAG_TLR_API_KEY | 無 | 選用 Bearer token |
TWLEGALRAG_HOME | ~/.twlegalrag | config 檔目錄(CI / 容器友善) |
5. 應用場景
5.1 律師事務所內部工作流
1# Step 1:助理檢索
2twlegalrag pack "員工 LINE 群洩漏營業秘密 損害賠償" -o case_001.json --read-top 5
3
4# Step 2:丟給律師慣用 LLM
5# - Claude Desktop:把 case_001.json 拖進對話框
6# - ChatGPT:上傳檔案 + prompt「請只引用 bundle 內的判決」
7
8# Step 3:律師核對
9twlegalrag check case_001.json llm_answer.txt
5.2 學術研究批次
1for topic in "勞動契約終止" "競業禁止" "資遣費計算"; do
2 twlegalrag pack "$topic" -n 10 -o "research/${topic}.json"
3done
5.3 整合進 Claude Desktop(Remote MCP,免 CLI)
README §「其他接法」明確支援:Claude Desktop → Connectors → Add custom connector → URL =
https://tlr.dr-lawbot.com/mcp(免 OAuth、免 API key)。
5.4 整合進 ChatGPT Custom GPT Action
Actions → import URL =
https://tlr.dr-lawbot.com/openapi.yaml,認證選 None。
6. 資安掃描報告
6.1 自動化掃描結果
對 twlegalrag/ + tests/ 跑 grep pattern(eval|exec|os.system|subprocess|shell=True|pickle|__import__|input(|secret|token|password|api_key):
- 無
eval/exec/os.system/subprocess/shell=True - 無
pickle/__import__動態載入 - 無硬編碼 secret / password
api_key/token只出現在合法的 config 讀取與 Bearer header 組裝
6.2 紅黃綠燈總評
| 風險面向 | 等級 | 說明 |
|---|---|---|
| 程式碼執行注入 | 🟢 低 | 無 eval/exec/shell,純 httpx + dataclass |
| Secret 管理 | 🟢 低 | API key 走 env var / git-ignored config,README 明示「切勿 commit」 |
| 外部網路請求 | 🟡 中 | 全部請求僅打 tlr.dr-lawbot.com(白名單單一 endpoint),但仍為第三方服務 |
| 隱私洩漏 | 🟡 中 | README 已揭露「TLR 後端會以明文記錄查詢字串、時間、IP 中介資料、結果筆數供檢索品質分析」。勿送個人機密或保密事實。明示不用於訓練生成模型 |
| 依賴鏈 | 🟢 低 | 只依賴 httpx / typer / rich 三個成熟套件,無 LLM SDK / pickle / yaml 等高風險庫 |
| 反序列化 | 🟢 低 | 只用 json.loads(strict=False)(控制字元容忍)+ tomllib.load(標準庫),無 pickle / yaml.unsafe_load |
| Rate limit / DoS | 🟢 低 | 內建 max_retries=2 + exponential backoff,HTTP 429 / 503 有明確錯誤訊息 |
| Supply chain | 🟢 低 | v0.1.0 PyPI 用 trusted-publishing(GitHub Actions OIDC),無 secret manual upload |
總評:🟢 低風險。設計上嚴守 retrieval-only 邊界,secret 管理規範清楚,掃描結果無高危模式。
6.3 使用前注意事項
- 隱私警告(README 已揭露但需重申):送出去的查詢字串會以明文進入 TLR 後端日誌。涉及客戶機密 / 個資的查詢請改寫成抽象化問題(如:「員工 LINE 群洩密 損害賠償」而非「王小明在 ABC 公司 LINE 群洩漏…」)。
- API key 配置:若拿到 key 一律放 env var 或
~/.twlegalrag/config.toml,切勿 commit 到 git 或寫死在 script 內。 - TLR 服務治理:後端 kill switch(HTTP 503)由服務方控制;商業用途請與 dr-lawbot.com 確認 SLA。
- 下游 LLM 責任:本工具完全不背書下游 LLM 的輸出。即使
check回pass也只代表「引用字號身份對得上」,不代表「法律推論正確」。
7. FAQ
Q1:為什麼不直接讓 CLI 呼叫 LLM 一次到位? A:為了把責任邊界畫清楚。retrieval-only 的 CLI 不會生成 hallucinated 法律意見,模型選擇與輸出責任由使用者承擔。也讓本工具能合法以 MIT 授權釋出。
Q2:bundle 層級檢查能擋多少幻覺? A:能擋「引用了不存在的字號」「引用了不在 bundle 的字號」這類最常見的捏造。擋不住 paraphrase 型誤讀、把當事人主張當法院見解、把附帶論述當成核心權威。這些都需要人工讀判決全文。
Q3:22M 判決庫可以下載嗎? A:不行。判決庫 / embedding / 向量索引留在伺服器端,本 repo 是 client。司法院公開資料每人可自行下載重建。
Q4:API key 怎麼申請? A:預設 authless 即可使用,per-IP rate limit。若需 attribute 流量請聯絡 dr-lawbot.com。
Q5:可不可以對接本地模型 (Ollama / vLLM)?
A:可以。pack 產生的 bundle 是純 JSON,餵給任何能讀 JSON 的模型都行。check 也是純字串,不限定模型來源。
Q6:v0.1.0 的 codex review 5 blockers 是什麼? A:v0.1.0 釋出前透過 OpenAI codex review 發現的 5 個 blocker,主要圍繞「降級成 retrieval-only + bundle-level citation check」「VENDORED 措辭精準化」「offline tests CI」(見 commit 2bd621f / 437b0cc / 29f238a)。
8. 進階技巧
8.1 切到 staging endpoint
1TWLEGALRAG_TLR_BASE_URL=https://staging.tlr.dr-lawbot.com twlegalrag health
8.2 程式化使用(不透過 CLI)
1from twlegalrag.retrieval import TLRClient
2from twlegalrag.bundle import build_bundle
3from twlegalrag.verify import citation_check
4
5with TLRClient() as c:
6 hits = c.search_and_read("車禍對方全責", max_results=5, read_top=3)
7
8bundle = build_bundle("車禍對方全責", hits)
9
10# 假設你拿到 AI 答案
11answer = "根據最高法院 100 年度台上字第 1 號..."
12report = citation_check(answer, hits)
13print(report.overall, report.out_of_bundle)
8.3 CI 跑 offline tests
repo 的 .github/workflows/ci.yml 跑 pytest,測試檔 tests/test_bundle.py + tests/test_verify.py 完全離線(用 Judgment dataclass 構造 fixture)。若 fork 加自己的測試,務必保持 offline。
8.4 客製 bundle 大小
預設 _EXCERPT_CHARS = 6000(bundle.py:21)。若餵超長 context 模型(Gemini 1M / Claude 200K),可 fork 改大;若餵小模型則改小。
9. 整合進其他工作流
9.1 整合進 AI-Knowledge Template(本 repo)
本 repo 設計上可作為 Layer 9 paper-search / Layer 11 paperqa-lite 的「法律判決對應物」:
- 同樣定位「retrieval-only + downstream LLM responsibility」
- 同樣有「bundle 層級保守檢查」設計哲學
- 可作為未來
legal-search:prefix 的參考實作
9.2 整合進 Discord workflow
1# 在 Discord channel 收到「找一下車禍判決」
2twlegalrag pack "車禍" -o /tmp/car_accident.json
3# 把 JSON 上傳 Discord,LLM 整理回覆,最後跑 check
9.3 整合進 paper-tutorial / gh-tutorial-qd
可作為「法律領域的 paper-tutorial」延伸 — bundle 取代 PDF;citation_id 取代 (pqac-xxx) 引文標籤。
10. 重點摘要 Checklist
- 安裝:
pip install twlegalrag - 驗證:
twlegalrag --version+twlegalrag health - 主流程:
search→pack -o bundle.json→ 餵 LLM →check bundle.json answer.txt - API key:放 env var(
TWLEGALRAG_TLR_API_KEY)或~/.twlegalrag/config.toml,切勿 commit - 隱私:查詢字串會進 TLR 明文日誌,勿送個人機密 / 客戶識別資訊
- 邊界:
check pass≠ 法律推論正確,仍須人工讀判決全文 - 不能驗 paraphrase 型幻覺 / 當事人主張被當法院見解(需人工)
- 不開源判決庫 / embedding / 向量索引(後端私有)
- 同後端也支援 Claude Desktop Remote MCP 與 ChatGPT Custom GPT Action
11. 進一步閱讀
- GitHub repo:https://github.com/aa0101181514/tw-legal-rag
- PyPI 套件:
pip install twlegalrag(v0.1.0,trusted-publishing 發佈) - 服務方主站:https://dr-lawbot.com
- TLR endpoint:https://tlr.dr-lawbot.com(authless)
- OpenAPI schema:https://tlr.dr-lawbot.com/openapi.yaml
- MCP endpoint:https://tlr.dr-lawbot.com/mcp(Claude Desktop Remote MCP)
- 內部 VENDORED 快照說明:
twlegalrag/faithful/VENDORED.md - License:MIT
Comments