kun432's blog

Alexaなどスマートスピーカーの話題中心に、Voiceflowの日本語情報を発信してます。たまにAWSやkubernetesなど。

〜スマートスピーカーやVoiceflowの記事は右メニューのカテゴリからどうぞ。〜

OpenAIのQuick Startをやってみる

ちょっと前にChatGPTの話をしました。

あくまでも動いているものを試して見るだけで、これをどういう風に作るのか?ということまでは踏み込んでいませんでした。

ということでOpenAIのQuick Startをやってみたいと思います。

目次

GPT-3とは

ここがわかりやすい気がします。

www.nri.com

ChatGPTは、その名からも分かる通り、GPT-3をベースとして、対話に特化した形で実装されているようです。

Quick Startをやってみる

Quick Startはここです。

https://beta.openai.com/docs/quickstart/start-with-an-instruction

ドキュメントの中でもいくつか試せるようになっていますが、実際にアプリを作って試すのは「Build your application」のところです。今回はNode.jsでやってみることにします。

サンプルのレポジトリをクローンします。

$ git clone https://github.com/openai/openai-quickstart-node.git
$ cd openai-quickstart-node

OpenAIのAPIキーを.envファイルに記載します。

$ cp .env.example .env
OPENAI_API_KEY=XXXXXXXXXXXXXXX

パッケージをインストールします。

$ npm install

アプリケーションを起動します。http://localhost:3000 で立ち上がります。

$ npm run dev

> openai-quickstart-node@0.1.0 dev
> next dev

ready - started server on 0.0.0.0:3000, url: http://localhost:3000
(snip)

ブラウザでアクセスするとこういうのが立ち上がります。

動物を入れるとその名前を生成してくれるようですね。Quick Startの最初で紹介されていた通りに試してみましょう。

"horse"を入力します。

結果はこうなります。

もう一度同じく"horse"を入力するとこうなります。

1回めと違いますね。"Temperature"により意図的に精度を下げて結果としてバリエーションが生まれるということですね。

https://beta.openai.com/docs/quickstart/adjust-your-settings

少し絞り込んでみましょう。"black horse"で。

"black"に関連しそうなキーワードが選ばれていますね。

コードを読んで見る

デモアプリはNext.jsを使っています。で、GPT-3へのAPI処理はpages/api/generate.jsになります。

import { Configuration, OpenAIApi } from "openai";

const configuration = new Configuration({
  apiKey: process.env.OPENAI_API_KEY,
});
const openai = new OpenAIApi(configuration);

export default async function (req, res) {
  if (!configuration.apiKey) {
    res.status(500).json({
      error: {
        message: "OpenAI API key not configured, please follow instructions in README.md",
      }
    });
    return;
  }

  const animal = req.body.animal || '';
  if (animal.trim().length === 0) {
    res.status(400).json({
      error: {
        message: "Please enter a valid animal",
      }
    });
    return;
  }

  try {
    const completion = await openai.createCompletion({
      model: "text-davinci-003",
      prompt: generatePrompt(animal),
      temperature: 0.6,
    });
    res.status(200).json({ result: completion.data.choices[0].text });
  } catch(error) {
    // Consider adjusting the error handling logic for your use case
    if (error.response) {
      console.error(error.response.status, error.response.data);
      res.status(error.response.status).json(error.response.data);
    } else {
      console.error(`Error with OpenAI API request: ${error.message}`);
      res.status(500).json({
        error: {
          message: 'An error occurred during your request.',
        }
      });
    }
  }
}

function generatePrompt(animal) {
  const capitalizedAnimal =
    animal[0].toUpperCase() + animal.slice(1).toLowerCase();
  return `Suggest three names for an animal that is a superhero.

Animal: Cat
Names: Captain Sharpclaw, Agent Fluffball, The Incredible Feline
Animal: Dog
Names: Ruff the Protector, Wonder Canine, Sir Barks-a-Lot
Animal: ${capitalizedAnimal}
Names:`;
}

順番に見ていきましょう。

createCompletionでテキスト補完の初期化を行っています。

  try {
    const completion = await openai.createCompletion({
      model: "text-davinci-003",
      prompt: generatePrompt(animal),
      temperature: 0.6,
    });

GPT-3は、用途に応じて4つのモデルを提供しています。これをmodelで指定します。精度やレイテンシー、費用などが異なるようです。

https://beta.openai.com/docs/models/gpt-3

temperatureは上で紹介したとおりですね。

promptでAPIに渡す文字列を指定します。ここでgeneratePromptが呼ばれていますね。

function generatePrompt(animal) {
  const capitalizedAnimal =
    animal[0].toUpperCase() + animal.slice(1).toLowerCase();
  return `Suggest three names for an animal that is a superhero.

Animal: Cat
Names: Captain Sharpclaw, Agent Fluffball, The Incredible Feline
Animal: Dog
Names: Ruff the Protector, Wonder Canine, Sir Barks-a-Lot
Animal: ${capitalizedAnimal}
Names:`;
}

Quick Startにもあったように、いくつかの例をヒントとしてモデルに渡すことで、より自分たちが期待する方向に寄せるような感じになります。

https://beta.openai.com/docs/quickstart/add-some-examples

日本語について

GPT-3は日本語にも対応しています。

ということで少し修正してみましょう。以下の関数を追加します。

function generatePromptJa(animal) {
  return `動物の日本っぽいクラシカルな名前を3つ挙げて。

動物名: 猫
名前: シロ, タマ, ミケ
動物名: 犬
名前: ポチ, ラッシー, ハチ
動物名: ${animal}
名前:`;
}

呼び出し元で関数名を上記に変えます。

   const completion = await openai.createCompletion({
      model: "text-davinci-003",
      prompt: generatePromptJa(animal),
      temperature: 0.6,
    });

試してみましょう。

どうでしょうか。そう言われてみれば、って感じかなと思います。

まとめ

とてもシンプルに使えていい感じですね。パラメータやヒントなどを色々変えて試してみると良いかと思いますし、プロンプトの例もあります。

https://beta.openai.com/examples

また、ビジネスのユースケースで使うには、コンテキストをあわせるような工夫も必要になるかなと思いますが、そのあたりも考えられているようです。ここはキーになるかなと思っているのでもう少し調べてみます。

https://beta.openai.com/docs/guides/fine-tuning