Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Dify 的提供商抽象层设计:我们如何同时支持数十个 LLM 并保持松散耦合

简介

对于企业人工智能平台来说,“使用哪个LLM”并不是一次性的决定。由于成本优化、性能要求的变化、新型号的引入、因法规遵从而导致的供应商变化等,型号切换不断发生。

Dify 的 Provider 抽象层是对这一现实的结构性回答。本文从架构设计的角度阐述了Dify如何抽象LLM Provider,并实现应用层和模型层之间的松耦合。


1.什么是Provider抽象层?

1.1 问题定义

直接调用LLM的应用程序会遇到以下问题:

# 抽象層がない場合の典型的なコード
import openai

# OpenAI に直接依存
response = openai.ChatCompletion.create(
    model="gpt-4",
    messages=[{"role": "user", "content": prompt}],
    temperature=0.7,
)

此实现在以下方面容易受到攻击:

  • 更改模型时需要修改整个应用程序代码
  • API密钥管理分散在应用程序内
  • 吸收应用端各提供商的API规范差异(参数名称、响应格式)
  • 难以统一处理速率限制、重试和回退

1.2 Dify 解决方案:分离提供者层

Dify 在应用层(Workflow/Agent/Chat)和模型调用层之间放置了一个 Provider 抽象层:

graph TB
    subgraph "Application Layer"
        W[Workflow]
        AG[Agent]
        CH[Chat App]
    end
    
    subgraph "Provider Abstraction Layer"
        direction TB
        MI[Model Interface<br/>統一 API]
        MC[Model Configuration<br/>Workspace レベル管理]
        MR[Model Runtime<br/>実行・リトライ・制御]
    end
    
    subgraph "Model Providers"
        OP[OpenAI]
        AZ[Azure OpenAI]
        AN[Anthropic]
        GG[Google Gemini]
        OL[Ollama / Local]
        CU[Custom Provider]
    end
    
    W --> MI
    AG --> MI
    CH --> MI
    MI --> MC
    MC --> MR
    MR --> OP
    MR --> AZ
    MR --> AN
    MR --> GG
    MR --> OL
    MR --> CU
    
    style MI fill:#69b,stroke:#333,color:#fff

2. 架构细节

2.1 模型提供者注册结构

📖 注:以下 YAML 是 Dify Provider 抽象层的概念模型示意,用于说明设计意图。Dify 1.x 实际的 Plugin Manifest 结构请参考官方仓库

  • 主清单 manifest.yaml(包含 plugin 元信息、版本、依赖)
  • 工具 / 模型 provider 的具体字段定义见 api/core/plugin/entities/plugin.pyPluginDeclaration
  • Model Runtime 基类位于 api/core/entities/model_entities.pyProviderEntityModelTypeProviderModel),底层依赖 graphon
  • 凭证字段实际命名为 credentials_schema(工具 / Provider 通用),ProviderEntity 嵌套字段为 provider_credential_schema.credential_form_schemas
# Provider 抽象的概念模型(不要直接照抄到 plugin manifest)
provider:
  name: "openai"
  label: "OpenAI"
  supported_model_types:
    - llm
    - text-embedding
    - speech2text
    - tts
  credentials_schema:   # 实际字段名(注意是复数)
    - name: api_key
      type: secret
      required: true
    - name: organization_id
      type: string
      required: false
  models:
    - name: "gpt-4o"
      type: llm
      features:
        - function_calling
        - vision
      context_length: 128000
      pricing:
        input: 0.005   # per 1K tokens
        output: 0.015

本设计有以下意图:

设计元素目的
supported_model_types统一管理同一提供商提供的不同能力(LLM、Embedding、TTS)
credentials_schema定义如何管理每个提供商的 API 密钥并在工作区级别集中管理它们
features应用层可以通过声明函数调用、视觉等能力来判断兼容性
context_length在设计工作流程时将上下文长度公开为元数据并可视化约束
pricing实现成本估算并支持公司的模型选择决策

2.2 模型接口统一

Provider抽象层的核心是能够通过统一的接口调用不同Provider的API:

# Dify の Model Interface 概念モデル
class ModelInterface:
    """全 LLM Provider に共通のインターフェース"""
    
    def invoke(
        self,
        model: str,
        credentials: dict,
        prompt_messages: list[PromptMessage],
        model_parameters: dict,
        tools: list[Tool] | None = None,
        stop: list[str] | None = None,
        stream: bool = False,
        user: str | None = None,
    ) -> LLMResult | Generator[LLMResultChunk]:
        """
        統一的なモデル呼び出しインターフェース。
        プロバイダー固有のパラメータ変換は内部で処理される。
        """
        pass
    
    def get_num_tokens(
        self,
        model: str,
        credentials: dict,
        prompt_messages: list[PromptMessage],
    ) -> int:
        """トークン数の事前計算"""
        pass
    
    def validate_credentials(
        self,
        model: str,
        credentials: dict,
    ) -> None:
        """クレデンシャルの事前検証"""
        pass

