3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

@TheGateBreaker さんが、掲載されている絵が素敵だなあと思いました。それで自分でも作ってみたくなり、さくらのAI Engine x Claude Code で聞いてみました。

さくらのAI Engine x Claude Code

Claude CodeをさくらのAI Engineと組み合わせて使う方法です。
公式のコラムがわかりやすいです。


2026/07/28現在、preview/Kimi-K2.7-Codeも提供されています。
使うしかありません。

claude --model preview/Kimi-K2.7-Code

インプットにした図

token消化ではなく、記事のご縁を可視化!さくらのAI Engine RAGでチャレンジ参加記事の相関図を描いてみた🌸の記事に掲載されている図をインプットにさせていただいた。

Claude Codeへのプロンプトと回答

プロンプト

Issue809_jpn_fig01_ja.webp

この絵をGeminiやChatGPTに描いてもらいたいと思います。
同じような絵ができあがるようにプロンプトを提案してください。

回答

回答は2つ作ってくれました。

🎨 基本版プロンプト

手描きの可愛らしいインフォグラフィックを作成してください。
白背景に、マーカーと色鉛筆で描いたような柔らかいタッチです。

テーマ:「RAGを回答生成ではなく、記事同士の意味的な近さの計測に使う」

構成:
1. 上部に大きなタイトル「*token*消化ではなく、記事のご縁を可視化!」
   「token」は青、「消化ではなく、記事のご縁を可視化!」は赤で。
   その下にサブタイトル「*RAG*を『回答生成』ではなく『近さの計測』に使う」

2. 横に3つのパネルを並べて、ワークフローを示す
   - パネル1(青):「1 参加記事を集める」
     Qiitaの参加記事群から、記事A・B・Cのカードを集める様子
   - パネル2(緑):「2 *RAG*で意味の近さを測る」
     記事を入力する可愛いロボット型の機械「さくらのAI Engine RAG」
     虫眼鏡を持ち、*multilingual-e5-large*と書かれている
   - パネル3(青):「3 相関図として描く」
     記事A・B・Cがノードとなり、0.04 / 0.06 / 0.10 などの数字がついたエッジで結ばれたネットワーク図

3. 下部に赤いリボン
   「いいね数では見えない『話題のハブ』が見える」

4. 装飾:桜の花びら、可愛い桜のキャラクター、虫眼鏡のキャラクター

5. 一番下にステップバー
   「収集 22件 → 条件通過 12件 → エッジ 15本」

全体的に親しみやすく、ポップで、技術的な内容をやさしく説明する雰囲気。

📝 詳細版プロンプト

以下の仕様で、手描き風の日本語インフォグラフィックを作成してください。

【全体の雰囲気】
- 白背景、マーカー・クレヨン・色鉛筆で描いたような温かみのある質感
- 線は少しガタついた手描き風、角は丸みを帯びる
- ポップで親しみやすい、技術ブログの解説図のようなスタイル
- 桜モチーフ(花びら、可愛い桜のキャラクター)を散りばめる

【上部:タイトルエリア】
- メインタイトル:「*token*消化ではなく、記事のご縁を可視化!」
  - *token*は水色、それ以降は赤色
  - 手書き風の太字フォント
- サブタイトル:「*RAG*を『回答生成』ではなく『近さの計測』に使う」
  - *RAG*は緑色、カギ括弧内は黒

【中央:3つのパネル(横並び)】
各パネルは水色や緑色の点線・丸角の枠で囲む。左上に白抜きの丸い数字アイコン(1,2,3)。

パネル1「参加記事を集める」(青色系)
- 左に「Qiita参加記事群」と書かれた雲形の吹き出し
- 下にデータベースのような円筒アイコン
- 右側に記事A・B・Cの3枚のカード
  - それぞれに</>、{}、>_のようなコードアイコン
  - カードの下に小さなハートマーク
- 左下に虫眼鏡を持った可愛い桜のキャラクター

