0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【備忘録】Next.js×OpenaiAPIの使い方

Posted at

はじめに

この記事は、OpenAIAPIを使ったwebアプリを作成している途中で、公式ドキュメントと検索でヒットする物の間に乖離があったため、備忘録としてまとめたものです。

開発絶賛勉強中の私が書いたものであるため、必ずしもベストプラクティスではないことに注意しください!

もっと良いディレクトリ構成やAPIの呼び出し方などがあれば教えていただけると幸いです!

動作確認環境

  • Next.js 13.4.5
  • React 18.2

公式ドキュメント

公式ドキュメントにはnode.js向けのapiの叩き方として次のような方法が掲載されています。

OpenAIクラスをインポートして、インスタンス化したものを使うという感じですね。

今回はこれを骨組みにします。

公式Doc
import OpenAI from "openai";
const openai = new OpenAI();
const completion = await openai.chat.completions.create({
    model: "gpt-4o",
    messages: [
        {"role": "user", "content": "write a haiku about ai"}
    ]
});

外部APIはサーバから呼び出す

クライアントからでもコードを書けば外部APIを使うことはできますがセキュリティの観点からサーバ側で処理するべきみたいです。

➡ Next.jsが提供するRouteHandlersを使い、中間APIを作成する

ディレクトリ構成

今回説明するコードのディレクトリ構成です。慣習から逸れている部分がありましたら指摘していただけると幸いです!

project-root/
│
├── .env                    
├── .gitignore              
│
├── app/                    
│   ├── api/                
│   │   └── openai/         
│   │       └── route.ts  
│   │
│   ├──utils/           
│   │   └── callOpenai.tsx  
│   │
│   └── test.tsx
│
└──  types.tsx                 
          

準備

インストール

npm install openai

APIキーの作成

下のページから発行できます。詳しくは添付した記事を参照してください!

APIキーの登録

プロジェクト直下の.envファイルに次のようにAPIキーを貼りつけます

.envファイルが.gitignoreにあることを確認する

OPENAI_API_KEY="sk-..."

OpenAIAPIを直接叩く部分(中間API)の作成

app/api/openai/route.tsを作成し、サーバーサイドで動く物を実装します。
※エラーハンドリングは割愛してあります

各ディレクトリ、ファイル名について

名前 説明
app appディレクトリ
api 慣習、apiに関連するものをまとめる
openai 自由、APIのサービス名にしておくのが無難
route.ts(.js) 必須、他の名前だとエラー
route.ts
import {NextResponse,NextRequest} from 'next/server';
import {OpenAI} from 'openai';
import type {openaiTypes} from '@/types'; //{model:string; system:string; prompt:string;}

const openai = new OpenAI({ apiKey:process.env.OPENAI_API_KEY});//.envファイルからAPIキーを取得する

export async function POST(req:NextRequest){
    const {model,system,prompt}=(await req.json()) as openaiTypes;//クライアントサイドからのリクエストを取得   
    
    const response=await openai.chat.completions.create({
        model:model, //モデル
        messages:[
            {
                role:'system', //システムプロンプト
                content:system,
            },
            {
                role:'user', //プロンプト
                content:prompt,
            },
        ],   
    });
    
    return NextResponse.json(response);//クライアントサイドにに出力を返す
}

クライアント側の実装

今作成した中間APIを呼び出すコードを実装します。fetchを使い、エンドポイントはapi/openaiとします。エンドポイントについてはapi/route.tsが入ったディレクトリ名となっています。

今回は複数のモデル、複数のシステムプロンプトを使いたかったので、CallOpenai(model,system,prompt)のように呼び出せる関数を作成しました。

ファイルはapp/utils/callOpenai.tsxに作成してあります。これについては慣習から逸れている可能性があります。

コメントにて教えていただけるとありがたいです!

callOpenai.tsx
export default async function CallOpenai(model: string,system:string,prompt: string) {
    const response = await fetch('api/openai', { //エンドポイントに注意
        //この辺はお決まりのやつ
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
        },
        body: JSON.stringify({
            model: model,//モデル
            system:system,//システムプロンプト
            prompt: prompt,//プロンプト         
        }),
    });
    const data = await response.json();レスポンスをjson形式で受け取る
    return data.choices[0].message;//ここに最新の出力が格納されている(公式doc参照)
}

呼び出してみる

↓こんな感じで呼び出せます!

import CallOpenai from '@/features/callOpenai';

async function test(){
    const model = "gpt-3.5-turbo";
    const system = "Hello";
    const prompt = "How are you?";
    const response = await CallOpenai(model,system,prompt);
    console.log(response);//=>Hello How are you?
}

まとめ

OpenAIAPIの使い方について、半年ほど前の記事と比較しても変わっていたため、公式ドキュメントの大切さを痛感しました

様々なご指摘コメントにてお待ちしております!!!

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?