在進行 Claude 程式碼模式選擇時,應使用 Haiku 進行小規模且可測試的變更、使用 Sonnet 進行例行性實作,並使用 Opus 處理較具模糊性或需更多推理的工作。. Anthropic 目前建議將 Opus 5.5 作為一個廣泛的起點;您的任務、審查工作量及預算將決定較小規格的機型是否更適合您。.
若要變更模型,請開啟 /模型. 按 輸入 要儲存預設值,或 s 僅切換當前工作階段。若僅執行一次,請使用 claude --model opus. 這些選項的持久性各不相同,因此決定開關應維持多長時間,其重要性不亞於選擇模型本身。.
程式設計工作還包含研究、說明、文件編寫以及創意資產的製作。GlobalGPT 將頂尖的 AI 模型與多種 AI 工具整合至一個價格實惠的控制面板中,其命令列介面(CLI)則能將這些工具與終端機及開發工作流程相連結。. 使用 GlobalGPT 建立您的工作流程 在將構想轉化為可運作程式碼的過程中,將這些相關任務集中管理。.

在 Claude 程式碼中,您應該使用哪種模型?
首先從工作的性質著手。一個輸出預期明確的簡短函式,其評估方式應有別於橫跨多個服務的間歇性錯誤。關鍵在於:該模型是否能在合理的審查與迭代過程中,產生可接受的變更。.
| 現行型號 | 其定位為何 | 一項實用的入門任務 |
|---|---|---|
| 克勞德俳句 4.5 | 透過範圍狹窄的合約,實現快速、高效的工作 | 一項小規模的重構、重複的轉換,或一個簡單的測試案例 |
| 克勞德·索內特 第五首 | 在日常編程中兼顧智慧與速度 | 具有既定模式的功能、例行性的錯誤修正,或是程式碼說明 |
| Claude Opus 5.5 | 複雜推理與較長篇幅的行為主體編碼作業 | 一種模稜兩可的失敗、架構取捨,或是受相互作用的限制所影響的變更 |
| Claude Fable 5.1 | 最艱鉅且歷時最久的調查 | 當艱鉅的工作仍能壓倒更強的「Opus」努力程度時,便會出現情勢升級 |
當錯誤容易被察覺且變更幅度較小時,值得考慮採用 Haiku。當日常實作需要更多背景資訊與判斷時,Sonnet 是一個明智的選擇。當理解問題本身是任務的重要組成部分時,Opus 值得納入考量。至於 Fable,由於其工作需求較高,應另行評估;它並未納入我們這三種模型的編碼測試範圍。.
這些只是起點,並非自動的品質保證。如果需要多次修改或大量審閱,原本較便宜的解決方案反而可能變得昂貴。反之,對於已經通過您檢查的簡單轉換而言,較大的模型可能幾乎無法帶來任何附加價值。若要將其應用範圍擴展至 Claude Code 之外,, 比較 Claude 系列產品.

的 官方車型總覽 列出了 Fable 5.1、Opus 5.5 及 Sonnet 5 的 100 萬個代幣上下文視窗,以及 Haiku 4.5 的 20 萬個代幣上下文視窗。這些是 API 規格。 您的 Claude 程式碼提供者、帳戶及設定,將決定單一會話中可用的上下文選項。較大的上下文視窗對於提供必要的背景資訊很有幫助;但若將其填滿與主題無關的內容,仍會增加模型的運算負擔。.
如何在單次會話中切換模型
在互動式工作坊中,進行 /模型 以開啟模型選擇器。選取模型列,然後按下 s 如果這是一次性的變更,請按下 輸入 將選取內容儲存為您的使用者預設值。輸入 /模範十四行詩 在當前版本中,這也會直接將其儲存起來。.
根據變更應維持的時間長短來選擇指令
| 您的目標 | 該怎麼辦 | 已儲存預設變更? |
|---|---|---|
| 僅切換此互動式工作階段 | 開啟 /模型, 選擇一款機型,按下 s. | 沒有. |
| 儲存偏好的型號 | 開啟 /模型 並按下 輸入, ,或輸入 /模範十四行詩. | 是的,當使用者設定具有寫入權限時。. |
| 在 Opus 上開始單一會話 | 啟動 claude --model opus. | 沒有. |
| 恢復至該帳戶的執行時預設值 | 使用 /預設模型. | 清除模型覆寫設定;所解析出的預設值可能取決於帳戶和組織的設定。. |
| 檢查當前模型 | 奔跑 /狀態. | 沒有. |
專案或受管理的設定、環境覆寫以及已恢復的執行階段,都可能影響下次啟動。當可重現性至關重要時,請檢查當前活躍的模型。.
若要開啟新的終端機工作階段,請在啟動時選擇模型。當 Claude Code 在 VS Code 的內建終端機中執行時,這些指令同樣適用。以下範例會明確選取一個版本:
claude --model claude-opus-5-5
claude --model claude-sonnet-5針對您想要的會話執行該指令;範例中提供的是幾種替代方案。您可以透過不同的 -模型 在不需反覆變更共用儲存預設值的情況下設定數值。請使用 /狀態 以檢查當前模型。.
諸如以下這類姓氏: opus 和 十四行詩 可升級至較新版本。其解析度亦取決於服務供應商:Anthropic API 目前將其映射至 Opus 5.5 和 Sonnet 5,而各雲端服務供應商的映射方式可能有所不同。 若需可重現的執行結果,請使用完整的模型 ID;若您的環境有此需求,請確認供應商專屬的名稱。.
Opus 5.5 需要 Claude Code v2.1.280 或更新版本;Sonnet 5 則需要 v2.1.197 或更新版本。該 模型配置文件說明 此處提供當前別名、版本需求及供應商對應關係的參考資訊。此處的指令僅為文件範例;我們的實作章節將另行評估生成的程式碼。.