パネル2「*RAG*で意味の近さを測る」(緑色系)
- 左に3枚の文書アイコンから青い矢印が右へ向かう
- 中央に「さくらの*AI Engine RAG*」と書かれた、キャスター付きの可愛いロボット型機械
  - 顔がついていて、虫眼鏡を持っている
  - 機械の下に「*multilingual-e5-large*」と注釈
- 下に吹き出し「検索で得た距離を、記事同士の意味的な近さとして読む」
  - 「意味的な近さ」の部分は赤色で強調

パネル3「相関図として描く」(青色系)
- 3つのノード「参加記事A」「参加記事B」「参加記事C」を三角形配置
  - 各ノードにコードアイコンを配置
- ノード間を青い線で結び、線の近くに距離の数値(0.04、0.06、0.10)を記載
- 下に吹き出し「回答を作るのではなく、関係性を描く」
  - 「関係性を描く」は赤色で強調
- 右下に虫眼鏡のキャラクター

【下部:リボンとステップバー】
- 赤いリボン帯に白抜き文字:
  「いいね数では見えない『話題のハブ』が見える」
  - 「話題のハブ」は黄色で強調
- その下に水色の丸角長方形のステップバー:
  - クリップボードアイコン「収集 22件」
  - 緑の矢印 → シールドチェックアイコン「条件通過 12件」
  - 緑の矢印 → ネットワークアイコン「エッジ 15本」
  - 数字は手書き風の大きな文字

【その他】
- 桜の花びらを画面の上下に散りばめる
- 全体的にバランスよく配置し、可読性を高く
- 日本語テキストを正確に描画してください

作図しました

ツール 基本版プロンプト 詳細版プロンプト
Gemini(3.6 Flash) image.png image.png
ChatGPT(5.5最速) image.png image.png

思っていた以上に近いものができました :tada:

プログラム化

画像を読み込んでプロンプトを作ってもらうプログラムを作りました。
プログラムはもちろん、さくらのAI Engine(preview/Kimi-K2.7-Code)に作ってもらいました 🌸

generate_image_prompt.py
#!/usr/bin/env -S uv run --script
# /// script
# dependencies = ["openai>=2.0.0"]
# ///
"""v1/chat/completions で画像入力 + テキスト送信し、
同じような絵を描くためのプロンプトを SSE ストリーミング (stream=True) で受け取るサンプル。

使い方:
    uv run generate_image_prompt.py
    uv run generate_image_prompt.py --image path/to/image.webp

必要な環境変数:
    SAKURA_AI_ENGINE_ACCOUNT_TOKEN
"""

import argparse
import base64
import os
from pathlib import Path

from openai import OpenAI

# ── 設定 ──────────────────────────────────────────
BASE_URL = "https://api.ai.sakura.ad.jp/v1"
API_KEY = os.environ.get("SAKURA_AI_ENGINE_ACCOUNT_TOKEN", "")

# 今回使用するモデル
DEFAULT_MODEL = "preview/Kimi-K2.7-Code"

# デフォルトの入力画像(このリポジトリ内の WebP)
DEFAULT_IMAGE = Path(__file__).parent / "Issue809_jpn_fig01_ja.webp"


# ── 関数 ──────────────────────────────────────────
def get_client() -> OpenAI:
    """OpenAI 互換クライアントを初期化して返す。"""
    if not API_KEY:
        raise RuntimeError(
            "環境変数 SAKURA_AI_ENGINE_ACCOUNT_TOKEN が設定されていません。"
            "さくらのAI Engineのアクセストークンを設定してください。"
        )
    return OpenAI(base_url=BASE_URL, api_key=API_KEY)


def encode_image(path: str) -> str:
    """画像ファイルを base64 エンコードして data URI を返す。"""
    p = Path(path)
    data = p.read_bytes()
    b64 = base64.b64encode(data).decode("utf-8")
    ext = p.suffix.lower().lstrip(".")
    if ext == "jpg":
        ext = "jpeg"
    return f"data:image/{ext};base64,{b64}"


