以下の内容はhttps://yohfee.hatenadiary.org/entry/2024/12/21/075305より取得しました。


Semantic KernelのOpenTelemetryメトリックをMackerelに送る

Mackerel Advent Calendar 2024 の21日目です。 20日目は id:lufiabb さんの 意思決定のためにOpenTelemetry Metricsを利用する でした。

こんにちは、Mackerel開発チームWebアプリケーションエンジニアの id:yohfee です。 今年の冬はあまり寒くなくない?と、まだ仕事部屋の暖房をつけていなかったのですが、ここのところは画像生成やSLMなどAIの利用や学習などでGPUが元気に働いて部屋を暖めてくれていたのでした。 その様子は mackerel-plugin-nvidia-smi を利用した次のグラフから観察することができます。

さて前回はその一環として、MackerelのドキュメントをRAGとしてSLMから参照するってことをやってました。

yohfee.hatenadiary.org

Semantic KernelのメトリックやトレースはOpenTelemetry形式で取れるとのことなので、今回はメトリックをMackerelに投稿してみます。 トレースはVaxilaの準備をしてなかったのでまた今度…

learn.microsoft.com

> dotnet add package OpenTelemetry --version 1.10.0
> dotnet add package OpenTelemetry.Exporter.OpenTelemetryProtocol --version 1.10.0
> dotnet add package Microsoft.SemanticKernel --version 1.32.0
> dotnet add package Microsoft.SemanticKernel.Connectors.Onnx --version 1.32.0-alpha

前回との差分として、SLMモデルを Phi-3.5-mini-instruct-onnx に更新してGPUから利用できるようにしたり、RAGのEmbeddingを省略したりなどありますが、基本的にSemantic Kernel方面のコードに変更はありません。 ちなみにPhi-3.5を使っているのは実質無料だからで、速度や精度が重要な場合はSemantic KernelのバックエンドをOpenAIなどに差し替えるのも簡単です。

OpenTelemetryの計装はMeterProvider を組み立ててExporterにMackerelのエンドポイントとAPIキーを設定するだけです。 いずれも環境変数で設定できるけど今回は素朴に。 アプリケーションの方に手を入れなくてもいいのはお手軽でいいですね。 .NETランタイムなど組み込みのメトリックを追加したい場合は .AddRuntimeInstrumentation() を足すだけなのも便利です。

open System
open System.IO
open Microsoft.SemanticKernel
open Microsoft.SemanticKernel.ChatCompletion
open Microsoft.SemanticKernel.Connectors.OpenAI
open OpenTelemetry
open OpenTelemetry.Metrics
open OpenTelemetry.Resources

AppContext.SetSwitch("Microsoft.SemanticKernel.Experimental.GenAI.EnableOTelDiagnosticsSensitive", true)

let resourceBuilder =
    ResourceBuilder.CreateDefault() |> _.AddService("OtelSkSample")

let meterProvider =
    Sdk.CreateMeterProviderBuilder()
    |> _.SetResourceBuilder(resourceBuilder)
    |> _.AddMeter("Microsoft.SemanticKernel*")
    |> _.AddOtlpExporter(fun b ->
        b.Endpoint <- Uri "https://otlp.mackerelio.com:4317"
        b.Headers <- "Mackerel-Api-Key=****************************")
    |> _.Build()

let kernel =
    Kernel.CreateBuilder()
    |> _.AddOnnxRuntimeGenAIChatCompletion(
        "phi-3.5",
        Path.Join("path", "to", "gpu-int4-awq-block-128")
    )
    |> _.Build()

let chatCompletionService = kernel.GetRequiredService<IChatCompletionService>()
let executionSettings = OpenAIPromptExecutionSettings(MaxTokens = 200)

while true do
    Console.ForegroundColor <- ConsoleColor.White
    Console.Write "\n>> "

    let arguments = KernelArguments executionSettings
    arguments.Add("input", Console.ReadLine())

    let response = kernel.InvokePromptStreamingAsync("Question: {{$input}}", arguments)

    Console.ForegroundColor <- ConsoleColor.Cyan
    Console.Write "\n> "

    task {
        let enumerator = response.GetAsyncEnumerator()

        while! enumerator.MoveNextAsync() do
            Console.Write enumerator.Current
    }
    |> Async.AwaitTask
    |> Async.RunSynchronously

    Console.WriteLine()

実行しておしゃべりを楽しんだ後、メトリックエクスプローラーを覗いてみるとこんな感じでした。

前掲のドキュメントによるとカーネル関数の呼び出しごとに実行時間やトークン数が計測されるようです。 このままのグラフだとあまり役に立たないので、関数名あたりで集計するといい感じになりそうです。

ところで、最初はメトリックの投稿に失敗していたのですが、 OTEL_DIAGNOSTICS.json として次のようなファイルをプロジェクトのルートディレクトリに置いておくとOpenTelemetry.NET SDK自体のログが吐き出されるのがとても便利でした。

{
  "LogDirectory": ".",
  "FileSize": 1024,
  "LogLevel": "LogAlways"
}

github.com

余談ですが、はてなブログのAIタイトルアシスト機能で提案されたものがおもしろかったので供養しておきます。

  • Mackerelの開発チームが暖房をつけない理由
  • 冬の暖房不要説に挑戦!Mackerel開発者のグラフ観察奮戦記
  • 冬のGPU活用術!部屋を暖めるAIの力

どうして…

Mackerel Advent Calendar 2024 の22日目は k-masuyaさんです。




以上の内容はhttps://yohfee.hatenadiary.org/entry/2024/12/21/075305より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14