kun432's blog

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

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

今後の技術ネタはzennに移行することにした

今後の技術系の記事はzennで書くことにしました。

これまでは技術ネタも個人的なポエムもひっくるめて全部このブログで書いていたのだけど、

  • コードとかちょっと見にくい
  • そのために色々カスタマイズするのももうやりたくないし、テーマ変えるのも面倒。
  • 前から技術ネタ書くのにzennいいなと思っていた

ということで。そのためにVSCodeの執筆環境も作りました。Boilerplateありがたいですね。

ということで、こちらのブログでは個人的な話とかだけになるかなと思います。音声関係とか技術的な話は今後はzennのほうをごらんください。

気が向いたら既存コンテンツもzennに移すかもしれません。

引き続きよろしくお願いします。

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

Finch試してみた

Docker Desktopが企業ユースだと有料になるという話、個人としては何も影響ないのですが、まあ代替が今後のメインストリームになる可能性はあるよね、ということで、Finchを試してみます。

目次

Finchとは?

github.com

  • re:Invent 2022で発表された、AWSによるオープンソースなDocker Desktop代替。無料で使える。
  • containerd/nerdctl/Lima/BuildKitをオールインワンで管理。
  • 現状はMacのみで、GUIはない。

前提

$ system_profiler SPHardwareDataType
Hardware:

    Hardware Overview:

      Model Name: MacBook Pro
      Model Identifier: MacBookPro13,3
      Processor Name: Quad-Core Intel Core i7
      Processor Speed: 2.9 GHz
      Number of Processors: 1
      Total Number of Cores: 4
      L2 Cache (per Core): 256 KB
      L3 Cache: 8 MB
      Hyper-Threading Technology: Enabled
      Memory: 16 GB

インストール

$ brew install finch

$ finch version
Finch version: v0.1.1

Finchが使う仮想マシンを初期化。これはインストール直後の1回だけ。うちの環境ではそこそこ時間かかった。

$ finch vm init

仮想マシンの起動。ただしinitしたときはあわせて起動しているので、再起動したときとか。

$ finch vm start

テスト用のコンテナを実行してみる。

