平台的核心資產是一套「問 N 個 AI 平台、拿回品牌應答」的掃描引擎(第 5 章)。若要把這套引擎以 API 對外供給給消費方,最直覺的做法是開一個對內 endpoint 讓對方呼叫——但那同時開了一個攻擊面,也很容易把外部任務的資料混進核心租戶庫。本章記錄一個相反的設計:把供給端做成主動輪詢的 executor,而非被呼叫的 endpoint,並在其上疊 exactly-once 交付、誠實記帳與零基建的市場視角。
平台既有的掃描引擎(queryPlatform,第 5 章多 provider 路由)能對任一 AI 平台送出品牌查詢、拿回應答與引用來源。當一個外部消費方(內容分發平台、聚合服務等)想「程式化地大量取得品牌在各 AI 平台的原始應答」時,平台可以把這套引擎當成一個 API 服務供給出去。
直覺設計是開一個 inbound endpoint:對方 POST /scan {brand, prompt, model},我方同步回應答。但這帶來三個工程負擔:
brands / axp_pages / RAG 知識庫,會破壞核心租戶隔離(平台鐵律),也會讓外部查詢污染自家 GEO 內容。本章的設計把這三個負擔一次性壓掉:不開對內 endpoint、批發 track 與核心完全切開、以獨立 worker 承載。
關鍵決策:我方不是被呼叫方,而是主動輪詢的 executor。消費方把查詢排進它自己的任務網關,我方的 worker 定期去拉任務、執行、再把結果回推回去。
flowchart LR
subgraph 消費方網關
Q[待執行任務佇列<br/>brand + prompt + model + region]
end
subgraph 供給端 executor(本平台)
P[poller<br/>輪詢拉取] --> X[executor<br/>queryPlatform 執行]
X --> S[submitter<br/>回推結果]
end
P -.①GET tasks.-> Q
S -.③PUT result.-> Q
X -->|②answerContent + references| S
Fig 20-1:pull-based executor——供給端只發出方向 HTTPS(拉任務 + 回結果),不開任何對內 endpoint。
這個倒置帶來的直接好處:
answerContent + references);其餘欄位是消費方餵入的輸入,回推時原樣帶回。實際運算極小,工程重點落在傳輸對接 + 冪等 + 隔離 + 記帳,而非演算法。核心引擎 queryPlatform 被當成一個無狀態、per-task 的 pass-through 執行單元——這與平台平常掃描自家品牌的行為刻意不同:
| 面向 | 平台自監測(零售) | 程式化供給(本章) |
|---|---|---|
| prompt 來源 | GEO 提示生成(keywords / 意圖模板 / 反查) | 消費方原文,不改寫不擴充 |
| 平台數 | 一次掃多個 AI 平台 | 單任務單平台(對方指定那一個) |
| 資料落地 | 進品牌庫 / AXP / 成本帳 | 執行完即棄,不落核心庫 |
呼叫形態化約為 queryPlatform(mapModel(model), { brandName, query: prompt }):brand 只作上下文,查詢以對方 prompt 原文為準。model_key 經一層對映表轉成內部 platform;認不得的 model 直接回對方的錯誤契約碼(模型暂不支持),不進執行。
這裡複用了第 5 章多 provider 路由的全部既有能力(逾時、快取、RPM、重試),等於把一套已在 PROD 驗證過的掃描引擎,以最薄的一層轉接對外供給——新增的不是引擎,而是引擎外面的傳輸與治理殼層。
供給 track 與核心 SaaS 在五個維度全部切開,對齊平台的跨租戶隔離鐵律:
| 維度 | 隔離做法 |
|---|---|
| 資料 | 外部任務的 brand / prompt / 答案只進獨立表 answer_feed_tasks,絕不寫 brands / axp_pages / ground_truths / RAG。表內 brand 只是外部字串,天生不與核心品牌實體關聯。 |
| 成本帳 | 獨立記帳,不混入核心掃描的成本表(或以 source 明確標記可切分)。 |
| 限流桶 | 獨立節流,不佔用核心租戶的掃描配額。 |
| worker | 獨立 answerFeed.worker.js,與核心掃描 worker 分離,故障互不影響。 |
| 啟用 | 預設對所有租戶關閉;只有明確加入 allowlist 的夥伴帳號可用(非按方案層,而是按特定帳號),config 讀取失敗時 fail-closed。 |
「brand 只是外部字串」這點很關鍵:因為批發 track 的 brand 欄從不反查、不 JOIN 核心品牌表,跨產品的品牌隔離天生成立,不需要額外的過濾邏輯去防止污染——結構上就到不了核心庫。
供給的財務正確性建立在一條原則上:同一任務只執行一次、只計費一次、只交付一次。但「拉取→執行→回推→計費」是四個獨立的網路 / DB 動作,中間任一步崩潰都可能留下模糊狀態。設計以一個顯式狀態機 + 冪等鍵處理:
stateDiagram-v2
[*] --> pulled: 冪等領取(唯一鍵)
pulled --> executing
executing --> succeeded: 答案已存
executing --> failed: provider 失敗(不計費)
succeeded --> submitting: 回推 PUT 前先標記
submitting --> submitted: 回推成功
submitting --> in_doubt: PUT 已發、結果不明(崩潰)
submitted --> acked: 對方確認 + 計費
submitting --> submit_failed: 回推失敗(退避重送)
submit_failed --> submitting
Fig 20-2:交付狀態機。submitting 這個中間態把「已執行、從未嘗試回推」與「PUT 已發、結果不明」明確分開。
幾個關鍵工程紀律:
(gateway_task_id, resolved_platform) 唯一索引。同一任務重派 → 更新狀態,不重複執行、不重複計費。submitting:讓 succeeded 的語意明確 = 「已執行、從未嘗試回推」。沒有這個中間態時,「PUT 成功但記帳未 commit 就崩潰」的列會停在 succeeded,與真孤兒無從區分 → 盲目重送 = 重複交付。submitting(PUT 已發、結果不明)不自動重送,只計數告警人工對帳——因為消費方網關對 taskId 是否冪等未必保證,重送的風險大於漏送。billed_at 標記區分「已交付但尚未計費」,由背景 sweep 週期性補上(冪等鍵保證補計費不重複)。任一中間崩潰都能被 sweep 自癒,而不是靜默漏帳。這一節的設計哲學與第 9 章(閉環)一致:在分散式邊界上,把每一種「中間崩潰」都想清楚它會停在哪個狀態、由誰回收,而不是假設 happy path。
本供給模式的成本歸屬有一個特別之處:AI 存取可由消費方提供的 key 執行,於是 AI Token 成本落在消費方帳上,我方只收 per-task 的執行 / orchestration 服務費。記帳因此把兩件事嚴格脫鉤:
billable 只在「執行成功且非重複」時為真;provider 失敗、空答案、逾時都不計費。空 / 純空白答案視為 provider 拒答或內容過濾,走失敗路徑而非當有效答案交付。計費量本身走平台的通用計量計費引擎(以整數化的最小計價單位累計,避免逐筆浮點捨入累積誤差),供給只是這個引擎的其中一個用量來源——計費邏輯不重寫,只接線。
當消費方背後有大量下游客戶、同時送不同品牌 / 地區的查詢時,吞吐成為瓶頸。一個常見的初版陷阱是序列單線:單一 cycle、逐任務 await,每任務 provider 逾時可達數十秒。上百任務序列跑一輪要數十分鐘,尾端任務直接撞上消費方的當日截止時間被丟棄——大量任務永遠處理不完。
規模化設計把序列改成有界並發:
p-limit(N) 平行:N 依 provider rate limit 與自身資源決定,取代逐一序列。這裡再次出現「per-迴圈總時長 = 單筆延遲 × 任務數」的算術(與第 19 章 stagger 同源):在任何「一輪要處理 N 筆、每筆可能慢」的批次設計裡,序列的總時長會線性爆炸,有界並發是把它壓回可控的唯一辦法。
一個常見需求是「請以某個市場(如泰國)的視角回答」。直覺會想到「從該地區的 IP 發問」,但這條路在工程與商業上都不成立,平台選了相反的做法。
做法:在 executor 呼叫 provider 之前,依任務帶的 region 於提示層注入市場 / 語言脈絡(告訴 AI「以該市場在地消費者視角、用當地語言回答,僅考慮該市場實際可得的品牌 / 通路 / 價格」),原始 user prompt 不動。這是 per-task、無狀態的純轉換,複用平台既有的市場→語言映射(第 17 章跨境所用的 contentLanguage),對任何市場一致成立、零基建。
為什麼不追求「地區 IP 發問」:
誠實界線(工程上顯式標註):我方交付的是「AI 對該市場的在地視角答案」,不是「真人在該地區 IP 用網頁版拿到的 IP-在地化答案」——這是純文字方案的已知界線,寫進對接協議。對應地,回推的結果只有在確實套了市場視角時才標記為「市場視角來源」;若只是套了一個預設語言指示(例如未指定語系時預設某語言),不得被誤標為市場視角。這條「語言指示 ≠ 市場視角」的界線由程式顯式區分:市場鎖定旗標只反映地區鎖定本身,不因「是否附帶了任何語言提示」而連帶為真——否則幾乎每一筆 pass-through 答案都會被誤標,破壞對消費方的誠實界線。
satori → PNG,不啟動瀏覽器)回推,供消費方當引用證據卡;它不改變保真度界線 —— 呈現的仍是 API 純文字答案本身,只是換個視覺載體。「渲染答案卡 ≠ 截真實 UI」這條區分需消費方知悉並接受。本章的核心價值:把一套已驗證的掃描引擎對外供給,不必開放對內攻擊面(pull executor)、不必污染核心資料(五維隔離)、不必犧牲財務正確性(exactly-once + 誠實記帳),也不必蓋不可擴的地區 IP 基建(零基建市場視角)。新增的工程量幾乎全在引擎外的傳輸與治理殼層,而非引擎本身。
queryPlatform 被當成 per-task、無狀態的 pass-through 執行單元:prompt 用對方原文、單任務單平台、執行完即棄。brand 只是外部字串,結構上到不了核心品牌庫。submitting in-doubt 態 + 計費 / 交付分離的補償 sweep;每種中間崩潰都想清楚停在哪、由誰回收。p-limit(N) + 兩層限流 + per-cycle 預算 + 公平排程)把「序列總時長 = 延遲 × 任務數」的線性爆炸壓回可控。| 日期 | 版本 | 說明 |
|---|---|---|
| 2026-08-26 | v1.3(草案) | 初稿。記錄 pull-based executor 架構、pass-through 執行、五維隔離、exactly-once 交付狀態機、誠實記帳、有界並發、零基建市場視角。 |
導覽:← Ch 19: 快取失效 5 層架構 · 目次 · 附錄 A: 詞彙表 →