diff --git a/plugins/dify/main.py b/plugins/dify/main.py index dba55fb..a01ca55 100644 --- a/plugins/dify/main.py +++ b/plugins/dify/main.py @@ -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: