VIDRAFT 如何在 Gemma-4 上達到 510.58 TPS

Back
Category : News



VIDRAFT 如何在 Gemma-4 上達到 510.58 TPS:「The First Gemma Challenge」冠軍深度解析

TL;DR: VIDRAFT 在「The First Gemma Challenge」排行榜上以單一 NVIDIA A10G GPU 在 google/gemma-4-E4B-it 模型上取得經驗證的 510.58 tokens-per-second (TPS) 成績,同時擊敗了一個原始速度更快但未通過品質門檻的競爭對手。本文剖析使其成功的公開設定選擇,以及工程師們能在自己的推論調校工作中借鏡的技巧。




這是什麼

「The First Gemma Challenge」是一場受嚴格限制的推論速度競賽,有兩項硬性規則:固定使用單一 GPU(NVIDIA A10G)與固定模型(google/gemma-4-E4B-it)。參賽者無法更換更強的硬體或更輕量的模型,唯一能操作的槓桿就是軟體層級的最佳化

評分指標為TPS(Tokens Per Second,每秒生成 token 數),但同時設有Perplexity(PPL)預算——PPL 超過約 2.42 的提交將被取消資格,無論速度多快。主辦單位還針對參賽者從未見過的保留提示集進行盲測重新評估,這意味著任何過度擬合自報基準的設定都會被抓出來。

VIDRAFT 的優勝提交——設定名稱為 vidraft-fw188-ctk49-n64-patchbridge-v1——的成績如下:

  • TPS: 510.58
  • PPL: 2.3930
  • 狀態: 通過盲測重新評估 ✅

另一個競爭提交雖然錄得 535.91 TPS,但其 PPL 約為 2.44,超過品質門檻。因此這個較低的原始數值被認定為經驗證的 SOTA。




運作原理

優勝設定的公開 manifest.json 揭示了三個概念性的最佳化支柱:



1. 滑動視窗注意力壓縮(SLIDING_WINDOW=188

KV-cache 記憶體頻寬是自迴歸生成過程中的主要瓶頸。將注意力視窗限制在最近的 token 上能減輕這項壓力並提升吞吐量——但視窗縮得太小就會喪失上下文,導致 PPL 急遽上升。188 這個數值顯然不是整數,這強烈暗示它是透過實證調整而非直接採用預設值。團隊透過 HF_OVERRIDES 覆寫了模型的 text_config.sliding_window,並啟用 Flash Attention 滑動功能(FA_SLIDING=1)來配合。



2. 質心 Top-k 核心調校(CENTROID_TOP_K=49

此參數更接近核心層級,會同時影響吞吐量與 PPL。根據原始碼分析,團隊依序測試了 44、48、49 等數值——目標是找出在 PPL 仍在預算內的前提下所能使用的最大值。越大並不一定越好,這是在品質限制下的 Pareto 搜尋。



3. 暖機紀律——將初始化過程排除在測量視窗之外

該設定使用了:WARMUP_BRIDGE=1WARMUP_NUM_PROMPTS=64WARMUP_MAX_TOKENS=1WARMUP_SEED=42。這會在計時基準測試開始前先執行 64 個單一 token 的虛擬提示,讓 CUDA graph capture 與 JIT 編譯的成本在計時開始前就被吸收。原始文章指出這個暖機步驟大約貢獻了 15 TPS——在一個以數十 TPS 決勝負的競賽中,這是相當可觀的差距。

同樣重要的是:PRECACHE_BENCH=0 被明確設定,停用了會讓自報 TPS 虛增的旗標。團隊選擇測量盲測評估器實際會看到的真實表現。



其他值得注意的參數(已公開)

  • 推測解碼: 透過 SPECULATIVE_CONFIG 啟用,設定 num_speculative_tokens=7method=mtp——這是一種先草稿再驗證的方法,能增加每次正向傳遞所生成的 token 數
  • MAX_MODEL_LEN=4096
  • GPU_MEMORY_UTILIZATION=0.90
  • MAX_NUM_BATCHED_TOKENS=512
  • MAX_NUM_SEQS=1



基準測試與結果

提交 TPS PPL 盲測
VIDRAFT(vidraft-fw188-ctk49-n64-patchbridge-v1 510.58 2.3930 ✅ 通過
競爭提交 535.91 ~2.44 ❌ 未通過(PPL > 2.42)

最重要的啟示:原始吞吐量排名與驗證後排名出現分歧,因為品質門檻是根據保留提示分佈來執行的,而非參賽者自己的測試集。




如何嘗試

競賽中所使用的模型已由 Google 在 Hugging Face 公開提供:

huggingface-cli download google/gemma-4-E4B-it

Enter fullscreen mode

Exit fullscreen mode

特定的 VIDRAFT 設定(vidraft-fw188-ctk49-n64-patchbridge-v1)以及任何 VIDRAFT 專屬工具在本文撰寫時尚未確認已公開釋出。請查看 VIDRAFT 的 Hugging Face 組織 與他們的 GitHub 以取得最新資訊。如果開放取得管道,會優先在那裡公布。




常見問題

Q:在「速度」競賽中,為什麼 PPL 門檻比原始 TPS 更重要?
A:因為沒有品質底線的 TPS 很容易被操縱——你可以讓模型輸出垃圾內容來快速生成。PPL 上限加上盲測重新評估,共同確保速度數字反映的是真實、可部署的推論品質。

Q:我能將這些技術應用在其他模型或 GPU 上嗎?
A:概念——品質門控的參數搜尋、暖機分離、滑動視窗調校、推測解碼——都是通用的推論工程實務。特定數值(SLIDING_WINDOW=188CENTROID_TOP_K=49 等)是針對單一 A10G 上的 google/gemma-4-E4B-it 所調校的,應該視為其他硬體或模型設定的起點,而非直接複製貼上的目標。

Q:推測解碼(method=mtp)在這裡的作用是什麼?
A:一個更小、更快的「草稿」模型會先預測主模型接下來的幾個 token。主模型再在單一次正向傳遞中驗證這些預測。如果預測被接受,你就能在每個步驟中實際生成多個 token——在不改變模型權重或降低輸出品質的情況下提升測得的 TPS。


原文由 note(日本)於 2026-08-15 報導 — 原始文章

https://dev.to/ai_openfree_b23025ef075cf/how-vidraft-hit-51058-tps-on-gemma-4-a-deep-dive-into-the-first-gemma-challenge-win-15j6

https://www.worldprogramming.org/posts/how-vidraft-hit-51058-tps-on-gemma-4-a-deep-dive-into-the-first-gemma-challenge-win-z3jp0h


Cover image for repomapper v0.1.0: 任何儲存庫的 AGENTS.md 操作指南

Fenix



repomapper v0.1.0: 任何儲存庫的 AGENTS.md 操作指南

為任何程式碼儲存庫產生一份精簡的操作指南,格式為 AGENTS.md:包含子系統、測試、慣例與歷史陷阱。82 項測試。基於論文 Probe-and-Refine Tuning of Repository Guidance for Coding Agents (2026)



問題所在

程式碼代理需要儲存庫的操作知識,而這些知識並未存在於程式碼中:

  • 哪些檔案存放各個子系統。
  • 如何執行測試套件。
  • 歷史上哪些工作流程曾導致錯誤的修正。
  • 專案的慣例與結構。

人類會維護 AGENTS.md 檔案來提供這些上下文,但手動建立非常耗時且容易過時。



解決方案

RepoMapper 以三個步驟自動化此流程:

  1. 掃描:儲存庫結構、語言、進入點、測試、子系統、依賴與慣例。
  2. 探測:合成任務(import 檢查、語法檢查、測試執行器、設定檔驗證)。
  3. 產生:以 AGENTS.md 格式輸出精簡的操作指南(<3000 字元)。



基本用法

git clone https://github.com/amurlaniakea/repomapper.git
cd repomapper
python3 -m venv venv && source venv/bin/activate && pip install -e .

# 為某個儲存庫產生 AGENTS.md
python3 -m repomapper /path/to/repo

Enter fullscreen mode

Exit fullscreen mode



相關連結

你的代理每次遇到新儲存庫時,要花多少時間學習那些早已被寫好的知識?

https://dev.to/magopredator/repomapper-v010-guia-operativa-agentsmd-para-cualquier-repositorio-d09

https://www.worldprogramming.org/posts/repomapper-v010-guia-operativa-agentsmd-para-cualquier-repositorio-qo4hnh

Juan Barriteau

Cipr(Cosmic Index of Public Resources)是一個去中心化、分散式且具抗審查能力的網路索引,由網域擁有者自行掌控自己的條目。

沒有爬蟲決定你是否值得被索引。沒有策展人審核你的提交。沒有中央權威可以將你除名。如果你擁有一個網域,你只需發布一個小型 daemon、加入一筆 DNS TXT 記錄,你的網站就會在幾分鐘內出現在全球索引中。更新條目或永久離開也非常快速且容易。

Cipr 並非傳統意義上的搜尋引擎。它是一個共享的點對點目錄,每位參與者都擁有一份完整副本,並透過病毒式傳播保持同步。搜尋結果依據標準化、可公開稽核的因素(基於擁有者宣告之元資料的 BM25)進行排名,而非不透明的演算法或廣告收益。

審查 Cipr 條目需要 DNS 等級的介入——這與讓一個網域下架所需的基礎設施層級動作相同。沒有中央伺服器可以關閉,沒有 API 金鑰可以撤銷,也沒有服務條款可以違反。

它最適合小型網路:個人部落格、家庭實驗室服務、獨立專案、社群資源——這些主流搜尋引擎越來越常埋沒或完全忽略的網站類型。

Ciprnode zero 是 Cipr 通訊協定的第一個也是參考實作。它完全基於 Deno 建構,沒有任何 runtime npm 依賴。本地索引使用 SQLite 資料庫,搭配外部內容的 FTS5 虛擬表格與 BM25 排名。API 採用嚴格的語義 RESTful 實作,透過 HAL+JSON 完全符合 HATEOAS 規範,並實際使用 QUERY HTTP 方法(draft-ietf-httpbis-safe-method-with-body)。

內建的網頁介面(ciprface)提供搜尋功能,可依語言、地理鄰近度、冒犯程度與時間戳記進行篩選。驗證採用 DNS TXT 三重驗證(透過自訂 TLS 連線使用 3 個隨機 DoH 解析器)與病毒式 P2P 傳播。沒有中央伺服器、沒有區塊鏈、沒有代幣。採用 MIT 授權、可自行架設,能編譯成適用於 Linux、Windows 和 macOS 的獨立執行檔。

更多資訊:https://cipr.info

目前有三個節點正在運行:

https://dev.to/barriteau/cipr-and-ciprnode-zero-1b89

https://www.worldprogramming.org/posts/cipr-and-ciprnode-zero-xozdup


Cover image for Cursor's Origin Platform Launches Amid GitHub Outage

Dave Kurian

一家以 AI 編輯器聞名的公司推出新的程式碼託管平台,這件事本身就值得關注。Cursor 於週一早上開始推出 Origin — 這是一個真正的程式碼託管與協作平台,首先開放給付費的 Cursor 使用者。三個半小時後,GitHub 的狀態頁面變成紅色,持續了六小時四十二分鐘。這兩個事件並不相關。它們出現在同一個新聞週期的事實,最清楚地證明了程式碼存放的位置屬於基礎設施,而基礎設施會發生當機。

這對開發者來說是真正的好消息,而「我該怎麼做」的實用版本就是本文的其餘部分。



1. Origin 是一個真正的 Git 託管平台,不是側邊欄

許多非平台公司所發表的「程式碼託管」公告,最終只是唯讀鏡像或包在他人託管平台外的薄薄一層包裝。Origin 並非如此。Cursor 以版本控制和協作的形式推出它,具備你預期的功能範圍 — 儲存庫、合併請求、權限 — 並且僅限付費 Cursor 方案使用。

有趣的是,一家 AI 編輯器供應商決定要擁有編輯器之下的工作流程層。而不是模型。也不是聊天側邊欄。是儲存庫、差異比對、合併、部署鉤子。Cursor 的賭注是 AI 和託管平台屬於同一個產品表面,如果你用他們的工具寫程式碼,你也會用他們的工具來提交程式碼。

這是一個有意義的賭注,也是那種會在未來一年對 GitHub 的編輯器整合和定價帶來真正壓力的舉動。



2. 六小時四十二分鐘是一段很長的被鎖定時間

GitHub 自己的事件紀錄,如當日事件報導所述,讀起來就像是開發者在週一所需一切的清單:

  • 合併請求、議題和 API 出現接近 20% 的錯誤
  • 封存和原始檔案下載出現接近 50% 的錯誤
  • 企業單一登入在 SAML、OIDC、SCIM 佈建和 Team Sync 上全部失敗
  • Copilot 在整個期間都無法使用

這不是單一服務故障。這是整個循環。你無法合併。你無法開啟 PR。你無法在不重試的情況下 curl 一個發行版本的 tarball。而你在手動復原時通常會依賴的 AI 輔助,也同樣託管在這個正在故障的供應商上。

六小時四十二分鐘是那種會讓人安排平台風險會議的數字。它也是那種不需要經常發生,就能合理化至少平行運行替代方案一週的數字。

SSO 失敗值得單獨提出。對企業團隊來說,「託管平台當機」很煩人;而「我們甚至無法驗證身分來登入託管平台」則是從週一延燒到週二的事件。SAML、OIDC、SCIM、Team Sync — 四個全部失敗。這是整個紀錄中最糟糕的單一類別,因為驗證身分是所有其他功能背後的大門。



3. 這次推出並未造成當機 — 但它改變了人們注意到的焦點

這兩個事件並非協調安排。產品推出通常在數週前就已確定,而 Cursor 的推出中沒有任何跡象顯示他們在等待狀態頁面變紅。但在 GitHub 故障的同一天,一個 GitHub 競爭對手推出自己的託管平台,這種巧合讓原本安靜的付費用戶推出,變成本週最受關注的程式碼託管新聞。

Vercel 的執行長公開表達意見。一位 Cursor 員工發表的言論,根據報導,「自己寫好了標題」。我正在參考的文章中並沒有確切用詞,所以我不會假裝引用它 — 但這種模式很熟悉:當一個供應商跌倒時,競爭對手的推出就獲得了不用付費的觀眾。

教訓不是「切換託管平台」。教訓是「停止假裝你不能這麼做」。



4. 如何在今天實際試用 Origin

這次推出僅限 Cursor 的付費方案。我正在參考的文章並未列出公開註冊網址或定價頁面,因此以下具體描述的是工作流程的樣貌,而非可複製貼上的步驟 — 當你建立儲存庫時,Cursor 會提供實際的遠端 URL。

# 1. 確認你的 Cursor 編輯器處於付費方案。
#    Origin 僅在付費 Cursor 方案中提供,不包含免費方案。

# 2. 開啟 Cursor 的工作區並找到 Origin 的入口 —
#    一個新的儀表板或側邊欄項目,用來存放儲存庫。

# 3. 在 Origin 上建立你的第一個儲存庫。一旦 Origin 提供
#    遠端 URL,就從你的本機檢出推送:
git remote add origin <the-url-origin-gives-you>
git push -u origin main

# 4. 如果你想在接下來的四分之一時間同時運行兩者,
#    而不是直接遷移,可以鏡像你現有的 GitHub 儲存庫:
git clone --bare [email protected]:your-org/your-repo.git
cd your-repo.git
git push --mirror <the-url-origin-gives-you>

Enter fullscreen mode

Exit fullscreen mode

一些實用注意事項:

  • 把第一週當作雙重寫入,而不是遷移。同時推送到兩邊,在各自開啟幾個 PR,看看審核、CI 和權限在實際負載下的表現。
  • Cursor 在推出時強調的功能是版本控制和協作 — 這是任何託管平台的基礎。值得你自己回答的問題是,編輯器到託管平台的循環是否真的比目前的 GitHub-Cursor 循環更緊密。
  • 如果你使用的是企業方案,並且在 GitHub 上綁定 SAML SSO,請先在沙盒組織中測試 Origin 的驗證機制,再將任何真實工作負載託付給它。GitHub 當機最糟糕的時刻就是 SSO 失敗;不要註冊一個你尚未驗證的單一故障點。

目前還沒有 Origin 與 GitHub 之間在延遲、可靠性和託管成本方面的公開基準測試。Cursor 尚未公布數據,而我在此寫下的任何具體數字都將是捏造的。這才是接下來 90 天真正值得觀察的事情。



5. 當程式碼底下的託管平台改變時,什麼是持久不變的

以下是當 Cursor 推出 Origin、GitHub 推出新的定價方案,或下一次當機讓大家尋找備份時,不會改變的部分:你的使用者所接觸的 UI。那些在 iOS、Android 和網頁上渲染的元件。你畫面所呼叫的 API。你在上一個版本中交付的視覺合約。

[[DIAGRAM: model provider → editor → code host (GitHub or Origin) → repo → UI component → web + iOS + Android]]

程式碼託管平台是堆疊中的一層。編輯器也是。模型供應商也是。它們都不是你的客戶所互動的那一層。那是元件層 — 也是系統中設計不應該取決於提交內容存放在哪裡的唯一部分。

這就是 OTF 所支撐的建構部分。當你的儲存庫今天在 GitHub 而明天在 Origin — 或在你做決定的這一季同時使用兩者 — 同樣的 ButtonDialogSheet 在網頁和原生平台上不需要知道這些變化。一個元件、一個 API,網頁 + iOS + Android,所有三者行為和樣式完全相同。交換底下的託管平台,上面的畫面不會有任何變化。

在這裡慣例勝過設定。選擇在供應商更迭中保持穩定的那一層,盡可能將你的建構內容推送到該層,那麼下一次當機就只是週一早上的不便,而不是週一下午的重建。



6. 接下來 90 天值得關注什麼

新的託管平台意味著在定價、可靠度 SLA,以及編輯器與託管平台整合緊密程度上帶來新的競爭壓力。這對開發者來說是好事 — 每一個在這些面向推動 GitHub 的公告,都是對所有正在交付程式碼的人的助力。

有四件事值得追蹤:

  1. Origin 的公開可靠度和延遲數據。 在 Cursor 公布基準測試之前,「Origin 是否和 GitHub 一樣快」是無法回答的。
  2. 定價方案和免費與付費的分界線。 Origin 是否提供有意義的免費方案,將決定它是否真的能將開發者從 GitHub 拉走,還是只能與之共存。
  3. 編輯器到託管平台的整合。 如果 Cursor 編輯器與 Origin 的循環明顯比與 GitHub 更緊密,那就是這個功能不再只是功能,而是開始成為護城河的時刻。
  4. 其他 AI 程式碼供應商是否會推出自己的託管平台。 如果 Origin 獲得採用,預計下一個主要的 AI 工具也會跟進。

在這一切之中持久不變的部分:能夠在交換中存活下來的跨平台 UI 層。當 Origin 獲得真正採用,或當下一個託管平台在之後獲得採用時,不需要改變的工作就是能夠複利的部分。一個程式碼庫,網頁和原生平台,每個介面上都是相同的元件。一次建置,下一次當機就只是週二早上的故事。

https://dev.to/davekurian/cursors-origin-platform-launches-amid-github-outage-4854

https://www.worldprogramming.org/posts/cursors-origin-platform-launches-amid-github-outage-yyoqu7

Marco



將 CI/CD 視為控制系統:從提交熵到生產證據

CI/CD 常被簡化為自動化,但其更深層的目的在於認知:它將不確定的變更轉化為系統是否仍可安全運作的證據。管線就是一個回饋控制器。原始碼變更是干擾;測試、政策檢查與遙測是感測器;部署策略是執行器;服務等級目標則定義了可接受的運作範圍。



控制迴路

持續整合透過保持變更集小巧並反覆測試其組成,來降低整合熵。持續交付則維持可部署的狀態;持續部署則在政策閘道成功後自動推進變更。這些是不同的成熟度等級,將它們混為一談會產生不安全的期望。

一個可防禦的管線評估的不只是功能正確性:

  1. 來源: 每個成品是否都能追溯到已審核的原始碼與可重現的建置?
  2. 安全性: 是否已評估依賴項目、秘密、權限與成品簽章?
  3. 可運作性: 在推進前是否已有延遲、飽和度、錯誤率與回滾訊號?
  4. 變更風險: 推出範圍是否與不確定性成正比?
promote:
  needs: [unit, integration, policy, sbom]
  environment: production
  steps:
    - run: cosign verify --key cosign.pub artifact.example/app:$GIT_SHA
    - run: deploy --strategy=canary --initial-traffic=1%
    - run: verify-slo --window=15m --max-error-budget-burn=2

進入全螢幕模式

離開全螢幕模式



為什麼小批次佔優勢

如果每個變更的元件都有某種獨立的機率會引入缺陷,那麼較大的批次會同時增加失敗機率與診斷搜尋空間。獨立性是一個不完美的假設——軟體依賴關係是相關聯的——但結論仍然成立:小批次能縮短回饋延遲並改善因果歸因。因此,部署頻率只有在搭配快速復原與可信賴的驗證時才有價值。



失敗模式

管線成功並非生產安全的證明。測試可能編碼了不完整的規格;預發佈流量很少與正式環境匹配;可變動的標籤可能切斷來源追溯;而核准閘道可能淪為形式主義。一個成熟的設計會將每個閘道視為可否證的主張,並持續衡量其預測能力。例如, flaky 測試並非無害的雜訊:它們削弱了綠色建置的統計意義,並訓練操作人員忽略警報。



關鍵要點

  • CI/CD 是一個社會技術回饋系統,而不僅僅是一堆腳本的集合。
  • 最佳化證據品質、小批次大小、有界爆炸半徑以及可逆變更。
  • 綠色管線是一種風險估計;生產遙測必須閉合控制迴路。
  • 除了變更失敗率與復原時間外,還要衡量前置時間與部署頻率。

https://dev.to/marco13moo/daily-dose-of-devops-what-is-cicd-and-why-it-matters-3ohj

https://www.worldprogramming.org/posts/daily-dose-of-devops-what-is-cicd-and-why-it-matters-ktxq4v



如果你的 AI 助理能在你睡覺時真正「做事」呢?

劇透:它可以。而這就叫做 AI 代理人。以下是如何在 10 分鐘內打造一個。


你用過 ChatGPT。你驚嘆於它的回答。你也曾在某個時刻,把它的輸出複製貼上到試算表裡,自己發送電子郵件,然後心想——「為什麼我還在做這些無聊的部分?」

那不是 AI 助理。那只是一個非常聰明的自動完成工具。

AI 代理人則不一樣。代理人不只是「回答」——它會「行動」。它會閱讀你的收件匣、總結重要內容、草擬回覆、安排後續追蹤,然後在你睡前就先去休息。你醒來時,事情已經完成了。

這聽起來像科幻小說,但現在它只是週末專案的程度。讓我來詳細示範它是如何運作的。




那個改變一切的關鍵:工具

任何代理人中最神奇的成分並不是語言模型——那些現在到處都是。而是工具使用

可以這樣想:單獨的 GPT-4 就像一位才華洋溢的顧問,被鎖在一個沒有電話、沒有筆電、沒有門的房間裡。它可以「思考」得很漂亮,但無法接觸世界。給它工具——網頁瀏覽器、計算機、API 金鑰——它就突然能伸出手、做事,並回報結果。

以下是用 Python 搭配 OpenAI 函式呼叫 API 實現的最簡代理人迴圈版本:

import openai
import json

def get_weather(city: str) -> str:
    # In real life, call a weather API here
    return f"It's 22°C and sunny in {city}."

tools = [{
    "type": "function",
    "function": {
        "name": "get_weather",
        "description": "Get current weather for a city",
        "parameters": {
            "type": "object",
            "properties": {
                "city": {"type": "string", "description": "City name"}
            },
            "required": ["city"]
        }
    }
}]

messages = [{"role": "user", "content": "What's the weather in Tokyo?"}]

response = openai.chat.completions.create(
    model="gpt-4o",
    messages=messages,
    tools=tools
)

# If the model wants to call a tool, handle it
if response.choices[0].finish_reason == "tool_calls":
    tool_call = response.choices[0].message.tool_calls[0]
    args = json.loads(tool_call.function.arguments)
    result = get_weather(**args)
    print(f"Tool result: {result}")

Enter fullscreen mode

Exit fullscreen mode

執行它。觀察模型「決定」呼叫 get_weather,自己提取城市名稱,並使用結果。這個決定與行動的迴圈,就是每個 AI 代理人的心跳。




為什麼這其實是一件大事

傳統軟體遵循腳本。你寫下 if X then do Y。每個分支都是你預先預測好的。

代理人則遵循「目標」,而非腳本。你說「清空我的收件匣」,它就會自己想出步驟。它閱讀郵件、分類它們、決定哪些需要回覆、草擬回覆,並將邊緣案例標記給你。你並沒有指定任何這些細節——它是靠推理自己走到那一步的。

這種從腳本式轉向目標導向的轉變,就如同我們從手寫網站程式碼轉向使用框架一樣。它不會取代工程師,而是提高了單一個人能打造的上限。




每個代理人都具備的三個組成部分

無論你是使用 LangChain、AutoGen、CrewAI,還是自己從頭打造,每個代理人都有相同的三個部分:

1. 大腦(LLM)——根據其目標和目前已知資訊,決定下一步要做什麼。

2. 記憶體——追蹤發生過的事情。短期記憶是對話歷史。長期記憶則是向量資料庫或代理人會讀寫的檔案。沒有記憶體,你的代理人注意力持續時間就像金魚一樣。雖然是一隻有博士學位的金魚,但還是金魚。

3. 工具——就是它的手。API、檔案讀取器、網頁擷取器、計算機、程式碼執行器。工具越多,代理人能觸及的範圍就越大。

拿掉其中任何一項,你就沒有代理人——你只擁有一個有野心的聊天機器人。




這個週末你可以打造什麼

以下是三個真正可行的週末專案,按照野心程度排序:

  • 收件匣總結器——連接 Gmail,閱讀未讀郵件,按主題分組,並將 bullet point 簡報丟到 Slack 私人訊息中。大約 100 行 Python + LangChain。
  • 研究代理人——給它一個主題,它會搜尋網路、閱讀 5 篇文章、比較它們,並寫出一頁附有引用的摘要。不用再花 45 分鐘掉進兔子洞裡。
  • 開發助理——監視 GitHub 儲存庫的新 Issue,將它們分類(bug/功能/問題)、草擬分類回應,並通知正確的團隊成員。在忙碌的儲存庫中,每天約可節省 30 分鐘。

這些都不需要博士學位。它們只需要一個 API 金鑰、幾個小時,以及願意讓機器處理無聊部分的心態。




真正的問題

問題不再是「AI 代理人能不能做到這件事?」那艘船早就開走了。

真正的問題是:你一天中還有哪一部分是自己手動在做,而代理人可以接手負責的?

挑選你待辦事項中最繁瑣的那件事——你害怕的 recurring 任務、吃掉 20 分鐘的複製貼上工作、沒人真正閱讀但大家都要求的報告。那就是你的第一個代理人。

打造那一個。你從一個小型可運作的範例中,對代理式 AI 的理解,會比閱讀網路上每一篇解釋文章都還要深刻。

包括這一篇,也有可能。


正在用代理人打造東西嗎?在留言區分享吧——我很想看看大家正在做什麼。

https://dev.to/aninmukhe/what-if-your-ai-assistant-could-actually-do-things-while-you-sleep-2fc9

https://www.worldprogramming.org/posts/what-if-your-ai-assistant-could-actually-do-things-while-you-sleep-4p3o3r

每個政府資助計畫都回答相同的五個問題:誰可以申請、金額多少、用途為何、截止日期是什麼,以及如何申請。這種一致性其實是個陷阱。當你試圖以程式方式從數千個來源中萃取這五個答案時,你會發現沒有兩個機構同意該如何表述其中任何一個——而你最不預期會出問題的欄位,也就是截止日期,結果卻是破壞最多事情的那一個。

以下是當你試圖大規模解析時實際看到的樣子。

同一個計畫,五種不同的形式

一個資助機會可能以以下形式出現:

來自機構 API 的結構化 JSON 記錄(很少見,即使有也填充不一致)
州經濟發展網站上的 HTML 表格
掃描的 PDF 資助機會通知(NOFO),資格條件埋在第四段
宣布計畫的新聞稿,連結到另一頁提供實際細節
單頁傳單,將真正規則引用為「見 2 CFR 200」而沒有其他內容

同一個底層計畫——例如 SBIR 第一階段徵求——可能在 SBIR.gov 上是機器可讀的,同時又以該資助機構自己網站上 40 頁的 PDF 形式存在,包含額外、非重複的資格細節,而這些細節在 SBIR.gov 上完全沒有。沒有單一的「標準」版本可以依賴。你需要兩者,並加以調和。

這是核心資料工程問題:你不是在解析一種格式,而是要維護解析器來處理一組開放式、不斷增長、沒有共同規格的格式。

資格條件:拒絕成為欄位的欄位

資格條件是整個資料集中價值最高的欄位——它是相關結果與浪費申請人時間之間的差別——但它也是最不可能以結構化資料形式存在的欄位。

當它被結構化時,你可能會得到類似這樣的內容:

json
{
“eligible_applicant_types”: [“small_business”, “nonprofit”],
“naics_codes”: [“541511”, “541512”]
}

當它不是(大多數情況都是如此)時,你會得到這樣的文字:

“Applications will be accepted from small business concerns as defined in 13 CFR 121.201 that are majority-owned by U.S. citizens or permanent residents, provided the applicant has not received more than one prior Phase II award under this topic in the preceding three fiscal years.”

那句話至少包含四個不同的、可分別檢查的限制條件,透過編號交叉引用外部法規,並使用只有在你已經解析過 13 CFR 121.201 的情況下才能解析成具體規則的措辭(「small business concerns as defined in…」)。要可靠地萃取這類內容,意味著要將用於知名法規用語的規則基礎模式匹配,與用於其他一切的 LLM 輔助萃取結合起來,然後將低信心的萃取標記出來供人工審核,而不是默默猜測。將這當作普通的 NLP 實體萃取任務是低估了它——一半的工作在於知道一句話隱含指向哪些外部法規。

截止日期:小欄位,巨大的失敗成本

在資助記錄的每個欄位中,截止日期如果出錯會造成最大的損害,而且出奇地難以正確取得。有幾個原因:

它們以不相容的格式出現。「Rolling」、「Q3 2026」、「the 15th of each month」、「45 days after LOI acceptance」、「no later than 5:00 PM ET on the due date」,以及純 ISO 日期,都會在不同來源中針對同一類型計畫出現。

它們比你預期的更常是相對而非絕對的。「60 days from opportunity posting」只有在你正確捕捉到張貼日期時才能解析成真實日期——而該日期本身可能已被默默更新。計畫會被修訂,而修訂有時會改變所有下游截止日期,卻沒有明確的變更記錄。

時區和截止時間通常是缺失的。「Due August 15」如果沒有時區,在美國各地會有最多三小時的模糊性,而聯邦截止日期通常被嚴格解釋——因為你推斷的是東部時間而不是入口網站自己的伺服器時間,導致錯過提交入口網站的截止時間幾分鐘,是使用者不會原諒的那種失敗。

過時的重發很常見。一個計畫頁面被重新抓取,文字與去年的週期 99% 相同,但截止日期欄位是唯一改變的那一行。如果你的差異比對邏輯沒有特別針對截止日期進行調整,這正是那種通用「頁面是否改變」檢查可能錯過或誤判的改變類型。

對我們有效的解決方法:將截止日期萃取視為獨立子系統,而不是一般頁面解析的副作用。解析成結構化的 (date, time, timezone, confidence, relative_basis) 元組,總是將原始措辭與解析值一起保留,而且永遠不要在沒有同時顯示原始文字的情況下向使用者呈現標準化日期。當解析信心低時,顯示原始文字而不是猜測的日期——看起來錯誤的猜測比誠實的「無法解析」更糟。

建立標準化層

在實務中表現良好的模式:

特定格式的萃取,而非單一通用解析器。HTML 表格、PDF 和 API 回應需要不同的萃取策略,然後饋入相同的目標架構——不要試圖強迫一個解析器處理所有輸入形狀。
一切都對應到的標準架構。申請人類型、資助金額範圍、產業/NAICS、截止日期(結構化)以及地理位置,無論來源格式為何。
每個欄位的信心分數,而不是每個記錄。一個記錄可能有非常可靠的截止日期和垃圾的資格條件萃取。將它們混合成單一的記錄層級信心分數,會丟棄你需要用來知道該雙重檢查什麼的資訊。
在每個標準化值旁邊保留來源文字。每個結構化欄位都帶有其原始措辭。這同時是你的除錯工具、稽核軌跡,以及信心低時的後備使用者介面。
以針對高價值欄位的差異比對進行重新抓取。將截止日期和資格條件變更視為比頁面外觀變更更高優先的差異,因為這些是最可能默默改變、且錯過時成本最高的欄位。
真正的教訓

人們很容易把截止日期當作已解決的問題——日期就是日期,對吧?實際上,一個截止日期欄位的可信度,只取決於餵給它的最混亂來源,而政府資助資料無非就是混亂的來源。讓「deadline: August 15」可靠地代表申請人需要它代表的意義,需要一個專用的解析子系統,而不是一個 regex 和祈禱。把它當作它所是的重大欄位來對待,因為弄錯它不僅會損壞一筆記錄——它會讓某人失去一個真正的機會。

https://dev.to/fundnai/the-hidden-reason-government-funding-data-is-so-hard-to-trust-4g09

https://www.worldprogramming.org/posts/the-hidden-reason-government-funding-data-is-so-hard-to-trust-ygftu4

Multigrid

壓縮是唯一需要花錢應用的上下文技術,因此也是最需要用算術來合理化的技術。通常有兩種更便宜的方法勝過它,而知道何時它們不適用才是真正的技巧。



先談免費的勝利

在任何基於模型的技術之前,先移除那些不帶資訊的 tokens。這看起來不華麗、是無損的,而且在真實提示詞上通常能省下 30–60%:

  • 去除標記。 提示詞中抓取的 HTML 大多是屬性、導航和腳本標籤。請提取純文字。
  • 壓縮結構化資料。 美化過的 JSON 會為每個空格付費。對於表格資料,CSV 或每欄一個緊湊鍵值的形式,遠比在每一列重複鍵值的物件陣列便宜得多。
  • 去除重複。 使用重疊區塊的檢索會傳回幾乎相同的段落。進行雜湊並丟棄。
  • 丟棄無法被讀取的內容。 Base64 資料塊、長 ID、雜湊、壓縮過的 bundle。它們無法被 tokenizer 進一步壓縮,對模型也沒有用處。
  • 修剪工具描述。 JSON Schema 描述中的每個字都會在迴圈的每次呼叫中被計費。



四種需要成本的類型

類型 描述
抽取式選取 為句子或段落根據與查詢的相關性進行評分,並保留最相關的。交叉編碼器 reranker 是標準工具。成本低,而且輸出是逐字的原始文字,這在答案必須可被引用時非常重要。
抽象式摘要 要求模型將上下文改寫得更短。壓縮率最高,風險也最高:摘要會遺漏具體數字、限定詞和否定詞,而這些常常是最終答案的關鍵。
token 剪枝 使用小型語言模型的 perplexity 作為訊號,刪除個別低資訊量的 token。這方面的已發表研究來自微軟研究院的 LLMLingua 和 LongLLMLingua(Jiang et al., EMNLP 2023 及其後續),在他們的評估任務上報告了高達約 20 倍的壓縮率,且性能損失有限。輸出不是人類可讀的,這對模型來說沒問題,但對記錄來說很麻煩。
改用檢索 根本不是壓縮 — 不要把它放進提示詞。幾乎總是最便宜的選項,也是考慮其他方法前要先排除的。



壓縮必須能回收成本

每種基於模型的技術都會花費 tokens 來節省 tokens。以下是算術,以您應該替換的示意費率為例:

original context T  = 20,000 tok      target model input   $3.00 / M
compressed T'       =  4,000 tok      compressor in/out    $0.15 / $0.60 per M

saving per use    (20,000 - 4,000) / 1e6 * $3.00       = $0.0480
compression cost  20,000/1e6*$0.15 + 4,000/1e6*$0.60   = $0.0054

net per use, if the compressed artefact is reused      = +$0.0426
net on a single use (compress then immediately send)   = +$0.0426 as well

BUT compare against caching the same 20,000 tokens:
  cache read at a 0.1x multiplier: 20,000/1e6 * $0.30  = $0.0060
  compressed prompt, uncompressed rate: 4,000/1e6*$3   = $0.0120

Enter fullscreen mode

Exit fullscreen mode

仔細閱讀最後兩行,因為它們才是真正重要的發現。當上下文是穩定的時,快取既比壓縮便宜,又是無損的 — 沒有理由去壓縮靜態的系統提示詞。壓縮只有在每次請求的上下文都不同、其大小大到無法經濟地快取,或是必須跨沒有共享快取的模型重複使用時,才有其價值。

因此完整的決策順序是:刪除無用的內容、改用檢索而非塞入、快取穩定的部分,然後壓縮剩下的。大多數團隊卻第一個就去抓第四個。

延遲值得在算術中單獨列一行,因為壓縮只是把成本移來移去,而非單純降低。一個壓縮呼叫是一次額外的網路來回和一次額外的生成,都在關鍵路徑上,而且壓縮器必須先讀完整個上下文才能開始輸出。對於互動功能,這很容易增加比縮短提示詞所節省的更多實際時間。因此壓縮最有道理的地方是它可以離線進行 — 在攝取時或按照排程進行 — 而在人類正在等待的請求中間進行是最沒有道理的。



每種方法會破壞什麼

壓縮本質上是有損的;問題在於你能容忍哪種損失。抽取式選取會失去段落之間的連接組織,因此會損害需要跨段落進行綜合的任務。抽象式摘要會失去精確性 — 精確數字、日期、名稱,以及眾所周知的否定詞,因為「該條款不適用於子公司」和「該條款適用於子公司」在嵌入空間中幾乎會被摘要成相鄰的向量。Token 剪枝會失去語法結構,這通常能被模型恢復,但偶爾不行,而且會讓你的提示詞對半夜兩點正在除錯的人類來說無法閱讀。

有一種損失是所有方法都共有的,值得明白指出:壓縮之後你就無法再引用原始來源。如果你的產品會顯示引用,壓縮後的文字必須保留指向原始段落的識別符,否則引用功能會悄悄開始捏造內容。

在長期執行的對話中還有一種複合效應需要注意。壓縮一個已經包含先前壓縮摘要的上下文,就會變成摘要的摘要,而損失不是加成而是相乘 — 具體細節最先消失,然後是限定詞,最後是已確認事實與假設之間的區別。在每個層級都保留指向未壓縮原始內容的指標,並盡可能從原始來源重新壓縮,而不是從先前的壓縮結果壓縮。



防止最壞結果的規則

  • 絕對不要壓縮指令。 系統提示詞和使用者的問題要原封不動。它們很小,而且是規格說明。
  • 絕對不要壓縮結構化數值。 識別符、金額、日期、數量。將它們提取成一個小的逐字區塊,只壓縮它們周圍的散文。
  • 壓縮一次,快取結果。 如果同一份原始文件被重複使用,壓縮後的形式就是一個穩定的成品 — 應該儲存它,而不是每次請求都重新產生。
  • 衡量端到端的結果,而非壓縮率。 以三個答案準確度點為代價換來的 10 倍壓縮率,在幾乎任何價格下都是糟糕的交易,而除非評估是在最終答案上執行,否則你不會看到這一點。
  • 保留未壓縮的路徑。 當答案錯誤時,第一個診斷方法是用完整上下文重新執行。如果這樣就修好了,壓縮就是你的 bug;如果沒有,那它從來就不是問題。

上述損益平衡取決於壓縮器與目標模型之間的價格差距,這是兩個模型的比較而非單一查詢;把小型和大型模型的費率並排比較就足以判斷一個壓縮步驟在你開始建置前是否能回收成本。



相關文章

https://dev.to/multigrid/context-compression-making-100k-tokens-fit-in-10k-4aam

https://www.worldprogramming.org/posts/context-compression-making-100k-tokens-fit-in-10k-flby9g

Multigrid

在原本運作良好的向量查詢中加入 WHERE tenant_id = 42,會發生兩種情況之一:查詢變慢,或是返回的資料列比你要求的還少。這兩種現象背後是相同的事實——近似索引與過濾器無法同時套用——而導致致命問題的選擇性是可以事先計算出來的。



為什麼兩者無法組合

B-tree 索引和 GIN 索引可以結合:Postgres 會從每個索引建立位元圖並進行 AND 運算。HNSW 索引無法參與其中,因為它不會產生一組符合的資料列——它產生的是有序串流,最接近的排在最前面,而這個排序正是它的全部價值。你無法將一個排序與位元圖進行交集運算後還保有排序。

因此規劃器必須做出選擇。它要嘛走訪圖形,之後再捨棄不符合過濾器的資料列(後置過濾),要嘛先找出通過過濾器的資料列,再為它們全部計算距離(前置過濾)。這兩種方式有不同的成本,更重要的是,會產生不同的結果。

Postgres 使用其成本模型在兩者之間選擇,而它對近似最近鄰居掃描的成本模型接近猜測。它沒有描述圖形在找到十個通過你過濾器的資料列之前會檢查多少資料列的統計資訊,因為這個數量取決於你的查詢落在向量空間的哪個位置。因此規劃器使用結構上缺乏資訊的估計值來選擇,有時會選到無法回答你查詢的執行計畫。這是在 Postgres 中唯一一種從應用程式覆寫規劃器是正常行為而非壞味道的情況。



後置過濾器及其運算

這是你對明顯查詢預設會得到的結果:

SELECT id, content
FROM chunks
WHERE tenant_id = 42
ORDER BY embedding <=> $1
LIMIT 10;

Enter fullscreen mode

Exit fullscreen mode

HNSW 掃描會讓 hnsw.ef_search 個候選保持存活,並依距離順序返回它們;過濾器會套用在這個串流上。令 s 為過濾器的選擇性——它通過資料表的分數。如果過濾器與向量空間中的位置無關,預期的倖存者數量為:

survivors ≈ ef_search × s

To get k results:   ef_search ≥ k / s

Assumptions: the filter is uncorrelated with the embedding
distribution; ef_search candidates are the only rows examined;
hnsw.ef_search has a hard maximum of 1000.

Enter fullscreen mode

Exit fullscreen mode

在預設 ef_search = 40 且過濾器通過資料表一半的情況下,你預期有二十個倖存者,而你要求十個。沒問題。在過濾器每千分之一列通過的情況下,你預期有 40 × 0.001 = 0.04 個倖存者,這在實務上代表查詢完全沒有返回任何結果,而索引運作完全符合設計。

在 pgvector 0.8.0 之前,在掃描內沒有補救方法:你只會得到倖存的資料列數量,無聲無息,且不會提示答案不足。0.8.0 加入了疊代掃描,它會使用較大的候選集合重新掃描,直到達到限制或耗盡預算為止:

SET LOCAL hnsw.iterative_scan = strict_order;   -- pgvector 0.8.0+
SET LOCAL hnsw.max_scan_tuples = 20000;        -- the budget it stops at

Enter fullscreen mode

Exit fullscreen mode

strict_order 保證結果會以真正的距離順序返回;relaxed_order 較快,可能會讓結果稍微偏離順序,如果之後無論如何都會執行重新排序器,這通常是可以接受的。兩者都無法消除底層成本——在高度選擇性過濾器上的疊代掃描需要做大量工作才能找到少數幾列。



以數字呈現的懸崖

將公式放入表格中,問題的形狀立刻顯現。對於 k = 10

Filter passes Description
50% of rows ef_search of 20 is enough. The default of 40 has margin. Nothing to do.
10% of rows ef_search ≥ 100. Query cost roughly 2.5× the unfiltered one. Still comfortable.
2% of rows ef_search ≥ 500. Roughly 12× the work of the default, and latency you will notice.
1% of rows ef_search ≥ 1000 — exactly the maximum pgvector allows. You are at the edge with no margin for an unlucky query.
0.1% of rows ef_search would need to be 10,000. Not reachable. The post-filter plan cannot answer this query correctly, at any setting, ever.

這就是懸崖:它不是逐漸退化,而是在頂-10 查詢百分之一選擇性處的硬牆,一般而言位於 s = k / 1000。在它之下,索引不是變慢——而是無能為力,而疊代掃描會把這種無能從錯誤答案轉變成緩慢答案。

該推導中的一個假設值得一提,因為它經常是錯誤的。它假設過濾器與向量位置無關。租戶過濾器通常大致無關。語言、文件類型或日期的過濾器則有強烈相關性——所有德文區塊在嵌入空間中都彼此靠近——這時倖存者要嘛聚集在候選集合中(優於公式),要嘛完全不在其中(糟得多)。公式是正確的規劃工具;你自己的測量才是正確的決策工具。



前置過濾器,以及它何時更快

另一個執行計畫完全忽略向量索引:使用 B-tree 找出符合的資料列,為每個計算距離,排序,取十個。召回率精確為 100%,因為沒有任何近似。

-- Force it, to see what it costs:
SET LOCAL enable_indexscan = off;   -- disables the HNSW ordered scan
SET LOCAL enable_bitmapscan = on;

EXPLAIN (ANALYZE, BUFFERS)
SELECT id FROM chunks WHERE tenant_id = 42
ORDER BY embedding <=> $1 LIMIT 10;

 Limit
   ->  Sort
         Sort Key: ((embedding <=> '[...]'::vector))
         Sort Method: top-N heapsort  Memory: 27kB
         ->  Bitmap Heap Scan on chunks
               Recheck Cond: (tenant_id = 42)
               ->  Bitmap Index Scan on chunks_tenant_idx
                     Index Cond: (tenant_id = 42)

Enter fullscreen mode

Exit fullscreen mode

這個執行計畫的成本是 s × N 次各有 d 個維度的距離計算,加上堆積提取。在 N = 10,000,000s = 0.001d = 1536 時:一萬列、一千五百萬次乘加,個位數毫秒的運算。一萬個分散資料列的堆積提取才是真正的成本,而且在暖機狀態下仍可能低於一百毫秒。

因此後置過濾器完全無法回答的執行計畫,是前置過濾器能精確且快速回答的計畫。懸崖和交叉點是同一個地方,這是個方便的巧合,也是本頁最有用的資訊。



交叉點位於何處

將兩種成本設為相等並求解。精確計畫的成本約為 sNd。後置過濾計畫需要 ef_search ≈ k/s,且每個候選會展開約 m 個鄰居,因此成本約為 (k/s)md

s N d  =  (k / s) m d

s²     =  k m / N

s*     =  sqrt(k m / N)

k = 10, m = 16, N = 10,000,000:
  s* = sqrt(160 / 10,000,000) = sqrt(1.6e-5) = 0.0040  →  0.40%

k = 10, m = 16, N = 1,000,000:
  s* = sqrt(160 / 1,000,000)  = 0.0126        →  1.26%

Assumptions: distance computation dominates both plans; heap access
costs are ignored, which flatters the exact plan; graph traversal
cost is linear in ef_search and m.

Enter fullscreen mode

Exit fullscreen mode

s* 之下,不要使用向量索引。在它之上,才使用。這個數字會隨著你的資料表大小移動,而平方根意味著它移動緩慢——從一百萬列成長到一千萬列只會讓它從約 1.3% 移動到約 0.4%。

這代表實務規則是:選擇超過資料表百分之幾的過濾器應該透過提高 ef_search 的向量索引;選擇低於百分之一的過濾器應該跳過它。規劃器不會可靠地為你做出這個選擇,因為它對 ANN 掃描的成本模型只是個佔位符,所以你應該明確地做出選擇。



四種解決方法

  1. 提高 ef_search 並測量。 對於高於百分之幾的選擇性,這就是完整解答。根據預期的選擇性為每個查詢設定它——你通常大致知道一個租戶有多少列——而不是全域設定。
  2. 依過濾欄位進行分割。 如果你的過濾器幾乎總是同一個欄位,將它設為分割鍵並為每個分割區建立一個 HNSW 索引。每個分割區的索引只包含符合的資料列,因此對它的掃描是未過濾的,上面的運算完全不適用。這是最乾淨的修正,也是具有真正運作成本的修正,因為它會讓你的索引數量倍增。

    CREATE TABLE chunks (
      id bigint GENERATED ALWAYS AS IDENTITY,
      tenant_id int NOT NULL,
      embedding vector(1536) NOT NULL,
      content text NOT NULL
    ) PARTITION BY LIST (tenant_id);
    
    CREATE TABLE chunks_t42 PARTITION OF chunks FOR VALUES IN (42);
    CREATE INDEX ON chunks_t42 USING hnsw (embedding vector_cosine_ops);
    
  3. 部分索引,用於少數熱門值。 索引本身的 WHERE 子句。適合兩三個大型租戶或單一 status = 'active' 述詞;超過幾十個就無法實用,因為每個都需要完整的 HNSW 建置。

    CREATE INDEX chunks_active_hnsw ON chunks
      USING hnsw (embedding vector_cosine_ops)
      WHERE deleted_at IS NULL;
    
  4. 在交叉點之下強制使用精確計畫。(tenant_id) 上建立複合 B-tree,並為該查詢停用索引掃描,或是撰寫查詢讓 ANN 索引無法套用——例如對計算出的運算式排序。在小的已過濾集合上進行精確搜尋不是後備方案;在 s* 之下,它才是正確的計畫。

不在清單中的一件事:將過濾欄位加入 HNSW 索引。pgvector 不支援多欄位 HNSW 索引,也沒有任何運算子類別能讓它有意義。如果某個教學建議這麼做,那個教學是在描述不同的引擎。

無論你採取哪種路線,你首先需要的數字是實際的選擇性,而它是一個查詢而非假設。過濾器很少是均勻的:少數租戶持有大部分語料,而長尾幾乎沒有,因此平均選擇性為百分之五可能隱藏著一千個坐在 0.01% 的客戶,他們看到空的結果而其他人都沒問題。

-- The distribution of selectivity across the filter values you
-- actually use. Look at the bottom decile, not the mean.
WITH n AS (SELECT count(*)::numeric AS total FROM chunks)
SELECT tenant_id,
       count(*) AS rows,
       round(100.0 * count(*) / (SELECT total FROM n), 4) AS pct_of_table,
       -- ef_search needed for a top-10 query, from k/s:
       ceil(10.0 * (SELECT total FROM n) / count(*)) AS ef_search_needed
FROM chunks
GROUP BY tenant_id
ORDER BY ef_search_needed DESC
LIMIT 20;

Enter fullscreen mode

Exit fullscreen mode

該輸出中任何 ef_search_needed 高於 1000 的項目,都是後置過濾計畫無法服務的過濾值,而此類資料列的計數會告訴你答案是每個查詢的 ef_search、分割策略,還是將小型租戶送到精確路徑、大型租戶透過索引的路由規則。最後這個選項值得考慮:兩個計畫都是正確的,因此依每個請求在它們之間選擇是一種合理的優化,而不是駭客行為。

最後,讓團隊驚訝的互動是:Postgres 列層級安全性原則會變成 WHERE 子句,這意味著啟用 RLS 會在一夜之間把應用程式中每個向量查詢都變成後置過濾的查詢,具有單一租戶的選擇性。這在多租戶檢索的列層級安全性中有涵蓋,並包含洩漏測試。



相關文章

https://dev.to/multigrid/filtering-and-vector-search-in-one-query-5085

https://www.worldprogramming.org/posts/filtering-and-vector-search-in-one-query-wki9iv

在 localhost,Rami Banna,Stripe 負責 Ecosystems、Apps 和 Stripe Projects 的產品負責人,介紹了 Stripe Projects,這是一款針對建置初期階段的工具:在產品還沒有使用者、還沒向任何人收費、開發者仍在為新技術堆疊連接帳號與服務的時候。

它背後的痛點與撰寫程式碼無關。設定一個新專案通常意味著在各個儀表板之間跳來跳去:建立帳號、架設服務、複製環境變數、輸入付款資訊、將所有內容貼到本機檔案中,並為堆疊所需的每個供應商重複這個過程。Stripe 將這個痛點追溯到付款:人們在第一天使用的多數 SaaS 和開發者工具,已經透過 Stripe 進行計費。這個重疊正是 Stripe Projects 所建立的基礎,讓開發者能從單一 CLI 建立帳號、佈建服務、管理環境變數,並支付升級費用。

其背後的網路目前約有 50 個供應商並持續增加,旨在作為一個開放生態系,任何人都能加入。

Stripe Projects 背後的協定運行在三個物件上:一個帳號(開發者在特定供應商的租戶、組織或團隊)、一個服務(該供應商提供的項目,其方案與價格目錄),以及一個資源(被建立並回傳憑證的具體實例)。

Three actors, one protocol
Three actors, one protocol

這三個物件支援完整的生命週期:建立或連接供應商帳號,即使原本不存在,也能使用 Stripe 自己的驗證機制來建立新帳號;拉取即時的服務目錄;佈建資源;回傳其憑證;之後輪替這些憑證;並在不再需要時移除資源。

Provisioning lifecycle steps
Provisioning lifecycle steps

每個供應商透過圍繞相同三個物件建置一小組端點來實作此協定:一個用於初始帳號請求,無需任何瀏覽器互動即可處理;一個用於服務請求,每十分鐘輪詢一次以保持價格與方案最新;以及一個用於資源本身,涵蓋其餘的生命週期。底層的服務 schema 足夠彈性,能夠建模用量計費、固定方案、混合計費或預付額度,因為供應商的收費方式差異很大。

Three core provider endpoints
Three core provider endpoints

在演講當時,該協定本身尚未公開。計畫是在今年夏天稍晚開放,並期望它能成為共享的標準。

佈建資源後仍會留下誰來支付的問題,而答案是一個共享的付款 token。開發者透過 Stripe Checkout 一次性輸入付款方式,Stripe 會為每個供應商分別將該憑證 token 化。每個供應商以其正常方式對自己的 token 進行計費,而開發者可以針對該共享方式為每個供應商個別設定消費上限。

其結果是在所有已連接的供應商之間,只需在單一地方輸入和檢視付款資訊,而非每個供應商各有一個,另外還有一個自然的控制點,可以限制代理程式正在消費的任何地方的支出。該層位於底層付款方式之上;目前支援銀行轉帳和先買後付。另一個推送 API 讓供應商能直接向 Stripe 回報變更,因此在供應商自家儀表板上所做的更新,仍會出現在 Stripe 這一側。

這與其說是一個平台,不如說是一個協調層。它是一個基礎設施層,讓你能夠擁有自己的供應商帳號。

透過 Stripe Projects 建立的帳號屬於開發者,而非 Stripe。當透過 Stripe 使用 Render 基礎設施時,Render 仍是實際的服務供應商和計費關係;憑證與環境變數會留在開發者自己的專案內。Stripe Projects 只負責協調佈建本身,之後不會介入開發者與供應商之間。

從命令列佈建

從 CLI 拉出 Stripe Projects 目錄,會顯示 Render 在網路中提供的項目:Postgres、Web 服務或靜態網站。輸入 stripe projects add render 會直接顯示該目錄,接著相同的指令可以交給像 Claude 這樣的程式碼代理,它會連接公開的 GitHub 儲存庫,並直接從命令列透過 Render 進行部署。同樣的模式也能擴展到加入其他供應商,包括 OpenRouter、Exa、Clerk 和 PostHog 等,只要用自然語言詢問代理它需要什麼;它會使用相同的底層指令,將所有東西整合到一個專案中,並共用一組環境變數。

Stripe Projects CLI setup
Stripe Projects CLI setup

https://render.com/blog/stripe-an-orchestration-layer-not-a-platform

https://www.worldprogramming.org/posts/stripe-an-orchestration-layer-not-a-platform-av4nrm