$ finch run --rm public.ecr.aws/finch/hello-finch
public.ecr.aws/finch/hello-finch:latest:                                          resolved       |++++++++++++++++++++++++++++++++++++++|
index-sha256:a71e474da9ffd6ec3f8236dbf4ef807dd54531d6f05047edaeefa758f1b1bb7e:    done           |++++++++++++++++++++++++++++++++++++++|
manifest-sha256:2f848edb93f7d0cfa20d7dc7add84586fe06d258d6dd54422d8015c584ff3b9e: done           |++++++++++++++++++++++++++++++++++++++|
config-sha256:50c36f221209ea6829db90eff11db167d8cc22abf7c2c0f1e7f4a0c701c0592f:   done           |++++++++++++++++++++++++++++++++++++++|
layer-sha256:4f4fb700ef54461cfa02571ae0db9a0dc1e0cdb5577484a6d75e68dc38e8acc1:    done           |++++++++++++++++++++++++++++++++++++++|
layer-sha256:cb7e3bc996dd3208c5b4560d5f6571486e2fe90b5a1cc384e2d6af0dc07de02a:    done           |++++++++++++++++++++++++++++++++++++++|
elapsed: 3.4 s                                                                    total:  1.0 Mi (312.8 KiB/s)

                            @@@@@@@@@@@@@@@@@@@
                        @@@@@@@@@@@@    @@@@@@@@@@@
                      @@@@@@@                  @@@@@@@
                    @@@@@@                        @@@@@@
                  @@@@@@                            @@@@@
                 @@@@@                      @@@#     @@@@@@@@@
                @@@@@                     @@   @@@       @@@@@@@@@@
                @@@@%                     @     @@            @@@@@@@@@@@
                @@@@                                               @@@@@@@@
                @@@@                                         @@@@@@@@@@@&
                @@@@@                                  &@@@@@@@@@@@
                 @@@@@                               @@@@@@@@
                  @@@@@                            @@@@@(
                   @@@@@@                        @@@@@@
                     @@@@@@@                  @@@@@@@
                        @@@@@@@@@@@@@@@@@@@@@@@@@@
                            @@@@@@@@@@@@@@@@@@


Hello from Finch!

Visit us @ github.com/runfinch

イメージのビルド

サンプルにある例を試してみる。

$ git clone https://github.com/runfinch/finch.git
$ cd finch/contrib/hello-finch
$ tree
.
├── Dockerfile
├── README.md
├── go.mod
└── main.go

Dockerfileの中身はこんな感じ

FROM public.ecr.aws/docker/library/golang:1.19 AS builder
WORKDIR /build
COPY . .

RUN CGO_ENABLED=0 go build -a -o hello-finch .

FROM scratch
COPY --from=builder /build/hello-finch /app/
WORKDIR /app
ENTRYPOINT ["./hello-finch"]

ではビルド。

$ finch build . -t hello-finch

[+] Building 112.2s (11/11) FINISHED
 => [internal] load build definition from Dockerfile                       0.2s
 => => transferring dockerfile: 270B                                       0.0s
 => [internal] load .dockerignore                                          0.2s
 => => transferring context: 2B                                            0.0s
 => [internal] load metadata for public.ecr.aws/docker/library/golang:1.1  2.7s
 => [builder 1/4] FROM public.ecr.aws/docker/library/golang:1.19@sha256:  89.5s
 => => resolve public.ecr.aws/docker/library/golang:1.19@sha256:bace16d06  0.1s
 => => sha256:b40aef772139aeff34bb1a2ad1c26882b81665c29fd2da9 0B / 156B  108.5s
 => => sha256:26aad9da304d88ad9b1a5521215b5874b99b7 147.85MB / 148.95MB  108.5s
 => => sha256:c768848b86a20f52a12485455ca0607c26af780 85.98MB / 85.98MB  108.5s
 => => sha256:81283a9569ad5e90773f038daedd0d565810ca5 53.48MB / 54.58MB  108.4s
 => => sha256:c796299bbbddc7aeada9539a4e7874a75fa2b6f 10.49MB / 10.88MB  108.2s
 => => sha256:32de3c850997ce03b6ff4ae8fb00b34b9d7d7f9 55.03MB / 55.03MB  100.9s
 => => sha256:fa1d4c8d85a4e064e50cea74d4aa848dc5fc275aef 4.19MB / 5.16MB  72.3s
 => => extracting sha256:32de3c850997ce03b6ff4ae8fb00b34b9d7d7f9a35bfcdb  11.5s
 => => extracting sha256:fa1d4c8d85a4e064e50cea74d4aa848dc5fc275aef223fcc  1.3s
 => => extracting sha256:c796299bbbddc7aeada9539a4e7874a75fa2b6ff421f8d5a  1.3s
 => => extracting sha256:81283a9569ad5e90773f038daedd0d565810ca5935eec8f5  8.3s
 => => extracting sha256:c768848b86a20f52a12485455ca0607c26af7804eca934c7  6.2s
 => => extracting sha256:26aad9da304d88ad9b1a5521215b5874b99b70b75989cf3  16.7s
 => => extracting sha256:b40aef772139aeff34bb1a2ad1c26882b81665c29fd2da93  0.1s
 => [internal] load build context                                          0.4s
 => => transferring context: 2.11kB                                        0.0s
 => [builder 2/4] WORKDIR /build                                           0.1s
 => [builder 3/4] COPY . .                                                 0.2s
 => [builder 4/4] RUN CGO_ENABLED=0 go build -a -o hello-finch .          18.5s
 => [stage-1 1/2] COPY --from=builder /build/hello-finch /app/             0.1s
 => [stage-1 2/2] WORKDIR /app                                             0.2s
 => exporting to oci image format                                          0.8s
 => => exporting layers                                                    0.4s
 => => exporting manifest sha256:8e21310d5b6462746b71fbf5b038f99f0be14759  0.0s
 => => exporting config sha256:17d42c196a8705bb28ff80da4193f755364d38748f  0.0s
 => => sending tarball                                                     0.2s
unpacking docker.io/library/hello-finch:latest (sha256:8e21310d5b6462746b71fbf5b038f99f0be147599517c4352d0866ce8d918ea5)...
Loaded image: docker.io/library/hello-finch:latest

できたイメージを見てみる。

$ finch images
REPOSITORY                          TAG       IMAGE ID        CREATED          PLATFORM       SIZE       BLOB SIZE
hello-finch                         latest    8e21310d5b64    2 minutes ago    linux/amd64    1.7 MiB    1.0 MiB
public.ecr.aws/finch/hello-finch    latest    a71e474da9ff    8 minutes ago    linux/amd64    1.7 MiB    1.0 MiB

実行してみる。あえて-rmなしで。

$ finch run hello-finch

                            @@@@@@@@@@@@@@@@@@@
                        @@@@@@@@@@@@    @@@@@@@@@@@
                      @@@@@@@                  @@@@@@@
                    @@@@@@                        @@@@@@
                  @@@@@@                            @@@@@
                 @@@@@                      @@@#     @@@@@@@@@
                @@@@@                     @@   @@@       @@@@@@@@@@
                @@@@%                     @     @@            @@@@@@@@@@@
                @@@@                                               @@@@@@@@
                @@@@                                         @@@@@@@@@@@&
                @@@@@                                  &@@@@@@@@@@@
                 @@@@@                               @@@@@@@@
                  @@@@@                            @@@@@(
                   @@@@@@                        @@@@@@
                     @@@@@@@                  @@@@@@@
                        @@@@@@@@@@@@@@@@@@@@@@@@@@
                            @@@@@@@@@@@@@@@@@@


Hello from Finch!

Visit us @ github.com/runfinch

コンテナを確認してみる。

$ finch ps -a
CONTAINER ID    IMAGE                                   COMMAND            CREATED           STATUS                       PORTS    NAMES
0a03134644cd    docker.io/library/hello-finch:latest    "./hello-finch"    23 seconds ago    Exited (0) 22 seconds ago             hello-finch-0a031

コンテナを削除。

$ finch rm $(finch ps -a -q)
0a03134644cd

イメージの方も。

$ finch images
REPOSITORY                          TAG       IMAGE ID        CREATED           PLATFORM       SIZE       BLOB SIZE
hello-finch                         latest    8e21310d5b64    10 minutes ago    linux/amd64    1.7 MiB    1.0 MiB
public.ecr.aws/finch/hello-finch    latest    a71e474da9ff    16 minutes ago    linux/amd64    1.7 MiB    1.0 MiB

$ finch rmi public.ecr.aws/finch/hello-finch
Untagged: public.ecr.aws/finch/hello-finch:latest@sha256:a71e474da9ffd6ec3f8236dbf4ef807dd54531d6f05047edaeefa758f1b1bb7e
Deleted: sha256:2e05c12f4142e6af2317b4097ab105857eb97781088895f41479a9b27378bdcf

コマンドライン的にはdockerと何も変わらない。

compose

内部でnerdctlを使っているということで、docker-compose的なこともできる。nerdctlのサンプルを試してみる。

$ wget https://raw.githubusercontent.com/containerd/nerdctl/main/examples/compose-wordpress/docker-compose.yaml
$ finch compose up -d
(snip)
INFO[0093] Creating container hello-finch_db_1
INFO[0093] Creating container hello-finch_wordpress_1

$ finch ps -a
CONTAINER ID    IMAGE                              COMMAND                   CREATED           STATUS    PORTS                   NAMES
6a1de3f39ac8    docker.io/library/wordpress:5.7    "docker-entrypoint.s…"    19 seconds ago    Up        0.0.0.0:8080->80/tcp    hello-finch_wordpress_1
9877bfdbc470    docker.io/library/mariadb:10.5     "docker-entrypoint.s…"    20 seconds ago    Up                                hello-finch_db_1

ブラウザで localhost:8080 にアクセスしてみる。

普通に使えますね。

停止もdocker-composeと同じ。

$ finch compose down 

まとめ

dockerと何も違わないですね。Docker Desktop使ってない/GUI不要なら、これでいいかも。