Azure OpenAI Service 本のサンプルを Semantic Kernel で書き直す

発売時期的に Azure OpenAI Service の API を直接使っている「Azure OpenAI Service入門」ではありますが、同じことは Semantic Kernelを使って書き換えることが可能です。

もともと、Semantic Kernel は Python の LangChain の .NET版(主にC#ではありますが)なところがあって、生成AIのモデルを問わない形になっています。出版時には、OpenAI社の GPTシリーズが主流であったためのこれに揃えて Azure OpenAI Serviceを活用しているのですが、現在では Google の Gemini など他の生成AIのモデルもあり、同じプログラムでもモデルを切り替えられるのは便利…とは思うんですがどうなんでしょう?

ひとまず、APIとしてはどのAIモデルもAPIをJSON形式で呼び出すようになっているので、そのフォーマットを切り替えるだけで概ねいけそうです。違いとしては、Calling Functionのように他システムと組み合わせたいときのプレ処理・ポスト処理に係る部分でしょう。属にいうRAG(検索拡張生成)と呼ばれる部分です。「RAG」というとちょっと難しい感じもしますが、要するの画像処理のプレ処理やポスト処理にあたります。画像処理を行うときに、プレ処理として2値化やグレー処理、エンボス処理などを行いますが、それと似たような形でテキスト解釈をGPTのAPIに任せて関数をコールバックさせることができます。私の場合、GPTシリーズでしかやったことがないのですが、Gemini などの他の生成AIでも同じことができるでしょう(未確認)。

まずは簡単なところから

簡単なところで、第7章のコードを書き直してみましょう。

Microsoft.SemanticKernel パッケージを追加する

Semantic Kernel はパッケージ「Microsoft.SemanticKernel」を使うので、*.csproj を以下に書き換えます。

  <ItemGroup>
    <PackageReference Include="Microsoft.SemanticKernel" Version="1.14.1" />
  </ItemGroup>

現在のところ最新版は ver.1.14.1 になります。

実は、Microsoft.SemanticKernelパッケージは、Azure.AI.OpenAI パッケージに依存しています。なので書籍で書いたAzure.AI.OpenAIパッケージのもそのままで動くし、Semantic Kernel で書き直したものも動きます。ちなみに、Azure.AI.OpenAI パッケージは beta 版のまま ver.2 に移行しているので、ver.1 はリリース版はない…と見るんでしょうね。やっぱり(苦笑)

従来の Completion(入力候補)を呼び出す

おそらく従来型のCompletion(プロンプトから1回だけ呼び出すもの)の方法を先に示します。

using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Connectors.OpenAI;

var builder = Kernel.CreateBuilder();
builder.AddAzureOpenAIChatCompletion(
    "test-x",
    "https://sample-moonmile-openai.openai.azure.com/",
    Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY") ?? "");
var kernel = builder.Build();

最初の Kernel 部分(従来の OpenAIClientに当たるところ)を Builder パターンで作成します。

  1. CreateBuilder でビルダーを作成
  2. AddAzureOpenAIChatCompletion でチャット/入力候補用の設定を追加
  3. Build メソッドで Kernel を作成

という手順です。ここでの「test-x」は、Azure OpenAI Studio で作成したデプロイ名です。

var kernel_args = new KernelArguments(
    new OpenAIPromptExecutionSettings()
    {
        Temperature = (float)0.5,
        MaxTokens = 800,
        TopP = (float)0.95,
        FrequencyPenalty = 0,
        PresencePenalty = 0,
    });

温度や最大トークンなどは、OpenAIPromptExecutionSettings で作成します。先に作成した Kernel に渡すために、KernelArguments でくるんでおきます。このあたり、KernelArguments 内で色々と切り替える(プロンプトテンプレートとか)のですが、ひとまず OpenAI のチャットか入力候補を試したいときはこれで十分です。

Console.WriteLine("通常のプロンプト") ;
var result = await kernel.InvokePromptAsync(
    """
    Azure OpenAIについて詳しく説明してください。
    """,
    kernel_args
    );

Console.WriteLine(result.GetValue<string>());

InvokePromptAsync でプロンプトを呼び出します。

各種パラメータがデフォルト値のままでいい場合は、kernel_args は追加しなくて構いません。応答は、GetValue で string 型にキャストしています。

結果

stream で出しているわけではないので応答が長いのですが、こんな感じで AI から応答が返ってきます。

文章が途中で途切れてしまっているのは、トークン数を800に制限したためで、チャット型式にして「続き」のように要求するか、最大トークン数をもう少し大きめにしておきます。

このあたりの詳しいところは書籍の第7章に書いてあります。

サンプルコードはこちら。ブランチを SemanticKernel にして取得してください。

https://github.com/moonmile/openai-samples/tree/SemanticKernel

カテゴリー: 開発 パーマリンク