はじめに
Difyがすごい勢いで流行っているのでLINEボットサーバーと連携をやってみることにしました。
本記事ではDifyのクラウド版で試してみます。Difyの出自はTencent系なのでクラウドはやばい?という話もあるようですが、このあたりは各自で判断してください。
やってみる
今回はカンタンのためにサラのテキストジェネレーターアプリを作成します。Difyの基本的な使い方に関しては他のWebサイトにたくさん情報が載っているのでそちらを参考にしてください。現時点では頻繁にUIがアップデートされていっている感があります。
適当なアプリをつくる
ダッシュボードから最初から作成
をクリックします
テキストジェネレーター
を選択してアプリの名前を入力し作成する
をクリックします
アプリが作成されました。デバッグとプレビュー
欄で何かプロンプトを入力すると回答が返ってきます。
APIを叩いてみる
サイドメニューの概要
をクリックしてバックエンドサービスAPI
欄に移動しAPIキー
をクリックします
新しいシークレットキーを作成
をクリックします
生成されたAPIシークレットキーをコピーしてメモ帳などに控えます
サイドメニューのAPIアクセス
をクリックするとAPIリファレンスが参照できます
APIリファレンスを参考にcurlでAPIを叩いてみます。ENTER-YOUR-SECRET-KEY
は先程控えたAPIシークレットキーに差し替えてください
curl -X POST 'https://api.dify.ai/v1/completion-messages' \
--header 'Authorization: Bearer ENTER-YOUR-SECRET-KEY' \
--header 'Content-Type: application/json' \
--data-raw '{
"inputs": {"query": "Hello world!"},
"response_mode": "blocking",
"user": "abc-123"
}'|jq .
回答が返ってきました。つまりinputs.query
にLINEメッセージを入力してリクエストしてレスポンスのanswer
をリプライすれば良さげです
{
"event": "message",
"task_id": "b7bf90b5-5fd5-4519-9edf-ef55b724183b",
"id": "f0521730-cf3f-408e-ba9c-9441006d30ec",
"message_id": "f0521730-cf3f-408e-ba9c-9441006d30ec",
"mode": "completion",
"answer": "Hello! How can I assist you today?",
"metadata": {
"usage": {
"prompt_tokens": 10,
"prompt_unit_price": "0.001",
"prompt_price_unit": "0.001",
"prompt_price": "0.0000100",
"completion_tokens": 9,
"completion_unit_price": "0.002",
"completion_price_unit": "0.001",
"completion_price": "0.0000180",
"total_tokens": 19,
"total_price": "0.0000280",
"currency": "USD",
"latency": 0.3724584267474711
}
},
"created_at": 1715491205
}
LINE Botサーバーをカスタマイズする
Botサーバーは[Deno] FreshでLINE Messaging API SDKを使ってみるで作ったものをカスタムするかたちでやってみます。次のAPIトークンの値は適宜差し替えてください。
-
YOUR_CHANNEL_ACCESS_TOKEN
: LINEチャンネルアクセストークン -
YOUR_CHANNEL_SECRET
: LINEチャンネルシークレット -
ENTER-YOUR-SECRET-KEY
: Dify APIシークレットキー
下記のようにroutes/api/messaging.ts
を更新します。
import type { Handlers, FreshContext } from "$fresh/server.ts";
import { messagingApi, MessageEvent } from "npm:@line/bot-sdk@9.2.2";
import type { ClientConfig, TextEventMessage } from "npm:@line/bot-sdk@9.2.2";
declare interface DifyCompletionMessageResponse {
event: string;
task_id: string;
id: string;
message_id: string;
mode: string;
answer: string;
metadata: {
usage: {
prompt_tokens: number;
prompt_unit_price: string;
prompt_price_unit: string;
prompt_price: string;
completion_tokens: number;
completion_unit_price: string;
completion_price_unit: string;
completion_price: string;
total_tokens: number;
total_price: string;
currency: string;
latency: number;
}
},
created_at: number;
}
const config: ClientConfig = {
channelAccessToken: "YOUR_CHANNEL_ACCESS_TOKEN",
channelSecret: "YOUR_CHANNEL_SECRET",
};
const client = new messagingApi.MessagingApiClient(config);
export const handler: Handlers = {
async POST(_req: Request, _ctx: FreshContext): Promise<Response> {
const body = await _req.json();
const event: MessageEvent = body.events[0];
const textMessage = event.message as TextEventMessage;
console.log(textMessage.text);
// request to Dify API
const requestData = {
inputs: {
query: textMessage.text,
},
response_mode: "blocking",
user: "line-bot",
};
const resp = await fetch("https://api.dify.ai/v1/completion-messages", {
method: "POST",
headers: {
"Authorization": "Bearer ENTER-YOUR-SECRET-KEY",
"Content-Type": "application/json",
},
body: JSON.stringify(requestData),
});
const res = await resp.json() as DifyCompletionMessageResponse;
await client.replyMessage({
replyToken: event.replyToken,
messages: [
{
type: "text",
text: res.answer,
},
],
});
return new Response(null, { status: 204 });
}
};
使ってみる
実行します
deno task start
Task start deno run -A --watch=static/,routes/ dev.ts
Watcher Process started.
The manifest has been generated for 6 routes and 1 islands.
🍋 Fresh ready
Local: http://localhost:8000/
正常に実行できました。
カレーライスについては長文でけっこういい回答が返ってきました。最近GPT3.5は使ってなかったんですが、かなり性能が上がっていますね。
おわりに
DifyとLINEボットの連携を簡単にやってみました。今回のようにDifyのテキストジェネレーターの場合はAPIが簡単に使えますが、エージェントの場合はresponse_mode:"blocking"
が使えずstreaming
のみのようなので使う場合は工夫が必要そうです。
他にもpre promptやナレッジデータの利用などもまだわかってないのでDify APIをもうちょっと調べて次回以降アップデートしてみようと思います。