docs/api-based-extension (#419)

* Update cloudflare-workers.md

* Update moderation.md
This commit is contained in:
zm1990s
2025-04-15 17:18:36 +08:00
committed by GitHub
parent 3035d76e44
commit cf35b112cc
2 changed files with 143 additions and 4 deletions
@@ -38,15 +38,43 @@ const result = await fetch(url).then(res => res.text())
这个仓库简化了除了业务逻辑之外所有的配置,你可以直接使用 `npm` 命令来部署你的 API 扩展。
```bash
npm install
npm run deploy
```
部署成功之后,你会得到一个公网地址,你可以在 Dify 中添加这个地址作为 API Endpoint。请注意不要遗漏 `endpoint` 这个路径。
部署成功之后,你会得到一个公网地址,你可以在 Dify 中添加这个地址作为 API Endpoint。请注意不要遗漏 `endpoint` 这个路径,此路径的具体定义在 `src/index.ts` 中可以查看
<figure><img src="../../../.gitbook/assets/api_extension_edit.png" alt=""><figcaption><p>在 Dify 中添加 API Endpoint</p></figcaption></figure>
<figure><img src="../../../.gitbook/assets/app_tools_edit.png" alt=""><figcaption><p>在 App 编辑页面中添加上 API Tool</p></figcaption></figure>
另外,也可以直接使用 `npm run dev` 命令来部署到本地进行测试。
```bash
npm install
npm run dev
```
相关输出:
```bash
$ npm run dev
> dev
> wrangler dev src/index.ts
⛅️ wrangler 3.99.0
-------------------
Your worker has access to the following bindings:
- Vars:
- TOKEN: "ban****ool"
⎔ Starting local server...
[wrangler:inf] Ready on http://localhost:58445
```
之后就可以使用 Postman 等工具进行本地接口调试。
## 其他逻辑 TL;DR
### 关于 Bearer Auth
@@ -12,6 +12,8 @@
### app.moderation.input 扩展点 <a href="#usercontentappmoderationinput-kuo-zhan-dian" id="usercontentappmoderationinput-kuo-zhan-dian"></a>
当在 Chatflow、Agent、聊天助手等应用下开启**内容审查>审查输入内容**时,Dify 会给相应的 API 扩展发送下列 HTTP POST 请求:
#### Request Body <a href="#user-content-request-body" id="user-content-request-body"></a>
```
@@ -44,7 +46,7 @@
}
```
#### API 返回 <a href="#usercontentapi-fan-hui" id="usercontentapi-fan-hui"></a>
#### API 返回规范 <a href="#usercontentapi-fan-hui" id="usercontentapi-fan-hui"></a>
```
{
@@ -61,7 +63,7 @@
```
* Example
* `action=``direct_output`
* `action=direct_output`
* ```
{
"flagged": true,
@@ -84,6 +86,8 @@
### app.moderation.output 扩展点 <a href="#usercontentappmoderationoutput-kuo-zhan-dian" id="usercontentappmoderationoutput-kuo-zhan-dian"></a>
当在 Chatflow、Agent、聊天助手等应用下开启**内容审查>审查输出内容**时,Dify 会给相应的 API 扩展发送下列 HTTP POST 请求:
#### Request Body <a href="#user-content-request-body-1" id="user-content-request-body-1"></a>
```
@@ -107,7 +111,7 @@
}
```
#### API 返回 <a href="#usercontentapi-fan-hui-1" id="usercontentapi-fan-hui-1"></a>
#### API 返回规范 <a href="#usercontentapi-fan-hui-1" id="usercontentapi-fan-hui-1"></a>
```
{
@@ -135,3 +139,110 @@
"text": "I will *** you."
}
```
## 代码示例
下面展示一段可部署在 Cloudflare 的 `src/index.ts` 代码。(Cloudflare 完整的使用方法参见[此文档](https://docs.dify.ai/zh-hans/guides/extension/api-based-extension/cloudflare-workers)
代码工作原理是进行关键词匹配,实现对 Input (用户输入的内容)以及输出(大模型返回的内容)进行过滤。用户可以按照需求自行修改匹配逻辑。
```
import { Hono } from "hono";
import { bearerAuth } from "hono/bearer-auth";
import { z } from "zod";
import { zValidator } from "@hono/zod-validator";
import { generateSchema } from '@anatine/zod-openapi';
type Bindings = {
TOKEN: string;
};
const app = new Hono<{ Bindings: Bindings }>();
// API 格式校验 ⬇️
const schema = z.object({
point: z.union([
z.literal("ping"),
z.literal("app.external_data_tool.query"),
z.literal("app.moderation.input"),
z.literal("app.moderation.output"),
]), // Restricts 'point' to two specific values
params: z
.object({
app_id: z.string().optional(),
tool_variable: z.string().optional(),
inputs: z.record(z.any()).optional(),
query: z.any(),
text: z.any()
})
.optional(),
});
// Generate OpenAPI schema
app.get("/", (c) => {
return c.json(generateSchema(schema));
});
app.post(
"/",
(c, next) => {
const auth = bearerAuth({ token: c.env.TOKEN });
return auth(c, next);
},
zValidator("json", schema),
async (c) => {
const { point, params } = c.req.valid("json");
if (point === "ping") {
return c.json({
result: "pong",
});
}
// ⬇️ impliment your logic here ⬇️
// point === "app.external_data_tool.query"
else if (point === "app.moderation.input"){
// 输入检查 ⬇️
const inputkeywords = ["输入过滤测试1", "输入过滤测试2", "输入过滤测试3"];
if (inputkeywords.some(keyword => params.query.includes(keyword)))
{
return c.json({
"flagged": true,
"action": "direct_output",
"preset_response": "输入存在违法内容,请换个问题再试!"
});
} else {
return c.json({
"flagged": false,
"action": "direct_output",
"preset_response": "输入无异常"
});
}
// 输入检查完毕
}
else {
// 输出检查 ⬇️
const outputkeywords = ["输出过滤测试1", "输出过滤测试2", "输出过滤测试3"];
if (outputkeywords.some(keyword => params.text.includes(keyword)))
{
return c.json({
"flagged": true,
"action": "direct_output",
"preset_response": "输出存在敏感内容,已被系统过滤,请换个问题再问!"
});
}
else {
return c.json({
"flagged": false,
"action": "direct_output",
"preset_response": "输出无异常"
});
};
}
// 输出检查完毕
}
);
export default app;
```