はじめに
OpenAIのCreate image APIをElixirでコールしてみます。
ElixirではHTTPクライアントとして Req がモダンで扱いやすいです。今回のようなAPI連携にも最適です。特にシンプルなJSONベースのやり取りには圧倒的な手軽さがあります。
Elixir使い(アルケミスト=錬金術師)でOpenAI APIを叩きたい人向けに、Reqで完結する最小実装を紹介します。
(つまりは、ReqでHTTP Postしているだけの記事です。)
参考実装
参考となる実装を紹介します。
公式ドキュメントに書いてあります。
Python
pip install openai
でライブラリを利用する例です。
https://platform.openai.com/docs/guides/image-generation?image-generation-model=gpt-image-1&lang=python#generate-images に書いてあるサンプルのモデルをdall-e-3
に変更しただけです。
from openai import OpenAI
import base64
client = OpenAI()
prompt = """
A children's book drawing of a veterinarian using a stethoscope to
listen to the heartbeat of a baby otter.
"""
result = client.images.generate(
model="dall-e-3",
prompt=prompt,
response_format="b64_json"
)
image_base64 = result.data[0].b64_json
image_bytes = base64.b64decode(image_base64)
# Save the image to a file
with open("otter.png", "wb") as f:
f.write(image_bytes)
curl
https://platform.openai.com/docs/guides/image-generation?image-generation-model=gpt-image-1&lang=curl
に書いてあるサンプルのモデルをdall-e-3
に変更しただけです。
curl -X POST "https://api.openai.com/v1/images/generations" \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-type: application/json" \
-d '{
"model": "dall-e-3",
"prompt": "A childrens book drawing of a veterinarian using a stethoscope to listen to the heartbeat of a baby otter."
}' | jq -r '.data[0].b64_json' | base64 --decode > otter.png
Elixirで実装する
curlの実装例が参考になります。
Mix.install([
{:req, "~> 0.5.0"}
])
openai_api_key = System.get_env("OPENAI_API_KEY")
headers = [
"Content-Type": "application/json",
Authorization: "Bearer #{openai_api_key}"
]
prompt = """
A children's book drawing of a veterinarian using a stethoscope to
listen to the heartbeat of a baby otter.
"""
url = "https://api.openai.com/v1/images/generations"
body = %{
prompt: prompt,
model: "dall-e-3",
response_format: "b64_json",
n: 1
}
{:ok, %{body: %{"data" => [%{"b64_json" => b64_json}]}}} =
Req.post(url,
headers: headers,
json: body,
connect_options: [timeout: 60_000],
receive_timeout: 60_000
)
Base.decode64!(b64_json)
|> then(fn content -> File.write("otter-elixir.png", content) end)
特筆すべき点としては、receive_timeout: 60_000
を指定しないと{:error, %Req.TransportError{reason: :timeout}}
が頻発していました。
Req.post/2の第2引数options
にいろいろなオプションを指定している恒例の好例です。
:headers
や:json
(つまりはボディにMap渡す)などを指定しています。
結果
結果です。
dall-e-3
dall-e-3
モデルで描いたものはうまいです。
dall-e-2
dall-e-2
モデルで描いたものはなんだか気持ち悪いです。怖いです。
折りたたんでおきます。
怖いものを見たい方はどうぞ。
おわりに
OpenAIのCreate image APIをElixirでコールしてみました。
APIのその先には、誰かの「描きたい未来」がある。
Elixirはその想いを、静かに、そして確かに形にする──。
そう、闘魂とは「描くこと」なのだ。