支持Markdown包裹的base64图片直发

1. 为Dify聊天插件新增Markdown图片语法解析,支持从 ![image](data:image/...;base64,...) 中提取内联图片。

2. 兼容JSON里text/answer/result/content字段承载Markdown图片的返回格式。

3. 避免绘图模型返回Markdown图片时被误判为普通文本而继续走md2image。
This commit is contained in:
liuwei
2026-04-28 16:37:35 +08:00
parent 3b2dcb5cae
commit 6003aa7beb

View File

@@ -561,7 +561,8 @@ class DifyPlugin(MessagePluginInterface):
支持的输入形态:
1. `data:image/png;base64,...` 这类 data URL
2. 纯 base64 图片字符串;
3. JSON 字符串里常见的 `b64_json` / `image_base64` / `base64` / `data` 字段。
3. Markdown 图片语法中的 data URL例如 `![image](data:image/png;base64,...)`
4. JSON 字符串里常见的 `b64_json` / `image_base64` / `base64` / `data` 字段。
"""
normalized_text = str(response_text or "").strip()
if not normalized_text:
@@ -572,6 +573,15 @@ class DifyPlugin(MessagePluginInterface):
if image_bytes and str(mime_type or "").startswith("image/"):
return image_bytes
# 再处理 Markdown 包裹的 data URL。
# 当前绘图模型常见返回形态就是:![image_1](data:image/png;base64,...)
# 如果不先拆出来,后续会把整段 Markdown 当作普通文本,最终误走 md2image。
markdown_data_url = self._extract_data_url_from_markdown(normalized_text)
if markdown_data_url:
image_bytes, mime_type = UnifiedLLMClient.decode_data_url(markdown_data_url)
if image_bytes and str(mime_type or "").startswith("image/"):
return image_bytes
# 再尝试把字符串解析为 JSON兼容工作流把 base64 包在结构化字段里的情况。
# 这里优先挑常见图片字段,避免把普通 JSON 文本误判成图片。
json_candidate = self._extract_base64_from_json_text(normalized_text)
@@ -595,6 +605,27 @@ class DifyPlugin(MessagePluginInterface):
value = parsed.get(key)
if isinstance(value, str) and value.strip():
return value.strip()
# 一些返回会把 markdown 图片包在 text 字段里,这里顺手兼容。
if key == "data":
continue
for key in ("text", "answer", "result", "content"):
value = parsed.get(key)
if isinstance(value, str) and value.strip():
markdown_data_url = self._extract_data_url_from_markdown(value.strip())
if markdown_data_url:
return markdown_data_url
return ""
def _extract_data_url_from_markdown(self, text: str) -> str:
"""从 Markdown 图片语法中提取 data URL。"""
normalized = str(text or "").strip()
if not normalized:
return ""
# 匹配形如 ![alt](data:image/png;base64,...)
match = re.search(r"!\[[^\]]*\]\((data:image/[^)]+)\)", normalized, flags=re.IGNORECASE | re.DOTALL)
if match:
return match.group(1).strip()
return ""
def _decode_base64_image_bytes(self, candidate: str) -> bytes: