Next.js ServerActionsでDifyのチャットボットAPIを使ってみる
1.Difyのチャットボットを作成
2.npx create-next-appでアプリ作成
3.ルートディレクトリに.env.localファイル作成
DIFY_API_KEY=xxxxxxxxxxxxxxxxx
4.DifyのAPIにfetchするServerActionを作成
app/utils/dify.ts
"use server";
export async function sendDifyRequest(message: string, conversationId?: string): Promise<any> {
try {
const response = await fetch("https://api.dify.ai/v1/chat-messages", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${process.env.DIFY_API_KEY}`,
},
body: JSON.stringify({
inputs: {},
query: message,
response_mode: "blocking",
conversation_id: conversationId || "",
user: "abc-123",
}),
});
if (!response.ok) {
throw new Error("Dify APIからのレスポンスが正常ではありません");
}
const data = await response.json();
console.log(data);
return data;
} catch (error) {
console.error("Dify APIリクエストエラー:", error);
throw new Error("Dify APIリクエスト中にエラーが発生しました");
}
}
注意点:Difyは会話履歴がDifyサーバーに保存される。そのため、APIにはチャット履歴を入力する必要が無い。その代わりにconversation_idを指定する。一番最初はconversation_idは""(空)でリクエストを送り、レスポンスからconversation_idを受け取る。2回目以降のリクエストは1回目で受け取ったconversation_idを送信メッセージと一緒に送ればOK
5.page.tsxにチャット用のUIを作成
app/page.tsx
"use client";
import { useState } from "react";
import { sendDifyRequest } from "./utils/dify";
// メッセージの型を定義
interface Message {
role: "user" | "assistant";
content: string;
}
export default function Home() {
const [message, setMessage] = useState("");
const [history, setHistory] = useState<Message[]>([]);
const [conversationId, setConversationId] = useState<string>("");
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (!message.trim()) return;
// ユーザーのメッセージを履歴に追加
const newHistory = [...history, { role: "user", content: message }];
setHistory(newHistory as Message[]);
setMessage("");
try {
const result = await sendDifyRequest(message, conversationId);
const answer = result.answer as string;
const newConversationId = result.conversation_id as string;
// AIの応答を履歴に追加
setHistory([...newHistory, { role: "assistant", content: answer }] as Message[]);
console.log(newConversationId);
setConversationId(newConversationId);
} catch (error) {
console.error("エラー:", error);
}
};
return (
<div className="p-4">
<h1 className="text-2xl font-bold mb-4">Dify API テスト</h1>
<div className="mb-4 h-64 overflow-y-auto border p-2">
{history.map((msg, index) => (
<div key={index} className={`mb-2 ${msg.role === "user" ? "text-right" : "text-left"}`}>
<span className={`inline-block p-2 rounded ${msg.role === "user" ? "bg-blue-100" : "bg-gray-100"}`}>
{msg.content}
</span>
</div>
))}
</div>
<form onSubmit={handleSubmit} className="mb-4">
<input
type="text"
value={message}
onChange={(e) => setMessage(e.target.value)}
className="border p-2 mr-2"
placeholder="メッセージを入力"
/>
<button type="submit" className="bg-blue-500 text-white p-2 rounded">
送信
</button>
</form>
</div>
);
}
いい感じにできた。しっかり、過去の会話履歴も反映されている。