利用規約にご同意の上ご利用ください。
※候補者の選挙公報を学習したAIがあなた質問にお答えします。
※AIは事実と異なる事を言うこともあります。必ず自身で情報を確かめて下さい。
※ボートマッチの仕組みと使い方はコチラ
※システムのソースコードはコチラ
※選挙公報は鹿児島県選挙管理委員会HPから引用

学習済み候補者一覧

公報No. 候補者名 党派
1 米丸まき子 無所属
2 てのくち里花 無所属
3 しおた康一 無所属

ソースコード

“use client”;
import React from “react”;

function MainComponent() {
const [userInput, setUserInput] = React.useState(“”);
const [chatHistory, setChatHistory] = React.useState([]);
const [isLoading, setIsLoading] = React.useState(false);
const [conversationContext, setConversationContext] = React.useState(“”);

const handleInputChange = (e) => {
setUserInput(e.target.value);
};

const handleSubmit = async (e) => {
e.preventDefault();
if (!userInput.trim()) return;

setIsLoading(true);
const newUserMessage = { role: “user”, content: userInput };
setChatHistory((prev) => […prev, newUserMessage]);

try {
const candidatesResponse = await fetch(“/api/db/2024-88”, {
method: “POST”,
headers: { “Content-Type”: “application/json” },
body: JSON.stringify({
query: “SELECT * FROM `kagoshima_governor_candidates`”,
}),
});
const candidatesData = await candidatesResponse.json();

const systemMessage = {
role: “system”,
content: `鹿児島県知事選挙2024の候補者情報について回答してください。候補者の名前の後には「候補」とつけてください。回答は読みやすいように改行を入れてください。以下は候補者の情報です:\n${JSON.stringify(
candidatesData
)}\n\n前回の質問:${conversationContext}`,
};

const response = await fetch(
“/integrations/anthropic-claude-sonnet-3-5/”,
{
method: “POST”,
headers: { “Content-Type”: “application/json” },
body: JSON.stringify({
messages: [systemMessage, newUserMessage],
}),
}
);

const data = await response.json();
const assistantResponse = data.choices[0].message.content;

setChatHistory((prev) => [
…prev,
{ role: “assistant”, content: assistantResponse },
]);

const now = new Date().toISOString();
await fetch(“/api/db/2024-60”, {
method: “POST”,
headers: { “Content-Type”: “application/json” },
body: JSON.stringify({
query:
“INSERT INTO `conversation_data` (`date_time`, `user_question`, `assistant_response`) VALUES (?, ?, ?)”,
values: [now, userInput, assistantResponse],
}),
});

setConversationContext(userInput);
setUserInput(“”);
} catch (error) {
console.error(“Error:”, error);
} finally {
setIsLoading(false);
}
};

return (
<div className=”flex flex-col h-screen bg-gradient-to-r from-blue-100 to-purple-100″>
<div className=”flex items-center justify-between p-4 bg-gradient-to-r from-blue-100 to-purple-100 shadow-md h-[63px]”>
<h1 className=”text-2xl font-bold text-indigo-800 font-noto-sans text-[15px]”>
AIボートマッチ丨鹿児島県知事選挙2024
</h1>
<a
href=”https://demotech.jp/”
target=”_blank”
rel=”noopener noreferrer”
className=”text-[11px] text-indigo-600 hover:text-indigo-800 transition duration-300 ease-in-out font-noto-sans”
>
一般社団法人デモテク
</a>
</div>
<div className=”flex-grow overflow-y-auto p-4″>
{chatHistory.map((message, index) => (
<div
key={index}
className={`mb-4 ${
message.role === “user” ? “text-right” : “text-left”
}`}
>
<div
className={`inline-block p-3 rounded-lg ${
message.role === “user”
? “bg-indigo-500 text-white”
: “bg-gray-100”
}`}
>
{message.content.split(“\n”).map((line, i) => (
<p key={i} className=”mb-1 last:mb-0 text-lg”>
{line}
</p>
))}
</div>
</div>
))}
</div>
<form
onSubmit={handleSubmit}
className=”p-4 bg-gradient-to-r from-blue-100 to-purple-100″
>
<div className=”flex flex-col”>
<div className=”flex”>
<input
type=”text”
name=”userInput”
value={userInput}
onChange={handleInputChange}
className=”flex-grow p-3 border-2 border-indigo-300 rounded-l-lg focus:outline-none focus:border-indigo-500 text-lg font-noto-sans”
placeholder=”質問を入力してください…”
disabled={isLoading}
/>
<button
type=”submit”
className=”bg-indigo-500 text-white p-3 rounded-r-lg hover:bg-indigo-600 transition duration-300 ease-in-out”
disabled={isLoading}
>
{isLoading ? (
<i className=”fas fa-spinner fa-spin text-xl”></i>
) : (
<i className=”fas fa-paper-plane text-xl”></i>
)}
</button>
</div>
<p className=”text-[10px] text-gray-500 mt-1″>
回答は必ずしも正しいとは限りません。重要な情報は確認するようにしてください。
</p>
</div>
</form>
</div>
);
}

export default MainComponent;