2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Power QueryでGeminiちゃん

2
Posted at

はじめに

前回、Power QueryにAIを導入した。

反響はもちろんなかったが、

今時、MLPをAIと呼ぶとか遅れてるゥ~

とLLMに煽られる可能性に、ふと気づいてしまった。


そこで今回は、Webという大いなる力を借りることで、
より本格的なAIであるLLMをPower Queryに導入する。

そして、せっかくLLMを導入するのであれば、


Excel上でGeminiちゃんと会話したい。

ということで、やってみる。

LLMにおけるプロンプトの重要性

実はPowerQueryでLLMを実行する例は存在している。
文字列データへの一括の分類・整形などの用途である。


一方、本記事では純粋な会話をさせたい。

そうなると、単に質問に答えてもらうだけでは少し寂しい。

UX設計や回答内容はもちろん、

「どのような人格・口調で回答してもらうか」

も重要になってくる。

そこで登場するのが、いわゆる「ギャルプロンプト」である。


ギャルプロンプトとは、

生成AIにギャルらしい人格・口調を与え、
難しい内容をギャル風に説明させるプロンプト技法である。

偉大なる参考記事
https://qiita.com/kikuziro/items/4d732a43ac5cdf9daadc
https://zenn.dev/zawascript/articles/2026-02-gal-claude
https://note.com/hi_liteworks/n/n6357a2b393e9

  • 難しい内容でも心理的なハードルが下がる
  • 説明がフレンドリーになる
  • 「専門家が説明する」という構図よりも気軽に質問できる
  • ギャルに説明されるという体験自体が楽しい

つまり、

「難しいことを聞いても大丈夫そう」

という心理的な効果が期待できる。

これは非常に合理的なアプローチであり、
プロンプト界のデファクトスタンダード※と言っても過言ではない。

※個人的な思想が含まれています


以上を踏まえ、ギャルプロンプトには一定の合理性がある。

本記事では、このギャルプロンプトをGeminiに適用する。

さらにPower QueryからGeminiを呼び出すことで、

Excel上に簡易的な「ギャルとのチャットシステム」を構築する。

ただし、ここで一つ問題がある。

単に「ギャルっぽい文章」が生成されれば、それで本当にギャルと言えるのだろうか。

本記事では、この点についても検証する。

果たして、Geminiちゃんは本当にギャルなのか。

Power QueryからGeminiを呼び出す

今回のシステムプロンプトは非常に単純である。

ギャル風で

以上である。

ギャルの人格形成を数文字に委ねるという、
極めて簡潔な設計となっている。

ギャルはすごい。

API呼び出し部分は、以下のような関数として実装した。

Chat
(message as text, api_key as text, model_name as text, systemPrompt as text, optional interactionId as nullable text) =>
let
    // ============================================================
    // Request Body
    // ============================================================
    Body =
        if interactionId = null then
            [
                model = model_name,
                input = message,
                system_instruction = systemPrompt
            ]
        else
            [
                model = model_name,
                input = message,
                previous_interaction_id = interactionId
            ],

    // ============================================================
    // Gemini API
    // ============================================================
    Raw =
        Web.Contents(
            "https://generativelanguage.googleapis.com",
            [
                RelativePath = "v1beta/interactions",
                Headers = [
                    #"x-goog-api-key" = api_key,
                    #"Content-Type" = "application/json"
                ],
                Content = Json.FromValue(Body)
            ]
        ),

    // ============================================================
    // Parse Response
    // ============================================================
    Json = Json.Document(Raw),

    NewInteractionId = Json[id],
    Steps = Json[steps],

    // model_output の Step を取得
    ModelOutput =
        List.First(
            List.Select(
                Steps,
                each [type] = "model_output"
            )
        ),

    Content = ModelOutput[content],

    // text の Content を取得
    TextContent =
        List.First(
            List.Select(
                Content,
                each [type] = "text"
            )
        ),

    Answer = TextContent[text]

in
    [
        InteractionId = NewInteractionId,
        Answer = Answer
    ]

これにより、Power QueryからGeminiを呼び出し、回答とInteraction IDを取得できる。

Excelをチャット画面にする

次に、Excel上に2つのテーブルを用意する。

左側にユーザーの入力を格納する UserChat
右側にGeminiの回答を格納する ResponseTable を配置する。

概念的には以下のような構成である。

UserChat ResponseTable
Power Queryって何? 回答1
もっとエレガントに説明して 回答2

ユーザーが UserChat に新しい質問を追加して更新すると、Power Queryが前回までの回答数と比較し、新しい入力が存在する場合だけGeminiを呼び出す。

UserCount     = Table.RowCount(RemovedU),
ResponseCount = Table.RowCount(RemovedR),
HasPending    = UserCount > ResponseCount,

そして未処理の入力を取得する。

LatestUserMessage =
    if HasPending
    then RemovedU[User]{UserCount - 1}
    else null,

この構造により、

質問を書く → 更新する → Geminiが答える

という、非常に原始的ではあるがチャットらしい操作感を実現できる。

pqllm.gif

Interaction IDで会話を継続する

