为了方便区分,本文将 Dify 平台之外的知识库统称为“外部知识库”。
功能简介
Dify 内置的知识库功能和文本检索机制可能无法满足部分高级开发者的需求,他们可能需要更精确地控制文本召回结果。
有些团队会选择自研 RAG 算法并独立维护文本召回系统,或者使用云服务商提供的知识库服务(如 AWS Bedrock)。
Dify 作为一个开放的 LLM 应用开发平台,希望给开发者提供更多的选择。
通过“连接外部知识库”功能,Dify 可以与外部知识库建立连接。这样,AI 应用就能获取更多信息来源。
具体来说,有以下优势:
- Dify 可以直接获取托管在云服务商知识库内的文本,开发者无需将内容复制到 Dify 的知识库中。
- Dify 可以直接获取自建知识库中经过算法处理后的文本,开发者只需专注于优化信息检索机制,提高召回准确度。
- 相比直接使用云厂商的知识库服务,Dify 提供了更灵活的应用层集成能力,方便开发者构建多样化的 AI 应用。
下图展示了外部知识库的连接原理:
连接步骤
1. 建立符合要求的外部知识库 API
在建立 API 服务之前,请务必仔细阅读 Dify 编写的外部知识库 API 规范。
2. 关联外部知识库 API
请注意,Dify 目前仅支持对外部知识库进行检索,不支持修改。开发者需要自行维护外部知识库。
进入“知识库”页面,点击右上角的“外部知识库 API”,然后点击“添加外部知识库 API”。
根据页面提示填写:
- 知识库名称: 可以自定义,用于区分不同的外部知识库 API。
- API 接口地址: 外部知识库的连接地址,例如
api-endpoint/retrieval
。详细说明请参考外部知识库 API。 - API Key: 外部知识库的连接密钥,详细说明请参考外部知识库 API。
3. 连接外部知识库
在“知识库”页面,点击“添加知识库”下方的“连接外部知识库”,进入参数配置页面。
填写以下参数:
- 知识库名称与描述
- 外部知识库 API: 选择在第二步中关联的外部知识库 API。 Dify 将通过 API 连接调用外部知识库的文本内容。
- 外部知识库 ID: 指定需要关联的外部知识库 ID,详细说明请参考外部知识库 API。
- 调整召回设置:
- Top K: 值越大,召回的文本片段越多。建议从较小的值开始尝试,逐步增加,直到找到最佳平衡点。
- Score 阈值: 值越高,召回的文本片段与问题的相关性越高,但数量会减少。建议从较高的值开始,逐步降低,以获取足够数量的相关文本。
4. 测试连接与召回
连接建立后,可以在“召回测试”中模拟问题关键词,预览从外部知识库召回的文本片段。如果对结果不满意,可以尝试修改召回参数或调整外部知识库的检索设置。
5. 在应用内集成
- Chatbot / Agent 类型应用: 在编排页面的“上下文”中,选择带有
EXTERNAL
标签的外部知识库。
- Chatflow / Workflow 类型应用: 添加“知识检索”节点,选择带有
EXTERNAL
标签的外部知识库。
6. 管理外部知识库
在“知识库”页面,外部知识库卡片右上角会有 EXTERNAL
标签。进入需要修改的知识库,点击“设置”可以修改:
- 知识库名称和描述
- 可见范围(“只有我”、“所有团队成员”和“部分团队成员”)。没有权限的成员无法访问该知识库。
- 召回设置(Top K 和 Score 阈值)
注意:无法修改已关联的“外部知识库 API”和“外部知识 ID”,如需修改,请关联新的“外部知识库 API”并重新连接。
连接示例:如何连接 AWS Bedrock 知识库?
本文将简要介绍如何通过外部知识库 API 将 Dify 平台与 AWS Bedrock 知识库相连接,使得 Dify 平台内的 AI 应用能够直接获取存储在 AWS Bedrock 知识库中的内容,扩展新的信息来源渠道。
前置准备
- AWS Bedrock Knowledge Base
- Dify SaaS 服务 / Dify 社区版
- 后端 API 开发基础知识
1. 注册并创建 AWS Bedrock Knowledge Base
访问 AWS Bedrock,创建 Knowledge Base 服务。
2. 构建后端 API 服务
Dify 平台尚不能直接连接 AWS Bedrock Knowledge Base,需要开发团队参考 Dify 关于外部知识库连接的 API 定义,手动创建后端 API 服务,建立与 AWS Bedrock 的连接。具体架构示意图请参考:
你可以参考以下 2 个代码文件,构建后端服务 API。
knowledge.py
from flask import request
from flask_restful import Resource, reqparse
from bedrock.knowledge_service import ExternalDatasetService
class BedrockRetrievalApi(Resource):
# url : <your-endpoint>/retrieval
def post(self):
parser = reqparse.RequestParser()
parser.add_argument("retrieval_setting", nullable=False, required=True, type=dict, location="json")
parser.add_argument("query", nullable=False, required=True, type=str,)
parser.add_argument("knowledge_id", nullable=False, required=True, type=str)
args = parser.parse_args()
# Authorization check
auth_header = request.headers.get("Authorization")
if " " not in auth_header:
return {
"error_code": 1001,
"error_msg": "Invalid Authorization header format. Expected 'Bearer <api-key>' format."
}, 403
auth_scheme, auth_token = auth_header.split(None, 1)
auth_scheme = auth_scheme.lower()
if auth_scheme != "bearer":
return {
"error_code": 1001,
"error_msg": "Invalid Authorization header format. Expected 'Bearer <api-key>' format."
}, 403
if auth_token:
# process your authorization logic here
pass
# Call the knowledge retrieval service
result = ExternalDatasetService.knowledge_retrieval(
args["retrieval_setting"], args["query"], args["knowledge_id"]
)
return result, 200
knowledge_service.py
import boto3
class ExternalDatasetService:
@staticmethod
def knowledge_retrieval(retrieval_setting: dict, query: str, knowledge_id: str):
# get bedrock client
client = boto3.client(
"bedrock-agent-runtime",
aws_secret_access_key="AWS_SECRET_ACCESS_KEY",
aws_access_key_id="AWS_ACCESS_KEY_ID",
# example: us-east-1
region_name="AWS_REGION_NAME",
)
# fetch external knowledge retrieval
response = client.retrieve(
knowledgeBaseId=knowledge_id,
retrievalConfiguration={
"vectorSearchConfiguration": {"numberOfResults": retrieval_setting.get("top_k"), "overrideSearchType": "HYBRID"}
},
retrievalQuery={"text": query},
)
# parse response
results = []
if response.get("ResponseMetadata") and response.get("ResponseMetadata").get("HTTPStatusCode") == 200:
if response.get("retrievalResults"):
retrieval_results = response.get("retrievalResults")
for retrieval_result in retrieval_results:
# filter out results with score less than threshold
if retrieval_result.get("score") < retrieval_setting.get("score_threshold", .0):
continue
result = {
"metadata": retrieval_result.get("metadata"),
"score": retrieval_result.get("score"),
"title": retrieval_result.get("metadata").get("x-amz-bedrock-kb-source-uri"),
"content": retrieval_result.get("content").get("text"),
}
results.append(result)
return {
"records": results
}
在此过程中,你可以构建 API 接口地址以及用于鉴权的 API Key 并用于后续的连接。
3. 获取 AWS Bedrock Knowledge Base ID
登录 AWS Bedrock Knowledge 后台,获取已创建 Knowledge Base 的 ID。此参数将会在后续步骤用于与 Dify 平台的连接。
4. 关联外部知识 API
前往 Dify 平台中的 “知识库” 页,点击右上角的 “外部知识库 API”,轻点 “添加外部知识库 API”。
按照页面提示,依次填写以下内容:
- 知识库的名称,允许自定义名称,用于区分 Dify 平台内所连接的不同外部知识 API;
- API 接口地址,外部知识库的连接地址,可在第二步中自定义。示例
api-endpoint/retrieval
; - API Key,外部知识库连接密钥,可在第二步中自定义。
5. 连接外部知识库
前往 “知识库” 页,点击添加知识库卡片下方的 “连接外部知识库” 跳转至参数配置页面。
填写以下参数:
- 知识库名称与描述
- 外部知识库 API选择在第四步中关联的外部知识库 API
- 外部知识库 ID填写在第三步中获取的 AWS Bedrock knowledge base ID
- 调整召回设置Top K:用户发起提问时,将请求外部知识 API 获取相关性较高的内容分段。该参数用于筛选与用户问题相似度较高的文本片段。默认值为 3,数值越高,召回存在相关性的文本分段也就越多。
Score 阈值:文本片段筛选的相似度阈值,只召回超过设置分数的文本片段,默认值为 0.5。数值越高说明对于文本与问题要求的相似度越高,预期被召回的文本数量也越少,结果也会相对而言更加精准。
设置完成后即可建立与外部知识库 API 的连接。
6. 测试外部知识库连接与召回
建立与外部知识库的连接后,开发者可以在 “召回测试” 中模拟可能的问题关键词,预览从 AWS Bedrock Knowledge Base 召回的文本分段。
若对于召回结果不满意,可以尝试修改召回参数或自行调整 AWS Bedrock Knowledge Base 的检索设置。
常见问题
连接外部知识库 API 时出现错误怎么办?
以下是错误码及对应的解决办法:
错误码 | 错误提示 | 解决办法 |
---|---|---|
1001 | 无效的 Authorization header 格式 | 检查请求的 Authorization header 格式 |
1002 | 验证异常 | 检查 API Key 是否正确 |
2001 | 知识库不存在 | 检查外部知识库 |
外部知识库 API 规范
端点
POST <your-endpoint>/retrieval
请求头
该 API 用于连接团队内独立维护的知识库。更多操作指引,请参考连接外部知识库。
可以在 HTTP 请求头的 Authorization
字段中使用 API-Key
来验证权限。身份验证逻辑由你在检索 API 中定义,如下所示:
Authorization: Bearer {API_KEY}
请求体
请求接受以下 JSON 格式的数据:
属性 | 必填 | 类型 | 描述 | 示例值 |
---|---|---|---|---|
knowledge_id | 是 | 字符串 | 知识库唯一 ID | AAA-BBB-CCC |
query | 是 | 字符串 | 用户的查询 | Dify 是什么? |
retrieval_setting | 是 | 对象 | 知识检索参数 | 见下文 |
retrieval_setting
属性包含以下键:
属性 | 必填 | 类型 | 描述 | 示例值 |
---|---|---|---|---|
top_k | 是 | 整数 | 检索结果的最大数量 | 5 |
score_threshold | 是 | 浮点数 | 结果与查询相关性的分数限制,范围:0~1 | 0.5 |
请求示例
POST <your-endpoint>/retrieval HTTP/1.1
Content-Type: application/json
Authorization: Bearer your-api-key
{
"knowledge_id": "your-knowledge-id",
"query": "你的问题",
"retrieval_setting": {
"top_k": 2,
"score_threshold": 0.5
}
}
响应体
如果操作成功,服务将返回 HTTP 200 响应,并以 JSON 格式返回以下数据:
属性 | 必填 | 类型 | 描述 | 示例值 |
---|---|---|---|---|
records | 是 | 对象列表 | 从知识库查询的记录列表 | 见下文 |
records
属性是一个对象列表,包含以下键:
属性 | 必填 | 类型 | 描述 | 示例值 |
---|---|---|---|---|
content | 是 | 字符串 | 知识库中文本块 | Dify:GenAI 应用开发平台 |
score | 是 | 浮点数 | 结果与查询的相关性分数,范围:0~1 | 0.98 |
title | 是 | 字符串 | 文档标题 | Dify 简介 |
metadata | 否 | JSON | 数据源中文档的元数据属性及其值 | 见示例 |
响应示例
HTTP/1.1 200
Content-Type: application/json
{
"records": [
{
"metadata": {
"path": "s3://dify/knowledge.txt",
"description": "dify 知识文档"
},
"score": 0.98,
"title": "knowledge.txt",
"content": "这是外部知识的文档。"
},
{
"metadata": {
"path": "s3://dify/introduce.txt",
"description": "dify 介绍"
},
"score": 0.66,
"title": "introduce.txt",
"content": "GenAI 应用程序的创新引擎"
}
]
}
错误
如果操作失败,服务将返回以下错误信息(JSON 格式):
属性 | 必填 | 类型 | 描述 | 示例值 |
---|---|---|---|---|
error_code | 是 | 整数 | 错误代码 | 1001 |
error_msg | 是 | 字符串 | API 异常描述 | 无效的 Authorization 头格式。 |
error_code
属性类型:
代码 | 描述 |
---|---|
1001 | 无效的 Authorization 头格式 |
1002 | 授权失败 |
2001 | 知识库不存在 |
HTTP 状态码
- AccessDeniedException: 缺少访问权限。 (HTTP 状态码:403)
- InternalServerException: 内部服务器错误。 (HTTP 状态码:500)