TL;DR:你只有真正重建一個系統,才能真正理解它。我在學校用 C 語言重新實作 TCP,之後又重寫 DNS 協定與 Modbus,每次都是為了從內部理解它。一位同事最近也用同樣方式理解 LLM。他用 Go 寫了一個小型代理,終於搞懂工具呼叫與上下文視窗。LLM 不過是另一個需要解謎的系統。重建一個微型版本,就能從使用者變成工程師。
給想精通 LLM、而非只是使用它的開發者。
一位同事、一個 Go 代理、一次領悟
這週我正在協助一位同事提升 LLM 技能。我解釋概念:上下文、token、工具。token 是模型讀取並計數的一小段文字。他聽懂了,但仍缺少那個「啊哈」時刻。
後來他回來,興奮地說他用 Go 寫了一個小型 CLI:一個純聊天迴圈,能呼叫模型並執行其工具。現在他懂了。工具、上下文視窗、迴圈。不是因為我解釋,而是因為他親手重建。
我對這種領悟再熟悉不過。我在其他主題上也多次感受過。方法永遠相同:要理解某件事,我就重建它。
你只有重建系統才能理解它
閱讀文件給你一張地圖。重建則讓你踏上真實地形。兩者並不相同。地圖說「這裡有條河」,地形則讓你感受水流。
當你重寫一個系統,你再也無法蒙混。每個位元組都必須放在正確位置。每個邊緣案例都落在你身上。你不再「以為」自己懂。你真的懂,否則程式會失敗。
這不是學術練習。恰恰相反。你重建是為了之後能更好地行動。能更快除錯。能改造工具。能打造市售函式庫無法提供的東西。
C 語言中的 TCP:第一次
第一次是在學校,用 C 語言。我重寫 TCP 與 UDP 的一小部分。著名的三次交握,以及逐欄位剖析標頭。
TCP 用三個訊息開啟連線:SYN、SYN-ACK、ACK。以前這只是講義上的一行。之後,我親手將這些位元組放入封包。
我沒有發明任何東西。協定已存在四十年。但重做一次改變了我看待網路的方式。從此封包捕捉對我不再神秘。它是我親手寫過的格式。
DNS:重寫協定以操控其子網域
後來我挑戰 DNS。DNS 將像 jrobineau.com 這樣的名稱轉成 IP 位址。我用 Go 親自重寫。標頭、問題、回答,一個位元組一個位元組。
重建過程中,你會遇到文件略過的細節。網域名稱是一系列標籤。每個標籤前面有其長度。「www」是 3,後面接 w、w、w。
接著靈感出現:如果我能控制標籤,我就控制位元組。我可以把自己的資料藏進子網域。這就是 DNS 滲透的基本原理,在授權的安全情境中。
我的伺服器接收查詢、剖析名稱,並取出隱藏在其中的資料。我甚至處理了名稱壓縮,這是協定中棘手的角落。現成函式庫不會告訴你這些。重建才會。
Modbus:重建以找出誰該為錯誤負責
在一個工業硬體專案中,我們使用 Modbus 通訊。Modbus 是驅動控制器與感測器的老協定。我們使用的函式庫很差。有很多錯誤、奇怪的行為。
無法分辨問題來自哪裡。是協定?函式庫?還是我們的程式碼?所以我做了唯一能解決疑問的事:我用 Go 親自重寫 Modbus。
結論:協定沒問題。罪魁禍首是函式庫。一旦協定重建完成,真正的收穫來了。我能用自己的方式圍繞它打造工具。
我把它變成一個小型 Go 函式庫,擁有類似 Gin 的 API。你為每個暫存器範圍宣告處理器。你加入日誌與復原中介軟體。一個 1979 年的工業協定,卻擁有 Web 框架的舒適度。這就是將知識轉化為你所需的能力。
LLM 是另一個需要重建的系統
回到 LLM。2026 年,AI 被宣傳為魔法。一個你對話的黑盒子。而你只是使用者,有點被動,有點任其擺布。
但 LLM 代理不是魔法。它是一個迴圈。你傳送訊息給模型。它回應,有時要求工具。你執行工具。你把結果傳回。然後再來一次。
上下文視窗是模型此刻看到的一切。你的迴圈決定放入什麼、丟棄什麼。模型不記得任何事。是你在每回合餵給它過去的內容。
以下是用 Go 寫的完整迴圈。去掉華麗外衣,只剩下這些。
func runAgent(ctx context.Context, client LLM, tools map[string]Tool, goal string) (string, error) {
// The context window is this list. You alone fill it.
msgs := []Message{{Role: "user", Content: goal}}
for {
// 1. You send the whole context to the model.
reply, err := client.Complete(ctx, msgs, tools)
if err != nil {
return "", err
}
msgs = append(msgs, reply)
// 2. No tool requested? The model is done, you return.
if len(reply.ToolCalls) == 0 {
return reply.Content, nil
}
// 3. You run each tool yourself, not the model.
for _, call := range reply.ToolCalls {
out := tools[call.Name].Run(ctx, call.Args)
// 4. You feed the result back into the context. Loop again.
msgs = append(msgs, Message{Role: "tool", Content: out})
}
}
}
Enter fullscreen mode Exit fullscreen mode
一旦寫完這個,恐懼就消散了。「代理」就是這個迴圈加上幾個好工具。工具呼叫只是模型告訴你該呼叫哪個函式。僅此而已。
重建,是的,但不是一切,也不是永遠
目標不是終身重寫一切。我不會把自己的 TCP 堆疊部署到生產環境。我使用系統提供的,而且我做對了。
你重建一次,為了理解。然後你信任,因為你知道盒子裡有什麼。這是贏得的信任,而不是盲目的信任。
當 stakes 高時才重建。產品核心的協定。你會經常除錯的工具。像 LLM 這樣的新技術,每個人都停留在表面。這就是理解能帶來回報的地方。
透過重建學習技術的清單
下次有技術讓你印象深刻,不要只使用它。重建它的一部分。
- [ ] 瞄準核心,而非舒適區。代理迴圈,而非整個廠商 API
- [ ] 保持小規模。一個 CLI、一個檔案、一個下午通常就夠了
- [ ] 親手寫一次格式。位元組會教你文件隱藏的東西
- [ ] 尋找解鎖的細節。DNS 標籤、上下文迴圈
- [ ] 故意讓它壞掉。你會快速看到限制與陷阱
- [ ] 函式庫讓你失望?重建以找出誰真正該負責
- [ ] 一旦理解,就改造它。打造市售函式庫無法提供的工具
- [ ] 然後丟掉你的玩具版本。回到生產函式庫,帶著真正的心理模型
要記住的事
開發者的精神從未改變。在不理解的情況下使用工具,意味著任其擺布。重建它,即使只是玩具,也能奪回控制權。
TCP、DNS、Modbus、LLM 代理。每一次都是相同的方法。重建以理解。理解以改造。LLM 只是清單上的下一個系統。
想為團隊培訓 LLM,或需要穩固的 Go 後端?這就是我做的事。寫信給我。我們不被工具折磨。我們理解它們。
Sources: RFC 1035, DNS format · RFC 9293, TCP · Modbus Application Protocol · Anthropic, Building effective agents
0 Comments
Log in to join the conversation.No comments yet. Be the first to share your thoughts.