MyClaude源碼分析:從零仿製ClaudeCode

作者:Agent工程化
日期:2026年5月5日 上午2:39
來源:WeChat 原文

整理版優先睇

速讀 5 個重點 高亮

500行Python復現Claude Code核心機制的開源學習項目

整理版摘要

呢篇文章係由一位開發者分享佢嘅學習項目MyClaude,目的係用約500行Python代碼,從零復現Claude Code嘅核心交互循環,包括CLI界面、XML工具調用解析、LLM對話管理、文件操作同Bash執行。作者想透過呢個極簡實現,拆解AI編碼助手嘅底層原理,同時為日後AI自我進化留空間。整體結論係:用分層架構、容錯優先嘅正則解析、智能重試機制同配置驅動設計,可以喺極少代碼量下達到完整閉環,適合想理解呢類工具點運作嘅開發者。

首先,項目採用五層分層架構,由下至上分別係配置層、消息層、查詢層、工具層同表現層,每層職責單一,模塊間透過回調注入解耦。系統提示詞係成個項目最核心嘅資產,用六層分層規則設計,比單一長提示詞更易維護。工具解析器利用正則表達式提取XML標籤,對LLM嘅非嚴格輸出有天然容錯性。重試機制檢測到截斷時會翻倍max_tokens再試,而非等時間,更切合截斷原因。

總括而言,MyClaude展示咗「極簡、完整、可進化」嘅設計哲學,每個機制都有清晰取捨。文章詳細拆解咗入口、配置加載、提示詞設計、消息管理、LLM調用、工具解析、工具執行同CLI界面,並提供實踐指南。呢啲內容對想自建AI Agent系統、研究提示詞工程或學習最小可行AI編碼助手架構嘅讀者好有參考價值。

  • 用約500行Python完整實現Claude Code嘅核心交互循環,涵蓋CLI、工具解析、對話管理等。
  • 系統提示詞採用六層分層規則,比單一長提示詞更易維護同調優,並包含正反示例。
  • 工具解析使用正則表達式而非XML解析器,對LLM嘅非嚴格輸出有更強容錯性。
  • 重試機制採用指數擴增token配額(而非等待時間),更符合截斷原因係token不足嘅現實。
  • 項目設計為可進化架構,所有可調參數集中喺配置檔,便於AI日後自我修改及測試。
值得記低
連結 github.com

MyClaude 專案倉庫

GitHub上嘅源碼及文檔,適合想深入研究或自行部署嘅開發者。

結構示例

內容片段

內容片段 text
src/
├── myclaude.py              # 入口:參數解析、CLI 啓動
├── cli/
│  ├──mycli.py # CLI 主循環:輸入處理、命令路由
│   └── cli_print.py         # 終端輸出:彩色打印、Markdown 渲染
├── llm_tool/
│   ├── tool_executor.py     # 工具解析與執行調度
│   └── cmd_bash.py          # Bash 命令執行
├── message/
│   ├── llm_api_msg.py       # API 消息管理
│   └── sys_prompt.py        # 系統提示詞定義
├── query/
│   ├── query_loop.py        # 核心查詢循環
│   ├── chat_llm.py          # LLM API 調用(同步/流式/異步)
│   └── session_log.py       # 會話日誌記錄
└── utility/
    ├── config_loader.py     # 配置加載與全局單例
    ├── file_tool.py         # 文件操作(view/create/str_replace)
    └── normal_utility.py    # 通用工具(thinking 過濾等)
整理重點

項目背景與目標

MyClaude係一個學習性開源項目,作者想用極簡方式復現Claude Code嘅核心機制。目標分兩步:先做一個功能精簡嘅0.01版本,實現基本編碼對話循環;再期望呢個版本可以喺AI輔助下自我進化到0.1版本。

麻雀雖小,五臟俱全

項目使用Python(約500行有效代碼)、MiniMax M2.7 LLMRich庫做終端UI,同埋XML格式工具系統。設計理念係極簡實現、完整閉環同可進化。

整理重點

核心架構與模塊職責

項目採用分層架構,從下到上分為配置層、消息層、查詢層、工具層同表現層。核心循環由QueryLoop驅動,流程係:用戶輸入 → LLM調用 → 工具解析 → 工具執行 → 結果反饋,直到收到done信號。

QueryLoop不持有任何終端輸出邏輯

模塊劃分好清晰:myclaude.py係入口,cli/處理用戶交互,llm_tool/負責工具解析同執行,message/管理系統提示詞同API消息,query/控制查詢循環同LLM調用,utility/提供配置加載同文件操作。

工具執行結果以user角色追加入消息列表

呢種設計令到LLM將工具結果視為用戶反饋,自然理解後續操作。done工具係循環終止唯一信號。

整理重點

源碼分析亮點

系統提示詞係最核心資產,採用六層分層規則:強制編碼信號、普通模式區分、衝突仲裁、代碼規範、任務終止規則同環境約束。每層處理獨立決策,高層覆蓋低層。

正反示例對比

提示詞包含正向同反向示例,教LLM正確交付代碼:必須用XML標籤,禁止Markdown代碼塊。

工具解析器使用正則而非XML解析器,原因係LLM輸出天然包含唔合法XML(如唔閉合嘅done標籤),正則對格式錯誤有天然容錯性。

str_replace支援精確代碼替換

五個工具嘅正則按出現位置排序,保持原始順序。非工具文本保留展示,實現對話加工具調用混合輸出。

連續三個以上換行壓縮為兩個

重試機制採用指數擴增token配額:檢測到截斷即翻倍max_tokens,最多重試3次或達到上限64000。呢個設計基於洞察:截斷通常因token不足,而非網絡波動。

智能重試機制

文件操作安全邊界:相對路徑拼接至code_output_root目錄,create拒絕覆蓋已有文件,bash執行有30秒超時。

工具執行安全邊界

整理重點

功能詳解:查詢循環與模式切換

QueryLoop.run()每個用戶查詢會話包含最多max_turns輪循環。首次輪發送用戶輸入,後續輪追加工具結果。對話模式同編碼模式透過is_chat_mode標記切換。

一旦LLM開始用工具,就必須明確發done才能結束

如果LLM未返回任何工具(包括done),系統直接結束並提示用戶,防止無限掛起。最後一輪會提前追加指令「請立刻完成,使用<done>標記結束」。

温和嘅強制終止機制

回調注入模式實現查詢邏輯與表現層完全解耦。QueryLoop接收五個回調函數,可以替換為WebSocketGUI等任何表現形式。

CLI界面支援斜槓命令:/quit、/clear、/help、/tokens。輸出渲染透過Rich庫實現Markdown渲染、語法高亮同打字機效果。

整理重點

實踐指南與總結

環境準備好簡單:安裝openai、rich、pyyaml、numpy等依賴。配置檔config.yaml分五組:model、model_chat、memory、code_project、cli,關鍵項包括api_key、max_turns同code_output_root。

所有可調參數集中管理

