Docs: update cloudflare extension (#728)

This commit is contained in:
AllenWriter
2025-04-15 17:40:42 +08:00
committed by GitHub
parent 33a565b72d
commit 3f9da78bfc
4 changed files with 297 additions and 19 deletions
@@ -38,15 +38,42 @@ const result = await fetch(url).then(res => res.text())
This repository simplifies all configurations except for business logic. You can directly use `npm` commands to deploy your API extension.
```bash
npm install
npm run deploy
```
After successful deployment, you will get a public internet address, which you can add in Dify as an API Endpoint. Please note not to miss the `endpoint` path.
After successful deployment, you will get a public internet address, which you can add in Dify as an API Endpoint. Please note not to miss the `endpoint` path, which is specifically defined in `src/index.ts`.
<figure><img src="../../../.gitbook/assets/api_extension_edit (1).png" alt=""><figcaption><p>Adding API Endpoint in Dify</p></figcaption></figure>
<figure><img src="../../../.gitbook/assets/app_tools_edit (1).png" alt=""><figcaption><p>Adding API Tool in the App edit page</p></figcaption></figure>
Additionally, you can use the `npm run dev` command to deploy locally for testing.
```bash
npm install
npm run dev
```
Related output:
```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
```
After this, you can use tools like Postman to debug the local interface.
## Other Logic TL;DR
### About Bearer Auth
@@ -96,4 +123,4 @@ wrangler tail
* [Cloudflare Workers](https://workers.cloudflare.com/)
* [Cloudflare Workers CLI](https://developers.cloudflare.com/workers/cli-wrangler/install-update)
* [Example GitHub Repository](https://github.com/crazywoola/dify-extension-workers)
* [Example GitHub Repository](https://github.com/crazywoola/dify-extension-workers)
@@ -12,6 +12,8 @@ This module is used to review the content input by end-users and the output cont
### app.moderation.input Extension Point
When **Content Moderation > Review Input Content** is enabled in applications like Chatflow, Agent, or Chat Assistant, Dify will send the following HTTP POST request to the corresponding API extension:
#### Request Body
```
@@ -44,7 +46,7 @@ This module is used to review the content input by end-users and the output cont
}
```
#### API Response
#### API Response Specifications
```
{
@@ -84,6 +86,8 @@ This module is used to review the content input by end-users and the output cont
### app.moderation.output Extension Point
When **Content Moderation > Review Output Content** is enabled in applications like Chatflow, Agent, or Chat Assistant, Dify will send the following HTTP POST request to the corresponding API extension:
#### Request Body
```
@@ -107,7 +111,7 @@ This module is used to review the content input by end-users and the output cont
}
```
#### API Response
#### API Response Specifications
```
{
@@ -134,4 +138,112 @@ This module is used to review the content input by end-users and the output cont
"action": "overridden",
"text": "I will *** you."
}
```
```
## Code Example
Below is an example `src/index.ts` code that can be deployed on Cloudflare. (For the complete usage method of Cloudflare, please refer to [this document](https://docs.dify.ai/guides/extension/api-based-extension/cloudflare-workers))
The code works by performing keyword matching to filter Input (user-entered content) and output (content returned by the large model). Users can modify the matching logic according to their needs.
```
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 format validation ⬇️
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 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",
});
}
// ⬇️ implement your logic here ⬇️
// point === "app.external_data_tool.query"
else if (point === "app.moderation.input"){
// Input check ⬇️
const inputkeywords = ["input filter test1", "input filter test2", "input filter test3"];
if (inputkeywords.some(keyword => params.query.includes(keyword)))
{
return c.json({
"flagged": true,
"action": "direct_output",
"preset_response": "Input contains prohibited content, please try a different question!"
});
} else {
return c.json({
"flagged": false,
"action": "direct_output",
"preset_response": "Input is normal"
});
}
// Input check completed
}
else {
// Output check ⬇️
const outputkeywords = ["output filter test1", "output filter test2", "output filter test3"];
if (outputkeywords.some(keyword => params.text.includes(keyword)))
{
return c.json({
"flagged": true,
"action": "direct_output",
"preset_response": "Output contains sensitive content and has been filtered by the system. Please ask a different question!"
});
}
else {
return c.json({
"flagged": false,
"action": "direct_output",
"preset_response": "Output is normal"
});
};
}
// Output check completed
}
);
export default app;
```
@@ -1,19 +1,19 @@
# Cloudflare ワーカーを使用して API ツールをデプロイ
## 入門
## 始めに
Dify API Extension は、アクセス可能な公開アドレスを API エンドポイントとして使用する必要があるため、API 拡張を公開アドレスにデプロイする必要があります。ここでは、Cloudflare ワーカーを使用して API 拡張をデプロイします。
まず、[Example GitHub ポジトリ](https://github.com/crazywoola/dify-extension-workers) をクローンします。このポジトリには、簡単な API 拡張が含まれており、これを基にして修正を行うことができます。
まず、[サンプル GitHub ポジトリ](https://github.com/crazywoola/dify-extension-workers) をクローンします。このポジトリには、簡単な API 拡張が含まれており、これを基にして修正を行うことができます。
```bash
git clone https://github.com/crazywoola/dify-extension-workers.git
cp wrangler.toml.example wrangler.toml
```
次に、`wrangler.toml` ファイルを開き、`名前``互換性の日付` をあなたのアプリ名と互換日付に変更します。
次に、`wrangler.toml` ファイルを開き、`name``compatibility_date` をあなたのアプリ名と互換日付に変更します。
ここで注意が必要な設定は、`vars` 内の `トークン` です。Dify に API 拡張を追加する際に、このトークンを入力する必要があります。セキュリティ上の観点から、ランダムな文字列をトークンとして使用することをお勧めします。トークンをソースコードに直接書き込むのではなく、環境変数を使用してトークンを渡す方法を取るべきです。したがって、wrangler.toml をコードポジトリにコミットしないでください。
ここで注意が必要な設定は、`vars` 内の `TOKEN` です。Dify に API 拡張を追加する際に、このトークンを入力する必要があります。セキュリティ上の観点から、ランダムな文字列をトークンとして使用することをお勧めします。トークンをソースコードに直接書き込むのではなく、環境変数を使用してトークンを渡す方法を取るべきです。したがって、wrangler.toml をコードポジトリにコミットしないでください。
```toml
name = "dify-extension-example"
@@ -26,30 +26,57 @@ TOKEN = "bananaiscool"
この API 拡張は、ランダムなブレイキング・バッドの名言を返します。`src/index.ts` 内でこの API 拡張のロジックを変更することができます。この例は、サードパーティの API とやり取りする方法を示しています。
```typescript
// ⬇️ Implement your logic here ⬇️
// ⬇️ ここにロジックを実装 ⬇️
// point === "app.external_data_tool.query"
// https://api.breakingbadquotes.xyz/v1/quotes
const count = params?.inputs?.count ?? 1;
const url = `https://api.breakingbadquotes.xyz/v1/quotes/${count}`;
const result = await fetch(url).then(res => res.text())
// ⬆️ implement your logic here ⬆️
// ⬆️ ここにロジックを実装 ⬆️
```
このポジトリは、ビジネスロジック以外のすべての設定を簡素化しています。`npm` コマンドを使用して API 拡張をデプロイすることができます。
このポジトリは、ビジネスロジック以外のすべての設定を簡素化しています。`npm` コマンドを使用して API 拡張をデプロイすることができます。
```bash
npm install
npm run deploy
```
デプロイが成功すると、公開アドレスが得られます。このアドレスを Dify に API エンドポイントとして追加できます。`endpoint` パスを忘れないようにしてください。
デプロイが成功すると、公開アドレスが得られます。このアドレスを Dify に API エンドポイントとして追加できます。`endpoint` パスを忘れないようにしてください。この経路の具体的な定義は `src/index.ts` で確認できます。
<figure><img src="../../../.gitbook/assets/api_extension_edit.png" alt=""><figcaption><p>Dify に API エンドポイントを追加する</p></figcaption></figure>
<figure><img src="../../../.gitbook/assets/app_tools_edit.png" alt=""><figcaption><p>アプリ編集ページに API ツールを追加する</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 認証について
```typescript
import { bearerAuth } from "hono/bearer-auth";
@@ -60,7 +87,7 @@ import { bearerAuth } from "hono/bearer-auth";
},
```
上記のコードでは、ベアラー認証ロジックを示しています。`hono/bearer-auth` パッケージを使用してベアラー認証を実装しています。`src/index.ts``c.env.TOKEN` を使用してトークンを取得できます。
上記のコードでは、Bearer 認証ロジックを示しています。`hono/bearer-auth` パッケージを使用して Bearer 認証を実装しています。`src/index.ts``c.env.TOKEN` を使用してトークンを取得できます。
### パラメータの検証について
@@ -97,4 +124,4 @@ wrangler tail
* [Cloudflare Workers](https://workers.cloudflare.com/)
* [Cloudflare Workers CLI](https://developers.cloudflare.com/workers/cli-wrangler/install-update)
* [Example GitHub Repository](https://github.com/crazywoola/dify-extension-workers)
* [サンプル GitHub リポジトリ](https://github.com/crazywoola/dify-extension-workers)
@@ -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リクエストを送信します:
#### リクエストボディ <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>
```
{
@@ -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リクエストを送信します:
#### リクエストボディ <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>
```
{
@@ -134,4 +138,112 @@
"action": "overridden",
"text": "I will *** you."
}
```
```
## コード例
以下は、Cloudflareにデプロイできる`src/index.ts`コードの例です。(Cloudflareの完全な使用方法については、[このドキュメント](https://docs.dify.ai/ja-jp/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"),
]), // 'point'の値を特定の値に制限
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(),
});
// OpenAPIスキーマを生成
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",
});
}
// ⬇️ ここにロジックを実装 ⬇️
// 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;
```