1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Azure AI FoundryでChat Completion APIの結果をトレースと監視

Last updated at Posted at 2025-07-21

Chat Completion APIの結果をAzure AI Foundryでトレースと監視できるようにしてみました。
評価メトリックやRisk&Safetyは出力していません。

Agentに関してはこちらで書いています。

前提

  • Log Analytics Workspaceのリソース作成済
  • Application insightsのリソース作成済
  • Azure AI Foundreyのリソース作成し、モデルもデプロイ済

ちなみにAzure AI Foundry画面から「リソース配分状況」は特に設定なしに参照可能です。
image.png

Step

1. Application Insights のリソース接続

Azure AI Foundry画面のメニュー「監視」を開いて、「アプリケーション分析」タブからリソース接続実施
image.png

2. プログラム作成

プログラム環境

種類 Version 備考
OS Ubuntu22.04.5 LTS WSL2で動かしています
Python 3.13.2
Poetry 2.1.3 仮想環境の管理に使用

Python パッケージ

種類 Version 備考
azure-monitor-opentelemetry 1.6.11
azure-ai-projects 1.0.0b12
opentelemetry-instrumentation-openai-v2 2.1b0
openai 1.97.0

プログラム全体

まずはプログラム全体です。
シンプルにトレース残すパターンとspanでまとめるパターンの2種類に分けています。

import os
from datetime import datetime
from logging import Formatter

from azure.ai.projects import AIProjectClient
from azure.identity import DefaultAzureCredential
from azure.monitor.opentelemetry import configure_azure_monitor
from opentelemetry import trace
from opentelemetry.instrumentation.openai_v2 import OpenAIInstrumentor


os.environ["OTEL_RESOURCE_ATTRIBUTES"]="service.namespace=my-namespace,service.instance.id=my-instance"
os.environ["OTEL_SERVICE_NAME"]="テストアプリ"
os.environ["OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT"] = "true"


OpenAIInstrumentor().instrument()


project_client = AIProjectClient(
    credential=DefaultAzureCredential(),
    endpoint="https://<your-resource>.services.ai.azure.com/api/projects/<your-project>",
)

connection_string = project_client.telemetry.get_connection_string()

configure_azure_monitor(connection_string=connection_string,
                        logging_formatter=Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
)

client = project_client.inference.get_azure_openai_client(api_version="2024-10-21")#2025-02-01-preview")

response = client.chat.completions.create(
    model="gpt-4.1-nano",
    messages=[
        {"role": "user", "content": "あなたは誰?"},
    ],
)
print(response.choices[0].message.content)


tracer = trace.get_tracer(__name__)

def build_prompt_with_context(message: str) -> str:
    return [{'role': 'developer', 'content': "あなたは頼りになるAIアシスタントです"},
            {'role': 'user', 'content': message}]

@tracer.start_as_current_span("まとめるspan")
def assess_claims_with_context(messages):
    responses = []
    current_span = trace.get_current_span()
    current_span.set_attribute("operation.custom_attribute", str(datetime.now()))
    for message in messages:
        response = client.chat.completions.create(
            model="gpt-4.1-nano",
            messages=build_prompt_with_context(message=message),
        )
        responses.append(response.choices[0].message.content.strip('., '))

    return responses
assess_claims_with_context(["今何時?", "きょうは何日?"])

共通部分

部分的に解説します。

環境変数設定

面倒だったのでPyenv使わずに直接設定。
最初の2行で、画面のフィルタに使う「アプリケーション」の設定。ここに何も設定しないとunknown_serviceになります。
image.png
OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENTはトレースにメッセージ入出力を残すための設定です。

os.environ["OTEL_RESOURCE_ATTRIBUTES"]="service.namespace=my-namespace,service.instance.id=my-instance"
os.environ["OTEL_SERVICE_NAME"]="テストアプリ"
os.environ["OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT"] = "true"

こちらを参考にしました。

監視とトレース開始

監視とトレースを開始します

OpenAIInstrumentor().instrument()

監視の設定

接続文字列を取得して監視設定。loggingのformatterは設定しないとエラー起きたので設定しています。前に試した時は不要だったので、バージョンに依存しているかもしれません。