運行指令係python src/myclaude.py,啓動後直接輸入自然語言即可互動。當AI檢測到編碼意圖就會自動切換工具模式。總結嚟講,MyClaude用極簡代碼實現咗完整AI編碼助手循環,關鍵設計包括極簡分層架構、分層提示詞、容錯優先解析器同安全執行邊界。

適合理解AI Coding助手底層原理

MyClaude 係一個學習性項目,用大約 500 行 Python 程式碼實現咗 Claude Code 嘅核心交互循環——CLI 界面、XML 工具調用解析、LLM 對話管理、檔案操作同 Bash 執行。本文逐模組拆解佢嘅源碼架構,分析系統提示詞嘅分層規則設計、工具調用解析器嘅正則匹配策略、帶自動擴容嘅重試機制,以及配置驅動嘅模組化設計思想,適合想理解 AI Coding 助手底層原理嘅開發者睇。

目錄

  1. 概述
      1.1 項目背景
      1.2 技術棧
      1.3 設計目標
  2. 核心架構
      2.1 整體架構概覽
      2.2 模塊職責劃分
      2.3 主循環流程
  3. 源碼分析
      3.1 入口與配置加載
      3.2 系統提示詞設計
      3.3 消息管理
      3.4 LLM 調用與重試
      3.5 工具調用解析
      3.6 工具執行
      3.7 CLI 界面
  4. 功能詳解
      4.1 查詢循環
      4.2 工具調用流程
      4.3 對話模式與編碼模式切換
  5. 技術亮點
      5.1 分層規則系統
      5.2 正則解析器設計
      5.3 智能重試機制
      5.4 配置驅動的模塊化
      5.5 工具執行安全邊界
  6. 實踐指南
      6.1 環境準備
      6.2 配置說明
      6.3 運行與調試
  7. 總結
    參考文獻

1. 概述

1.1 項目背景

MyClaude 係一個用嚟學習同研究 Claude Code 工作原理嘅開源項目。佢嘅目標分做兩步:首先整一個功能精簡嘅 0.01 版本,實現基本嘅編碼對話循環;然後期望呢個 0.01 版本能夠喺 AI 輔助下自我進化到 0.1 版本。項目嘅設計理念係「麻雀雖小,五臟俱全」——喺好少嘅程式碼量入面覆蓋 AI 編程助手嘅核心機制。

1.2 技術棧

  • 語言:Python 100%(約 500 行有效程式碼)
  • LLM:MiniMax M2.7(通過 OpenAI 兼容接口調用)
  • 終端 UI:Rich 庫(Markdown 渲染、語法高亮)
  • 配置:YAML(通過 PyYAML 解析為 SimpleNamespace)
  • 工具系統:XML 標籤格式(view / create / str_replace / bash / done)

1.3 設計目標

  • 極簡實現:核心程式碼量控制在 500 行以內,每個模塊職責單一
  • 完整閉環:覆蓋「用戶輸入 → LLM 調用 → 工具解析 → 工具執行 → 結果反饋」嘅完整鏈路
  • 可進化:架構設計為 AI 自我修改留有空間,支持後續嘅自動進化

2. 核心架構

2.1 整體架構概覽

項目採用分層架構,從下到上分為五個層次:

  • 配置層(utility/config_loader.py):YAML 配置加載,全局單例模式
  • 消息層(message/):系統提示詞管理、API 消息構建
  • 查詢層(query/):LLM 調用、重試邏輯、會話日誌
  • 工具層(llm_tool/):XML 解析、工具執行、檔案操作
  • 表現層(cli/):CLI 交互、輸出渲染、命令處理
圖片

流程執行說明:

  • 階段一(步驟 1-2):CLI 接收用戶輸入,傳遞畀 QueryLoop 啟動查詢循環
  • 階段二(步驟 3-5):QueryLoop 構建 API 消息,調用 LLM 並獲取響應
  • 階段三(步驟 6-12):解析 LLM 響應入面嘅工具調用,執行工具操作,將結果反饋畀 LLM
  • 階段四(步驟 13):LLM 返回 done 或冇工具嘅時候,結束循環並展示結果

關鍵規則:

  • QueryLoop 唔持有任何終端輸出邏輯,所有輸出通過回調函數注入
  • 工具執行結果以 [tool_name] 工具執行結果:... 嘅格式追加到消息歷史
  • done 工具係循環終止嘅唯一信號

2.2 模塊職責劃分

項目源碼目錄結構如下:

src/
├── myclaude.py              # 入口:參數解析、CLI 啓動
├── cli/
│  ├──mycli.py # CLI 主循環:輸入處理、命令路由
│   └── cli_print.py         # 終端輸出:彩色打印、Markdown 渲染
├── llm_tool/
│   ├── tool_executor.py     # 工具解析與執行調度
│   └── cmd_bash.py          # Bash 命令執行
├── message/
│   ├── llm_api_msg.py       # API 消息管理
│   └── sys_prompt.py        # 系統提示詞定義
├── query/
│   ├── query_loop.py        # 核心查詢循環
│   ├── chat_llm.py          # LLM API 調用(同步/流式/異步)
│   └── session_log.py       # 會話日誌記錄
└── utility/
    ├── config_loader.py     # 配置加載與全局單例
    ├── file_tool.py         # 文件操作(view/create/str_replace)
    └── normal_utility.py    # 通用工具(thinking 過濾等)

每個模塊嘅職責:

  • myclaude.py:程式入口。處理命令行參數,創建 MyClaudeCLI 實例並啟動
  • mycli.py:CLI 主循環。接收用戶輸入,路由斜槓命令(/quit、/clear、/help、/tokens),調用 QueryLoop 執行普通查詢
  • cli_print.py:終端輸出層。提供彩色打印、Markdown 渲染、打字機效果、工具調用格式化顯示
  • tool_executor.py:工具系統。使用正則表達式從 LLM 響應中提取 XML 工具標籤,調度執行具體工具
  • cmd_bash.py:Bash 執行器。通過 subprocess.run 執行 shell 命令,30 秒超時
  • llm_api_msg.py:消息管理器。維護發送畀 LLM 嘅 messages 列表,提供系統提示詞初始化、用戶消息追加、助手回覆追加、工具結果追加等方法
  • sys_prompt.py:系統提示詞定義。約 80 行嘅分層規則系統,定義 LLM 嘅行為準則
  • query_loop.py:核心循環控制器。管理「發送消息 → 接收響應 → 解析工具 → 執行工具 → 繼續下一輪」嘅循環
  • chat_llm.py:LLM 客戶端。封裝 OpenAI SDK,提供阻塞式、流式、異步流式三種調用方式,以及帶自動擴容嘅重試邏輯
  • config_loader.py:配置管理器。加載 YAML 配置文件,轉換為點號訪問嘅 SimpleNamespace 對象,實現全局單例
  • file_tool.py:檔案操作工具。實現 view(查看)、create(創建)、str_replace(替換)三種檔案操作
  • normal_utility.py:通用工具函數。目前包含 thinking 內容過濾功能

2.3 主循環流程

