3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Azure Functions で Semantic Kernel を使用する

Last updated at Posted at 2023-08-11

更新事項
2023/11/08
.NET 版の Semantic Kernel の v1.0.0-beta5 に対応した書き方に変更しました。

やってみたこと

Semantic Kernel をアプリに組み込むために、Azure Functions に Semantic Kernel を組み込んで API を作成してみました。
デモとして、文章を要約させる機能を作りました。

ローカルで、Postman で API 実行してみると、要約された文章が返ってきます。
image.png

Azure Functions の設定

  • .NET7 の Isolated モード
  • Http トリガー
    image.png

実装

DIの設定

  • Semantic Kernel
  • Azure OpenAI
Program.cs
var host = new HostBuilder()
.ConfigureFunctionsWorkerDefaults()
.ConfigureAppConfiguration(config =>
{
    config
    .SetBasePath(Directory.GetCurrentDirectory())
    .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
    .AddEnvironmentVariables();
})
.ConfigureServices((context, services) =>
{
    var configuration = context.Configuration;
    services.AddSingleton<IKernel>(serviceProvider => Kernel.Builder.WithAzureChatCompletionService(
                    configuration.GetSection("AzureOpenAI").GetValue<string>("ModelName"),
                    configuration.GetSection("AzureOpenAI").GetValue<string>("Endpoint"),
                    configuration.GetSection("AzureOpenAI").GetValue<string>("APIKey")
                ).Build());
    services.AddAzureClients(builder =>
            {
                builder.AddOpenAIClient(
                    new Uri(configuration.GetSection("AzureOpenAI").GetValue<string>("Endpoint")),
                    new AzureKeyCredential(configuration.GetSection("AzureOpenAI").GetValue<string>("APIKey"))
                    );
            });
})
.Build();

host.Run();

ポイントは以下になります。

  • 今回は簡単のためネイティブ関数(コードでプラグインを作成)は使わず、セマンティック関数(要約するプラグイン)のみを使用
  • パスの指定を書いて、Skills フォルダを指定してあげる(※注意点後述)
SKFunction
namespace SKDemo
{
    public class SKFunction
    {
        private readonly ILogger _logger;
        private readonly IKernel kernel;

        public SKFunction(ILoggerFactory loggerFactory, IKernel kernel)
        {
            _logger = loggerFactory.CreateLogger<SKFunction>();
            this.kernel = kernel;
        }

        [Function("SummarizeFunction")]
        public async Task<SKResponseModel> Run([HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequestData req)
        {
            var input = await req.ReadFromJsonAsync<SKRequestModel>();

            string exePath = AppDomain.CurrentDomain.BaseDirectory;
            string parentDirectory = Directory.GetParent(exePath).Parent.Parent.Parent.FullName;
            string skillsDirectory = Path.Combine(parentDirectory, "Skills");
            IDictionary<string, ISKFunction>? semanticPlugins = kernel.ImportSemanticSkillFromDirectory(skillsDirectory, "Plugins");

            SKContext context = kernel.CreateNewContext();
            context.Variables["INPUT"] = input.Text;
            SKContext answer = await semanticPlugins["SummarizeFunction"].InvokeAsync(context);
            context["answer"] = answer.ToString();

            var result = new SKResponseModel
            {
                Answer = answer.ToString()
            };

            return result;
        }
    }
}

public class SKRequestModel
{
    [JsonPropertyName("text")]
    public string? Text { get; set; }
}

public class SKResponseModel
{
    [JsonPropertyName("answer")]
    public string? Answer { get; set; }
}
config.json
{
  "schema": 1,
  "type": "completion",
  "description": "文章(ユーザーの入力値)を要約する",
  "completion": {
    "max_tokens": 4000,
    "temperature": 0.0,
    "top_p": 1.0,
    "presence_penalty": 0.0,
    "frequency_penalty": 0.0
  },
  "input": {
    "parameters": [
      {
        "name": "INPUT",
        "description": "ユーザーの入力値",
        "defaultValue": ""
      }
    ]
  }
}
skprompt.txt
以下の文章を要約してください。以下の条件に従ってください。
・日本語で回答してください
・文章の長さは、200文字以内にしてください

文章:
{{$INPUT}}

注意点

Skills フォルダについて以下 2 つ注意点があります。

  1. フォルダ構造
    Skills フォルダ内に Plugins フォルダを作成しており、その中に各種セマンティック関数を置いています。今回は要約するために使う SummarizeFunction というセマンティック関数を作って置いてあります。コード内でフォルダ指定するので、フォルダ名は何でもいいです。
    (ネイティブ関数を使う場合は、この場合 Skills フォルダ配下に置きます)
    image.png

  2. プロパティ設定
    ローカルで実行する場合は気にしなくてよいのですが、Azure リソースへデプロイして使う場合に必要な設定があります。以下の項目をプロジェクトファイルに追加してください。この設定をしないと Azure 上で動きません。

SKDemo.csproj
<ItemGroup>
    <Content Include="Skills\**\*">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
</ItemGroup>
3
3
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
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?