Next.jsでのopenAIの使い方
APIキーは、openaiのサイトにログインしたのち「API keys」で作成することができます。
一度発行したキーは改めて確認しなおすことはできないので、どこかにメモしておきましょう。
APIキーが取得できた前提で、Next.jsのAPIを記述していきます。
もし、Next.jsのプロジェクトが作成できないという方がいましたら、以下の記事をご参考ください。
![](https://qiita-user-contents.imgix.net/https%3A%2F%2Fcdn.qiita.com%2Fassets%2Fpublic%2Farticle-ogp-background-412672c5f0600ab9a64263b751f1bc81.png?ixlib=rb-4.0.0&w=1200&mark64=aHR0cHM6Ly9xaWl0YS11c2VyLWNvbnRlbnRzLmltZ2l4Lm5ldC9-dGV4dD9peGxpYj1yYi00LjAuMCZ3PTk3MiZoPTM3OCZ0eHQ9TmV4dC5qcyVFMyU4MSVBNyVFOSU5NiU4QiVFNyU5OSVCQSVFMyU4MiU5MiVFNSVBNyU4QiVFMyU4MiU4MSVFMyU4MiU4QiVFMyU4MSVCRSVFMyU4MSVBNyZ0eHQtYWxpZ249bGVmdCUyQ3RvcCZ0eHQtY29sb3I9JTIzMjEyMTIxJnR4dC1mb250PUhpcmFnaW5vJTIwU2FucyUyMFc2JnR4dC1zaXplPTU2JnM9ZDk2YmQyNWMyOGJkM2NjMzNhMzM3MTk2ZGMwNjI3ZTc&mark-x=142&mark-y=57&blend64=aHR0cHM6Ly9xaWl0YS11c2VyLWNvbnRlbnRzLmltZ2l4Lm5ldC9-dGV4dD9peGxpYj1yYi00LjAuMCZoPTc2Jnc9NzcwJnR4dD0lNDByaXN0bzI0JnR4dC1jb2xvcj0lMjMyMTIxMjEmdHh0LWZvbnQ9SGlyYWdpbm8lMjBTYW5zJTIwVzYmdHh0LXNpemU9MzYmdHh0LWFsaWduPWxlZnQlMkN0b3Amcz1kMWM2MjQxYTlhMTc3YTA4ZDlkZjQ3ODdjYTA1NWM4NQ&blend-x=142&blend-y=486&blend-mode=normal&s=e2f70b9848145d1572162fe63384c288)
Next.jsのAPIからopenaiを呼び出すコード
import { NextApiRequest, NextApiResponse } from 'next';
import axios from 'axios';
export default async (req: NextApiRequest, res: NextApiResponse) => {
try {
const prompt = req.body.prompt; // リクエストボディからpromptを取得
const api_url = "https://api.openai.com/v1/chat/completions";
const data = {
"model": "gpt-3.5-turbo",
"messages": [
{"role":"system","content":"これからの解答にはすべてギャルの口調で答えてください。"},
{"role": "user", "content": prompt}
],
"max_tokens": 3000
};
const headers = {
"Authorization": `Bearer ${process.env.API_KEY}` // 環境変数からAPIキーを取得
};
const response = await axios.post(api_url, data, { headers });
const result = response.data.choices[0].message.content;
const tokensUsed = response.data.usage.total_tokens;
res.status(200).json({ result, tokensUsed });
res.status(200).json({ result });
} catch (error) {
console.error(error);
res.status(500).json({ error: "An error occurred" });
}
};
少々荒い作りではありますが、説明用ということでご容赦を!
大事なのは先ほど取得したkeyをそのまま埋めるのではなくprocess.env.API_KEYという環境変数に入れていることです。
すべてローカルで開発する分には問題ありませんが、githubにコードをあげたりするときに直接ファイルに書き込んでいると悪用される可能性が高いです。
.envファイルあるいは、.env.lovalファイルなどに入れたうえで、しっかりとgitignoreをしておきましょう。
APIキーは大事!envファイルに入れてgitignore!
messagesに入れるもの
openaiのAPIを叩くとき、
“model”と”messages”というリクエストパラメータが必要になります。
modelは”gpt-3.5-turbo”であったり、”gpt-4.0″などというモデルのことで性能が変わります。
messagesが少し癖があり”role”と”content”を指定します。
roleには”system”と”user”と”assistant”があります。
簡単に言うと、systemはAIに指定する前提条件、userはAIに質問する内容、assistantはAIから帰ってきた返答です。
帰ってきた返答というのがわかりにくいですが、要は何回も質問と回答を繰り返すときに、それらを再現するために存在している部分です。
つまり、messagesでは過去の解答なども含めたものを渡すことになります。
ただ、tokenをその分消費してしまうのに注意が必要です。
"messages": [
{"role":"system","content":"これからの解答にはすべてギャルの口調で答えてください。"},
{"role": "user", "content": prompt}
],
ギャル調にしているのは趣味です。特に意味はありません。
つぎにこのAPIを利用した画面を作っていきます。
先ほどのapiは/api/gptというエンドポイントにしてます。(適当)
また消費したトークンなどを取得できるようにしてます。お金がかからないように。
import { useState } from "react";
import axios from "axios";
export default function Home() {
const [prompt, setPrompt] = useState("");
const [result, setResult] = useState("");
const [tokensUsed, setTokensUsed] = useState(null);
const handleGeneratePrompt = async () => {
try {
const response = await axios.post("/api/gpt", { prompt });
setResult(response.data.result);
setTokensUsed(response.data.tokensUsed);
} catch (error) {
console.error(error);
}
};
return (
<div className="min-h-screen flex items-center justify-center bg-gray-100">
<div className="bg-white p-6 rounded-lg shadow-md">
<h1 className="text-3xl font-semibold mb-4">
GPT-3.5 Turbo Prompt Generator
</h1>
<div className="mb-4">
<textarea
className="w-full p-2 border border-gray-300 rounded-lg"
rows="4"
placeholder="Enter your prompt here..."
value={prompt}
onChange={(e) => setPrompt(e.target.value)}
/>
</div>
<div className="mb-4">
<button
className="bg-blue-500 text-white px-4 py-2 rounded-lg hover:bg-blue-600"
onClick={handleGeneratePrompt}
>
Generate Prompt
</button>
</div>
{result && (
<div className="mb-4">
<h2 className="text-xl font-semibold mb-2">Generated Response:</h2>
<p className="border border-gray-300 p-2 rounded-lg">{result}</p>
</div>
)}
{tokensUsed !== null && (
<div>
<h2 className="text-xl font-semibold mb-2">Tokens Used:</h2>
<p className="mb-2">Tokens: {tokensUsed}</p>
<p>Cost: ${((tokensUsed * 0.002) / 1000).toFixed(6)}</p>
</div>
)}
</div>
</div>
);
}
完成形
import { useState } from "react";
import axios from "axios";
export default function Home() {
const [prompt, setPrompt] = useState("");
const [result, setResult] = useState("");
const [tokensUsed, setTokensUsed] = useState(null);
const handleGeneratePrompt = async () => {
try {
const response = await axios.post("/api/gpt", { prompt });
setResult(response.data.result);
setTokensUsed(response.data.tokensUsed);
} catch (error) {
console.error(error);
}
};
return (
<div className="min-h-screen flex items-center justify-center bg-gray-100">
<div className="bg-white p-6 rounded-lg shadow-md">
<h1 className="text-3xl font-semibold mb-4">
GPT-3.5 Turbo Prompt Generator
</h1>
<div className="mb-4">
<textarea
className="w-full p-2 border border-gray-300 rounded-lg"
rows="4"
placeholder="Enter your prompt here..."
value={prompt}
onChange={(e) => setPrompt(e.target.value)}
/>
</div>
<div className="mb-4">
<button
className="bg-blue-500 text-white px-4 py-2 rounded-lg hover:bg-blue-600"
onClick={handleGeneratePrompt}
>
Generate Prompt
</button>
</div>
{result && (
<div className="mb-4">
<h2 className="text-xl font-semibold mb-2">Generated Response:</h2>
<p className="border border-gray-300 p-2 rounded-lg">{result}</p>
</div>
)}
{tokensUsed !== null && (
<div>
<h2 className="text-xl font-semibold mb-2">Tokens Used:</h2>
<p className="mb-2">Tokens: {tokensUsed}</p>
<p>Cost: ${((tokensUsed * 0.002) / 1000).toFixed(6)}</p>
</div>
)}
</div>
</div>
);
}
![](https://faw-nlily.com/wp-content/uploads/2023/11/image-10-1024x509.png)
こんな感じになります。