Day 27 我們分析了最終實驗結果。
走到這裡,原本分散的功能已經組成一個小型 Agent 測試驗證平台,包含:
如果只看每天的文章,我們可以跟著一步一步做出功能。
但當功能累積到這個階段,只靠文章順序已經不夠了。
一個專案要能被持續使用和維護,需要有清楚的入口文件。
這份文件至少要回答三個問題:
這個專案在做什麼?
要怎麼跑起來?
結果要怎麼看?
所以 Day 28 要整理專案架構與 README。
Day 28 不加新功能,而是把現有內容整理成容易閱讀、能重現結果,也方便繼續擴充的工程專案。
整理工作包括:
這次先不做:
整理後要達到:
讓專案能被讀懂、跑起來、重現結果。
先把目前專案整理成一棵乾淨的 tree。
README 不需要列出 __pycache__、資料庫檔、舊 eval run 全部 JSON。
列出主要模組的位置就夠了。
可以在 README.md 放這段。
新增 README.md:
# Agent Testing Platform
這是一個簡化版 AI Agent 測試驗證平台。
它的目標不是打造最強的 Agent,而是建立一套流程,讓 Agent 的執行過程可以被記錄、測試、評分、分析與改善。
## Project Structure
```text
agent-testing-platform/
app.py
trace_viewer_app.py
failure_dashboard_app.py
agents/
client_factory.py
fake_llm.py
gemini_llm.py
prompts.py
simple_agent.py
tools/
calculator.py
tracing/
models.py
storage/
database.py
schema.sql
evals/
cases.json
evaluators.py
runner.py
final_experiment_plan.json
final_experiment_runs.md
analyze_final_runs.py
guardrails/
json_schema.py
tool_permissions.py
metrics/
cost.py
ui/
trace_viewer.py
failure_dashboard.py
tests/
test_json_schema_guardrail.py
test_tool_permissions_guardrail.py
```
這段 tree 的重點不是列出所有檔案。
而是讓人一眼看懂:
| 目錄 | 負責內容 |
|---|---|
agents/ |
Agent、LLM client、prompt version |
tools/ |
Agent 可以呼叫的工具 |
tracing/ |
Trace 資料模型 |
storage/ |
SQLite 儲存 |
evals/ |
測試案例、評分、批次 eval、最終實驗 |
guardrails/ |
JSON schema 與 tool permission guardrail |
metrics/ |
token、cost、latency 相關 helper |
ui/ |
Streamlit viewer 與 dashboard |
tests/ |
guardrail 單元測試 |
README 開頭要先回答:
這個專案解決什麼問題?
不是先放安裝指令。
可以這樣寫。
繼續修改 README.md:
## What This Project Does
這個專案示範一個 AI Agent 測試驗證流程:
1. 使用 `SimpleAgent` 執行任務。
2. 記錄每次 Agent 執行的 trace。
3. 使用 eval dataset 批次測試 Agent。
4. 用 rule-based evaluator 自動評分。
5. 將失敗案例分類成 `format_error`、`wrong_answer`、`tool_error` 等類型。
6. 使用 JSON schema guardrail 驗證結構化輸出。
7. 使用 tool guardrail 限制 Agent 可用工具。
8. 記錄 latency、LLM call count、token usage 與 estimated cost。
9. 用 Streamlit dashboard 分析可靠性與失敗原因。
這個專案適合用來理解:
- Agent 為什麼需要 trace。
- 如何建立最小 eval pipeline。
- prompt 改善與 retry 是否真的有效。
- guardrails 如何讓失敗變得可觀察。
- reliability 和 cost 之間如何取捨。
這段文字要務實。
不要寫成:
這是一個 production-ready AgentOps 平台。
因為目前它不是。
它是一個教學用、可重現的 MVP。
接著寫執行環境。
修改 README.md:
## Requirements
- Python 3.12+
- Streamlit
- Pandas
- Pytest
- Gemini API key(如果要使用 Gemini provider)
本專案提供兩種 LLM provider:
| Provider | 說明 |
|---|---|
| `fake` | 本機測試用,不需要 API key |
| `gemini` | 使用 Gemini API,需要 `GEMINI_API_KEY` |
如果專案目前沒有 requirements.txt,可以先在 README 寫手動安裝方式。
例如:
## Installation
```bash
python3 -m venv .venv
source .venv/bin/activate
pip install streamlit pandas pytest google-genai
```
這裡要注意。
如果只用 fake provider 和測試 guardrails,不一定需要 google-genai。
但如果要跑 Gemini,就需要安裝 Gemini SDK。
這個專案已經使用不少環境變數。
README 裡一定要整理。
修改 README.md:
## Environment Variables
| Name | Required | Default | Description |
|---|---|---|---|
| `LLM_PROVIDER` | no | `fake` | `fake` or `gemini` |
| `GEMINI_API_KEY` | only for Gemini | none | Gemini API key |
| `GEMINI_MODEL` | no | project default | Gemini model name |
| `PROMPT_VERSION` | no | `baseline` | `baseline` or `json_strict` |
| `RETRY_ENABLED` | no | `0` | `1` enables retry for JSON format error |
| `EVAL_DELAY_SECONDS` | no | `0` | delay between eval cases |
| `INPUT_COST_PER_1K_TOKENS` | no | `0.0` | estimated input cost |
| `OUTPUT_COST_PER_1K_TOKENS` | no | `0.0` | estimated output cost |
如果要使用 Gemini:
```bash
export GEMINI_API_KEY="your-api-key"
```
如果只是要本機驗證流程,可以使用 fake provider:
```bash
LLM_PROVIDER=fake python3 -m evals.runner
```
這段很重要。
因為如果沒有說清楚,使用者很容易遇到:
ValueError: GEMINI_API_KEY is not set
README 應該讓這種錯誤變得可預期。
接著寫最短路徑。
第一次看專案的人通常想知道:
我要打哪幾個指令才看得到成果?
修改 README.md:
## Quick Start
### 1. Run the Agent
使用 fake provider:
```bash
LLM_PROVIDER=fake python3 app.py
```
使用 Gemini:
```bash
export GEMINI_API_KEY="your-api-key"
LLM_PROVIDER=gemini PROMPT_VERSION=json_strict python3 app.py
```
### 2. Run Evaluation
本機流程驗證:
```bash
RETRY_ENABLED=0 LLM_PROVIDER=fake python3 -m evals.runner
```
使用 Gemini 執行 eval:
```bash
EVAL_DELAY_SECONDS=10 \
RETRY_ENABLED=0 \
PROMPT_VERSION=json_strict \
LLM_PROVIDER=gemini \
python3 -m evals.runner
```
### 3. Run Tests
```bash
python3 -m pytest tests/test_json_schema_guardrail.py
python3 -m pytest tests/test_tool_permissions_guardrail.py
```
這裡不要一次塞太多指令。
README 的目標是讓人能成功跑起第一輪。
更完整的實驗指令可以放在後面。
目前有兩個 Streamlit app:
README 要清楚分開。
修改 README.md:
## Dashboards
### Trace Viewer
Trace Viewer 用來查看單次 Agent 執行過程。
```bash
streamlit run trace_viewer_app.py
```
可以用來查看:
- user input
- LLM response
- tool call
- tool result
- final answer
- error
### Reliability Dashboard
Reliability Dashboard 用來分析 eval run。
```bash
streamlit run failure_dashboard_app.py
```
可以用來查看:
- success rate
- failed cases
- failure type distribution
- task type failure rate
- latency
- LLM call count
- token usage
- estimated cost
- prompt version comparison
這裡檔名仍然是 failure_dashboard_app.py。
雖然 Day 24 把它擴充成 Reliability Dashboard,但入口檔沿用 Day 17 的命名。
README 可以直接說明:
failure_dashboard_app.py now renders the Reliability Dashboard.
如果未來要整理得更漂亮,可以把檔案改名成 reliability_dashboard_app.py。
但 Day 28 先不做這個重構。
README 可以用 Mermaid 畫簡單流程圖。
GitHub Markdown 支援 Mermaid,所以不需要另外產生圖片。
修改 README.md:
## System Flow
```mermaid
flowchart TD
A[User Task] --> B[SimpleAgent]
B --> C[LLM Client]
C --> D{Tool Call?}
D -- yes --> E[Tool Guardrail]
E --> F[Tool Execution]
F --> G[Trace Recorder]
D -- no --> G
G --> H[SQLite Storage]
I[Eval Cases] --> J[Eval Runner]
J --> B
J --> K[JSON Schema Guardrail]
K --> L[Rule-based Evaluator]
L --> M[Eval Run JSON]
M --> N[Reliability Dashboard]
```
這張圖說明兩條線:
這比單純列檔案更容易讓讀者理解系統。
Day 26 和 Day 27 的結果也應該放進 README。
但 README 不需要貼所有 case output。
只要放摘要。
修改 README.md:
## Final Experiment Summary
Final experiment 使用同一份 `evals/cases.json`,比較 baseline prompt、`json_strict` prompt 和 retry。
| Experiment | Passed | Failed | Success Rate | LLM Calls | Total Latency |
|---|---:|---:|---:|---:|---:|
| baseline / no retry | 10 | 5 | 66.7% | 15 | 88262.05 ms |
| json_strict / no retry | 13 | 2 | 86.7% | 15 | 80131.38 ms |
| baseline / retry | 11 | 4 | 73.3% | 18 | 105118.41 ms |
| json_strict / retry | 12 | 3 | 80.0% | 15 | 79742.16 ms |
在目前這組 eval dataset 上,`json_strict / no retry` 是最值得保留的設定。
原因是:
- success rate 最高。
- JSON format error 從 3 降到 0。
- 沒有增加 LLM calls。
Retry 仍然有價值,但比較適合做為 JSON format error 的備援策略。
這段要延續 Day 27 的保守結論。
不要寫成:
json_strict 永遠最好。
而是:
在目前這組 eval dataset 上最值得保留。
Day 27 新增了 evals/analyze_final_runs.py。
README 也要讓讀者知道怎麼用。
修改 README.md:
## Analyze Final Runs
```bash
python3 -m evals.analyze_final_runs
```
這個指令會讀取 final experiment 的 eval run JSON,輸出:
- success rate
- failure type counts
- LLM calls
- total tokens
- total latency
- average latency
- estimated cost
這樣 README 也能當成專案的操作入口。
它也變成重現實驗的入口。
目前測試主要集中在 guardrails。
這要誠實寫。
修改 README.md:
## Tests
目前測試涵蓋:
- JSON schema guardrail
- Tool permission guardrail
執行:
```bash
python3 -m pytest tests/test_json_schema_guardrail.py
python3 -m pytest tests/test_tool_permissions_guardrail.py
```
目前尚未完整測試:
- Gemini API integration
- Streamlit UI
- SQLite persistence edge cases
- end-to-end eval runner
這樣寫比假裝測試完整更好。
清楚說明測試範圍,會讓後續維護者知道哪些地方已經被驗證,哪些地方還需要補測。
Day 29 會完整談限制和未來工作。
但 README 可以先放短版。
修改 README.md:
## Limitations
這是一個 MVP,不是 production-ready AgentOps 平台。
目前限制包含:
- eval dataset 規模很小。
- rule-based evaluator 對語意等價答案不夠寬容。
- token usage 和 cost 是估算,不是真實 billing。
- Gemini API 可能受到 quota 和 429 影響。
- dashboard 主要用於觀察,不包含完整實驗管理功能。
- 目前沒有支援 resume failed cases。
更多限制與未來工作會在 Day 29 整理。
這段很重要。
README 不應該只寫專案做得到的事情。
能清楚說明限制,才能讓使用者知道系統邊界在哪裡。
除了 README,也可以補一個 .env.example。
這不是必要,但很實用。
新增 .env.example:
LLM_PROVIDER=fake
GEMINI_API_KEY=
GEMINI_MODEL=
PROMPT_VERSION=baseline
RETRY_ENABLED=0
EVAL_DELAY_SECONDS=0
INPUT_COST_PER_1K_TOKENS=0.0
OUTPUT_COST_PER_1K_TOKENS=0.0
這個檔案不要放真的 API key。
它只是告訴使用者有哪些環境變數可以設定。
如果之後加入 .gitignore,也可以提醒:
.env
不要被 commit。
整理後,README.md 可以長這樣。
新增 README.md:
# Agent Testing Platform
這是一個簡化版 AI Agent 測試驗證平台。
它的目標不是打造最強的 Agent,而是建立一套流程,讓 Agent 的執行過程可以被記錄、測試、評分、分析與改善。
## What This Project Does
這個專案示範一個 AI Agent 測試驗證流程:
1. 使用 `SimpleAgent` 執行任務。
2. 記錄每次 Agent 執行的 trace。
3. 使用 eval dataset 批次測試 Agent。
4. 用 rule-based evaluator 自動評分。
5. 使用 guardrails 檢查 JSON schema 與 tool permission。
6. 記錄 latency、LLM call count、token usage 與 estimated cost。
7. 用 Streamlit dashboard 分析可靠性與失敗原因。
## Project Structure
```text
agent-testing-platform/
app.py
trace_viewer_app.py
failure_dashboard_app.py
agents/
tools/
tracing/
storage/
evals/
guardrails/
metrics/
ui/
tests/
```
## Requirements
- Python 3.12+
- Streamlit
- Pandas
- Pytest
- Gemini API key(如果使用 Gemini provider)
## Environment Variables
| Name | Required | Default | Description |
|---|---|---|---|
| `LLM_PROVIDER` | no | `fake` | `fake` or `gemini` |
| `GEMINI_API_KEY` | only for Gemini | none | Gemini API key |
| `PROMPT_VERSION` | no | `baseline` | `baseline` or `json_strict` |
| `RETRY_ENABLED` | no | `0` | `1` enables retry |
| `EVAL_DELAY_SECONDS` | no | `0` | delay between eval cases |
| `INPUT_COST_PER_1K_TOKENS` | no | `0.0` | estimated input cost |
| `OUTPUT_COST_PER_1K_TOKENS` | no | `0.0` | estimated output cost |
## Quick Start
```bash
RETRY_ENABLED=0 LLM_PROVIDER=fake python3 -m evals.runner
```
Use Gemini:
```bash
export GEMINI_API_KEY="your-api-key"
EVAL_DELAY_SECONDS=10 \
RETRY_ENABLED=0 \
PROMPT_VERSION=json_strict \
LLM_PROVIDER=gemini \
python3 -m evals.runner
```
## Dashboards
Trace Viewer:
```bash
streamlit run trace_viewer_app.py
```
Reliability Dashboard:
```bash
streamlit run failure_dashboard_app.py
```
## System Flow
```mermaid
flowchart TD
A[User Task] --> B[SimpleAgent]
B --> C[LLM Client]
C --> D{Tool Call?}
D -- yes --> E[Tool Guardrail]
E --> F[Tool Execution]
F --> G[Trace Recorder]
D -- no --> G
G --> H[SQLite Storage]
I[Eval Cases] --> J[Eval Runner]
J --> B
J --> K[JSON Schema Guardrail]
K --> L[Rule-based Evaluator]
L --> M[Eval Run JSON]
M --> N[Reliability Dashboard]
```
## Final Experiment Summary
| Experiment | Passed | Failed | Success Rate | LLM Calls | Total Latency |
|---|---:|---:|---:|---:|---:|
| baseline / no retry | 10 | 5 | 66.7% | 15 | 88262.05 ms |
| json_strict / no retry | 13 | 2 | 86.7% | 15 | 80131.38 ms |
| baseline / retry | 11 | 4 | 73.3% | 18 | 105118.41 ms |
| json_strict / retry | 12 | 3 | 80.0% | 15 | 79742.16 ms |
在目前這組 eval dataset 上,`json_strict / no retry` 是最值得保留的設定。
## Tests
```bash
python3 -m pytest tests/test_json_schema_guardrail.py
python3 -m pytest tests/test_tool_permissions_guardrail.py
```
## Limitations
- eval dataset 規模很小。
- rule-based evaluator 對語意等價答案不夠寬容。
- token usage 和 cost 是估算。
- Gemini API 可能受到 quota 和 429 影響。
- dashboard 主要用於觀察,不包含完整實驗管理功能。
這個版本已經足夠作為第一版 README。
它清楚交代:
這一篇處理的是工程整理,沒有新增 Agent 能力。
完成內容包含:
README.md。.env.example。整理後可以做到:
讓專案從「功能已經做出來」變成「流程可以被理解與重現」。
如果專案沒有 README,即使功能完成,後續使用者仍然很難知道怎麼啟動、測試和判讀結果。
Day 29 會整理限制、風險與未來工作。
README 目前只放短版 limitations。
明天會更完整地討論:
下一篇會補齊風險與限制,讓系統邊界交代得更清楚。