Jules Robineau

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