ROMANCE DAWN for the new world

Microsoft Azure を中心とした技術情報を書いています。

Azure OpenAI Service で Semantic Kernel を使ってみた

前回の記事では、Azure OpenAI Client Library を使って Azure OpenAI で遊んでみました。
gooner.hateblo.jp
今回は、Semantic Kernel を使って、Azure OpenAI の要約を試してみます。

Semantic Kernel とは

Semantic Kernel は、Azure OpenAI などの AI サービスと C# や Python などのプログラミング言語を簡単に組み合わせることができる OSS の SDK です。
AI アプリケーションでプロンプト設計が重要なことは言うまでもありませんが、本格的に作りこむとなると複数のプロンプトを部品化して順番に呼び出すオーケストレーション的な設計が必要となり、Semantic Kernel のような LLM と C# を統合して扱える SDK が使いたくなります。
learn.microsoft.com

先日の Build 2003 で、Copilot(AI アプリケーション)を開発するフレームワークとして「Copilot stack」が発表されました。
qiita.com
Copilot stack の中心となる AI オーケストレーション レイヤーに Semantic Kernel を使い、複数のプロンプトを順番に呼び出すオーケストレーションを組み立て、AI アプリを作成できるようになります。

Microsoft Learn から引用

なお、Copilot stack との連携強化に伴い、Semantic Kernel で「スキル」と呼んでいた機能は「プラグイン」へリネームされています。

Semantic Kernel を使ってみる

Azure OpenAI で text-davinci-003 のモデルを使った要約を Semantic Kernel で実装してみます。.NET 7 のコンソールアプリを作り、NuGet パッケージをインストールします。

Install-Package Microsoft.SemanticKernel -Version 0.17.230629.1-preview
Install-Package Microsoft.Extensions.Configuration.Binder -Version 7.0.4
Install-Package Microsoft.Extensions.Configuration.UserSecrets -Version 7.0.0

Microsoft.Extensions.Configuration 関連の NuGet パッケージは、Azure OpenAI に接続する資格情報を管理するためにインストールしました。Managed ID を使ってもいいですが、環境によって認証が通らないケースもあるので、シンプルに .NET の UserSecrets を使います。誤って GitHub にプッシュするリスクがあるのでハードコーディングはやめましょう。

{
  "AzureOpenAISettings": {
    "Endpoint": "https://xxx.openai.azure.com/",
    "ApiKey": "xxx",
    "DeploymentName": "text-davinci-003"
  }
}

secret.json にエンドポイント、キー、モデル名を定義したら、バインドするクラスを作ります。

internal class AzureOpenAISettings
{
    public required string Endpoint { get; set; }
    public required string ApiKey { get; set; }
    public required string DeploymentName { get; set; }
}

ConfigurationBuilder を使って、secret.json を読み込んで AzureOpenAISettings クラスにバインドします。

var settings = new ConfigurationBuilder()
    .AddUserSecrets<Program>()
    .Build()
    .GetSection(nameof(AzureOpenAISettings)).Get<AzureOpenAISettings>() ?? throw new NullReferenceException();

ここで Semantic Kernel のアーキテクチャを簡単に説明しておきます。
Kernel がオーケストレーション全体の制御を行います。Kernel にロードされたプラグインやコネクタの実行順序をプランナーが決定し、パイプラインチェーンとして実行させる構造になっています。

Microsoft Learn から引用

まずは、Kernel のインスタンスを作成します。

var builder = new KernelBuilder();
builder.WithAzureTextCompletionService(settings.DeploymentName, settings.Endpoint, settings.ApiKey);
var kernel = builder.Build();

要約するプロンプトを定義し、セマンティック関数として Kernel にロードします。プラグインは使わず、パラメータを使ってプロンプトを実行させます。

// Running prompts with input parameters
Console.WriteLine("Running prompts with input parameters...");
var summarizePrompt = @"{{$input}}

One line TLDR with the fewest words.";
var summarize = kernel.CreateSemanticFunction(summarizePrompt);

要約するテキストを定義し、セマンティック関数に引数で渡して実行させます。テキストは、昨シーズンのアーセナル最終節のマッチレポートを使いました。

string text = @"
We rounded off the Premier League season with an emphatic win over Wolves, the highlight of which saw Granit Xhaka net his first brace for the club.
The Swiss midfielder took just 13 minutes of the first half to achieve the feat, with Bukayo Saka adding an excellent third before half-time to mark the week in which he pledged his future in the club in style.
We kept up the pressure in the second half and Gabriel Jesus added a fourth with a header just before the hour mark, and Jakub Kiwior bagged his first in red and white to complete the scoring, as well as a memorable campaign that has brought Champions League football back to the Emirates Stadium.";

Console.WriteLine(await summarize.InvokeAsync(text));

マッチレポートのテキストが要約されたことを確認できます。

Granit Xhaka nets brace as Arsenal beat Wolves 5-0 to secure Champions League football.


プロンプトをチェインしてみる

次に、プロンプトをチェインする方法を試してみます。日本語に翻訳するプロンプトを定義し、要約→翻訳の順序で実行します。

// Prompt chaining
Console.WriteLine("Prompt chaining...");
var translationPrompt = @"{{$input}}

Translate the following English text into Japanese.";
var translator = kernel.CreateSemanticFunction(translationPrompt);

Console.WriteLine(await kernel.RunAsync(text, summarize, translator));

マッチレポートのテキストが日本語で要約されたことを確認できます。日本語に翻訳するプロンプトを定義することもできるので、あくまでチェインを試すためのサンプルシナリオです。


まとめ

Semantic Kernel を使って、Azure OpenAI の要約を試してみました。
今回は非常にシンプルな例で試しましたが、次回からはプラグインを組み合わせたりカスタムのプラグインを作ったりしていきます。
GitHub にある Jupyter Notebooks のチュートリアルが便利なのでお勧めです。
github.com

今回のサンプルアプリは、こちらで公開しています。
github.com