主循環係整個系統嘅核心,由 QueryLoop.run() 方法驅動。佢嘅流程如下:

  • 第一輪:初始化 API 消息列表(系統提示詞 + 用戶輸入)
  • 循環體(最多 max_turns 輪):
    • 發送消息畀 LLM,獲取響應
    • 從響應中解析工具調用列表
    • 如果有工具調用,執行工具,將結果追加到消息列表,繼續下一輪
    • 如果冇工具調用或收到 done 信號,退出循環
  • 超輪次處理:達到最大輪次仍未結束,強制終止並提示用戶

3. 源碼分析

3.1 入口與配置加載

程式入口喺 src/myclaude.py,核心邏輯非常簡潔:

from cli.mycli import MyClaudeCLI

def main():
    import argparse
    parser = argparse.ArgumentParser(description="MyClaude Code CLI")
    parser.add_argument('-m', '--model', type=str, default='MiniMax-M2.7',
   help='AI model to use')
    cli = MyClaudeCLI()
    cli.run()

if __name__ == "__main__":
    main()

入口做咗三件事:解析命令行參數、創建 CLI 實例、啟動主循環。注意 argparse 解析咗 model 參數但未用——呢個係為後續多模型支持預留嘅擴展點。

配置加載(utility/config_loader.py)採用咗一種巧妙嘅單例模式:

def load_config(filename="config.yaml"):
    start_dir = Path(__file__).resolve().parent
    base_dir = find_project_root(start_dir, filename)
    config_path = base_dir / filename
    with open(config_path, "r", encoding="utf-8") as f:
        raw = yaml.safe_load(f)
    return _dict_to_namespace(raw)

# 模塊級全局單例
global_cfg = load_config()

關鍵設計點:

  • find_project_root 函數通過向上查找 config.yaml 檔案來確定項目根目錄,支持從任意子目錄啟動
  • _dict_to_namespace 遞歸將 YAML 字典轉換為 SimpleNamespace,支持 global_cfg.model.api_key 咁樣嘅點號訪問
  • 利用 Python 嘅模塊緩存機制(sys.modules)實現全局單例:無論被 import 幾多次,load_config() 只執行一次

3.2 系統提示詞設計

系統提示詞(message/sys_prompt.py)係整個項目最核心嘅資產,定義咗 LLM 嘅行為準則。佢採用六層分層規則結構:

Layer 1 - 強制編碼信號:檢測用戶嘅「寫」、「創建」、「修改」等請求,強制使用 XML 工具而非直接輸出程式碼。

Layer 2 - 普通模式區分:區分編碼任務(使用工具)同純問答任務(直接回覆)。

Layer 3 - 衝突仲裁:當用戶請求同時包含問答同編碼需求時,以 Layer 1 為準。

Layer 4 - 程式碼規範:要求生成嘅 Python 程式碼通過 PyCharm 格式化檢查,包括檔案末尾換行、PEP 8 空格、冇重複程式碼片段、冇非 ASCII 字符等。

Layer 5 - 任務終止規則:任務完成時必須使用 <done> 標籤標記結束,禁止喺 done 之後繼續調用工具。

Layer 6 - 環境約束:聲明當前環境為 Windows,要求使用 CMD 語法。

提示詞仲包含正向示例同反向示例,通過對比教識 LLM 正確嘅程式碼交付方式:程式碼一定要擺喺 XML 標籤入面,禁止用 Markdown 程式碼塊。

3.3 消息管理

LLMAPIMessage 類(message/llm_api_msg.py)管理發送畀 LLM 嘅消息歷史:

class LLMAPIMessage:
    def __init__(self):
        self.api_messages = sys_prompt.system_prompt.copy()

    def init_api_msg(self, user_input):
        msg = {"role": "user", "content": user_input}
        self._append_info(msg)

    def append_llm_response(self, llm_response):
        msg = {"role": "assistant", "content": llm_response}
        self._append_info(msg)

    def append_tool_exec_result(self, result_msg):
        self._append_info(result_msg)

消息管理嘅設計原則:

  • 系統提示詞喺初始化時被複製一份,避免修改原始模板
  • 所有消息追加都通過 _append_info 方法,為後續嘅記憶壓縮(memory compaction)預留擴展點
  • 工具執行結果直接以 dict 形式追加,其 role 由 tool_executor 設定為 "user"(呢個係一種巧妙嘅設計:將工具結果偽裝成用戶消息,令 LLM 自然理解呢個係對之前操作嘅反饋)
  • append_micro_info 方法名中嘅 "micro" 暗示呢個係輕量級追加,唔會觸發記憶壓縮

3.4 LLM 調用與重試

LLM 調用層(query/chat_llm.py)提供咗三種調用方式同智能重試機制:

def chat_with_retry(api_messages):
    initial_max_tokens = global_cfg.model_chat.initial_max_tokens
    max_retries = global_cfg.model_chat.max_retries
    max_tokens_limit = global_cfg.model_chat.max_tokens_limit
    max_tokens = initial_max_tokens

    for attempt in range(max_retries + 1):
        ai_response, is_truncated = stream_chat(api_messages, max_tokens=max_tokens)
        if not is_truncated:
            return ai_response
        if attempt >= max_retries:
            return ai_response
        next_tokens = max_tokens * 2
        if next_tokens > max_tokens_limit:
            return ai_response
        max_tokens = next_tokens

重試策略嘅設計思路:

  • 初始 max_tokens 從配置讀取(預設 9000)
  • 檢測到截斷(finish_reason == "length")時,將 max_tokens 翻倍重試
  • 翻倍上限由 max_tokens_limit(預設 64000)控制
  • 最大重試次數由 max_retries(預設 3)控制
  • 超過任一限制,返回帶截斷標記嘅結果而唔係無限重試

流式調用(stream_chat)處理咗三種 finish_reason:

  • "length":標記截斷,觸發重試邏輯
  • "stop":正常結束
  • 其他:記錄原因並結束

3.5 工具調用解析

工具解析器(llm_tool/tool_executor.py)係整個工具系統嘅核心。佢使用正則表達式從 LLM 嘅文字響應中提取 XML 格式嘅工具調用:

patterns = [
    ("view", re.compile(r'<view\s+path="([^"]*)"\s*/>')),
    ("create", re.compile(r'<create\s+path="([^"]*)">(.*?)</create>', re.DOTALL)),
    ("bash", re.compile(r'<bash>(.*?)</bash>', re.DOTALL)),
    ("str_replace", re.compile(
        r'<str_replace\s+path="([^"]*)">(.*?)<old>(.*?)</old>(.*?)<new>(.*?)</new>(.*?)</str_replace>',
        re.DOTALL
    )),
    ("done", re.compile(r'<done>(.*?)(?:</done>|$)', re.DOTALL)),
]

設計要點:

  • 五個工具嘅正則按出現位置排序,保持原始順序
  • done 標籤允許唔閉合(</done>|$),作為容錯措施
  • str_replace 使用四段式結構(path + old + new),支持精確嘅程式碼替換
  • 非工具文本(remaining)被保留並展示畀用戶,實現「對話 + 工具調用」混合輸出
  • 連續三個以上嘅換行被壓縮為兩個,保持輸出整潔

