# AI Agent 系統分析文件(SA)
**版本**:v2.0
**日期**:2026-03-05
**環境**:離線繪圖筆電 + 機構整合部後端伺服器
**狀態**:可執行開發版
---
## 目錄
1. [目的與範圍](#1-目的與範圍)
2. [設計原則與約束](#2-設計原則與約束)
3. [系統架構](#3-系統架構)
4. [技術選型](#4-技術選型)
5. [資料庫 Schema](#5-資料庫-schema)
6. [API 規格](#6-api-規格)
7. [文件匯入與向量化流程](#7-文件匯入與向量化流程)
8. [RAG 對話流程](#8-rag-對話流程)
9. [上下文管理策略](#9-上下文管理策略)
10. [RAG 精準度提升](#10-rag-精準度提升)
11. [MCP / Skills 框架](#11-mcp--skills-框架)
12. [安全性設計](#12-安全性設計)
13. [部署手冊(可複製步驟)](#13-部署手冊可複製步驟)
14. [開發計畫與里程碑](#14-開發計畫與里程碑)
15. [驗收準則](#15-驗收準則)
16. [風險管理與降級策略](#16-風險管理與降級策略)
17. [交付物清單](#17-交付物清單)
---
## 1. 目的與範圍
### 1.1 目的
本文件為機構設計研發人員工作站上部署之 **離線 AI Agent 系統** 的系統分析(SA)文件,旨在提供可直接執行開發的完整規格,涵蓋架構設計、流程定義、API 合約、DB Schema、部署步驟與開發里程碑。
### 1.2 使用情境
| 角色 | 情境描述 |
|------|----------|
| 設計研發人員 | 在繪圖筆電上同時執行 CAD 與 AI Agent 查詢,取得技術文件的 AI 輔助分析 |
| 整合部工程師 | 管理後端伺服器上的模型推理服務、文件知識庫 |
| 系統管理員 | 部署、備份、監控整體系統 |
### 1.3 範圍邊界
- **納入**:本地推理、文件向量化、RAG 對話、MCP 工具呼叫、使用者端 UI、後端 API
- **排除**:雲端服務整合、Docker 容器化、跨網際網路部署
---
## 2. 設計原則與約束
| 原則 | 說明 |
|------|------|
| **離線運行** | 核心功能(推理、檢索、向量搜尋、文件匯入)在無外網下完整運作 |
| **無 Docker** | 以系統服務(systemd / Windows Service)或虛擬環境(venv / conda)部署 |
| **資源限制** | 客戶端:8 GB RAM + 獨立 GPU;後端伺服器規格視實際為準 |
| **資料主權** | 所有資料留存於機構內部網路,不外傳 |
| **可複製部署** | 任何人依此文件可在相似環境自行架設 |
| **降級設計** | 每個元件有明確的替代方案,避免單點依賴 |
### 2.1 推理平台優先順序
```
llama.cpp > Foundry Local > LM Studio CLI(待確認) > Ollama(備援)
```
優先選用 `llama.cpp` 原因:最輕量、純 CLI/API、無 GUI 包裝、離線能力最強、授權風險最低。
---
## 3. 系統架構
### 3.1 整體部署架構
```mermaid
graph TB
subgraph CLIENT["使用者端(繪圖筆電)"]
UI["桌面 UI\n(Electron / 本地 Web)"]
AC["Agent Client\n(Python)"]
LC["本地 SQLite\n快取 & 對話歷程"]
LS["本地 Skills / MCP\n(可攜帶 Scripts)"]
LI["本地輕量推理\n(llama.cpp, 可選)"]
UI --> AC
AC --> LC
AC --> LS
AC -.->|"資源允許時"| LI
end
subgraph BACKEND["後端(整合部 Host)"]
API["API Gateway\n(FastAPI)"]
AUTH["認證服務\n(JWT + API Token)"]
INGEST["文件處理服務\n(Ingestion Worker)"]
RETRIEVAL["檢索服務\n(Retrieval Engine)"]
INFERENCE["推理服務\n(llama.cpp server)"]
RERANK["Reranking 模組\n(cross-encoder)"]
MCP["MCP / Skills\n執行器"]
subgraph DB["資料層"]
PG["PostgreSQL"]
PGV["pgvector 擴充"]
FS["本地檔案系統\n(原始文件儲存)"]
end
API --> AUTH
API --> INGEST
API --> RETRIEVAL
API --> MCP
RETRIEVAL --> PGV
RETRIEVAL --> RERANK
RERANK --> INFERENCE
INGEST --> FS
INGEST --> PG
INGEST --> PGV
end
subgraph KM["KM 系統(外部)"]
KMS["知識管理系統\n文件庫"]
end
AC -->|"HTTPS / LAN"| API
KMS -->|"匯出 / 批次推送"| INGEST
style CLIENT fill:#e8f4fd,stroke:#2196F3
style BACKEND fill:#f3e8fd,stroke:#9C27B0
style KM fill:#fdf3e8,stroke:#FF9800
```
### 3.2 元件責任分配
#### 客戶端元件
| 元件 | 技術 | 責任 | 記憶體預估 |
|------|------|------|-----------|
| 桌面 UI | Electron 或 Python Web (Gradio/Streamlit) | 操作介面、對話視窗 | ~200 MB |
| Agent Client | Python 3.11+ | 請求組裝、上下文管理、快取讀寫 | ~100 MB |
| 本地 SQLite | SQLite 3 | 對話歷程、技能快取、暫存狀態 | ~50 MB |
| 本地 Skills | Python Scripts | 離線可執行的工具(CAD 指令、格式轉換) | 無常駐 |
| 本地推理(可選) | llama.cpp (quantized) | 簡單分類/路由不需 remote 的任務 | 2–4 GB(啟動時) |
#### 後端元件
| 元件 | 技術 | 責任 |
|------|------|------|
| API Gateway | FastAPI 0.110+ | 路由、認證、請求驗證、速率限制 |
| 文件處理服務 | Python Worker (Celery / asyncio) | PDF 解析、OCR、Chunking、Embedding |
| 檢索服務 | Python + pgvector | 向量搜尋、metadata 篩選、結果組裝 |
| Reranking 模組 | sentence-transformers (cross-encoder) | 對召回結果重新排序 |
| 推理服務 | llama.cpp server (HTTP mode) | 文字生成、embedding 生成 |
| MCP 執行器 | Python Plugin 框架 | 呼叫已註冊 Skill,回傳結構化結果 |
| PostgreSQL + pgvector | PostgreSQL 16 + pgvector 0.7+ | 向量儲存、metadata、使用者資料 |
---
## 4. 技術選型
### 4.1 推理平台比較矩陣
| 指標 | llama.cpp | Foundry Local | LM Studio CLI | Ollama |
|------|:---------:|:-------------:|:-------------:|:------:|
| 離線能力 | ✅ 完整 | ✅ 完整 | ✅ 完整 | ✅ 完整 |
| API 相容性 (OpenAI-compat) | ✅ | ✅ | ⚠️ 待確認 | ✅ |
| 無 GUI 可執行 | ✅ | ✅ | ⚠️ CLI 模式限制 | ✅ |
| 記憶體效率 | ✅ 最輕 | ✅ | ✅ | ⚠️ 含包裝層 |
| Context 超限行為 | 🟡 截斷(可預測) | ⚠️ 需測試 | ⚠️ 需測試 | 🔴 可能異常回傳 |
| GPU 卸載 | ✅ CUDA/Metal | ✅ | ✅ | ✅ |
| 授權風險 | ✅ MIT | ⚠️ Microsoft 自有 | ⚠️ 商業化風險 | ⚠️ 商業化改變中 |
| 社群活躍度 | ✅ 非常活躍 | ⚠️ 中等 | ⚠️ 中等 | ✅ 活躍 |
| **優先等級** | **1(首選)** | **2** | **3(待確認)** | **4(備援)** |
### 4.2 模型選型建議
| 用途 | 推薦模型 | 量化建議 | 記憶體需求 |
|------|---------|---------|-----------|
| 主要對話/RAG | Qwen2.5-7B-Instruct | Q4_K_M | ~5 GB |
| 輕量路由/分類(Client) | Qwen2.5-1.5B | Q4_K_M | ~1.2 GB |
| 文字 Embedding | nomic-embed-text-v1.5 | F16 | ~0.3 GB |
| 圖片/多模態 Embedding | CLIP ViT-B/32 | FP16 | ~0.6 GB |
| Reranking | ms-marco-MiniLM-L-6-v2 | FP32 | ~0.1 GB |
> **備選**:Gemma3-9B(若 Qwen 授權有疑慮);LLaMA-3.1-8B(通用備援)
### 4.3 Agent 框架
採用 **LangChain(純程式化)** 為核心框架:
- 穩定 Python API,易於整合 MCP/Skill
- 無圖形化 GUI 依賴,降低商業化風險
- 可選擇性引入 LangGraph 管理多步驟 Agent 流程
### 4.4 技術堆疊總覽
```
後端語言:Python 3.11
API 框架:FastAPI 0.110 + Uvicorn
任務佇列:Celery 5 + Redis(或 asyncio task queue)
資料庫 :PostgreSQL 16 + pgvector 0.7
文件解析:PyMuPDF 1.24 + pdfminer.six + Tesseract OCR 5
Embedding:sentence-transformers + llama.cpp embedding API
向量索引:pgvector HNSW index
Agent :LangChain 0.3 + LangGraph(選用)
前端 :Gradio(快速展示)或 Electron(桌面版)
認證 :JWT (PyJWT) + API Token
```
---
## 5. 資料庫 Schema
### 5.1 Schema 概覽(Mermaid ERD)
```mermaid
erDiagram
users {
uuid id PK
varchar username
varchar password_hash
varchar role
timestamp created_at
timestamp last_login
}
api_tokens {
uuid id PK
uuid user_id FK
varchar token_hash
varchar description
timestamp expires_at
timestamp created_at
}
documents {
uuid id PK
varchar filename
varchar original_path
varchar source_type
varchar mime_type
bigint file_size
varchar status
uuid uploaded_by FK
timestamp uploaded_at
timestamp processed_at
jsonb metadata
}
chunks {
uuid id PK
uuid document_id FK
int chunk_index
text content
varchar content_type
int page_number
jsonb metadata
vector embedding
timestamp created_at
}
conversations {
uuid id PK
uuid user_id FK
varchar title
timestamp created_at
timestamp updated_at
}
messages {
uuid id PK
uuid conversation_id FK
varchar role
text content
jsonb sources
float confidence
int token_count
timestamp created_at
}
ingest_tasks {
uuid id PK
uuid document_id FK
varchar status
int total_chunks
int processed_chunks
text error_log
timestamp started_at
timestamp finished_at
}
skills {
uuid id PK
varchar name
varchar version
varchar entrypoint
jsonb schema
bool enabled
timestamp registered_at
}
users ||--o{ api_tokens : "has"
users ||--o{ documents : "uploads"
users ||--o{ conversations : "has"
documents ||--o{ chunks : "splits into"
documents ||--|| ingest_tasks : "has"
conversations ||--o{ messages : "contains"
```
### 5.2 關鍵 SQL 建表語句
```sql
-- 啟用 pgvector
CREATE EXTENSION IF NOT EXISTS vector;
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
-- 使用者
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
username VARCHAR(64) UNIQUE NOT NULL,
password_hash VARCHAR(128) NOT NULL,
role VARCHAR(16) NOT NULL DEFAULT 'viewer', -- admin | editor | viewer
created_at TIMESTAMPTZ DEFAULT now(),
last_login TIMESTAMPTZ
);
-- 文件
CREATE TABLE documents (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
filename VARCHAR(512) NOT NULL,
original_path TEXT,
source_type VARCHAR(32) NOT NULL, -- pdf | image | zip | km_export
mime_type VARCHAR(64),
file_size BIGINT,
status VARCHAR(16) NOT NULL DEFAULT 'pending', -- pending | processing | done | failed
uploaded_by UUID REFERENCES users(id),
uploaded_at TIMESTAMPTZ DEFAULT now(),
processed_at TIMESTAMPTZ,
metadata JSONB DEFAULT '{}'
);
-- 文件切片與向量(維度 768 對應 nomic-embed-text)
CREATE TABLE chunks (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
document_id UUID NOT NULL REFERENCES documents(id) ON DELETE CASCADE,
chunk_index INT NOT NULL,
content TEXT NOT NULL,
content_type VARCHAR(16) NOT NULL DEFAULT 'text', -- text | image
page_number INT,
metadata JSONB DEFAULT '{}',
embedding vector(768),
created_at TIMESTAMPTZ DEFAULT now()
);
-- HNSW 索引(高效近似最近鄰搜尋)
CREATE INDEX ON chunks USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 64);
-- 匯入任務
CREATE TABLE ingest_tasks (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
document_id UUID NOT NULL REFERENCES documents(id),
status VARCHAR(16) NOT NULL DEFAULT 'queued',
total_chunks INT DEFAULT 0,
processed_chunks INT DEFAULT 0,
error_log TEXT,
started_at TIMESTAMPTZ,
finished_at TIMESTAMPTZ
);
-- 對話
CREATE TABLE conversations (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
user_id UUID NOT NULL REFERENCES users(id),
title VARCHAR(256) DEFAULT '新對話',
created_at TIMESTAMPTZ DEFAULT now(),
updated_at TIMESTAMPTZ DEFAULT now()
);
-- 訊息
CREATE TABLE messages (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
conversation_id UUID NOT NULL REFERENCES conversations(id) ON DELETE CASCADE,
role VARCHAR(16) NOT NULL, -- user | assistant | system
content TEXT NOT NULL,
sources JSONB DEFAULT '[]',
confidence FLOAT,
token_count INT,
created_at TIMESTAMPTZ DEFAULT now()
);
-- Skills 註冊表
CREATE TABLE skills (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
name VARCHAR(64) UNIQUE NOT NULL,
version VARCHAR(16) NOT NULL,
entrypoint TEXT NOT NULL,
schema JSONB NOT NULL,
enabled BOOLEAN DEFAULT true,
registered_at TIMESTAMPTZ DEFAULT now()
);
```
---
## 6. API 規格
### 6.1 基本規範
- **Base URL**:`https://<backend-host>/api/v1`
- **認證**:`Authorization: Bearer <jwt_token>` 或 `X-API-Token: <token>`
- **Content-Type**:`application/json`(上傳接受 `multipart/form-data`)
- **錯誤格式**:
```json
{ "error": "error_code", "message": "human readable", "detail": {} }
```
### 6.2 認證
| 方法 | 路徑 | 說明 |
|------|------|------|
| POST | `/auth/login` | 帳密登入,回傳 JWT |
| POST | `/auth/token` | 建立 API Token |
| DELETE | `/auth/token/{id}` | 撤銷 API Token |
**POST /auth/login 請求:**
```json
{ "username": "designer01", "password": "..." }
```
**回應:**
```json
{ "access_token": "eyJ...", "token_type": "bearer", "expires_in": 86400 }
```
### 6.3 文件管理
| 方法 | 路徑 | 說明 |
|------|------|------|
| POST | `/upload-batch` | 批次上傳文件(PDF / 圖片 / ZIP),回傳 task_id |
| GET | `/upload-status/{task_id}` | 查詢匯入進度 |
| GET | `/docs` | 列出已上傳文件(支援分頁與篩選) |
| GET | `/docs/{id}` | 取得文件 metadata |
| GET | `/docs/{id}/download` | 下載原始文件 |
| DELETE | `/docs/{id}` | 刪除文件與對應向量(需 editor 權限) |
**POST /upload-batch 請求(multipart/form-data):**
| 欄位 | 型別 | 說明 |
|------|------|------|
| `files` | File[] | 最多 50 個檔案,單檔最大 100 MB |
| `source_type` | string | `pdf` \| `image` \| `km_export` |
| `metadata` | JSON string | 選填,附加描述資訊 |
**回應:**
```json
{
"task_id": "uuid",
"queued_count": 5,
"document_ids": ["uuid1", "uuid2", "..."]
}
```
**GET /upload-status/{task_id} 回應:**
```json
{
"task_id": "uuid",
"status": "processing",
"total": 5,
"done": 3,
"failed": 0,
"errors": []
}
```
### 6.4 查詢與對話
| 方法 | 路徑 | 說明 |
|------|------|------|
| POST | `/query` | 單次 RAG 查詢(無狀態) |
| POST | `/conversations` | 建立新對話 |
| POST | `/conversations/{id}/messages` | 在對話中發送訊息(有狀態,含上下文) |
| GET | `/conversations` | 列出使用者對話 |
| GET | `/conversations/{id}/messages` | 取得對話歷程 |
**POST /query 請求:**
```json
{
"prompt": "請說明這份規格書中的耐壓測試標準",
"top_k": 5,
"filters": {
"source_type": "pdf",
"doc_ids": ["uuid1"]
},
"options": {
"rerank": true,
"multi_round": false,
"verify_answer": true
}
}
```
**POST /query 回應:**
```json
{
"answer": "根據第 3 章規定,耐壓測試需在...",
"confidence": 0.87,
"sources": [
{
"doc_id": "uuid",
"filename": "spec_v3.pdf",
"page": 12,
"chunk_index": 5,
"score": 0.93,
"excerpt": "耐壓測試標準:..."
}
],
"token_usage": { "prompt": 1024, "completion": 256 },
"warning": null
}
```
### 6.5 Skills / MCP
| 方法 | 路徑 | 說明 |
|------|------|------|
| GET | `/skills` | 列出已啟用的 Skills |
| POST | `/skills/{name}/invoke` | 直接呼叫 Skill |
---
## 7. 文件匯入與向量化流程
### 7.1 流程圖
```mermaid
flowchart TD
A([上傳請求\nPOST /upload-batch]) --> B{檔案類型}
B -->|PDF| C[PyMuPDF 解析\n擷取文字區塊 + 圖像區塊]
B -->|圖片| D[標準化尺寸\n圖片前處理]
B -->|ZIP| E[解壓縮\n遞迴分派]
E --> B
C --> F{是掃描 PDF?}
F -->|是| G[Tesseract OCR\n逐頁辨識]
F -->|否| H[直接使用擷取文字]
G --> H
D --> I[CLIP 視覺 Embedder\n產生圖像向量]
H --> J[文字 Chunking\n語意/段落切片\n+metadata 標注]
J --> K[文字 Embedding\nnomic-embed-text]
K --> L[寫入 pgvector\n+ metadata]
I --> L
L --> M[更新 ingest_task 狀態]
M --> N([匯入完成])
style A fill:#4CAF50,color:#fff
style N fill:#4CAF50,color:#fff
```
### 7.2 Chunking 策略
| 策略 | 適用情境 | 實作 |
|------|---------|------|
| 語意段落切片 | 結構化技術文件 | 依標題層級切割,保留段落完整性 |
| 固定長度與重疊 | 密集敘述文字 | 512 token / 64 token overlap |
| 表格保留 | PDF 中的規格表 | PyMuPDF 表格偵測,以 markdown 格式保留 |
| 圖像獨立 chunk | 圖示/圖表 | 獨立 chunk,content_type = 'image' |
**Chunk Metadata 格式:**
```json
{
"source_file": "spec_v3.pdf",
"page": 12,
"section": "3.2 耐壓測試",
"chunk_index": 5,
"char_count": 420,
"has_table": false,
"has_image": false
}
```
---
## 8. RAG 對話流程
### 8.1 完整流程時序圖
```mermaid
sequenceDiagram
participant U as 使用者端
participant AG as Agent Client
participant API as API Gateway
participant RET as 檢索服務
participant RNK as Reranker
participant INF as 推理服務(llama.cpp)
participant MCP as MCP 執行器
participant DB as pgvector DB
U->>AG: 輸入查詢
AG->>AG: 組裝請求 (含對話歷程 + context)
AG->>API: POST /query
API->>API: 身分驗證
API->>RET: retrieval(query, top_k=20)
RET->>DB: ANN 向量搜尋 cos sim
DB-->>RET: 候選 chunks (top 20)
RET->>RET: metadata 篩選 / recency 加權
RET-->>API: filtered chunks (top 10)
API->>RNK: rerank(query, chunks)
RNK->>INF: cross-encoder scoring
INF-->>RNK: scores
RNK-->>API: reranked chunks (top 5)
API->>API: 評估是否觸發 MCP Skill
alt 確定需要工具呼叫
API->>MCP: invoke_skill(name, params)
MCP-->>API: skill_result
end
API->>API: Context Window 管理\n(token count check)
API->>INF: generate(prompt + context)
INF-->>API: generated answer
API->>API: Answer Verification\n(置信度評估)
API-->>AG: response (answer + sources + confidence)
AG->>AG: 更新本地 SQLite 對話快取
AG-->>U: 顯示回應 + 來源
```
### 8.2 MCP Skill 觸發條件
| 條件類型 | 判斷方式 | 範例 |
|----------|---------|------|
| 明確工具指令 | Query 包含特定關鍵詞 / LLM 意圖分類 | "轉換這個 DXF 檔案" |
| 資料庫查詢 | Query 需要最新動態資料 | "最近一週的設計變更記錄" |
| 計算任務 | 需要精確數值運算 | "計算這個截面的慣性矩" |
| 信心不足時 | RAG confidence < 0.6 且有對應 Skill | 嘗試 Skill 補強 |
---
## 9. 上下文管理策略
### 9.1 Context Window 處理流程
```mermaid
flowchart TD
A[組裝 Prompt] --> B[計算總 Token 數]
B --> C{大於 80% Context Limit?}
C -->|否| I[直接送推理]
C -->|是| D[Step 1: Rerank 取 Top-K\n降低 chunk 數量]
D --> E{仍然超限?}
E -->|否| I
E -->|是| F[Step 2: Summarize Chunks\n壓縮為摘要]
F --> G{仍然超限?}
G -->|否| I
G -->|是| H[Step 3: 僅保留最高分\n單一 chunk + 系統提示]
H --> I
I --> J[送推理服務]
J --> K{推理回傳異常?}
K -->|否| L([成功回應])
K -->|是| M[捕捉異常\n分析錯誤類型]
M --> N{Context 超限錯誤?}
N -->|是| O[減少 50% Context\n重試]
N -->|否| P[記錄錯誤\n回傳錯誤訊息]
O --> J
```
### 9.2 Token 預算分配
以 context limit = 8192 tokens 為例:
| 區塊 | 配額 | 說明 |
|------|-----|------|
| 系統提示 | 256 | 固定 |
| 對話歷程 | 512 | 最近 N 輪,動態截斷 |
| 召回 Chunks | 4096 | rerank 後最多 5 chunks |
| 使用者查詢 | 512 | 含當前輸入 |
| 生成預留 | 2816 | 模型輸出上限 |
### 9.3 Sliding Window 對話管理
```python
# 偽代碼:保留最近 N 輪,超限時摘要較早輪次
def build_conversation_context(messages: list, max_tokens: int) -> list:
recent = messages[-6:] # 最近 3 輪 (user+assistant)
older = messages[:-6]
if count_tokens(recent) > max_tokens * 0.4:
summary = summarize(older) # 用小型 LLM 摘要
return [SystemMessage(summary)] + recent
return older + recent
```
---
## 10. RAG 精準度提升
### 10.1 精準度提升管線
```mermaid
flowchart LR
A[使用者 Query] --> B[Query 前處理\n+ HyDE 可選]
B --> C[向量搜尋\nANN top-20]
C --> D[Metadata 篩選\nrecency / source 加權]
D --> E[Cross-Encoder Reranker\ntop-5]
E --> F[Answer Generation\nLLM]
F --> G[Answer Verification\n與 chunks 交叉驗證]
G --> H{Confidence 達到閾值?}
H -->|是| I([回傳答案 + 來源])
H -->|否| J[Multi-Round Retrieval\n補充查詢]
J --> C
```
### 10.2 各模組說明
| 模組 | 實作方式 | 驗收指標 |
|------|---------|---------|
| **HyDE(選用)** | LLM 先生成假設答案,用假設答案向量做初步搜尋 | 召回率 +10% |
| **Cross-Encoder Reranker** | `ms-marco-MiniLM-L-6-v2` 對 (query, chunk) 配對打分 | MRR@5 > 0.7 |
| **Answer Verification** | 擷取 LLM 答案中的關鍵聲明,與 chunks 做語意相似度比對 | 置信度標注準確率 |
| **Multi-Round Retrieval** | 首輪生成草稿 → 從草稿抽出缺失概念 → 補充查詢 → 合成最終答案 | 複雜查詢準確率 +15% |
| **langextract(實驗)** | A/B 測試,與標準 RAG pipeline 比較 F1 | 列為實驗指標 |
---
## 11. MCP / Skills 框架
### 11.1 Skill 介面規格
```python
# skills/base.py
from abc import ABC, abstractmethod
from pydantic import BaseModel
class SkillInput(BaseModel):
pass
class SkillOutput(BaseModel):
result: dict
error: str | None = None
confidence: float = 1.0
class BaseSkill(ABC):
name: str
version: str
description: str
input_schema: type[SkillInput]
@abstractmethod
def invoke(self, input_data: SkillInput) -> SkillOutput:
...
```
### 11.2 內建 Skills 清單(V1)
| Skill 名稱 | 說明 | 輸入 | 輸出 |
|-----------|------|------|------|
| `file_convert` | 格式轉換(DXF → PDF 等) | file_path, target_format | converted_file_path |
| `db_query` | 執行預定義 SQL 查詢 | query_name, params | rows |
| `doc_search` | 直接全文搜尋(非向量) | keyword, doc_ids | matching_chunks |
| `calculator` | 工程計算(截面屬性等) | expression, variables | result |
| `km_fetch` | 從 KM 系統拉取最新文件 | document_id | document_content |
### 11.3 Skill 註冊方式
```bash
# 將 Skill 腳本放入 skills/ 目錄後執行
python manage.py register-skill --path skills/file_convert.py
```
---
## 12. 安全性設計
### 12.1 網路架構
```
[繪圖筆電] ──HTTPS/TLS 1.3──→ [整合部 Switch] ──→ [後端伺服器]
↕ 內網隔離
[PostgreSQL]
(不直接對外開放 5432)
```
### 12.2 認證與授權
| 控制項 | 實作方式 |
|-------|---------|
| 使用者認證 | JWT (HS256),TTL 8 小時,Refresh Token 7 天 |
| API Token | SHA-256 hash 儲存,永久有效(可手動撤銷) |
| 角色權限 | RBAC:`admin` / `editor` / `viewer` |
| 速率限制 | `/query` 最多 30 req/min per user |
| CORS | 僅允許機構內網 IP 段 |
### 12.3 資料保護
```bash
# PostgreSQL 備份排程(每日 02:00,加入 crontab)
# 0 2 * * * agent pg_dump -U agent_user agent_db | gzip > /backup/agent_$(date +%Y%m%d).sql.gz
# 0 3 * * * find /backup -name "agent_*.sql.gz" -mtime +30 -delete
```
---
## 13. 部署手冊(可複製步驟)
### 13.1 後端部署(整合部 Host,Ubuntu / Rocky Linux)
```bash
# Step 1:系統套件
sudo apt update && sudo apt install -y python3.11 python3.11-venv \
postgresql-16 postgresql-contrib redis-server \
tesseract-ocr tesseract-ocr-chi-tra build-essential cmake git
# Step 2:安裝 pgvector
git clone https://github.com/pgvector/pgvector.git
cd pgvector && make && sudo make install
sudo -u postgres psql -c "CREATE EXTENSION vector;"
# Step 3:建立資料庫
sudo -u postgres psql <<EOF
CREATE USER agent_user WITH PASSWORD 'CHANGE_ME_STRONG_PASSWORD';
CREATE DATABASE agent_db OWNER agent_user;
GRANT ALL PRIVILEGES ON DATABASE agent_db TO agent_user;
EOF
# Step 4:部署 API 服務
git clone <repo_url> /opt/agent-backend
cd /opt/agent-backend
python3.11 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
# Step 5:設定環境變數
cp .env.example .env
vim .env # 填入 DB_URL, SECRET_KEY, INFERENCE_URL 等
# Step 6:初始化資料庫
python manage.py db-init
# Step 7:安裝 llama.cpp(含 CUDA 支援)
git clone https://github.com/ggerganov/llama.cpp /opt/llama.cpp
cd /opt/llama.cpp
cmake -B build -DLLAMA_CUDA=ON
cmake --build build -j$(nproc)
# Step 8:下載模型(離線環境:透過內網或移動硬碟傳入)
mkdir -p /opt/models
# 將 Qwen2.5-7B-Instruct-Q4_K_M.gguf 放入 /opt/models/
# Step 9:以 systemd 管理各服務
sudo cp deploy/llama-server.service /etc/systemd/system/
sudo cp deploy/agent-api.service /etc/systemd/system/
sudo cp deploy/agent-worker.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now llama-server agent-api agent-worker
```
### 13.2 環境變數(.env)
```ini
# 資料庫
DATABASE_URL=postgresql://agent_user:CHANGE_ME@localhost:5432/agent_db
# 安全
SECRET_KEY=<32字元隨機字串,可用 openssl rand -hex 32 生成>
API_TOKEN_SALT=<16字元隨機字串>
# 推理服務
INFERENCE_URL=http://127.0.0.1:8080
EMBEDDING_URL=http://127.0.0.1:8080/v1/embeddings
EMBED_MODEL=nomic-embed-text-v1.5
EMBED_DIM=768
# Context 管理
MAX_CONTEXT_TOKENS=8192
TOP_K_RETRIEVAL=20
TOP_K_RERANK=5
CONFIDENCE_THRESHOLD=0.6
# 任務佇列
REDIS_URL=redis://127.0.0.1:6379/0
# TLS(生產環境)
TLS_CERT=/etc/ssl/certs/agent.crt
TLS_KEY=/etc/ssl/private/agent.key
```
### 13.3 systemd Service 範例(llama-server.service)
```ini
[Unit]
Description=llama.cpp HTTP Server
After=network.target
[Service]
Type=simple
User=agent
WorkingDirectory=/opt/llama.cpp
ExecStart=/opt/llama.cpp/build/bin/llama-server \
--model /opt/models/Qwen2.5-7B-Instruct-Q4_K_M.gguf \
--port 8080 \
--ctx-size 8192 \
--n-gpu-layers 35 \
--host 127.0.0.1 \
--embedding
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
```
### 13.4 客戶端部署(繪圖筆電,Windows)
```powershell
# Step 1:安裝 Python 3.11
winget install Python.Python.3.11
# Step 2:部署客戶端
git clone <repo_url> C:\agent-client
Set-Location C:\agent-client
python -m venv .venv
.venv\Scripts\Activate.ps1
pip install -r requirements-client.txt
# Step 3:設定連線
Copy-Item .env.client.example .env.client
# 編輯 .env.client 填入 BACKEND_URL 與 API_TOKEN
# Step 4:啟動 UI
python client\app.py
```
---
## 14. 開發計畫與里程碑
### 14.1 甘特圖
```mermaid
gantt
title AI Agent 開發計畫(2026)
dateFormat YYYY-MM-DD
axisFormat %m/%d
section 基礎建設
M1 環境建置與 MVP :m1, 2026-03-09, 14d
E1 Inference 平台評估 :e1, 2026-03-09, 28d
section 核心功能
M2 文件匯入與向量化 Pipeline :m2, after m1, 28d
E2 效能與邊界測試 :e2, after e1, 14d
section RAG 功能
M3 RAG 對話、Rerank 與 MCP :m3, after m2, 28d
section 多模態與前端
M4 多模態支援與前端整合 :m4, after m3, 28d
section 穩固化
M5 安全強化、備份、部署文件 :m5, after m4, 28d
```
### 14.2 里程碑任務細項
#### M1:環境建置與 MVP(第 1–2 週)
| # | 任務 | 完成標準 |
|---|------|---------|
| 1.1 | PostgreSQL + pgvector 安裝與設定 | `SELECT * FROM pg_extension WHERE extname='vector'` 回傳結果 |
| 1.2 | DB Schema migration 腳本 | 所有表與 HNSW index 建立成功 |
| 1.3 | FastAPI skeleton(含 /auth/login) | JWT 登入回傳 token |
| 1.4 | llama.cpp server 啟動 | `GET /v1/models` 回傳模型清單 |
| 1.5 | 單文件上傳(同步)+ 最小 chunk | 上傳 1 份 PDF 後可在 chunks 表查到資料 |
| 1.6 | 最小 RAG /query | 傳入 prompt 收到含 sources 的回應 |
#### E1:Inference 平台評估(第 1–4 週)
| # | 測試項目 | 測試方法 | 交付物 |
|---|---------|---------|-------|
| E1.1 | API 相容性 | OpenAI Python client 各平台呼叫 | 相容性矩陣 |
| E1.2 | 資源占用量測 | 8 GB 機器 idle / 推理中 RAM/VRAM | 資源圖表 |
| E1.3 | Context 超限測試 | 送入超出 context_limit 的請求 | 錯誤行為記錄 |
| E1.4 | 推理速度 | Token/sec(512 input, 256 output) | 速度比較表 |
#### M2:文件匯入與向量化 Pipeline(第 3–6 週)
| # | 任務 | 完成標準 |
|---|------|---------|
| 2.1 | PyMuPDF PDF 文字解析 | 100 篇 PDF 解析成功率 ≥ 95% |
| 2.2 | Tesseract OCR(掃描 PDF) | 掃描文件辨識率 ≥ 85% |
| 2.3 | 語意段落 Chunking | 切片含完整 source/page/section metadata |
| 2.4 | 文字 Embedding pipeline | 批次速度 ≥ 10 chunk/sec |
| 2.5 | 非同步批次上傳 API + Redis 佇列 | 50 份同時上傳,task 正確追蹤 |
| 2.6 | /upload-status 進度 API | 回傳 done/total/errors 正確 |
#### M3:RAG 對話 API 與 MCP 框架(第 7–10 週)
| # | 任務 | 完成標準 |
|---|------|---------|
| 3.1 | 完整 RAG pipeline(含 rerank) | /query 回傳 sources + confidence |
| 3.2 | Cross-Encoder Reranker 整合 | MRR@5 > 0.7 |
| 3.3 | Answer Verification | 低信心答案標注 confidence < 0.6 |
| 3.4 | Multi-Round Retrieval(基礎) | 2 輪檢索正確補強答案 |
| 3.5 | MCP Skill 框架(2 個內建 Skill) | file_convert 與 db_query 可呼叫 |
| 3.6 | 有狀態對話 API | /conversations/{id}/messages 維持上下文 |
#### M4:多模態支援與前端整合(第 11–14 週)
| # | 任務 | 完成標準 |
|---|------|---------|
| 4.1 | 圖片 Embedding(CLIP ViT-B/32) | 圖片 chunk 正確存入 pgvector |
| 4.2 | 多模態查詢支援 | 文字查詢可召回相關圖片 |
| 4.3 | Gradio 前端 UI | 對話視窗、來源顯示、文件上傳功能正常 |
| 4.4 | 客戶端 Agent Client | SQLite 快取對話,離線可查歷程 |
#### M5:安全強化、備份與部署文件(第 15–18 週)
| # | 任務 | 完成標準 |
|---|------|---------|
| 5.1 | TLS 設定(內部 CA) | HTTPS 存取無憑證警告 |
| 5.2 | RBAC 完整實作 | admin/editor/viewer 權限正確隔離 |
| 5.3 | 資料庫備份排程 | 每日自動備份,保留 30 天 |
| 5.4 | 部署手冊驗證 | 新環境依文件可在 4 小時內完成部署 |
| 5.5 | .mmd 圖檔完成與驗證 | 5 個 Mermaid 檔案可正確轉圖 |
---
## 15. 驗收準則
### 15.1 功能驗收
| 測試項目 | 通過標準 |
|---------|---------|
| 離線完整流程 | 斷網後,上傳 → 向量化 → 查詢 → 回應全程可用 |
| 批次匯入成功率 | 100 篇測試文件,處理成功率 ≥ 90% |
| RAG 來源回傳 | 每筆回應均附帶 sources(doc_id / page / excerpt) |
| MCP Skill 呼叫 | 至少 2 個 Skill 可在 RAG 流程中被觸發 |
| 多模態查詢 | 文字查詢可召回相關圖片 chunks |
| Context 超限處理 | 超出 context limit 時系統 graceful 降級,不 crash |
### 15.2 效能驗收
| 指標 | 目標值 |
|------|-------|
| 單次 RAG 查詢回應時間 | P95 < 8 秒(後端伺服器) |
| 批次文件處理速度 | ≥ 5 頁/秒(純文字 PDF) |
| 向量搜尋延遲 | < 100 ms(100 萬筆 chunks) |
| API 並發支援 | 10 concurrent users 無明顯降速 |
---
## 16. 風險管理與降級策略
| 風險 | 等級 | 降級 / 因應策略 |
|------|------|----------------|
| `llama.cpp` API 破壞性更新 | 中 | 鎖定版本標籤;定期評估升級;備援 Ollama |
| Ollama 商業化限制 API | 中 | 切換至 llama.cpp HTTP server(介面已預留)|
| `pgvector` 效能不足 | 低 | 加 HNSW index;分表;評估遷移至 Milvus |
| LangChain 大版本破壞 | 中 | 以介面層隔離呼叫,易於替換底層框架 |
| Tesseract OCR 精準度不足 | 低 | 評估 PaddleOCR 或離線版商業 OCR |
| 繪圖筆電記憶體不足 | 高 | 停用客戶端本地推理,所有推理走後端 |
| 客戶端網路斷線 | 中 | SQLite 快取最近對話;提示使用者目前為離線狀態 |
---
## 17. 交付物清單
| 編號 | 交付物 | 格式 | 所屬里程碑 |
|------|-------|------|-----------|
| D1 | 本 SA 文件 | `sa.md` | M1 |
| D2 | Use Case 圖 | `use_case.mmd` | M1 |
| D3 | UML Class 圖 | `uml_class.mmd` | M2 |
| D4 | 資料庫 Schema 圖 | `database_schema.mmd` | M2 |
| D5 | RAG 對話 Sequence | `sequence_rag.mmd` | M3 |
| D6 | 文件上傳 Sequence | `sequence_upload.mmd` | M2 |
| D7 | API OpenAPI 規格 | `openapi.yaml` | M3 |
| D8 | 可複製部署手冊 | `deploy_guide.md` | M5 |
| D9 | Inference 平台評估報告 | `inference_eval.md` | E2 |
| D10 | RAG 精準度基準測試結果 | `rag_benchmark.md` | M3 |
---
*文件維護人:整合部工程師*
*下次審查:M3 結束後(預計 2026-07-10)*
Comments...
No Comments Yet...