據(jù)管道:models.dev 緩存、查詢規(guī)則與自定義定價覆蓋層)
CodexBar 模型定價元數(shù)據(jù)管道m(xù)odels.dev 緩存、查詢規(guī)則與自定義定價覆蓋層【免費下載鏈接】CodexBarShow usage stats for OpenAI Codex and Claude Code, without having to login.項目地址: https://gitcode.com/GitHub_Trending/co/CodexBar導(dǎo)讀本文深入剖析 CodexBar 的模型定價元數(shù)據(jù)管道它如何以 models.dev 作為增量定價源配合內(nèi)置兜底價格表為 OpenAI Codex 與 Claude Code 的本地會話成本估算提供統(tǒng)一、可離線、可覆蓋的價格體系。讀者將掌握定價緩存的存放位置與刷新機制、provider/model 雙維度的精確查詢規(guī)則、USD per 1M tokens 到 per-token 的單位換算邏輯以及如何通過custom-pricing.json覆蓋層精確修改某個模型在本地掃描中的計價并理解價格指紋fingerprint為何能驅(qū)動下游緩存失效。整體架構(gòu)models.dev 增量定價 內(nèi)置兜底價格CodexBar 的成本計算并不只依賴一份硬編碼價格表。文檔明確了它的核心設(shè)計以 models.dev 作為增量定價來源additive pricing source與內(nèi)置兜底費率bundled fallback rates并存。models.dev 覆蓋不到的模型例如剛剛發(fā)布、尚未收錄的新模型回落到倉庫內(nèi)置的價格表一旦 models.dev 收錄了該模型后續(xù)刷新即優(yōu)先使用在線數(shù)據(jù)。二者的分工體現(xiàn)在 CostUsagePricing.swift 中內(nèi)置表codex與claude兩個字典以「每 token」為單位預(yù)置了一批常見模型的輸入、輸出、緩存讀/寫價格而 models.dev 查詢則作為更靠前的數(shù)據(jù)層。在代碼層面模型的最終解析由CostUsagePricing.resolvedCodexPricing(model:...)完成其返回結(jié)構(gòu)CodexPricing同時攜帶閾值 token 數(shù)與超閾值價格帶thresholdTokens/inputCostPerTokenAboveThreshold等說明價格解析不僅區(qū)分輸入/輸出還支持長上下文切換價格帶見 CostUsagePricing.swift。數(shù)據(jù)源與本地緩存數(shù)據(jù)源與緩存位置定價元數(shù)據(jù)來自一個公開接口無需任何 API Key源 APIhttps://models.dev/api.json本地緩存~/Library/Caches/CodexBar/model-pricing/models-dev-v1.jsonTTL24 小時源碼中這三個要素均有對應(yīng)常量。ModelsDevClient默認(rèn) URL 即為該接口請求使用 GET、超時 20 秒并在收到非 2xx 狀態(tài)碼或 JSON 解析失敗時拋出ModelsDevClient.Error見 ModelsDevPricing.swift。緩存文件的版本號與 TTL 定義在ModelsDevCache中artifactVersion 1、ttlSeconds 24 * 60 * 60緩存文件路徑由cacheFileURL拼裝為Caches/CodexBar/model-pricing/models-dev-v版本.json見 ModelsDevPricing.swift。緩存內(nèi)容是一個帶版本號和抓取時間戳的歸檔ModelsDevCacheArtifact結(jié)構(gòu)體還保留了fetchedAt供判斷過期。雙入口同步 lookup 與異步 refresh管道對外暴露兩個互補的入口見 ModelsDevPricing.swiftModelsDevPricingPipeline.lookup(providerID:modelID:)同步讀取最近一次有效的緩存歸檔并返回價格查詢結(jié)果供掃描器在遍歷每一條 usage 記錄時零延遲調(diào)用不會觸發(fā)網(wǎng)絡(luò)請求。ModelsDevPricingPipeline.refreshIfNeeded(now:cacheRoot:client:)異步檢查緩存是否過期過期才發(fā)起拉取用于后臺維護(hù)新鮮度。此外還有一個面向「未知模型」的入口refreshForUnknownModelsIfNeeded(providerID:modelIDs:)當(dāng)某條記錄的模型 ID 在現(xiàn)有目錄中查不到價格時若距上次抓取已超過 15 分鐘冷卻期modelsDevCatalogRetryInterval 15 * 60則觸發(fā)一次刷新并返回pricingAvailable/unavailable表示新價格是否因此可用。ModelsDevRefreshCoordinatoractor 會按緩存路徑合并并發(fā)請求同一路徑上的并發(fā)刷新共享同一個 in-flight Task避免 TTL 刷新與未知模型刷新重復(fù)下載失敗后 15 分鐘內(nèi)也不會重試見 ModelsDevPricing.swift。原子寫入與內(nèi)存 memo 失效文檔強調(diào)兩處實現(xiàn)細(xì)節(jié)源碼均有一一對應(yīng)原子寫入ModelsDevCache.save使用data.write(to: url, options: [.atomic])落盤見 ModelsDevPricing.swift。因此 macOS 與 Linux 上刷新已有緩存時是「先完整寫入新文件再替換」不會先刪除目標(biāo)文件中途斷電或進(jìn)程被殺也不會留下半截 JSON。內(nèi)存 memo 失效解碼 ~800KB 目錄 JSON 代價很高如果每條 usage 行都重新讀取并解碼會拖慢掃描。ModelsDevCacheMemo以「文件路徑 mtime 文件大小」為鍵緩存完整的加載結(jié)果包括成功與失敗兩類結(jié)果避免損壞緩存反復(fù)觸發(fā)昂貴的解碼save成功后主動invalidate(path:)下一次load必然解碼新文件見 ModelsDevPricing.swift。刷新時的數(shù)據(jù)保全策略拉取到的新目錄并不會無條件替換舊緩存ModelsDevPricingPipeline.performRefresh有三層保護(hù)見 ModelsDevPricing.swift合理性校驗isPlausibleRefresh要求新目錄中anthropic與openai兩個 provider 至少各存在一個有價格isPriceable的模型直接拒絕空響應(yīng)或殘缺響應(yīng)見 ModelsDevPricing.swift。兜底合并mergingFallbackPricingmodels.dev 目錄會隨上游變動增刪模型。刷新時若發(fā)現(xiàn)舊緩存中有價格、而新目錄中已消失的模型會以codexbar-fallback:前綴的鍵合并進(jìn)新目錄保證歷史模型價格不因上游刪檔而「失憶」見 ModelsDevPricing.swift。失敗保底refreshStaleCache在刷新生效前先復(fù)查一次緩存是否已被其他并發(fā)刷新更新刷新失敗時返回false舊的 last-valid 緩存依舊可讀。測試ModelsDevPricingTests中network failure preserves last valid cache、refresh preserves cache when fetched catalog drops cached provider、refresh accepts model churn and preserves removed pricing as fallback等用例直接驗證了上述行為見 ModelsDevPricingTests.swift。查詢規(guī)則以 provider id model id 雙維度精確匹配定價查詢始終以provider id 與 model id 組成的二元組為作用域防止兩個 provider 下同名 model 或同名顯示名互相串價。ModelsDevCatalog.pricing(providerID:modelID:)先把 provider id 歸一化去空白、轉(zhuǎn)小寫見ModelsDevProvider.normalizeProviderID再在對應(yīng) provider 的模型字典內(nèi)查找查找時會對模型 ID 生成候選序列如去掉openai/前綴、把claude-xxx補成claude-xxxdefault、剝離日期快照后綴-20251001等見ModelsDevModelIDNormalizer.candidates依次精確比對字典鍵或模型自身normalizedID見 ModelsDevPricing.swift。測試does not fall back across providers專門驗證了隔離性openai下查claude-sonnet-4-6與anthropic下查gpt-4o-mini均返回nil見 ModelsDevPricingTests.swift。Codex/OpenAI 側(cè)的路由規(guī)則對于本地 Codex 會話掃描codexModelsDevPricingTargets(for:)負(fù)責(zé)把原始模型 ID 展開成候選(providerID, modelID)列表見 CostUsagePricing.swift裸的 Codex/OpenAI 模型 ID一律掛到 provider idopenai常量codexModelsDevProviderID見 CostUsagePricing.swift并順帶嘗試normalizeCodexModel后的規(guī)范化寫法例如gpt-5.6規(guī)范化為gpt-5.6-sol、gpt-reserve映射為 Luna見 CostUsagePricing.swift。帶前綴的 provider 限定路由只有當(dāng)路由前綴落在codexModelsDevProviderIDs白名單deepseek、kimi-coding、kimi-for-coding、openai、opencode、opencode-free、opencode-go見 CostUsagePricing.swift內(nèi)才保留原路由例如deepseek/deepseek-chat仍按deepseek計kimi-coding會同時嘗試kimi-for-codingopencode-free會同時嘗試opencode。未知前綴不計價前綴不在白名單內(nèi)的帶路由 ID 返回空列表保持 unpriced絕不誤并入 OpenAI 價格。Claude 側(cè)的一手廠商路由Claude 會話日志里的模型 ID 走的是另一套「一手廠商」路由claudeModelsDevPricingTargets/claudeModelsDevLookup見 CostUsagePricing.swift可辨識的裸 Claude 會話模型族按前綴歸屬一手廠商目錄claude-前綴歸anthropicgpt-/o1/o3/o4等歸openaigemini-/gemma-等歸googlek3/k3[1m]歸kimi-for-codingkimi-/moonshot-歸moonshot含kimi-for-codingminimax-歸minimaxdeepseek-歸deepseek見 CostUsagePricing.swift。其他裸 ID 要求唯一命中無法辨識歸屬的裸 Claude-session ID會在全部一手廠商anthropic、openai、google、moonshot、kimi-for-coding、minimax、deepseek見 CostUsagePricing.swift中查找只有當(dāng)恰好一個廠商命中時才計價跨廠商歧義命中保持 unpriced見 CostUsagePricing.swift。顯式路由不回落帶顯式provider/model前綴的 Claude-session ID 只在該批準(zhǔn)的顯式路由上計價絕不回落到其他廠商。Kimi 的 k3[1m] 上下文別名Claude 會話中常見的k3[1m]是 Kimi Code 文檔化的「1M 上下文」別名。CodexBar 在kimi-for-coding路由下完成精確行查找之后額外把k3[1m]追加解析為kimi-for-coding/k3見 CostUsagePricing.swift。注意細(xì)節(jié)記錄中的模型名k3[1m]保持不變不會被改寫只是價格解析落到k3行其他上下文變體與付費 Moonshot 路由不會被推斷目錄中k3的零費率只是「已知的估計值」并不代表訂閱或額外用量免費——這是文檔特意強調(diào)的語義邊界。Vertex AI 上的 Claude 日志當(dāng) Claude 會話來自 Google Vertex AI 時對應(yīng)的 models.dev provider id 為google-vertex-anthropic。測試supports provider scoped model normalization驗證了google-vertex-anthropic/claude-sonnet-4-6與anthropic/claude-sonnet-4-6能各自命中正確的價格見 ModelsDevPricingTests.swift。計價單位從「每百萬 token」換算到「每 token」models.dev 對外發(fā)布的價格單位是USD per 1M tokens而 CodexBar 內(nèi)部成本數(shù)學(xué)使用USD per token換算在元數(shù)據(jù)層完成perToken modelsDevCost / 1_000_000源碼中ModelsDevModel.pricing(providerID:providerName:)即執(zhí)行該換算input / unit、output / unit其中unit 1_000_000.0緩存讀cacheRead→cacheReadInputCostPerToken與緩存寫cacheWrite→cacheCreationInputCostPerToken同樣按此規(guī)則換算見 ModelsDevPricing.swift。超 200K 上下文價格帶當(dāng) models.dev 包含cost.context_over_200k字段時CodexBar 將其解析為「超過 200K token 之后」的價格帶并同樣按 per-1M 規(guī)則換算。換算后的結(jié)構(gòu)中thresholdTokens被置為200_000并填充inputCostPerTokenAboveThreshold、outputCostPerTokenAboveThreshold、cacheReadInputCostPerTokenAboveThreshold、cacheCreationInputCostPerTokenAboveThreshold四個超閾值字段見 ModelsDevPricing.swift。單位換算有測試覆蓋converts models dev per million token prices to per token prices斷言 3/1M、15/1M、0.3/1M、3.75/1M 等原始值換算后的 per-token 結(jié)果并驗證thresholdTokens 200_000及超閾值字段見 ModelsDevPricingTests.swift。在成本計算階段超閾值價格帶會被真正使用codexCostUSD依據(jù)thresholdTokens判斷整次請求是否進(jìn)入長上下文計費claudeCostUSD則以input cacheRead cacheCreationTotal是否超過閾值來切換價格帶見 CostUsagePricing.swift。值得注意的是 Codex 側(cè)還有一個codexPriorityInputTokenLimit 272_000的優(yōu)先級輸入上限見 CostUsagePricing.swift與 models.dev 的 200K 閾值是兩套獨立機制。自定義定價覆蓋層custom-pricing.json文件位置與平臺差異精確匹配的「標(biāo)價覆蓋」存放在平臺 Application Support 目錄macOS: ~/Library/Application Support/CodexBar/custom-pricing.json Linux: ${XDG_DATA_HOME:-~/.local/share}/CodexBar/custom-pricing.jsonLinux CLI 走的是FileManager的 Application Support 目錄即 XDG data home而不是~/.config。只把文件放到 XDG config 下會被忽略。源碼中CostUsageCustomPricing.defaultFileURL正是通過AppGroupSupport.localFallbackDirectory定位該目錄并拼接固定文件名custom-pricing.json見 CostUsageCustomPricing.swift。解析順序與作用范圍文件內(nèi)的值一律是USD per 1M tokens。對原生 Codex 會話掃描解析順序為overlay覆蓋層 models.dev builtin內(nèi)置表。測試codex cost prefers overlay over bundled list prices與aggregate fallback consults the overlay before bundled rates直接驗證了覆蓋層優(yōu)先于內(nèi)置表見 CostUsageCustomPricingTests.swift。改文件即失效文件內(nèi)容以 SHA-256 生成fingerprint見 CostUsageCustomPricing.swift該指紋被拼入CostUsagePricingKey.codex(...)的定價鍵見 CostUsagePricingKey.swift。因此任何一次編輯保存都會使 Codex 定價指紋失效下一次原生 Codex 掃描會重新加載費率。測試overlay fingerprint invalidates the Codex pricing key驗證了這一點見 CostUsageCustomPricingTests.swift。作用范圍限制重要覆蓋層目前只作用于原生 Codex/OpenAI 兼容會話的計價。Claude 的本地掃描器、Cursor 以及生產(chǎn)環(huán)境的 OpenCodex 快照加載都不讀取該文件OpenCodex 側(cè)始終持有空覆蓋層。因此寫入anthropic/claude-…這樣的鍵不會改變?nèi)魏?Claude 標(biāo)價。鍵的規(guī)范與完整 JSON 示例鍵大小寫不敏感統(tǒng)一 trim 小寫歸一化見CostUsageCustomPricing.normalizeKey。鍵可以是裸模型 IDgpt-5.4也可以是provider/modelopenai/gpt-5.4。只有精確歸一化后的鍵能匹配不存在前綴或家族通配。同一模型兩種寫法并存時裸鍵優(yōu)先provider 限定行被忽略。除非你就是想讓裸鍵覆蓋生效否則不要同時定義兩行。{ gpt-5.4: { input: 1.25, output: 10, cacheRead: 0.125, cacheWrite: 1.25 }, openai/gpt-5.4-mini: { input: 0, output: 0 } }查詢時先查裸鍵、再查provider/model復(fù)合鍵的順序在rates(providerID:model:)中實現(xiàn)見 CostUsageCustomPricing.swift。字段規(guī)則0表示該 token 類別免費不是未知。測試overlay exact match uses per-million rates and treats zero as free驗證了輸入 0 費率參與求和時按 0 計算見 CostUsageCustomPricingTests.swift。缺字段保持未知CodexBar 不會用 models.dev 或內(nèi)置表去填補缺失字段。因此一個只寫了input的局部覆蓋行整體是「未定價」而不是「覆蓋層與目錄混合價」。測試missing overlay fields stay unknown instead of falling through與matching partial overlay stays unknown instead of using bundled list prices雙雙驗證見 CostUsageCustomPricingTests.swift。負(fù)數(shù)與非有限數(shù)被忽略rate(_:)只接受有限且 0的數(shù)字0是合法免費值見 CostUsageCustomPricing.swift。緩存字段接受替代拼寫cache_read、cache_write、cacheCreation、cache_creation見 CostUsageCustomPricing.swift。測試隔離測試進(jìn)程通過XCTestConfigurationFilePath、.xctest后綴等環(huán)境/進(jìn)程特征識別永遠(yuǎn)不讀開發(fā)者 Application Support 目錄中的真實覆蓋文件load直接返回空覆蓋層測試只使用 fixtures 或空覆蓋層見 CostUsageCustomPricing.swift。測試保障行為可驗證定價管道的行為在倉庫中有系統(tǒng)性測試覆蓋是排查問題時的第一手參照ModelsDevPricingTests.swift覆蓋 models.dev 子集解析、按 provider/model 查詢、跨 provider 不回落、per-1M 到 per-token 換算、過期緩存仍可讀、網(wǎng)絡(luò)失敗保底、部分目錄不覆蓋、未知模型刷新與冷卻、TTL 與未知模型刷新合并單次下載等。CostUsageCustomPricingTests.swift覆蓋零費率、缺字段保持未知、覆蓋層優(yōu)先于內(nèi)置表、指紋失效定價鍵、聚合路徑同樣優(yōu)先覆蓋層等。這兩份測試文件完整刻畫了本文所述每一條規(guī)則的預(yù)期行為無論是自行接入該管道還是排查「為什么這個模型沒有價格」都可以從中找到對應(yīng)斷言。結(jié)語三層價格體系的協(xié)作方式至此可以完整概括 CodexBar 的定價元數(shù)據(jù)體系custom-pricing 覆蓋層用戶精確覆蓋→ models.dev 目錄在線增量、24h TTL 緩存、失敗保底、合并兜底→ 內(nèi)置價格表離線最后防線。三層之間通過 provider id model id 精確作用域隔離通過 SHA-256 指紋串聯(lián)緩存失效通過單元測試鎖定每一條規(guī)則。理解這套管道后無論是調(diào)試「某模型價格不更新」、排查「為什么某條記錄未定價」還是為自己的私有模型添加本地標(biāo)價都能快速定位到對應(yīng)的源碼位置與測試用例。【免費下載鏈接】CodexBarShow usage stats for OpenAI Codex and Claude Code, without having to login.項目地址: https://gitcode.com/GitHub_Trending/co/CodexBar創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考