Dify二次开发,模块API封装(Knowledge_Retriever)

Dify二次开发,模块API封装(Knowledge_Retriever)

在这里插入图片描述
图片源自官网[1]

声明

首先声明,测试用的是powershell,每个Windows系统都有,用GPT生成的测试代码很方便。作为记录只是部署和必要参数查询教程。Dify版本为1.3.1,针对workflow和chatflow的知识检索模块。
POST 请求
URL:console/api/workflow/knowledge-retriever/fetch-dataset
github地址:https://github.com/First-Comer/dify_knowledge_retrieve_api

Docker部署

Dify作为当今最流行的开源LLM应用开发平台是很多开发人员的优选,但是官方给出的API相对较少,在不改动源代码的情况下进行二次开发,用最简单的模式进行开发和部署。部署方式和源代码相同,但在部署前,我们新建Dockerfile,本文以源代码为基础镜像,并将本地新增的代码复制到新容器中。
Dockerfile:

FROM langgenius/dify-api:1.3.1

COPY ../api /app/api
COPY ../api/core/workflow/nodes/knowledge_retrieval/knowledge_retrieval_node.py /app/api/core/workflow/nodes/knowledge_retrieval/knowledge_retrieval_node.py

只COPY /api这部分代码我要封装的模块不能复制过去,没找到什么原因很奇怪,暂且当作是源码问题,干脆专门把这个要用到代码复制过来。

再修改源码部署方式,因为本次的开发只是对/api中的小模块进行API封装,所以我们只需要修改/api部分代码的部署即可。
docker-compose.yaml:

  api:
    build:
      context: ..
      dockerfile: docker/Dockerfile
    # 用我们自己打的镜像标签
    image: my-dify-api-test:1.3.1
    restart: always
    environment:
      # Use the shared environment variables.
      <<: *shared-api-worker-env
      # Startup mode, 'api' starts the API server.
      MODE: api
      SENTRY_DSN: ${API_SENTRY_DSN:-}
      SENTRY_TRACES_SAMPLE_RATE: ${API_SENTRY_TRACES_SAMPLE_RATE:-1.0}
      SENTRY_PROFILES_SAMPLE_RATE: ${API_SENTRY_PROFILES_SAMPLE_RATE:-1.0}
      PLUGIN_REMOTE_INSTALL_HOST: ${EXPOSE_PLUGIN_DEBUGGING_HOST:-localhost}
      PLUGIN_REMOTE_INSTALL_PORT: ${EXPOSE_PLUGIN_DEBUGGING_PORT:-5003}
      PLUGIN_MAX_PACKAGE_SIZE: ${PLUGIN_MAX_PACKAGE_SIZE:-52428800}
      INNER_API_KEY_FOR_PLUGIN: ${PLUGIN_DIFY_INNER_API_KEY:-QaHbTe77CtuXmsfyhR7+vRjI/+XbV1AaFy691iy+kGDv2Jvy0/eAh8Y1}
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started
    volumes:
      # Mount the storage directory to the container, for storing user files.
      - ./volumes/app/storage:/app/api/storage
    networks:
      - ssrf_proxy_network
      - default

部署部分的代码就这两段,做二次开发部署自己的镜像都可以用到。
忘了说目录结构,本次开发的全部修改目录都在这!!!

dify-main/
├── api/                          # 你修改过的 Dify API 源码
│   ├── services/   
│   │    ├── workflow/                 
│   │    │    ├── dataset_retriever.py   # 修改此文件
│   ├── controllers/
│   │    ├── console/
│   │    ├── __init__.py                 # 修改此文件
│   │    │    ├── knowledge/         # 新建此文件包
│   │    │    ├── __init__.py          #新建自带
│   │    │    │    ├── rettiever.py    # 新建此文件
├── docker/
│   ├── Dockerfile                # 新建此文件
│   ├── docker-compose.yml      # 修改此文件

API封装代码

直接给代码了,源自GPT-4o和GPT-o4-mini,DeepSeek也有参与,因为免费的份额用完了…

首先是路由注册:
dify-main\api\controllers\console_init_.py

from .knowledge.retriever import KnowledgeRetrieverApi

api.add_resource(
    KnowledgeRetrieverApi,
    "/workflow/knowledge-retriever/fetch-dataset",
    endpoint="workflow_knowledge_retriever_fetch"
)

还有两个代码一起给了。

# api/services/workflow/dataset_retriever.py

