Dify Python调用API

前期准备

在调用API之前得先拿到API KEY,具体操作如下:

文件上传

如果你的工作流的参数涉及到文件上传以及图片上传的(音频、视频也类似),需要先调用upload方法拿到file_id,具体代码如下:

import os
import requests
import logging

# 假设 logger_info 已定义好
logger_info = logging.getLogger(__name__)

class YourUploaderClass:
    def __init__(self, base_url, your_api_key):
        self.base_url = base_url
        self.api_key = your_api_key  #随意一条工作流的API_Key

    def upload_file(self, file_path):
        """
        文件上传,支持文档和图片
        :param file_path: 本地文件路径
        :return: 返回上传成功后的文件 ID,失败返回 None
        """
        headers = {
            "Authorization": f"Bearer {self.api_key}"
        }

        # 获取文件扩展名并确定 MIME 类型
        file_extension = os.path.splitext(file_path)[1].lower()

        # 定义文档类型的 MIME 映射
        document_mime_map = {
            '.txt': 'text/plain',
            '.md': 'text/markdown',
            '.markdown': 'text/markdown',
            '.pdf': 'application/pdf',
            '.html': 'text/html',
            '.xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
            '.xls': 'application/vnd.ms-excel',
            '.docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
            '.csv': 'text/csv',
            '.eml': 'message/rfc822',
            '.msg': 'application/vnd.ms-outlook',
            '.pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
            '.ppt': 'application/vnd.ms-powerpoint',
            '.xml': 'application/xml',
            '.epub': 'application/epub+zip'
        }

        # 定义图片类型的扩展名映射到对应的 MIME 类型
        image_ext_to_mime = {
            '.png': 'image/png',
            '.jpg': 'image/jpeg',
            '.jpeg': 'image/jpeg',
            '.webp': 'image/webp',
            '.gif': 'image/gif'
        }

        # 判断是文档还是图片
        mime_type = document_mime_map.get(file_extension)
        if not mime_type:
            mime_type = image_ext_to_mime.get(file_extension)

        # 如果文件类型不支持,返回 None
        if mime_type is None:
            return None

        current_file_path = os.path.abspath(__file__)
        dir = os.path.dirname(os.path.dirname(os.path.dirname(current_file_path)))
        path = os.path.join(dir, file_path)

        try:
            with open(path, "rb") as f:
                files = {
                    "file": (os.path.basename(file_path), f, mime_type)
                }
                data = {
                    "user": "abc_user"
                }

                upload_url = f"{self.base_url}/files/upload"

                response = requests.post(upload_url, headers=headers, files=files, data=data)

                logger_info.info(f"dify upload_file 请求结果:{response.json()}")
                if response.status_code == 201:
                    result = response.json()
                    logger_info.info(f"dify upload_file 成功:{result}")
                    return result.get("id")
                else:
                    return None

        except requests.exceptions.RequestException as e:
            logging.error(f"dify upload_file 请求出错:{e}")
            return None
        except Exception as e:
            logging.error(f"上传文件时发生异常:{e}")
            return None

流式输出 streaming

基于 SSE(Server-Sent Events)实现类似打字机输出方式的流式返回。注意,以下代码展示的是chatflow模式,所以参数inputs为空,如果是工作流,入参放在inputs即可,形式是:

"inputs": {
    "outline": outline
}

    def user_intent(self, question, upload_file_id=""):
        """
        第一步:用户意图分析
        :param question:
        :param upload_file_id:
        :return:
        """
        headers = {
            "Authorization": f"Bearer {self.intent_api_key}",
            "Content-Type": "application/json"
        }

        data = {
            "inputs": {},
            "query": question,
            "response_mode": "streaming",  # 根据需求选择 streaming 或 blocking
            "user": "abc_user"  # 与上传文件时的用户标识一致

        }
        if upload_file_id:
            data["inputs"]["file"] = [{
                "type": "document",  # 根据实际文件类型修改
                "transfer_method": "local_file",
                "upload_file_id": upload_file_id
            }]
        workflow_url = f"{self.base_url}/chat-messages"
        try:
            response = requests.post(workflow_url, headers=headers, json=data, stream=True)

            if response.status_code == 200:
                for line in response.iter_lines():

                    if line:  # 过滤掉keep-alive新行
                        # 解码为字符串
                        line_str = line.decode('utf-8')
                        # 确保是有效的 JSON 行
                        if line_str.startswith("data:"):
                            json_str = line_str[5:].strip()  # 去掉前缀并清理空格
                            if json_str:
                                json_data = json.loads(json_str)
                                #这里不一定是message,具体你得打印json_data你才知道
                                if json_data.get("event") == "message":  
                                    yield json_data
                logger_info.info(f"user_intent 请求结果:{response.json()}")
                return response.json()
            else:
                logger.error(f"user_intent 请求出错:{response.json()}")
                return {}
        except Exception as e:
            logger.error(f"user_intent 请求出错:{e}")
            return {}

阻塞模式 blocking

阻塞模式,等待执行完毕后返回结果。(请求若流程较长可能会被中断)。 由于 Cloudflare 限制,请求会在 100 秒超时无返回后中断。注意:以下代码是chatflow模式,不是工作流,但是代码是一样的,只不过取值不一样

    def judge_steps(self, question):
        """
        判断步骤
        :param question:
        :return:
        """
        headers = {
            "Authorization": f"Bearer {self.judge_steps_api_key}",
            "Content-Type": "application/json"
        }
        data = {
            "inputs": {},
            "query": question,
            "response_mode": "blocking",  # 根据需求选择 streaming 或 blocking
            "user": "abc_user"  # 与上传文件时的用户标识一致
        }
        #注意,我这里用的是CHATFLOW,不是工作流
        workflow_url = f"{self.base_url}/chat-messages"
        try:
            response = requests.post(workflow_url, headers=headers, json=data)

            if response.status_code == 200:
                #由于不是工作流,所以取出来的不一定是["answer"],方法都是一样的,到时候自己打印response.json()出来就知道了
                answer = response.json()["answer"]
                if answer:
                    logger_info.info(f"dify judge_steps 请求结果:{response.json()}")
                    return answer
                else:
                    return ""
            else:
                logging.error(f"judge_steps 请求出错:{response.json()}")
                return 0
        except Exception as e:
            print(e)
            logging.error(f"judge_steps 请求出错:{e}")
            return 0

### 关于 Dify API 的使用 Dify 是一款支持多种大模型集成的应用开发框架,其核心功能之一是通过 API 提供灵活的知识管理能力。以下是关于如何获取和使用 Dify API 文档以及示例教程的相关说明。 #### 获取 Dify API 使用文档 官方提供了详细的 API 接口列表用于开发者调用知识库相关功能[^2]。可以通过访问以下链接来查看完整的 API 文档: - 官方地址:[Dify 中的知识库 API 列表](https://z0yrmerhgi8.feishu.cn/wiki/VzQjwhpEjiQH2okq1f3cTBMcn0x)[^2] 此页面涵盖了所有可用的接口定义、请求参数结构、返回数据格式等内容,适合初学者快速上手并深入理解。 #### 示例代码展示 下面是一个简单的 Python 脚本示例,演示如何利用 Dify API 创建一个新的知识条目: ```python import requests def create_knowledge_entry(api_key, title, content): url = "https://api.dify.com/v1/knowledge_entries" headers = { "Authorization": f"Bearer {api_key}", "Content-Type": "application/json", } payload = { "title": title, "content": content } response = requests.post(url, json=payload, headers=headers) if response.status_code == 201: print(f"Knowledge entry created successfully with ID: {response.json()['id']}") else: print(f"Failed to create knowledge entry. Error: {response.text}") # 替换为实际的 API 密钥 create_knowledge_entry("your_api_key_here", "Example Title", "This is an example of a new knowledge entry.") ``` 上述脚本实现了向 Dify 平台上传新知识的功能,并展示了基本的身份验证机制与 POST 请求方法。 #### 注意事项 在尝试以上操作之前,请确保已注册账户并获得有效的 API Key。此外,在生产环境中应妥善保管密钥信息以防泄露风险。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值