connection_string = project_client.telemetry.get_connection_string()
configure_azure_monitor(connection_string=connection_string,
                        logging_formatter=Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
)

シンプルにトレース残すパターン

API実行

特筆することはないです。

client = project_client.inference.get_azure_openai_client(api_version="2024-10-21")#2025-02-01-preview")

response = client.chat.completions.create(
    model="gpt-4.1-nano",
    messages=[
        {"role": "user", "content": "あなたは誰?"},
    ],
)
print(response.choices[0].message.content)

トレース結果

Azure AI Foundry画面上にトレースが表示されるようになりました。
image.png

image.png

image.png

Metadata
{
	"name": "chat gpt-4.1-nano",
	"context": {
		"trace_id": "faf76a72b9d50df2bc4be8eb1c4ad68a",
		"span_id": "d898f8acf0242d5d",
		"thread_id": "undefined",
		"trace_state": "undefined"
	},
	"kind": "GenAI",
	"parent_id": "undefined",
	"start_time": "2025-07-21T06:10:33.1151180Z",
	"end_time": "2025-07-21T06:10:40.014Z",
	"status": {
		"status_code": "Ok",
		"description": "0 undefined"
	},
	"attributes": {
		"span_type": "GenAI",
		"_MS.ResourceAttributeId": "04387455-8e56-48b9-a22d-978213d336da",
		"gen_ai.operation.name": "chat",
		"gen_ai.system": "openai",
		"gen_ai.request.model": "gpt-4.1-nano",
		"gen_ai.response.model": "gpt-4.1-nano-2025-04-14",
		"gen_ai.response.finish_reasons": "('stop',)",
		"gen_ai.response.id": "chatcmpl-Bve1OUMOno6IfcK4F7NeScCn4bAUa",
		"gen_ai.usage.input_tokens": 11,
		"gen_ai.usage.output_tokens": 62,
		"gen_ai.usage.total_tokens": "73"
	},
	"events": [
		{
			"name": "gen_ai.user.message",
			"timestamp": "2025-07-21T06:10:33.1152830Z",
			"attributes": {
				"gen_ai.event.content": {
					"content": "あなたは誰?"
				},
				"gen_ai.system": "openai",
				"event.name": "gen_ai.user.message"
			}
		},
		{
			"name": "gen_ai.choice",
			"timestamp": "2025-07-21T06:10:40.0142070Z",
			"attributes": {
				"gen_ai.event.content": {
					"role": "assistant",
					"content": "こんにちは!私はOpenAIが開発したAI、ChatGPTです。あなたのお手伝いをしたり、質問にお答えしたりするためにここにいます。何か知りたいことや話したいことがあれば、遠慮なく教えてください!"
				},
				"gen_ai.system": "openai",
				"event.name": "gen_ai.choice"
			}
		}
	],
	"external_event_data_uris": "undefined",
	"span_json_uri": "undefined",
	"links": "undefined",
	"resource": "undefined"
}

spanにまとめるパターン

tracer取得

tracer = trace.get_tracer(__name__)

API呼出

デコレーター@tracer.start_as_current_spanを使ってまとめる幅を定義します。これで、SPAN単位でAI Foundry上で見ることができます。RAGなどのときに便利かと思います。
カスタム属性operationcustom_attributeも試しに追加しています(spanの親側に追加)。


def build_prompt_with_context(message: str) -> str:
    return [{'role': 'developer', 'content': "あなたは頼りになるAIアシスタントです"},
            {'role': 'user', 'content': message}]

@tracer.start_as_current_span("まとめるspan")
def assess_claims_with_context(messages):
    responses = []
    current_span = trace.get_current_span()
    current_span.set_attribute("operation.custom_attribute", str(datetime.now()))
    for message in messages:
        response = client.chat.completions.create(
            model="gpt-4.1-nano",
            messages=build_prompt_with_context(message=message),
        )
        responses.append(response.choices[0].message.content.strip('., '))

    return responses
assess_claims_with_context(["今何時?", "きょうは何日?"])

トレース結果

「まとめるspan」を開いて2つのトレースが確認できます。
image.png

image.png

image.png

監視画面

こんな風に見ることができます。
image.png

image.png

1
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?