上一季度,我們承接了一個在紙面上聽起來很簡單的專案:用AI生成的描述、分類和元數據豐富28,840條產品記錄。客戶有一個龐大的電子商務目錄正在遷移到無頭CMS,每一條記錄都需要更好的內容。隨後發生的事情是當您將數以萬計的記錄投入AI API時,一切可能出錯和正確的方面的大師級教學。

這不是理論指南。我將帶您詳細了解我們構建的實際架構、我們支付的確切成本、我們遇到的失敗模式,以及拯救我們的模式。如果您正在考慮為自己的專案進行AI批量內容豐富,這應該可以讓您節省幾週的痛苦探索。

目錄

為什麼我們選擇AI豐富而不是手動工作

數學非常簡單。我們的客戶有28,840條產品記錄——每一條都需要改寫描述(150-300字)、三個SEO友好的分類標籤、元描述和從非結構化文本中提取的結構化屬性。以一位人工文案寫手每條記錄保守估計8分鐘計算,這需要3,845小時的工作。以$35/小時計,您需要支付$134,575,加上一個小團隊大約6個月的工期。

我們在11天內完成了AI豐富,API成本不到$3,200,加上大約80小時的工程和品質保證時間。即使計入我們的開發時間,總成本大約是手動方法的十分之一。

但這裡有一個沒有人告訴您的事情:困難的部分不是調用API。而是它周圍的一切。數據清潔、提示調整、品質驗證、錯誤處理,以及不可避免的邊界情況,讓人質疑職業選擇。

架構:我們如何構建管道

我們構建了豐富管道作為Node.js應用程式,這對我們在Next.js開發和TypeScript中的專業知識很有意義。以下是高階架構:

Source CSV → Parser → Batch Queue → Claude API → Response Validator → Output Store → QA Dashboard

數據層

我們使用SQLite作為本地處理數據庫。聽起來不性感,對嗎?但對於這樣的批量處理,它是完美的。無需管理伺服器,交易速度快,您可以輕鬆查詢結果。每條記錄都有一個狀態欄追蹤其歷程:

interface EnrichmentRecord {
  id: string;
  original_title: string;
  original_description: string;
  raw_attributes: string;
  status: 'pending' | 'processing' | 'completed' | 'failed' | 'needs_review';
  enriched_description: string | null;
  enriched_categories: string[] | null;
  enriched_meta: string | null;
  structured_attributes: Record<string, string> | null;
  attempts: number;
  last_error: string | null;
  token_usage: number;
  created_at: string;
  updated_at: string;
}

佇列系統

我們使用由Redis支持的BullMQ實現了一個簡單的工作佇列。每個工作都代表單個記錄豐富。我們配置了:

  • 並發:5個並行工作線程(稍後詳細說明為什麼是這個數字)
  • 最大重試次數:每條記錄3次
  • 退避:指數級,起始30秒
  • 工作逾時:60秒
const enrichmentQueue = new Queue('enrichment', {
  connection: redisConnection,
  defaultJobOptions: {
    attempts: 3,
    backoff: {
      type: 'exponential',
      delay: 30000,
    },
    timeout: 60000,
    removeOnComplete: false, // Keep for auditing
  },
});

處理工作線程

每個工作線程拉取一條記錄,構建提示,調用Claude的API,驗證響應結構,並將結果寫回。如果響應與我們預期的JSON架構不匹配,它會進入needs_review桶中,而不是無聲地破壞我們的數據集。

選擇Claude API進行批量處理

在決定使用Claude(特別是Claude 3.5 Sonnet,之後對於更簡單的任務使用Claude 3.5 Haiku)之前,我們評估了三個選項:

功能 Claude 3.5 Sonnet GPT-4o Gemini 1.5 Pro
輸入成本(每1M令牌) $3.00 $2.50 $1.25
輸出成本(每1M令牌) $15.00 $10.00 $5.00
速率限制(RPM,第2層) 1,000 500 360
JSON模式可靠性 優秀 優秀 不一致
結構化輸出品質 最佳級別 非常好
批量API折扣 50% 50% N/A

Q1 2025年的價格。檢查當前定價——這些經常變化。

我們選擇Claude有幾個原因。首先,它在我們的500條記錄測試運行中對結構化輸出的指令遵循明顯優於替代品。當您處理近29K條記錄時,即使是2%的格式合規性改進也會節省您數百次手動修正。其次,Anthropic的批量API為非時間敏感的工作提供了50%的折扣,這使得經濟效益更加有利。

老實說,GPT-4o也會沒問題。這種規模的差異更多是關於速率限制和定價,而不是原始品質。但Claude與JSON輸出的一致性是決定因素。

為什麼我們同時使用Sonnet和Haiku

這是一個為我們節省了大約40%API成本的技巧:我們沒有對所有內容使用相同的模型。產品描述需要Sonnet的品質。但分類和屬性提取?Haiku以極低的成本處理得很好。

我們將豐富分為兩個階段:

  1. 階段1(Haiku):分類分類、屬性提取、基本元數據——$0.25/1M輸入、$1.25/1M輸出
  2. 階段2(Sonnet):描述改寫、元描述、SEO內容——$3.00/1M輸入、$15.00/1M輸出

大規模提示工程

這是大多數教程讓您失望的地方。他們展示您一個單一提示並完成。當您通過相同的提示範本運行28,840條記錄時,細微的缺陷被放大為巨大的問題。

提示範本

經過大約15次迭代(是的,我們在git中追蹤了它們),以下是有效的粗略結構:

const buildPrompt = (record: SourceRecord): string => `
You are enriching product data for an e-commerce catalog. Generate the following for the product below:

1. A product description (150-300 words, second person, benefit-focused)
2. Exactly 3 category tags from this allowed list: ${CATEGORY_LIST}
3. A meta description (120-155 characters)
4. Structured attributes as key-value pairs

Rules:
- Do NOT invent features not present in the source data
- If information is ambiguous, use the "uncertain" flag
- Match the brand's tone: professional but approachable
- Description must be unique -- do not repeat the title verbatim in the first sentence

Respond ONLY with valid JSON matching this schema:
${JSON_SCHEMA}

Source product data:
Title: ${record.title}
Existing description: ${record.description}
Raw attributes: ${record.attributes}
Price: ${record.price}
Brand: ${record.brand}
`;

大規模提示課程

對輸出格式極其具體。 我們在每個請求中包含了完整的JSON架構。是的,它增加了令牌。不,不要跳過它。唯一一次我們嘗試僅依賴系統指令時,我們的格式合規性從97%下降到81%。

限制輸出詞彙。 對於分類標籤,我們提供了一個明確的允許列表。開放式分類在我們的測試批次中產生了847個唯一分類。受限的版本?正好是我們想要的42個。

為幻覺添加護欄。 產品偶爾會長出他們沒有的功能。添加「不要發明源數據中不存在的功能」減少了大約70%的幻覺屬性。添加uncertain標誌捕獲了大多數剩餘情況。

溫度比您想像的更重要。 我們確定了0.3。低於這個值,描述在類似產品中變得重複。更高,我們開始得到創意寫作,不符合品牌聲音。

速率限制、重試和不被禁的藝術

這一部分真的應該被稱為「花費最多工程時間的部分」。Anthropic的速率限制得到了很好的記錄,但在持續負載下的行為方式與您從閱讀文件中預期的不同。

我們的速率限制策略

在第2層(您花費$40+後獲得),Claude為您提供1,000個請求/分鐘和80,000個令牌/分鐘。聽起來很慷慨,直到您意識到我們的平均請求約為1,200個輸入令牌和800個輸出令牌。這意味著我們在達到令牌限制之前的實際限制約為40個並發請求。

我們運行5個並發工作線程,每個處理一條記錄,請求之間延遲200毫秒。這給了我們大約15-20個請求/分鐘——遠低於RPM限制,舒適地在令牌預算內。

const rateLimiter = new Bottleneck({
  maxConcurrent: 5,
  minTime: 200, // ms between requests
  reservoir: 900, // requests per minute (leaving buffer)
  reservoirRefreshAmount: 900,
  reservoirRefreshInterval: 60 * 1000,
});

為什麼這麼保守? 因為達到速率限制會導致級聯故障。一個429響應觸發重試,這增加到佇列,增加並發壓力。我們在第一次真實運行的第3小時時以困難的方式學到了這一點,當時激進的設置導致重試風暴,有效地使管道停頓了45分鐘。

批量API替代方案

在項目的中途,我們部分轉向了Anthropic的批量API。與其發出個別請求,您上傳一個請求的JSONL文件,並在24小時內取得結果。權衡:50%的成本降低,但您失去實時反饋。

我們對階段1(Haiku分類)使用了批量API,對階段2(Sonnet描述)使用了實時API。這種混合方法對我們來說是最佳點——對昂貴創意工作的快速反饋,對商品分類的批量經濟。

品質控制:人在環路中的現實

任何告訴您AI豐富完全自動化的人要麼在撒謊,要麼還沒有大規模進行過。我們構建了一個品質保證流程,可以及早捕獲問題並防止垃圾進入生產環境。

自動化驗證

每個API響應在被接受前都要進行驗證:

const validateEnrichment = (result: EnrichmentResult): ValidationOutcome => {
  const issues: string[] = [];
  
  // Length checks
  if (result.description.length < 400 || result.description.length > 2000) {
    issues.push('description_length');
  }
  
  // Category validation
  const invalidCats = result.categories.filter(c => !ALLOWED_CATEGORIES.includes(c));
  if (invalidCats.length > 0) issues.push('invalid_categories');
  
  // Meta description length
  if (result.meta.length > 160) issues.push('meta_too_long');
  
  // Hallucination signals
  const hallucination_phrases = ['I think', 'probably', 'might be', 'as an AI'];
  if (hallucination_phrases.some(p => result.description.includes(p))) {
    issues.push('possible_hallucination');
  }
  
  // Duplicate detection (fuzzy match against already-processed records)
  if (isDuplicateDescription(result.description)) {
    issues.push('duplicate_content');
  }
  
  return {
    valid: issues.length === 0,
    issues,
    needsReview: issues.length > 0 && issues.length < 3,
    rejected: issues.length >= 3,
  };
};

手動審查取樣

我們對所有已處理記錄的5%(約1,440條)進行了手動審查取樣。我們的品質保證團隊根據準確性、品牌聲音和完整性對每一項進行了評分。以下是我們實際審查的數字:

指標 分數
事實準確性 94.2%
品牌聲音匹配 87.6%
格式合規性 97.1%
分類準確性 91.8%
需要修訂的記錄 8.3%
完全拒絕的記錄 1.9%

那8.3%需要修訂是重要的背景。這意味著約2,400條記錄需要人工編輯。仍然遠少於手動編寫全部28,840——但它不是零。為此做預算。

真實成本分解

透明時間。以下是我們實際支出:

成本類別 金額
Claude 3.5 Haiku(階段1 - 批量API) $312
Claude 3.5 Sonnet(階段2 - 實時) $2,147
失敗/重試請求(~6%開銷) $189
Redis託管(2週) $15
工程時間(80小時× $150) $12,000
品質保證審查時間(40小時× $45) $1,800
總計 $16,463
僅API成本 $2,648

與完全手動工作的$134,575估計相比。即使包括所有工程和品質保證時間,我們也在手動成本的約12%。每條記錄的API成本計算為約$0.092。每條記錄不到一毛錢用於AI豐富。這是讓高管坐起來的數字。

我們做錯的事

低估數據清潔

在向Claude發送數據之前,我們花費了3天時間清潔源數據。記錄有HTML實體、Unicode垃圾、截斷描述和列中的錯誤字段。垃圾進,垃圾出不只是一個陳詞濫調——它是批量AI處理的基本法則。

沒有從第一天開始使用批量API

通過實時API運行階段1時,我們燃燒了大約$400額外的API成本,然後才發現批量API會將成本降低一半。開始之前閱讀完整文件。全部的。

重複檢測不足

我們最初的重複檢測太天真了——簡單的字符串匹配。Claude會為類似產品生成結構上相同但使用稍微不同措辭的描述。我們必須實現語義相似性檢查(使用嵌入)來捕獲這些,這增加了一天的工作。

JSON解析失敗

大約2.4%的響應返回格式不正確的JSON。有時是尾隨逗號,有時是產品描述中未轉義的引號。我們應該從一開始就實現更寬鬆的JSON解析器,而不是將這些視為硬性失敗。

// What we should have done from day one
const parseResponse = (raw: string): EnrichmentResult | null => {
  try {
    return JSON.parse(raw);
  } catch {
    // Try to extract JSON from markdown code blocks
    const jsonMatch = raw.match(/```json?\n?([\s\S]*?)\n?```/);
    if (jsonMatch) {
      try { return JSON.parse(jsonMatch[1]); } catch { /* fall through */ }
    }
    // Try jsonrepair library as last resort
    try { return JSON.parse(jsonrepair(raw)); } catch { return null; }
  }
};

我們下次會做什麼不同的事

  1. 從1,000條記錄試點開始,然後再提交完整運行。我們做了500條,但還不足以涵蓋所有邊界情況。

  2. 從一開始就使用結構化輸出。 Anthropic現在支持帶有定義架構的工具使用,這消除了大多數JSON解析問題。我們在中途遷移到了這一點,並希望我們從一開始就開始了。

  3. 首先構建品質保證儀表板。 我們在反應性地構建它後出現問題。從第一天開始使用它會在前100條記錄而不是前2,000條記錄中捕獲問題。

  4. 投資更好的嵌入以進行去重。 我們從一開始就使用專用嵌入模型(如text-embedding-3-small)進行語義重複檢測。

  5. 考慮混合模型路由。 一些記錄很簡單(帶有基本屬性的T恤),有些很複雜(帶有數十個規格的電子產品)。將簡單記錄路由到Haiku,複雜記錄路由到Sonnet——即使對於描述——也會為API成本再節省20-30%。

如果您正在計劃類似項目並希望跳過困難部分,我們已將此類工作的可重複使用管道構建為我們無頭CMS開發實踐的一部分。很樂意分享更多細節。

常見問題

用AI豐富28,000多條記錄需要多長時間? 我們的實際處理時間約為11天,包括管道開發、測試、處理和品質保證審查。API處理本身(發送請求和取得響應)花費了大約48小時的連續運行。如果您專門使用批量API,預期API處理需24-48小時,加上3-5天的工程和品質保證。

AI內容豐富的每條記錄成本是多少? 使用Claude 3.5 Sonnet和Haiku的組合,我們的API成本約為每條記錄$0.092,用於生成產品描述、分類、元描述和結構化屬性。您的實際成本將根據輸入/輸出長度和您選擇的模型而有所不同。批量API處理會將此大致減半。

Claude還是GPT-4更適合批量數據豐富? 兩者都效果很好。我們選擇Claude 3.5 Sonnet是因為在我們的測試中它優越的JSON格式合規性(97.1%對GPT-4o的~94%)。但是,GPT-4o在輸出令牌方面稍便宜。如果您的豐富主要是分類而不是內容生成,差異不大。提交前先用500條記錄測試兩者。

在進行數千個API調用時,您如何處理速率限制? 使用速率限制程式庫,如Bottleneck,設置保守的並發(5-10個並行請求),為重試實現指數退避,並在發佈的速率限制下留下10-15%的緩衝。對於非時間敏感的工作,Anthropic的批量API避免了速率限制問題,成本降低50%。

AI豐富的記錄中有多少百分比需要人工審查? 在我們的項目中,8.3%的記錄需要某種形式的人工編輯,1.9%完全被拒絕並手動改寫。您的數字將取決於數據品質、提示工程和可接受的品質閾值。計劃人工干預為5-15%作為現實基線。

AI批量豐富能處理多種語言嗎? 是的,但品質因語言而異。Claude和GPT-4很好地處理主要歐洲語言,但對於較少見語言的準確性下降。我們建議每種語言運行單獨的提示範本,並在品質保證取樣中具有母語使用者。預期非英文內容的人工審查百分比大致翻倍。

您如何防止AI在產品數據中出現幻覺? 三層:明確禁止發明功能的提示指令、用於不明確數據的「不確定」標誌,以及自動化驗證將豐富屬性與源數據進行比較。我們還使用語義相似性評分來標記偏離原始產品信息的描述。這減少了大約70%的幻覺屬性。

值得構建自訂管道還是應該使用現有工具? 對於少於1,000條記錄,像Clay、Bardeen或精心構建的Google Sheets + Apps Script之類的工具可以工作。超過這個數字,自訂管道會很快為自己付費。自訂解決方案提供的對重試邏輯、品質驗證和成本優化的控制在大規模時是必不可少的。我們的管道約為2,000行TypeScript——不是平凡的,但也不是一個大項目。如果您想讓我們為您的用例構建一個,請查看我們的定價頁面