├── .difyignore
├── .env.example
├── .gitignore
├── GUIDE.md
├── LICENSE
├── PRIVACY.md
├── README.md
├── _assets
└── icon.svg
├── img
├── actions.png
├── retrieve.png
└── upload.png
├── knowledge-manager.difypkg
├── knowledge-upload.difypkg
├── main.py
├── manifest.yaml
├── plugin.yaml
├── provider
├── knowledge.py
└── knowledge.yaml
├── requirements.txt
├── test_tool.py
├── test_tool.py.combined
├── test_tool.py.retrieve
├── test_tool.py.upload
└── tools
├── knowledge_retrieve.py
├── knowledge_retrieve.yaml
├── knowledge_upload.py
└── knowledge_upload.yaml
/.difyignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # Distribution / packaging
7 | .Python
8 | build/
9 | develop-eggs/
10 | dist/
11 | downloads/
12 | eggs/
13 | .eggs/
14 | lib/
15 | lib64/
16 | parts/
17 | sdist/
18 | var/
19 | wheels/
20 | share/python-wheels/
21 | *.egg-info/
22 | .installed.cfg
23 | *.egg
24 | MANIFEST
25 |
26 | # PyInstaller
27 | # Usually these files are written by a python script from a template
28 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
29 | *.manifest
30 | *.spec
31 |
32 | # Installer logs
33 | pip-log.txt
34 | pip-delete-this-directory.txt
35 |
36 | # Unit test / coverage reports
37 | htmlcov/
38 | .tox/
39 | .nox/
40 | .coverage
41 | .coverage.*
42 | .cache
43 | nosetests.xml
44 | coverage.xml
45 | *.cover
46 | *.py,cover
47 | .hypothesis/
48 | .pytest_cache/
49 | cover/
50 |
51 | # Translations
52 | *.mo
53 | *.pot
54 |
55 | # Django stuff:
56 | *.log
57 | local_settings.py
58 | db.sqlite3
59 | db.sqlite3-journal
60 |
61 | # Flask stuff:
62 | instance/
63 | .webassets-cache
64 |
65 | # Scrapy stuff:
66 | .scrapy
67 |
68 | # Sphinx documentation
69 | docs/_build/
70 |
71 | # PyBuilder
72 | .pybuilder/
73 | target/
74 |
75 | # Jupyter Notebook
76 | .ipynb_checkpoints
77 |
78 | # IPython
79 | profile_default/
80 | ipython_config.py
81 |
82 | # pyenv
83 | # For a library or package, you might want to ignore these files since the code is
84 | # intended to run in multiple environments; otherwise, check them in:
85 | .python-version
86 |
87 | # pipenv
88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
91 | # install all needed dependencies.
92 | Pipfile.lock
93 |
94 | # UV
95 | # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
96 | # This is especially recommended for binary packages to ensure reproducibility, and is more
97 | # commonly ignored for libraries.
98 | uv.lock
99 |
100 | # poetry
101 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
102 | # This is especially recommended for binary packages to ensure reproducibility, and is more
103 | # commonly ignored for libraries.
104 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
105 | poetry.lock
106 |
107 | # pdm
108 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
109 | #pdm.lock
110 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
111 | # in version control.
112 | # https://pdm.fming.dev/latest/usage/project/#working-with-version-control
113 | .pdm.toml
114 | .pdm-python
115 | .pdm-build/
116 |
117 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
118 | __pypackages__/
119 |
120 | # Celery stuff
121 | celerybeat-schedule
122 | celerybeat.pid
123 |
124 | # SageMath parsed files
125 | *.sage.py
126 |
127 | # Environments
128 | .env
129 | .venv
130 | env/
131 | venv/
132 | ENV/
133 | env.bak/
134 | venv.bak/
135 |
136 | # Spyder project settings
137 | .spyderproject
138 | .spyproject
139 |
140 | # Rope project settings
141 | .ropeproject
142 |
143 | # mkdocs documentation
144 | /site
145 |
146 | # mypy
147 | .mypy_cache/
148 | .dmypy.json
149 | dmypy.json
150 |
151 | # Pyre type checker
152 | .pyre/
153 |
154 | # pytype static type analyzer
155 | .pytype/
156 |
157 | # Cython debug symbols
158 | cython_debug/
159 |
160 | # PyCharm
161 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
162 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
163 | # and can be added to the global gitignore or merged into this file. For a more nuclear
164 | # option (not recommended) you can uncomment the following to ignore the entire idea folder.
165 | .idea/
166 |
167 | # Vscode
168 | .vscode/
169 |
170 | # Git
171 | .git/
172 | .gitignore
173 |
174 | # Mac
175 | .DS_Store
176 |
177 | # Windows
178 | Thumbs.db
179 |
--------------------------------------------------------------------------------
/.env.example:
--------------------------------------------------------------------------------
1 | INSTALL_METHOD=remote
2 | REMOTE_INSTALL_HOST=debug.dify.ai
3 | REMOTE_INSTALL_PORT=5003
4 | REMOTE_INSTALL_KEY=********-****-****-****-************
5 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | share/python-wheels/
24 | *.egg-info/
25 | .installed.cfg
26 | *.egg
27 | MANIFEST
28 |
29 | # PyInstaller
30 | # Usually these files are written by a python script from a template
31 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
32 | *.manifest
33 | *.spec
34 |
35 | # Installer logs
36 | pip-log.txt
37 | pip-delete-this-directory.txt
38 |
39 | # Unit test / coverage reports
40 | htmlcov/
41 | .tox/
42 | .nox/
43 | .coverage
44 | .coverage.*
45 | .cache
46 | nosetests.xml
47 | coverage.xml
48 | *.cover
49 | *.py,cover
50 | .hypothesis/
51 | .pytest_cache/
52 | cover/
53 |
54 | # Translations
55 | *.mo
56 | *.pot
57 |
58 | # Django stuff:
59 | *.log
60 | local_settings.py
61 | db.sqlite3
62 | db.sqlite3-journal
63 |
64 | # Flask stuff:
65 | instance/
66 | .webassets-cache
67 |
68 | # Scrapy stuff:
69 | .scrapy
70 |
71 | # Sphinx documentation
72 | docs/_build/
73 |
74 | # PyBuilder
75 | .pybuilder/
76 | target/
77 |
78 | # Jupyter Notebook
79 | .ipynb_checkpoints
80 |
81 | # IPython
82 | profile_default/
83 | ipython_config.py
84 |
85 | # pyenv
86 | # For a library or package, you might want to ignore these files since the code is
87 | # intended to run in multiple environments; otherwise, check them in:
88 | # .python-version
89 |
90 | # pipenv
91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
94 | # install all needed dependencies.
95 | #Pipfile.lock
96 |
97 | # UV
98 | # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
99 | # This is especially recommended for binary packages to ensure reproducibility, and is more
100 | # commonly ignored for libraries.
101 | #uv.lock
102 |
103 | # poetry
104 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
105 | # This is especially recommended for binary packages to ensure reproducibility, and is more
106 | # commonly ignored for libraries.
107 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
108 | #poetry.lock
109 |
110 | # pdm
111 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
112 | #pdm.lock
113 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
114 | # in version control.
115 | # https://pdm.fming.dev/latest/usage/project/#working-with-version-control
116 | .pdm.toml
117 | .pdm-python
118 | .pdm-build/
119 |
120 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
121 | __pypackages__/
122 |
123 | # Celery stuff
124 | celerybeat-schedule
125 | celerybeat.pid
126 |
127 | # SageMath parsed files
128 | *.sage.py
129 |
130 | # Environments
131 | .env
132 | .venv
133 | env/
134 | venv/
135 | ENV/
136 | env.bak/
137 | venv.bak/
138 |
139 | # Spyder project settings
140 | .spyderproject
141 | .spyproject
142 |
143 | # Rope project settings
144 | .ropeproject
145 |
146 | # mkdocs documentation
147 | /site
148 |
149 | # mypy
150 | .mypy_cache/
151 | .dmypy.json
152 | dmypy.json
153 |
154 | # Pyre type checker
155 | .pyre/
156 |
157 | # pytype static type analyzer
158 | .pytype/
159 |
160 | # Cython debug symbols
161 | cython_debug/
162 |
163 | # PyCharm
164 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
165 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
166 | # and can be added to the global gitignore or merged into this file. For a more nuclear
167 | # option (not recommended) you can uncomment the following to ignore the entire idea folder.
168 | .idea/
169 |
170 | # Vscode
171 | .vscode/
172 |
--------------------------------------------------------------------------------
/GUIDE.md:
--------------------------------------------------------------------------------
1 | # Dify知识库管理插件使用指南
2 |
3 | ## 简介
4 |
5 | Dify知识库管理插件是一个用于管理Dify知识库的综合工具。它支持创建知识库、上传文本内容以及从知识库检索信息,提供简单的界面来配置各种操作参数。
6 |
7 | ## 安装前准备
8 |
9 | 在安装和使用此插件前,您需要:
10 |
11 | 1. 拥有Dify平台账号
12 | 2. 获取知识库API Key
13 |
14 | ## 安装步骤
15 |
16 | 1. 在Dify平台中,点击右上角的"插件"按钮
17 | 2. 选择"本地上传"选项
18 | 3. 上传插件文件(.difypkg格式)
19 | 4. 完成安装后,您需要配置API Key才能使用插件
20 |
21 | ## 配置API Key
22 |
23 | 1. 在插件列表中找到"Dify知识库管理"插件
24 | 2. 点击"配置"按钮
25 | 3. 在弹出的窗口中输入您的知识库API Key
26 | 4. 点击"保存"按钮完成配置
27 |
28 | ## 如何获取知识库API Key
29 |
30 | 1. 登录Dify平台
31 | 2. 导航到知识库页面
32 | 3. 从左侧导航切换到**API访问**页面
33 | 4. 在**API Keys**部分管理访问凭证
34 | 5. 如果没有API Key,点击"创建"按钮生成一个新的API Key
35 |
36 | ## 如何获取知识库ID
37 |
38 | 知识库ID可以从知识库URL获取,例如:
39 | `https://app.dify.ai/datasets/12345678-1234-1234-1234-123456789012`
40 | 其中`12345678-1234-1234-1234-123456789012`就是知识库ID。
41 |
42 | ## 使用方法
43 |
44 | ### 上传功能
45 |
46 | #### 在Agent应用中使用
47 |
48 | 1. 创建或编辑一个Agent应用
49 | 2. 在应用编排页面底部找到"工具"选项
50 | 3. 选择"知识库上传"工具
51 | 4. 配置工具参数:
52 | - 知识库名称:要创建的知识库名称
53 | - 描述:知识库的描述(可选)
54 | - 文档名称:要创建的文档名称
55 | - 文本内容:要上传的文本内容
56 | - 权限:选择知识库权限(仅自己或公开可读)
57 | - 索引技术:选择高质量(high_quality)或经济(economy)模式
58 | 5. 保存配置
59 |
60 | #### 在Chatflow/Workflow应用中使用
61 |
62 | 1. 在工作流编排画布中,点击节点末尾的"+"号
63 | 2. 选择"知识库上传"工具
64 | 3. 将其连接到上游节点
65 | 4. 配置工具参数
66 | 5. 保存配置
67 |
68 | ### 检索功能
69 |
70 | #### 在Agent应用中使用
71 |
72 | 1. 创建或编辑一个Agent应用
73 | 2. 在应用编排页面底部找到"工具"选项
74 | 3. 选择"知识库检索"工具
75 | 4. 配置工具参数:
76 | - 知识库ID:要检索的知识库ID
77 | - 查询内容:在知识库中搜索的查询内容
78 | - 搜索方法:选择搜索方法(关键词检索、语义检索、全文检索或混合检索)
79 | - 启用重排序:是否启用搜索结果重排序
80 | - 结果数量:返回的结果数量
81 | - 启用分数阈值:是否启用分数阈值过滤
82 | - 分数阈值:结果的最小分数阈值
83 | 5. 保存配置
84 |
85 | #### 在Chatflow/Workflow应用中使用
86 |
87 | 1. 在工作流编排画布中,点击节点末尾的"+"号
88 | 2. 选择"知识库检索"工具
89 | 3. 将其连接到上游节点
90 | 4. 配置工具参数
91 | 5. 保存配置
92 |
93 | ## 上传功能参数说明
94 |
95 | - **知识库名称**(必填):要创建的知识库名称
96 | - **描述**(可选):知识库的描述
97 | - **文档名称**(必填):要创建的文档名称
98 | - **文本内容**(必填):要上传的文本内容
99 | - **权限**(必填):知识库的权限设置,可选值:
100 | - `only_me`:仅自己可见,只有创建者可以访问
101 | - `publicly_readable`:公开可读,所有人可以读取
102 | - **索引技术**(必填):选择索引技术,可选值:
103 | - `high_quality`:高质量模式,提供更准确的检索结果,但处理时间较长
104 | - `economy`:经济模式,处理速度较快,但检索准确性可能略低
105 |
106 | ## 检索功能参数说明
107 |
108 | - **知识库ID**(必填):要检索的知识库ID
109 | - **查询内容**(必填):在知识库中搜索的查询内容
110 | - **搜索方法**(可选,默认为语义检索):用于搜索知识库的方法,可选值:
111 | - `keyword_search`:关键词检索,基于关键词匹配
112 | - `semantic_search`:语义检索,基于语义理解
113 | - `full_text_search`:全文检索,搜索整个文本内容
114 | - `hybrid_search`:混合检索,结合关键词和语义检索
115 | - **启用重排序**(可选,默认为否):是否启用搜索结果重排序
116 | - **结果数量**(可选,默认为3):返回的结果数量
117 | - **启用分数阈值**(可选,默认为否):是否启用分数阈值过滤
118 | - **分数阈值**(可选,默认为0.5):结果的最小分数阈值,范围0-1
119 |
120 | ## 上传工作流程
121 |
122 | 1. 创建新的知识库:插件会根据提供的名称和描述创建一个新的知识库
123 | 2. 创建文档:在知识库中创建一个空文档
124 | 3. 上传文本内容:将文本内容上传到创建的文档中
125 | 4. 处理文档:Dify平台会自动处理上传的文本内容,包括文本分段和索引
126 | 5. 返回结果:插件会返回处理状态和结果
127 |
128 | ## 检索工作流程
129 |
130 | 1. 提供知识库ID和查询内容
131 | 2. 选择搜索方法和其他参数
132 | 3. 执行知识库检索
133 | 4. 返回检索结果和相关信息
134 |
135 | ## 搜索方法说明
136 |
137 | - **关键词检索**:基于关键词匹配,适合精确查找特定术语或短语
138 | - **语义检索**:基于语义理解,能够找到语义相关但可能不包含完全相同关键词的内容
139 | - **全文检索**:搜索整个文本内容,适合需要在大量文本中查找信息
140 | - **混合检索**:结合关键词和语义检索,提供更全面的搜索结果
141 |
142 | ## 常见问题
143 |
144 | ### 上传或检索失败,提示"API Key validation failed"
145 |
146 | 请检查您提供的API Key是否正确,以及是否有足够的权限访问知识库。
147 |
148 | ### 上传成功后,文档在知识库中不可见
149 |
150 | 文档上传后需要一段时间进行处理和索引。您可以在知识库页面查看文档的处理状态。
151 |
152 | ### 检索失败,提示"知识库不存在或无权访问"
153 |
154 | 请确保您提供的知识库ID是正确的,并且您的API Key有权限访问该知识库。
155 |
156 | ### 检索结果不符合预期
157 |
158 | 尝试调整搜索方法、启用重排序或调整分数阈值,以获得更符合预期的结果。
159 |
160 | ## 技术支持
161 |
162 | 如果您在使用过程中遇到任何问题,请联系插件作者或在Dify社区论坛中提问。
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2025 Steven Lynn
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/PRIVACY.md:
--------------------------------------------------------------------------------
1 | # 隐私政策
2 |
3 | ## 数据收集和使用
4 |
5 | 本插件需要访问以下信息:
6 |
7 | 1. **Dify知识库API Key**:用于验证用户身份并授权访问Dify知识库。API Key存储在用户的Dify工作区中,不会被插件保存或传输到其他地方。
8 |
9 | 2. **文本内容**:插件需要读取用户提供的文本内容,以便上传到Dify知识库。文本内容仅用于上传目的,不会被插件保存或用于其他目的。
10 |
11 | 3. **查询内容**:插件需要读取用户提供的查询内容,以便在Dify知识库中进行检索。查询内容仅用于检索目的,不会被插件保存或用于其他目的。
12 |
13 | 4. **知识库ID**:插件需要知道用户想要检索的知识库ID。知识库ID仅用于检索目的,不会被插件保存或用于其他目的。
14 |
15 | ## 数据传输
16 |
17 | 所有数据传输都通过HTTPS协议进行加密。插件直接与Dify API通信,不经过任何第三方服务器。
18 |
19 | ## 数据存储
20 |
21 | 插件本身不存储任何用户数据。所有上传的文本内容都存储在用户的Dify知识库中,受Dify平台的隐私政策保护。所有检索操作都是实时进行的,结果直接返回给用户,不会在插件中保存。
22 |
23 | ## 第三方服务
24 |
25 | 本插件使用Dify API服务。使用本插件即表示您同意Dify的服务条款和隐私政策。
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Dify Knowledge Base Manager Plugin
2 |
3 | A plugin for managing Dify knowledge base - creating knowledge bases, uploading text content, and retrieving information.
4 | 
5 |
6 | ## Prerequisites
7 |
8 | Before using this plugin, you need:
9 |
10 | 1. A Dify platform account
11 | 2. Knowledge base API Key
12 |
13 | ## How to Get API Key
14 |
15 | 1. Log in to [Dify.ai](https://cloud.dify.ai)
16 | 2. Navigate to the knowledge base page
17 | 3. Switch to the **API Access** page from the left navigation
18 | 4. Manage access credentials in the **API Keys** section
19 |
24 |
25 | ## How to Get Knowledge Base ID
26 |
27 | The knowledge base ID can be obtained from the knowledge base URL, for example:
28 | `https://app.dify.ai/datasets/12345678-1234-1234-1234-123456789012`
29 | where `12345678-1234-1234-1234-123456789012` is the knowledge base ID.
30 |
31 | ## Upload Tool Parameters
32 |
33 | 
34 | - **Knowledge Base Name**: The name of the knowledge base to create
35 | - **Description**: Description of the knowledge base (optional)
36 | - **Document Name**: The name of the document to create
37 | - **Text Content**: The text content to upload
38 | - **Permission**: Knowledge base permission settings
39 | - only_me: Only the creator can access
40 | - publicly_readable: Everyone can read
41 | - **Indexing Technology**: Choose high_quality or economy mode
42 |
43 | ## Retrieve Tool Parameters
44 |
45 | 
46 | - **Knowledge Base ID**: The ID of the knowledge base to retrieve from (required)
47 | - **Query**: The query to search for in the knowledge base (required)
48 | - **Search Method**: The method to use for searching the knowledge base (optional, default is semantic search)
49 | - keyword_search: Keyword search, based on keyword matching
50 | - semantic_search: Semantic search, based on semantic understanding
51 | - full_text_search: Full text search, searches the entire text content
52 | - hybrid_search: Hybrid search, combines keyword and semantic search
53 | - **Enable Reranking**: Whether to enable reranking of search results (optional, default is false)
54 | - **Number of Results**: The number of results to return (optional, default is 3)
55 | - **Enable Score Threshold**: Whether to enable score threshold filtering (optional, default is false)
56 | - **Score Threshold**: The minimum score threshold for results (0-1) (optional, default is 0.5)
57 |
58 | ## Upload Output
59 |
60 | The upload tool returns a JSON response with the following structure:
61 | ```json
62 | {
63 | "status": "success",
64 | "knowledge_base_id": "12345678-1234-1234-1234-123456789012",
65 | "knowledge_base": {
66 | "id": "12345678-1234-1234-1234-123456789012",
67 | "name": "Knowledge Base Name"
68 | },
69 | "document": {
70 | "id": "document-id",
71 | "name": "Document Name",
72 | "batch": "batch-id",
73 | "status": "completed"
74 | }
75 | }
76 | ```
77 |
78 | ## Retrieve Output
79 |
80 | The retrieve tool returns a JSON response with the following structure:
81 | ```json
82 | {
83 | "status": "success",
84 | "query": "Query content",
85 | "knowledge_base_id": "Knowledge base ID",
86 | "results": [
87 | {
88 | "segment": {
89 | "id": "Segment ID",
90 | "content": "Segment content",
91 | "document": {
92 | "id": "Document ID",
93 | "name": "Document name"
94 | }
95 | },
96 | "score": 0.95
97 | }
98 | ]
99 | }
100 | ```
101 |
102 | The `knowledge_base_id` field can be used for further operations with the knowledge base.
103 |
104 | ## Notes
105 |
106 | - Text content requires some time for processing and indexing after upload
107 | - Processing large amounts of text may take longer
108 | - If processing is not complete, the plugin will return the current status, and you can check the processing results later on the Dify platform
109 | - Text content will be automatically segmented for processing, using automatic mode by default
110 |
111 | ## Supported File Formats
112 |
113 | - Text files (.txt)
114 | - PDF files (.pdf)
115 | - Word documents (.doc, .docx)
116 | - Markdown files (.md, .markdown)
117 | - HTML files (.html, .htm)
118 | - Excel files (.xlsx)
119 | - CSV files (.csv)
120 |
121 |
122 |
123 |
--------------------------------------------------------------------------------
/_assets/icon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/img/actions.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stvlynn/better-knowledge-base/d78e166819ff14e774f8e612ca7e4b1255b59563/img/actions.png
--------------------------------------------------------------------------------
/img/retrieve.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stvlynn/better-knowledge-base/d78e166819ff14e774f8e612ca7e4b1255b59563/img/retrieve.png
--------------------------------------------------------------------------------
/img/upload.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stvlynn/better-knowledge-base/d78e166819ff14e774f8e612ca7e4b1255b59563/img/upload.png
--------------------------------------------------------------------------------
/knowledge-manager.difypkg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stvlynn/better-knowledge-base/d78e166819ff14e774f8e612ca7e4b1255b59563/knowledge-manager.difypkg
--------------------------------------------------------------------------------
/knowledge-upload.difypkg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stvlynn/better-knowledge-base/d78e166819ff14e774f8e612ca7e4b1255b59563/knowledge-upload.difypkg
--------------------------------------------------------------------------------
/main.py:
--------------------------------------------------------------------------------
1 | from dify_plugin import Plugin, DifyPluginEnv
2 |
3 | plugin = Plugin(DifyPluginEnv(MAX_REQUEST_TIMEOUT=120))
4 |
5 | if __name__ == '__main__':
6 | plugin.run()
7 |
--------------------------------------------------------------------------------
/manifest.yaml:
--------------------------------------------------------------------------------
1 | version: 0.0.1
2 | type: plugin
3 | author: stvlynn
4 | name: knowledge-manager
5 | label:
6 | en_US: Dify Knowledge Base Manager
7 | ja_JP: Dify Knowledge Base Manager
8 | zh_Hans: Dify知识库管理器
9 | pt_BR: Dify Knowledge Base Manager
10 | description:
11 | en_US: A tool to manage Dify Knowledge Base - create, upload text content, and retrieve information.
12 | ja_JP: A tool to manage Dify Knowledge Base - create, upload text content, and retrieve information.
13 | zh_Hans: 一个管理Dify知识库的工具 - 创建、上传文本内容和检索信息。
14 | pt_BR: A tool to manage Dify Knowledge Base - create, upload text content, and retrieve information.
15 | icon: icon.svg
16 | resource:
17 | memory: 268435456
18 | permission: {}
19 | plugins:
20 | tools:
21 | - provider/knowledge.yaml
22 | meta:
23 | version: 0.0.1
24 | arch:
25 | - amd64
26 | - arm64
27 | runner:
28 | language: python
29 | version: "3.12"
30 | entrypoint: main
31 | created_at: 2025-03-04T23:40:41.394653+08:00
32 | privacy: PRIVACY.md
33 | verified: false
34 |
--------------------------------------------------------------------------------
/plugin.yaml:
--------------------------------------------------------------------------------
1 | name: knowledge-manager
2 | version: 0.0.1
3 | description:
4 | en_US: Manage Dify knowledge base - create, upload text content, and retrieve information
5 | zh_Hans: 管理Dify知识库 - 创建、上传文本内容和检索信息
6 | author: stvlynn
7 | avatar: ./_assets/icon.svg
8 | category: knowledge
9 | type: tool
10 | env:
11 | - name: DIFY_KNOWLEDGE_API_KEY
12 | description:
13 | en_US: Dify Knowledge API Key
14 | zh_Hans: Dify知识库API密钥
15 | type: secret
16 | required: true
17 | help:
18 | en_US: You can get the API Key from the API Access page in the Dify knowledge base
19 | zh_Hans: 您可以从Dify知识库的API访问页面获取API密钥
--------------------------------------------------------------------------------
/provider/knowledge.py:
--------------------------------------------------------------------------------
1 | from typing import Any
2 | import requests
3 | import os
4 |
5 | from dify_plugin import ToolProvider
6 | from dify_plugin.errors.tool import ToolProviderCredentialValidationError
7 |
8 |
9 | class KnowledgeProvider(ToolProvider):
10 | def _validate_credentials(self, credentials: dict[str, Any]) -> None:
11 | try:
12 | api_key = credentials.get('api_key')
13 | if not api_key:
14 | raise ValueError("API Key is required")
15 |
16 | # 将API Key保存到环境变量中,以便工具可以访问
17 | os.environ['DIFY_KNOWLEDGE_API_KEY'] = api_key
18 |
19 | # 尝试使用API Key获取知识库列表,验证API Key是否有效
20 | headers = {
21 | 'Authorization': f'Bearer {api_key}',
22 | 'Content-Type': 'application/json'
23 | }
24 |
25 | response = requests.get('https://api.dify.ai/v1/datasets?page=1&limit=1', headers=headers)
26 |
27 | if response.status_code != 200:
28 | error_data = response.json()
29 | raise ValueError(f"API Key validation failed: {error_data.get('message', 'Unknown error')}")
30 |
31 | except Exception as e:
32 | raise ToolProviderCredentialValidationError(str(e))
33 |
--------------------------------------------------------------------------------
/provider/knowledge.yaml:
--------------------------------------------------------------------------------
1 | identity:
2 | author: stvlynn
3 | name: knowledge
4 | label:
5 | en_US: Dify Knowledge Base
6 | zh_Hans: Dify 知识库
7 | description:
8 | en_US: A tool to manage Dify Knowledge Base - upload content and retrieve information
9 | zh_Hans: 一个管理Dify知识库的工具 - 上传内容和检索信息
10 | icon: icon.svg
11 | tags:
12 | - productivity
13 | - education
14 | credentials_for_provider:
15 | api_key:
16 | type: secret-input
17 | required: true
18 | label:
19 | en_US: Dify Knowledge Base API Key
20 | zh_Hans: Dify 知识库 API Key
21 | placeholder:
22 | en_US: Please input your Dify Knowledge Base API Key
23 | zh_Hans: 请输入您的Dify知识库API Key
24 | help:
25 | en_US: Get your API Key from Dify Knowledge Base API Access page
26 | zh_Hans: 从Dify知识库API访问页面获取您的API Key
27 | tools:
28 | - tools/knowledge_upload.yaml
29 | - tools/knowledge_retrieve.yaml
30 | extra:
31 | python:
32 | source: provider/knowledge.py
33 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | dify-plugin==0.0.1b70
2 | requests>=2.31.0
3 |
--------------------------------------------------------------------------------
/test_tool.py:
--------------------------------------------------------------------------------
1 | import os
2 | import json
3 | import time
4 | import requests
5 |
6 | # Test parameters
7 | knowledge_base_name = "Test KB"
8 | description = ""
9 | document_name = "Test Doc"
10 | text_content = "This is a test content for the document."
11 | permission = "only_me"
12 | indexing_technique = "high_quality"
13 |
14 | # Set API Key
15 | api_key = "test_key" # Replace with your actual API Key
16 |
17 | # Set request headers
18 | headers = {
19 | 'Authorization': f'Bearer {api_key}',
20 | 'Content-Type': 'application/json'
21 | }
22 |
23 | print("Starting API request test...")
24 |
25 | # Step 1: Create knowledge base
26 | print("Step 1: Creating knowledge base")
27 | url = "https://api.dify.ai/v1/datasets"
28 | payload = {
29 | "name": knowledge_base_name,
30 | "description": description,
31 | "permission": permission,
32 | "indexing_technique": indexing_technique,
33 | "provider": "vendor"
34 | }
35 |
36 | print(f"Request URL: {url}")
37 | print(f"Request parameters: {payload}")
38 |
39 | try:
40 | response = requests.post(url, headers=headers, json=payload)
41 | print(f"Response status code: {response.status_code}")
42 | print(f"Response content: {response.text}")
43 |
44 | if response.status_code == 200:
45 | result = response.json()
46 | dataset_id = result.get('id')
47 | print(f"Knowledge base created successfully, ID: {dataset_id}")
48 |
49 | # Step 2: Create document by text
50 | print("\nStep 2: Creating document")
51 | url = f"https://api.dify.ai/v1/datasets/{dataset_id}/document/create-by-text"
52 |
53 | # Prepare processing rules
54 | process_rule = {
55 | "mode": "automatic"
56 | }
57 |
58 | payload = {
59 | "name": document_name,
60 | "text": text_content,
61 | "indexing_technique": indexing_technique,
62 | "process_rule": process_rule
63 | }
64 |
65 | print(f"Request URL: {url}")
66 | print(f"Request parameters: {payload}")
67 |
68 | response = requests.post(url, headers=headers, json=payload)
69 | print(f"Response status code: {response.status_code}")
70 | print(f"Response content: {response.text}")
71 |
72 | if response.status_code == 200:
73 | result = response.json()
74 | document = result.get('document', {})
75 | document_id = document.get('id')
76 | batch = result.get('batch', '')
77 | print(f"Document created successfully, ID: {document_id}, Batch: {batch}")
78 |
79 | # Step 3: Check document processing status
80 | print("\nStep 3: Checking document processing status")
81 | url = f"https://api.dify.ai/v1/datasets/{dataset_id}/documents/{batch}/indexing-status"
82 |
83 | print(f"Request URL: {url}")
84 |
85 | response = requests.get(url, headers=headers)
86 | print(f"Response status code: {response.status_code}")
87 | print(f"Response content: {response.text}")
88 |
89 | if response.status_code == 200:
90 | result = response.json()
91 | documents = result.get('data', [])
92 | if documents:
93 | document = documents[0]
94 | status = document.get('indexing_status', 'unknown')
95 | print(f"Document status: {status}")
96 |
97 | # 测试输出JSON响应
98 | print("\nStep 4: 输出最终JSON响应")
99 | final_response = {
100 | "status": "success",
101 | "knowledge_base_id": dataset_id, # 单独列出知识库ID作为顶级字段
102 | "knowledge_base": {
103 | "id": dataset_id,
104 | "name": knowledge_base_name
105 | },
106 | "document": {
107 | "id": document_id,
108 | "name": document_name,
109 | "batch": batch,
110 | "status": status
111 | }
112 | }
113 | print(f"最终JSON响应: {json.dumps(final_response, indent=2)}")
114 | print(f"知识库ID: {final_response['knowledge_base_id']}")
115 | else:
116 | print("No document status information found")
117 | else:
118 | error_data = response.json()
119 | error_code = error_data.get('code', 'unknown_error')
120 | error_message = error_data.get('message', 'Unknown error')
121 |
122 | if error_code == "archived_document_immutable":
123 | print("Error: The archived document is not editable.")
124 | elif error_code == "document_already_finished":
125 | print("Error: The document has been processed. Please refresh the page or go to the document details.")
126 | elif error_code == "document_indexing":
127 | print("Error: The document is being processed and cannot be edited.")
128 | else:
129 | print(f"Error checking document status: {error_message}")
130 | else:
131 | error_data = response.json()
132 | error_code = error_data.get('code', 'unknown_error')
133 | error_message = error_data.get('message', 'Unknown error')
134 |
135 | if error_code == "no_file_uploaded":
136 | print("Error: Please upload your file.")
137 | elif error_code == "too_many_files":
138 | print("Error: Only one file is allowed.")
139 | elif error_code == "file_too_large":
140 | print("Error: File size exceeded.")
141 | elif error_code == "unsupported_file_type":
142 | print("Error: File type not allowed.")
143 | elif error_code == "high_quality_dataset_only":
144 | print("Error: Current operation only supports 'high-quality' datasets.")
145 | elif error_code == "dataset_not_initialized":
146 | print("Error: The dataset is still being initialized or indexing. Please wait a moment.")
147 | elif error_code == "invalid_metadata":
148 | print("Error: The metadata content is incorrect. Please check and verify.")
149 | else:
150 | print(f"Error creating document: {error_message}")
151 | else:
152 | error_data = response.json()
153 | error_code = error_data.get('code', 'unknown_error')
154 | error_message = error_data.get('message', 'Unknown error')
155 |
156 | if error_code == "dataset_name_duplicate":
157 | print("Error: The dataset name already exists. Please modify your dataset name.")
158 | elif error_code == "invalid_action":
159 | print("Error: Invalid action.")
160 | else:
161 | print(f"Error creating knowledge base: {error_message}")
162 | except Exception as e:
163 | print(f"Error occurred during test: {str(e)}")
164 |
165 | print("Test completed")
166 |
167 | def test_knowledge_upload_tool():
168 | """Test the KnowledgeUploadTool with the modified output"""
169 | from tools.knowledge_upload import KnowledgeUploadTool
170 | from dify_plugin.entities.tool import ToolInvokeMessage
171 | from unittest.mock import MagicMock, patch
172 |
173 | print("\n=== Testing KnowledgeUploadTool with modified output ===")
174 |
175 | # Create mock objects for runtime and session
176 | mock_runtime = MagicMock()
177 | mock_session = MagicMock()
178 |
179 | # Create tool instance with mock objects
180 | tool = KnowledgeUploadTool(mock_runtime, mock_session)
181 |
182 | # Set test parameters
183 | tool_parameters = {
184 | "knowledge_base_name": "Test KB",
185 | "description": "Test description",
186 | "document_name": "Test Doc",
187 | "text": "This is a test content for the document.",
188 | "permission": "only_me",
189 | "indexing_technique": "high_quality"
190 | }
191 |
192 | # Mock the API calls
193 | tool._create_knowledge_base = lambda headers, name, desc, perm, tech: "test-dataset-id-123"
194 | tool._create_document_by_text = lambda headers, dataset_id, doc_name, text, tech: {"id": "test-doc-id-456", "batch": "test-batch-789"}
195 | tool._check_document_status = lambda headers, dataset_id, batch: "completed"
196 |
197 | # Mock the create_text_message and create_json_message methods
198 | def mock_create_text_message(content):
199 | mock_msg = MagicMock()
200 | mock_msg.message_type = "text"
201 | mock_msg.content = content
202 | return mock_msg
203 |
204 | def mock_create_json_message(content):
205 | mock_msg = MagicMock()
206 | mock_msg.message_type = "json"
207 | mock_msg.content = json.dumps(content)
208 | return mock_msg
209 |
210 | tool.create_text_message = mock_create_text_message
211 | tool.create_json_message = mock_create_json_message
212 |
213 | # Mock environment variable for API key
214 | with patch.dict('os.environ', {'DIFY_KNOWLEDGE_API_KEY': 'test_api_key'}):
215 | # Invoke the tool
216 | messages = list(tool._invoke(tool_parameters))
217 |
218 | # Print all messages
219 | for i, msg in enumerate(messages):
220 | print(f"Message {i+1}: {msg.message_type}")
221 | if msg.message_type == "json":
222 | json_content = json.loads(msg.content)
223 | print(f"JSON content: {json.dumps(json_content, indent=2)}")
224 |
225 | # Verify the output fields
226 | assert "id" in json_content, "Missing 'id' field in output"
227 | assert "status" in json_content, "Missing 'status' field in output"
228 | assert json_content["status"] == 200, "Status should be 200"
229 | assert json_content["id"] == "test-dataset-id-123", "ID should match the test dataset ID"
230 |
231 | print("✅ Output validation passed!")
232 | else:
233 | print(f"Content: {msg.content}")
234 |
235 | print("=== Test completed ===\n")
236 |
237 | if __name__ == "__main__":
238 | # Run the new test for the modified output
239 | test_knowledge_upload_tool()
240 |
241 | # Uncomment to run the original API test
242 | # try:
243 | # # Step 1: Create knowledge base
244 | # # ... existing code ...
245 | # except Exception as e:
246 | # print(f"Error occurred during test: {str(e)}")
247 | #
248 | # print("Test completed")
--------------------------------------------------------------------------------
/test_tool.py.combined:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
--------------------------------------------------------------------------------
/test_tool.py.retrieve:
--------------------------------------------------------------------------------
1 | import os
2 | import json
3 | import requests
4 |
5 | # 测试参数
6 | dataset_id = "your_dataset_id" # 替换为您的知识库ID
7 | query = "测试查询"
8 | search_method = "semantic_search"
9 | reranking_enable = False
10 | top_k = 3
11 | score_threshold_enabled = False
12 | score_threshold = 0.5
13 |
14 | # 设置API Key
15 | api_key = "your_api_key" # 替换为您的API Key
16 |
17 | # 设置请求头
18 | headers = {
19 | 'Authorization': f'Bearer {api_key}',
20 | 'Content-Type': 'application/json'
21 | }
22 |
23 | print("开始API请求测试...")
24 |
25 | # 构建检索模型参数
26 | retrieval_model = {
27 | "search_method": search_method,
28 | "reranking_enable": reranking_enable,
29 | "reranking_mode": None,
30 | "reranking_model": {
31 | "reranking_provider_name": "",
32 | "reranking_model_name": ""
33 | },
34 | "weights": None,
35 | "top_k": top_k,
36 | "score_threshold_enabled": score_threshold_enabled,
37 | "score_threshold": score_threshold if score_threshold_enabled else None
38 | }
39 |
40 | # 执行知识库检索
41 | print(f"从知识库 {dataset_id} 检索与 '{query}' 相关的信息...")
42 |
43 | try:
44 | url = f"https://api.dify.ai/v1/datasets/{dataset_id}/retrieve"
45 |
46 | payload = {
47 | "query": query,
48 | "retrieval_model": retrieval_model
49 | }
50 |
51 | print(f"请求URL: {url}")
52 | print(f"请求参数: {payload}")
53 |
54 | response = requests.post(url, headers=headers, json=payload)
55 | print(f"响应状态码: {response.status_code}")
56 | print(f"响应内容: {response.text}")
57 |
58 | if response.status_code == 200:
59 | result = response.json()
60 | records = result.get('records', [])
61 |
62 | if not records:
63 | print(f"未找到与 '{query}' 相关的信息。")
64 | else:
65 | print(f"找到 {len(records)} 条相关信息:")
66 |
67 | for i, record in enumerate(records):
68 | segment = record.get('segment', {})
69 | content = segment.get('content', '')
70 | document = segment.get('document', {})
71 | document_name = document.get('name', '未知文档')
72 | score = record.get('score', 0)
73 |
74 | print(f"结果 {i+1}:")
75 | print(f"文档: {document_name}")
76 | print(f"相关度: {score}")
77 | print(f"内容: {content}")
78 | print("-------------------")
79 |
80 | # 输出最终JSON响应
81 | print("\n最终JSON响应:")
82 | final_response = {
83 | "status": "success",
84 | "query": query,
85 | "knowledge_base_id": dataset_id,
86 | "results": records
87 | }
88 | print(json.dumps(final_response, indent=2, ensure_ascii=False))
89 | else:
90 | error_data = response.json()
91 | error_code = error_data.get('code', 'unknown_error')
92 | error_message = error_data.get('message', '未知错误')
93 |
94 | if error_code == "dataset_not_found":
95 | print("知识库不存在或无权访问")
96 | elif error_code == "invalid_api_key":
97 | print("API Key无效")
98 | else:
99 | print(f"检索知识库时出错: {error_message}")
100 | except Exception as e:
101 | print(f"测试过程中发生错误: {str(e)}")
102 |
103 | print("测试完成")
--------------------------------------------------------------------------------
/test_tool.py.upload:
--------------------------------------------------------------------------------
1 | import os
2 | import json
3 | import time
4 | import requests
5 |
6 | # 测试选项
7 | test_upload = True # 设置为True测试上传功能
8 | test_retrieve = True # 设置为True测试检索功能
9 |
10 | # 上传功能测试参数
11 | knowledge_base_name = "Test KB"
12 | description = ""
13 | document_name = "Test Doc"
14 | text_content = "This is a test content for the document."
15 | permission = "only_me"
16 | indexing_technique = "high_quality"
17 |
18 | # 检索功能测试参数
19 | dataset_id = "your_dataset_id" # 替换为您的知识库ID,如果测试上传成功,会自动使用上传创建的知识库ID
20 | query = "test"
21 | search_method = "semantic_search"
22 | reranking_enable = False
23 | top_k = 3
24 | score_threshold_enabled = False
25 | score_threshold = 0.5
26 |
27 | # 设置API Key
28 | api_key = "test_key" # 替换为您的实际API Key
29 |
30 | # 设置请求头
31 | headers = {
32 | 'Authorization': f'Bearer {api_key}',
33 | 'Content-Type': 'application/json'
34 | }
35 |
36 | print("开始API请求测试...")
37 |
38 | # 上传功能测试
39 | if test_upload:
40 | print("\n===== 测试上传功能 =====")
41 | # 步骤1: 创建知识库
42 | print("步骤1: 创建知识库")
43 | url = "https://api.dify.ai/v1/datasets"
44 | payload = {
45 | "name": knowledge_base_name,
46 | "description": description,
47 | "permission": permission,
48 | "indexing_technique": indexing_technique,
49 | "provider": "vendor"
50 | }
51 |
52 | print(f"请求URL: {url}")
53 | print(f"请求参数: {payload}")
54 |
55 | try:
56 | response = requests.post(url, headers=headers, json=payload)
57 | print(f"响应状态码: {response.status_code}")
58 | print(f"响应内容: {response.text}")
59 |
60 | if response.status_code == 200:
61 | result = response.json()
62 | dataset_id = result.get('id')
63 | print(f"知识库创建成功,ID: {dataset_id}")
64 |
65 | # 步骤2: 通过文本创建文档
66 | print("\n步骤2: 创建文档")
67 | url = f"https://api.dify.ai/v1/datasets/{dataset_id}/document/create-by-text"
68 |
69 | # 准备处理规则
70 | process_rule = {
71 | "mode": "automatic"
72 | }
73 |
74 | payload = {
75 | "name": document_name,
76 | "text": text_content,
77 | "indexing_technique": indexing_technique,
78 | "process_rule": process_rule
79 | }
80 |
81 | print(f"请求URL: {url}")
82 | print(f"请求参数: {payload}")
83 |
84 | response = requests.post(url, headers=headers, json=payload)
85 | print(f"响应状态码: {response.status_code}")
86 | print(f"响应内容: {response.text}")
87 |
88 | if response.status_code == 200:
89 | result = response.json()
90 | document = result.get('document', {})
91 | document_id = document.get('id')
92 | batch = result.get('batch', '')
93 | print(f"文档创建成功,ID: {document_id}, 批次: {batch}")
94 |
95 | # 步骤3: 检查文档处理状态
96 | print("\n步骤3: 检查文档处理状态")
97 | url = f"https://api.dify.ai/v1/datasets/{dataset_id}/documents/{batch}/indexing-status"
98 |
99 | print(f"请求URL: {url}")
100 |
101 | response = requests.get(url, headers=headers)
102 | print(f"响应状态码: {response.status_code}")
103 | print(f"响应内容: {response.text}")
104 |
105 | if response.status_code == 200:
106 | result = response.json()
107 | documents = result.get('data', [])
108 | if documents:
109 | document = documents[0]
110 | # Step 1: Create knowledge base
111 | print("Step 1: Creating knowledge base")
112 | url = "https://api.dify.ai/v1/datasets"
113 | payload = {
114 | "name": knowledge_base_name,
115 | "description": description,
116 | "permission": permission,
117 | "indexing_technique": indexing_technique,
118 | "provider": "vendor"
119 | }
120 |
121 | print(f"Request URL: {url}")
122 | print(f"Request parameters: {payload}")
123 |
124 | try:
125 | response = requests.post(url, headers=headers, json=payload)
126 | print(f"Response status code: {response.status_code}")
127 | print(f"Response content: {response.text}")
128 |
129 | if response.status_code == 200:
130 | result = response.json()
131 | dataset_id = result.get('id')
132 | print(f"Knowledge base created successfully, ID: {dataset_id}")
133 |
134 | # Step 2: Create document by text
135 | print("\nStep 2: Creating document")
136 | url = f"https://api.dify.ai/v1/datasets/{dataset_id}/document/create-by-text"
137 |
138 | # Prepare processing rules
139 | process_rule = {
140 | "mode": "automatic"
141 | }
142 |
143 | payload = {
144 | "name": document_name,
145 | "text": text_content,
146 | "indexing_technique": indexing_technique,
147 | "process_rule": process_rule
148 | }
149 |
150 | print(f"Request URL: {url}")
151 | print(f"Request parameters: {payload}")
152 |
153 | response = requests.post(url, headers=headers, json=payload)
154 | print(f"Response status code: {response.status_code}")
155 | print(f"Response content: {response.text}")
156 |
157 | if response.status_code == 200:
158 | result = response.json()
159 | document = result.get('document', {})
160 | document_id = document.get('id')
161 | batch = result.get('batch', '')
162 | print(f"Document created successfully, ID: {document_id}, Batch: {batch}")
163 |
164 | # Step 3: Check document processing status
165 | print("\nStep 3: Checking document processing status")
166 | url = f"https://api.dify.ai/v1/datasets/{dataset_id}/documents/{batch}/indexing-status"
167 |
168 | print(f"Request URL: {url}")
169 |
170 | response = requests.get(url, headers=headers)
171 | print(f"Response status code: {response.status_code}")
172 | print(f"Response content: {response.text}")
173 |
174 | if response.status_code == 200:
175 | result = response.json()
176 | documents = result.get('data', [])
177 | if documents:
178 | document = documents[0]
179 | status = document.get('indexing_status', 'unknown')
180 | print(f"Document status: {status}")
181 |
182 | # 测试输出JSON响应
183 | print("\nStep 4: 输出最终JSON响应")
184 | final_response = {
185 | "status": "success",
186 | "knowledge_base_id": dataset_id, # 单独列出知识库ID作为顶级字段
187 | "knowledge_base": {
188 | "id": dataset_id,
189 | "name": knowledge_base_name
190 | },
191 | "document": {
192 | "id": document_id,
193 | "name": document_name,
194 | "batch": batch,
195 | "status": status
196 | }
197 | }
198 | print(f"最终JSON响应: {json.dumps(final_response, indent=2)}")
199 | print(f"知识库ID: {final_response['knowledge_base_id']}")
200 | else:
201 | print("No document status information found")
202 | else:
203 | error_data = response.json()
204 | error_code = error_data.get('code', 'unknown_error')
205 | error_message = error_data.get('message', 'Unknown error')
206 |
207 | if error_code == "archived_document_immutable":
208 | print("Error: The archived document is not editable.")
209 | elif error_code == "document_already_finished":
210 | print("Error: The document has been processed. Please refresh the page or go to the document details.")
211 | elif error_code == "document_indexing":
212 | print("Error: The document is being processed and cannot be edited.")
213 | else:
214 | print(f"Error checking document status: {error_message}")
215 | else:
216 | error_data = response.json()
217 | error_code = error_data.get('code', 'unknown_error')
218 | error_message = error_data.get('message', 'Unknown error')
219 |
220 | if error_code == "no_file_uploaded":
221 | print("Error: Please upload your file.")
222 | elif error_code == "too_many_files":
223 | print("Error: Only one file is allowed.")
224 | elif error_code == "file_too_large":
225 | print("Error: File size exceeded.")
226 | elif error_code == "unsupported_file_type":
227 | print("Error: File type not allowed.")
228 | elif error_code == "high_quality_dataset_only":
229 | print("Error: Current operation only supports 'high-quality' datasets.")
230 | elif error_code == "dataset_not_initialized":
231 | print("Error: The dataset is still being initialized or indexing. Please wait a moment.")
232 | elif error_code == "invalid_metadata":
233 | print("Error: The metadata content is incorrect. Please check and verify.")
234 | else:
235 | print(f"Error creating document: {error_message}")
236 | else:
237 | error_data = response.json()
238 | error_code = error_data.get('code', 'unknown_error')
239 | error_message = error_data.get('message', 'Unknown error')
240 |
241 | if error_code == "dataset_name_duplicate":
242 | print("Error: The dataset name already exists. Please modify your dataset name.")
243 | elif error_code == "invalid_action":
244 | print("Error: Invalid action.")
245 | else:
246 | print(f"Error creating knowledge base: {error_message}")
247 | except Exception as e:
248 | print(f"Error occurred during test: {str(e)}")
249 |
250 | print("Test completed")
--------------------------------------------------------------------------------
/tools/knowledge_retrieve.py:
--------------------------------------------------------------------------------
1 | import os
2 | import json
3 | import requests
4 | from collections.abc import Generator
5 | from typing import Any, Dict, Optional, List
6 |
7 | from dify_plugin import Tool
8 | from dify_plugin.entities.tool import ToolInvokeMessage
9 |
10 | class KnowledgeRetrieveTool(Tool):
11 | def _invoke(self, tool_parameters: dict[str, Any]) -> Generator[ToolInvokeMessage, None, None]:
12 | # Get parameters
13 | dataset_id = tool_parameters.get('dataset_id')
14 | query = tool_parameters.get('query')
15 | search_method = tool_parameters.get('search_method', 'semantic_search')
16 | reranking_enable = tool_parameters.get('reranking_enable', False)
17 | top_k = tool_parameters.get('top_k', 3)
18 | score_threshold_enabled = tool_parameters.get('score_threshold_enabled', False)
19 | score_threshold = tool_parameters.get('score_threshold', 0.5)
20 |
21 | # Debug information
22 | print(f"Received parameters: {tool_parameters}")
23 |
24 | # Check required parameters
25 | if not dataset_id:
26 | yield self.create_text_message("Knowledge base ID is required.")
27 | return
28 |
29 | if not query:
30 | yield self.create_text_message("Query content is required.")
31 | return
32 |
33 | # Get API Key from environment variables
34 | api_key = os.environ.get('DIFY_KNOWLEDGE_API_KEY')
35 | if not api_key:
36 | yield self.create_text_message("API Key not found. Please make sure it's set in the plugin configuration.")
37 | return
38 |
39 | # Set request headers
40 | headers = {
41 | 'Authorization': f'Bearer {api_key}',
42 | 'Content-Type': 'application/json'
43 | }
44 |
45 | # Build retrieval model parameters
46 | retrieval_model = {
47 | "search_method": search_method,
48 | "reranking_enable": reranking_enable,
49 | "reranking_mode": None,
50 | "reranking_model": {
51 | "reranking_provider_name": "",
52 | "reranking_model_name": ""
53 | },
54 | "weights": None,
55 | "top_k": top_k,
56 | "score_threshold_enabled": score_threshold_enabled,
57 | "score_threshold": score_threshold if score_threshold_enabled else None
58 | }
59 |
60 | # Perform knowledge base retrieval
61 | yield self.create_text_message(f"Retrieving information from knowledge base {dataset_id} related to '{query}'...")
62 |
63 | result = self._retrieve_from_knowledge_base(headers, dataset_id, query, retrieval_model)
64 | if not result:
65 | yield self.create_text_message("Retrieval failed. Please check your API Key and parameters.")
66 | return
67 |
68 | if isinstance(result, str):
69 | # This is an error message
70 | yield self.create_text_message(f"Error: {result}")
71 | return
72 |
73 | records = result.get('records', [])
74 |
75 | if not records:
76 | yield self.create_text_message(f"No information found related to '{query}'.")
77 | return
78 |
79 | # Return retrieval results
80 | yield self.create_text_message(f"Found {len(records)} related results:")
81 |
82 | for i, record in enumerate(records):
83 | segment = record.get('segment', {})
84 | content = segment.get('content', '')
85 | document = segment.get('document', {})
86 | document_name = document.get('name', 'Unknown document')
87 | score = record.get('score', 0)
88 |
89 | result_text = f"Result {i+1}:\n"
90 | result_text += f"Document: {document_name}\n"
91 | result_text += f"Relevance: {score}\n"
92 | result_text += f"Content: {content}\n"
93 | result_text += "-------------------"
94 |
95 | yield self.create_text_message(result_text)
96 |
97 | # Return detailed information
98 | yield self.create_json_message({
99 | "status": "success",
100 | "query": query,
101 | "knowledge_base_id": dataset_id,
102 | "results": records
103 | })
104 |
105 | def _retrieve_from_knowledge_base(self, headers: Dict, dataset_id: str, query: str, retrieval_model: Dict) -> Optional[Dict]:
106 | """Retrieve information from knowledge base"""
107 | try:
108 | url = f"https://api.dify.ai/v1/datasets/{dataset_id}/retrieve"
109 |
110 | payload = {
111 | "query": query,
112 | "retrieval_model": retrieval_model
113 | }
114 |
115 | print(f"Knowledge base retrieval request URL: {url}")
116 | print(f"Knowledge base retrieval request parameters: {payload}")
117 |
118 | response = requests.post(url, headers=headers, json=payload)
119 |
120 | print(f"Knowledge base retrieval response status code: {response.status_code}")
121 | print(f"Knowledge base retrieval response content: {response.text}")
122 |
123 | if response.status_code == 200:
124 | return response.json()
125 | else:
126 | error_data = response.json()
127 | error_code = error_data.get('code', 'unknown_error')
128 | error_message = error_data.get('message', 'Unknown error')
129 |
130 | if error_code == "dataset_not_found":
131 | return "Knowledge base does not exist or you don't have access"
132 | elif error_code == "invalid_api_key":
133 | return "Invalid API Key"
134 | else:
135 | print(f"Error retrieving from knowledge base: {error_message}")
136 | print(f"Status code: {response.status_code}")
137 | print(f"Response content: {response.text}")
138 | return f"Retrieval failed: {error_message}"
139 | except Exception as e:
140 | print(f"Error occurred while retrieving from knowledge base: {str(e)}")
141 | return f"Exception occurred: {str(e)}"
--------------------------------------------------------------------------------
/tools/knowledge_retrieve.yaml:
--------------------------------------------------------------------------------
1 | identity:
2 | name: knowledge_retrieve
3 | author: stvlynn
4 | label:
5 | en_US: Retrieve from Knowledge Base
6 | zh_Hans: 从知识库检索
7 | description:
8 | human:
9 | en_US: A tool to retrieve information from Dify Knowledge Base.
10 | zh_Hans: 一个从Dify知识库检索信息的工具。
11 | llm: A tool to retrieve information from Dify Knowledge Base.
12 | parameters:
13 | - name: dataset_id
14 | type: string
15 | required: true
16 | label:
17 | en_US: Knowledge Base ID
18 | zh_Hans: 知识库ID
19 | human_description:
20 | en_US: The ID of the knowledge base to retrieve from
21 | zh_Hans: 要检索的知识库ID
22 | llm_description: The ID of the knowledge base to retrieve from
23 | form: form
24 | - name: query
25 | type: string
26 | required: true
27 | label:
28 | en_US: Query
29 | zh_Hans: 查询内容
30 | human_description:
31 | en_US: The query to search for in the knowledge base
32 | zh_Hans: 在知识库中搜索的查询内容
33 | llm_description: The query to search for in the knowledge base
34 | form: llm
35 | - name: search_method
36 | type: select
37 | required: false
38 | options:
39 | - value: keyword_search
40 | label:
41 | en_US: Keyword Search
42 | zh_Hans: 关键词检索
43 | - value: semantic_search
44 | label:
45 | en_US: Semantic Search
46 | zh_Hans: 语义检索
47 | - value: full_text_search
48 | label:
49 | en_US: Full Text Search
50 | zh_Hans: 全文检索
51 | - value: hybrid_search
52 | label:
53 | en_US: Hybrid Search
54 | zh_Hans: 混合检索
55 | default: semantic_search
56 | label:
57 | en_US: Search Method
58 | zh_Hans: 搜索方法
59 | human_description:
60 | en_US: The method to use for searching the knowledge base
61 | zh_Hans: 用于搜索知识库的方法
62 | llm_description: The method to use for searching the knowledge base
63 | form: form
64 | - name: reranking_enable
65 | type: boolean
66 | required: false
67 | default: false
68 | label:
69 | en_US: Enable Reranking
70 | zh_Hans: 启用重排序
71 | human_description:
72 | en_US: Whether to enable reranking of search results
73 | zh_Hans: 是否启用搜索结果重排序
74 | llm_description: Whether to enable reranking of search results
75 | form: form
76 | - name: top_k
77 | type: number
78 | required: false
79 | default: 3
80 | label:
81 | en_US: Number of Results
82 | zh_Hans: 结果数量
83 | human_description:
84 | en_US: The number of results to return
85 | zh_Hans: 返回的结果数量
86 | llm_description: The number of results to return
87 | form: form
88 | - name: score_threshold_enabled
89 | type: boolean
90 | required: false
91 | default: false
92 | label:
93 | en_US: Enable Score Threshold
94 | zh_Hans: 启用分数阈值
95 | human_description:
96 | en_US: Whether to enable score threshold filtering
97 | zh_Hans: 是否启用分数阈值过滤
98 | llm_description: Whether to enable score threshold filtering
99 | form: form
100 | - name: score_threshold
101 | type: number
102 | required: false
103 | default: 0.5
104 | label:
105 | en_US: Score Threshold
106 | zh_Hans: 分数阈值
107 | human_description:
108 | en_US: The minimum score threshold for results (0-1)
109 | zh_Hans: 结果的最小分数阈值(0-1)
110 | llm_description: The minimum score threshold for results (0-1)
111 | form: form
112 | extra:
113 | python:
114 | source: tools/knowledge_retrieve.py
--------------------------------------------------------------------------------
/tools/knowledge_upload.py:
--------------------------------------------------------------------------------
1 | import os
2 | import json
3 | import time
4 | import requests
5 | from collections.abc import Generator
6 | from typing import Any, Dict, Optional, List
7 |
8 | from dify_plugin import Tool
9 | from dify_plugin.entities.tool import ToolInvokeMessage
10 |
11 | class KnowledgeUploadTool(Tool):
12 | def _invoke(self, tool_parameters: dict[str, Any]) -> Generator[ToolInvokeMessage, None, None]:
13 | # Get parameters
14 | knowledge_base_name = tool_parameters.get('knowledge_base_name')
15 | description = tool_parameters.get('description', '')
16 | document_name = tool_parameters.get('document_name')
17 | text_content = tool_parameters.get('text')
18 | permission = tool_parameters.get('permission', 'only_me')
19 | indexing_technique = tool_parameters.get('indexing_technique', 'high_quality')
20 |
21 | # Debug information
22 | print(f"Received parameters: {tool_parameters}")
23 | print(f"Text content: {text_content}")
24 |
25 | # Check required parameters
26 | if not knowledge_base_name:
27 | yield self.create_text_message("Knowledge base name is required.")
28 | return
29 |
30 | if not document_name:
31 | yield self.create_text_message("Document name is required.")
32 | return
33 |
34 | if not text_content:
35 | yield self.create_text_message("Text content is required.")
36 | return
37 |
38 | # Get API Key from environment variables
39 | api_key = os.environ.get('DIFY_KNOWLEDGE_API_KEY')
40 | if not api_key:
41 | yield self.create_text_message("API Key not found. Please make sure it's set in the plugin configuration.")
42 | return
43 |
44 | # Set request headers
45 | headers = {
46 | 'Authorization': f'Bearer {api_key}',
47 | 'Content-Type': 'application/json'
48 | }
49 |
50 | # Step 1: Create knowledge base
51 | yield self.create_text_message(f"Creating knowledge base: {knowledge_base_name}...")
52 |
53 | dataset_id = self._create_knowledge_base(headers, knowledge_base_name, description, permission, indexing_technique)
54 | if not dataset_id:
55 | yield self.create_text_message("Failed to create knowledge base. Please check your API Key and parameters.")
56 | return
57 |
58 | yield self.create_text_message(f"Knowledge base created successfully, ID: {dataset_id}")
59 |
60 | # Step 2: Create document with text
61 | yield self.create_text_message(f"Creating document: {document_name}...")
62 |
63 | document_result = self._create_document_by_text(headers, dataset_id, document_name, text_content, indexing_technique)
64 | if not document_result:
65 | yield self.create_text_message("Failed to create document. Please check your parameters.")
66 | return
67 |
68 | if isinstance(document_result, str):
69 | # This is an error message
70 | yield self.create_text_message(f"Error: {document_result}")
71 | return
72 |
73 | document_id = document_result.get('id')
74 | batch = document_result.get('batch')
75 |
76 | yield self.create_text_message(f"Document created successfully, ID: {document_id}, Batch: {batch}")
77 |
78 | # Step 3: Check document processing status
79 | yield self.create_text_message(f"Processing document, please wait...")
80 |
81 | status_result = self._check_document_status(headers, dataset_id, batch)
82 |
83 | if isinstance(status_result, str) and status_result.startswith("Error:"):
84 | yield self.create_text_message(status_result)
85 | return
86 |
87 | status = status_result
88 |
89 | if status == "completed":
90 | yield self.create_text_message(f"Document processing completed!")
91 | elif status == "error" or status == "failed":
92 | yield self.create_text_message(f"Document processing failed. Please check your text content.")
93 | else:
94 | yield self.create_text_message(f"Document is being processed, current status: {status}")
95 | yield self.create_text_message(f"You can check the result later on the Dify platform.")
96 |
97 | # Return detailed information
98 | yield self.create_json_message({
99 | "status": 200,
100 | "id": dataset_id,
101 | "knowledge_base": {
102 | "id": dataset_id,
103 | "name": knowledge_base_name
104 | },
105 | "document": {
106 | "id": document_id,
107 | "name": document_name,
108 | "batch": batch,
109 | "status": status
110 | }
111 | })
112 |
113 | def _create_knowledge_base(self, headers: Dict, name: str, description: str, permission: str, indexing_technique: str) -> Optional[str]:
114 | """Create an empty knowledge base"""
115 | try:
116 | url = "https://api.dify.ai/v1/datasets"
117 | payload = {
118 | "name": name,
119 | "description": description,
120 | "permission": permission,
121 | "indexing_technique": indexing_technique,
122 | "provider": "vendor"
123 | }
124 |
125 | print(f"Knowledge base creation request URL: {url}")
126 | print(f"Knowledge base creation request parameters: {payload}")
127 |
128 | response = requests.post(url, headers=headers, json=payload)
129 |
130 | print(f"Knowledge base creation response status code: {response.status_code}")
131 | print(f"Knowledge base creation response content: {response.text}")
132 |
133 | if response.status_code == 200:
134 | result = response.json()
135 | return result.get('id')
136 | else:
137 | error_data = response.json()
138 | error_code = error_data.get('code', 'unknown_error')
139 | error_message = error_data.get('message', 'Unknown error')
140 |
141 | if error_code == "dataset_name_duplicate":
142 | print(f"Error: The dataset name already exists. Please modify your dataset name.")
143 | elif error_code == "invalid_action":
144 | print(f"Error: Invalid action.")
145 | else:
146 | print(f"Error creating knowledge base: {error_message}")
147 |
148 | print(f"Status code: {response.status_code}")
149 | print(f"Response content: {response.text}")
150 | return None
151 | except Exception as e:
152 | print(f"Error occurred while creating knowledge base: {str(e)}")
153 | return None
154 |
155 | def _create_document_by_text(self, headers: Dict, dataset_id: str, document_name: str, text_content: str, indexing_technique: str) -> Optional[Dict]:
156 | """Create document by text"""
157 | try:
158 | # Correct API endpoint
159 | url = f"https://api.dify.ai/v1/datasets/{dataset_id}/document/create-by-text"
160 |
161 | # Prepare processing rules
162 | process_rule = {
163 | "mode": "automatic"
164 | }
165 |
166 | # Ensure text content is a string
167 | if not isinstance(text_content, str):
168 | text_content = str(text_content)
169 |
170 | payload = {
171 | "name": document_name,
172 | "text": text_content,
173 | "indexing_technique": indexing_technique,
174 | "process_rule": process_rule
175 | }
176 |
177 | print(f"Document creation request URL: {url}")
178 | print(f"Document creation request parameters: {payload}")
179 |
180 | response = requests.post(url, headers=headers, json=payload)
181 |
182 | print(f"Document creation response status code: {response.status_code}")
183 | print(f"Document creation response content: {response.text}")
184 |
185 | if response.status_code == 200:
186 | result = response.json()
187 | document = result.get('document', {})
188 | batch = result.get('batch', '')
189 | return {
190 | 'id': document.get('id'),
191 | 'batch': batch
192 | }
193 | else:
194 | error_data = response.json()
195 | error_code = error_data.get('code', 'unknown_error')
196 | error_message = error_data.get('message', 'Unknown error')
197 |
198 | if error_code == "no_file_uploaded":
199 | return "Error: Please upload your file."
200 | elif error_code == "too_many_files":
201 | return "Error: Only one file is allowed."
202 | elif error_code == "file_too_large":
203 | return "Error: File size exceeded."
204 | elif error_code == "unsupported_file_type":
205 | return "Error: File type not allowed."
206 | elif error_code == "high_quality_dataset_only":
207 | return "Error: Current operation only supports 'high-quality' datasets."
208 | elif error_code == "dataset_not_initialized":
209 | return "Error: The dataset is still being initialized or indexing. Please wait a moment."
210 | elif error_code == "invalid_metadata":
211 | return "Error: The metadata content is incorrect. Please check and verify."
212 | else:
213 | print(f"Error creating document: {error_message}")
214 | print(f"Status code: {response.status_code}")
215 | print(f"Response content: {response.text}")
216 | return None
217 | except Exception as e:
218 | print(f"Error occurred while creating document: {str(e)}")
219 | print(f"Exception details: {repr(e)}")
220 | return None
221 |
222 | def _check_document_status(self, headers: Dict, dataset_id: str, batch: str) -> str:
223 | """Check document processing status"""
224 | try:
225 | # Use the correct API endpoint
226 | url = f"https://api.dify.ai/v1/datasets/{dataset_id}/documents/{batch}/indexing-status"
227 |
228 | print(f"Document status check request URL: {url}")
229 |
230 | # Try to check status, maximum 5 attempts
231 | for i in range(5):
232 | print(f"Document status check attempt {i+1}")
233 | response = requests.get(url, headers=headers)
234 |
235 | print(f"Document status check response status code: {response.status_code}")
236 | print(f"Document status check response content: {response.text}")
237 |
238 | if response.status_code == 200:
239 | result = response.json()
240 | documents = result.get('data', [])
241 |
242 | if documents:
243 | document = documents[0]
244 | status = document.get('indexing_status', 'unknown')
245 | print(f"Document status: {status}")
246 |
247 | if status in ['completed', 'error', 'failed']:
248 | return status
249 |
250 | # If still processing, wait 3 seconds before checking again
251 | print("Document is still being processed, waiting 3 seconds before checking again")
252 | time.sleep(3)
253 | else:
254 | error_data = response.json()
255 | error_code = error_data.get('code', 'unknown_error')
256 | error_message = error_data.get('message', 'Unknown error')
257 |
258 | if error_code == "archived_document_immutable":
259 | return "Error: The archived document is not editable."
260 | elif error_code == "document_already_finished":
261 | return "Error: The document has been processed. Please refresh the page or go to the document details."
262 | elif error_code == "document_indexing":
263 | return "Error: The document is being processed and cannot be edited."
264 | else:
265 | print(f"Error checking document status: {error_message}")
266 | print(f"Response content: {response.text}")
267 | return "Error: Failed to check document status."
268 |
269 | # If still not completed after 5 attempts, return processing status
270 | return "processing"
271 | except Exception as e:
272 | print(f"Error occurred while checking document status: {str(e)}")
273 | return "Error: An unexpected error occurred while checking document status."
--------------------------------------------------------------------------------
/tools/knowledge_upload.yaml:
--------------------------------------------------------------------------------
1 | identity:
2 | name: knowledge_upload
3 | author: stvlynn
4 | label:
5 | en_US: Upload to Knowledge Base
6 | zh_Hans: 上传到知识库
7 | description:
8 | human:
9 | en_US: A tool to upload text content to Dify Knowledge Base.
10 | zh_Hans: 一个上传文本内容到Dify知识库的工具。
11 | llm: A tool to upload text content to Dify Knowledge Base.
12 | parameters:
13 | - name: knowledge_base_name
14 | type: string
15 | required: true
16 | label:
17 | en_US: Knowledge Base Name
18 | zh_Hans: 知识库名称
19 | human_description:
20 | en_US: The name of the knowledge base to create
21 | zh_Hans: 要创建的知识库名称
22 | llm_description: The name of the knowledge base to create
23 | form: form
24 | - name: description
25 | type: string
26 | required: false
27 | label:
28 | en_US: Description
29 | zh_Hans: 描述
30 | human_description:
31 | en_US: The description of the knowledge base
32 | zh_Hans: 知识库的描述
33 | llm_description: The description of the knowledge base
34 | form: form
35 | - name: document_name
36 | type: string
37 | required: true
38 | label:
39 | en_US: Document Name
40 | zh_Hans: 文档名称
41 | human_description:
42 | en_US: The name of the document to create
43 | zh_Hans: 要创建的文档名称
44 | llm_description: The name of the document to create
45 | form: form
46 | - name: text
47 | type: string
48 | required: true
49 | label:
50 | en_US: Text Content
51 | zh_Hans: 文本内容
52 | human_description:
53 | en_US: The text content to upload to the knowledge base
54 | zh_Hans: 要上传到知识库的文本内容
55 | llm_description: The text content to upload to the knowledge base
56 | form: llm
57 | - name: permission
58 | type: select
59 | required: true
60 | options:
61 | - value: only_me
62 | label:
63 | en_US: Only Me
64 | zh_Hans: 仅自己
65 | - value: publicly_readable
66 | label:
67 | en_US: Publicly Readable
68 | zh_Hans: 公开可读
69 | default: only_me
70 | label:
71 | en_US: Permission
72 | zh_Hans: 权限
73 | human_description:
74 | en_US: The permission of the knowledge base (only_me or publicly_readable)
75 | zh_Hans: 知识库的权限(仅自己或公开可读)
76 | llm_description: The permission of the knowledge base (only_me or publicly_readable)
77 | form: form
78 | - name: indexing_technique
79 | type: select
80 | required: true
81 | options:
82 | - value: high_quality
83 | label:
84 | en_US: High Quality
85 | zh_Hans: 高质量
86 | - value: economy
87 | label:
88 | en_US: Economy
89 | zh_Hans: 经济
90 | default: high_quality
91 | label:
92 | en_US: Indexing Technique
93 | zh_Hans: 索引技术
94 | human_description:
95 | en_US: The indexing technique to use (high_quality or economy)
96 | zh_Hans: 要使用的索引技术(高质量或经济)
97 | llm_description: The indexing technique to use (high_quality or economy)
98 | form: form
99 | extra:
100 | python:
101 | source: tools/knowledge_upload.py
--------------------------------------------------------------------------------