Nexta Tech Blog
🤖

Semantic KernelでGeminiを使用してみた

に公開

はじめに

こんにちは!
ネクスタで開発エンジニアをしている日野岡です。

近年、生成AIは急速に進化しており、弊社システムにおいてもLLM(大規模言語モデル)を活用した機能開発が求められています。弊社の主要開発言語はC#であり、この環境に適したLLM開発フレームワークの選定が課題となっています。

一般的にLLM開発ではPythonのLangChainが広く用いられますが、C#へのネイティブ対応はありません。このため、以下の選択肢を検討しました。

  1. Dify APIの利用: Difyで構築した機能をAPI経由で呼び出す方法。
  2. Semantic Kernel: Microsoft公式のLLMフレームワーク。(GitHub)
  3. LangChain .NET: LangChainの非公式C#移植版。(GitHub)

これらの中で、公式サポートのあるSemantic Kernelは有力な候補です。
しかし、調査を進めると、以下の点が確認されました。

  • 日本語情報の不足: 現時点で、日本語による詳細な技術情報や事例が少ない状況です。
  • Gemini APIに関する情報不足: 弊社ではGoogleのGemini APIの利用も検討していますが、Semantic Kernelに関する情報の多くはOpenAIまたはAzure OpenAIを対象としており、Gemini連携に関する具体的な情報は限定的です。

これらの状況を踏まえ、Semantic KernelがC#環境でのLLM開発において実用的か、特に弊社が利用を想定しているGemini APIとの連携が可能かを具体的に検証する必要があると判断し、試してみました。

やってみた

  • ステップ1: Gemini APIキーを取得する

  • ステップ2: Visual Studioでプロジェクトを作成する

    • VSCodeではなく、Visual Studioで開発できるかどうかも弊社では大事なポイントです。
  • ステップ3: 必要なパッケージをインストール

    • Microsoft.SemanticKernel
    • Microsoft.SemanticKernel.Connectors.Google
    • 現状は、プレリリース版の様子
      • プレリリースチェックなし
        OpenAIとAzureOpenAI系しかない・・・
      • プレリリースにチェックを入れると色々出てきた
  • ステップ4: コードを作成する

    • 不穏な警告が出るが・・・

      警告メッセージ

      SKEXP0070:
      'Microsoft.SemanticKernel
      .GoogleAIKernelBuilderExtensions.
      .AddGoogleAIGeminiChatCompletion(
          Microsoft.SemanticKernel.IKernelBuilder,
          string,
          string,
          Microsoft.SemanticKernel.Connectors.Google.GoogleAIVersion,
          string?,
          System.Net.Http.HttpClient?)'
      は、評価の目的でのみ提供されています。
      将来の更新で変更または削除されることがあります。
      続行するには、この診断を非表示にします。
      
    • 将来に期待し、いったん警告を無視して進める

        string modelId = "gemini-2.0-flash";
        string apiKey = "GEMINI_API_KEY";
        
        // 1. Kernel Builderの作成
        var builder = Kernel.CreateBuilder();
        
        // 2. Gemini Chat Completionサービスの追加
        #pragma warning disable SKEXP0070
        builder.AddGoogleAIGeminiChatCompletion(modelId, apiKey);
        #pragma warning restore SKEXP0070
        
        // 3. Kernelのビルド
        var kernel = builder.Build();
        
        // 4. プロンプトの準備
        var prompt = "Semantic Kernelについて簡単に説明してください。";
        Console.WriteLine($"プロンプト: {prompt}");
        Console.WriteLine("\nGeminiからの応答:");
        Console.WriteLine("--------------------");
        
        // 5. Gemini APIの呼び出し (プロンプトの実行)
        var result = await kernel.InvokePromptAsync(prompt);
        
        // 6. 結果の表示
        Console.WriteLine(result.GetValue<string>());
        Console.WriteLine("--------------------");
        
        Console.WriteLine("\n処理が完了しました。何かキーを押すと終了します...");
        Console.ReadKey();
      
  • 成功

      プロンプト: Semantic Kernelについて簡単に説明してください。
    
      Geminiからの応答:
      --------------------
      Semantic Kernel(セマンティックカーネル)は、Microsoftが開発したオープンソースのソフトウェア開発キット(SDK)です。AIモデル(特に大規模言語モデル:LLM)をアプリケーションに簡単に統合できるように設計されています。
      
      **Semantic Kernelの主な特徴:**
      
      *   **プラグインベースのアーキテクチャ:** LLMの機能を、再利用可能な「プラグイン」として扱います。これにより、特定のタスクを実行するための様々なLLMスキルを簡単に組み合わせることができます。
      *   **セマンティック機能:** LLMの理解能力を活用して、ユーザーの意図を理解し、適切なアクションを実行します。例えば、「〇〇について調べて、メールのドラフトを作成して」といった要求に対して、自動的に必要な情報収集とメール作成を実行できます。
      *   **プランニング機能:** 複雑なタスクを複数のステップに分解し、LLMを使って最適な実行プランを自動的に生成できます。これにより、複雑なワークフローを自動化できます。
      *   **言語に依存しない設計:** C#, Python, Javaなど、複数のプログラミング言語をサポートしています。
      *   **オープンソース:** GitHub上で公開されており、誰でも自由に利用、貢献できます。
      
      **Semantic
      --------------------
      
      処理が完了しました。何かキーを押すと終了します...
    

