作ったもの
Windows版
https://github.com/7tsuno/dev.to-summarizer/releases/tag/1.0
dev.to-summerizer-1.0.0-setup.exe
をダウンロードしてセットアップできます
Mac版
ADPへの登録が必要で手続きが煩雑なため、現在提供していません。
Macで動かしてみたい人は
https://github.com/7tsuno/dev.to-summarizer
をCloneして使ってみてください
どんなアプリ?
-
dev.toの記事をまとめて要約してくれるアプリです
- tagと取得件数と期間を指定して、トレンド記事を取得することができます
- 取得したトレンド記事の中で興味があるものをまとめて要約することができます
なんでつくったの?
- OpenAIのBatch APIを使ってみたかった
- Electronのアプリを作ってみたかった
本当はTauriが使いたかったけど諦めた - 海外の最新トレンドを追いたかった
対象読者
- OpenAIのBatch APIって実際どうなの?って人
- Batchの動くサンプルが欲しい人
書かないこと
- 詳細な実装のはなし
- バッチ処理以外の話 (特筆すべき点がないのでカットしました)
OpenAIのBatch API
Batch APIは、大量のリクエストを非同期に処理できるAPIです。これを使用すると、リアルタイムで答えを得られる普通のAPIとは違い、リクエストを一括で送信し、24時間以内に結果をまとめて取得できます。
今回のアプリでは、複数の記事を一気に要約させるためにBatch APIを利用しています。
ここではアプリに取り込む場合のOpenAIのSDKを使ったAPIの使い方を紹介したいと思います。
Batch APIのメリット
- トークンあたりの金額が普通のAPIの半額
- 大量のリクエストを一度に送信し、結果をまとめて取得できる
Batch APIのデメリット
- リアルタイムに結果を取得することはできない
Batch APIの大まかな流れ
- プロンプトをまとめたファイルをアップロードする
- ファイルに対して処理を実行する
- 実行結果を確認する
- 実行結果のファイルをダウンロードする
これを一つずつ見ていきます。
プロンプトをまとめたファイルをアップロードする
Batch APIのInputはファイルである必要があります。jsonlという形式のファイルに1行1プロンプトを入れていきます。この形式は、JSONを行単位で構造したファイルです。
イメージとしては↓のような感じです。他にも必要なパラメータはありますが、ここでは省略しています
{"messages": [{"role": "user", "content": "1 + 1は?"}]}
{"messages": [{"role": "user", "content": "日本の首都は?"}]}
{"messages": [{"role": "user", "content": "株式会社CureAppの社長の名前は?"}]}
この形式のファイルを作成して、ファイルをアップロードします。
await openai.files.create({
file: fs.createReadStream(batchInputFilePath),
purpose: 'batch'
})
また、アップロードに成功すると、OpenAIのコンソール上でStorageにファイルがアップロードされていることが分かります。
ファイルに対して処理を実行する
先ほどのファイルアップロードのレスポンスとしてファイルIDが取得できます。このIDに対してバッチ処理を実行するAPIを叩きます。
await openai.batches.create({
input_file_id: inputFile.id,
endpoint: '/v1/chat/completions',
completion_window: '24h'
})
この処理は非同期なので、この時点では結果を取得することはできません。
実行結果を確認する
先ほどのBatch処理実行のレスポンスとしてBatch IDが取得できます。このIDに対して実行結果を確認するAPIを叩きます。
await openAI.batches.retrieve(batchId)
このような返却値が返ってきます。
{
"id": "batch_abc123",
"object": "batch",
"endpoint": "/v1/completions",
"status": "completed",
"output_file_id": "file-cvaTdG",
...
}
status
はin_progress
, failed
, completed
などがあり、completed
の場合はoutput_file_id
があるので、これを取得することができます。
実行結果のファイルをダウンロードする
status
がcompleted
の場合はファイルをダウンロードする処理を行うことができます。取得したoutput_file_id
を利用してファイルをダウンロードします。
await openAI.files.content(fileId)
取得した内容もまたjsonl形式なので、良い感じにparseして使用しましょう。
コード
おわりに
Batch API、使ってみると正直使いづらいです。ファイル作るのもparseするのもしんどいです。
ただ、非同期で問題ない処理の場合はコストを抑えるために積極的に使っていったほうが良さそうだなと思っています。
どこかの天才の人がいい感じのラッパーを作ってくれたら嬉しいですね。