🤖

Semantic Kernelを使って天気を取得してみる

2023/12/24に公開

始めに

Semantic Kernelの天気の取得のしかたを通してSemantic Kernelにおけるネイティブ関数の作成のしかたを学んでいきます。

データの取得のしかた

ここでは気象庁のウェブサイトからデータを取得します。
気象庁の情報を利用する場合は利用規約に従う必要があります。

https://www.jma.go.jp/jma/kishou/info/coment.html

以下のような形式で天気のデータは公開されています。

https://www.jma.go.jp/bosai/forecast/data/forecast/{地域コード}.json

ですのでまずは地域コードを知る。
それから、天気の情報をGETするという2段階のステップになります。

まずは地域コードを取得します。

地域コードごとに取得するURLが違うので地域コードがどうなっているかを調べます。

https://www.jma.go.jp/bosai/common/const/area.json

群馬だったら100000、埼玉だったら110000などというようになっています。

すべてを実装するのは大変なのでとりあえず一部だけ実装しました。

    [KernelFunction, Description("天気を取得する場所コードを取得します。")]
    public static int GetPlaceId([Description("天気を取得する場所")] string place)
    {
        var res = place switch
        {
            "東京" => 130000,
            "横浜" => 140000,
            "名古屋" => 230000,
            "京都" => 260000,
            "静岡" => 220000,
            "福井" => 180000,
            "新潟" => 150000,
            "富山" => 160000,
            "金沢" => 170000,
            "岐阜" => 210000,
            "長野" => 200000,
            "高山" => 190000,
            "松本" => 200000,
            "大津" => 250000,
            "大阪" => 270000,
            "札幌" => 016000,
            "仙台" => 040000,
            "福岡" => 400000,
            "那覇" => 471000,
            _ => throw new ArgumentException("対応していない地域です。")
        };
        return res;
    }

ポイントととしてはメソッドと引数それぞれに説明文をつけておくことです。
これはAIが自動的に関数を呼び出すことができるようにするためです。また、プランナーにも使われます。

地域コードに基づいて天気を返す

次は、地域コードが決まってくるので取得するURLが決定しますので天気が入っているJSONを取得できます。これをよしなにAIに解析させて答えさせればよいわけです。
なので、この関数の仕事としてはJSONを取得してあげるところまで。

というわけで、以下のように書いてみました。

    [KernelFunction, Description("場所コードの地域の天気を返す")]
    public async Task<string> Weather([Description("場所コード")]int place)
    {
        return (await _client.GetAsync($"https://www.jma.go.jp/bosai/forecast/data/forecast/{place}.json")).Content.ReadAsStringAsync().Result;
    }

呼び出し側

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

Kernel kernel = Kernel.CreateBuilder()
 .AddAzureOpenAIChatCompletion(
    "デプロイ名",
    "エンドポイント",
    "APIキー").Build();

kernel.Plugins.AddFromType<WeatherPlugin>();

OpenAIPromptExecutionSettings? setting = new()
{
    ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions,
};

while (true)
{
    Console.Write("User > ");
    string input = Console.ReadLine()!;
    if (input == "exit")
    {
        break;
    }
    else
    {
        var result = await kernel.InvokePromptAsync(input, new(setting));
        Console.WriteLine($"Assistant > {result}");
    }
}

いつもの呼び出し部分です。
これまで通りですので目新しい部分はありません。

実行結果

おお、これはちゃんと場所コードを取得した上にしっかり福井の天気を取得している雰囲気あり。

Discussion