issue #2:--all-pending 長時間本地 Ollama 攝入全程靜默,使用者不確定有沒有在 跑、又不敢中斷。三處補強: - 進度可見:每份來源印 [i/N] 起始行、長文件逐分段印「分段 k/n」、每個 knowledge-item 印「↳ 新增/更新」、完成印「✓」,全部 flush=True 即時顯示。 最會靜默的分段迴圈正是重點回報處。 - Ctrl-C 安全:KeyboardInterrupt 不是 Exception 子類,原本會略過善後、把使用者 留在 ingest 分支且無指引。改為獨立攔截——commit 在迴圈之後,故 main 必然未受 影響——印出可照做的回復指令(git checkout main && git stash -u && git branch -D <branch>),以結束碼 130 收場。 selfcheck_ingest 新增:驗進度標記出現;驗中斷後 main HEAD 未動、停在 ingest 分支、且照文件回復指令實測能回到乾淨 main(驗結果可用,非字串存在,§13.4)。 README §7 補一列。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
228 lines
10 KiB
Markdown
228 lines
10 KiB
Markdown
# README — QA 知識庫使用手冊
|
||
|
||
金融電子支付 QA 部門知識庫,採 **Karpathy LLM Wiki 模式**:知識在文件**攝入時**由本地
|
||
LLM 編譯成 wiki 頁,查詢時只讀已編譯頁面(**非 RAG**,檢索用 BM25)。
|
||
|
||
> **本檔是操作手冊(怎麼裝、怎麼跑)。** 所有 schema、工作流細節、硬性約束與行為紀律的
|
||
> **唯一正本**是 [AGENTS.md](AGENTS.md)——動手前請先讀它。本檔只做操作說明,不複製其內容。
|
||
|
||
---
|
||
|
||
## 1. 環境需求
|
||
|
||
| 項目 | 需求 |
|
||
|------|------|
|
||
| Python | 3.11+ |
|
||
| 本地 Ollama | 執行於 `http://localhost:11434`(見 [config/models.yaml](config/models.yaml)) |
|
||
| Ollama 模型 | 已 `ollama pull` 且與 `config/models.yaml` 的 tag 一致的**合規本地模型** |
|
||
| Git remote(選用) | 攝入自動開 PR 用;無 remote 時分支保留於本地 |
|
||
|
||
**資料落地是硬性約束([AGENTS.md](AGENTS.md) §1.1)**:所有文件內容的 LLM 處理一律走本地
|
||
Ollama,**禁止**任何雲端 API、雲端轉換服務,及任何 `:cloud` 後綴模型。供應鏈限制(§1.3):
|
||
禁用中國關聯模型(bge / Qwen / GLM / MiniMax / Jina 等)。
|
||
|
||
---
|
||
|
||
## 2. 安裝
|
||
|
||
Windows PowerShell(本專案主要環境):
|
||
|
||
```powershell
|
||
python -m venv .venv
|
||
.venv\Scripts\pip install -r requirements.txt
|
||
```
|
||
|
||
Linux / Gitea runner:
|
||
|
||
```bash
|
||
python3 -m venv .venv
|
||
.venv/bin/pip install -r requirements.txt
|
||
```
|
||
|
||
接著確認 Ollama 已拉好 `config/models.yaml` 內指定的模型:
|
||
|
||
```powershell
|
||
ollama list # 對照 tasks.ingest.model / tasks.lint.model / tasks.fallback.model
|
||
```
|
||
|
||
**換模型只改 [config/models.yaml](config/models.yaml),不動任何程式碼**(§1.2)。設定缺欄位時程式直接
|
||
報錯,不使用隱含預設值。唯一允許的覆寫來源是環境變數 `OLLAMA_BASE_URL`。
|
||
|
||
> 下文指令以 Windows 的 `.venv\Scripts\python` 為例;Linux 換成 `.venv/bin/python`。
|
||
|
||
---
|
||
|
||
## 3. 四大工作流
|
||
|
||
資料流:**原始檔 → `convert` → `raw/converted/` Markdown → `ingest` → `wiki/` 頁面 →
|
||
`search` / MCP 查詢**;`lint` 定期健檢整庫。
|
||
|
||
### 3.1 轉換 `convert` — 原始檔轉 Markdown
|
||
|
||
把 docx / xlsx / pdf / pptx / html 或網頁 URL 轉成 Markdown,並登記 SHA-256 至
|
||
`raw/manifest.json`(`raw/` 只讀不可變,§1.4)。
|
||
|
||
```powershell
|
||
# 本機檔案(可多個)
|
||
.venv\Scripts\python tools\convert\convert.py 報告.docx 測項.xlsx 規格.pdf
|
||
|
||
# 網頁快照(保存完整 HTML,因來源可能消失)
|
||
.venv\Scripts\python tools\convert\convert.py https://example.com/guideline
|
||
|
||
# 只看計畫、不寫檔
|
||
.venv\Scripts\python tools\convert\convert.py 報告.docx --dry-run
|
||
```
|
||
|
||
- 支援:`.docx .xlsx .pdf .pptx .html/.htm` 與 `http(s)://` URL。
|
||
- hash 相同的檔會自動 `skip`(去重)。
|
||
- 掃描件(PDF 無文字層)標記 `needs_ocr` 並跳過,**不擅自 OCR**,留待人工決定。
|
||
- 單檔失敗不中斷批次,最後彙總並以結束碼 1 回報。
|
||
|
||
### 3.2 攝入 `ingest` — 編譯成 wiki 頁
|
||
|
||
讀 `raw/converted/` 的 Markdown,呼叫本地 Ollama 產出 / 更新 wiki 頁,重建
|
||
`index.md`、追加 `log.md`,並**開新 git 分支 + PR**(HITL 閘門,§1.5——永不直接 commit 到 main)。
|
||
|
||
```powershell
|
||
# 攝入指定來源
|
||
.venv\Scripts\python tools\ingest.py raw\converted\xxx.md
|
||
|
||
# 攝入所有「尚無 summary 頁引用」的來源
|
||
.venv\Scripts\python tools\ingest.py --all-pending
|
||
|
||
# 只列計畫(分支名、模型、分段數),不呼叫 LLM、不寫檔
|
||
.venv\Scripts\python tools\ingest.py --all-pending --dry-run
|
||
|
||
# 已攝入過(hash 相同)也強制重跑
|
||
.venv\Scripts\python tools\ingest.py raw\converted\xxx.md --force
|
||
```
|
||
|
||
**前置條件**:須在 `main` 分支、且工作區除 `raw/` 外無未提交變更,否則會報錯中止。
|
||
|
||
> **`convert` 的產出請保持未提交,不要另開分支 commit。** 除 `raw/` 外無未提交變更的條件
|
||
> 刻意把 `raw/` 排除在外——正確流程是在 `main` 上 `convert`、確認 `raw/converted/*.md` 內容
|
||
> 無誤後直接 `ingest`,由 ingest 把來源與編譯出的 wiki 頁**一起** commit 進同一個分支。這樣
|
||
> PR 的 diff 同時含來源與產出,審核者才能對照 LLM 有無編譯錯誤。若先開分支 commit 了轉換檔,
|
||
> 切回 `main` 時那些檔案會隨分支離開工作區;此時請先 `git merge` 該分支回 `main` 再攝入
|
||
> (`raw/` 不受 §1.5 HITL 閘門管轄,該條只規範 wiki 層變更)。
|
||
|
||
執行後:變更落在 `ingest/<時間戳>-<slug>` 分支。有 remote 時自動 push 並印出 PR 建立網址;
|
||
無 remote / 離線時分支保留本地,請手動 push 後開 PR。**經人工審核合併後才進 main。**
|
||
|
||
### 3.3 健檢 `lint` — 全庫品質檢查
|
||
|
||
檢查 schema 完整性、過期主張、覆蓋缺口、孤兒頁,並用 LLM 偵測重複 / 矛盾頁。
|
||
**絕不修改或刪除任何檔案**,一律產出報告列為「待人工核准」(§1.5、§7)。
|
||
|
||
```powershell
|
||
# 完整健檢,報告寫入 reports/
|
||
.venv\Scripts\python tools\lint.py --output reports
|
||
|
||
# 跳過 LLM 重複/矛盾比對(較快,純 schema/結構檢查)
|
||
.venv\Scripts\python tools\lint.py --no-llm
|
||
```
|
||
|
||
- 報告路徑印在 stdout,例如 `reports/lint-YYYYMMDD-HHMMSS.md`。
|
||
- **結束碼**:`0` = 無發現;`1` = 有待人工核准項目(供 CI 判斷 / 標紅通知)。
|
||
- 排程:[.gitea/workflows/lint.yaml](.gitea/workflows/lint.yaml)(每週一台北時間 05:00,草稿,部署 Gitea 時啟用)。
|
||
|
||
> **`source_ref 不在 manifest` 的成因分類**:lint 只報「對不上」,不分辨成因。跑
|
||
> [tools/diag_refs.py](tools/diag_refs.py) 把每個對不上的 source_ref 分成五類(hash 不符 /
|
||
> 路徑字串岔開 / 檔名 hash 後綴岔開 / 檔在磁碟未登記 / 完全無對應),各附修法——
|
||
> 「補帳本」(§14.3)與「修規則」(§12)的處置相反,先分類再動手。純唯讀不改任何檔,
|
||
> 結束碼同 lint(`0` 全部解得開 / `1` 有對不上),可當搬機或改 manifest 後的閘門。
|
||
>
|
||
> ```powershell
|
||
> .venv\Scripts\python tools\diag_refs.py
|
||
> ```
|
||
|
||
### 3.4 查詢 `search` — BM25 檢索
|
||
|
||
```powershell
|
||
.venv\Scripts\python tools\search.py "AML 測試準則" -k 10
|
||
```
|
||
|
||
輸出 JSON 陣列(`path / title / description / tags / score`),供人工或 agent 定位候選頁。
|
||
`-k` 上限 10(查詢工作流 §8:先讀 `index.md` 定位、最多 10 頁、只讀命中頁、回答必附
|
||
`source_ref`、禁止全庫掃描)。
|
||
|
||
---
|
||
|
||
## 4. MCP server — 供內部 AI agent / 團隊查詢
|
||
|
||
[mcp/server.py](mcp/server.py) 是 FastMCP 薄殼,只暴露兩個唯讀 tool:`search_wiki`(BM25 檢索)與
|
||
`read_page`(讀單頁全文,依 `models.yaml` 的 token 上限截斷)。只讀已編譯 wiki 頁,不觸碰
|
||
`raw/` 層、不做全庫掃描。
|
||
|
||
```powershell
|
||
# stdio 啟動
|
||
.venv\Scripts\python mcp\server.py
|
||
```
|
||
|
||
測試時可用環境變數 `PP_QA_ROOT` 指定專案根目錄。`read_page` 有路徑跳脫防護,只接受
|
||
`wiki/` 下的 `.md`。
|
||
|
||
---
|
||
|
||
## 5. Copilot Custom Agents(雙棧)
|
||
|
||
同一套 [AGENTS.md](AGENTS.md) 規範同時服務 Claude Code 與 GitHub Copilot(§11 雙棧規則)。
|
||
[.github/agents/](.github/agents/) 提供三個 Copilot 編排 agent——它們**只編排、不處理文件內容**
|
||
(成本紀律 §1.6:LLM 處理一律 shell out 給本地腳本,agent 只讀精簡結果):
|
||
|
||
| Agent | 職責 |
|
||
|-------|------|
|
||
| [kb-ingest](.github/agents/kb-ingest.agent.md) | 轉換 → 攝入 → 開 PR |
|
||
| [kb-lint](.github/agents/kb-lint.agent.md) | 執行健檢並摘要報告重點 |
|
||
| [kb-query](.github/agents/kb-query.agent.md) | 檢索 → 只讀命中頁 → 附 source_ref 回答 |
|
||
|
||
---
|
||
|
||
## 6. 目錄速查
|
||
|
||
```text
|
||
config/models.yaml # Ollama 端點與模型 tag(唯一設定來源)
|
||
raw/originals/ # 原始檔,只讀
|
||
raw/converted/ # 轉換後 Markdown,攝入的實際輸入,只讀
|
||
raw/manifest.json # SHA-256 登記 + 原始檔↔轉換檔對應
|
||
wiki/summaries/ # 每份來源一頁摘要
|
||
wiki/entities/ # 實體頁(系統/模組/API/法規/專案)
|
||
wiki/concepts/ # 概念頁(跨來源綜合)
|
||
index.md # 目錄式導航(由 ingest 自動重建)
|
||
log.md # append-only 操作日誌
|
||
tools/ # convert/ ingest.py lint.py diag_refs.py search.py kb.py(共用模組)
|
||
mcp/server.py # MCP 薄殼
|
||
```
|
||
|
||
完整結構與各檔用途見 [AGENTS.md](AGENTS.md) §2。
|
||
|
||
---
|
||
|
||
## 7. 疑難排解
|
||
|
||
| 訊息 / 現象 | 原因與處置 |
|
||
|-------------|-----------|
|
||
| `config/models.yaml 缺欄位` | 設定不完整;補齊欄位,不要用預設值繞過(§1.2)。 |
|
||
| `tasks.X.model 為 :cloud 模型` | 違反資料落地;改用本地模型 tag(§1.1)。 |
|
||
| `須在 main 分支執行` | 攝入前先切回 `main`。 |
|
||
| `工作區有 raw/ 以外的未提交變更` | 先 commit / stash 非 `raw/` 的變更再攝入。 |
|
||
| `... 不在 manifest 的 converted 條目中` | 該來源尚未轉換;先跑 `convert.py`。 |
|
||
| lint 報 `source_ref 不在 manifest` | 跑 `tools/diag_refs.py` 分類成因:帳本掉條目→補登走 PR(§14.3);路徑字串岔開→修規則(§12),別逐頁改。 |
|
||
| `LLM 輸出驗證失敗(含 fallback)` | 本地模型連主模型 + fallback 都無法產出合規 JSON;檢查 Ollama 是否在線、模型是否拉好。 |
|
||
| `push 失敗(無 remote 或離線)` | 正常;分支已保留本地,手動 push 後開 PR。 |
|
||
| ingest 跑很久、看不到進度/想中斷 | 已逐來源 `[i/N]` +逐分段回報進度。Ctrl-C 安全:main 不受影響,中斷時會印回復指令(`git checkout main && git stash -u && git branch -D <branch>`),續跑 `--all-pending` 自動接續。 |
|
||
|
||
---
|
||
|
||
## 8. 開發者自檢
|
||
|
||
各工具附 assert 式自檢腳本(免框架、免 fixtures,§13.4):
|
||
|
||
```powershell
|
||
.venv\Scripts\python tools\convert\selfcheck.py
|
||
.venv\Scripts\python tools\selfcheck_ingest.py
|
||
.venv\Scripts\python tools\selfcheck_lint.py
|
||
.venv\Scripts\python tools\selfcheck_diag_refs.py
|
||
.venv\Scripts\python tools\selfcheck_search.py
|
||
```
|