from core.workflow.nodes.knowledge_retrieval.knowledge_retrieval_node import KnowledgeRetrievalNode
from core.workflow.nodes.knowledge_retrieval.entities import KnowledgeRetrievalNodeData
from core.variables import StringSegment

def fetch_dataset_retriever(payload: dict) -> list[dict]:
    # 1. 从 payload 中单独提取 id,剩余字段给 Pydantic
    raw = payload["node_data"].copy()
    node_id = raw.pop("id")
    node_data = KnowledgeRetrievalNodeData(**raw)

    # 2. 提取 query
    selector = node_data.query_variable_selector[0]
    query_str = payload["inputs"][selector]
    if not isinstance(query_str, str):
        raise ValueError("Query must be a string")

    # 3. 初始化 node
    node = KnowledgeRetrievalNode.__new__(KnowledgeRetrievalNode)
    node.id = node_id
    node.node_data = node_data

    # 4. 模拟 runtime state
    class DummyPool:
        def __init__(self, value): self.value = value
        def get(self, _): return StringSegment(self.value)

    class DummyRuntime:
        variable_pool = DummyPool(query_str)

    setattr(node, "graph_runtime_state", DummyRuntime())
    setattr(node, f"graph_{node.id}_runtime_state", DummyRuntime())

    # 5. 补齐其他必需属性
    node.tenant_id = payload["tenant_id"]
    node.user_id = payload["user_id"]
    node.app_id = payload["app_id"]
    node.user_from = type("UserFrom", (), {"value": payload.get("user_from", "api")})()

    # 6. 调用底层检索方法
    results = node._fetch_dataset_retriever(node_data=node_data, query=query_str)

    # 7. 转成 JSON-serializable 的 list[dict]
    out: list[dict] = []
    for r in results:
        try:
            out.append(dict(r))
        except Exception:
            out.append(r)
    return out

# api/controllers/console/knowledge/retriever.py

from flask_restful import Resource, request
from services.workflow.dataset_retriever import fetch_dataset_retriever

class KnowledgeRetrieverApi(Resource):
    def post(self):
        payload = request.get_json(force=True)
        result = fetch_dataset_retriever(payload)
        return {"status": "success", "data": result}, 200

直接CV。。。

这些都CV后就可以部署了,我也CV一下源代码的部署README:

快速启动

启动 Dify 服务器的最简单方法是运行我们的 docker-compose.yml 文件。在运行安装命令之前,请确保您的机器上安装了 Docker 和 Docker Compose:

cd docker
cp .env.example .env
docker compose up -d

运行后,可以在浏览器上访问 http://localhost/install 进入 Dify 控制台并开始初始化安装操作。
ok了,非常方便,后面我们测试还需要一些参数在下一章。

参数规范

先给测试代码,这个前提是部署的Dify有workflow或是chatflow,有上传和embedding好了的知识库。

# 构造请求体
$bodyB = @{
  node_data = @{
    id                      = "kr-node-1"                              #知识检索节点的唯一标识符。通常用于区分不同的节点,无需修改
    title                   = "KnowledgeRetrievalNode"      
    type                    = "knowledge-retrieval"
    query_variable_selector = @("question")
    dataset_ids             = @("*****")   #知识库数据id,可以多个,英文逗号隔开","
    retrieval_mode          = "single"                               #指定检索模式。常见的值可能是 "single" 或 "batch"
    single_retrieval_config = @{
      model = @{
        provider          = "tongyi"                                   #自行换
        name              = "qwen-max"
        mode              = "chat"
        completion_params = @{ temperature = 0.7 }
      }
      top_k           = 5
      score_threshold = 0.1
    }
  }
  inputs    = @{ question = "***?" }
  tenant_id = "****"         #租户 ID,标识不同用户
  app_id    = "****"             #应用程序 ID,用于区分不同的应用
  user_id   = "****"             #用户 ID,表示发起请求的用户
  user_from = "api"
}

# 序列化并发送
$jsonB = $bodyB | ConvertTo-Json -Depth 5
Invoke-RestMethod `
  -Uri 'http://localhost/console/api/workflow/knowledge-retriever/fetch-dataset' `
  -Method POST `
  -ContentType 'application/json; charset=utf-8' `
  -Body $jsonB

你就测吧,这么详细肯定没问题🆗
上文代码给出了必要的参数及其定义,大部分可以不用修改,只有四个是要修改的:

  1. user_id查询
    1.1连接到 PostgreSQL 数据库
    powershell