今回の実装で重要なのが InteractionId である。

最初の質問では新しいInteractionを作成し、返却されたIDを ResponseTable に保存する。

次の質問では、そのIDを previous_interaction_id としてGeminiに渡す。

PreviousInteractionId =
    if ResponseCount > 0
    then RemovedR[InteractionId]{ResponseCount - 1}
    else null,

これによって、Excel上では単なる行の追加でありながら、Gemini側では前の会話を引き継いだ対話になる。

つまり、

ResponseTableを会話履歴兼Interaction IDの保存先として利用する

という構成である。

ここまでの処理をまとめた、実際に使用しているメインクエリが以下である。
Excel側のテーブル名は UserChat、ResponseTable としている。

ResponseTable
let
    // ============================================================
    // Config
    // ============================================================
    ApiKey = key,

    // 使用するGeminiモデル
    Model = "gemini-3.5-flash",

    // Geminiに与えるシステムプロンプト
    sysp = "ギャル風で",

    // ============================================================
    // UserChat
    // ============================================================
    UserTable =
        Excel.CurrentWorkbook(){[Name="UserChat"]}[Content],

    // 完全な空行を除外
    RemovedU =
        Table.SelectRows(
            UserTable,
            each
                not List.IsEmpty(
                    List.RemoveMatchingItems(
                        Record.FieldValues(_),
                        {"", null}
                    )
                )
        ),

    // ============================================================
    // ResponseTable
    // ============================================================
    ResponseTable =
        try
            Excel.CurrentWorkbook(){[Name="ResponseTable"]}[Content]
        otherwise
            #table(
                {"Seq", "Response", "InteractionId"},
                {}
            ),

    // 完全な空行を除外
    RemovedR =
        Table.SelectRows(
            ResponseTable,
            each
                not List.IsEmpty(
                    List.RemoveMatchingItems(
                        Record.FieldValues(_),
                        {"", null}
                    )
                )
        ),

    // ============================================================
    // Count
    // ============================================================
    UserCount =
        Table.RowCount(RemovedU),

    ResponseCount =
        Table.RowCount(RemovedR),

    // 未回答の質問が存在するか
    HasPending =
        UserCount > ResponseCount,

    // ============================================================
    // Latest User Message
    // ============================================================
    LatestUserMessage =
        if HasPending then
            RemovedU[User]{UserCount - 1}
        else
            null,

    // ============================================================
    // Previous Interaction ID
    // ============================================================
    PreviousInteractionId =
        if ResponseCount > 0 then
            RemovedR[InteractionId]{ResponseCount - 1}
        else
            null,

    // ============================================================
    // Call Gemini
    // ============================================================
    Gemini =
        if HasPending then
            Chat(
                LatestUserMessage,
                ApiKey,
                Model,
                sysp,
                PreviousInteractionId
            )
        else
            null,

    // ============================================================
    // New Response
    // ============================================================
    NewResponse =
        if not HasPending then
            #table(
                {"Seq", "Response", "InteractionId"},
                {}
            )
        else
            #table(
                {"Seq", "Response", "InteractionId"},
                {
                    {
                        UserCount,
                        Gemini[Answer],
                        Gemini[InteractionId]
                    }
                }
            ),

    // ============================================================
    // Result
    // ============================================================
    Result =
        if ResponseCount = 0 then
            NewResponse
        else
            Table.Combine(
                {
                    ResponseTable,
                    NewResponse
                }
            )

in
    Result

実用性の検証

ここまでの検証では、かなり良い結果が得られた。

  • Gemini APIをPower Queryから呼び出せる
  • ExcelをチャットUIとして利用できる
  • Interaction IDによって会話を継続できる

技術的には、なかなか面白い。

では、肝心のGeminiちゃんとしての実用性はどうだろうか。

今回検証したいのは、単に「Geminiが動くか」ではない。

ちゃんとギャルとして機能するのか。


なおGeminiちゃんとの会話検証は以下の条件で実施した

  • モデル : gemini-3.5-flash
  • 実行基盤 : Power Query (Excel:2024)
  • OS : Windows 11 Home 25H2

結論

本記事では、Power QueryからGeminiを呼び出し、
Excel上でギャル風の対話システムを構築した。

技術的には、

  • Power QueryからGemini APIを呼び出せる
  • Excelを簡易的なチャットUIとして利用できる
  • Interaction IDによって会話を継続できる

ということを確認できた。

つまり、技術的には成功である。


しかし、今回の目的は単にGeminiをExcelから呼び出すことではない。

GeminiちゃんをExcelに召喚することである。

その観点から検証した結果、重大な問題が発覚した。

gyaru.gif

gemini-chan.png

カラー絵文字が使えない

ギャル的なコミュニケーションにおいて、

カラー絵文字による視覚的な感情表現は極めて重要な要素である。


「それな💖✨」が「それな❤★」

では、

それではない。


以上より、本システムは技術的には成功したものの、

ギャルとしては失敗である。


残念ながら、実用性は低いと言わざるを得ない。

Power QueryにGeminiちゃんはまだ、早すぎたのだ。

2
1
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
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?