2.3 参数映射实际情况

每个提供商的 API 使用的参数名称和格式略有不同。 Provider 抽象层透明地对此进行了转换:

定义统一参数开放人工智能人择Azure 开放人工智能奥拉玛
temperaturetemperaturetemperaturetemperaturetemperature
max_tokensmax_tokensmax_tokensmax_tokensnum_predict
stopstopstop_sequencesstopstop
toolstoolstoolstoolstools
streamstreamstreamstreamstream
response_formatresponse_format不适用(替代方法)response_formatformat

3.工作区级模型管理

3.1 为什么是工作区级别?

在 Dify 中,模型提供程序设置是在 工作区基础 上管理的,而不是在应用程序基础上进行管理。这一设计决定有明确的理由:

graph TB
    subgraph "Workspace A(営業部門)"
        APP1[顧客対応 Bot]
        APP2[提案書生成]
        APP3[FAQ 検索]
        
        subgraph "Workspace A の Model Config"
            M1[OpenAI GPT-4o<br/>API Key: ****]
            M2[Azure OpenAI<br/>Endpoint: jpeast]
        end
    end
    
    subgraph "Workspace B(開発部門)"
        APP4[コードレビュー]
        APP5[ドキュメント生成]
        
        subgraph "Workspace B の Model Config"
            M3[Anthropic Claude<br/>API Key: ****]
            M4[Ollama Llama3<br/>Local]
        end
    end
    
    APP1 --> M1
    APP2 --> M2
    APP3 --> M1
    APP4 --> M3
    APP5 --> M4
设计意图描述
API 密钥集中管理工作区管理员集中管理 API 密钥,无需将其分发到每个应用程序
成本可视化了解 Workspace 的代币消耗和成本
部门治理可用型号可以受部门限制
更高效的模型切换只需更改工作区设置,它将反映在所有应用程序中

3.2 模型切换用例

企业实际切换模式的典型场景:

  1. 成本优化:从 GPT-4o 切换到 GPT-4o-mini(降低成本,同时保证准确性)
  2. 监管准备:从外部 API 迁移到本地本地 LLM
  3. 性能提升:新机型发布时逐步过渡
  4. 故障响应:在特定提供商发生故障时切换到后备目的地
  5. 多模型策略:根据任务类型使用最优模型

4. 插件架构:可扩展性设计

4.1 使用插件添加自定义提供程序

Dify 允许您通过插件机制添加不支持开箱即用的模型提供程序:

graph LR
    subgraph "Dify Core"
        PA[Plugin Architecture]
        MR[Model Runtime]
    end
    
    subgraph "Built-in Providers"
        OP[OpenAI]
        AN[Anthropic]
        AZ[Azure]
    end
    
    subgraph "Custom Plugins"
        CP1[社内 LLM Gateway]
        CP2[国産 LLM<br/>ELYZA / PLaMo]
        CP3[vLLM Cluster]
    end
    
    PA --> OP
    PA --> AN
    PA --> AZ
    PA --> CP1
    PA --> CP2
    PA --> CP3
    PA --> MR

4.2 模型设计规则

官方文档中发布的模型设计规则定义了插件开发者必须遵循的接口约定:

# Model Plugin の必須実装項目
model_plugin:
  # 1. Provider 定義
  provider_manifest:
    - プロバイダー名・アイコン・説明
    - サポートするモデルタイプ
    - クレデンシャルスキーマ
  
  # 2. モデル定義
  model_manifest:
    - モデル名・バージョン
    - 能力宣言 (features)
    - パラメータ制約 (context_length, max_tokens)
    - 価格情報(任意)
  
  # 3. Runtime 実装
  runtime:
    - invoke(): 同期/ストリーミング呼び出し
    - get_num_tokens(): トークン計算
    - validate_credentials(): 認証情報検証

通过遵循此约定,您的自定义提供程序将自动与所有 Dify 功能集成,例如工作流节点中的模型选择、代理中的模型规范、知识库中的嵌入模型选择等。

4.3 插件分离带来的稳定性

📖 前提:进程隔离是 Dify 1.0 引入 Plugin Daemon 之后的特性。0.x 版本的 Provider 不是进程隔离的,自定义 Provider 的崩溃可能影响主进程。Enterprise 部署默认启用 Plugin Daemon。

启用 Plugin Daemon 后,插件作为独立进程运行,自定义 Provider 中的错误或故障不会影响 Dify 核心:

