Dify_专题五_大模型运行成功但Dify仍不可用_cursor.md
这是基于原文生成的 Cursor 版文档。
原文件未改动;本版只做三件事:统一阅读入口、修正已审出的明显问题、补充更适合快速排障的提示。
Cursor 版修订说明
- 保持“七层排查”结构,Cursor 版仅加强提示框与阅读引导,不改原主线。
阅读提示
- 若正文中的容器名、目录名、IP 与你的环境不一致,请以实际
docker ps、docker compose ps、目录结构为准。 - 若正文属于“本次实战记录”,应理解为环境实录,不等同于所有环境的唯一正确默认值。
运行环境:业务脚本均在 207 固定目录
/opt/workbuddy执行,Python 为/usr/bin/python3。 Windows 开发机仅保留_probe_*调试脚本;同步命令:python scripts_cursor/完整代码约定/00_部署_workbuddy到207.py。
原文主体(已纳入 Cursor 版纠错)
专题五:大模型"运行成功"了,但 Dify 里还是不行——系统性排查
阅读导航(何时打开 · 报错往哪查)
本文是单点修复/排障专题,配合《安装配置手册》使用;下文实战步骤与代码全部保留,此处只做索引。
| 何时打开 | 说明 |
|---|---|
| vLLM curl 通,Dify 仍不可用 | 按 7 层总图 从外到内,不要跳层 |
| 不知道先查哪 | §十一 落地清单顺序 |
| 层 | 典型现象 | 章节 |
|---|---|---|
| 1 | 容器在但 /v1 不通 | §三 |
| 2 | Dify→116 网络 | §四 |
| 3 | 凭据/Base 错 | §五 |
| 4 | 不兼容/列表空 | §六 + 专题一/十 |
| 7 | 400 system | §九 + 专题四 |
典型场景:vLLM 容器已跑、日志显示
Application startup complete,你在聊天里发了句"大模型运行成功了 这里还是不行"。这说明模型端看起来正常,但 Dify 到模型之间的链路仍有某个环节没通。
本文给出从"模型端"到"Dify 问答"的 7 层排查路径,每一层都附带可直接执行的命令/代码,直到定位并解决。
一、场景描述
- vLLM 容器状态
Up; docker logs vllm-qwen3.6-27b看到Application startup complete;- 但 Dify 里:测试连接失败、保存模型凭据报错、或发消息后页面无响应/报错(如
System message must be at the beginning)。
关键认知:
运行成功只是容器和模型加载成功,不等于 Dify 能正确地把请求交给它。
二、排查总图(7 层,从外到内)
模型端是否真可用?
└─ 是 → Dify 服务器到模型端网络通吗?
└─ 是 → Dify 模型供应商凭据配对了吗?
└─ 是 → 模型 schema 兼容吗?(不兼容/选不到)
└─ 是 → 默认 LLM 指向 qwen3.6-27b 了吗?
└─ 是 → plugin_daemon 加载 patch 了吗?
└─ 是 → 问答时 system 消息格式正确吗?
└─ 是 → 通。每一层都可能让"模型运行成功"的表象破裂。下面逐层展开。
三、第 1 层:模型端真的可用吗?(区分"启动"与"可服务")
不要只看 docker logs 里的启动成功,要做三次 curl。
3.1 列出模型
完整脚本:scripts_bash_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_内联_01.sh
运行/引用:bash /opt/workbuddy/scripts_bash_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_内联_01.sh
#!/usr/bin/env bash
set -euo pipefail
curl -s http://116.62.10.183:8000/v1/models \
-H "Authorization: Bearer 123456" | head必须返回模型名 qwen3.6-27b:
{
"object": "list",
"data": [
{"id": "qwen3.6-27b", "object": "model"}
]
}如果这里为空,说明
--served-model-name没配对或模型没加载完。
3.2 最简单的一次对话
完整脚本:scripts_bash_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_内联_02.sh
运行/引用:bash /opt/workbuddy/scripts_bash_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_内联_02.sh
#!/usr/bin/env bash
set -euo pipefail
curl -s -X POST http://116.62.10.183:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer 123456" \
-d '{
"model": "qwen3.6-27b",
"messages": [{"role": "system", "content": "你是一个助手"},{"role": "user", "content": "你好"}],
"max_tokens": 128
}'期望:返回 choices[0].message.content,无 400/500。
3.3 带工具的最小验证(确认 parser 正确)
完整脚本:scripts_bash_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_内联_03.sh
运行/引用:bash /opt/workbuddy/scripts_bash_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_内联_03.sh
#!/usr/bin/env bash
set -euo pipefail
curl -s -X POST http://116.62.10.183:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer 123456" \
-d '{
"model": "qwen3.6-27b",
"messages": [{"role": "user", "content": "上海今天天气怎么样"}],
"tools": [{
"type": "function",
"function": {
"name": "get_weather",
"description": "查询天气",
"parameters": {"type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"]}
}
}],
"tool_choice": "auto"
}'期望:返回里有 tool_calls,且 name 为 get_weather。若此处报错,优先检查 --tool-call-parser qwen3_xml(专题四 C 类)。
四、第 2 层:Dify 服务器到模型端的网络是否可达?
vLLM 在 116.62.10.183:8000,Dify 在 192.168.110.207,必须能从 207 连到 116:8000。
在 Dify 服务器上执行:
完整脚本:scripts_bash_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_内联_04.sh
运行/引用:bash /opt/workbuddy/scripts_bash_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_内联_04.sh
#!/usr/bin/env bash
set -euo pipefail
curl -s -m 10 http://116.62.10.183:8000/v1/models \
-H "Authorization: Bearer 123456" | head如果超时/连接失败:
- 检查 116 服务器防火墙是否放行 8000;
- 检查 vLLM 是否
--host 0.0.0.0(不是127.0.0.1,否则外部不可访问); - 检查网络是否跨段被拦截。
之前保存凭据时如果报
Connection error/no available node,多半就是这里没通。
五、第 3 层:Dify 模型供应商凭据是否配对?
在 Dify「设置 → 模型供应商 → OpenAI-API-compatible」里,添加/编辑自定义模型时核对:
| 字段 | 正确值 | 常见错误 |
|---|---|---|
| API Base URL | http://116.62.10.183:8000/v1 | 忘写 /v1;写成 /v1/(多斜杠也可能通,但最好一致) |
| API Key | 123456 | vLLM 未启用鉴权时可任意填,但 Dify 要求非空 |
| 自定义模型名 | qwen3.6-27b | 必须与 vLLM --served-model-name 完全一致 |
| 模型类型 | LLM | 误选成 Text Embedding / Rerank |
保存时会触发 Dify 的连通性校验:它会用上面这些信息去 /v1/models 拉模型列表,拉不到就保存失败。
六、第 4 层:模型 schema 是否兼容(选不到 / 显示"不兼容")
现象:凭据保存成功,但前端模型列表里 qwen3.6-27b 显示"不兼容",或创建 Agent 时选不到。
根因:OpenAI 插件 models/llm/llm.py 的 get_customizable_model_schema 只认预定义 OpenAI 基座模型(如 gpt-4),自定义名 qwen3.6-27b 找不到,于是抛出 Base model qwen3.6-27b not found,前端据此标为不兼容。
解决:patch llm.py(文件在 plugin_daemon 容器挂载目录,路径类似):
/dify/dify-main/docker/volumes/plugin_daemon/cwd/langgenius/openai-1.0.3@<hash>/models/llm/llm.py把 get_customizable_model_schema 改成:找不到基座时,clone 一个 chat 能力的预定义 schema,并允许凭据里的 model_properties 覆盖 context_size / max_tokens。
完整补丁:patches_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_内联_01.py
运行/引用:见 patches_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_内联_01.py
def get_customizable_model_schema(
self, model: str, credentials: dict
) -> AIModelEntity:
schema = {item.model: item for item in self.predefined_models()}.get(
_base_model(model)
)
if schema is None:
# Fallback for custom / non-OpenAI base models served via an
# OpenAI-compatible endpoint (e.g. Qwen, DeepSeek, local vLLM):
# clone a chat-capable predefined schema so the model is listable
# and can be set as the default model.
template = next(
(m for m in self.predefined_models()
if m.model_properties.get("mode") == "chat"),
None,
)
if template is None:
template = self.predefined_models()[0]
props = dict(template.model_properties)
mp = (credentials or {}).get("model_properties") or {}
try:
if "context_size" in mp:
props["context_size"] = int(mp["context_size"])
if "max_tokens" in mp:
props["max_tokens"] = int(mp["max_tokens"])
except (ValueError, TypeError):
pass
schema = template.model_copy(deep=True, update={"model_properties": props})
return schema.model_copy(
deep=True,
update={
"model": model,
"label": I18nObject(zh_hans=model, en_us=model),
"fetch_from": FetchFrom.CUSTOMIZABLE_MODEL,
},
)改完重启:
完整脚本:scripts_bash_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_内联_05.sh
运行/引用:bash /opt/workbuddy/scripts_bash_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_内联_05.sh
#!/usr/bin/env bash
set -euo pipefail
cd /dify/dify-main/docker && docker compose restart plugin_daemon然后回到模型供应商页,重新保存凭据,qwen3.6-27b 应该变为可选/兼容。
七、第 5 层:默认 LLM 是否切到了 qwen3.6-27b?
现象:模型可选,但新建应用时默认仍是 gpt-5.6 之类的旧模型,导致问答时报 The model gpt-5.6 does not exist。
7.1 先看当前默认模型
完整脚本:scripts_bash_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_内联_06.sh
运行/引用:bash /opt/workbuddy/scripts_bash_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_内联_06.sh
#!/usr/bin/env bash
set -euo pipefail
docker exec docker-db_postgres-1 psql -U postgres -d dify -c \
"SELECT model_type, provider_name, model_name FROM tenant_default_models;"期望看到:
model_type | provider_name | model_name
----------------+----------------------------------+-------------
llm | langgenius/openai/openai | qwen3.6-27b
text-embedding | langgenius/xinference/xinference | bge-m37.2 如果 llm 还是 gpt-5.6,改成 qwen3.6-27b
完整脚本:scripts_bash_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_内联_07.sh
运行/引用:bash /opt/workbuddy/scripts_bash_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_内联_07.sh
#!/usr/bin/env bash
set -euo pipefail
# 获取当前登录用户对应的 tenant_id
TENANT_ID=$(docker exec docker-db_postgres-1 psql -U postgres -d dify -tc \
"SELECT id FROM tenants WHERE email='38205036@qq.com'" | xargs)
# 把 llm 默认模型改成 qwen3.6-27b
docker exec docker-db_postgres-1 psql -U postgres -d dify -c \
"UPDATE tenant_default_models
SET provider_name='langgenius/openai/openai', model_name='qwen3.6-27b'
WHERE tenant_id='$TENANT_ID' AND model_type='llm';"7.3 重启 Dify 相关容器
完整脚本:scripts_bash_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_内联_08.sh
运行/引用:bash /opt/workbuddy/scripts_bash_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_内联_08.sh
#!/usr/bin/env bash
set -euo pipefail
cd /dify/dify-main/docker && docker compose restart api worker plugin_daemon新建应用时默认 LLM 就会是 qwen3.6-27b。
八、第 6 层:plugin_daemon 是否加载了 patch?
现象:明明改了 llm.py 或 chat.py,但问题照旧,像没改一样。
根因:OpenAI 插件在 plugin_daemon 容器内被 Python 导入后缓存,必须重启容器才能加载新文件; 或者 patch 写到了 from __future__ import annotations 之前,触发 SyntaxError,导致整个 openai 插件加载失败。
8.1 检查 plugin_daemon 是否健康
完整脚本:scripts_bash_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_内联_09.sh
运行/引用:bash /opt/workbuddy/scripts_bash_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_内联_09.sh
#!/usr/bin/env bash
set -euo pipefail
docker ps --filter name=plugin_daemon --format '{{.Names}} {{.Status}}'
# 应显示 docker-plugin_daemon-1 Up ...8.2 检查插件加载日志有无 Python 报错
完整脚本:scripts_bash_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_内联_10.sh
运行/引用:bash /opt/workbuddy/scripts_bash_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_内联_10.sh
#!/usr/bin/env bash
set -euo pipefail
docker logs docker-plugin_daemon-1 2>&1 | grep -iE 'error|syntax|traceback|openai' | tail -20如果看到 SyntaxError: from __future__ imports must occur at the beginning,说明 chat.py 里的函数被写到了 from __future__ 之前,需要上移。
8.3 改完任何 patch 都要重启
完整脚本:scripts_bash_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_内联_11.sh
运行/引用:bash /opt/workbuddy/scripts_bash_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_内联_11.sh
#!/usr/bin/env bash
set -euo pipefail
cd /dify/dify-main/docker && docker compose restart plugin_daemon
# 等 5-10 秒
sleep 8
docker ps --filter name=plugin_daemon --format '{{.Names}} {{.Status}}'九、第 7 层:问答时 system 消息格式是否正确?
现象:前面全通了,但只要一发消息就报 400 System message must be at the beginning。
根因与解决:Qwen3 的 chat template 只接受一条 system 消息且在最前,而 Dify Agent 会把知识库助手提示 + Agent 工具提示 + 空 system + 配置 + 环境变量多条 system 堆在最前面。需要在 chat.py 里把它们合并成一条。
文件路径同 llm.py,只是改 models/llm/chat.py。在 from __future__ import annotations 之后加入/替换:
完整程序:/opt/workbuddy/scripts_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_内联_01.py
运行/引用:/usr/bin/python3 /opt/workbuddy/scripts_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_内联_01.py
def _ensure_system_first(messages: list[PromptMessage]) -> list[PromptMessage]:
"""Qwen3/vLLM chat templates accept ONLY one system message, at the start.
Dify (esp. Agent apps) stacks several system/developer prompts: KB assistant
prompt + agent tool prompt + an empty system + config manifest... Merging them
into a single system message (joined by blank lines, empties dropped) keeps it
at the front; every other message keeps its original relative order.
"""
system_parts: list[str] = []
rest: list[PromptMessage] = []
for m in messages:
if isinstance(m, (SystemPromptMessage, DeveloperPromptMessage)):
text = _text_content(m)
if text.strip():
system_parts.append(text)
else:
rest.append(m)
if system_parts:
rest.insert(0, SystemPromptMessage(content="\n\n".join(system_parts)))
return rest调用处:在 client.chat.completions.create 里把 prompt_messages 包一层:
完整程序:/opt/workbuddy/scripts_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_内联_02.py
运行/引用:/usr/bin/python3 /opt/workbuddy/scripts_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_内联_02.py
response = client.chat.completions.create(
model=model,
messages=cast(Any, [message(item) for item in _ensure_system_first(prompt_messages)]),
stream=stream,
...
)改完重启 plugin_daemon,然后重新提问验证。详细抓日志、直连复现的方法见 Dify_专题四_Agent问答报错.md。
十、常见"假成功"陷阱速查
| 现象 | 你以为的问题 | 真正原因 |
|---|---|---|
docker logs 显示 startup complete | 模型可用 | 还要 curl /v1/models 和 /v1/chat/completions 验证 |
| 模型在 116 本机 curl 通 | 网络没问题 | Dify 在 207,要从 207 curl 116:8000 才算通 |
| Dify 凭据保存成功 | 模型配好了 | 还要看是否显示"不兼容"、默认模型是否指向 qwen |
改了 chat.py 但还报错 | 改错了 | 多半是没重启 plugin_daemon,或插件加载失败 |
| 普通聊天助手能用,Agent 不行 | Agent 配置错 | 是 Agent 塞了多条 system,必须合并 |
| 第一次问答正常,重启后不行了 | 模型挂了 | vLLM 容器可能 Exited,或者 Xinference 里的 bge-m3 实例掉了 |
十一、落地清单(按顺序排查)
- [ ] 第 1 层:
curl /v1/models能列出qwen3.6-27b; - [ ] 第 1 层:
curl /v1/chat/completions单轮对话返回内容; - [ ] 第 2 层:从 Dify 服务器
curl 116.62.10.183:8000/v1/models通; - [ ] 第 3 层:Dify OpenAI 兼容凭据 API Base=
http://116.62.10.183:8000/v1、Key=123456、模型名=qwen3.6-27b; - [ ] 第 4 层:如果显示"不兼容",按本文 patch
llm.py并重启plugin_daemon; - [ ] 第 5 层:数据库里
tenant_default_models的llm行已改为qwen3.6-27b; - [ ] 第 6 层:
docker logs docker-plugin_daemon-1无 Python/SyntaxError; - [ ] 第 7 层:如果还报
System message...,按本文 patchchat.py合并 system 并重启plugin_daemon; - [ ] 最终验证:通过 Agent API
streaming模式发一条问题,无event: error且能正常返回知识库答案。
十二、关联文档
Dify_Qwen安装配置手册.md:从零开始部署 Dify + vLLM(Qwen3.6-27B) + BGE-M3 的纯步骤版;Dify_专题一_集成Qwen3.6-27B.md:专题一,详解如何在模型供应商入口添加 qwen3.6-27b 并让其可选;Dify_专题二_Xinference运行bge-m3.md:专题二,讲 Xinference 如何跑起 bge-m3;Dify_专题三_Agent知识库选择.md:专题三,讲 Agent 里选不到知识库的解决;Dify_专题四_Agent问答报错.md:专题四,讲问答时报错的排查(400 System message / Connection / 工具解析)。
十三、实战记录(本次部署真实遇到的情况)
本专题的引子就是那张截图:"大模型运行成功了 这里还是不行"。按统一维度拆解真实经过。
现象:docker logs vllm-qwen3.6-27b 显示 Application startup complete,但 Dify 里发消息仍报 System message must be at the beginning。
定位(按 7 层逐层查):
- 第 1 层
curl /v1/models能列qwen3.6-27b、单轮对话也通; - 第 2 层从 Dify 服务器(207)
curl 116:8000也通; - 第 3 层 Dify 凭据配对 OK;
- 第 4 层模型不再显示"不兼容"(llm.py 已 patch);
- 第 5 层默认 llm 已指向 qwen3.6-27b——前 5 层都 OK。
改了什么(真正卡在第 6+7 层):早期给 chat.py 打的"置顶 system"补丁只排序没合并,且一度因函数写在 from __future__ import annotations 之前触发 SyntaxError,导致整个 openai 插件没真正加载(保存凭据时还报过 no available node)。修复:
- 把
_ensure_system_first重写为"合并"逻辑; - 把新增函数移到
from __future__之后; - 备份
chat.py.bak_systemfix/llm.py.bak_qwenfix。
怎么重启服务: 完整脚本:scripts_bash_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_内联_12.sh
运行/引用:bash /opt/workbuddy/scripts_bash_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_内联_12.sh
#!/usr/bin/env bash
set -euo pipefail
cd /dify/dify-main/docker && docker compose restart plugin_daemon
# 若改过 default model 也要重启:
docker compose restart api worker plugin_daemon怎么看日志: 完整脚本:scripts_bash_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_内联_13.sh
运行/引用:bash /opt/workbuddy/scripts_bash_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_内联_13.sh
#!/usr/bin/env bash
set -euo pipefail
docker logs docker-plugin_daemon-1 2>&1 | grep -iE 'error|syntax|traceback|openai' | tail -20
# 应无 SyntaxError / Traceback,能看到 openai 插件正常 register怎么判断正常:用 Agent API streaming 实测发一条问题,无 event: error 且能正常返回知识库答案(详见专题四 2.6)。
对照专题四:本专题的"假成功"在第 6 节有速查表,这次根因就是其中"模型在 116 本机通、但插件没加载 patch"那一行。
一句话对照:专题五前面是"7 层排查法",本节是"用户截图那个场景被按这 7 层一步步定位到第 7 层并修好"的真实经过。
本专题 Python 程序一览
| 文件 | 用途 | |---|---|| 专题五_01_验证vLLM三层.py | 专题五 · 步骤 1:验证 vLLM 三层(列模型 / 单轮对话 / 工具调用)。 | | 专题五_02_验证207到vLLM网络.py | 专题五 · 步骤 2:从 Dify 服务器验证到 vLLM 的网络可达性。 | | 专题五_03_查默认LLM模型.py | 专题五 · 步骤 3:查询 tenant_default_models 当前默认 LLM。 | | 专题五_04_改默认LLM为Qwen_修改后.py | 专题五 · 步骤 4 · 修改后:把 tenant 默认 LLM 改为 qwen3.6-27b 并重启 api/worker/plugin。 | | 专题五_05_检查plugin_daemon健康.py | 专题五 · 步骤 5:检查 plugin_daemon 容器状态与 Python 加载错误。 | | 专题五_06_应用llm_schema补丁_修改后.py | 专题五 · 步骤 6 · 修改后:patch llm.py get_customizable_model_schema(自定义模型可选)。 | | 专题五_07_应用chat合并system补丁_修改后.py | 专题五 · 步骤 7 · 修改后:patch chat.py 合并多条 system(同专题四步骤 4)。 |
专题五_01_验证vLLM三层.py
运行:/usr/bin/python3 /opt/workbuddy/scripts_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_01_验证vLLM三层.py
完整补丁:patches_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_内联_02.py
运行/引用:见 patches_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_内联_02.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""专题五 · 步骤 1:验证 vLLM 三层(列模型 / 单轮对话 / 工具调用)。"""
from __future__ import annotations
import json
import sys
import _bootstrap # noqa: F401
import _config as C
from dify_api import Dify
def curl_json(d: Dify, cmd: str, label: str) -> None:
out, err = d.sh(cmd, t=120)
print("\n=== %s ===" % label)
print((out or err)[:1500])
def main() -> int:
d = Dify(C.DIFY_EMAIL, C.DIFY_PASSWORD)
try:
d.login()
auth = "-H 'Authorization: Bearer %s'" % C.VLLM_KEY
curl_json(
d,
"curl -s %s/v1/models %s | head -c 800" % (C.VLLM_URL, auth),
"3.1 GET /v1/models",
)
chat_body = {
"model": C.LLM_MODEL,
"messages": [
{"role": "system", "content": "你是一个助手"},
{"role": "user", "content": "你好"},
],
"max_tokens": 128,
}
remote = "/tmp/vllm_chat_smoke.json"
with d.sftp.open(remote, "w") as f:
f.write(json.dumps(chat_body, ensure_ascii=False))
curl_json(
d,
"curl -s -X POST %s/v1/chat/completions -H 'Content-Type: application/json' %s -d @%s"
% (C.VLLM_URL, auth, remote),
"3.2 POST /v1/chat/completions",
)
tool_body = {
"model": C.LLM_MODEL,
"messages": [{"role": "user", "content": "上海今天天气怎么样"}],
"tools": [{
"type": "function",
"function": {
"name": "get_weather",
"description": "查询天气",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"],
},
},
}],
"tool_choice": "auto",
}
remote2 = "/tmp/vllm_tool_smoke.json"
with d.sftp.open(remote2, "w") as f:
f.write(json.dumps(tool_body, ensure_ascii=False))
curl_json(
d,
"curl -s -X POST %s/v1/chat/completions -H 'Content-Type: application/json' %s -d @%s"
% (C.VLLM_URL, auth, remote2),
"3.3 POST /v1/chat/completions(带 tools)",
)
return 0
finally:
d.close()
if __name__ == "__main__":
sys.exit(main())专题五_02_验证207到vLLM网络.py
运行:/usr/bin/python3 /opt/workbuddy/scripts_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_02_验证207到vLLM网络.py
完整补丁:patches_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_内联_03.py
运行/引用:见 patches_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_内联_03.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""专题五 · 步骤 2:从 Dify 服务器验证到 vLLM 的网络可达性。"""
from __future__ import annotations
import sys
import _bootstrap # noqa: F401
import _config as C
from dify_api import Dify
def main() -> int:
d = Dify(C.DIFY_EMAIL, C.DIFY_PASSWORD)
try:
d.login()
cmd = (
"curl -s -m 10 %s/v1/models -H 'Authorization: Bearer %s' | head -c 800"
% (C.VLLM_URL, C.VLLM_KEY)
)
out, err = d.sh(cmd, t=30)
text = out or err
print(text)
if C.LLM_MODEL in text:
print("\n[OK] 从 Dify 服务器可达 vLLM,且列出 %s" % C.LLM_MODEL)
return 0
print("\n[FAIL] 未在响应中看到 %s" % C.LLM_MODEL)
return 1
finally:
d.close()
if __name__ == "__main__":
sys.exit(main())专题五_03_查默认LLM模型.py
运行:/usr/bin/python3 /opt/workbuddy/scripts_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_03_查默认LLM模型.py
完整补丁:patches_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_内联_04.py
运行/引用:见 patches_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_内联_04.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""专题五 · 步骤 3:查询 tenant_default_models 当前默认 LLM。"""
from __future__ import annotations
import sys
import _bootstrap # noqa: F401
import _config as C
from dify_api import Dify
def main() -> int:
d = Dify(C.DIFY_EMAIL, C.DIFY_PASSWORD)
try:
d.login()
sql = (
"docker exec %s psql -U postgres -d dify -c "
"\"SELECT model_type, provider_name, model_name FROM tenant_default_models;\"" % C.PG_CONTAINER
)
out, err = d.sh(sql)
print(out or err)
return 0
finally:
d.close()
if __name__ == "__main__":
sys.exit(main())专题五_04_改默认LLM为Qwen_修改后.py
运行:/usr/bin/python3 /opt/workbuddy/scripts_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_04_改默认LLM为Qwen_修改后.py
完整补丁:patches_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_内联_05.py
运行/引用:见 patches_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_内联_05.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""专题五 · 步骤 4 · 修改后:把 tenant 默认 LLM 改为 qwen3.6-27b 并重启 api/worker/plugin。"""
from __future__ import annotations
import sys
import _bootstrap # noqa: F401
import _config as C
from dify_api import Dify
def main() -> int:
d = Dify(C.DIFY_EMAIL, C.DIFY_PASSWORD)
try:
d.login()
tenant_sql = (
"docker exec %s psql -U postgres -d dify -tc "
"\"SELECT id FROM tenants WHERE email='%s'\"" % (C.PG_CONTAINER, C.DIFY_EMAIL)
)
out, err = d.sh(tenant_sql)
tenant_id = out.strip()
if not tenant_id:
print("未找到 tenant:", err)
return 1
print("tenant_id:", tenant_id)
upd = (
"docker exec %s psql -U postgres -d dify -c "
"\"UPDATE tenant_default_models SET provider_name='%s', model_name='%s' "
"WHERE tenant_id='%s' AND model_type='llm';\"" % (
C.PG_CONTAINER, C.OPENAI_PROVIDER, C.LLM_MODEL, tenant_id
)
)
out2, err2 = d.sh(upd)
print(out2 or err2)
out3, err3 = d.sh(
"cd %s && docker compose restart api worker plugin_daemon" % C.DIFY_DOCKER_DIR,
t=180,
)
print(out3 or err3)
return 0
finally:
d.close()
if __name__ == "__main__":
sys.exit(main())专题五_05_检查plugin_daemon健康.py
运行:/usr/bin/python3 /opt/workbuddy/scripts_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_05_检查plugin_daemon健康.py
完整补丁:patches_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_内联_06.py
运行/引用:见 patches_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_内联_06.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""专题五 · 步骤 5:检查 plugin_daemon 容器状态与 Python 加载错误。"""
from __future__ import annotations
import sys
import _bootstrap # noqa: F401
import _config as C
from dify_api import Dify
def main() -> int:
d = Dify(C.DIFY_EMAIL, C.DIFY_PASSWORD)
try:
d.login()
out1, _ = d.sh(
"docker ps --filter name=plugin_daemon --format '{{.Names}} {{.Status}}'"
)
print("=== plugin_daemon 状态 ===")
print(out1.strip())
out2, _ = d.sh(
"docker logs %s 2>&1 | grep -iE 'error|syntax|traceback|openai' | tail -20"
% C.PLUGIN_CONTAINER
)
print("\n=== 最近 plugin 相关日志 ===")
print(out2.strip() or "(无匹配行,通常表示 OK)")
return 0
finally:
d.close()
if __name__ == "__main__":
sys.exit(main())专题五_06_应用llm_schema补丁_修改后.py
运行:/usr/bin/python3 /opt/workbuddy/scripts_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_06_应用llm_schema补丁_修改后.py
完整补丁:patches_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_内联_07.py
运行/引用:见 patches_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_内联_07.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""专题五 · 步骤 6 · 修改后:patch llm.py get_customizable_model_schema(自定义模型可选)。"""
from __future__ import annotations
import sys
import _bootstrap # noqa: F401
import _config as C
import _plugin_patch as P
from dify_api import Dify
def main() -> int:
d = Dify(C.DIFY_EMAIL, C.DIFY_PASSWORD)
try:
d.login()
llm_path = P.find_plugin_file(d, "llm.py")
print("llm.py:", llm_path)
content = P.read_remote_file(d, llm_path)
new_content = P.replace_method(
content, "get_customizable_model_schema", P.GET_CUSTOMIZABLE_MODEL_SCHEMA
)
P.deploy_plugin_file(d, llm_path, new_content)
print("已应用 llm.py schema 补丁并重启 plugin_daemon")
return 0
finally:
d.close()
if __name__ == "__main__":
sys.exit(main())专题五_07_应用chat合并system补丁_修改后.py
运行:/usr/bin/python3 /opt/workbuddy/scripts_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_07_应用chat合并system补丁_修改后.py
完整补丁:patches_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_内联_08.py
运行/引用:见 patches_cursor/Dify_专题五_大模型运行成功但Dify仍不可用/专题五_内联_08.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""专题五 · 步骤 7 · 修改后:patch chat.py 合并多条 system(同专题四步骤 4)。"""
from __future__ import annotations
import sys
import _bootstrap # noqa: F401
import _plugin_patch as P
from dify_api import Dify
import _config as C # noqa: F401
def main() -> int:
d = Dify(C.DIFY_EMAIL, C.DIFY_PASSWORD)
try:
d.login()
chat_path = P.find_plugin_file(d, "chat.py")
content = P.read_remote_file(d, chat_path)
new_content = P.replace_function(content, "_ensure_system_first", P.ENSURE_SYSTEM_FIRST)
P.deploy_plugin_file(d, chat_path, new_content)
print("已应用 chat.py 合并 system 补丁")
return 0
finally:
d.close()
if __name__ == "__main__":
sys.exit(main())