次の方法で共有


OpenAI SDK を使用して AI アプリケーションをトレースする

トレースを使用すると、各実行ステップで詳細なテレメトリをキャプチャすることで、アプリケーションの実行を詳細に把握できます。 このような方法は、不正確なツール呼び出し、誤解を招くプロンプト、待機時間の長い、低品質の評価スコアなどの問題を特定することで、問題の診断とパフォーマンスの向上に役立ちます。

この記事では、Azure AI Foundry で OpenAI SDK と OpenTelemetry を使用して AI アプリケーションのトレースを実装する方法について説明します。

[前提条件]

このチュートリアルを完了するには、次のものが必要です。

  • Azure AI Foundry プロジェクトが作成されました。

  • OpenAI SDK を使用して Azure AI Foundry でホストされているモデルを呼び出す AI アプリケーション。

プロジェクトでトレースを有効にする

Azure AI Foundry は、OpenTelemetry を使用して Azure Application Insight リソースにトレースを格納します。 既定では、新しい Azure AI Foundry リソースではこれらのリソースはプロビジョニングされません。 プロジェクトを既存の Azure Application Insights リソースに接続することも、プロジェクト内から新しいリソースを作成することもできます。 このような構成は、Azure AI Foundry リソースごとに 1 回行います。

次の手順では、リソースを構成する方法を示します。

  1. Azure AI Foundry ポータルに移動し、プロジェクトに移動します。

  2. サイド ナビゲーション バーで、[トレース] を選択 します

  3. Azure Application Insights リソースが Azure AI Foundry リソースに関連付けられていない場合は、関連付けます。

    Azure AI Foundry リソースに対して Azure Application Insights を構成する方法を示すスクリーンショット。

  4. 既存の Azure Application Insights を再利用するには、ドロップダウン の Application Insights リソース名 を使用してリソースを検索し、[ 接続] を選択します。

    ヒント

    既存の Azure Application Insights に接続するには、Azure AI Foundry リソース (またはハブ) への少なくとも共同作成者アクセス権が必要です。

  5. 新しい Azure Application Insights リソースに接続するには、[ 新規作成] オプションを選択します。

    1. 構成ウィザードを使用して、新しいリソースの名前を構成します。

    2. 既定では、新しいリソースは、Azure AI Foundry リソースが作成されたのと同じリソース グループに作成されます。 [詳細設定] オプションを使用して、別のリソース グループまたはサブスクリプションを構成します。

      ヒント

      新しい Azure Application Insight リソースを作成するには、選択したリソース グループ (または既定のリソース グループ) に対する共同作成者ロールも必要です。

    3. [ 作成] を選択してリソースを作成し、Azure AI Foundry リソースに接続します。

  6. 接続が構成されたら、リソース内の任意のプロジェクトでトレースを使用する準備が整います。

  7. プロジェクトのランディング ページに移動し、プロジェクトのエンドポイント URI をコピーします。 このチュートリアルの後半で必要になります。

    プロジェクト エンドポイント URI をコピーする方法を示すスクリーンショット。

    Von Bedeutung

    プロジェクトのエンドポイントを使用するには、アプリケーションで Microsoft Entra ID を構成する必要があります。 Entra ID が構成されていない場合は、チュートリアルの手順 3 で示されているように、Azure Application Insights 接続文字列を使用します。

OpenAI SDK をインストルメント化する