返回結構為 (剩餘文本, 工具列表),其中工具列表嘅每個元素為 {"llm_tool": "工具名", "params": {...}}

3.6 工具執行

工具執行函數 execute_code_tool 根據工具名分發到具體實現:

  • view:調用 file_view,支持查看檔案內容同目錄列表
  • create:調用 file_create,自動創建父目錄,檢測已有檔案並拒絕覆蓋
  • str_replace:調用 file_str_replace,精確匹配替換,僅替換首次出現
  • bash:調用 tool_bash,subprocess.run 執行,30 秒超時

檔案操作嘅安全邊界:

  • 所有相對路徑拼接到 code_output_root 目錄下,防止越權訪問
  • create 檢測檔案已存在且非空時拒絕覆蓋,要求使用 str_replace
  • bash 通過 subprocess 嘅超時機制防止命令掛起
  • 絕對路徑直接放行(信任 LLM 嘅判斷)

3.7 CLI 界面

CLI 界面(cli/mycli.py + cli/cli_print.py)實現咗完整嘅交互體驗:

  • 主循環:接收輸入 → 判斷係咪斜槓命令 → 如果係命令就路由處理,否則進入查詢循環
  • 命令系統:/quit(退出)、/clear(清屏)、/help(幫助)、/tokens(顯示 token 消耗)
  • 輸出渲染:通過回調函數將 QueryLoop 嘅事件(狀態顯示、LLM 回覆、工具調用、工具結果)映射為 Rich 終端嘅格式化輸出
  • 打字機效果:可配置嘅逐字符輸出延遲,模擬實時打印

回調注入模式嘅設計非常優雅。QueryLoop 唔直接依賴 CLI 模塊,而係通過 run() 方法嘅參數接收五個回調函數:

def run(self, user_input,
        on_context_mgr,     # 狀態上下文管理器(顯示 thinking 動畫)
        print_info,         # 信息輸出
        print_llm_rsp,      # LLM 響應渲染
        print_tool_call,    # 工具調用顯示
        print_tool_result): # 工具結果顯示

呢種設計實現咗查詢邏輯與表現層嘅完全解耦——可以替換為 WebSocket 輸出、GUI 界面或任何其他表現形式。

4. 功能詳解

4.1 查詢循環

QueryLoop.run() 係項目嘅核心編排方法。每次調用代表一個完整嘅用戶查詢會話:

turn = 0
while turn < max_turns:
    turn += 1
    1. 發送消息給 LLM(首輪初始化消息,後續輪追加工具結果)
    2. 接收 LLM 響應
    3. 解析響應中的工具調用
    4. 如果有 done 工具 → 結束循環
    5. 如果無工具調用且非對話模式 → 結束循環
    6. 否則執行工具,結果追加到消息列表,繼續循環

對話模式嘅判斷邏輯:

  • 初始化時 is_chat_mode = True
  • 一旦發現 LLM 返回咗工具調用,is_chat_mode = False
  • 喺非對話模式下,如果 LLM 未返回任何工具(包括 done),系統直接結束循環並提示用戶——唔做額外補救
  • 呢個機制防止咗 LLM 喺工具使用中途「迷失方向」而無限掛起

最後一輪嘅特殊處理:喺發起 LLM 請求前(_on_llm_req),如果當前已係最後一輪且處於編碼模式,系統會提前追加指令 "請立刻完成當前任務,使用 <done> 標記結束",爭取喺超限前完成任務,呢個係一種温和嘅強制終止機制。

4.2 工具調用流程

一次完整嘅工具調用流程如下(以「寫一個斐波那契函數」為例):

圖片

流程執行說明:

  • 步驟 1-2:用戶輸入被封裝為 API 消息併發送畀 LLM
  • 步驟 3-4:LLM 返回嘅響應中同時包含說明文字同 XML 工具標籤,解析器將佢哋分離
  • 步驟 5-8:create 工具執行,將程式碼寫入檔案系統,執行結果以 user 角色追加到消息列表
  • 步驟 9-12:LLM 收到工具執行結果後判斷任務完成,發出 done 信號
  • 步驟 13:QueryLoop 檢測到 done 工具,退出循環並展示最終結果

關鍵設計:

  • 工具結果以 user 角色返回係一個巧妙嘅設計,令 LLM 將佢視為「用戶話畀你操作結果」,自然噉理解並做出後續響應
  • 多工具並行執行支持:同一輪響應中嘅多個工具會依次執行

4.3 對話模式與編碼模式切換

QueryLoop 維護一個 is_chat_mode 標記嚟區分兩種交互模式:

  • 對話模式(is_chat_mode = True):LLM 直接回覆文字,唔產生工具調用。本輪結束後 QueryLoop 退出循環(QuitByNoneTool)
  • 編碼模式(is_chat_mode = False):LLM 產生咗至少一次工具調用。此後每次循環都期待 LLM 繼續使用工具或發出 done 信號

模式切換邏輯:

# 如果 LLM response 裏有工具,那就不是單純的對話模式
self.is_chat_mode = False

# 如果無工具且為非對話模式:提醒用戶
if not self.is_chat_mode:
    self._print_info("LLM 未發出 done 工具,編碼操作可能未完成,已自動結束")

呢種設計嘅巧妙之處在於:單次交互中 LLM 嘅行為可能從「對話」切換為「編碼」,但唔會從「編碼」切返「對話」。一旦 LLM 開始使用工具,就必須明確發出 done 信號先可以結束,防止中途沉默。

5. 技術亮點

5.1 分層規則系統

系統提示詞嘅六層結構係經過精心設計嘅:

  • 優先級從高到低,高層規則覆蓋低層規則
  • 每層處理一類獨立嘅決策問題,互不幹擾
  • 衝突仲裁層(Layer 3)明確處理模糊場景
  • 環境約束層(Layer 6)將運行時環境信息注入提示詞,令 LLM 產生平台正確嘅命令

呢種分層設計比單一長提示詞更易於維護同調優——可以獨立修改某一層嘅規則而唔影響其他層。

5.2 正則解析器設計

工具解析器使用正則表達式而唔係 XML 解析器,原因在於:

  • LLM 輸出天然包含「唔合法」嘅 XML(例如唔閉合嘅 done 標籤、混合文字同標籤)
  • 正則表達式對格式錯誤具有天然嘅容錯性
  • 解析失敗時返回空工具列表,系統將佢視為普通文字回覆,唔會冧

done 標籤嘅正則 r'<done>(.*?)(?:</done>|$)' 尤其體現咗容錯設計——即使 LLM 忘記閉合標籤,都能正確提取內容。

5.3 智能重試機制

chat_with_retry 實現咗一種指數退避嘅變體——唔係延長等待時間,而係擴大 token 配額。呢個設計基於一個洞察:LLM 輸出被截斷最常見嘅原因係 max_tokens 設定唔夠,而唔係網絡波動。因此:

  • 檢測到截斷 → 翻倍 max_tokens → 重試
  • 達到上限或最大重試次數 → 返回當前結果(即使截斷)
  • 保證咗重試唔會無限進行

