diff --git a/zh_CN/.gitbook/assets/api_based_01.png b/zh_CN/.gitbook/assets/api_based_01.png new file mode 100644 index 0000000..e21f08b Binary files /dev/null and b/zh_CN/.gitbook/assets/api_based_01.png differ diff --git a/zh_CN/.gitbook/assets/api_based_02.png b/zh_CN/.gitbook/assets/api_based_02.png new file mode 100644 index 0000000..b483fdb Binary files /dev/null and b/zh_CN/.gitbook/assets/api_based_02.png differ diff --git a/zh_CN/SUMMARY.md b/zh_CN/SUMMARY.md index 6c0824b..66d62f0 100644 --- a/zh_CN/SUMMARY.md +++ b/zh_CN/SUMMARY.md @@ -52,6 +52,9 @@ * [接入 OpenLLM 部署的本地模型](advanced/model-configuration/openllm.md) * [接入 LocalAI 部署的本地模型](advanced/model-configuration/localai.md) * [更多集成](advanced/more-integration.md) +* [API-based 扩展](advanced/api\_based\_extension/README.md) + * [外部数据工具](advanced/api\_based\_extension/wai-bu-shu-ju-gong-ju.md) + * [敏感内容审查](advanced/api\_based\_extension/min-gan-nei-rong-shen-cha.md) ## 使用案例 diff --git a/zh_CN/advanced/api_based_extension/README.md b/zh_CN/advanced/api_based_extension/README.md new file mode 100644 index 0000000..45e0278 --- /dev/null +++ b/zh_CN/advanced/api_based_extension/README.md @@ -0,0 +1,226 @@ +# API-based 扩展 + +开发者可通过 API 扩展模块能力,当前支持以下模块扩展: + +* `moderation` 敏感内容审计 +* `external_data_tool` 外部数据工具 + +在扩展模块能力之前,您需要准备一个 API 和用于鉴权的 API Key(也可由 Dify 自动生成,可选)。 + +除了需要开发对应的模块能力,还需要遵照以下规范,以便 Dify 正确调用 API。 + +

基于 API 扩展