def build_messages(image_url: str) -> list[dict]:
    """画像を入力とし、同じような絵を描くためのプロンプトを求めるメッセージを組み立てる。"""
    prompt_instruction = (
        "添付した画像と同じような絵を、Gemini や ChatGPT に描いてもらいたいです。\n"
        "同じ雰囲気・構成・スタイルで再現できるよう、具体的なプロンプトを日本語で提案してください。\n"
        "必要に応じて、レイアウト、配色、キャラクター、テキスト、図の構造などを詳しく説明してください。"
    )
    return [
        {
            "role": "user",
            "content": [
                {"type": "text", "text": prompt_instruction},
                {"type": "image_url", "image_url": {"url": image_url}},
            ],
        },
    ]


# ── メイン ─────────────────────────────────────────
def main() -> None:
    parser = argparse.ArgumentParser(
        description="画像を入力として、同じような絵を描くためのプロンプトを生成します。"
    )
    parser.add_argument(
        "--image",
        type=Path,
        default=DEFAULT_IMAGE,
        help="入力画像のパス (デフォルト: Issue809_jpn_fig01_ja.webp)",
    )
    parser.add_argument(
        "--model",
        default=DEFAULT_MODEL,
        help=f"使用するモデル (デフォルト: {DEFAULT_MODEL})",
    )
    args = parser.parse_args()

    client = get_client()
    image_path: Path = args.image

    if not image_path.exists():
        print(f"画像ファイルが見つかりません: {image_path}")
        print("先に画像を用意するか、--image で正しいパスを指定してください。")
        return

    image_url = encode_image(str(image_path))
    messages = build_messages(image_url)

    print(f"モデル: {args.model}")
    print(f"エンドポイント: POST {client.base_url}chat/completions (stream=True)")
    print(f"画像: {image_path}")
    print("-" * 40)

    # stream=True で SSE ストリーミングレスポンスを取得
    stream = client.chat.completions.create(
        model=args.model,
        messages=messages,
        max_tokens=4096,
        temperature=0.4,
        stream=True,
    )

    finish_reason = None

    # リアルタイムでトークンを逐次表示
    for chunk in stream:
        if chunk.choices:
            choice = chunk.choices[0]
            if choice.delta and choice.delta.content:
                print(choice.delta.content, end="", flush=True)
            if choice.finish_reason is not None:
                finish_reason = choice.finish_reason

    print()  # 改行
    print("-" * 40)

    # finish_reason による安全なハンドリング
    if finish_reason == "length":
        print("⚠️  [警告] レスポンスが max_tokens の上限に達したため途中で切れました。")
    elif finish_reason == "stop":
        print("✅ レスポンスは正常に完了しました (finish_reason: stop)。")
    elif finish_reason:
        print(f"ℹ️  完了理由 (finish_reason): {finish_reason}")


if __name__ == "__main__":
    main()

uv run generate_image_prompt.py で実行できます。

実行結果

手描きマーカー風の可愛らしいインフォグラフィックを1枚描いてください。
白背景、全体に桜の花びらがちらばる春らしい雰囲気にしてください。
線は少しゆがんだ手書き風、角丸の囲み線、太めの色付き矢印を使ってください。

【全体構成】
・トップに大きなタイトル
・中央に横並びの3ステップ(①②③)
・下部に赤いリボン風バナー
・その下に「収集→条件通過→エッジ」の数値フローを横一列に配置
アスペクト比は横長(16:9程度)でお願いします。