5.4 配置驅動的模塊化

所有可調參數集中喺 config.yaml 入面,通過 SimpleNamespace 轉換為點號訪問。模塊間依賴通過「導入 global_cfg 單例」嘅方式實現,避免咗參數層層傳遞。

呢種設計有一個隱含優勢:AI 喺自我進化時,可以通過修改 config.yaml 嚟調整行為,而唔需要深入理解程式碼結構。

5.5 工具執行安全邊界

  • 檔案操作默認限制喺 code_output_root 目錄內(通過 add_root_path 函數拼接路徑前綴)
  • create 操作檢測已有檔案並拒絕覆蓋,防止 AI 誤刪程式碼
  • bash 執行有 30 秒超時保護
  • 系統提示詞中聲明「環境為 Windows」,引導 LLM 生成正確嘅命令

6. 實踐指南

6.1 環境準備

依賴項(requirements.txt):

  • openai >= 1.0.0:LLM API 客戶端
  • rich >= 13.0.0:終端 UI 渲染
  • pyyaml >= 6.0:配置文件解析
  • numpy >= 1.24.0:數學計算(為 MemorySystem 預留)
pip install -r requirements.txt

6.2 配置說明

config.yaml 分為五個配置組:

  • model:LLM API 連接參數(api_key、base_url、model_name、max_tokens、temperature)
  • model_chat:重試策略參數(initial_max_tokens、max_retries、max_tokens_limit)
  • memory:記憶系統配置(root_dir、max_inject_tokens、compact_threshold)
  • code_project:項目路徑配置(project_root、code_output_root、logs_root)
  • cli:終端界面配置(theme、typewriter_delay、max_turns、show_thinking)

關鍵配置項:

  • model.api_key:LLM API 密鑰
  • cli.max_turns:工具調用最大輪次(預設 10),防止 LLM 陷入無限循環
  • code_project.code_output_root:AI 生成程式碼嘅輸出目錄

6.3 運行與調試

cd MyClaude
python src/myclaude.py

啟動後進入交互式 CLI 界面,支持嘅命令:

  • /help:顯示幫助信息
  • /clear:清屏
  • /tokens:顯示當前會話嘅 token 消耗
  • /quit 或 /exit:退出程式

直接輸入自然語言就可以同 AI 對話。當 AI 檢測到編碼意圖時,會自動切換到工具模式,使用 XML 標籤執行檔案操作。

7. 總結

MyClaude 用大約 500 行 Python 程式碼實現咗一個完整嘅 AI 編程助手核心循環,展示咗幾個關鍵設計原則:

  • 極簡分層架構:每層職責單一,模塊間通過回調注入解耦,冇任何循環依賴
  • 分層提示詞工程:六層規則系統比單一長提示詞更可維護,正反示例對比提升 LLM 行為準確性
  • 容錯優先嘅解析器:正則表達式比 XML 解析器更適合解析 LLM 嘅非嚴格輸出
  • 配置驅動:所有可調參數集中管理,為 AI 自我進化提供簡潔嘅「控制面板」
  • 安全嘅執行邊界:檔案操作限制喺指定目錄,bash 有超時保護,防止意外破壞

適合以下讀者睇:

  • 想理解 AI Coding 助手底層原理嘅開發者
  • 準備構建自己嘅 AI Agent 系統嘅工程師
  • 對 LLM 提示詞工程感興趣嘅實踐者
  • 希望研究「最小可行 AI 編碼助手」架構嘅學習者

該項目嘅下一步方向係令 0.01 版本喺 AI 輔助下自我進化到 0.1 版本,呢個將會涉及程式碼生成、測試驗證、自動提交等自動化流程嘅引入。

參考文獻

[1] MyClaude 項目倉庫:https://github.com/1801573781/MyClaude

[2] MiniMax API 文檔:https://platform.minimaxi.com

[3] OpenAI Python SDK:https://github.com/openai/openai-python

[4] Rich 終端庫:https://github.com/Textualize/rich

[5] PyYAML 文檔:https://pyyaml.org

MyClaude 是一個學習性項目,用約 500 行 Python 代碼實現了 Claude Code 的核心交互循環——CLI 界面、XML 工具調用解析、LLM 對話管理、文件操作與 Bash 執行。本文逐模塊拆解其源碼架構,分析系統提示詞的分層規則設計、工具調用解析器的正則匹配策略、帶自動擴容的重試機制,以及配置驅動的模塊化設計思想,適合想理解 AI Coding 助手底層原理的開發者閲讀。

目錄

  1. 概述
      1.1 項目背景
      1.2 技術棧
      1.3 設計目標
  2. 核心架構
      2.1 整體架構概覽
      2.2 模塊職責劃分
      2.3 主循環流程
  3. 源碼分析
      3.1 入口與配置加載
      3.2 系統提示詞設計
      3.3 消息管理
      3.4 LLM 調用與重試
      3.5 工具調用解析
      3.6 工具執行
      3.7 CLI 界面
  4. 功能詳解
      4.1 查詢循環
      4.2 工具調用流程
      4.3 對話模式與編碼模式切換
  5. 技術亮點
      5.1 分層規則系統
      5.2 正則解析器設計
      5.3 智能重試機制
      5.4 配置驅動的模塊化
      5.5 工具執行安全邊界
  6. 實踐指南
      6.1 環境準備
      6.2 配置說明
      6.3 運行與調試
  7. 總結
    參考文獻

1. 概述

1.1 項目背景

MyClaude 是一個用於學習和研究 Claude Code 工作原理的開源項目。它的目標分為兩步:首先搭建一個功能精簡的 0.01 版本,實現基本的編碼對話循環;然後期望這個 0.01 版本能夠在 AI 輔助下自我進化到 0.1 版本。項目的設計理念是"麻雀雖小,五臟俱全"——在極少的代碼量中覆蓋 AI 編程助手的核心機制。

1.2 技術棧

  • 語言:Python 100%(約 500 行有效代碼)
  • LLM:MiniMax M2.7(通過 OpenAI 兼容接口調用)
  • 終端 UI:Rich 庫(Markdown 渲染、語法高亮)
  • 配置:YAML(通過 PyYAML 解析為 SimpleNamespace)
  • 工具系統:XML 標籤格式(view / create / str_replace / bash / done)

1.3 設計目標

  • 極簡實現:核心代碼量控制在 500 行以內,每個模塊職責單一
  • 完整閉環:覆蓋"用戶輸入 → LLM 調用 → 工具解析 → 工具執行 → 結果反饋"的完整鏈路
  • 可進化:架構設計為 AI 自我修改留有空間,支持後續的自動進化

2. 核心架構

2.1 整體架構概覽

項目採用分層架構,從下到上分為五個層次:

  • 配置層(utility/config_loader.py):YAML 配置加載,全局單例模式
  • 消息層(message/):系統提示詞管理、API 消息構建
  • 查詢層(query/):LLM 調用、重試邏輯、會話日誌
  • 工具層(llm_tool/):XML 解析、工具執行、文件操作
  • 表現層(cli/):CLI 交互、輸出渲染、命令處理
