アイデアから実装へ:画像説明のためのカスタムAI関数の作成

2025年12月19日著者:Denis

AIエージェントを使用すると、標準のエディターアクションを超えて、ニーズに合わせたカスタム関数を追加できます。この投稿では、describeImage関数の作成について説明し、それが画像をタイトル、キャプション、アクセシブルなaltテキストに変換する方法をご紹介します。

From idea to implementation: Creating a custom AI function for image description

アイデア

目標はシンプルです。画像を選択し、短い指示を提供し、必要な場所に正確に配置された生成されたテキストを受け取ります。この関数は、画像のタイトル、キャプション、altテキストなどの一般的な使用例をサポートし、明示的なプロンプトに依存することでユーザーの意図についての仮定を回避します。

関数の設計

関数をONLYOFFICE AIエンジンで利用可能にするために、RegisteredFunctionとして定義されました。この定義では、関数名、予想されるパラメーター、および意図された使用法を示すサンプルプロンプトを指定します。

  let func = new RegisteredFunction({
    name: "describeImage",
    description:
      "Allows users to select an image and generate a meaningful title, description, caption, or alt text for it using AI.",
    parameters: {
      type: "object",
      properties: {
        prompt: {
          type: "string",
          description:
            "instruction for the AI (e.g., 'Add a short title for this chart.')",
        },
      },
      required: ["prompt"],
    },
    examples: [
      {
        prompt: "Add a short title for this chart.",
        arguments: { prompt: "Add a short title for this chart." },
      },
      {
        prompt: "Write me a 1-2 sentence description of this photo.",
        arguments: {
          prompt: "Write me a 1-2 sentence description of this photo.",
        },
      },
      {
        prompt: "Generate a descriptive caption for this organizational chart.",
        arguments: {
          prompt:
            "Generate a descriptive caption for this organizational chart.",
        },
      },
      {
        prompt: "Provide accessibility-friendly alt text for this infographic.",
        arguments: {
          prompt:
            "Provide accessibility-friendly alt text for this infographic.",
        },
      },
    ],
  });

この定義には2つの目的があります。

  1. ONLYOFFICE AIエンジンに関数の機能と予想される入力を通知します。
  2. AIとエンドユーザーの両方をガイドする使用例を提供します。

ロジックの実装

callメソッドには、ユーザーが関数を呼び出したときに実行される実際の機能が含まれています:

  1. 選択した画像を取得GetImageDataFromSelectionを使用して、ドキュメントから画像を取得します。また、プレースホルダー画像をフィルタリングして、意味のあるAI結果を保証します。
  2. AIプロンプトを構築—ユーザーの指示を選択した画像のコンテキストと組み合わせて、明確で実行可能なプロンプトを作成します。
  3. AIモデルの互換性を確認—ビジョン対応モデル(GPT-4VやGeminiなど)のみが画像を処理できます。現在のモデルが画像を処理できない場合は、ユーザーに警告します。
  4. AIにリクエストを送信chatRequestを介して画像とプロンプトをAIエンジンに送信し、生成されたテキストをリアルタイムで収集します。
  5. AI生成テキストをドキュメントに挿入—関数は画像が選択されているかどうかを検出し、結果を適切に挿入します。
  6. エラー処理—関数は、欠落している画像、サポートされていないモデル、または予期しないAIエラーを適切に処理し、ユーザーに明確なメッセージを提供します。

1. 選択した画像を取得

ONLYOFFICEでは、ドキュメント内の画像は図形と呼ばれます。ユーザーが選択した画像を処理するために、ONLYOFFICEプラグインAPIを使用します:

    let imageData = await new Promise((resolve) => {
        window.Asc.plugin.executeMethod(
          "GetImageDataFromSelection",
          [],
          function (result) {
            resolve(result);
          }
        );
      });
  • GetImageDataFromSelectionは、現在選択されている画像をbase64エンコードされた文字列として抽出するONLYOFFICEプラグインメソッドです。
  • 結果は通常、次のようなオブジェクトです:
{
  "src": "data:image/png;base64,iVBORw0K...",
  "width": 600,
  "height": 400
}

このsrc文字列には、画像データを受け入れるAIモデルに直接送信できるBase64形式の画像全体が含まれています。

主な考慮事項:

  • 画像が選択されていない場合、imageDatanullです。
  • 一部のユーザーは、プレースホルダーグラフィックスまたは空の長方形を選択する場合があります。たとえば、ONLYOFFICEは空の画像のプレースホルダーとして小さな白い長方形を使用します。base64表現と比較してフィルタリングします:
   const whiteRectangleBase64 =   "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==";
      if (imageData.src === whiteRectangleBase64) {
        console.log("describeImage: Image is white placeholder");
        await insertMessage("Please select a valid image first.");
        return;
      }

2. AI用の画像の準備

