很多教材教你「Agent 是什麼」,然後就停在那裡。這篇走相反的路線:用一個專案從頭到尾做完一遍,把 第一次 API 呼叫、Prompt 設計、Function Calling、迴圈、RAG 與 Eval 串成一條線。專案很樸素——一個「論文小助理」:給它一個題目,它抓摘要、評分、整理成一段筆記。但它會經過每一個真正重要的關卡。
這篇改編自 awesome-agentic-ai-zh 的整合教學(MIT 授權,見文末出處),程式碼大幅精簡;完整版含雲端路徑與成本試算,連結在文末。
| 步驟 | 做什麼 | 產出 |
|---|---|---|
| 第 0 步 | 環境準備 | 可跑的 Python 3.11+Ollama |
| 第 1 步 | 第一次呼叫 LLM | hello_llm.py |
| 第 2 步 | Prompt 寫成四格 | 穩定的摘要輸出 |
| 第 3 步 | Tool Use | 自動抓論文摘要 |
| 第 4 步 | 迴圈+反思 | 會重試的 agent |
| 第 6 步 | RAG 記憶 | 帶證據的回答 |
| 第 7 步 | Eval+觀測+剎車 | 可重跑的品質檢查 |
| 第 8 步 | 最小的門 | CLI 介面與安全出口 |
(上游教材刻意跳過第 5 步的生態系內容——從零打造的專案用不到,先不學。)
第 0 步:環境準備
一次裝完後面所有步驟會用到的東西。Ollama 走本機路徑,API 費用是 0;你的電力與硬體當然還是成本。
python3 --version # 需要 3.11 以上
python3 -m pip install "openai>=1.0,<3"
ollama pull qwen2.5:3b # 入門小模型,跑得動就好
ollama serve # 預設 port 11434
建一個資料夾放這個專案,並用 Git 保存每一步的成果——第 7 步的「復原」全靠它。
第 1 步:第一次呼叫 LLM
五行核心呼叫。重點不是輸出多漂亮,而是從 usage 讀到 token 數:這是你之後算成本、看延遲的入口。
# step1_hello_llm.py
from openai import OpenAI
client = OpenAI(base_url="http://localhost:11434/v1", api_key="ollama")
r = client.chat.completions.create(
model="qwen2.5:3b",
max_tokens=100,
messages=[{"role": "user", "content": "用一句話自我介紹。"}],
)
print(r.choices[0].message.content)
print("output tokens:", r.usage.completion_tokens)
第 2 步:把 Prompt 寫成四格
「幫我整理」這種模糊要求,改成目標、資料、規則、輸出四格。資料會換、規則不換,這就是可重用的 prompt。
# step2_paper_summary.py(節錄)
SYSTEM_PROMPT = """目標:把一段論文摘要整理成三行研究筆記。
規則:只根據資料;找不到的地方寫「未提及」。
輸出:三行,每行以「·」開頭。"""
def summarize(text: str) -> str:
r = client.chat.completions.create(
model="qwen2.5:3b",
messages=[{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": f"資料:<input_data>{text}</input_data>"}],
)
return r.choices[0].message.content
第 3 步:Tool Use:自動抓論文
模型自己不能上網。你宣告一個工具(schema 就是它的說明卡),模型回傳「我想呼叫 fetch_abstract,參數是……」,你的程式檢查、執行、把結果送回去。
# step3_tool_use.py(節錄)
TOOLS = [{
"type": "function",
"function": {
"name": "fetch_abstract",
"description": "依 arXiv 論文 ID 抓摘要",
"parameters": {
"type": "object",
"properties": {"paper_id": {"type": "string",
"description": "例如 2210.03629"}},
"required": ["paper_id"],
"additionalProperties": False,
},
},
}]
兩條鐵律:只執行 allowlist 裡的工具名稱;參數當不可信輸入檢查。完整的五步往返與 Function Calling 入門 那篇相同。
第 4 步:加迴圈與反思
把第 3 步的單次往返包進迴圈,就得到最小 Agent Loop。上限(MAX_STEPS)不是可選的裝飾——沒有它,模型卡住時你的程式會陪它繞圈到天亮。
# step4_loop.py(核心 13 行)
for step in range(MAX_STEPS):
resp = ask_model(messages, tools)
calls = read_tool_calls(resp)
if not calls:
break # 沒有工具請求 → 視為完成
for call in calls:
name, args, call_id = validate_call(call) # allowlist+參數檢查
result = TOOL_IMPL[name](**args)
messages.append(make_tool_result(call_id, result))
else:
raise RuntimeError(f"超過 {MAX_STEPS} 步,停止")
反思(reflection)先做最便宜的版本:如果輸出缺了「未提及」標記或行數不對,把錯誤描述當下一輪的 user 訊息再跑一次。一次只改一件事,你才知道是哪個改動有效。
第 6 步:加 RAG 記憶
到目前為止,模型每次都是從零開始。RAG 給它一本可以翻的筆記本:把抓過的摘要切成小塊、轉成向量存起來,回答前先檢索最相關的幾塊放進 prompt。
# step6_rag.py(節錄)
collection.add(ids=[paper_id], documents=[abstract]) # 存入 Chroma
hits = collection.query(query_texts=[question], n_results=3)
context = "\n---\n".join(hits["documents"][0])
# 把 context 放進 prompt,並要求「引用編號」
兩個誠實規則:回答要附來源;檢索不到證據就說「不知道」。RAG 不等於記憶——跨 session 的偏好保存是另一件事,細節見 RAG 深入原理。
第 7 步:Eval、觀測與剎車
沒有這步,前面一切都只是「在我面前成功過」。三件事:
# step7_eval.py(節錄)
CASES = [
{"q": "ReAct 是什麼?", "must_contain": ["Reasoning", "Acting"]},
{"q": "隨便一個不存在的詞", "must_contain": ["不知道"]},
]
for c in CASES:
answer = agent_answer(c["q"])
ok = any(k in answer for k in c["must_contain"])
print(("PASS" if ok else "FAIL"), c["q"])
# 每次執行記一行:時間、步數、token、結果
log.write(f"{ts}\t{steps}\t{tokens}\t{ok}\n")
固定題目(case)不可中途偷換,否則兩次分數無從比較;高風險動作(寄信、刪檔、付款)加人工確認;每次執行留下可以事後查看的紀錄。這套就是 評測指南 講的最小 Eval。
第 8 步:選最小的門
專案最後一步是選介面。判斷順序:只找資料 → Web Search/Fetch;工作都在網頁裡 → Browser Use;跨桌面 → Computer Use;跑別人寫的程式碼 → Sandbox。能用最小的門,就不要開最大的。這個專案只需要 CLI——一個 argparse 入口就是合格的介面。
底線:七步通用的安全規則
不管走到哪一步,這五條不變:只執行 allowlist 裡的工具;參數當不可信輸入;工具只拿最小權限;高風險動作先問人;設上限(輪數、timeout、費用)。它們來自上游教材的重複叮嚀,也是本站 Agent Harness 概念的核心。
常見卡點與解法
- 模型不呼叫工具:固定 prompt、模型與 schema 重跑三次再下結論,不要用一次失敗宣布「不支援」。
- 回應被截斷:降低輸入長度或 max_tokens,並查該型號的 context 上限。
- 工具結果對不上:call ID 沒有正確回填——照規格把每個 tool result 綁回原請求。
- 分數忽高忽低:trial 次數太少;同一題至少跑五次看分佈。
下一步
- 把這七步對應到本站的學習地圖:每一步都有獨立站點可以深入(第一次 API 呼叫、Function Calling、RAG、Eval)。
- 想看完整版(含雲端路徑、成本試算與逐行解說):上游的七步教學原文在awesome-agentic-ai-zh(MIT)。
- 做完之後,拿它去申請地圖的結業專題:把五題 Eval 換成你自己領域的題目。