基于 langgenius/dify 代码仓库 v1.13.x 版本的系统性源码分析与落地实战手册 分析基线目录:
d:/opencode/q/dify/
目录
- 项目定位与总体架构
- 仓库结构与顶层组织
- 后端 API 架构(api/)——DDD 分层剖析
- 后端启动链路与扩展机制
- Core 核心引擎深度解读
- 数据模型与数据库设计
- Celery 任务队列与异步子系统
- 前端 Web 架构(web/)
- Docker 部署拓扑与生产化配置
- 生产环境最佳实践与运维手册
- 二次开发指南:扩展节点、工具、模型
- 典型业务场景案例
- 性能调优、安全加固与排障手册
- 总结:Dify 的设计哲学
1. 项目定位与总体架构
1.1 定位
Dify(读作 /ˈdɪfaɪ/,取自 "Define + Modify") 是由 LangGenius 开源的 LLM 应用开发平台(LLMOps Platform)。它不是又一个 LangChain 封装,而是定位于:
- 面向"应用生产"的 BaaS + LLMOps:把 Prompt 工程、RAG、Agent、工作流、可观测性、权限、计费、多租户等能力一次性交付
- 低代码可视化编排:工作流画布(基于 ReactFlow)让业务人员也能搭建 AI 应用
- 多模型统一接入:100+ 模型提供商,通过统一 Model Runtime 抽象
- 企业级运行时:多租户、RBAC、API Key、SSO、License Gate、OTEL 观测、Sentry 告警
1.2 五层总体架构
┌──────────────────────────────────────────────────────────┐
│ 浏览器 / 第三方客户端 │
└──────────────────────────────────────────────────────────┘
│
HTTPS / WSS
│
┌──────────────────────────────────────────────────────────┐
│ Nginx (反向代理 + SSL 终止) │
└──────────────────────────────────────────────────────────┘
│ │
│ /console/api /v1 /api │ 静态资源
▼ ▼
┌──────────────────┐ ┌────────────────────┐
│ dify-api (Flask)│ │ dify-web (Next.js)│
│ ───────────────│ │ ──────────────────│
│ Controllers │ │ App Router │
│ ↓ │ │ ReactFlow Editor │
│ Services │ │ Zustand/Jotai │
│ ↓ │ │ ORPC + SWR │
│ Core (Engine) │ └────────────────────┘
│ ↓ │
│ Models / Repos │
└──────────────────┘
│ │ │ │
│ │ │ └──→ Celery Worker (异步任务:RAG 索引/工作流)
│ │ │ │
│ │ │ ▼
│ │ │ ┌──────────────┐
│ │ │ │ Redis │(Broker + Cache + Rate Limit)
│ │ │ └──────────────┘
│ │ ▼
│ │ ┌────────────────────┐
│ │ │ Plugin Daemon (Go)│(插件运行时)
│ │ └────────────────────┘
│ ▼
│ ┌────────────────────┐
│ │ Sandbox (Rust+Py) │(代码节点沙箱)
│ └────────────────────┘
│ │
│ └──→ SSRF Proxy (Squid) ──→ Internet
▼
┌──────────────────────────────────────────────────────────┐
│ PostgreSQL │ Weaviate/Qdrant/PGVector │ Object Store │
│ (元数据) │ (向量数据库) │ (S3/本地FS) │
└──────────────────────────────────────────────────────────┘
1.3 核心能力矩阵
| 能力 | 实现位置 | 关键技术 |
|---|---|---|
| 应用编排(5 种) | core/app/apps/{chat,completion,agent_chat,advanced_chat,workflow} | AppRunner + QueueManager |
| 工作流 DAG | core/workflow/ + 外部 graphon 库 | Graph + NodeFactory + VariablePool |
| RAG 管道 | core/rag/ | Extractor + Splitter + Embedding + VDB |
| Agent | core/agent/{fc,cot}_agent_runner.py | Function Call + CoT/ReAct |
| 模型统一接入 | core/model_manager.py + core/provider_manager.py | 策略 + 工厂 + 负载均衡 |
| 工具体系 | core/tools/ | 5 类 Provider(Builtin/API/Plugin/Workflow/MCP) |
| 插件运行时 | core/plugin/ + 独立 Go Daemon | RPC 进程隔离 |
| 异步调度 | tasks/ + schedule/ | Celery + Redis |
| 多租户 | models/account.py:Tenant | 所有资源 tenant_id 外键 |
| 可观测性 | extensions/ext_otel.py ext_sentry.py | OTEL + Sentry |
2. 仓库结构与顶层组织
dify/
├── api/ # 后端 Flask 应用(DDD 分层)
├── web/ # 前端 Next.js 应用
├── docker/ # Docker Compose 部署模板
├── sdks/ # 各语言 SDK(python/node/php 等)
├── packages/ # 前端内部 workspace 包
├── e2e/ # 端到端测试
├── dev/ # 开发脚本
├── docs/ # 多语言 README
├── images/ # 宣传图
├── Makefile
├── README.md
├── CLAUDE.md # 指向 AGENTS.md
└── AGENTS.md # 顶层贡献守则(DDD、TDD、TypedDict 等)
顶层 AGENTS.md 直接声明了工程规范:
- 后端遵循 DDD + Clean Architecture
- 异步任务通过 Celery + Redis Broker
- 测试必须 TDD(红 → 绿 → 重构)
- 严禁
Any,优先TypedDict - 前端 i18n 强制
web/i18n/en-US/
这些准则体现在整个 codebase 的每一层实现中。
3. 后端 API 架构(api/)——DDD 分层剖析
3.1 五层架构地图
api/
├── controllers/ ← Presentation(HTTP 层)
│ ├── console/ # 控制台 API(管理员/工作空间)
│ ├── service_api/ # 外部服务 API(Bearer API Key)
│ ├── web/ # Web App 嵌入 API(EndUser 上下文)
│ ├── inner_api/ # 内部服务间 RPC
│ ├── files/ # 文件上传下载
│ ├── trigger/ # Webhook 触发
│ └── mcp/ # MCP 协议
├── services/ ← Application(用例编排)
│ ├── app_service.py
│ ├── workflow_service.py
│ ├── dataset_service.py
│ ├── conversation_service.py
│ ├── account_service.py
│ └── ...50+ 服务
├── core/ ← Domain / Engine(核心业务规则)
│ ├── app/
│ ├── workflow/
│ ├── rag/
│ ├── agent/
│ ├── tools/
│ ├── plugin/
│ ├── model_manager.py
│ ├── provider_manager.py
│ └── ...
├── models/ ← Data(SQLAlchemy ORM)
│ ├── model.py
│ ├── account.py
│ ├── dataset.py
│ └── workflow.py
├── repositories/ ← Repository(ORM 抽象)
│ └── sqlalchemy_*_repository.py
├── tasks/ ← Celery 异步任务
├── schedule/ ← 定时任务
├── extensions/ ← Infrastructure(Flask 扩展)
│ ├── ext_database.py
│ ├── ext_redis.py
│ ├── ext_celery.py
│ ├── ext_login.py
│ ├── ext_storage.py
│ ├── ext_blueprints.py
│ └── ...
├── events/ ← 领域事件
├── factories/ ← 工厂(文件、对象)
├── migrations/ ← Alembic 迁移
├── contexts/ ← 请求上下文变量
├── configs/ ← Pydantic 配置分组
├── app.py ← 入口
├── app_factory.py ← 工厂函数 + 扩展装配
├── dify_app.py ← DifyApp(Flask 子类)
└── celery_entrypoint.py
3.2 Controllers —— HTTP 表现层
api/extensions/ext_blueprints.py 负责注册 6 大 Blueprint,每个带差异化 CORS 策略:
| Blueprint | URL 前缀 | 认证方式 | 目标用户 |
|---|---|---|---|
console_app_bp | /console/api | JWT(Passport) | 控制台管理员 |
service_api_bp | /v1 | Bearer API Key | 第三方开发者 |
web_bp | /api | WebApp Passport(可选) | C 端访客 |
files_bp | /files | 签名 URL / Token | 文件直传 |
inner_api_bp | 内部 | Inner API Key | 插件守护进程 |
mcp_bp | /mcp | 令牌 | MCP 客户端 |
控制台 API 按领域拆分子目录: app/、auth/、datasets/、workspace/、billing/、explore/。
以 创建应用 为例(api/controllers/console/app/app.py):
@login_required # Flask-Login
@account_initialization_required # 账号激活校验
@cloud_edition_billing_resource_check('apps') # 计费资源校验
@is_admin_or_owner_required # RBAC
def post(self):
payload = CreateAppPayload.parse_obj(request.json)
app = AppService().create_app(payload, current_user)
return marshal(app, app_fields), 201
关键点:
- 装饰器堆叠实现 AOP:认证 → 激活 → 计费 → 权限
- 使用 Flask-RESTX 构建资源类
- Pydantic 做入参校验,Flask-RESTX
fields做出参序列化
3.3 Services —— 应用层编排
Services 层负责用例编排,协调 Core 引擎、Model、Repository、Task、Event,不包含 HTTP 细节。
典型:api/services/workflow_service.py(约 1700 行)
class WorkflowService:
def draft_workflow_version_to_graph(self, ...) -> Graph: ...
def execute(self, ...) -> Generator[GraphEngineEvent, None, None]: ...
def publish_draft(self, ...) -> WorkflowVersion: ...
服务调用图:
Controller
↓
WorkflowService.execute()
├──→ core.workflow.workflow_entry.WorkflowEntry
├──→ core.model_manager.ModelManager
├──→ core.tools.tool_manager.ToolManager
├──→ repositories.WorkflowExecutionRepository(持久化)
├──→ tasks.async_workflow_tasks(异步分发)
└──→ events.app_was_updated(领域事件)
api/services/async_workflow_service.py 是生产环境下的关键:它不执行工作流,只是创建 WorkflowTriggerLog 并根据租户计划(sandbox / team / professional)路由到不同的 Celery 队列,立刻返回 trigger_log_id。客户端轮询或接收 Webhook 拉取结果。
3.4 DDD 的落地技巧
- 依赖注入:Service 构造函数显式接收 Repository / Manager,便于测试替换
- 领域事件:
events/目录发布app_was_created、document_was_deleted,下游(通知、埋点)订阅 - 上下文变量:api/contexts/wrapper.py 的
RecyclableContextVar承载current_user、current_tenant、request_id,请求结束自动清理 - 多租户隔离:所有核心表均带
tenant_id,查询层默认按当前租户过滤,防止越权
4. 后端启动链路与扩展机制
4.1 入口 api/app.py
# 根据命令行参数分叉:迁移 vs 正常启动
if flask_migrate:
flask_app = create_migrations_app()
else:
socketio_app, flask_app = create_app()
celery = flask_app.extensions["celery"]
入口同时绑定 WebSocket (SocketIO) 与 Flask,用 Gevent 事件循环,监听 0.0.0.0:5001。
4.2 工厂函数 api/app_factory.py
关键流程(第 49–231 行):
- 实例化 DifyApp(Flask 子类):api/dify_app.py 仅加了
login_manager: DifyLoginManager类型提示,提供类型安全 dify_config.model_dump()加载 Pydantic 配置:聚合configs/deploy/、feature/、middleware/、extra/、observability/、enterprise/、packaging/各子配置before_request:初始化日志上下文 + 线程回收 + 企业证书检查(INACTIVE/EXPIRED 时除白名单端点外全部拦截)after_request:注入X-Trace-Id/X-Span-Idinitialize_extensions():按严格顺序装配 28 个扩展
4.3 扩展装配顺序(关键)
ext_timezone → ext_logging → ext_warnings → ext_import_modules
→ ext_orjson → ext_forward_refs → ext_set_secretkey → ext_compress
→ ext_code_based_extension
→ ext_database (SQLAlchemy + gevent 兼容)
→ ext_app_metrics → ext_migrate
→ ext_redis → ext_storage (依赖 redis) → ext_logstore (依赖 storage)
→ ext_celery (依赖 logstore)
→ ext_login → ext_mail → ext_hosting_provider
→ ext_sentry → ext_proxy_fix
→ ext_blueprints (最后注册,此时依赖都就绪)
→ ext_commands → ext_fastopenapi → ext_otel
→ ext_enterprise_telemetry → ext_request_logging → ext_session_factory
注意 gevent 兼容性 (api/extensions/ext_database.py):注册了 SQLAlchemy Pool reset 事件监听器,在 greenlet 切换时安全 rollback,防止连接状态泄漏。这是高并发场景稳定运行的关键。
4.4 配置系统
api/configs/app_config.py 的 DifyConfig 继承 BaseSettings,聚合多个配置分组。通过 Pydantic 自动从 .env 和环境变量解析,支持 Apollo / Nacos 远端配置中心。
5. Core 核心引擎深度解读
api/core/ 共 500+ Python 文件,是 Dify 的"发动机"。
5.1 应用运行器(App Runner)
5 种应用类型对应 5 套运行器:
| 类型 | 运行器 | 用途 |
|---|---|---|
CHAT | ChatAppRunner | 多轮对话 |
COMPLETION | CompletionAppRunner | 单次生成 |
AGENT_CHAT | AgentChatAppRunner | Agent 循环决策 |
ADVANCED_CHAT | AdvancedChatAppRunner | 高级聊天(绑定工作流) |
WORKFLOW | WorkflowAppRunner | 纯工作流 |
基类 api/core/app/apps/base_app_runner.py 定义:
class AppRunner:
def recalc_llm_max_tokens(...) # 根据历史长度动态调整 max_tokens
def organize_prompt_messages(...) # 系统提示 + 历史 + 上下文 + 查询
def direct_output(...) # 直接输出(moderation 命中时)
AppQueueManager —— 事件流核心
api/core/app/apps/base_app_queue_manager.py
class AppQueueManager:
def publish(self, event: QueueEvent, publish_from): ...
事件体系:
| 事件 | 语义 |
|---|---|
QueueLLMChunkEvent | LLM 流式 token |
QueueMessageEndEvent | 消息结束 |
QueueAgentMessageEvent | Agent 思考 / 工具调用 |
QueueMessageFileEvent | 附件 |
QueueWorkflowStartedEvent | 工作流开始 |
QueueNodeStartedEvent / QueueNodeSucceededEvent | 节点生命周期 |
事件消费端把事件转译成 SSE(Server-Sent Events) 流回前端,驱动工作流画布节点高亮、聊天窗口流式输出。
5.2 工作流引擎(Workflow Engine)
核心哲学:把整个应用建模为一张有向图,节点是执行单元,边是数据流。这张图可序列化为 JSON DSL,可以在前端画布上可视化编辑。
关键组件
| 组件 | 文件 | 职责 |
|---|---|---|
WorkflowEntry | api/core/workflow/workflow_entry.py | 工作流入口,初始化 GraphEngine |
DifyNodeFactory | api/core/workflow/node_factory.py | 节点工厂(自注册) |
VariablePool | 来自 graphon.VariablePool | 跨节点变量容器 |
GraphRuntimeState | 来自 graphon | 运行时状态机 |
| Layers | graphon | 可堆栈中间件 |
GraphEngine 中间件堆栈
engine = GraphEngine(graph, variable_pool, state)
engine.use(DebugLoggingLayer()) # 调试日志
engine.use(ExecutionLimitsLayer(...)) # 最大步数 / 最大耗时
engine.use(LLMQuotaLayer(...)) # LLM 配额
engine.use(ObservabilityLayer(...)) # OTEL Trace
每层封装 run() 方法,实现类似 Express/Koa 的洋葱模型。
节点类型(40+)
启动类(_START_NODE_TYPES):
START——标准入口DATASOURCE——数据源触发WEBHOOK/SCHEDULE/PLUGIN——三类触发器
流控类:IF_ELSE、ITERATION、LOOP、VARIABLE_AGGREGATOR
AI 类:LLM、AGENT、PARAMETER_EXTRACTOR、QUESTION_CLASSIFIER
集成类:HTTP_REQUEST、TOOL、CODE、TEMPLATE_TRANSFORM
知识类:KNOWLEDGE_RETRIEVAL、KNOWLEDGE_INDEX
输出类:END、ANSWER
节点类自动通过 Node.register() 注册到 Node.get_node_type_classes_mapping(),支持 多版本共存(v1、latest),运行时按版本匹配。
变量池与 Selector
变量池使用 列表路径 作为 key:
pool.add(["llm_1", "output"], "..."])
pool.get(["llm_1", "structured_output", "field_name"])
前端 {{#llm_1.output#}} 解析成 VariableSelector = ["llm_1", "output"],底层用同一套访问协议。
事件流
GraphEngineEvent(基类)
├── GraphNodeEventBase
│ ├── WorkflowNodeExecutionStarted
│ ├── WorkflowNodeExecutionSucceeded
│ ├── WorkflowNodeExecutionFailed
│ └── NodeStreamChunkEvent(流式输出)
├── GraphRunSucceededEvent
├── GraphRunFailedEvent
└── GraphEngineMetricsEvent
WorkflowEntry.run() 返回 Generator[GraphEngineEvent],上层订阅并持久化 WorkflowNodeExecutionModel,同时 Push 到前端 SSE。
5.3 Agent 运行时(Agent Runtime)
api/core/agent/ 提供两种 Agent 策略:
FC Agent(Function Calling)
api/core/agent/fc_agent_runner.py
while True:
result = llm.invoke(messages, tools=tool_schemas, stream=True)
tool_calls = parse_tool_calls(result)
if not tool_calls:
break
for tc in tool_calls:
tool = tool_manager.get(tc.name)
obs = tool.invoke(tc.params)
messages.append(ToolPromptMessage(obs))
依赖 OpenAI / Anthropic 原生函数调用能力,Token 效率高、稳定性好,推荐优先使用。
CoT Agent(Chain-of-Thought / ReAct)
api/core/agent/cot_agent_runner.py
使用固定 Prompt 模板约束 LLM 输出结构:
Thought: 我需要查询天气
Action: get_weather
Action Input: {"city": "Beijing"}
Observation: 晴朗,25°C
Thought: 我已经有信息了
Final Answer: 今天北京晴朗,25°C
适合不支持原生 Function Call 的模型(LLaMA、ChatGLM 等)。
TokenBufferMemory
api/core/memory/token_buffer_memory.py
def get_history_prompt_messages(
max_token_limit: int = 2000,
message_limit: int = 500,
) -> Sequence[PromptMessage]:
从最新消息倒序累加,超出 token 预算则丢弃最早消息。支持多模态(图像内容也计入 Token)。
5.4 RAG 管道与向量数据库
api/core/rag/ 是 Dify 知识库能力的核心。
子目录地图
rag/
├── extractor/ # 文档提取(PDF/Excel/Notion/Markdown/HTML/Firecrawl/JinaReader)
├── splitter/ # 文本分割(递归字符/句子/ETC 中文/Token)
├── cleaner/ # 文本清洗(去 HTML、去脚注、去重复)
├── embedding/ # 嵌入
│ ├── embedding_base.py
│ ├── cached_embedding.py # Redis 缓存层
│ └── retrieval.py
├── datasource/
│ ├── vdb/ # 向量数据库适配器
│ │ ├── vector_factory.py
│ │ ├── vector_base.py
│ │ ├── qdrant_vector.py
│ │ ├── milvus_vector.py
│ │ ├── weaviate_vector.py
│ │ ├── pgvector/
│ │ ├── chroma_vector.py
│ │ ├── tidb_on_qdrant_vector.py
│ │ ├── oracle_vector.py
│ │ └── ...(20+ VDB)
│ ├── keyword/ # Jieba 分词 + BM25 倒排
│ └── retrieval_service.py
├── rerank/ # 重排
│ ├── rerank_model.py # 模型重排(Cohere/Jina)
│ └── weight_rerank.py # 权重加权
├── index_processor/ # 索引构建策略
│ └── processor/
│ ├── paragraph_index_processor.py
│ ├── qa_index_processor.py
│ └── parent_child_index_processor.py
└── retrieval/ # 检索路由
├── dataset_retrieval.py
└── router/ # 多数据集路由
支持的向量数据库
通过 api/core/rag/datasource/vdb/vector_type.py:
QDRANT、MILVUS、WEAVIATE、PGVECTOR、CHROMA、PGVECTO_RS、TIDB_VECTOR、TIDB_ON_QDRANT、ORACLE、RELYT、OPENSEARCH、ELASTICSEARCH、TENCENT、ANALYTICDB、COUCHBASE、VIKINGDB、LINDORM、OCEANBASE、BAIDU、UPSTASH、MYSCALE、VASTBASE 等。
统一接口 VectorBase:
class VectorBase:
def create(self, texts, embeddings, **kwargs): ...
def add_texts(self, documents, embeddings, **kwargs): ...
def search_by_vector(self, query_vector, **kwargs): ...
def search_by_full_text(self, query, **kwargs): ...
def delete_by_ids(self, ids): ...
def delete_by_metadata_field(self, key, value): ...
RetrievalService 检索管道
api/core/rag/datasource/retrieval_service.py
用户查询
↓
RetrievalService.retrieve(retrieval_method=HYBRID)
↓
ThreadPoolExecutor 并发:
├─ Vector.search_by_vector(embed(query)) # 语义召回
└─ Vector.search_by_full_text(query) # 全文召回
↓
DataPostProcessor:
├─ 去重(按 segment_id)
├─ Rerank(模型重排 或 权重加权)
└─ score_threshold 过滤 + top_k 截断
↓
return list[Document]
索引策略(IndexProcessor)
- Paragraph:段落级分块,最常用
- QA:LLM 自动为每段生成 QA 对后索引,召回率更高
- Parent-Child:父子分段,父段用于上下文,子段用于精确召回
嵌入缓存
api/core/rag/embedding/cached_embedding.py 将文本哈希作为 Redis key,避免重复 embedding。文档重建索引时节省 70%+ 调用费用。
5.5 Model Runtime 与 Provider 体系
ModelManager
api/core/model_manager.py 提供统一模型调用入口:
class ModelManager:
def get_model_instance(self, tenant_id, provider, model_type, model) -> ModelInstance: ...
class ModelInstance:
def invoke_llm(prompt_messages, tools=None, stream=True, ...) -> Union[LLMResult, Generator]: ...
def invoke_text_embedding(texts) -> TextEmbeddingResult: ...
def invoke_rerank(query, docs) -> RerankResult: ...
def invoke_moderation(text) -> ModerationResult: ...
def invoke_tts(text) -> Generator[bytes]: ...
def invoke_speech2text(file) -> str: ...
ProviderManager
api/core/provider_manager.py 管理租户级配置:
- Hosting Provider:Dify 云服务免费额度 (quota_type/quota_limit)
- Custom Provider:用户自己填写 API Key
- 负载均衡:一个模型配置多组凭证,轮询使用
- 配额限流:按租户/模型粒度的日请求数/Token 数配额
Provider 注册机制
Provider 定义在独立的 graphon 库 或 Plugin 中,每个 Provider 包含:
<provider_name>/
├── provider.yaml # 元数据(名称/图标/支持模型类型)
├── _common.py # 凭证校验
├── llm.py # LargeLanguageModel 实现
├── text_embedding.py # TextEmbeddingModel
├── rerank.py # RerankModel
├── moderation.py # ModerationModel
├── tts.py / speech2text.py
└── models/ # 模型 schema(上下文长度/价格/能力标签)
├── gpt-4o.yaml
└── ...
YAML 驱动 + Python 实现,易于扩展。
5.6 工具系统(Tools Subsystem)
api/core/tools/ 的 5 类 Provider:
| 类型 | 目录 | 场景 |
|---|---|---|
BUILTIN | builtin_tool/providers/ | 内置(Google/Slack/GitHub 等) |
API | custom_tool/ | OpenAPI Spec 导入 |
PLUGIN | plugin_tool/ | 第三方插件 |
WORKFLOW | workflow_as_tool/ | 工作流作为工具被别的 App 调用 |
MCP | mcp_tool/ | Model Context Protocol 工具 |
统一抽象 Tool 基类:
class Tool(ABC):
@property
def identity(self) -> ToolIdentity: ...
@property
def parameters(self) -> list[ToolParameter]: ...
def invoke(self, tool_parameters: dict) -> ToolInvokeMessage: ...
ToolManager.get_tool_runtime() 根据 provider_type 返回对应子类实例,Agent / Tool Node 统一通过 tool.invoke() 调用。
特殊工具:DatasetRetrieverTool 把知识库包装成 Agent 可调用的工具,实现 RAG 与 Agent 的融合。
5.7 插件系统(Plugin System)
Dify 的插件运行在 独立 Go 进程 plugin_daemon 中,API 服务通过 RPC 调用。这种设计带来:
- 进程隔离:插件崩溃不影响 API
- 多语言支持:插件可用 Python/Node/Go 等实现,由 daemon 统一托管
- 资源限制:daemon 可施加 CPU / 内存 / 超时限制
- 安全签名:
FORCE_VERIFYING_SIGNATURE=true强制验证插件签名
核心类:
PluginInstaller(api/core/plugin/impl/plugin.py):上传、安装、卸载PluginToolManager(api/core/plugin/impl/tool.py):加载插件工具BasePluginClient:封装与 daemon 的 HTTP/RPC 通信
一个插件包(.difypkg) 可以同时声明:Tool + Model + Endpoint(HTTP 路由) + Agent Strategy + Datasource。
5.8 记忆、Prompt 与 Moderation
Prompt Transform
- api/core/prompt/simple_prompt_transform.py:简单模板
{{var}}替换 - api/core/prompt/advanced_prompt_transform.py:Jinja2 模板,支持条件、循环、内存窗口
Moderation
api/core/moderation/ 支持输入审核与输出审核两道关:
InputModeration:Keyword / OpenAI Moderation API / 自定义 APIOutputModeration:流式 chunk 到达时实时审核,命中敏感词立即中止
ModerationAction:
DIRECT_OUTPUT:命中时直接返回预设 "抱歉我不能回答"OVERRIDDEN:用占位符覆盖敏感输入
6. 数据模型与数据库设计
6.1 核心 ER 图(文字版)
Tenant(工作空间)
├ 1:N TenantAccountJoin ── N:1 Account
│ (role: OWNER/ADMIN/EDITOR/NORMAL/DATASET_OPERATOR)
├ 1:N App
│ ├ 1:1 AppModelConfig
│ ├ 1:N Workflow ── 1:N WorkflowNodeExecution
│ ├ 1:N Conversation ── 1:N Message
│ │ ├ 1:N MessageFile
│ │ ├ 1:N MessageFeedback
│ │ └ 1:N MessageAgentThought
│ ├ 1:1 Site(分享页配置)
│ └ 1:N ApiToken
├ 1:N Dataset
│ └ 1:N Document ── 1:N DocumentSegment ── 1:N ChildChunk
├ 1:N EndUser(C 端用户)
├ 1:N Provider ── 1:N ProviderModel
└ 1:N Tag ── N:M TagBinding
6.2 关键表
| 表 | 说明 |
|---|---|
App | 应用,mode ∈ {chat, completion, agent_chat, advanced_chat, workflow} |
AppModelConfig | 应用模型配置(prompt/参数/数据集引用) |
Conversation | 会话,区分 from_source(console/api/web) |
Message | 消息对,content 含角色和文本 |
MessageFeedback | like/dislike 评分,评审意见 |
MessageAgentThought | Agent 思考链(tool_name/inputs/thought) |
EndUser | C 端匿名访客(session_id) |
ApiToken | 应用级 API Key |
UploadFile | 上传文件映射到存储 key |
api/models/account.py:Account、Tenant、TenantAccountJoin(关键的租户-用户-角色三元组)
api/models/dataset.py:Dataset、Document、DocumentSegment、ChildChunk、Embedding、DatasetPermission、Pipeline
api/models/workflow.py:Workflow(graph 字段为 JSON DSL)、WorkflowVersion、WorkflowNodeExecutionModel、WorkflowRun
6.3 多租户与 RBAC
TenantAccountRole枚举:OWNER / ADMIN / EDITOR / NORMAL / DATASET_OPERATOR- 所有资源表通过
tenant_idFK 物理隔离 - Service 层默认拼接
tenant_id = g.current_tenant.id - Dataset 额外支持
DatasetPermission(按成员授权)
6.4 迁移
api/migrations/versions/ 数百个 Alembic 脚本,命名类似 2024_01_01_xxxx_add_foo_column.py。升级命令:
uv run --project api flask db upgrade
7. Celery 任务队列与异步子系统
7.1 配置
api/extensions/ext_celery.py 要点:
- Broker: Redis(支持 Sentinel 故障转移)
- Backend: Redis(结果持久化)
- 自定义
FlaskTask包装:确保每个 Task 都运行在 Flask app 上下文 + 日志上下文中 - 支持 SSL Broker(
BROKER_USE_SSL=true)
7.2 任务分类
| 类别 | 代表任务 |
|---|---|
| RAG 索引 | document_indexing_task、add_document_to_index_task、deal_dataset_vector_index_task |
| RAG 清理 | batch_clean_document_task、clean_document_task、delete_segment_from_index_task |
| 工作流 | execute_workflow_professional/team/sandbox(按计划分流) |
| 会话 | delete_conversation_task |
| 邮件 | mail_invite_member_task、mail_email_code_login_task |
| 企业 | enterprise_telemetry_task |
| 定时任务 | 作用 |
|---|---|
clean_messages | 定期清理旧消息 |
clean_workflow_runs_task | 归档工作流运行记录 |
queue_monitor_task | 健康监控 |
workflow_schedule_task | Cron 触发工作流 |
7.3 队列分流(生产推荐)
# 按业务队列分工作进程,避免重任务阻塞轻任务
@celery.task(queue="dataset")
def document_indexing_task(...): ...
@celery.task(queue="workflow_professional")
def execute_workflow_professional(...): ...
启动多实例:
celery -A celery_entrypoint worker -Q dataset -c 4 --loglevel=info
celery -A celery_entrypoint worker -Q workflow_professional -c 8
celery -A celery_entrypoint beat --loglevel=info
8. 前端 Web 架构(web/)
8.1 技术栈
| 维度 | 选型 |
|---|---|
| 框架 | Next.js 15(App Router + RSC) |
| 语言 | TypeScript strict |
| 状态 | Zustand(多 slice) + Jotai(原子) |
| 数据获取 | ORPC 类型安全 + TanStack React Query + SWR |
| UI | Tailwind CSS + CVA + Headless UI + Floating UI |
| 编辑器 | ReactFlow(工作流) + Lexical(富文本) + Monaco(代码) |
| 图表 | Mermaid + ECharts |
| i18n | i18next(23 种语言) |
| 构建 | Turbopack + standalone output |
8.2 目录核心组
web/app/ 使用 Route Groups(括号目录)做布局分组:
(commonLayout)—— 控制台核心(应用/数据集/插件/工具/探索)(shareLayout)—— 公开分享页(chat/workflow 等免登录嵌入)(humanInputLayout)—— 人工表单account/—— 账户设置 + OAuth
base/—— 基础组件(chat/form/icons/prompt-editor/file-uploader 等)app/—— 应用编辑器workflow/—— 工作流画布(下节重点)datasets/—— 知识库 UIplugins/—— 插件市场
8.3 工作流编辑器——Zustand 多 Slice
web/app/components/workflow/store/workflow/ 将巨大的 workflow store 拆成独立 slice:
| Slice | 职责 |
|---|---|
workflow-slice | 工作流元数据 |
node-slice | 节点集合 / 坐标 |
form-slice | 节点配置表单 |
panel-slice | 左右面板开关 |
env-variable-slice | 环境变量 |
chat-variable-slice | 会话变量 |
version-slice | 版本控制 |
history-slice | 撤销重做 |
layout-slice | 缩放 / 迷你图 |
comment-slice | 协作注释(WebSocket) |
debug/inspect-vars-slice | 调试变量检查 |
所有 slice 合并为单个 Zustand store,既避免 prop drilling,又保持关注点分离。
8.4 工作流运行时 UI 更新
web/app/components/workflow/hooks/use-workflow-run-event/ 订阅后端 SSE:
前端 fetch('/console/api/apps/.../workflows/draft/run', { method: POST })
↓ Response.body 读取流
↓ 解析 data: {...} 行
↓ 识别事件类型并分发到 store
├─ workflow_started → 画布进入运行态
├─ node_started → 节点高亮脉冲动画
├─ text_chunk → LLM 流式追加
├─ node_finished → 节点变色 + 输出面板填充
├─ agent_thought → Agent 日志面板追加
└─ workflow_finished → 结束,写入运行记录
8.5 前端构建
web/Dockerfile 采用 多阶段构建:
base(node:22-alpine, pnpm)
→ packages(仅装依赖,最大化缓存)
→ builder(pnpm build + build:vinext,产出 .next/standalone)
→ production(只搬 standalone,非 root 运行)
output: 'standalone' 极大减少镜像体积(700MB → 100MB)。
9. Docker 部署拓扑与生产化配置
9.1 Compose 服务矩阵
docker/docker-compose.yaml 声明的关键服务:
| 服务 | 镜像 | 端口 | 职责 |
|---|---|---|---|
api | langgenius/dify-api:1.13.x | 5001 | Flask API |
worker | 同上(MODE=worker) | - | Celery 异步 |
worker_beat | 同上(MODE=beat) | - | 定时任务 |
web | langgenius/dify-web:1.13.x | 3000 | Next.js |
db | postgres:15-alpine | 5432 | 元数据 |
redis | redis:7-alpine | 6379 | Broker / Cache |
sandbox | langgenius/dify-sandbox:0.2.x | 8194 | 代码执行沙箱 |
plugin_daemon | langgenius/dify-plugin-daemon:0.5.x | 5002 | 插件运行时 |
ssrf_proxy | ubuntu/squid:latest | 3128 | 防 SSRF |
nginx | nginx:latest | 80/443 | 反向代理 |
weaviate | semitechnologies/weaviate | 8080 | 向量库(默认) |
| 可选 | qdrant/milvus/pgvector/chroma/elasticsearch/opensearch/tidb/oceanbase/clickhouse/minio | 按需 | 其他后端 |
9.2 网络与数据流
┌──── 用户/第三方
▼
Nginx(80/443)
│
┌──────┼──────┐
▼ ▼
web(3000) api(5001)
│
┌────┬──────┼────────┬───────────┐
▼ ▼ ▼ ▼ ▼
postgres redis weaviate sandbox plugin_daemon
│
▼
ssrf_proxy(3128)
│
▼
Internet
两个独立网络:
default—— 主服务通信ssrf_proxy_network—— 只有 sandbox / api / ssrf_proxy 能加入,确保外网请求必须过代理
9.3 Sandbox 的安全设计
docker-compose.yaml 中 sandbox 服务:
- 容器级隔离(独立 PID/NS/FS)
HTTP_PROXY=http://ssrf_proxy:3128强制代理外网WORKER_TIMEOUT=15单次执行上限ENABLE_NETWORK=true/false控制是否联网/dependencies预装常用 Python 包
9.4 SSRF Proxy(Squid)
docker/ssrf_proxy/squid.conf.template 禁止访问私网:
acl private src 10.0.0.0/8
acl private src 172.16.0.0/12
acl private src 192.168.0.0/16
acl private src 127.0.0.0/8
http_access deny private
防止攻击者利用 HTTP 节点或代码节点访问云元数据服务(如 169.254.169.254)。
9.5 Plugin Daemon 配置
SERVER_PORT=5002
PLUGIN_DAEMON_KEY=...
DIFY_INNER_API_URL=http://api:5001
PLUGIN_WORKING_PATH=/app/storage/cwd
PLUGIN_MAX_EXECUTION_TIMEOUT=600
FORCE_VERIFYING_SIGNATURE=true
PLUGIN_STORAGE_TYPE=local # 或 s3
9.6 数据卷
./volumes/
├── app/storage # 应用上传/导出
├── db/postgres # PG 数据
├── sandbox/dependencies # pip 缓存
├── plugin_daemon # 插件包
├── weaviate # 向量库
└── certbot # SSL 证书
10. 生产环境最佳实践与运维手册
10.1 快速启动(开发)
cd dify/docker
cp .env.example .env
# 按需修改 .env(至少:SECRET_KEY / DB_PASSWORD / REDIS_PASSWORD)
docker compose up -d
# 访问 http://localhost/install 完成首次初始化
10.2 生产硬化清单
密钥与证书
-
SECRET_KEY生成 64 字节随机值:openssl rand -base64 42 -
DB_PASSWORD/REDIS_PASSWORD/WEAVIATE_API_KEY/PLUGIN_DAEMON_KEY全部修改 -
INIT_PASSWORD设为强密码或仅首次启动后置空 - Nginx 开启 HTTPS:挂载 certbot 证书 + 配置
conf.d/ssl.conf
数据库
- 使用 外部托管 PostgreSQL(RDS / Cloud SQL / 自建高可用主从),不用 compose 内嵌 PG
- 配置备份:每日
pg_dump+ WAL 归档 - 连接池:
SQLALCHEMY_POOL_SIZE=30、SQLALCHEMY_POOL_RECYCLE=3600
Redis
- 开启 Sentinel 或使用托管 Redis
-
maxmemory-policy allkeys-lru - Broker 与 Cache 使用不同 DB 编号分离
存储
- 切换
STORAGE_TYPE=s3(或 OSS/Azure),不用本地卷 - 启用版本化与生命周期策略
向量数据库
- 超过 100 万向量推荐 Qdrant / Milvus,不再用 Weaviate 默认配置
- 配置持久化卷 + 副本
扩容
- API 服务横向扩展:
SERVER_WORKER_AMOUNT=gevent worker 数,配合 Nginx upstream - Worker 按队列分工:
worker_dataset:
image: dify-api
command: celery -A app.celery worker -Q dataset -c 8
worker_workflow:
image: dify-api
command: celery -A app.celery worker -Q workflow -c 16
worker_mail:
image: dify-api
command: celery -A app.celery worker -Q mail -c 2
可观测性
-
SENTRY_DSN配置 Sentry -
ENABLE_OTEL=true+OTEL_EXPORTER_OTLP_ENDPOINT对接 Jaeger/Tempo/阿里云 ARMS - 配置 Langfuse / Opik / Arize Phoenix 做 LLM 调用追踪(在应用设置里开启)
安全
- 保留
ssrf_proxy服务,不要删 -
FORCE_VERIFYING_SIGNATURE=true防止未审核插件安装 - 对
/console/api配置 IP 白名单或 VPN 访问 -
MAX_TOOLS_NUM、APP_MAX_EXECUTION_TIME设合理上限,防止租户滥用
10.3 备份与恢复
# 数据库备份
docker exec dify-db pg_dump -U postgres dify > backup_$(date +%F).sql
# 文件卷备份
tar czf dify_volumes_$(date +%F).tgz docker/volumes/
# 向量库(Weaviate)
curl -X POST "http://localhost:8080/v1/backups/filesystem" \
-H "Content-Type: application/json" \
-d '{"id":"backup-$(date +%s)"}'
10.4 灰度发布
- 前端
web多版本通过 Nginx weight 做灰度 - 后端
api通过 Feature Flag(configs/feature/)按租户开关
11. 二次开发指南:扩展节点、工具、模型
11.1 新增自定义工作流节点
以新增一个"邮件发送"节点为例:
- 在
api/core/workflow/nodes/mail/新建目录 - 定义
MailNodeData(Pydantic):
class MailNodeData(BaseNodeData):
to: list[str]
subject: str
body_template: str
- 实现
MailNode:
from core.workflow.nodes.base.node import Node
@Node.register(NodeType.MAIL)
class MailNode(Node[MailNodeData]):
version = "1"
def run(self) -> Generator[GraphNodeEventBase, None, None]:
yield WorkflowNodeExecutionStarted(...)
to = self.data.to
body = render_template(self.data.body_template, self.variable_pool)
send_mail(to, self.data.subject, body)
yield WorkflowNodeExecutionSucceeded(outputs={"sent": True})
- 前端 web/app/components/workflow/nodes/mail/ 添加节点渲染与配置面板
- 注册到
BLOCK_ENUM和 i18n 键
11.2 新增内置工具
api/core/tools/builtin_tool/providers/<name>/:
my_provider/
├── my_provider.yaml # 提供者元数据
├── my_provider.py # Provider 类(凭证校验)
└── tools/
├── my_tool.yaml # 工具参数 schema
└── my_tool.py # Tool 实现(invoke 方法)
class MyTool(BuiltinTool):
def _invoke(self, user_id: str, tool_parameters: dict) -> ToolInvokeMessage:
result = call_external_api(tool_parameters["query"])
return self.create_json_message(result)
11.3 接入自定义 LLM 提供商
推荐通过 Plugin 实现(官方 SDK):
dify plugin init
dify plugin bundle
# 上传到 /console/api/workspaces/current/plugins/install/pkg
Plugin 里实现 LargeLanguageModel._invoke(),按统一协议返回 LLMResult。
11.4 新增向量数据库适配器
api/core/rag/datasource/vdb/my_vdb/ 继承 BaseVector:
class MyVector(BaseVector):
def create(self, texts, embeddings, **kwargs): ...
def search_by_vector(self, query_vector, **kwargs) -> list[Document]: ...
# 其余必需方法
然后在 vector_type.py 加枚举、vector_factory.py 注册工厂。
12. 典型业务场景案例
12.1 企业知识库问答
架构:Dataset(Knowledge Base) + Chat App + RAG Prompt
用户问题
↓
Chat App
↓ 自动触发知识库检索
KnowledgeRetrieval(hybrid 检索 + Rerank)
↓ 上下文拼入 Prompt
LLM (GPT-4o / Claude)
↓
回答 + 引用来源
配置要点:
- Dataset 用 Parent-Child 分段 提高召回
- Top-K = 4,Rerank 使用 Cohere rerank-v3
- Prompt 加入"基于提供的上下文回答,不知道时如实说明"
12.2 智能客服(Agent + 多工具)
架构:AgentChat App + FC Agent
Tools:
├─ search_order(查询订单)
├─ refund_request(发起退款)
├─ get_logistics(查物流)
└─ DatasetRetrieverTool(政策知识库)
系统 Prompt:
"你是 XX 客服,必须基于工具获取真实数据才能回答,
涉及退款金额必须让用户二次确认..."
使用 FC Agent 而非 CoT,因为 GPT-4 的原生 FC 更稳定。
工具调用要加 confirm_required 机制(Dify 支持在工具中声明)。
12.3 复杂业务流(Workflow 编排)
场景:合同审查
Start(上传合同 PDF)
→ KnowledgeIndex(临时索引)
→ LLM(提取关键条款)
→ IF_ELSE(判断是否有违规条款)
├─ true → LLM(生成修订建议) → End(返回修订版)
└─ false → LLM(生成审查报告) → End(通过)
利用 IF_ELSE + ITERATION 可以处理批量合同。
12.4 定时数据拉取 + 报告生成
ScheduleTrigger(每天 08:00)
→ HTTP_REQUEST(拉取业务指标 API)
→ Code(Pandas 分析)
→ LLM(生成自然语言报告)
→ Tool:send_mail(发给老板)
13. 性能调优、安全加固与排障手册
13.1 性能优化
| 瓶颈 | 排查 | 优化 |
|---|---|---|
| LLM 调用慢 | 查看 Message.provider_response_latency | 开启 stream、换更快模型、配负载均衡 |
| 知识库召回慢 | Vector DB 监控 | 索引 HNSW 参数、增加副本、用 Qdrant 替换 Weaviate |
| Worker 堆积 | celery -A app.celery inspect active | 增加 worker 实例、分队列、提高并发 |
| API 响应慢 | 看 Gunicorn/Gevent worker 利用率 | 增加 SERVER_WORKER_AMOUNT |
| DB 慢查询 | pg_stat_statements | 看缺失索引、分页改游标 |
| Redis 压力 | redis-cli --stat | 拆 Broker/Cache 实例、调大 maxmemory |
13.2 常见故障与解法
| 症状 | 可能原因 | 解决 |
|---|---|---|
| 前端白屏,控制台 401 | JWT 过期 / cookie 域配错 | 检查 NEXT_PUBLIC_COOKIE_DOMAIN |
| 应用卡在 "生成中" | SSE 被 Nginx 缓冲 | Nginx 加 proxy_buffering off; proxy_read_timeout 300s; |
| 工作流 Code 节点超时 | sandbox 超时默认 15s | 加大 WORKER_TIMEOUT,或 Celery 异步化 |
| 知识库索引失败 | 嵌入模型凭证失效 | 控制台 → 模型供应商 → 重新填写 Key |
| 插件安装失败 | 签名验证未通过 | 要么关闭 FORCE_VERIFYING_SIGNATURE,要么改用官方签名插件 |
| HTTP 节点访问内网失败 | SSRF Proxy 拦截 | 按需修改 Squid ACL 允许特定内网段 |
13.3 安全加固
- RCE 防护:Code 节点依赖 Sandbox 容器隔离,不要禁用
- SSRF 防护:保留 ssrf_proxy,不直接给 API 容器外网出口
- 凭证加密:DB 里的 Provider 凭证默认对称加密,
SECRET_KEY泄露等于凭证泄露,必须换 - 审计日志:
OperationLog表记录所有管理操作,对接 SIEM - 限流:
/console/api/login前加 Nginx rate limit 防爆破
14. 总结:Dify 的设计哲学
14.1 工程原则
- DDD + Clean Architecture:Controller / Service / Core / Model 严格分层,依赖单向
- Core 是引擎,Service 是用例:换掉 Flask 不影响 Core
- Everything is a Graph:工作流是图,Agent 内部也是图
- Everything is a Provider:Model / Tool / VectorDB / Storage 都走工厂 + 策略
- 同构可替换:一个 LLM 节点可以调用 OpenAI、也可以调用本地 vLLM,代码路径一致
- 异步优先:所有耗时任务经 Celery,API 只做编排
- 多租户一等公民:
tenant_id无处不在,权限前置
14.2 架构亮点
- graphon + NodeFactory 自注册:新节点只需实现 + 装饰器,零配置接入
- Layers 中间件堆栈:配额/超时/观测通过洋葱模型组合
- 事件流 + SSE:前后端通过生成器 + 事件,天然支持流式体验
- Plugin Daemon 进程隔离:插件崩溃不拖死主进程,又能支持多语言
- 5 类 Tool Provider 统一:Builtin/API/Plugin/Workflow/MCP 在 Agent 眼里没有区别
- Sandbox + SSRF Proxy 双隔离:安全左移,代码执行和外网访问都受控
14.3 适用场景
- 企业内 AI 应用平台:多团队共用,按 Tenant 隔离
- RAG 知识库服务:开箱即用的全套 RAG 能力
- Agent 工作流自动化:可视化编排 + 定时触发 + HTTP/Webhook
- 模型能力测试床:一个画布对比多个模型
14.4 使用边界
- 不适合极端低延迟场景(<100ms 单调用)——Flask + Celery 链路较长
- 不适合纯离线训练或大规模数据处理——定位是推理编排而非训练
- 对图引擎依赖重:
graphon库的行为需要深入理解,否则魔改易出问题
附录 A:核心文件速查表
| 功能 | 文件 |
|---|---|
| 后端入口 | api/app.py |
| 工厂 / 扩展装配 | api/app_factory.py |
| 路由注册 | api/extensions/ext_blueprints.py |
| 登录 / JWT | api/extensions/ext_login.py |
| Celery | api/extensions/ext_celery.py |
| 数据库 + Gevent | api/extensions/ext_database.py |
| 工作流执行 | api/services/workflow_service.py |
| 异步工作流 | api/services/async_workflow_service.py |
| 工作流入口 | api/core/workflow/workflow_entry.py |
| 节点工厂 | api/core/workflow/node_factory.py |
| Agent FC | api/core/agent/fc_agent_runner.py |
| Agent CoT | api/core/agent/cot_agent_runner.py |
| Model Manager | api/core/model_manager.py |
| Provider Manager | api/core/provider_manager.py |
| Tool Manager | api/core/tools/tool_manager.py |
| RAG 检索 | api/core/rag/datasource/retrieval_service.py |
| Vector 工厂 | api/core/rag/datasource/vdb/vector_factory.py |
| 核心 ORM | api/models/model.py |
| 租户 / 账号 | api/models/account.py |
| 知识库 ORM | api/models/dataset.py |
| 工作流 ORM | api/models/workflow.py |
| 前端工作流 Store | web/app/components/workflow/store/workflow/ |
| Docker 编排 | docker/docker-compose.yaml |
| 环境模板 | docker/.env.example |
附录 B:关键环境变量对照
# ——— 基础 ———
SECRET_KEY=<openssl rand -base64 42>
DEPLOY_ENV=PRODUCTION
APP_MAX_EXECUTION_TIME=1200
# ——— 数据库 ———
DB_TYPE=postgresql
DB_HOST=prod-pg.internal
DB_PORT=5432
DB_USERNAME=dify
DB_PASSWORD=<strong>
DB_DATABASE=dify
SQLALCHEMY_POOL_SIZE=30
SQLALCHEMY_POOL_RECYCLE=3600
# ——— Redis ———
REDIS_HOST=prod-redis.internal
REDIS_PASSWORD=<strong>
CELERY_BROKER_URL=redis://:<pw>@prod-redis.internal:6379/1
# ——— 向量库 ———
VECTOR_STORE=qdrant
QDRANT_URL=http://qdrant.internal:6333
QDRANT_API_KEY=<key>
# ——— 存储 ———
STORAGE_TYPE=s3
S3_ENDPOINT=https://s3.ap-east-1.amazonaws.com
S3_BUCKET_NAME=dify-prod
S3_ACCESS_KEY=<>
S3_SECRET_KEY=<>
# ——— 安全 ———
FORCE_VERIFYING_SIGNATURE=true
SSRF_PROXY_HTTP_URL=http://ssrf_proxy:3128
SSRF_PROXY_HTTPS_URL=http://ssrf_proxy:3128
# ——— 观测 ———
SENTRY_DSN=https://<dsn>
ENABLE_OTEL=true
OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4318
本文档基于 Dify v1.13.x 源码分析撰写,覆盖后端、核心引擎、前端、部署、运维、二开全链路。源码结构会随版本演进,建议配合最新 AGENTS.md 与 api/AGENTS.md 一起阅读。