AIモデルは、URLまたはbase64エンコードされたデータとして画像を期待し、通常はimage_urlのようなフィールドにあります。関数では、構造化された配列でテキストプロンプトとともに画像を渡します:

   let messages = [
        {
          role: "user",
          content: [
            { type: "text", text: argPrompt },
            {
              type: "image_url",
              image_url: { url: imageData.src, detail: "high" },
            },
          ],
        },
      ];
  • type: “text”はプロンプトの指示を提供します(例:「説明的なキャプションを追加」)。
  • type: “image_url”には画像自体が含まれます。AIエンジンは画像を分析し、関連するテキストを生成できます。
  • detail: “high”は、モデルが画像をフル解像度で処理するためのオプションのヒントです。

変換ロジック:

  1. ONLYOFFICEはsrcbase64文字列として提供します。
  2. AIモデルは、base64データまたはアクセス可能なURLのいずれかを受け入れることができます。ここでは、外部サーバーにアップロードすることを避けるために、base64を直接使用します。
  3. AIのチャットリクエストAPIと互換性のあるオブジェクトに画像をラップします。この構造により、単一のメッセージで複数のコンテンツタイプが可能になります。

3. AIへのリクエストの送信

画像とプロンプトが構造化されたら、ONLYOFFICE AIプラグインエンジンを使用します:

     let requestEngine = AI.Request.create(AI.ActionType.Chat);
      await requestEngine.chatRequest(messages, false, async function (data) {
        console.log("describeImage: chatRequest callback data chunk", data);
        if (data) {
          resultText += data;
        }
      });
  • AI.ActionType.Chatは、プロンプトと画像が一緒に分析されるチャットスタイルのメッセージの送信を可能にします。
  • コールバックは、AI応答テキストのチャンクをリアルタイムで収集します。
  • 送信する前に、選択したAIモデルがビジョンをサポートしているかどうかを確認します。特定のモデル(GPT-4V、Gemini)のみが画像を処理できます:
 const allowVision = /(vision|gemini|gpt-4o|gpt-4v|gpt-4-vision)/i;
      if (!allowVision.test(requestEngine.modelUI.name)) {
        console.warn("describeImage: Model does not support vision", requestEngine.modelUI.name);
        await insertMessage(
          "⚠ This model may not support images. Please choose a vision-capable model (e.g. GPT-4V, Gemini, etc.)."
        );
        return;
      }

4. AI出力をドキュメントに挿入

AI出力を受け取った後、テキストをONLYOFFICEドキュメントに挿入する必要があります。ロジックは2つのケースを処理します:

  1. 画像が選択されている:画像の後に段落を挿入します。
  2. 画像が選択されていない:現在のカーソル位置の後に段落を挿入します。
async function insertMessage(message) {
      console.log("describeImage: insertMessage called", message);
      Asc.scope._message = String(message || "");
      await Asc.Editor.callCommand(function () {
        const msg = Asc.scope._message || "";
        const doc = Api.GetDocument();
        const selected =
          (doc.GetSelectedDrawings && doc.GetSelectedDrawings()) || [];
        if (selected.length > 0) {
          for (let i = 0; i < selected.length; i++) {
            const drawing = selected[i];
            const para = Api.CreateParagraph();
            para.AddText(msg);
            drawing.InsertParagraph(para, "after", true);
          }
        } else {
          const para = Api.CreateParagraph();
          para.AddText(msg);
          let range = doc.GetCurrentParagraph();
          range.InsertParagraph(para, "after", true);
        }
        Asc.scope._message = "";
      }, true);
  • Api.GetSelectedDrawings()は、現在選択されている画像(図形)を取得します。
  • Api.CreateParagraph()は、新しい段落オブジェクトを作成します。
  • InsertParagraph(para, “after”, true)は、生成されたテキストを選択した画像または段落の直後に挿入します。
  • これにより、シームレスな統合が保証されます:AI出力は常に適切なコンテキストに表示されます。

5. エッジケースとエラーの処理

いくつかの課題には特別な注意が必要でした:

  • 画像が選択されていない—ユーザーに画像を選択するよう促します。
  • サポートされていないAIモデル—リクエストを送信する前にユーザーに警告します。
  • 空のAI応答—AIが説明を生成できなかったことをユーザーに通知します。
  • 予期しないエラー—ネストされたtry/catchを使用して、進行中のエディターアクションを安全に終了します:
    } catch (e) {
      try {
        await Asc.Editor.callMethod("EndAction", ["GroupActions"]);
        await Asc.Editor.callMethod("EndAction", [
          "Block",
          "AI (describeImage)",
        ]);
      } catch (ee) {
       
      }

これにより、AIまたはプラグインが操作の途中で失敗した場合でも、ドキュメントは安定した状態を保ちます。

最終結果

From idea to implementation: Creating a custom AI function for image description

From idea to implementation: Creating a custom AI function for image description

describeImage関数は、カスタム関数が小さいながらも大きな影響を与える方法でAIエージェントを拡張できることを示しています。明確なプロンプトとエディター対応ロジックを組み合わせることで、一般的なAIアクションではなく、実際のワークフローに直接適合する機能を構築できます。

AIエージェントの機能をカスタマイズするために、独自のカスタム関数を作成してみてください。何か便利なものを構築した場合は、お問い合わせページを介して共有してください。

ONLYOFFICEの無料アカウントを登録する

オンラインでドキュメント、スプレッドシート、スライド、フォーム、PDFファイルの閲覧、編集、共同作業