# 《WaLiAPI - 本地 LLM API 网关》第1-3节:渠道适配器模式

作者:小傅哥
博客:https://bugstack.cn (opens new window)

沉淀、分享、成长,让自己和他人都能有所收获!😄

大家好,我是技术UP主小傅哥。

上一节我们完成了数据库层。这一节进入 WaLiAPI 最核心的设计——渠道适配器模式。这是整个网关的灵魂:对外暴露统一的 OpenAI 协议,对内对接 N 家不同的 AI 供应商。

# 一、本章诉求

  1. 理解适配器模式(Adaptor Pattern)在 API 网关中的应用
  2. 定义 Adaptor trait——所有渠道适配器的统一抽象
  3. 实现 OpenAI 适配器(透传 + 模型映射)
  4. 实现 DeepSeek 适配器(OpenAI 兼容协议的复用)
  5. 实现渠道类型的元数据管理(channel_types)

# 二、为什么要用适配器模式?

# 2.1 问题场景

假设不用适配器模式,我们的代码会变成什么样?

// ❌ 反面教材:if-else 地狱
async fn forward(channel_type: &str, request: &Request) -> Response {
    if channel_type == "openai" {
        // OpenAI 的请求逻辑
    } else if channel_type == "claude" {
        // Claude 的请求逻辑:x-api-key 头、anthropic-version、消息格式转换...
    } else if channel_type == "gemini" {
        // Gemini 的请求逻辑:URL 带 key 参数、contents/parts 格式...
    } else if channel_type == "deepseek" {
        // ...
    }
}
1
2
3
4
5
6
7
8
9
10
11
12

这样的代码有几个致命问题:

  • 违反开闭原则:每加一个供应商就要改核心转发函数
  • 职责不单一:一个函数要懂所有供应商的协议细节
  • 无法独立测试:想测 Claude 的逻辑必须把整个函数跑起来

# 2.2 适配器模式解法

每家供应商是一个独立的"适配器",实现统一的接口:

                    ┌─────────────────┐
   统一 OpenAI 请求  │   Proxy 代理层   │  统一 OpenAI 响应
        ──────────→ │                 │ ──────────→
                    │  get_adaptor()  │
                    └────────┬────────┘
                             │ trait Adaptor
        ┌──────────┬─────────┼─────────┬──────────┐
        ↓          ↓         ↓         ↓          ↓
   ┌─────────┐┌─────────┐┌────────┐┌────────┐┌────────┐
   │ OpenAI  ││DeepSeek ││ Claude ││ Gemini ││ Custom │
   │ Adaptor ││ Adaptor ││Adaptor ││Adaptor ││Adaptor │
   └────┬────┘└────┬────┘└───┬────┘└───┬────┘└───┬────┘
        ↓         ↓         ↓          ↓
   api.openai  deepseek  anthropic  google    任意兼容端点
1
2
3
4
5
6
7
8
9
10
11
12
13
14

Proxy 层只依赖 Adaptor trait 这个抽象,不关心具体是哪家供应商。新增供应商 = 新增一个实现 trait 的结构体 + 在工厂函数中注册一行。