Back to blog
    API 日誌轉訓練資料:利用雲端 AI 歷史記錄進行微調
    training dataAPI logsfine-tuningmigrationon-device AIsegment:mobile-builder

    API 日誌轉訓練資料:利用雲端 AI 歷史記錄進行微調

    您現有的雲端 AI API 日誌就是一個現成的訓練資料集。如何從 API 互動日誌中提取、清洗和格式化微調資料,用於裝置端模型。

    EErtas Team·

    如果您目前在使用雲端 AI API(OpenAI、Anthropic、Google Gemini),您已經在產生訓練資料了。每次 API 呼叫都包含一個輸入(使用者的請求)和一個輸出(模型的回覆)。這就是一個訓練樣本。

    您的 API 日誌是從雲端 AI 遷移到裝置端 AI 的最快路徑。您不需要從零開始建立資料集。您已經有了。

    API 日誌包含什麼

    一個典型的 API 呼叫日誌條目:

    {
      "timestamp": "2026-03-15T14:22:03Z",
      "model": "gpt-4o-mini",
      "messages": [
        {
          "role": "system",
          "content": "You are the shopping assistant for StyleApp..."
        },
        {
          "role": "user",
          "content": "Find me a blue dress for a summer wedding"
        },
        {
          "role": "assistant",
          "content": "Here are some suggestions for a summer wedding...\n\n1. Floral midi dress in navy blue...\n2. Light blue chiffon maxi dress..."
        }
      ],
      "tokens_used": {"input": 1842, "output": 387},
      "latency_ms": 1203
    }

    這個日誌條目已經是微調所需的精確格式。messages 陣列就是一個訓練對話。

    提取流程

    步驟 1:匯出您的日誌

    日誌的儲存位置取決於您的架構:

    如果您自己記錄 API 呼叫: 從您的資料庫(PostgreSQL、MongoDB 等)或日誌聚合服務(Datadog、CloudWatch 等)匯出。

    如果您使用 OpenAI 的 API: API 預設不儲存日誌。您需要自己的日誌中介軟體。如果還沒有,現在就設定。每次未來的 API 呼叫都是潛在的訓練樣本。

    # 簡單的日誌中介軟體範例
    import json
    import datetime
    
    def log_api_call(request_messages, response_content, model, tokens):
        log_entry = {
            "timestamp": datetime.datetime.utcnow().isoformat(),
            "model": model,
            "messages": request_messages + [
                {"role": "assistant", "content": response_content}
            ],
            "tokens_used": tokens,
        }
        with open("api_logs.jsonl", "a") as f:
            f.write(json.dumps(log_entry) + "\n")

    步驟 2:品質過濾

    不是每個 API 回覆都是好的訓練資料。過濾掉:

    失敗的回覆: 逾時錯誤、格式錯誤的輸出、拒絕回覆。

    低品質輸出: 使用者立即重試的回覆(表示不滿意),或被截斷的輸出。

    異常值: 不代表典型行為的異常長或短的回覆。

    離題互動: 如果使用者偶爾提出離題問題,除非您希望模型處理它們,否則排除。

    def is_quality_example(log_entry):
        messages = log_entry["messages"]
        assistant_msg = next(
            (m for m in reversed(messages) if m["role"] == "assistant"), None
        )
        if not assistant_msg:
            return False
    
        content = assistant_msg["content"]
    
        # 過濾過短的回覆
        if len(content) < 50:
            return False
    
        # 過濾錯誤回覆
        if "I apologize" in content and "I cannot" in content:
            return False
    
        # 過濾截斷的回覆
        if log_entry.get("finish_reason") == "length":
            return False
    
        return True

    步驟 3:移除系統提示(選用)

    如果您在做微調,模型會從訓練樣本中學習行為。您可能不需要在訓練資料中包含系統提示,因為微調後的模型會內化這些指令。

    兩種方式:

    保留系統提示: 模型學習遵循這些特定指令。適用於系統提示簡短且穩定的情況。

    移除系統提示: 模型學習行為模式而非顯式指令。適用於系統提示較長(節省訓練 token)或您希望行為是內在的而非依賴指令的情況。

    步驟 4:匿名化

    從訓練資料中移除 PII:

    import re
    
    def anonymize_message(content):
        # 電子郵件
        content = re.sub(r'\b[\w.-]+@[\w.-]+\.\w+\b', '[EMAIL]', content)
        # 電話號碼
        content = re.sub(r'\b\d{3}[-.]?\d{3}[-.]?\d{4}\b', '[PHONE]', content)
        # 信用卡號
        content = re.sub(r'\b\d{4}[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4}\b', '[CARD]', content)
        # 地址(基礎模式)
        content = re.sub(r'\d+\s+[\w\s]+(?:Street|St|Avenue|Ave|Road|Rd|Drive|Dr)\b', '[ADDRESS]', content)
        return content
    
    def anonymize_log(log_entry):
        for msg in log_entry["messages"]:
            msg["content"] = anonymize_message(msg["content"])
        return log_entry

    步驟 5:格式化為訓練資料

    將過濾和匿名化後的日誌轉換為標準微調格式:

    def log_to_training_example(log_entry):
        messages = []
        for msg in log_entry["messages"]:
            if msg["role"] in ("system", "user", "assistant"):
                messages.append({
                    "role": msg["role"],
                    "content": msg["content"]
                })
        return {"messages": messages}
    
    # 處理所有日誌
    training_data = []
    for log_entry in load_logs("api_logs.jsonl"):
        if is_quality_example(log_entry):
            anonymized = anonymize_log(log_entry)
            example = log_to_training_example(anonymized)
            training_data.append(example)
    
    # 寫入訓練檔案
    with open("training_data.jsonl", "w") as f:
        for example in training_data:
            f.write(json.dumps(example) + "\n")

    需要多少日誌

    每日 API 呼叫量收集 1,000 個樣本所需時間收集 5,000 個樣本所需時間
    1002-3 週(品質過濾後)2-3 個月
    5003-5 天2-3 週
    1,0002-3 天1-2 週
    5,0001 天3-5 天

    假設 50-70% 的原始 API 呼叫能通過品質過濾。在每天 500 次呼叫的情況下,您每天累積 250-350 個高品質樣本。

    對於大多數任務,1,000 個高品質樣本就足以產出表現良好的微調模型。從設定日誌記錄開始,幾天到幾週內就可以開始訓練。

    蒸餾優勢

    當您用大模型(GPT-4o、Claude Sonnet)的輸出來微調小模型(1-3B)時,您正在執行知識蒸餾。小模型學習在您的特定任務上複現大模型的行為。

    結果:一個 3B 微調模型在您的領域任務上匹配大模型的效能,同時在裝置端運行。這不是理論。研究和生產部署持續表明,微調的小模型在狹窄的領域特定任務上能匹配甚至超越經提示的大模型。

    您的 API 日誌就是蒸餾資料集。大模型已經完成了工作。您只需要教一個小模型複製它。

    從日誌到部署

    端到端流程:

    1. 設定 API 日誌記錄(如果尚未到位)
    2. 累積 1,000+ 個高品質樣本(幾天到幾週)
    3. 提取、過濾、匿名化和格式化 日誌
    4. 上傳到微調平台 如 Ertas
    5. 選擇基礎模型(推薦 Llama 3.2 3B)
    6. 使用 LoRA 微調(30 分鐘到 3 小時)
    7. 匯出 GGUF(Q4_K_M 量化)
    8. 在行動應用程式中整合 llama.cpp
    9. A/B 測試 裝置端模型與雲端 API 的對比
    10. 遷移 當裝置端模型達到品質標準時

    您的 API 日誌不僅僅是成本中心。它們是通往裝置端 AI 的橋梁。

    Ship AI that runs on your users' devices.

    Early bird pricing starts at $14.50/mo — locked in for life. Plans for builders and agencies.

    Keep reading