OpenAI SDK を使用して開発する場合は、コードをインストルメント化して、トレースが Azure AI Foundry に送信されるようにすることができます。 コードをインストルメント化するには、次の手順に従います。

  1. 環境に azure-ai-projectsazure-monitor-opentelemetry、および opentelemetry-instrumentation-openai-v2 をインストールします。 pip の使用例を次に示します。

    pip install azure-ai-projects azure-monitor-opentelemetry opentelemetry-instrumentation-openai-v2
    
  2. OpenAIInstrumentor()を使用して OpenAI SDK をインストルメント化します。

    from opentelemetry.instrumentation.openai_v2 import OpenAIInstrumentor
    
    OpenAIInstrumentor().instrument()
    
  3. プロジェクトに関連付けられている Azure Application Insights リソースへの接続文字列を取得します。 次の行では、認証に Microsoft Entra ID を使用する必要がある Azure AI Project クライアントを使用します。

    from azure.ai.projects import AIProjectClient
    from azure.identity import DefaultAzureCredential
    
    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()
    

    ヒント

    Azure Application Insights への接続文字列は、 InstrumentationKey=aaaa0a0a-bb1b-cc2c-dd3d-eeeee4e4e4e;...のようになります。 Azure AI Foundry ポータルの [ トレース ] セクションから、プロジェクトで使用される接続文字列にアクセスすることもできます。 上部のナビゲーション バーで、[ データ ソースの管理 ] を選択し、接続文字列をコピー します。 環境変数で接続文字列を構成します。

    プロジェクトから基になる Azure Application Insights リソースに接続文字列をコピーする方法を示すスクリーンショット。

  4. Azure Application Insights にトレースを送信するように OpenTelemetry を構成します。

    from azure.monitor.opentelemetry import configure_azure_monitor
    
    configure_azure_monitor(connection_string=connection_string)
    
  5. 既定では、OpenTelemetry は入力と出力をキャプチャしません。 環境変数 OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=true を使用してキャプチャします。 この環境変数が、コードが実行されている環境レベルで構成されていることを確認します。

  6. 通常どおり OpenAI SDK を使用します。

    client = project_client.get_azure_openai_client()
    
    response = client.chat.completions.create(
        model="deepseek-v3-0324",
        messages=[
            {"role": "user", "content": "Write a short poem on open telemetry."},
        ],
    )
    
  7. Azure AI Foundry ポータルに戻ると、トレースが表示されます。

    トレースに単純なチャット完了要求がどのように表示されるかを示すスクリーンショット。

  8. 複雑なアプリケーションを開発するときに、ビジネス ロジックとモデルを組み合わせたコードのセクションをキャプチャすると便利な場合があります。 OpenTelemetry では、スパンの概念を使用して、関心のあるセクションをキャプチャします。 独自のスパンの生成を開始するには、現在の トレーサー オブジェクトのインスタンスを取得します。

    from opentelemetry import trace
    
    tracer = trace.get_tracer(__name__)
    
  9. 次に、メソッドでデコレーターを使用して、関心のあるコード内の特定のシナリオをキャプチャします。 このようなデコレーターはスパンを自動的に生成します。 次のコード例では、要求の一覧を反復処理して assess_claims_with_context と呼ばれるメソッドをインストルメント化し、LLM を使用してコンテキストで要求がサポートされているかどうかを確認します。 このメソッドで行われたすべての呼び出しは、同じスパン内でキャプチャされます。

    def build_prompt_with_context(claim: str, context: str) -> str:
        return [{'role': 'system', 'content': "I will ask you to assess whether a particular scientific claim, based on evidence provided. Output only the text 'True' if the claim is true, 'False' if the claim is false, or 'NEE' if there's not enough evidence."},
                {'role': 'user', 'content': f"""
                    The evidence is the following: {context}
    
                    Assess the following claim on the basis of the evidence. Output only the text 'True' if the claim is true, 'False' if the claim is false, or 'NEE' if there's not enough evidence. Do not output any other text.
    
                    Claim:
                    {claim}
    
                    Assessment:
                """}]
    
    @tracer.start_as_current_span("assess_claims_with_context")
    def assess_claims_with_context(claims, contexts):
        responses = []
        for claim, context in zip(claims, contexts):
            response = client.chat.completions.create(
                model="gpt-4.5-preview",
                messages=build_prompt_with_context(claim=claim, context=context),
            )
            responses.append(response.choices[0].message.content.strip('., '))
    
        return responses
    
  10. トレースは次のようになります。

    デコレーターを使用したメソッドがトレースにどのように表示されるかを示すスクリーンショット。

  11. 現在のスパンに追加情報を追加することもできます。 OpenTelemetry では、そのための 属性 の概念が使用されます。 trace オブジェクトを使用してそれらにアクセスし、追加情報を含めます。 属性を含むように assess_claims_with_context メソッドがどのように変更されたかを確認します。

    @tracer.start_as_current_span("assess_claims_with_context")
    def assess_claims_with_context(claims, contexts):
        responses = []
        current_span = trace.get_current_span()
    
        current_span.set_attribute("operation.claims_count", len(claims))
    
        for claim, context in zip(claims, contexts):
            response = client.chat.completions.create(
                model="gpt-4.5-preview",
                messages=build_prompt_with_context(claim=claim, context=context),
            )
            responses.append(response.choices[0].message.content.strip('., '))
    
        return responses
    

トレースをコンソールへ

また、アプリケーションをトレースし、トレースをローカル実行コンソールに送信すると便利な場合があります。 このようなアプローチは、自動化された CI/CD パイプラインを使用してアプリケーションで単体テストまたは統合テストを実行する場合に役立つ場合があります。 トレースをコンソールに送信し、CI/CD ツールでキャプチャしてさらに分析できます。

トレースを次のように構成します。

  1. 通常どおり OpenAI SDK をインストルメント化します。

    from opentelemetry.instrumentation.openai_v2 import OpenAIInstrumentor
    
    OpenAIInstrumentor().instrument()
    
  2. トレースをコンソールに送信するように OpenTelemetry を構成します。

    from opentelemetry import trace
    from opentelemetry.sdk.trace import TracerProvider
    from opentelemetry.sdk.trace.export import SimpleSpanProcessor, ConsoleSpanExporter
    
    span_exporter = ConsoleSpanExporter()
    tracer_provider = TracerProvider()
    tracer_provider.add_span_processor(SimpleSpanProcessor(span_exporter))
    trace.set_tracer_provider(tracer_provider)
    
  3. 通常どおり OpenAI SDK を使用します。

    response = client.chat.completions.create(
        model="deepseek-v3-0324",
        messages=[
            {"role": "user", "content": "Write a short poem on open telemetry."},
        ],
    )
    
    {
        "name": "chat deepseek-v3-0324",
        "context": {
            "trace_id": "0xaaaa0a0abb1bcc2cdd3d",
            "span_id": "0xaaaa0a0abb1bcc2cdd3d",
            "trace_state": "[]"
        },
        "kind": "SpanKind.CLIENT",
        "parent_id": null,
        "start_time": "2025-06-13T00:02:04.271337Z",
        "end_time": "2025-06-13T00:02:06.537220Z",
        "status": {
            "status_code": "UNSET"
        },
        "attributes": {
            "gen_ai.operation.name": "chat",
            "gen_ai.system": "openai",
            "gen_ai.request.model": "deepseek-v3-0324",
            "server.address": "my-project.services.ai.azure.com",
            "gen_ai.response.model": "DeepSeek-V3-0324",
            "gen_ai.response.finish_reasons": [
                "stop"
            ],
            "gen_ai.response.id": "aaaa0a0abb1bcc2cdd3d",
            "gen_ai.usage.input_tokens": 14,
            "gen_ai.usage.output_tokens": 91
        },
        "events": [],
        "links": [],
        "resource": {
            "attributes": {
                "telemetry.sdk.language": "python",
                "telemetry.sdk.name": "opentelemetry",
                "telemetry.sdk.version": "1.31.1",
                "service.name": "unknown_service"
            },
            "schema_url": ""
        }
    }
    

次のステップ