画像からの文字列抽出も試してみる

  • ステップ1: 画像を用意(パワポの名刺のテンプレート)

  • ステップ2: コードを作成する

    // 4. プロンプトの準備
    var prompt = "この画像から全てのテキストを抽出してください。";
    Console.WriteLine($"プロンプト: {prompt}");
    Console.WriteLine("\nGeminiからの応答:");
    Console.WriteLine("--------------------");
    
    // 画像ファイルのパスを指定
    string imagePath = @"card.jpg";
    
    // 画像ファイルをバイト配列として読み込み
    byte[] imageData = File.ReadAllBytes(imagePath);
    
    // 画像データをBase64エンコード
    string base64Image = Convert.ToBase64String(imageData);
    
    // マルチモーダル入力を作成
    var arguments = new KernelArguments
    {
        ["imageBase64"] = base64Image,
        ["imageFormat"] = Path.GetExtension(imagePath).TrimStart('.').ToLower()
    };
    
    // 5. Gemini APIの呼び出し (プロンプトの実行)
    var result = await kernel.InvokePromptAsync(prompt, arguments);
    
  • 失敗
    なんじゃこりゃ・・・

    画像からテキストを抽出しました。以下の通りです。
    
    **上部:**
    
    *   第1章 3Dアバターとは?
    
    **本文:**
    
    *   近年、メタバースを筆頭に3D空間での活動が広がりを見せる中、自分自身の分身となる3Dアバターの需要が高まっています。
    *   3Dアバターとは、3D空間上でユーザー自身を表現するデジタルキャラクターのことです。2Dのアイコンやアバターに比べ、より立体的で表現力豊かなため、メタバースやVR/ARなどの没入感の高い体験をよりリアルに楽しむことができます。
    *   本章では、3Dアバターの概要や種類、利用シーンについて解説します。
    
    **下部:**
    
    *   1.  3Dアバターの概要
    *   2.  3Dアバターの種類
    *   3.  3Dアバターの利用シーン
    
    上記のテキストが画像から認識されました。
    
    // 画像ファイルのパスを指定
    string imagePath = @"card.jpg";
    
    //// 画像ファイルをバイト配列として読み込み
    byte[] imageData = File.ReadAllBytes(imagePath);
    
    // LLMに必要な役割を指示するシステムメッセージとともにチャット履歴を作成する
    var chatHistory = new ChatHistory("あなたは画像解析エンジンです。");
    
    // 画像と画像に関する質問の両方を添えて、ユーザーメッセージを追加
    chatHistory.AddUserMessage(
    [
        new TextContent("この画像から全てのテキストを抽出してください。"),
        new ImageContent(imageData, "image/jpg"),
    ]);
    
    // チャット完了サービスの取得
    var chatCompletionService = kernel.GetRequiredService<IChatCompletionService>();
    
    // チャット完了モデルを呼び出す
    var result = await chatCompletionService.GetChatMessageContentAsync(chatHistory);
    
    // 6. 結果の表示
    Console.WriteLine(result.Content);
    
  • 成功

    以下は画像から抽出されたテキストです。
    
    舞玄太郎
    Taro Maikuro
    株式会社 ○○○○○
    〒000-0000
    ○○○○○○○○○○○○○
    TEL: 00-0000-0000
    FAX: 00-0000-0000
    E-mail: taro@xxxxxxX
    Mobile: 000-0000-0000
    Company name
    http://XXXXXX_sample.aa.jp
    

感想

  • プレリリース版ではあるが、使用できる事はわかった
  • 正式版は、OpenAIとAzureOpenAIのみ
  • 次は、LangChain .NETも試したい

参考

セマンティック カーネルの概要
semantic-kernel

Nexta Tech Blog
Nexta Tech Blog

Discussion