圖片

流程執行說明:

  • 階段一(步驟 1-2):CLI 接收用戶輸入,傳遞給 QueryLoop 啓動查詢循環
  • 階段二(步驟 3-5):QueryLoop 構建 API 消息,調用 LLM 並獲取響應
  • 階段三(步驟 6-12):解析 LLM 響應中的工具調用,執行工具操作,將結果反饋給 LLM
  • 階段四(步驟 13):LLM 返回 done 或無工具時,結束循環並展示結果

關鍵規則:

  • QueryLoop 不持有任何終端輸出邏輯,所有輸出通過回調函數注入
  • 工具執行結果以 [tool_name] 工具執行結果:... 格式追加到消息歷史
  • done 工具是循環終止的唯一信號

2.2 模塊職責劃分

項目源碼目錄結構如下:

src/
├── myclaude.py              # 入口:參數解析、CLI 啓動
├── cli/
│  ├──mycli.py # CLI 主循環:輸入處理、命令路由
│   └── cli_print.py         # 終端輸出:彩色打印、Markdown 渲染
├── llm_tool/
│   ├── tool_executor.py     # 工具解析與執行調度
│   └── cmd_bash.py          # Bash 命令執行
├── message/
│   ├── llm_api_msg.py       # API 消息管理
│   └── sys_prompt.py        # 系統提示詞定義
├── query/
│   ├── query_loop.py        # 核心查詢循環
│   ├── chat_llm.py          # LLM API 調用(同步/流式/異步)
│   └── session_log.py       # 會話日誌記錄
└── utility/
    ├── config_loader.py     # 配置加載與全局單例
    ├── file_tool.py         # 文件操作(view/create/str_replace)
    └── normal_utility.py    # 通用工具(thinking 過濾等)

每個模塊的職責:

  • myclaude.py:程序入口。處理命令行參數,創建 MyClaudeCLI 實例並啓動
  • mycli.py:CLI 主循環。接收用戶輸入,路由斜槓命令(/quit、/clear、/help、/tokens),調用 QueryLoop 執行普通查詢
  • cli_print.py:終端輸出層。提供彩色打印、Markdown 渲染、打字機效果、工具調用格式化顯示
  • tool_executor.py:工具系統。使用正則表達式從 LLM 響應中提取 XML 工具標籤,調度執行具體工具
  • cmd_bash.py:Bash 執行器。通過 subprocess.run 執行 shell 命令,30 秒超時
  • llm_api_msg.py:消息管理器。維護髮送給 LLM 的 messages 列表,提供系統提示詞初始化、用戶消息追加、助手回覆追加、工具結果追加等方法
  • sys_prompt.py:系統提示詞定義。約 80 行的分層規則系統,定義 LLM 的行為準則
  • query_loop.py:核心循環控制器。管理"發送消息 → 接收響應 → 解析工具 → 執行工具 → 繼續下一輪"的循環
  • chat_llm.py:LLM 客戶端。封裝 OpenAI SDK,提供阻塞式、流式、異步流式三種調用方式,以及帶自動擴容的重試邏輯
  • config_loader.py:配置管理器。加載 YAML 配置文件,轉換為點號訪問的 SimpleNamespace 對象,實現全局單例
  • file_tool.py:文件操作工具。實現 view(查看)、create(創建)、str_replace(替換)三種文件操作
  • normal_utility.py:通用工具函數。目前包含 thinking 內容過濾功能

2.3 主循環流程

主循環是整個系統的核心,由 QueryLoop.run() 方法驅動。其流程如下:

  • 第一輪:初始化 API 消息列表(系統提示詞 + 用戶輸入)
  • 循環體(最多 max_turns 輪):
    • 發送消息給 LLM,獲取響應
    • 從響應中解析工具調用列表
    • 如果有工具調用,執行工具,將結果追加到消息列表,繼續下一輪
    • 如果無工具調用或收到 done 信號,退出循環
  • 超輪次處理:達到最大輪次仍未結束,強制終止並提示用戶

3. 源碼分析

3.1 入口與配置加載

程序入口在 src/myclaude.py,核心邏輯非常簡潔:

from cli.mycli import MyClaudeCLI

def main():
    import argparse
    parser = argparse.ArgumentParser(description="MyClaude Code CLI")
    parser.add_argument('-m', '--model', type=str, default='MiniMax-M2.7',
   help='AI model to use')
    cli = MyClaudeCLI()
    cli.run()

if __name__ == "__main__":
    main()

入口做了三件事:解析命令行參數、創建 CLI 實例、啓動主循環。注意 argparse 解析了 model 參數但尚未使用——這是一個為後續多模型支持預留的擴展點。

配置加載(utility/config_loader.py)採用了一種巧妙的單例模式:

def load_config(filename="config.yaml"):
    start_dir = Path(__file__).resolve().parent
    base_dir = find_project_root(start_dir, filename)
    config_path = base_dir / filename
    with open(config_path, "r", encoding="utf-8") as f:
        raw = yaml.safe_load(f)
    return _dict_to_namespace(raw)

# 模塊級全局單例
global_cfg = load_config()

關鍵設計點:

  • find_project_root 函數通過向上查找 config.yaml 文件來確定項目根目錄,支持從任意子目錄啓動
  • _dict_to_namespace 遞歸將 YAML 字典轉換為 SimpleNamespace,支持 global_cfg.model.api_key 這樣的點號訪問
  • 利用 Python 的模塊緩存機制(sys.modules)實現全局單例:無論被 import 多少次,load_config() 只執行一次

3.2 系統提示詞設計

系統提示詞(message/sys_prompt.py)是整個項目最核心的資產,定義了 LLM 的行為準則。它採用六層分層規則結構:

Layer 1 - 強制編碼信號:檢測用戶的"寫"、"創建"、"修改"等請求,強制使用 XML 工具而非直接輸出代碼。

Layer 2 - 普通模式區分:區分編碼任務(使用工具)和純問答任務(直接回復)。

Layer 3 - 衝突仲裁:當用戶請求同時包含問答和編碼需求時,以 Layer 1 為準。

Layer 4 - 代碼規範:要求生成的 Python 代碼通過 PyCharm 格式化檢查,包括文件末尾換行、PEP 8 空格、無重複代碼片段、無非 ASCII 字符等。

Layer 5 - 任務終止規則:任務完成時必須使用 <done> 標籤標記結束,禁止在 done 之後繼續調用工具。

Layer 6 - 環境約束:聲明當前環境為 Windows,要求使用 CMD 語法。

提示詞還包含正向示例和反向示例,通過對比教會 LLM 正確的代碼交付方式:代碼必須放在 XML 標籤內,禁止使用 Markdown 代碼塊。

3.3 消息管理

LLMAPIMessage 類(message/llm_api_msg.py)管理發送給 LLM 的消息歷史:

class LLMAPIMessage:
    def __init__(self):
        self.api_messages = sys_prompt.system_prompt.copy()

    def init_api_msg(self, user_input):
        msg = {"role": "user", "content": user_input}
        self._append_info(msg)

    def append_llm_response(self, llm_response):
        msg = {"role": "assistant", "content": llm_response}
        self._append_info(msg)

    def append_tool_exec_result(self, result_msg):
        self._append_info(result_msg)

消息管理的設計原則:

  • 系統提示詞在初始化時被複制一份,避免修改原始模板
  • 所有消息追加都通過 _append_info 方法,為後續的記憶壓縮(memory compaction)預留擴展點
  • 工具執行結果直接以 dict 形式追加,其 role 由 tool_executor 設定為 "user"(這是一種巧妙的設計:將工具結果偽裝成用戶消息,讓 LLM 自然理解這是對之前操作的反饋)
  • append_micro_info 方法名中的 "micro" 暗示這是輕量級追加,不觸發記憶壓縮

3.4 LLM 調用與重試

LLM 調用層(query/chat_llm.py)提供了三種調用方式和智能重試機制:

def chat_with_retry(api_messages):
    initial_max_tokens = global_cfg.model_chat.initial_max_tokens
    max_retries = global_cfg.model_chat.max_retries
    max_tokens_limit = global_cfg.model_chat.max_tokens_limit
    max_tokens = initial_max_tokens

    for attempt in range(max_retries + 1):
        ai_response, is_truncated = stream_chat(api_messages, max_tokens=max_tokens)
        if not is_truncated:
            return ai_response
        if attempt >= max_retries:
            return ai_response
        next_tokens = max_tokens * 2
        if next_tokens > max_tokens_limit:
            return ai_response
        max_tokens = next_tokens

重試策略的設計思路:

  • 初始 max_tokens 從配置讀取(默認 9000)
  • 檢測到截斷(finish_reason == "length")時,將 max_tokens 翻倍重試
  • 翻倍上限由 max_tokens_limit(默認 64000)控制
  • 最大重試次數由 max_retries(默認 3)控制
  • 超過任一限制,返回帶截斷標記的結果而非無限重試

流式調用(stream_chat)處理了三種 finish_reason:

  • "length":標記截斷,觸發重試邏輯
  • "stop":正常結束
  • 其他:記錄原因並結束

3.5 工具調用解析

工具解析器(llm_tool/tool_executor.py)是整個工具系統的核心。它使用正則表達式從 LLM 的文本響應中提取 XML 格式的工具調用:

patterns = [
    ("view", re.compile(r'<view\s+path="([^"]*)"\s*/>')),
    ("create", re.compile(r'<create\s+path="([^"]*)">(.*?)</create>', re.DOTALL)),
    ("bash", re.compile(r'<bash>(.*?)</bash>', re.DOTALL)),
    ("str_replace", re.compile(
        r'<str_replace\s+path="([^"]*)">(.*?)<old>(.*?)</old>(.*?)<new>(.*?)</new>(.*?)</str_replace>',
        re.DOTALL
    )),
    ("done", re.compile(r'<done>(.*?)(?:</done>|$)', re.DOTALL)),
]

設計要點:

  • 五個工具的正則按出現位置排序,保持原始順序
  • done 標籤允許不閉合(</done>|$),作為容錯措施
  • str_replace 使用四段式結構(path + old + new),支持精確的代碼替換
  • 非工具文本(remaining)被保留並展示給用戶,實現"對話 + 工具調用"混合輸出
  • 連續三個以上的換行被壓縮為兩個,保持輸出整潔

返回結構為 (剩餘文本, 工具列表),其中工具列表的每個元素為 {"llm_tool": "工具名", "params": {...}}

3.6 工具執行

工具執行函數 execute_code_tool 根據工具名分發到具體實現:

  • view:調用 file_view,支持查看文件內容和目錄列表
  • create:調用 file_create,自動創建父目錄,檢測已有文件並拒絕覆蓋
  • str_replace:調用 file_str_replace,精確匹配替換,僅替換首次出現
  • bash:調用 tool_bash,subprocess.run 執行,30 秒超時

文件操作的安全邊界:

  • 所有相對路徑拼接到 code_output_root 目錄下,防止越權訪問
  • create 檢測文件已存在且非空時拒絕覆蓋,要求使用 str_replace
  • bash 通過 subprocess 的超時機制防止命令掛起
  • 絕對路徑直接放行(信任 LLM 的判斷)

3.7 CLI 界面

CLI 界面(cli/mycli.py + cli/cli_print.py)實現了完整的交互體驗:

  • 主循環:接收輸入 → 判斷是否為斜槓命令 → 如果是命令則路由處理,否則進入查詢循環
  • 命令系統:/quit(退出)、/clear(清屏)、/help(幫助)、/tokens(顯示 token 消耗)
  • 輸出渲染:通過回調函數將 QueryLoop 的事件(狀態顯示、LLM 回覆、工具調用、工具結果)映射為 Rich 終端的格式化輸出
  • 打字機效果:可配置的逐字符輸出延遲,模擬實時打印

回調注入模式的設計非常優雅。QueryLoop 不直接依賴 CLI 模塊,而是通過 run() 方法的參數接收五個回調函數:

def run(self, user_input,
        on_context_mgr,     # 狀態上下文管理器(顯示 thinking 動畫)
        print_info,         # 信息輸出
        print_llm_rsp,      # LLM 響應渲染
        print_tool_call,    # 工具調用顯示
        print_tool_result): # 工具結果顯示

這種設計實現了查詢邏輯與表現層的完全解耦——可以替換為 WebSocket 輸出、GUI 界面或任何其他表現形式。

4. 功能詳解

4.1 查詢循環

QueryLoop.run() 是項目的核心編排方法。每次調用代表一個完整的用戶查詢會話:

turn = 0
while turn < max_turns:
    turn += 1
    1. 發送消息給 LLM(首輪初始化消息,後續輪追加工具結果)
    2. 接收 LLM 響應
    3. 解析響應中的工具調用
    4. 如果有 done 工具 → 結束循環
    5. 如果無工具調用且非對話模式 → 結束循環
    6. 否則執行工具,結果追加到消息列表,繼續循環

對話模式的判斷邏輯:

  • 初始化時 is_chat_mode = True
  • 一旦發現 LLM 返回了工具調用,is_chat_mode = False
  • 在非對話模式下,如果 LLM 未返回任何工具(包括 done),系統直接結束循環並提示用戶——不做額外補救
  • 這個機制防止了 LLM 在工具使用中途"迷失方向"而無限掛起

最後一輪的特殊處理:在發起 LLM 請求前(_on_llm_req),如果當前已是最後一輪且處於編碼模式,系統會提前追加指令 "請立刻完成當前任務,使用 <done> 標記結束",爭取在超限前完成任務,這是一種温和的強制終止機制。

4.2 工具調用流程

一次完整的工具調用流程如下(以"寫一個斐波那契函數"為例):

圖片

