大模型节点实现(中文译文)
原始 DeepWiki 页面:https://deepwiki.com/langgenius/dify/5.3-llm-node-implementation
翻译时间:2026-05-27T08:44:38.657Z
翻译模型:deepseek-chat
原文字符数:18925
项目:Dify (dify)
---
LLM 节点实现
相关源文件
以下文件为本维基页面的生成提供了上下文:
api/core/agent/base_agent_runner.pyapi/core/agent/cot_agent_runner.pyapi/core/agent/cot_chat_agent_runner.pyapi/core/agent/cot_completion_agent_runner.pyapi/core/agent/entities.pyapi/core/agent/fc_agent_runner.pyapi/core/app/app_config/easy_ui_based_app/agent/manager.pyapi/core/app/apps/agent_chat/app_runner.pyapi/core/app/apps/base_app_runner.pyapi/core/app/apps/chat/app_runner.pyapi/core/app/apps/completion/app_runner.pyapi/core/memory/token_buffer_memory.pyapi/core/prompt/advanced_prompt_transform.pyapi/core/prompt/agent_history_prompt_transform.pyapi/core/prompt/entities/advanced_prompt_entities.pyapi/core/prompt/prompt_transform.pyapi/core/prompt/simple_prompt_transform.pyapi/factories/file_factory/message_files.pyapi/factories/file_factory/validation.pyapi/providers/trace/trace-langsmith/src/dify_trace_langsmith/entities/langsmith_trace_entity.pyapi/tests/unit_tests/core/memory/test_token_buffer_memory.pyapi/tests/unit_tests/core/prompt/test_advanced_prompt_transform.pyapi/tests/unit_tests/core/prompt/test_agent_history_prompt_transform.pyapi/tests/unit_tests/core/prompt/test_simple_prompt_transform.pyapi/tests/unit_tests/core/workflow/nodes/llm/test_node.pyapi/tests/unit_tests/factories/test_file_validation.pyweb/app/components/app/configuration/config-vision/param-config-content.tsxweb/app/components/app/configuration/dataset-config/context-var/index.tsxweb/app/components/billing/priority-label/index.tsxweb/app/components/workflow/nodes/_base/components/option-card.tsxweb/app/components/workflow/nodes/_base/components/variable/utils.tsweb/app/components/workflow/nodes/assigner/panel.tsxweb/app/components/workflow/nodes/http/components/key-value/key-value-edit/index.tsxweb/app/components/workflow/nodes/http/components/timeout/index.tsxweb/app/components/workflow/nodes/http/default.tsweb/app/components/workflow/nodes/http/panel.tsxweb/app/components/workflow/nodes/http/types.tsweb/app/components/workflow/nodes/http/use-config.tsweb/app/components/workflow/nodes/iteration/panel.tsxweb/app/components/workflow/nodes/knowledge-retrieval/use-single-run-form-params.tsweb/app/components/workflow/nodes/list-operator/components/filter-condition.tsxweb/app/components/workflow/nodes/list-operator/panel.tsxweb/app/components/workflow/nodes/llm/components/resolution-picker.tsxweb/app/components/workflow/nodes/llm/panel.tsxweb/app/components/workflow/nodes/llm/use-config.tsweb/app/components/workflow/nodes/parameter-extractor/panel.tsxweb/app/components/workflow/nodes/start/panel.tsxweb/app/components/workflow/nodes/trigger-webhook/components/generic-table.tsxweb/app/components/workflow/nodes/utils.tsweb/app/components/workflow/types.tsweb/utils/completion-params.ts
目的与范围
本文档记录了 Dify 工作流引擎中 LLM 节点的实现。LLM 节点负责使用构造好的提示词调用大语言模型,管理对话记忆,处理多模态输入,以及处理包括流式输出、结构化输出和推理内容在内的多种响应类型。
关于整体工作流执行模型和节点调度的信息,请参见工作流定义与执行模型。关于工作流中检索增强生成(RAG)的集成,请参见知识检索节点。关于提供商级别的配额管理,请参见6.3 配额管理与积分池。
---
节点类架构
LLM 节点通过 LLMNode 类实现,该类扩展了基础 Node 类,并增加了 LLM 调用的专门能力。
LLM 节点类结构
graph TB
Node["Node[LLMNodeData]<br/>基础工作流节点"]
LLMNode["LLMNode<br/>graphon.nodes.llm.node"]
LLMNodeData["LLMNodeData<br/>配置实体"]
Node -->|继承| LLMNode
LLMNode -->|由...配置| LLMNodeData
LLMNodeData -->|包含| ModelConfig["ModelConfig<br/>provider, name, mode, completion_params"]
LLMNodeData -->|包含| PromptTemplate["prompt_template<br/>List[LLMNodeChatModelMessage]"]
LLMNodeData -->|包含| MemoryConfig["MemoryConfig<br/>对话历史"]
LLMNodeData -->|包含| ContextConfig["ContextConfig<br/>RAG 上下文选择器"]
LLMNodeData -->|包含| VisionConfig["VisionConfig<br/>多模态文件选择器"]
LLMNode -->|使用| LLMFileSaver["LLMFileSaver<br/>文件输出管理"]
LLMNode -->|调用| ModelInstance["ModelInstance<br/>LLM 提供商包装器"]
LLMNode -->|读取自| VariablePool["VariablePool<br/>工作流变量状态"]
LLMNode -->|发出| StreamChunkEvent["StreamChunkEvent<br/>实时输出"]
LLMNode -->|发出| ModelInvokeCompletedEvent["ModelInvokeCompletedEvent<br/>最终结果"]
LLMNode -->|发出| RunRetrieverResourceEvent["RunRetrieverResourceEvent<br/>上下文元数据"]
来源: api/graphon/nodes/llm/node.py:70-77, api/graphon/nodes/llm/entities.py:53-62, api/tests/unit_tests/core/workflow/nodes/llm/test_node.py:156-171
---
节点执行生命周期
LLM 节点的执行遵循从输入处理到响应生成的结构化管线。_run() 方法负责编排变量提取、记忆加载和模型调用。
执行流程示意图
graph TB
Start["LLMNode._run() 入口"] --> TransformMessages["转换提示词模板<br/>Jinja2 → 文本转换"]
TransformMessages --> FetchInputs["获取输入变量<br/>从 VariablePool 提取"]
FetchInputs --> FetchJinja["获取 Jinja2 输入<br/>模板变量替换"]
FetchJinja --> FetchFiles["获取视觉文件<br/>从 vision.configs.variable_selector"]
FetchFiles --> FetchContext["获取上下文<br/>从 context.variable_selector"]
FetchContext --> YieldContextEvent["发出 RunRetrieverResourceEvent<br/>附带检索元数据"]
YieldContextEvent --> FetchModelConfig["获取模型配置<br/>ModelManager.get_model_instance()"]
FetchModelConfig --> FetchMemory["获取记忆<br/>TokenBufferMemory"]
FetchMemory --> BuildPrompts["构建提示词消息<br/>fetch_prompt_messages()"]
BuildPrompts --> InvokeLLM["调用 LLM<br/>invoke_llm()"]
InvokeLLM --> HandleResponse["处理调用结果<br/>handle_invoke_result()"]
HandleResponse --> ProcessStreaming{"流式<br/>模式?"}
ProcessStreaming -->|是| StreamLoop["流式输出片段<br/>发出 StreamChunkEvent"]
ProcessStreaming -->|否| BlockingResult["处理阻塞结果"]
StreamLoop --> ExtractReasoning["提取推理内容<br/>_split_reasoning()"]
BlockingResult --> ExtractReasoning
ExtractReasoning --> BuildOutputs["构建输出变量<br/>text, reasoning_content, usage"]
BuildOutputs --> YieldCompleted["发出 StreamCompletedEvent<br/>NodeRunResult"]
YieldCompleted --> End["返回"]
来源: api/graphon/nodes/llm/node.py:151-353, api/tests/unit_tests/core/workflow/nodes/llm/test_node.py:201-215
---
提示词构建管线
LLM 节点通过组装模板、上下文、记忆和多模态文件来构建提示词。它支持"基础"和"Jinja2"两种编辑类型。
提示词组装流程
graph TB
PromptRequest["fetch_prompt_messages()<br/>静态方法入口"]
PromptRequest --> CheckMode{"模型<br/>模式?"}
CheckMode -->|chat| ChatFlow["构建聊天消息"]
CheckMode -->|completion| CompletionFlow["构建补全提示词"]
ChatFlow --> SystemMsg["添加系统消息<br/>来自 prompt_template"]
SystemMsg --> UserAssistantPairs["添加用户/助手消息对<br/>来自 prompt_template"]
UserAssistantPairs --> SubstituteVars["替换变量<br/>VariableTemplateParser / Jinja2"]
SubstituteVars --> AddMemory{"记忆<br/>已启用?"}
AddMemory -->|是| FetchHistory["获取历史消息<br/>memory.get_history_prompt_messages()"]
FetchHistory --> InsertHistory["在查询前插入历史"]
AddMemory -->|否| AddQuery
InsertHistory --> AddQuery
AddQuery["添加用户查询消息<br/>sys.query 参数"]
AddQuery --> AddFiles{"视觉<br/>已启用?"}
AddFiles -->|是| AttachVision["附加视觉文件<br/>to_prompt_message_content()"]
AddFiles -->|否| FinalMessages
AttachVision --> FinalMessages["返回 PromptMessage 列表"]
CompletionFlow --> BuildTemplate["构建单个提示词<br/>替换所有变量"]
BuildTemplate --> InsertContext["插入 #context#"]
InsertContext --> FinalTemplate["返回补全提示词"]
来源: api/graphon/nodes/llm/node.py:628-662, api/graphon/nodes/llm/node.py:664-723, api/core/prompt/advanced_prompt_transform.py:37-80
变量类型与转换
| 变量类型 | 来源 | 转换方式 |
|---|---|---|
{{input_var}} | 用户输入或上游节点输出 | 通过 VariableTemplateParser 或 Jinja2Formatter 进行直接字符串替换 |
#context# | 知识检索节点输出 | 从文档片段组装,包含摘要 |
#histories# | 对话记忆 | 使用角色前缀(Human/Assistant)格式化 |
#files# | 视觉文件选择器 | 转换为 ImagePromptMessageContent |
来源: api/graphon/nodes/llm/node.py:584-626, api/graphon/nodes/llm/node.py:664-723, api/core/prompt/simple_prompt_transform.py:93-146
---
记忆集成
LLM 节点通过 TokenBufferMemory 与对话历史集成,以维持多轮对话。它使用 extract_thread_messages 确保只包含当前对话线程中的相关消息。
记忆检索流程
graph TB
FetchMemory["llm_utils.fetch_memory()"]
FetchMemory --> CheckConfig{"记忆<br/>已配置?"}
CheckConfig -->|否| ReturnNone["返回 None"]
CheckConfig -->|是| GetConvID["获取 conversation_id<br/>从 sys.conversation_id"]
GetConvID --> CreateMemory["创建 TokenBufferMemory<br/>使用 conversation + model_instance"]
CreateMemory --> ReturnMemory["返回记忆实例"]
ReturnMemory --> UsedInPrompt["用于提示词构建"]
UsedInPrompt --> GetHistory["memory.get_history_prompt_messages()"]
GetHistory --> FormattedHistory["使用 role_prefix 格式化"]
来源: api/graphon/nodes/llm/node.py:208-221, api/core/memory/token_buffer_memory.py:30-45, api/core/memory/token_buffer_memory.py:122-148, api/tests/unit_tests/core/workflow/nodes/llm/test_node.py:87-96
---
多模态支持
LLM 节点通过将图像文件附加到用户消息中来处理支持视觉的模型。TokenBufferMemory 在从历史构建提示词消息时也会处理文件附件。
视觉文件处理
graph TB
VisionCheck["VisionConfig.enabled = true"]
VisionCheck --> FetchFiles["llm_utils.fetch_files()<br/>从 variable_selector"]
FetchFiles --> CheckType{"变量<br/>类型?"}
CheckType -->|FileSegment| SingleFile["提取单个 File"]
CheckType -->|ArrayFileSegment| MultipleFiles["提取 File 数组"]
SingleFile --> ConvertFiles
MultipleFiles --> ConvertFiles["转换为提示词内容<br/>file_manager.to_prompt_message_content()"]
ConvertFiles --> SetDetail["设置细节级别<br/>HIGH 或 LOW"]
SetDetail --> AttachToMessage["附加到 UserPromptMessage<br/>content: [TextContent, ImageContent]"]
来源: api/graphon/nodes/llm/node.py:175-186, api/core/memory/token_buffer_memory.py:87-122, api/tests/unit_tests/core/workflow/nodes/llm/test_node.py:163-171
---
模型调用
LLM 节点支持标准文本生成和结构化输出生成。它还包含重新计算 max_tokens 的逻辑,以防提示词 Token 和请求的补全 Token 之和超过模型的上下文限制。
调用架构
graph TB
InvokeLLM["invoke_llm()<br/>静态方法"]
InvokeLLM --> GetSchema["获取模型模式<br/>model_instance.get_model_schema()"]
GetSchema --> RecalcTokens["recalc_llm_max_tokens()<br/>上下文大小检查"]
RecalcTokens --> CheckStructured{"structured_output<br/>已启用?"}
CheckStructured -->|是| StructuredPath["invoke_llm_with_structured_output()<br/>带 JSON 模式校验"]
CheckStructured -->|否| StandardPath["model_instance.invoke_llm()<br/>标准调用"]
SetParams["设置参数<br/>model_parameters, stop, stream"]
StructuredPath --> SetParams
StandardPath --> SetParams
SetParams --> ExecuteInvoke["通过 ModelInstance 执行调用"]
来源: api/graphon/nodes/llm/node.py:355-413, api/core/app/apps/base_app_runner.py:53-86
---
响应处理
LLM 节点根据流式模式和响应类型以不同方式处理响应。它处理标准 LLMResultChunk 和 LLMResultChunkWithStructuredOutput 两种类型。
响应处理流程
graph TB
HandleResult["handle_invoke_result()"]
HandleResult --> CheckType{"响应<br/>类型?"}
CheckType -->|LLMResult| BlockingMode["阻塞模式"]
CheckType -->|Generator| StreamingMode["流式模式"]
BlockingMode --> HandleBlocking["handle_blocking_result()"]
HandleBlocking --> YieldCompleted["发出 ModelInvokeCompletedEvent"]
StreamingMode --> IterateChunks["遍历 LLMResultChunk"]
IterateChunks --> YieldChunk["发出 StreamChunkEvent<br/>selector: [node_id, 'text']"]
IterateChunks -->|完成| ExtractReasoning["提取推理内容<br/>_split_reasoning()"]
ExtractReasoning --> YieldStreamCompleted["发出 ModelInvokeCompletedEvent"]
来源: api/graphon/nodes/llm/node.py:415-527, api/graphon/nodes/llm/node.py:534-567
推理内容提取
LLM 节点支持使用正则表达式模式从 <think> 标签中提取推理内容(例如来自 DeepSeek 等模型)。
graph TB
SplitReasoning["_split_reasoning()"]
SplitReasoning --> CheckFormat{"reasoning_format?"}
CheckFormat -->|separated| FindMatches["正则表达式 findall<br/>_THINK_PATTERN"]
FindMatches --> JoinContent["合并思考块"]
JoinContent --> RemoveTags["从文本中移除标签"]
CheckFormat -->|tagged| ReturnFull["原样返回完整文本"]
来源: api/graphon/nodes/llm/node.py:534-567, api/tests/unit_tests/core/workflow/nodes/llm/test_node.py:170-171
---
节点输出
LLM 节点生成多个输出变量,下游节点可以访问这些变量:
| 输出变量 | 类型 | 描述 |
|---|---|---|
text | 字符串 | 干净的文本输出("separated"模式下已移除推理内容) |
reasoning_content | 字符串 | 从 <think> 标签中提取的内容 |
usage | 对象 | Token 使用量元数据(prompt_tokens, completion_tokens, total_tokens) |
finish_reason | 字符串 | LLM 补全原因(stop, length, tool_calls) |
来源: api/graphon/nodes/llm/node.py:299-309, api/graphon/model_runtime/entities/llm_entities.py:29-30
---
错误处理
LLM 节点处理提示词构建和模型调用过程中的各种错误情况:
| 错误类型 | 原因 |
|---|---|
NoPromptFoundError | 未找到提示词模板或历史 |
VariableNotFoundError | 引用的变量在 VariablePool 中不存在 |
InvalidContextStructureError | 上下文字典缺少 'content' 字段 |
TemplateRenderError | Jinja2 模板渲染失败 |
来源: api/graphon/nodes/llm/exc.py:1-25, api/graphon/nodes/llm/node.py:64-68