【配色】
・タイトルの一部:青(#2E7AD1)、赤(#E63946)
・ステップ①の枠:青系
・ステップ②の枠:緑系
・ステップ③の枠:青系
・リボン:赤(#D62828)
・文字は黒または濃い紺、ポイント部分は赤やオレンジ
・桜:ピンク(#F4A6C3)

【テキスト】
トップタイトル:
「*token*消化ではなく、記事のご縁を可視化!」
サブタイトル:
「*RAG*を『回答生成』ではなく『近さの計測』に使う」

ステップ①「参加記事を集める」
・左側に「Qiita 参加記事群」と書いた雲の吹き出し
・その下にデータベースの円筒アイコン
・右側に3枚の参加記事カードを縦に並べる
 - 参加記事A:青い「</>」アイコン、ハートマーク
 - 参加記事B:緑い「{}」アイコン、ハートマーク
 - 参加記事C:オレンジの「>_」アイコン、ハートマーク
・左下に桜のキャラクター(笑顔で虫眼鏡を持っている)

ステップ②「*RAG*で意味の近さを測る」
・中央に「さくらの *AI Engine RAG*」と書かれた、顔と虫眼鏡が付いた白い箱型マシン
・マシンの下に小さく「*multilingual-e5-large*」と注釈
・マシンの左側に3枚の文書アイコン(①の記事A/B/Cと同じ色のアイコン)を配置し、緑の矢印でマシンに向かわせる
・マシンの下に吹き出し:
「検索で得た距離を、記事同士の意味的な近さとして読む」
(「意味的な近さ」は赤文字で強調)

ステップ③「相関図として描く」
・3つのノードを三角形配置
 - 上:参加記事A(青い</>アイコン)
 - 左下:参加記事B(緑い{}アイコン)
 - 右下:参加記事C(オレンジの>_アイコン)
・ノード間を青い線で結び、線の近くに距離数値を書く
 - A-B:0.04
 - A-C:0.06
 - B-C:0.10
・右下に虫眼鏡のキャラクターと吹き出し:
「回答を作るのではなく、関係性を描く」
(「関係性を描く」は赤文字で強調)

【下部バナー】
赤いリボン/帯の中に大きく:
「いいね数では見えない『話題のハブ』が見える」
(「話題のハブ」は黄色文字で強調)

【最下部の数値フロー】
左から右へ横一列にアイコン+文字+数字を並べる
・文書アイコン → 「収集 22 件」
・緑のチェック盾アイコン → 「条件通過 12 件」
・ネットワーク/エッジアイコン → 「エッジ 15 本」
数字(22, 12, 15)は大きく、色はそれぞれ青、緑、青で。

【全体的な雰囲気】
・落書き帳やホワイトボードに描いたような親しみやすさ
・情報量は多いが整理されている
・キャラクターはシンプルで可愛らしく、桜モチーフ
・テキストは読みやすく、重要語は色や大きさで強調

作ってもらったプロンプトをGeminiとChatGPTに流し込みました

ツール
Gemini(3.6 Flash) image.png
ChatGPT(5.5最速) image.png

まとめ

絵を言葉にするのも、言葉を絵にするのも、みんな(AIも人間も)上手。

今回やったことを一言でいうと、「絵→プロンプト化→AIに再投入→絵」を、さくらのAI Engine(preview/Kimi-K2.7-Code)にやらせてみた、というだけの話です。入力も出力も画像なのに、間に挟まっているのは全部言葉。当たり前ですが、地味に面白い構造だなと思いました。

さて、この記事を作るにあたり、今月の中ごろから、さくらのAI Engineを使わせていただいています!
いろいろな用途で、約1,500回くらいは使わせていただきました。3,000回はまだまだ遠いですが、2兆個のアイデアを試していきます!

スクリーンショット 2026-07-29 0.21.26.png

token消化ではなく、$\huge{闘魂昇華}$。無料枠を、闘って、磨いて、使い切りますッ!!!

ai-back.png


TokenをTokonへ

AIが扱うのは、Token。

\mathrm{Token}
-
\mathrm{見\ (Ken)}
+
\mathrm{魂\ (Kon)}
=
\mathrm{Tokon\ (闘魂)}

現段階の生成AIは、突き詰めればベクトルの数理遊びである。

どのモデルが賢い、速い、勝つ。
外から眺め、比べ、論評するだけでは、まだTokenだ。

だから「見(Ken)」を引く。

見る側から、使う側へ。
そこに目的と意味を与え、執念を持ち込み、魂を込めるのは人間である。

token消化ではなく、$\huge{闘魂昇華}$ :fire:
Don't just consume Tokens. Forge them into Tokon.

image.png

image.png

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?