流程執行說明:

  • 步驟 1-2:用戶輸入被封裝為 API 消息併發送給 LLM
  • 步驟 3-4:LLM 返回的響應中同時包含說明文本和 XML 工具標籤,解析器將其分離
  • 步驟 5-8:create 工具執行,將代碼寫入文件系統,執行結果以 user 角色追加到消息列表
  • 步驟 9-12:LLM 收到工具執行結果後判斷任務完成,發出 done 信號
  • 步驟 13:QueryLoop 檢測到 done 工具,退出循環並展示最終結果

關鍵設計:

  • 工具結果以 user 角色返回是一個巧妙的設計,讓 LLM 將其視為"用戶告訴你操作結果",自然地理解並做出後續響應
  • 多工具並行執行支持:同一輪響應中的多個工具會依次執行

4.3 對話模式與編碼模式切換

QueryLoop 維護一個 is_chat_mode 標記來區分兩種交互模式:

  • 對話模式(is_chat_mode = True):LLM 直接回覆文本,不產生工具調用。本輪結束後 QueryLoop 退出循環(QuitByNoneTool)
  • 編碼模式(is_chat_mode = False):LLM 產生了至少一次工具調用。此後每次循環都期待 LLM 繼續使用工具或發出 done 信號

模式切換邏輯:

# 如果 LLM response 裏有工具,那就不是單純的對話模式
self.is_chat_mode = False

# 如果無工具且為非對話模式:提醒用戶
if not self.is_chat_mode:
    self._print_info("LLM 未發出 done 工具,編碼操作可能未完成,已自動結束")

這種設計的巧妙之處在於:單次交互中 LLM 的行為可能從"對話"切換為"編碼",但不會從"編碼"切回"對話"。一旦 LLM 開始使用工具,就必須明確發出 done 信號才能結束,防止中途沉默。

5. 技術亮點

5.1 分層規則系統

系統提示詞的六層結構是經過精心設計的:

  • 優先級從高到低,高層規則覆蓋低層規則
  • 每層處理一類獨立的決策問題,互不干擾
  • 衝突仲裁層(Layer 3)明確處理模糊場景
  • 環境約束層(Layer 6)將運行時環境信息注入提示詞,讓 LLM 產生平台正確的命令

這種分層設計比單一長提示詞更易於維護和調優——可以獨立修改某一層的規則而不影響其他層。

5.2 正則解析器設計

工具解析器使用正則表達式而非 XML 解析器,原因在於:

  • LLM 輸出天然包含"不合法"的 XML(如不閉合的 done 標籤、混合文本與標籤)
  • 正則表達式對格式錯誤具有天然的容錯性
  • 解析失敗時返回空工具列表,系統將其視為普通文本回復,不會崩潰

done 標籤的正則 r'<done>(.*?)(?:</done>|$)' 尤其體現了容錯設計——即使 LLM 忘記閉合標籤,也能正確提取內容。

5.3 智能重試機制

chat_with_retry 實現了一種指數退避的變體——不是延長等待時間,而是擴大 token 配額。這個設計基於一個洞察:LLM 輸出被截斷最常見的原因是 max_tokens 設置不足,而非網絡波動。因此:

  • 檢測到截斷 → 翻倍 max_tokens → 重試
  • 達到上限或最大重試次數 → 返回當前結果(即使截斷)
  • 保證了重試不會無限進行

5.4 配置驅動的模塊化

所有可調參數集中在 config.yaml 中,通過 SimpleNamespace 轉換為點號訪問。模塊間依賴通過"導入 global_cfg 單例"的方式實現,避免了參數層層傳遞。

這種設計有一個隱含優勢:AI 在自我進化時,可以通過修改 config.yaml 來調整行為,而不需要深入理解代碼結構。

5.5 工具執行安全邊界

  • 文件操作默認限制在 code_output_root 目錄內(通過 add_root_path 函數拼接路徑前綴)
  • create 操作檢測已有文件並拒絕覆蓋,防止 AI 誤刪代碼
  • bash 執行有 30 秒超時保護
  • 系統提示詞中聲明"環境為 Windows",引導 LLM 生成正確的命令

6. 實踐指南

6.1 環境準備

依賴項(requirements.txt):

  • openai >= 1.0.0:LLM API 客戶端
  • rich >= 13.0.0:終端 UI 渲染
  • pyyaml >= 6.0:配置文件解析
  • numpy >= 1.24.0:數學計算(為 MemorySystem 預留)
pip install -r requirements.txt

6.2 配置說明

config.yaml 分為五個配置組:

  • model:LLM API 連接參數(api_key、base_url、model_name、max_tokens、temperature)
  • model_chat:重試策略參數(initial_max_tokens、max_retries、max_tokens_limit)
  • memory:記憶系統配置(root_dir、max_inject_tokens、compact_threshold)
  • code_project:項目路徑配置(project_root、code_output_root、logs_root)
  • cli:終端界面配置(theme、typewriter_delay、max_turns、show_thinking)

關鍵配置項:

  • model.api_key:LLM API 密鑰
  • cli.max_turns:工具調用最大輪次(默認 10),防止 LLM 陷入無限循環
  • code_project.code_output_root:AI 生成代碼的輸出目錄

6.3 運行與調試

cd MyClaude
python src/myclaude.py

啓動後進入交互式 CLI 界面,支持的命令:

  • /help:顯示幫助信息
  • /clear:清屏
  • /tokens:顯示當前會話的 token 消耗
  • /quit 或 /exit:退出程序

直接輸入自然語言即可與 AI 對話。當 AI 檢測到編碼意圖時,會自動切換到工具模式,使用 XML 標籤執行文件操作。

7. 總結

MyClaude 用約 500 行 Python 代碼實現了一個完整的 AI 編程助手核心循環,展示了幾個關鍵設計原則:

  • 極簡分層架構:每層職責單一,模塊間通過回調注入解耦,沒有任何循環依賴
  • 分層提示詞工程:六層規則系統比單一長提示詞更可維護,正反示例對比提升 LLM 行為準確性
  • 容錯優先的解析器:正則表達式比 XML 解析器更適合解析 LLM 的非嚴格輸出
  • 配置驅動:所有可調參數集中管理,為 AI 自我進化提供簡潔的"控制面板"
  • 安全的執行邊界:文件操作限制在指定目錄,bash 有超時保護,防止意外破壞

適合以下讀者閲讀:

  • 想理解 AI Coding 助手底層原理的開發者
  • 準備構建自己的 AI Agent 系統的工程師
  • 對 LLM 提示詞工程感興趣的實踐者
  • 希望研究"最小可行 AI 編碼助手"架構的學習者

該項目的下一步方向是讓 0.01 版本在 AI 輔助下自我進化到 0.1 版本,這將涉及代碼生成、測試驗證、自動提交等自動化流程的引入。

參考文獻

[1] MyClaude 項目倉庫:https://github.com/1801573781/MyClaude

[2] MiniMax API 文檔:https://platform.minimaxi.com

[3] OpenAI Python SDK:https://github.com/openai/openai-python

[4] Rich 終端庫:https://github.com/Textualize/rich

[5] PyYAML 文檔:https://pyyaml.org