如何設定預設模型
若要設定個人預設值,請在 /模型 並按下 輸入, ,或輸入選項,例如 /模範十四行詩. Claude Code 寫入 模型 當該檔案可寫入時,請在您的使用者設定中填寫該欄位。開啟一個新的工作階段,並檢查其活躍模型以確認結果。.
已儲存的偏好設定並不會覆寫所有其他設定。啟動參數,, ANTHROPIC_MODEL 在殼層、專案或受管設定中,或是已設定為覆寫使用者選擇的組織預設值,皆可在啟動時選取其他選項。恢復的會話也可能保留其儲存紀錄中的模型。請檢查啟動資訊並 /狀態 在認定這個選擇已經失去之前。.
/預設模型 清除您的模型覆寫設定,並恢復至您帳戶與設定的執行時預設值。這個詞 預設 這是一個重設值,並非某個固定 Claude 模型的名稱。不應將其用作可重現的模型識別碼。.
若要進行進階設定,, ANTHROPIC_DEFAULT_MODEL 自 v2.1.236 起,提供了一個預設的備用選項。此選項位於「明確定義的啟動方式」、「環境」、「設定」及「組織」選項之下,並會忽略包含以下內容的值: 俳句 和 opusplan. 對於一般的個人偏好而言,選項器較易於驗證。請參閱 Claude 編碼設定 當涉及共用設定時。.
Opusplan 實際上做些什麼
opusplan 在規劃模式下使用 Opus,執行時則使用 Sonnet。其吸引力很簡單:先運用更強大的推理模型來推導解決方案,再透過日常編碼模型來執行該計畫。.
Opusplan 採用以下運作模式
已記錄的路由行為。這些系列名稱所對應的版本取決於您的服務供應商及設定。.
這是一項取決於模式的規則。它並不會檢查每個提示,也不會自動選擇最經濟的合適模型家族。提供者的映射與存取限制仍適用於底層模型。此外,名稱也無法保證能節省成本:總成本取決於該任務所需的規劃、實作、修訂及語境處理的工作量。.
不妨試著從另一個角度思考:當設計能從更深入的分析中獲益,且實作遵循明確的計畫時,這種做法便值得考慮。若只是小幅修正,那額外的規劃或許就沒有必要了。.
這兩項編碼任務顯示了什麼
為了更具體地闡明模型選擇的概念,我們測試了一項範圍狹窄的 Unicode 重構,以及一項具有相互作用需求的路由選擇器修復方案。結果顯示,正確函數與完整交付成果之間的差異,其重要性遠超過單純的分數。.
我們如何測試程式碼輸出結果
2026 年 9 月 28 日,我們透過 GlobalGPT,向 Claude Haiku 4.5、Claude Sonnet 5 以及 Claude Opus 5.5 分配了相同的兩項 JavaScript 任務。 每個模型均回傳了原始碼;我們檢視了這些程式碼,並執行了固定的本地檢查。本指南中關於 Claude Code 模型切換的說明,均摘自其官方文件。.
每個請求的輸出限制為 4,096 個標記,不包含任何工具或對話紀錄,且採用預設模型設定。我們保留了第一個可評估的回應,包括不完整的回應。Sonnet 的路由任務發生一次服務錯誤,允許重試一次:七個請求產生了六個輸出結果。.
這兩項小型任務旨在衡量返回的程式碼及交付的完整性。它們並未衡量 Claude Code 的代理程式執行、儲存庫探索,或是整個開發工作階段。實際的美元費用並未被報告。每項任務僅有一項觀察結果,無法據此建立整體的速度或可靠性排名。.
檢視確切的模型 ID 及評估條件
所需的身分證號: claude-haiku-4-5-20251001, 克勞德·十四行詩·第5首, 以及 克勞德作品第5號第5首. 本地測試是在 Node.js v24.19.0 環境下執行的。提示訊息適用於 Node.js 18 及以上版本;Node.js 18 本身並未經過測試。.
在「蛞蝓任務」中設定了八組行為,而在「路徑選擇器」中則設定了十二組。格式符合性與完整交付結果分別列報。後續的程式碼審查檢查被單獨標示,且不會改變上述計數結果。我們並未編輯回傳的原始碼以使其通過審查。.
任務 1:在小型 slug 重構中保留 Unicode
該函式必須保留非拉丁字母和組合標記、將分解的音標進行標準化,並維持其現有的 ASCII 行為。.
| 模型 | 行為檢查 | 回應格式 | 完成所要求的送貨 |
|---|---|---|---|
| 克勞德俳句 4.5 | 8/8 | 錯誤:Markdown 包覆標籤 | 是:完整函式 |
| 克勞德·索內特 第五首 | 8/8 | 傳入參數:原始 JSON | 是:完整函式 |
| Claude Opus 5.5 | 8/8 | 傳入參數:原始 JSON | 是:完整函式 |
觀察結果: 這三項功能均通過了相同的八組測試。Sonnet 和 Opus 也符合原始 JSON 回應的要求。Haiku 將其回應以 Markdown 格式封裝,且其審查備註錯誤地將 NFC 描述為「分解字元」;但其程式碼確實正確地調用了 NFC。.
就這項有限度的重構而言,升級並未改善受測函式的行為。格式要求及隨附說明的準確性仍需進行審查。.
檢視完整的共享提示與輸入程式碼
SYSTEM
You are completing a bounded JavaScript coding task. Return only the requested JSON object with complete source files and brief review notes. Do not claim to have edited files, run commands, or used tools. You have no tool access. Do not include hidden reasoning.
USER
Implement the following Node.js 18+ CommonJS function from its current source. Return complete replacement source for src/slugify.js. Do not add dependencies, imports, I/O, or other files.
Required behavior:
1. slugify(value) returns an empty string for every non-string input.
2. Normalize string input to Unicode NFC, then lowercase it using JavaScript toLowerCase().
3. Preserve Unicode letters, numbers, and combining marks. Replace each consecutive run of all other characters with one ASCII hyphen.
4. Trim leading and trailing hyphens. Preserve the CommonJS export { slugify }.
5. Existing ASCII behavior must continue to work. Examples: Hello, World! -> hello-world; two words -> two-words; null -> empty string.
6. Additional examples: Café déjà vu -> café-déjà-vu; decomposed Cafe\u0301 -> café; 中文 测试 42 -> 中文-测试-42; **hi___there** -> hi-there; only punctuation or whitespace -> empty string.
Current src/slugify.js:
```javascript
function slugify(value) {
if (typeof value !== "string") return "";
return value
.trim()
.toLowerCase()
.replace(/[^a-z0-9]+/g, "-")
.replace(/^-+|-+$/g, "");
}
module.exports = { slugify };
```
Return exactly one JSON object with this shape:
{"files":{"src/slugify.js":"complete JavaScript source as a JSON string"},"review_notes":["at most four brief implementation or assumption notes"]}
No Markdown wrapper. You are returning code for someone else to evaluate locally; do not say that tests passed or that you ran them.
查看 Claude Haiku 4.5 提供的完整回覆(以原始形式呈現)
```json
{
"files": {
"src/slugify.js": "function slugify(value) {\n if (typeof value !== \"string\") return \"\";\n \n // Normalize to NFC and lowercase\n const normalized = value.normalize(\"NFC\").toLowerCase();\n \n // Replace consecutive runs of non-letter, non-number, non-combining-mark characters with a single hyphen\n // Unicode letter categories: L* (Lu, Ll, Lt, Lm, Lo)\n // Unicode number categories: N* (Nd, Nl, No)\n // Unicode combining mark categories: M* (Mn, Mc, Me)\n const slugged = normalized.replace(/[^\\p{L}\\p{N}\\p{M}]+/gu, \"-\");\n \n // Trim leading and trailing hyphens\n return slugged.replace(/^-+|-+$/g, \"\");\n}\n\nmodule.exports = { slugify };"
},
"review_notes": [
"Uses String.prototype.normalize(\"NFC\") to decompose composed characters like é into base+combining mark, then toLowerCase() applies to normalized string",
"Unicode property escapes (\\p{L}, \\p{N}, \\p{M}) with /u flag preserve all Unicode letters, numbers, and combining marks while replacing other consecutive characters with single hyphens",
"Existing ASCII behavior is preserved: punctuation and whitespace are replaced with hyphens, then leading/trailing hyphens are trimmed",
"Non-string inputs return empty string as required; normalized decomposed characters (e.g., Cafe\\u0301) are handled correctly by NFC normalization"
]
}
```檢視 Claude Sonnet 5 所提交的完整回覆
{"files":{"src/slugify.js":"function slugify(value) {\n if (typeof value !== \"string\") return \"\";\n return value\n .normalize(\"NFC\")\n .toLowerCase()\n .replace(/[^\\p{L}\\p{N}\\p{M}]+/gu, \"-\")\n .replace(/^-+|-+$/g, \"\");\n}\n\nmodule.exports = { slugify };\n"},"review_notes":["Used Unicode property escapes (\\p{L}, \\p{N}, \\p{M}) with the u flag to preserve letters, numbers, and combining marks across scripts.","NFC normalization ensures decomposed sequences like Cafe + combining acute compose to café before lowercasing.","Runs of any other characters (punctuation, whitespace, symbols) collapse to a single hyphen, then leading/trailing hyphens are trimmed."]}檢視 Claude Opus 5.5 原樣退回的完整回覆
{"files":{"src/slugify.js":"function slugify(value) {\n if (typeof value !== \"string\") return \"\";\n return value\n .normalize(\"NFC\")\n .toLowerCase()\n .replace(/[^\\p{L}\\p{N}\\p{M}]+/gu, \"-\")\n .replace(/^-+|-+$/g, \"\");\n}\n\nmodule.exports = { slugify };\n"},"review_notes":["The input is normalized to NFC before lowercasing, so decomposed input like Cafe\\u0301 composes to café.","A Unicode property regex with the u flag keeps letters (\\p{L}), numbers (\\p{N}) and combining marks (\\p{M}). Each run of any other characters, including underscores and whitespace, becomes one hyphen.","The explicit trim() was removed because the final step strips leading and trailing hyphens, which covers surrounding whitespace.","Lowercasing happens after NFC normalization, as the spec orders. toLowerCase can occasionally produce non-NFC output for rare characters, and it is not re-normalized here."]}任務 2:修復一個路徑選擇器並回傳其測試案例
該函式必須處理最長前綴匹配、方法優先級、區段邊界、格式錯誤的規則以及不可變的輸入。所要求的回應中還包含了一個新的測試檔案。.
| 模型 | 行為檢查 | 回應格式 | 完成所要求的送貨 |
|---|---|---|---|
| 克勞德俳句 4.5 | 僅針對完整功能,12/12 | 失敗:JSON 內容被截斷 | 編號:測試檔案被截斷 |
| 克勞德·索內特 第五首 | 僅針對完整功能,12/12 | 失敗:JSON 內容被截斷 | 編號:測試檔案被截斷 |
| Claude Opus 5.5 | 僅針對完整功能,12/12 | 失敗:JSON 內容被截斷 | 編號:測試檔案被截斷 |
觀察結果: 沒有任何模型能在共享的輸出限制內完成所要求的兩份檔案回應。三者皆在報告的 4,096 個完成標記處停止。每個模型都已返回完整的路由器函式,且該函式通過了十二組固定行為測試;新的測試檔案因不完整而未被執行。.
我們僅萃取了每個完全封閉的原始碼字串。下文中的原始截斷回應仍保持原樣。因此,函式評分合格並不代表完整的請求已成功。.
其他程式碼審查發現:因根號相等而出現平手
在完成固定檢查後,我們注意到 Haiku 已進行標準化 /// 轉為空字串,而不是 /. 另一項獨立的本地檢查使用了兩條 GET 規則,其前綴分別為 /// 和 /, 目標鎖定 第一 和 第二 依此順序。因為 /任何東西, ,根據合約規定 第一.
俳句回歸 第二; 《十四行詩》與《作品集》重現 第一. 這項額外的檢查是因程式碼審查而引發的,與測試前設定的十二項檢查是分開的。它不會影響那些檢查的分數。.
Sonnet 在其允許的重試次數內發生了一次服務錯誤,隨後返回了顯示中的截斷回應。該服務故障與程式碼品質無關。沒有任何模型收到進一步嘗試來改進或完成其回答。.
檢視完整的共享提示與輸入程式碼
SYSTEM
You are completing a bounded JavaScript coding task. Return only the requested JSON object with complete source files and brief review notes. Do not claim to have edited files, run commands, or used tools. You have no tool access. Do not include hidden reasoning.
USER
Repair a Node.js 18+ CommonJS route selector. Return complete replacement src/router.js and an additional test/router-added.test.js using node:test and node:assert/strict. Do not add dependencies or edit existing tests. Do not use I/O other than the test runner, network, child processes, timers, or any files beyond the two requested outputs.
Contract for chooseRoute(request, rules):
1. Invalid request or rules returns null, without throwing. Request must be a non-null, non-array object; method must be a nonempty ASCII-letter string; path must be a string beginning with /. Rules must be an array.
2. Before matching, remove the request path's query and fragment starting at the earliest ? or #. Do not URL-decode or collapse interior slashes.
3. Ignore invalid rules. A valid rule is a non-null, non-array object with method '*' or a nonempty ASCII-letter string, prefix a string starting with / containing neither ? nor #, and target a nonempty string.
4. Compare methods case-insensitively. Prefer any matching exact-method rule over all wildcard-method '*' rules, even if a wildcard has a longer prefix. Use wildcard rules only if no exact-method route matches the path.
5. Remove trailing slashes from a rule prefix, except that an all-slash prefix normalizes to /. A prefix matches the path only at a segment boundary: /api matches /api and /api/users, never /apix. Root / matches every valid request path.
6. Within the chosen method group, choose the longest normalized matching prefix. On equal prefix length, choose the earlier rule in the original input array. Return its target. Return null if none matches.
7. Do not mutate the request, rules array, or rule objects, including order or prefix strings. Preserve module.exports = { chooseRoute }.
8. Add tests for segment boundaries, query/fragment removal, method precedence, ties, malformed inputs and immutability. Existing simple GET /api/users and POST-no-match cases must still pass.
Current src/router.js:
```javascript
function chooseRoute(request, rules) {
if (!request || !Array.isArray(rules)) return null;
for (const rule of rules) {
if (request.method === rule.method && request.path.startsWith(rule.prefix)) {
return rule.target;
}
}
return null;
}
module.exports = { chooseRoute };
```
Existing regression cases (unchanged): rules [{method:'GET',prefix:'/api',target:'api'},{method:'GET',prefix:'/api/admin',target:'admin'}]; GET /api/users returns 'api'; POST /api/users returns null.
Return exactly one JSON object with this shape:
{"files":{"src/router.js":"complete JavaScript source as a JSON string","test/router-added.test.js":"complete JavaScript tests as a JSON string"},"review_notes":["at most four brief implementation or assumption notes"]}
No Markdown wrapper. You are returning code for someone else to evaluate locally; do not say you edited files, ran tests, or observed passing results.
查看 Claude Haiku 4.5 提供的完整回覆(以原始形式呈現)
這是收到的完整回應。由於達到限制,輸出中途便結束了;缺失的內容並未被補上。.
```json
{
"files": {
"src/router.js": "function chooseRoute(request, rules) {\n // Validate request\n if (request === null || Array.isArray(request) || typeof request !== 'object') {\n return null;\n }\n if (typeof request.method !== 'string' || request.method.length === 0 || !/^[a-zA-Z]+$/.test(request.method)) {\n return null;\n }\n if (typeof request.path !== 'string' || !request.path.startsWith('/')) {\n return null;\n }\n\n // Validate rules\n if (!Array.isArray(rules)) {\n return null;\n }\n\n // Remove query and fragment from path\n const cleanPath = request.path.split(/[?#]/)[0];\n\n // Filter and validate rules\n const validRules = [];\n for (const rule of rules) {\n if (rule === null || Array.isArray(rule) || typeof rule !== 'object') {\n continue;\n }\n \n const method = rule.method;\n if (typeof method !== 'string' || (method !== '*' && (method.length === 0 || !/^[a-zA-Z]+$/.test(method)))) {\n continue;\n }\n \n const prefix = rule.prefix;\n if (typeof prefix !== 'string' || !prefix.startsWith('/') || prefix.includes('?') || prefix.includes('#')) {\n continue;\n }\n \n const target = rule.target;\n if (typeof target !== 'string' || target.length === 0) {\n continue;\n }\n \n validRules.push(rule);\n }\n\n // Normalize prefixes and partition into exact-method and wildcard groups\n const exactMethodRules = [];\n const wildcardRules = [];\n \n for (const rule of validRules) {\n const normalizedPrefix = rule.prefix === '/' ? '/' : rule.prefix.replace(/\/+$/, '');\n \n const entry = {\n originalRule: rule,\n normalizedPrefix: normalizedPrefix,\n method: rule.method\n };\n \n if (rule.method === '*') {\n wildcardRules.push(entry);\n } else {\n exactMethodRules.push(entry);\n }\n }\n\n const requestMethod = request.method.toUpperCase();\n\n // Helper to check if a prefix matches the path at a segment boundary\n function prefixMatches(prefix, path) {\n if (prefix === '/') {\n return true;\n }\n if (!path.startsWith(prefix)) {\n return false;\n }\n // Check segment boundary: next character must be '/' or end of string\n const nextChar = path[prefix.length];\n return nextChar === undefined || nextChar === '/';\n }\n\n // Try exact-method rules first\n let bestMatch = null;\n let bestLength = -1;\n \n for (const entry of exactMethodRules) {\n if (entry.method.toUpperCase() === requestMethod) {\n if (prefixMatches(entry.normalizedPrefix, cleanPath)) {\n if (entry.normalizedPrefix.length > bestLength) {\n bestMatch = entry.originalRule;\n bestLength = entry.normalizedPrefix.length;\n }\n }\n }\n }\n \n if (bestMatch !== null) {\n return bestMatch.target;\n }\n\n // Try wildcard rules only if no exact-method match\n bestMatch = null;\n bestLength = -1;\n \n for (const entry of wildcardRules) {\n if (prefixMatches(entry.normalizedPrefix, cleanPath)) {\n if (entry.normalizedPrefix.length > bestLength) {\n bestMatch = entry.originalRule;\n bestLength = entry.normalizedPrefix.length;\n }\n }\n }\n \n if (bestMatch !== null) {\n return bestMatch.target;\n }\n\n return null;\n}\n\nmodule.exports = { chooseRoute };",
"test/router-added.test.js": "const test = require('node:test');\nconst assert = require('node:assert/strict');\nconst { chooseRoute } = require('../src/router.js');\n\n// Regression: existing test cases\ntest('GET /api/users matches /api prefix (exact method)', () => {\n const rules = [\n { method: 'GET', prefix: '/api', target: 'api' },\n { method: 'GET', prefix: '/api/admin', target: 'admin' }\n ];\n assert.equal(chooseRoute({ method: 'GET', path: '/api/users' }, rules), 'api');\n});\n\ntest('POST /api/users returns null (no matching method)', () => {\n const rules = [\n { method: 'GET', prefix: '/api', target: 'api' },\n { method: 'GET', prefix: '/api/admin', target: 'admin' }\n ];\n assert.equal(chooseRoute({ method: 'POST', path: '/api/users' }, rules), null);\n});\n\n// Invalid request handling\ntest('null request returns null', () => {\n assert.equal(chooseRoute(null, []), null);\n});\n\ntest('array request returns null', () => {\n assert.equal(chooseRoute([], []), null);\n});\n\ntest('request with missing method returns null', () => {\n assert.equal(chooseRoute({ path: '/api' }, []), null);\n});\n\ntest('request with empty method returns null', () => {\n assert.equal(chooseRoute({ method: '', path: '/api' }, []), null);\n});\n\ntest('request with non-letter method returns null', () => {\n assert.equal(chooseRoute({ method: 'GET-POST', path: '/api' }, []), null);\n});\n\ntest('request with numeric method returns null', () => {\n assert.equal(chooseRoute({ method: '123', path: '/api' }, []), null);\n});\n\ntest('request with missing path returns null', () => {\n assert.equal(chooseRoute({ method: 'GET' }, []), null);\n});\n\ntest('request with path not starting with / returns null', () => {\n assert.equal(chooseRoute({ method: 'GET', path: 'api' }, []), null);\n});\n\ntest('null rules returns null', () => {\n assert.equal(chooseRoute({ method: 'GET', path: '/api' }, null), null);\n});\n\ntest('non-array rules returns null', () => {\n assert.equal(chooseRoute({ method: 'GET', path: '/api' }, { method: 'GET' }), null);\n});\n\n// Query and fragment removal\ntest('query string is removed before matching', () => {\n const rules = [{ method: 'GET', prefix: '/api', target: 'found' }];\n assert.equal(chooseRoute({ method: 'GET', path: '/api/users?foo=bar' }, rules), 'found');\n});\n\ntest('fragment is removed before matching', () => {\n const rules = [{ method: 'GET', prefix: '/api', target: 'found' }];\n assert.equal(chooseRoute({ method: 'GET', path: '/api/users#section' }, rules), 'found');\n});\n\ntest('earliest ? or # is used as boundary', () => {\n const rules = [{ method: 'GET', prefix: '/api', target: 'found' }];\n assert.equal(chooseRoute({ method: 'GET', path: '/api/users?foo#bar' }, rules), 'found');\n});\n\ntest('fragment before query is used as boundary', () => {\n const rules = [{ method: 'GET', prefix: '/api', target: 'found' }];\n assert.equal(chooseRoute({ method: 'GET', path: '/api/users#foo?bar' }, rules), 'found');\n});\n\n// Segment boundary matching\ntest('prefix /api matches /api/users at segment boundary', () => {\n const rules = [{ method: 'GET', prefix: '/api', target: 'found' }];\n assert.equal(chooseRoute({ method: 'GET', path: '/api/users' }, rules), 'found');\n});\n\ntest('prefix /api does not match /apix (no segment boundary)', () => {\n const rules = [{ method: 'GET', prefix: '/api', target: 'found' }];\n assert.equal(chooseRoute({ method: 'GET', path: '/apix' }, rules), null);\n});\n\ntest('prefix /api matches /api exactly at segment boundary', () => {\n const rules = [{ method: 'GET', prefix: '/api', target: 'found' }];\n assert.equal(chooseRoute({ method: 'GET', path: '/api' }, rules), 'found');\n});\n\ntest('root / matches any valid path', () => {\n const rules = [{ method: 'GET', prefix: '/', target: 'root' }];\n assert.equal(chooseRoute({ method: 'GET', path: '/anything/here' }, rules), 'root');\n});\n\ntest('root / matches /', () => {\n const rules = [{ method: 'GET', prefix: '/', target: 'root' }];\n assert.equal(chooseRoute({ method: 'GET', path: '/' }, rules), 'root');\n});\n\n// Prefix normalization (trailing slash removal)\ntest('trailing slash is removed from prefix', () => {\n const rules = [{ method: 'GET', prefix: '/api/', target: 'found' }];\n assert.equal(chooseRoute({ method: 'GET', path: '/api/users' }, rules), 'found');\n});\n\ntest('multiple trailing slashes are removed', () => {\n const rules = [{ method: 'GET', prefix: '/api///', target: 'found' }];\n assert.equal(chooseRoute({ method: 'GET', path: '/api/users' }, rules), 'found');\n});\n\ntest('all-slash prefix normalizes to single /', () => {\n const rules = [{ method: 'GET', prefix: '///', target: 'found' }];\n assert.equal(chooseRoute({ method: 'GET', path: '/api' }, rules), 'found');\n});\n\n// Method case-insensitivity\ntest('method comparison is case-insensitive', () => {\n const rules = [{ method: 'get', prefix: '/api', target: 'found' }];\n assert.equal(chooseRoute({ method: 'GET', path: '/api' }, rules), 'found');\n});\n\ntest('request method case does not affect matching', () => {\n const rules = [{ method: 'GET', prefix: '/api', target: 'found' }];\n assert.equal(chooseRoute({ method: 'get', path: '/api' }, rules), 'found');\n});\n\n// Exact-method vs wildcard precedence\ntest('exact-method rule preferred over wildcard with longer prefix', () => {\n const rules = [\n { method: '*', prefix: '/api/admin/users', target: 'wildcard' },\n { method: 'GET', prefix: '/api', target: 'exact' }\n ];\n assert.equal(chooseRoute({ method: 'GET', path: '/api/test' }, rules), 'exact');\n});\n\ntest('wildcard rule used when no exact-method matches', () => {\n const rules = [\n { method: '*', prefix: '/api', target: 'wildcard' },\n { method: 'GET', prefix: '/other', target: 'exact' }\n ];\n assert.equal(chooseRoute({ method: 'POST', path: '/api/users' }, rules), 'wildcard');\n});\n\n// Longest prefix matching\ntest('longest matching prefix is chosen', () => {\n const rules = [\n { method: 'GET', prefix: '/api', target: 'short' },\n { method: 'GET', prefix: '/api/admin', target: 'long' }\n ];\n assert.equal(chooseRoute({ method: 'GET', path: '/api/admin/users' }, rules), 'long');\n});\n\n// Tie-breaking (first rule wins on equal prefix length)\ntest('first rule wins on equal prefix length', () => {\n const rules = [\n { method: 'GET', prefix: '/api', target: 'first' },\n { method: 'GET', prefix: '/api', target: 'second' }\n ];\n assert.equal(chooseRoute({ method: 'GET', path: '/api/users' }, rules), 'first');\n});\n\n// Invalid rules are ignored\ntest('null rule is ignored', () => {\n const rules = [\n null,\n { method: 'GET', prefix: '/api', target: 'found' }\n ];\n assert.equal(chooseRoute({ method: 'GET', path: '/api' }, rules), 'found');\n});\n\ntest('array rule is ignored', () => {\n const rules = [\n [],\n { method: 'GET', prefix: '/api', target: 'found' }\n ];\n assert.equal(chooseRoute({ method: 'GET', path: '/api' }, rules), 'found');\n});\n\ntest('rule with invalid method is ignored', () => {\n const rules = [\n { method: '', prefix: '/api', target: 'invalid' },\n { method: 'GET', prefix: '/api', target: 'valid' }\n ];\n assert.equal(chooseRoute({ method: 'GET', path: '/api' }, rules), 'valid');\n});\n\ntest('rule with non-letter method (if not wildcard) is ignored', () => {\n const rules = [\n { method: 'G3T', prefix: '/api', target: 'invalid' },\n { method: 'GET', prefix: '/api', target: 'valid' }\n ];\n assert.equal(chooseRoute({ method: 'GET', path: '/api' }, rules), 'valid');\n});\n\ntest('rule with prefix not starting with / is ignored', () => {\n const rules = [\n { method: 'GET', prefix: 'api', target: 'invalid' },\n { method: 'GET', prefix: '/api', target: 'valid' }\n ];\n assert.equal(chooseRoute({ method: 'GET', path: '/api' }, rules), 'valid');\n});\n\ntest('rule with query in prefix is ignored', () => {\n const rules = [\n { method: 'GET', prefix: '/api?foo=bar', target: 'invalid' },\n { method: 'GET', prefix: '/api', target: 'valid' }\n ];\n assert.equal(chooseRoute({ method: 'GET', path: '/api' }, rules), 'valid');\n});\n\ntest('rule with fragment in prefix is ignored', () => {\n const rules = [\n { method: 'GET', prefix: '/api#section', target: 檢視 Claude Sonnet 5 所提交的完整回覆
這是收到的完整回應。由於達到限制,輸出中途便結束了;缺失的內容並未被補上。.
{"files":{"src/router.js":"function isValidRequest(request) {\n return (\n request !== null &&\n typeof request === 'object' &&\n !Array.isArray(request) &&\n typeof request.method === 'string' &&\n request.method.length > 0 &&\n /^[A-Za-z]+$/.test(request.method) &&\n typeof request.path === 'string' &&\n request.path.startsWith('/')\n );\n}\n\nfunction isValidRule(rule) {\n if (rule === null || typeof rule !== 'object' || Array.isArray(rule)) {\n return false;\n }\n const { method, prefix, target } = rule;\n\n if (typeof method !== 'string') return false;\n if (method !== '*' && !(method.length > 0 && /^[A-Za-z]+$/.test(method))) {\n return false;\n }\n\n if (\n typeof prefix !== 'string' ||\n !prefix.startsWith('/') ||\n prefix.includes('?') ||\n prefix.includes('#')\n ) {\n return false;\n }\n\n if (typeof target !== 'string' || target.length === 0) return false;\n\n return true;\n}\n\nfunction normalizePrefix(prefix) {\n if (/^\/+$/.test(prefix)) return '/';\n return prefix.replace(/\/+$/, '');\n}\n\nfunction prefixMatches(normalizedPrefix, path) {\n if (normalizedPrefix === '/') return true;\n if (path === normalizedPrefix) return true;\n return path.startsWith(normalizedPrefix + '/');\n}\n\nfunction stripQueryAndFragment(path) {\n let cutIndex = path.length;\n for (let i = 0; i < path.length; i++) {\n const c = path[i];\n if (c === '?' || c === '#') {\n cutIndex = i;\n break;\n }\n }\n return path.slice(0, cutIndex);\n}\n\nfunction chooseRoute(request, rules) {\n if (!isValidRequest(request) || !Array.isArray(rules)) return null;\n\n const path = stripQueryAndFragment(request.path);\n const reqMethodLower = request.method.toLowerCase();\n\n let bestExact = null; // { len, idx, target }\n let bestWildcard = null;\n\n for (let idx = 0; idx < rules.length; idx++) {\n const rule = rules[idx];\n if (!isValidRule(rule)) continue;\n\n const normPrefix = normalizePrefix(rule.prefix);\n if (!prefixMatches(normPrefix, path)) continue;\n\n const len = normPrefix.length;\n\n if (rule.method === '*') {\n if (\n bestWildcard === null ||\n len > bestWildcard.len ||\n (len === bestWildcard.len && idx < bestWildcard.idx)\n ) {\n bestWildcard = { len, idx, target: rule.target };\n }\n } else if (rule.method.toLowerCase() === reqMethodLower) {\n if (\n bestExact === null ||\n len > bestExact.len ||\n (len === bestExact.len && idx < bestExact.idx)\n ) {\n bestExact = { len, idx, target: rule.target };\n }\n }\n }\n\n if (bestExact !== null) return bestExact.target;\n if (bestWildcard !== null) return bestWildcard.target;\n return null;\n}\n\nmodule.exports = { chooseRoute };\n","test/router-added.test.js":"const test = require('node:test');\nconst assert = require('node:assert/strict');\nconst { chooseRoute } = require('../src/router');\n\ntest('segment boundary: prefix matches at slash boundary only', () => {\n const rules = [\n { method: 'GET', prefix: '/api', target: 'api' },\n ];\n assert.equal(\n chooseRoute({ method: 'GET', path: '/api/users' }, rules),\n 'api'\n );\n assert.equal(\n chooseRoute({ method: 'GET', path: '/api' }, rules),\n 'api'\n );\n assert.equal(\n chooseRoute({ method: 'GET', path: '/apix' }, rules),\n null\n );\n});\n\ntest('root prefix matches every valid path', () => {\n const rules = [{ method: 'GET', prefix: '/', target: 'root' }];\n assert.equal(chooseRoute({ method: 'GET', path: '/' }, rules), 'root');\n assert.equal(\n chooseRoute({ method: 'GET', path: '/anything/here' }, rules),\n 'root'\n );\n});\n\ntest('trailing slashes in rule prefix are normalized', () => {\n const rules = [{ method: 'GET', prefix: '/api///', target: 'api' }];\n assert.equal(\n chooseRoute({ method: 'GET', path: '/api/users' }, rules),\n 'api'\n );\n assert.equal(chooseRoute({ method: 'GET', path: '/api' }, rules), 'api');\n});\n\ntest('all-slash prefix normalizes to /', () => {\n const rules = [{ method: 'GET', prefix: '////', target: 'root' }];\n assert.equal(\n chooseRoute({ method: 'GET', path: '/whatever' }, rules),\n 'root'\n );\n});\n\ntest('query and fragment are stripped before matching', () => {\n const rules = [{ method: 'GET', prefix: '/api', target: 'api' }];\n assert.equal(\n chooseRoute({ method: 'GET', path: '/api/users?x=1&y=2' }, rules),\n 'api'\n );\n assert.equal(\n chooseRoute({ method: 'GET', path: '/api/users#section' }, rules),\n 'api'\n );\n assert.equal(\n chooseRoute({ method: 'GET', path: '/api/users?x=1#frag' }, rules),\n 'api'\n );\n});\n\ntest('query/fragment stripping does not decode or collapse slashes', () => {\n const rules = [{ method: 'GET', prefix: '/a//b', target: 'weird' }];\n assert.equal(\n chooseRoute({ method: 'GET', path: '/a//b?x=1' }, rules),檢視 Claude Opus 5.5 原樣退回的完整回覆
這是收到的完整回應。由於達到限制,輸出中途便結束了;缺失的內容並未被補上。.
{"files":{"src/router.js":"'use strict';\n\nconst LETTERS = /^[A-Za-z]+$/;\n\nfunction isPlainObject(value) {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction isMethodName(value) {\n return typeof value === 'string' && value.length > 0 && LETTERS.test(value);\n}\n\nfunction stripQueryAndFragment(path) {\n const q = path.indexOf('?');\n const h = path.indexOf('#');\n let cut = -1;\n if (q !== -1 && h !== -1) cut = Math.min(q, h);\n else if (q !== -1) cut = q;\n else if (h !== -1) cut = h;\n return cut === -1 ? path : path.slice(0, cut);\n}\n\nfunction normalizePrefix(prefix) {\n let end = prefix.length;\n while (end > 0 && prefix[end - 1] === '/') end -= 1;\n return end === 0 ? '/' : prefix.slice(0, end);\n}\n\nfunction prefixMatches(path, prefix) {\n if (prefix === '/') return true;\n return path === prefix || path.startsWith(prefix + '/');\n}\n\nfunction chooseRoute(request, rules) {\n try {\n if (!isPlainObject(request) || !Array.isArray(rules)) return null;\n const method = request.method;\n const rawPath = request.path;\n if (!isMethodName(method)) return null;\n if (typeof rawPath !== 'string' || rawPath[0] !== '/') return null;\n\n const path = stripQueryAndFragment(rawPath);\n const upperMethod = method.toUpperCase();\n\n let bestExact = null;\n let bestWildcard = null;\n\n const count = rules.length;\n for (let i = 0; i < count; i += 1) {\n const rule = rules[i];\n if (!isPlainObject(rule)) continue;\n const ruleMethod = rule.method;\n const prefix = rule.prefix;\n const target = rule.target;\n const isWildcard = ruleMethod === '*';\n if (!isWildcard && !isMethodName(ruleMethod)) continue;\n if (typeof prefix !== 'string' || prefix[0] !== '/') continue;\n if (prefix.indexOf('?') !== -1 || prefix.indexOf('#') !== -1) continue;\n if (typeof target !== 'string' || target.length === 0) continue;\n\n const normalized = normalizePrefix(prefix);\n if (!prefixMatches(path, normalized)) continue;\n\n const candidate = { length: normalized.length, target };\n if (isWildcard) {\n if (bestWildcard === null || candidate.length > bestWildcard.length) bestWildcard = candidate;\n } else if (ruleMethod.toUpperCase() === upperMethod) {\n if (bestExact === null || candidate.length > bestExact.length) bestExact = candidate;\n }\n }\n\n if (bestExact !== null) return bestExact.target;\n if (bestWildcard !== null) return bestWildcard.target;\n return null;\n } catch (err) {\n return null;\n }\n}\n\nmodule.exports = { chooseRoute };\n","test/router-added.test.js":"'use strict';\n\nconst test = require('node:test');\nconst assert = require('node:assert/strict');\nconst { chooseRoute } = require('../src/router.js');\n\nconst baseRules = [\n { method: 'GET', prefix: '/api', target: 'api' },\n { method: 'GET', prefix: '/api/admin', target: 'admin' }\n];\n\ntest('existing regression cases still hold', () => {\n assert.equal(chooseRoute({ method: 'GET', path: '/api/users' }, baseRules), 'api');\n assert.equal(chooseRoute({ method: 'POST', path: '/api/users' }, baseRules), null);\n});\n\ntest('longest prefix wins within method group', () => {\n assert.equal(chooseRoute({ method: 'GET', path: '/api/admin/x' }, baseRules), 'admin');\n assert.equal(chooseRoute({ method: 'GET', path: '/api/admin' }, baseRules), 'admin');\n});\n\ntest('segment boundaries', () => {\n const rules = [{ method: 'GET', prefix: '/api', target: 'api' }];\n assert.equal(chooseRoute({ method: 'GET', path: '/api' }, rules), 'api');\n assert.equal(chooseRoute({ method: 'GET', path: '/api/' }, rules), 'api');\n assert.equal(chooseRoute({ method: 'GET', path: '/api/users' }, rules), 'api');\n assert.equal(chooseRoute({ method: 'GET', path: '/apix' }, rules), null);\n assert.equal(chooseRoute({ method: 'GET', path: '/ap' }, rules), null);\n});\n\ntest('trailing slashes in prefixes are normalized, all-slash is root', () => {\n const rules = [{ method: 'GET', prefix: '/api///', target: 'api' }];\n assert.equal(chooseRoute({ method: 'GET', path: '/api' }, rules), 'api');\n assert.equal(chooseRoute({ method: 'GET', path: '/apix' }, rules), null);\n const rootRules = [{ method: 'GET', prefix: '///', target: 'root' }];\n assert.equal(chooseRoute({ method: 'GET', path: '/' }, rootRules), 'root');\n assert.equal(chooseRoute({ method: 'GET', path: '/anything/else' }, rootRules), 'root');\n assert.equal(chooseRoute({ method: 'GET', path: '/x' }, [{ method: 'GET', prefix: '/', target: 'r' }]), 'r');\n});\n\ntest('query and fragment are removed at earliest ? or #', () => {\n assert.equal(chooseRoute({ method: 'GET', path: '/api?next=/api/admin' }, baseRules), 'api');\n assert.equal(chooseRoute({ method: 'GET', path: '/api#/admin' }, baseRules), 'api');\n assert.equal(chooseRoute({ method: 'GET', path: '/apix?/api' }, baseRules), null);\n assert.equal(chooseRoute({ method: 'GET', path: '/api/admin#frag?q' }, baseRules), 'admin');\n assert.equal(chooseRoute({ method: 'GET', path: '/api?q#/admin' }, baseRules), 'api');\n});\n\ntest('no URL decoding and no slash collapsing', () => {\n const rules = [{ method: 'GET', prefix: '/api/admin', target: 'admin' }];\n assert.equal(chooseRoute({ method: 'GET', path: '/api%2Fadmin' }, rules), null);\n assert.equal(chooseRoute({ method: 'GET', path: '/api//admin' }, rules), null);\n assert.equal(chooseRoute({ method: 'GET', path: '/api//admin' }, baseRules), 'api');\n});\n\ntest('methods compare case-insensitively', () => {\n const rules = [{ method: 'get', prefix: '/a', target: 'lower' }];\n assert.equal(chooseRoute({ method: 'GET', path: '/a' }, rules), 'lower');\n assert.equal(chooseRoute({ method: 'gEt', path: '/a/b' }, rules), 'lower');\n});\n\ntest('exact method beats longer wildcard; wildcard used only as fallback', () => {\n const rules = [\n { method: '*', prefix: '/api/admin', target: 'wild-admin' },\n { method: 'GET', prefix: '/', target: 'get-root' },\n { method: 'POST', prefix: '/other', target: 'post-other' },\n { method: '*', prefix: '/api', target: 'wild-api' }\n ];\n assert.equal(chooseRoute({ method: 'GET', path: '/api/admin/x' }, rules), 'get-root');\n assert.equal(chooseRoute({ method: 'POST', path: '/api/admin/x' }, rules), 'wild-admin');\n assert.equal(chooseRoute({ method: 'POST', path: '/api/x' }, rules), 'wild-api');\n assert.equal(chooseRoute({ method: 'POST', path: '/other/1' }, rules), 'post-other');\n assert.equal(chooseRoute({ method: 'PUT', path: '/nothing' }, rules), null);\n});\n\ntest('ties go to earlier rule in input order', () => {\n const rules = [\n { method: 'GET', pref4,096 個令牌的上限是本次測試所選定的輸出預算,並非任何模型的文件記載最大值。路由結果顯示,在發出更大規模的請求前,應進行實務上的確認:預先估算預期收到的實作內容、測試結果及解釋的規模。 將產出拆分或增加輸出空間可能是合適的做法;我們並未以不同設定重新執行這些輸出。.
在處理您自己的任務時,請分別從三個方面進行評估:回應是否完整、程式碼是否通過實用的檢查,以及審查是否發現了這些檢查所遺漏的缺漏。即使通過了十二項函式檢查,那些被截斷的兩檔回應也仍不構成完整的交付成果。.
選擇不同模型會對成本產生什麼影響
Claude Code 是一款編碼工具;Haiku、Sonnet、Opus 和 Fable 則是支援環境中的模型選項。驗證與付款方式亦屬可選項目。變更模型並不會將訂閱轉為 API 帳戶,也不會使所有使用限制消失。.
| 帳單寄送路線 | 看什麼 | 如何解讀模型選擇 |
|---|---|---|
| Claude 訂閱權限 | 方案內的使用量以及任何另行啟用的使用額度 | 不同機型的配額消耗方式可能有所不同;請查閱該方案提供的機型及限額 |
| Anthropic API 存取 | 輸入/輸出代幣、快取以及適用的 API 費用 | 請根據當前的費率表及實際使用量進行計算,然後在計費控制台中確認費用 |
| 雲端服務供應商或閘道器 | 您的服務提供者所支援的身分識別碼、費率及帳單紀錄 | Anthropic 的建議售價範例,可能與您的服務供應商實際收取的金額不盡相同 |
在 Claude 程式碼中,, /用法 顯示會話代幣資訊,以及(如適用)訂閱使用量進度條。其美元金額是根據清單或已設定的費率在本地計算出的估算值;這並非發票。對於 Pro 和 Max 訂閱者而言,該會話數字並不表示訂閱中新增了額外的 API 費用。進一步了解 Claude 代碼的定價與計費路徑 如果您正在考慮該如何付款。.
當前的 API 價格及等值代幣範例
Anthropic 每百萬個輸入/輸出代幣的標準基礎費率為 Haiku 4.5:$1/$5;Sonnet 5:$2/$10; Opus 5.5:$4/$20;Fable 5.1:$10/$50, ,查閱日期:2026年9月28日。下圖將代幣交易量設定為恆定值,以便於進行數值比較。.
相同的代幣數量,四種不同的 API 費用
範例: 100,000 個未緩存的輸入標記 + 10,000 個輸出標記, ,採用 Anthropic 於 2026 年 9 月 28 日查核之標準 API 清單價格。.
查看費率與計算方式
| 模型 | 輸入 / 1M | 輸出 / 1M | 範例總計 |
|---|---|---|---|
| 俳句 4.5 | $1 | $5 | $0.15 |
| 第5首十四行詩 | $2 | $10 | $0.30 |
| 作品第 5.5 號 | $4 | $20 | $0.60 |
| Fable 5.1 | $10 | $50 | $1.50 |
計算方式:0.1 × 輸入速率 + 0.01 × 輸出速率。以 Opus 5.5 為例:0.1 × $4 + 0.01 × $20 = $0.60。.
這是一個採用固定代幣數值的示意圖。實際任務消耗的代幣總數各不相同;快取寫入與讀取、重試、工具、供應商計費以及訂閱限制,均需分別進行核算。.
Source: Anthropic API 定價.

真正的 Claude Code 任務是一系列請求。先前的上下文可能會再次傳送,模型可能會進行進一步分析,而工具或額外的代理程式可能會產生更多工作。提示字串快取也有其獨特的寫入與讀取速率。因此,範例中最低的那條柱狀圖並不能代表每項被接受變更的最低成本。.
五種在不削弱任務成效的前提下控制成本的方法
- 在選擇模型之前,請先定義「接受標準」。. 請說明預期行為、邊界情況以及現有的限制條件。明確且規模較小的任務,在經濟上更容易委派,也更容易進行審查。.
- 請提供相關背景資訊。. 請附上該模型所需的檔案及失敗詳情。若涉及無關的工作,請開啟新的對話,而非僅因既有對話紀錄存在,就將冗長的對話歷史一併帶入新討論中。.
- 要區分「能力」與「努力」。. Anthropic 建議先從模型的預設投入程度開始。如果模型已正確讀取上下文,卻仍無法解決問題,則採用更強大的模型可能會有所幫助。如果模型跳過了讀取或驗證步驟,請檢查任務設定和投入程度選擇。.
- 請提供整段回答的預算。. 原始碼、測試程式碼和說明都需要輸出空間。我們的第二項任務將說明,為何僅憑一個完整的函式,並不能證明所要求的交付成果符合預算。.
- 比較已被採納的作品。. 針對具代表性的任務,記錄有用的輸出結果、重試次數、審查時間以及實際計費資料。請將服務提供者造成的錯誤與模型品質問題區分開來。.
這些策略與 官方費用指南 和 Anthropic 的「模型與工作量」指引. 切換模式後,整個方案層級的每週或每次使用上限仍可能繼續生效;但針對特定模式的上限則屬另一種情況。若需反覆切換模式,請先確認實際上限。.
若您的工作涵蓋程式碼、研究、寫作及媒體等領域,也請比較您所支付的那些工作流程。. GlobalGPT 的多模型工作區 將這些功能整合至單一儀表板中,並提供用於開發任務的命令列介面 (CLI) 存取權限。在評估計量式 API 路由時,應一併考量這項更廣泛的工作流程價值;上方的 API 圖表並非 GlobalGPT 訂閱價格表。.
為什麼您選擇的模型可能無法奏效
| 症狀 | 可能的檢查 | 切實可行的下一步 |
|---|---|---|
| 下一節將使用舊的模型 | 該開關可能僅限於當前工作階段 | 使用選取器的「Enter」動作進行儲存,然後檢查新的工作階段 |
| 偏好設定已儲存,但啟動的卻是另一個模型 | 「啟動」、「外殼」、「專案」、「受管理」或「組織」設定可能具有優先權 | 閱讀啟動資訊,並與其負責人一起檢查相關設定 |
| 恢復的對話採用不同的模式 | 已儲存的會話可能會還原其先前的模型 | 檢查 /status;在恢復工作時,請審慎選擇所需的模型 |
| 該模型遺失或遭拒絕 | 服務提供者的可用性、組織規則,或舊版的 Claude 程式碼版本 | 請確認支援的型號 ID、帳戶存取權限及版本需求 |
| 同一個姓氏在其他地方的解析方式不同 | 別名與提供者對應關係不同 | 當釋出版本必須保持不變時,請使用供應商的正確完整識別碼 |
| 更換服務不會重置使用上限 | 該限額可能適用於整個計劃 | 請閱讀使用說明並重新設定週期,而非單方面假設切換到家庭方案就足夠了 |
若 Claude Code 無法寫入您的使用者設定,互動式選項將僅在當前工作階段中生效,而不會永久儲存。對於受管理或自動生成的設定檔,可能需要由其擁有者進行變更,而非再次嘗試選擇。請避免僅為了讓某個選項顯示出來,就解除組織層級的限制。.
運用 GlobalGPT 建立更廣泛的工作流程
模型選擇是工作流程中的一環。您可能需要研究函式庫、草擬函式、向團隊夥伴說明變更內容、建立文件,以及準備視覺素材。GlobalGPT 將多種頂尖模型與 AI 功能整合於一個價格實惠的工作區中,因此這些任務都能在同一個儀表板中完成。.

就終端作業而言,該 GlobalGPT 命令列介面 將該平台的工具與開發環境相互連結。其文件中記載的設定流程會使用您的 GlobalGPT 帳號登入,並採用一般帳戶餘額。命令列介面(CLI)能支援更廣泛的編碼與創作工作流程,而 Claude Code 自身的模型則透過其模型控制功能,仍是一項經過深思熟慮的選擇。.
例如,先起草並審閱實施方案,採用另一種模式進行簡明說明,然後製作隨同發布版本一併提供的文件或資產。請依照指南進行: 將 GlobalGPT CLI 連接至 Claude 程式碼 當您需要進行工具整合時,請根據編碼任務,分別設定您的 Claude 程式碼推理模型。.
選擇一個起始模型,寫下定義成功的檢查項目,並在任務需要時升級。在宣布工作完成之前,請先審查完整的交付成果。. 使用 GlobalGPT 建立您的工作流程 當您希望在日常工作中,將模型選擇、研究、程式編寫及創意工具相互串聯時。.
常見問題
如何在 Claude Code 中變更模型?
執行 /model 指令以開啟選取器。按下 s 鍵僅會切換當前工作階段,或按下 Enter 鍵將選取的模型儲存為預設值。若要為單一新工作階段選擇模型,請使用 claude –model 指令並接上模型名稱來啟動。.
/model 會更改我儲存的預設值嗎?
在目前的互動式版本中,若按 Enter 鍵選取模型,或輸入 /model sonnet,系統會在可寫入時將該選擇儲存至使用者設定中。在選取器中按下 s 鍵的效果僅限當前工作階段。下次啟動時,其他設定仍可能具有優先權。.
什麼是預設的 Claude Code 型號?
執行時的預設值取決於您的帳戶、服務供應商及設定。該預設值會清除模型覆寫設定;它並非單一固定的模型 ID。請透過 /status 查詢當前有效的模型,並檢視選取器,而非假設每個帳戶都從相同的版本開始。.
Opusplan 的功能是什麼?
它在規劃模式下使用 Opus,在執行模式下則使用 Sonnet。它會依據模式轉換來運作,而非針對每個提示自動選擇成本最低的模型。實際成本取決於各階段所執行的作業。.
為什麼選取器中缺少一個模型?
可用性可能取決於您的服務供應商、帳戶、組織限制以及 Claude Code 的版本。請查閱當前模型的文件,並確認您環境中允許使用的模型。此外,家族別名在其他服務供應商處也可能對應至不同的版本。.
較便宜的機型是否總能讓任務成本更低?
不。代幣價格僅是其中一個因素。總使用量、不完整的回答、重試次數以及審查工作量,都會影響可接受變更的成本。在我們這次的小規模重構中,這三個函式皆通過測試;而那三個較大的、包含兩個檔案的回應,則全都因達到共用輸出限制而被截斷。.
來源
- Claude 代碼型號配置 — 模型選擇、預設值、別名、提供者之間的差異,以及 opusplan。.
- Claude 代碼費用 — 使用量預估、訂閱配額、快取及成本管控。.
- Anthropic 型號概覽 和 API 定價 — 現行車型的規格與建議售價。.
- 模型與工作量指引 — 能力、情境與投入之間的實際差異。.
- GlobalGPT CLI 說明文件 — 終端工作流程與基於帳戶的設定。.







