跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像AI 生图工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
PythonSaaSAI算法

Python 调用 Dify API 实现知识检索与前端溯源展示

如何使用 Python 调用 Dify HTTP API 进行聊天问答及文件上传。核心流程包括上传文件获取 ID、发送消息(支持文本和图文)以及删除会话。文章提供了封装类 DifyChat 的代码示例,展示了如何解析响应数据,特别是 metadata 中的 retriever_resources 字段,以便前端实现知识检索内容的溯源展示。

黑客发布于 2026/4/6更新于 2026/7/743 浏览
Python 调用 Dify API 实现知识检索与前端溯源展示

一、Dify 聊天示例脚本说明

本脚本演示了如何通过 Dify HTTP API 进行聊天问答,并可选携带图片。核心流程:

  1. 上传文件(可选)
    • 调用 /v1/files/upload 上传本地图片,得到 upload_file_id。
    • 只有在需要图文问答时才上传;纯文本时可跳过。
  2. 发送对话消息
    • 调用 /v1/chat-messages,必填 query,可选传 files(当有 upload_file_id 时)。
    • response_mode = "blocking" 表示同步等待完整答案;如需流式可改为 "streaming" 并按 SSE 解析。
  3. 删除会话(可选)
    • 调用 DELETE /v1/conversations/{id};返回可能是 204 空 body,因此需要容错解析。

1.1、代码结构

  • DifyChat:极简封装,包含 upload_file、send、delete、create_chat(可选)。
  • _safe_parse_response:统一解析响应,优先尝试 JSON;否则返回状态码和文本,避免 JSONDecodeError。
  • 示例入口:根据 image_path 是否存在,选择纯文本或图文问答,并打印答案。

1.2、快速使用

  1. 配置:
    • api_url: 你的 Dify 服务地址(到 /v1)。
    • api_key: Dify 应用的 API Key(通常以 app- 开头)。
    • user: 请求用户标识,用于配额和会话归属。

可选删除会话:

if ret_send.get("conversation_id"): ret_delete = chat.delete(ret_send["conversation_id"])print(ret_delete)

图文问答:

ret_upload = chat.upload_file("xxx.jpg") file_id = ret_upload["id"] ret_send = chat.send("你的问题", file_id=file_id)print(ret_send.get("answer"))

纯文本问答:

chat = DifyChat(api_url, api_key) ret_send = chat.send("你的问题")print(ret_send.get("answer"))

1.3、注意事项

  • files 字段仅在传入 file_id 时添加,允许无图时直接问答。
  • upload_file 使用 with open 避免句柄泄漏,并在 multipart 表单里传 user。
  • delete 可能返回 204/空 body,必须使用安全解析。
  • 示例里用 ret_send、ret_delete 避免变量覆盖导致拿不到 answer。
  • 若要流式输出,将 response_mode 改为 "streaming" 并按 SSE 处理返回。

1.4、适配其他项目的改动指引

  • 如需在多线程/多协程环境复用:将会话 id 存储在线程上下文或显式传入。
  • 若有多用户:实例化时传入不同 user 值;或在方法参数增加 user 覆盖。
  • 如需支持多文件:在 send 中把 data["files"] 扩展为文件列表,并按 Dify 要求传 type/transfer_method/upload_file_id。
  • 若要改为流式:封装一个 send_stream,使用 stream=True 并消费 SSE 事件。

二、代码部分

import os.path
import requests

