免費全文 工具與工作流 進階

串接多家模型服務:抽象層該做到什麼程度

過度抽象會綁死自己,完全不抽象又難以換供應商。這是實用的中間路線。

工具與工作流教程封面

想保留換供應商的彈性,但也不想寫一個支援所有功能的巨大抽象層。中間路線是:只抽象你真的會用到的部分。

建議抽象的部分

  • 基本補全與對話呼叫。
  • 串流。
  • 工具呼叫的請求與回應格式。
  • 用量統計(輸入輸出 token)。
  • 錯誤分類:限流、逾時、內容過濾、其他。

不建議抽象的部分

  • 各家特有的參數——用 extra 字典直接透傳。
  • 結構化輸出的實作細節,差異太大。
  • 快取機制,各家計費與行為不同。
@dataclass
class Reply:
    text: str
    tool_calls: list
    usage: dict          # {'in': int, 'out': int}
    raw: dict            # 保留原始回應,需要時可取用特有欄位

class Provider(Protocol):
    def chat(self, messages, tools=None, stream=False, **extra) -> Reply: ...

錯誤要統一分類

class RateLimited(Exception): pass
class Overloaded(Exception): pass
class ContentFiltered(Exception): pass

# 各家的錯誤碼在 provider 內部轉換成上面這幾種
# 上層邏輯只需要處理統一的類別

錯誤分類是抽象層最有價值的部分。有了它,重試與降級的邏輯才能寫一次就適用所有供應商。

保留 raw 欄位

抽象層一定會漏掉某些欄位。保留原始回應讓上層在需要時能取用,比為了每個新欄位改抽象層實際得多。

別在第一天就寫抽象層。先直接串一家,第二家要接的時候再重構——那時你才知道真正需要抽象什麼。
下一步

這個主題還有更深入的實戰教程

VIP 專區收錄 50 篇進階內容:架構設計、生產環境取捨、成本與合規。 每週五新增 3 篇。

看訂閱方案 → 先逛逛 VIP 專區