docker-compose exec db sh
psql -U postgres

在这里插入图片描述
1.2查看数据库列表
sql

\l  # 列出所有数据库
\c dify  # 连接到 dify 数据库
\dt
SELECT id, email, name FROM accounts LIMIT 5;

在这里插入图片描述
在这里插入图片描述
到这目的达到了
在这里插入图片描述

  1. tenant_id查询
    同user_id查询,最后命令换为SELECT id, name FROM tenants;

  2. app_id查询;
    在这里插入图片描述
    url里面有自己看。

  3. dataset_ids 查询;
    同app_id相同,都在url。

ok,大功告成,拿到你自己的id换上去测试就是200。

参考

本地Docker部署:
[1] https://github.com/langgenius/dify

<think>好的,我现在需要处理用户关于Dify二次开发的问题。首先,用户提到了引用[1]和引用[2],我需要先仔细看看这些引用内容。引用[1]提到DifyAPI功能和私有化部署的系统要求,引用[2]则比较了基础编排和工作流编排的区别,并提到编辑应用的部分。 用户的问题是关于Dify二次开发教程或如何进行定制化修改。根据引用内容,Dify提供了API支持,所以二次开发可能涉及调用这些API。另外,私有化部署可能需要满足一定的系统要求,这也是二次开发的前提条件。工作流编排支持外部插件接入,这可能与定制化有关。 接下来,我需要整理回答的结构。首先应该介绍二次开发的基础,比如系统要求和代码结构。然后,可能的分步骤指导,比如API集成、插件开发、界面定制等。接着,可以提到参考文档和社区资源,以及测试部署的注意事项。最后,生成相关问题。 需要确保回答中的LaTeX格式正确,比如行内公式用$...$,独立公式用$$...$$,但当前问题可能不涉及数学公式,所以可能不需要使用。不过要留意是否有变量或技术术语需要特别标注。 还需要检查引用是否正确,用户提供的引用[1]和[2]是否与二次开发相关。引用[1]提到API和私有化部署,引用[2]提到工作流编排和插件,这些都与二次开发相关,可以合理引用。 可能还需要补充一些用户未提到的点,比如版本控制、调试方法、依赖管理等,但需要根据Dify的文档实际情况来判断,如果不确定,可能需要建议用户查阅官方文档或社区资源。 最后,生成的相关问题需要围绕二次开发的扩展,比如API使用、插件开发、界面定制、调试方法、社区资源等。确保问题有逻辑性,覆盖用户可能关心的其他方面。 现在整理回答,确保结构清晰,分步骤说明,并正确引用提供的参考资料。</think>### Dify 二次开发与定制化修改指南 #### 1. **开发基础准备** - **系统要求**:确保部署环境满足Dify私有化部署的最低配置(如操作系统、内存、存储等)[^1]。 - **代码结构分析**:下载Dify源代码后,先熟悉项目目录结构,重点关注`backend`(核心逻辑)、`frontend`(界面)及`plugins`(插件模块)。 #### 2. **分步骤定制化开发** - **API集成**: 所有功能均提供API接口,可通过调用`/api/v1/`相关端点实现业务集成。例如,创建应用的API格式为: ```python import requests response = requests.post( "https://api.dify.ai/v1/apps", headers={"Authorization": "Bearer {API_KEY}"}, json={"name": "自定义应用"} ) ``` 参考[API文档](https://docs.dify.ai/api-reference)进行扩展开发[^1]。 - **插件开发**: 工作流编排支持外部插件接入。开发自定义插件的流程: 1. 在`plugins`目录下创建插件模块,实现`execute()`方法定义逻辑。 2. 注册插件到系统配置文件`config/plugins.yaml`。 3. 通过界面“工作流编排”拖拽插件节点进行测试[^2]。 - **界面定制**: 修改前端Vue组件(位于`frontend/src/views`),调整布局或交互逻辑后重新构建: ```bash cd frontend npm run build ``` #### 3. **调试与部署** - 本地调试使用`docker-compose up`启动开发环境。 - 私有化部署时,需按[引用1]要求配置服务器,并通过CI/CD工具实现自动化更新。 #### 4. **学习资源** - **官方文档**:[Dify开发者中心](https://docs.dify.ai/development-guide) - **社区支持**:加入Dify Slack频道或GitHub Discussions获取案例与答疑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值