+ +### [API 规范](https://github.com/langgenius/dify-docs/diffs/2?branch=main\&name=main\&qualified\_name=refs%2Fheads%2Fmain\&sha1=fb07d2bea301bd6388c393d5f3d8a80386c4dfdb\&sha2=a72d056812efe42f153d649085811e5b49ee131e\&short\_path=e2d7adb\&unchanged=expanded\&w=false#api-%E8%A7%84%E8%8C%83) + +Dify 将会以以下规范调用您的接口: + +``` +POST {Your-API-Endpoint} +``` + +#### [Header](https://github.com/langgenius/dify-docs/diffs/2?branch=main\&name=main\&qualified\_name=refs%2Fheads%2Fmain\&sha1=fb07d2bea301bd6388c393d5f3d8a80386c4dfdb\&sha2=a72d056812efe42f153d649085811e5b49ee131e\&short\_path=e2d7adb\&unchanged=expanded\&w=false#header) + +| Header | Value | Desc | +| --------------- | ----------------- | --------------------------------------------------------------------- | +| `Content-Type` | application/json | 请求内容为 JSON 格式。 | +| `Authorization` | Bearer {api\_key} | API Key 以 Token 令牌的方式传输,您需要解析该 `api_key` 并确认是否和提供的 API Key 一致,保证接口安全。 | + +#### [Request Body](https://github.com/langgenius/dify-docs/diffs/2?branch=main\&name=main\&qualified\_name=refs%2Fheads%2Fmain\&sha1=fb07d2bea301bd6388c393d5f3d8a80386c4dfdb\&sha2=a72d056812efe42f153d649085811e5b49ee131e\&short\_path=e2d7adb\&unchanged=expanded\&w=false#request-body) + +``` +{ + "point": string, // 扩展点,不同模块可能包含多个扩展点 + "params": { + ... // 各模块扩展点传入参数 + } +} +``` + +#### [API 返回](https://github.com/langgenius/dify-docs/diffs/2?branch=main\&name=main\&qualified\_name=refs%2Fheads%2Fmain\&sha1=fb07d2bea301bd6388c393d5f3d8a80386c4dfdb\&sha2=a72d056812efe42f153d649085811e5b49ee131e\&short\_path=e2d7adb\&unchanged=expanded\&w=false#api-%E8%BF%94%E5%9B%9E) + +``` +{ + ... // API 返回的内容,不同扩展点返回见不同模块的规范设计 +} +``` + +### [校验](https://github.com/langgenius/dify-docs/diffs/2?branch=main\&name=main\&qualified\_name=refs%2Fheads%2Fmain\&sha1=fb07d2bea301bd6388c393d5f3d8a80386c4dfdb\&sha2=a72d056812efe42f153d649085811e5b49ee131e\&short\_path=e2d7adb\&unchanged=expanded\&w=false#%E6%A0%A1%E9%AA%8C) + +在 Dify 配置 API-based Extension 时,Dify 将会发送一个请求至 API Endpoint,以检验 API 的可用性。 + +当 API Endpoint 接收到 `point=ping` 时,接口应返回 `result=pong`,具体如下: + +#### [Header](https://github.com/langgenius/dify-docs/diffs/2?branch=main\&name=main\&qualified\_name=refs%2Fheads%2Fmain\&sha1=fb07d2bea301bd6388c393d5f3d8a80386c4dfdb\&sha2=a72d056812efe42f153d649085811e5b49ee131e\&short\_path=e2d7adb\&unchanged=expanded\&w=false#header-1) + +``` +Content-Type: application/json +Authorization: Bearer {api_key} +``` + +#### [Request Body](https://github.com/langgenius/dify-docs/diffs/2?branch=main\&name=main\&qualified\_name=refs%2Fheads%2Fmain\&sha1=fb07d2bea301bd6388c393d5f3d8a80386c4dfdb\&sha2=a72d056812efe42f153d649085811e5b49ee131e\&short\_path=e2d7adb\&unchanged=expanded\&w=false#request-body-1) + +``` +{ + "point": "ping" +} +``` + +#### [API 期望返回](https://github.com/langgenius/dify-docs/diffs/2?branch=main\&name=main\&qualified\_name=refs%2Fheads%2Fmain\&sha1=fb07d2bea301bd6388c393d5f3d8a80386c4dfdb\&sha2=a72d056812efe42f153d649085811e5b49ee131e\&short\_path=e2d7adb\&unchanged=expanded\&w=false#api-%E6%9C%9F%E6%9C%9B%E8%BF%94%E5%9B%9E) + +``` +{ + "result": "pong" +} +``` + +### [范例](https://github.com/langgenius/dify-docs/diffs/2?branch=main\&name=main\&qualified\_name=refs%2Fheads%2Fmain\&sha1=fb07d2bea301bd6388c393d5f3d8a80386c4dfdb\&sha2=a72d056812efe42f153d649085811e5b49ee131e\&short\_path=e2d7adb\&unchanged=expanded\&w=false#%E8%8C%83%E4%BE%8B) + +此处以外部数据工具为例,场景为根据地区获取外部天气信息作为上下文。 + +#### [API 范例](https://github.com/langgenius/dify-docs/diffs/2?branch=main\&name=main\&qualified\_name=refs%2Fheads%2Fmain\&sha1=fb07d2bea301bd6388c393d5f3d8a80386c4dfdb\&sha2=a72d056812efe42f153d649085811e5b49ee131e\&short\_path=e2d7adb\&unchanged=expanded\&w=false#api-%E8%8C%83%E4%BE%8B) + +``` +POST https://fake-domain.com/api/dify/receive +``` + +[**Header**](https://github.com/langgenius/dify-docs/diffs/2?branch=main\&name=main\&qualified\_name=refs%2Fheads%2Fmain\&sha1=fb07d2bea301bd6388c393d5f3d8a80386c4dfdb\&sha2=a72d056812efe42f153d649085811e5b49ee131e\&short\_path=e2d7adb\&unchanged=expanded\&w=false#header-2) + +``` +Content-Type: application/json +Authorization: Bearer 123456 +``` + +[**Request Body**](https://github.com/langgenius/dify-docs/diffs/2?branch=main\&name=main\&qualified\_name=refs%2Fheads%2Fmain\&sha1=fb07d2bea301bd6388c393d5f3d8a80386c4dfdb\&sha2=a72d056812efe42f153d649085811e5b49ee131e\&short\_path=e2d7adb\&unchanged=expanded\&w=false#request-body-2) + +``` +{ + "point": "app.external_data_tool.query", + "params": { + "app_id": "61248ab4-1125-45be-ae32-0ce91334d021", + "tool_variable": "weather_retrieve", + "inputs": { + "location": "London" + }, + "query": "How's the weather today?" + } +} +``` + +[**API 返回**](https://github.com/langgenius/dify-docs/diffs/2?branch=main\&name=main\&qualified\_name=refs%2Fheads%2Fmain\&sha1=fb07d2bea301bd6388c393d5f3d8a80386c4dfdb\&sha2=a72d056812efe42f153d649085811e5b49ee131e\&short\_path=e2d7adb\&unchanged=expanded\&w=false#api-%E8%BF%94%E5%9B%9E-1) + +``` +{ + "result": "City: London\nTemperature: 10°C\nRealFeel®: 8°C\nAir Quality: Poor\nWind Direction: ENE\nWind Speed: 8 km/h\nWind Gusts: 14 km/h\nPrecipitation: Light rain" +} +``` + +#### [代码范例](https://github.com/langgenius/dify-docs/diffs/2?branch=main\&name=main\&qualified\_name=refs%2Fheads%2Fmain\&sha1=fb07d2bea301bd6388c393d5f3d8a80386c4dfdb\&sha2=a72d056812efe42f153d649085811e5b49ee131e\&short\_path=e2d7adb\&unchanged=expanded\&w=false#%E4%BB%A3%E7%A0%81%E8%8C%83%E4%BE%8B) + +代码基于 Python FastAPI 框架。 + +1. 安装依赖 + + ``` + pip install fastapi[all] uvicorn + ``` +2. 按照接口规范编写代码 + + ``` + from fastapi import FastAPI, Body, HTTPException, Header + from pydantic import BaseModel + + app = FastAPI() + + + class InputData(BaseModel): + point: str + params: dict + + + @app.post("/api/dify/receive") + async def dify_receive(data: InputData = Body(...), authorization: str = Header(None)): + """ + Receive API query data from Dify. + """ + expected_api_key = "123456" # TODO Your API key of this API + auth_scheme, _, api_key = authorization.partition(' ') + + if auth_scheme.lower() != "bearer" or api_key != expected_api_key: + raise HTTPException(status_code=401, detail="Unauthorized") + + point = data.point + + # for debug + print(f"point: {point}") + + if point == "ping": + return { + "result": "pong" + } + if point == "app.external_data_tool.query": + return handle_app_external_data_tool_query(params=data.params) + # elif point == "{point name}": + # TODO other point implementation here + + raise HTTPException(status_code=400, detail="Not implemented") + + + def handle_app_external_data_tool_query(params: dict): + app_id = params.get("app_id") + tool_variable = params.get("tool_variable") + inputs = params.get("inputs") + query = params.get("query") + + # for debug + print(f"app_id: {app_id}") + print(f"tool_variable: {tool_variable}") + print(f"inputs: {inputs}") + print(f"query: {query}") + + # TODO your external data tool query implementation here, + # return must be a dict with key "result", and the value is the query result + if inputs.get("location") == "London": + return { + "result": "City: London\nTemperature: 10°C\nRealFeel®: 8°C\nAir Quality: Poor\nWind Direction: ENE\nWind " + "Speed: 8 km/h\nWind Gusts: 14 km/h\nPrecipitation: Light rain" + } + else: + return {"result": "Unknown city"} + ``` +3. 启动 API 服务,默认端口为 8000,API 完整地址为:`http://127.0.0.1:8000/api/dify/receive`,配置的 API Key 为 `123456`。 + + ``` + uvicorn main:app --reload + ``` +4. 在 Dify 配置该 API。 + +[![](https://github.com/langgenius/dify-docs/raw/main/zh\_CN/.gitbook/assets/api\_based\_01.png)](../../.gitbook/assets/api\_based\_01.png) + +5. 在 App 中选择该 API 扩展。 + +[![](https://github.com/langgenius/dify-docs/raw/main/zh\_CN/.gitbook/assets/api\_based\_02.png)](../../.gitbook/assets/api\_based\_02.png) + +App 调试时,Dify 将请求配置的 API,并发送以下内容(范例): + +``` +{ + "point": "app.external_data_tool.query", + "params": { + "app_id": "61248ab4-1125-45be-ae32-0ce91334d021", + "tool_variable": "weather_retrieve", + "inputs": { + "location": "London" + }, + "query": "How's the weather today?" + } +} +``` + +API 返回为: + +``` +{ + "result": "City: London\nTemperature: 10°C\nRealFeel®: 8°C\nAir Quality: Poor\nWind Direction: ENE\nWind Speed: 8 km/h\nWind Gusts: 14 km/h\nPrecipitation: Light rain" +} +``` diff --git a/zh_CN/advanced/api_based_extension/min-gan-nei-rong-shen-cha.md b/zh_CN/advanced/api_based_extension/min-gan-nei-rong-shen-cha.md new file mode 100644 index 0000000..80976cc --- /dev/null +++ b/zh_CN/advanced/api_based_extension/min-gan-nei-rong-shen-cha.md @@ -0,0 +1,137 @@ +# 敏感内容审查 + +该模块用于审查应用中终端用户输入的内容和 LLM 输出的内容,分为两个扩展点类型。 + +### 扩展点 + +* `app.moderation.input` 终端用户输入的内容审查扩展点 + * 用于审查终端用户传入的变量内容以及对话型应用中对话的输入内容。 +* `app.moderation.output`LLM 输出的内容审查扩展点 + * 用于审查 LLM 输出的内容, + * 当 LLM 输出为流式时,输出的内容将分 100 字为一个分段进行请求 API,尽可能避免输出内容较长时,审查不及时的问题。 + +### app.moderation.input 扩展点 + +#### Request Body + +``` +{ + "point": "app.moderation.input", // 扩展点类型,此处固定为 app.moderation.input + "params": { + "app_id": string, // 应用 ID + "inputs": { // 终端用户传入变量值,key 为变量名,value 为变量值 + "var_1": "value_1", + "var_2": "value_2", + ... + }, + "query": string | null // 终端用户当前对话输入内容,对话型应用固定参数。 + } +} +``` + +* Example + * ``` + { + "point": "app.moderation.input", + "params": { + "app_id": "61248ab4-1125-45be-ae32-0ce91334d021", + "inputs": { + "var_1": "I will kill you.", + "var_2": "I will fuck you." + }, + "query": "Happy everydays." + } + } + ``` + +#### API 返回 + +``` +{ + "flagged": bool, // 是否违反校验规则 + "action": string, // 动作,direct_output 直接输出预设回答; overrided 覆写传入变量值 + "preset_response": string, // 预设回答(仅当 action=direct_output 返回) + "inputs": { // 终端用户传入变量值,key 为变量名,value 为变量值(仅当 action=overrided 返回) + "var_1": "value_1", + "var_2": "value_2", + ... + }, + "query": string | null // 覆写的终端用户当前对话输入内容,对话型应用固定参数。(仅当 action=overrided 返回) +} +``` + +* Example + * `action=``direct_output` + * ``` + { + "flagged": true, + "action": "direct_output", + "preset_response": "Your content violates our usage policy." + } + ``` + * `action=overrided` + * ``` + { + "flagged": true, + "action": "overrided", + "inputs": { + "var_1": "I will *** you.", + "var_2": "I will *** you." + }, + "query": "Happy everydays." + } + ``` + +### app.moderation.output 扩展点 + +#### Request Body + +``` +{ + "point": "app.moderation.output", // 扩展点类型,此处固定为 app.moderation.output + "params": { + "app_id": string, // 应用 ID + "text": string // LLM 回答内容。当 LLM 输出为流式时,此处为 100 字为一个分段的内容。 + } +} +``` + +* Example + * ``` + { + "point": "app.moderation.output", + "params": { + "app_id": "61248ab4-1125-45be-ae32-0ce91334d021", + "text": "I will kill you." + } + } + ``` + +#### API 返回 + +``` +{ + "flagged": bool, // 是否违反校验规则 + "action": string, // 动作,direct_output 直接输出预设回答; overrided 覆写传入变量值 + "preset_response": string, // 预设回答(仅当 action=direct_output 返回) + "text": string // 覆写的 LLM 回答内容。(仅当 action=overrided 返回) +} +``` + +* Example + * `action=direct_output` + * ``` + { + "flagged": true, + "action": "direct_output", + "preset_response": "Your content violates our usage policy." + } + ``` + * `action=overrided` + * ``` + { + "flagged": true, + "action": "overrided", + "text": "I will *** you." + } + ``` diff --git a/zh_CN/advanced/api_based_extension/wai-bu-shu-ju-gong-ju.md b/zh_CN/advanced/api_based_extension/wai-bu-shu-ju-gong-ju.md new file mode 100644 index 0000000..4613342 --- /dev/null +++ b/zh_CN/advanced/api_based_extension/wai-bu-shu-ju-gong-ju.md @@ -0,0 +1,89 @@ +# 外部数据工具 + +## 功能介绍 + +此前,为了应对大多数语言模型使用过时训练数据,且对文本长度有限制,无法利用用户最新的私有上下文进行对话等问题,Dify 通过数据集功能实现了简易的数据集管理和集成,参见 👉 [datasets](../datasets/ "mention")。开发者可以直接上传各类格式的长文本、结构化数据来构建数据集,同时支持从外部数据源同步数据至数据集,比如 [sync-from-notion.md](../datasets/sync-from-notion.md "mention")。Dify 会自动将数据集内容集成到 AI 应用中,使其基于用户的私有、最新上下文进行对话。这种数据集管理集成方式,解决了语言模型使用限制的同时,也降低了开发者获取高质量对话上下文的门槛。 + +然而企业在开发 AI 应用如企业知识库 ChatBot 的时候,会面临以下 4 个方面的难题: + +1. 数据安全 + +很多企业拥有自己的知识库或私有数据集,通常以数据库方式存储,其中可能包含隐私或敏感信息,不能直接上传到第三方平台。 + +2. 自定义能力 + +虽然此前 Dify 提供了统一管理数据集的平台以便于维护,但是企业可能根据自己的业务需要寻求更加定制化的需求。 + +3. 实时调用 + +上传离线数据,无法做到实时同步企业日益更新的知识库,频繁的手动上传无法跟上大批量内容更迭的脚步,在维护方面需要更宽泛的灵活性。 + +4. 保护核心竞争力 + +业务能力往往是企业的核心竞争力,无论是独特的产品或服务,还是创新的商业模式,都是企业珍贵的资产,企业往往不想直接暴露给第三方。 + + + +所以,我们开发了外部数据工具(External\_Data\_Tool),借助该功能,你可以通过企业自己的 API 来扩展 Dify 的查询模块能力,而无需将数据集上传到 Dify,同时解决了以上的 4 个难题。 + +## 具体实现 + +当终端用户向对话系统提出请求时,平台后端会触发外部数据工具(即调用自己的 API),它会查询用户问题相关的外部信息,如员工资料、实时记录等,并返回与当前请求相关的部分。平台后端会将返回的结果组装成文本作为上下文注入到 Prompt 中,以输出更加个性化和符合用户需求的回复内容。这样的设计避免了语言模型只依赖单次请求中的有限信息进行推理,让其可以基于更丰富的用户背景积累进行对话,从而产生更智能、贴近人的交互体验。 + +### 扩展点 + +`app.external_data_tool.query` 应用外部数据工具查询扩展点。 + +该扩展点将终端用户传入的应用变量内容和对话输入内容(对话型应用固定参数)作为参数,传给 API。 + +开发者需要实现对应工具的查询逻辑,并返回字符串类型的查询结果。 + +#### Request Body + +``` +{ + "point": "app.external_data_tool.query", // 扩展点类型,此处固定为 app.external_data_tool.query + "params": { + "app_id": string, // 应用 ID + "tool_variable": string, // 外部数据工具变量名称,表示对应变量工具调用来源 + "inputs": { // 终端用户传入变量值,key 为变量名,value 为变量值 + "var_1": "value_1", + "var_2": "value_2", + ... + }, + "query": string | null // 终端用户当前对话输入内容,对话型应用固定参数。 + } +} +``` + +* Example + * ``` + { + "point": "app.external_data_tool.query", + "params": { + "app_id": "61248ab4-1125-45be-ae32-0ce91334d021", + "tool_variable": "weather_retrieve", + "inputs": { + "location": "London" + }, + "query": "How's the weather today?" + } + } + ``` + +#### API 返回 + +``` +{ + "result": string +} +``` + +* Example + * ``` + { + "result": "City: London\nTemperature: 10°C\nRealFeel®: 8°C\nAir Quality: Poor\nWind Direction: ENE\nWind Speed: 8 km/h\nWind Gusts: 14 km/h\nPrecipitation: Light rain" + } + ``` + +\