建筑特色效果
进程隔离 (1.0+)插件崩溃不会蔓延到核心(前提:启用 Plugin Daemon)
版本无关Plugin和Dify Core可独立更新
资源限制每个插件的内存和 CPU 都可以受到限制
安全边界插件凭证与核心凭证分离

5. 设计权衡

5.1 抽象的限制

Provider抽象层吸收了许多差异,但不能使它们全部透明:

差异类型抽象的可能性如何应对
基本聊天完成完全可抽象统一接口
函数调用几乎可以抽象工具定义的统一格式
视觉(图像输入)条件抽象带有功能标志的功能声明
上下文长度作为元数据进行管理检查应用程序端的约束
速率限制依赖于提供商在运行时层重试/排队
JSON 模式实施情况因提供商而异部分抽象+回退
多模式(音频/视频)供应商之间的巨大差异对每种模型类型的单独支持
微调API每个提供商完全不同不抽象

5.2 处理“最小公约数”问题

抽象层的一个典型风险是它们只能提供“最低公分母”API,而无法利用每个提供商的独特功能。 Dify 通过 特征标志 + 模型参数扩展 解决了这个问题:

# Feature フラグによる能力の動的チェック
model_config = get_model_config("gpt-4o")

if "function_calling" in model_config.features:
    # Function Calling 対応のフローを実行
    result = invoke_with_tools(model, tools, prompt)
elif "vision" in model_config.features:
    # Vision 対応のフローを実行
    result = invoke_with_images(model, images, prompt)
else:
    # 基本的な Text Completion のみ
    result = invoke_text(model, prompt)

6. Provider抽象层在企业中的战略价值

6.1 避免供应商锁定

graph TB
    subgraph "ベンダーロックインの比較"
        direction LR
        subgraph "直接統合"
            A1[App] -->|"OpenAI SDK"| B1[OpenAI]
            A1 -.->|"移行コスト: 高"| C1[Anthropic]
        end
        
        subgraph "Dify Provider 抽象層"
            A2[App] --> D2[Provider Layer]
            D2 -->|"設定変更のみ"| B2[OpenAI]
            D2 -->|"設定変更のみ"| C2[Anthropic]
            D2 -->|"設定変更のみ"| E2[Azure]
        end
    end

6.2 多模型策略的实现

有远见的公司正在根据任务类型而不是单一模型采用多模型策略:

任务类型推荐型号选择理由
复杂的推理与分析GPT-4o / Claude Opus精度要求高
大批量常规加工GPT-4o-mini / Claude Haiku成本效益
日本专业任务国内LLM / Qwen日本表演
敏感数据处理奥拉马(本地)无法向外发送数据
嵌入文本嵌入-3-小成本与准确性之间的平衡
图像识别GPT-4o / Gemini Pro 视觉多式联运支持

Dify 的 Provider 抽象层允许您为同一工作流中的不同节点指定不同的模型。这使得上述多模型策略可以在工作流设计层面得以实现。

6.3 成本管理和治理

工作区级别的提供商管理自然提供以下治理功能:

  • 使用情况可视化:按工作空间/应用程序/用户跟踪令牌消耗情况
  • 预算控制:设置每个工作区的使用限制
  • 模型使用政策:仅允许在特定工作空间中使用特定模型的限制
  • 审计跟踪:记录哪些用户向哪些模型发送哪些查询

7. 与其他平台的比较

项目Dify浪链亚马逊基岩Azure 人工智能工作室
抽象层粒度供应商+模型连锁/LLM班API网关集线器+端点
GUI 中的模型管理是的没有是的是的
定制供应商可通过插件添加Python 类实现自定义模型导入自定义端点
工作区单元管理是的没有账户单位资源组单位
功能标志以模型单位声明无(由代码确定)模型单位模型单位
开源软件是的是的没有没有
运营成本中型(自托管)低(框架)高(AWS 计费)高(Azure 计费)

总结

Dify 的 Provider 抽象层在“支持多模型”的表面特征背后有以下设计理念:

  1. 应用层和模型层清晰分离:应用业务逻辑不依赖于模型选择
  2. 工作区级统一管理:API密钥管理、成本管理和治理集中于一处
  3. 使用插件的扩展性:可以使用相同的接口添加标准不支持的模型。
  4. 特征标志的灵活性:每个模型特定特征的抽象和利用

对于企业来说,Provider抽象层的价值不在于可以连接的模型数量,而在于能够选择、切换和使用模型作为业务决策。 Dify 的设计允许在管理屏幕上做出这些决策,而无需更改任何代码。


参考资料

-Model Providers - Dify Docs -Model Designing Rules -Model API Interface (Schema) -Workspace Overview - Dify Docs