今後の技術ネタはzennに移行することにした
今後の技術系の記事はzennで書くことにしました。
これまでは技術ネタも個人的なポエムもひっくるめて全部このブログで書いていたのだけど、
- コードとかちょっと見にくい
- そのために色々カスタマイズするのももうやりたくないし、テーマ変えるのも面倒。
- 前から技術ネタ書くのにzennいいなと思っていた
ということで。そのためにVSCodeの執筆環境も作りました。Boilerplateありがたいですね。
ということで、こちらのブログでは個人的な話とかだけになるかなと思います。音声関係とか技術的な話は今後はzennのほうをごらんください。
引き続きよろしくお願いします。
OpenAIのQuick Startをやってみる
ちょっと前にChatGPTの話をしました。
あくまでも動いているものを試して見るだけで、これをどういう風に作るのか?ということまでは踏み込んでいませんでした。
ということでOpenAIのQuick Startをやってみたいと思います。
目次
GPT-3とは
ここがわかりやすい気がします。
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
また、ビジネスのユースケースで使うには、コンテキストをあわせるような工夫も必要になるかなと思いますが、そのあたりも考えられているようです。ここはキーになるかなと思っているのでもう少し調べてみます。
Finch試してみた
Docker Desktopが企業ユースだと有料になるという話、個人としては何も影響ないのですが、まあ代替が今後のメインストリームになる可能性はあるよね、ということで、Finchを試してみます。
目次
Finchとは?
- 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不要なら、これでいいかも。