class DifyChat:
    """ 一个极简的 Dify HTTP API 调用封装(适合快速验证流程)。
    你这里用到的核心接口:
    - POST /v1/chat-messages 发起一次对话消息(可选携带图片)
    - POST /v1/files/upload 上传文件,得到 upload_file_id(给 chat-messages 的 files 用)
    - DELETE /v1/conversations/{id} 删除会话(有的服务端会返回空 body)
    """
    def __init__(self, api_url, api_key, user="abc-123"):
        """ :param api_url: Dify 服务地址(到 /v1 这一层),例如 http://10.0.100.98/v1
        :param api_key: Dify 应用 API Key(通常以 app- 开头)
        :param user: 用于标识请求用户的字符串。Dify 多数接口需要这个字段用于配额/会话归属。 
        """
        self.api_url = api_url
        self.api_key = api_key
        self.user = user
        # JSON 请求通用 Header(upload_file 是 multipart,会单独传 headers)
        self.headers = {'Authorization': f'Bearer {self.api_key}', 'Content-Type': 'application/json'}

    @staticmethod
    def _safe_parse_response(response):
        """ 尽量把响应解析成 JSON。
        - 像 DELETE 这类接口,经常返回 204 No Content(空 body)
        - 或者返回纯文本/HTML 错误页(不是 JSON)
        因此这里做'兜底',避免直接 response.json() 抛 JSONDecodeError。
        """
        try:
            # 204/205 等可能无 body
            if response.status_code in (204, 205) or not response.content:
                return {"status_code": response.status_code, "ok": response.ok, "text": ""}
            return response.json()
        except Exception:
            return {"status_code": response.status_code, "ok": response.ok, "text": response.text,}

    def create_chat(self, chat_name):
        """ 创建 chat(是否需要取决于你的 Dify 应用/版本;很多情况下直接用 chat-messages 即可)。 
        """
        url = f'{self.api_url}/chats/create'
        data = {'chat_name': chat_name}
        response = requests.post(url, json=data, headers=self.headers)
        return self._safe_parse_response(response)

    def send(self, message, file_id=None, conversation_id=""):
        """ 发送一条消息(文本问答),可选带图片。
        :param message: 用户问题/提示词(query)
        :param file_id: upload_file 接口返回的 id(即 upload_file_id);不传则表示纯文本问答
        :param conversation_id: 继续同一个会话时传入;留空表示开启新会话
        """
        url = f'{self.api_url}/chat-messages'
        data = {
            # inputs: 给'工作流应用/带变量的应用'传入输入变量;纯聊天一般为空即可
            "inputs": {},
            # query: 你的提问文本
            "query": message,
            # blocking: 同步等待完整结果;如果你要流式输出,可改为 streaming(并按 SSE 解析)
            "response_mode": "blocking",
            # conversation_id: 传入就续聊,不传就新开一轮会话
            "conversation_id": conversation_id or "",
            # user: 用于标识请求用户
            "user": self.user
        }
        # 只有在传入 file_id 时才携带 files 字段(不传图就纯文本问答)
        # files 的含义:告诉 Dify'本次对话引用了哪些已上传文件'。
        if file_id:
            data["files"] = [
                {
                    # type: 文件类型,这里是 image
                    "type": "image",
                    # transfer_method: local_file 表示使用'先上传 /files/upload,再在此引用 upload_file_id'的方式
                    "transfer_method": "local_file",
                    # upload_file_id: /files/upload 返回的 id
                    "upload_file_id": file_id
                }
            ]
        response = requests.post(url, json=data, headers=self.headers)
        return self._safe_parse_response(response)

    def delete(self, conver_id):
        """ 删除会话。
        注意:服务端可能返回 204(空响应体),所以不能直接 response.json()。
        """
        url = f'{self.api_url}/conversations/{conver_id}'
        data = {"user": self.user}
        response = requests.delete(url, json=data, headers=self.headers)
        return self._safe_parse_response(response)

    def upload_file(self, file_path):
        """ 上传本地文件到 Dify,返回值中通常包含:{"id": "..."}。
        随后把这个 id 作为 send(..., file_id=...) 的 upload_file_id 来引用。
        """
        url = f'{self.api_url}/files/upload'
        # Dify 通常要求 multipart form 里带 user 字段
        data = {"user": self.user}
        headers = {'Authorization': f'Bearer {self.api_key}'}
        with open(file_path, 'rb') as f:
            files = {'file': ("a.jpg", f, 'image/jpg')}
        response = requests.post(url, files=files, data=data, headers=headers)
        return self._safe_parse_response(response)

# 示例
if __name__ == "__main__":
    # 你的 Dify 服务地址(到 /v1)
    api_url = "http://127.0.0.1/v1"
    # 你的应用 API Key
    api_key = "app-xxxxxxxxxxxxxxxxxxxx"
    # 你的提问 query
    query = "时空之战的主要人物有哪些?"
    # image_path 为空字符串或不存在文件时:纯文本问答
    # image_path 指向真实图片文件时:会先上传图片,再在对话里引用该图片
    image_path = ""
    # image_path = "./beiguangdeshudianta1.jpg"
    chat = DifyChat(api_url, api_key)
    if not os.path.exists(image_path):
        # 方式 1:不上传图片,纯文本问答
        ret_send = chat.send(query)
    else:
        # 方式 2:需要图片时才上传,并把 file_id 带到 send 里
        ret_upload = chat.upload_file(image_path)
        file_id = ret_upload["id"]
        ret_send = chat.send(query, file_id=file_id)
    # send 的返回里一般会有 message_id / conversation_id / answer 等字段
    message_id = ret_send.get("message_id")
    conver_id = ret_send.get("conversation_id")
    print(ret_send)
    # 如果你的应用正常返回 answer,这里会打印答案
    if isinstance(ret_send, dict) and "answer" in ret_send:
        print(ret_send["answer"])
    # 可选:删除会话(有的场景你不需要删,保留会话便于续聊)
    # 注意:delete 的返回可能是 204 空 body,因此 ret_delete 不一定包含 JSON 字段
    if conver_id:
        ret_delete = chat.delete(conver_id)
        print(ret_delete)

三、返回内容分析

ret_send 的返回全部内容如下:

{
  'event': 'message',
  'task_id': 'e50a0154-5523-4c1a-93de-ae45a2568d00',
  'id': 'c3f11257-cc16-4718-84f8-f5a550b38757',
  'message_id': 'c3f11257-cc16-4718-84f8-f5a550b38757',
  'conversation_id': '3a1f9dd3-97a0-4d6e-bf74-bae87754ab02',
  'mode': 'advanced-chat',
  'answer': '根据提供的知识内容,时空之战的主要人物包括:\n\n1. 大雄:故事的主角,原本性格懦弱、逃避责任,但在经历未来世界的战斗后实现内心成长。\n2. 哆啦 A 梦:大雄的好朋友,来自未来的机器猫,拥有众多神奇道具,是事件的关键推动者。\n3. 特兰克斯:来自未来的超级赛亚人,身披战甲,拥有强大战斗力,为拯救未来世界而寻求帮助。\n',
  'metadata': {
    'retriever_resources': [
      {
        'position': 1,
        'dataset_id': '04adf974-e176-4d80-8d56-9720718b2b37',
        'dataset_name': '时空之战_1',
        'document_id': '时空之战.md',
        'document_name': '时空之战.md',
        'data_source_type': None,
        'segment_id': None,
        'retriever_from': 'workflow',
        'score': 0.36003251935408387,
        'hit_count': None,
        'word_count': None,
        'segment_position': None,
        'index_node_hash': None,
        'content': '# 哆啦 A 梦与超级赛亚人:时空之战\n\n在一个寻常的午后,大雄依旧坐在书桌前发呆,作业堆得像山,连第一页都没动。...',
        'page': None,
        'doc_metadata': None
      },
      ...
    ],
    'usage': {
      'prompt_tokens': 22886,
      'completion_tokens': 413,
      'total_tokens': 23299,
      ...,
      'latency': 4.649309985339642
    }
  },
  'created_at': 1769582803
}

其中 answer 是需要展示的内容:

根据提供的知识内容,时空之战的主要人物包括:
1. 大雄:故事的主角,原本性格懦弱、逃避责任,但在经历未来世界的战斗后实现内心成长。
2. 哆啦 A 梦:大雄的好朋友,来自未来的机器猫,拥有众多神奇道具,是事件的关键推动者。
3. 特兰克斯:来自未来的超级赛亚人,身披战甲,拥有强大战斗力,为拯救未来世界而寻求帮助。

其中,知识检索的内容,存储在了 metadata 内,可用作前端对'知识检索'原文的追溯。

四、总结

通过这样一个简单的示例调用,展示了调用 Dify 服务的整个过程,尤其是与前后端人员的交互,清楚的知道了返回内容,便于展示需要。

目录

  1. 一、Dify 聊天示例脚本说明
  2. 1.1、代码结构
  3. 1.2、快速使用
  4. 1.3、注意事项
  5. 1.4、适配其他项目的改动指引
  6. 二、代码部分
  7. 示例
  8. 三、返回内容分析
  9. 四、总结
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 7 款 AI 工具助力产品经理工作效率提升
  • TradingView 免费 Webhook 警报搭建指南
  • AI 时代产品经理:从需求到上线的全流程管控实战
  • Flutter for OpenHarmony 通义万相 AIGC 联调与相册持久化
  • Dify Web 前端二次开发:隐藏探索功能与替换 Logo
  • Oracle 统计信息自动收集任务检查与调整
  • 使用 Ollama 本地部署 Llama 3.1 大模型指南
  • 深入解析卷积神经网络(CNN):理论、实现与应用
  • 一切皆是映射:深入理解 DQN 的稳定性与收敛性
  • OpenClaw 腾讯云服务器部署与飞书对接实战
  • DeepSeek Janus-Pro 多模态大模型本地部署指南
  • Python 爬虫实战:从基础抓取到多线程下载优化
  • 算法基础:常见位运算技巧与实战总结
  • 2025 年开源图生图模型盘点:Kandinsky 5.0、Qwen-Image 与 Z-Image
  • 基于 Qwen3-VL 的操作视频智能评分系统部署实战
  • C、Java、Python 三大语言对比与未来选择指南
  • CATE 条件平均处理效应估计:五大方法原理详解与 Python 实战
  • AI 辅助编程的边界探索:当 Copilot 学会写测试
  • GitHub Copilot、Cursor 与 Codeium 三款 AI 编程工具深度对比
  • 大语言模型(LLM)技术深度解析与架构演进

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • RSA密钥对生成器

    生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online

  • Mermaid 预览与可视化编辑

    基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online

  • 随机西班牙地址生成器

    随机生成西班牙地址(支持马德里、加泰罗尼亚、安达卢西亚、瓦伦西亚筛选),支持数量快捷选择、显示全部与下载。 在线工具,随机西班牙地址生成器在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • curl 转代码

    解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online