🐒

かんたんDenoでOpenAI Chat Completions API

に公開

今更ですがOpenAI on JSRをDenoでやってみました。

https://deno.com/blog/openai-on-jsr

chat.ts
import { encodeBase64 } from "jsr:@std/encoding@1.0.10/base64";
import { extname } from "jsr:@std/path@1.1.2/extname";
import { OpenAI } from "jsr:@openai/openai@6.3.0";

if (Deno.args.length < 1) {
  console.log("Usage: deno -RWNE --env-file chat.ts <prompt> [image_file_1] [image_file_2]...");
  Deno.exit(1);
}

const text = Deno.args[0];
const paths = Deno.args.slice(1);
const model = Deno.env.get("OPENAI_MODEL") ?? "google/gemma-3-27b-it:free";

const mimeTypes: Record<string, string> = {
  ".png": "image/png",
  ".jpg": "image/jpeg",
  ".jpeg": "image/jpeg",
  ".gif": "image/gif",
  ".webp": "image/webp",
  ".avif": "image/avif",
};

const openai = new OpenAI();

const content: OpenAI.Chat.ChatCompletionContentPart[] = [
  {
    type: "text",
    text,
  },
];

for (const path of paths) {
  try {
    const bytes = await Deno.readFile(path);
    const base64 = encodeBase64(bytes);
    const ext = extname(path).toLowerCase();
    const mimeType = mimeTypes[ext] ?? "image/png";

    content.push({
      type: "image_url",
      image_url: {
        url: `data:${mimeType};base64,${base64}`,
      },
    });
  } catch (err) {
    console.error(`Failed to read image: ${path}`, err);
  }
}

const messages: OpenAI.Chat.ChatCompletionMessageParam[] = [
  {
    role: "system",
    content: "You are a helpful assistant.",
  },
  {
    role: "user",
    content,
  },
];

try {
  const result = await openai.chat.completions.create({ model, messages });
  const output = result.choices?.[0]?.message?.content;

  if (output) {
    await Deno.writeTextFile("output.md", output + "\n", { append: true });
    console.log("Response has been written to output.md.");
  } else {
    console.error("No response was returned from the OpenAI API.");
  }
} catch (err) {
  console.error("Error calling OpenAI API:", err);
}

デフォルトモデルはOpenRouterのGemma 3 27B (free)にしてありますが、私はGemini APIのOpenAI互換APIを使っています。

.env
OPENAI_MODEL=gemini-flash-latest
OPENAI_API_KEY=AI...
OPENAI_BASE_URL=https://generativelanguage.googleapis.com/v1beta/openai/
$ deno -RWNE --env-file chat.ts "Explanation must be in Japanese" maid.png
Response has been written to output.md.
output.md
この画像は、アニメまたはマンガのスタイルで描かれた、可愛らしい女の子のイラストです。

### 全体の特徴

*   **主題:** 笑顔でピースサインをする、若く見える女の子。
*   **服装:** 伝統的なクラシックメイドの制服を着用しています。黒い長袖のブラウスまたはワンピースに、大きなフリルが付いた白いエプロンと、同じくフリルの付いた白いカチューシャ(ヘッドドレス)を身につけています。
*   **背景:** シンプルな白(または透過)の背景です。

### 細部の描写

*   **髪:** 短めの黒髪または濃い茶色のショートカットです。
*   **瞳:** 非常に大きく、鮮やかなルビー色(赤色)をしており、光の反射(ハイライト)が描き込まれているため、生き生きとした印象を与えています。
*   **表情:** 満面の笑みを浮かべており、口を開いて白い歯を見せています。また、両頬は赤く色づいており(チークまたは照れ顔)、元気で明るい雰囲気です。
*   **ポーズ:** 両手を顔の横で掲げ、人差し指と中指を立ててVサイン(ピースサイン)を作っています。

全体として、非常に魅力的で高品質な、アニメキャラクターのイラストです。

テキストプロンプトだけでなく画像添付もできるようにすると様々なユースケースに対応できるようになるのでおすすめです。

Discussion