diff --git a/.chloggen/2179.yaml b/.chloggen/2179.yaml new file mode 100644 index 0000000000..aa0041689f --- /dev/null +++ b/.chloggen/2179.yaml @@ -0,0 +1,18 @@ +change_type: breaking +component: gen-ai +note: | + Revamp how GenAI chat history is recorded. Instead of per-message events, + we now have `gen_ai.system_instructions`, `gen_ai.input.messages`, and + `gen_ai.output.messages` attributes that can appear on GenAI spans or the new + `gen_ai.client.inference.operation.details` event. + + New attributes are not recorded by default when content capturing is disabled. + + Deprecations: + - `gen_ai.system.message` event - use `gen_ai.system_instructions` or + `gen_ai.input.messages` attributes instead. + - `gen_ai.user.message`, `gen_ai.assistant.message`, `gen_ai.tool.message` events + (use `gen_ai.input.messages` attribute instead) + - `gen_ai.choice` event (use `gen_ai.output.messages` attribute instead) + +issues: [2010, 2179, 1913, 1621, 1912] diff --git a/docs/gen-ai/aws-bedrock.md b/docs/gen-ai/aws-bedrock.md index 03302cf0ff..81636f4806 100644 --- a/docs/gen-ai/aws-bedrock.md +++ b/docs/gen-ai/aws-bedrock.md @@ -78,6 +78,9 @@ Describes an AWS Bedrock operation span. | [`gen_ai.usage.input_tokens`](/docs/registry/attributes/gen-ai.md) | int | The number of tokens used in the GenAI input (prompt). | `100` | `Recommended` | ![Development](https://img.shields.io/badge/-development-blue) | | [`gen_ai.usage.output_tokens`](/docs/registry/attributes/gen-ai.md) | int | The number of tokens used in the GenAI response (completion). | `180` | `Recommended` | ![Development](https://img.shields.io/badge/-development-blue) | | [`server.address`](/docs/registry/attributes/server.md) | string | GenAI server address. [10] | `example.com`; `10.1.2.80`; `/tmp/my.sock` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`gen_ai.input.messages`](/docs/registry/attributes/gen-ai.md) | any | The chat history provided to the model as an input. [11] | [
  {
    "role": "user",
    "parts": [
      {
        "type": "text",
        "content": "Weather in Paris?"
      }
    ]
  },
  {
    "role": "assistant",
    "parts": [
      {
        "type": "tool_call",
        "id": "call_VSPygqKTWdrhaFErNvMV18Yl",
        "name": "get_weather",
        "arguments": {
          "location": "Paris"
        }
      }
    ]
  },
  {
    "role": "tool",
    "parts": [
      {
        "type": "tool_call_response",
        "id": " call_VSPygqKTWdrhaFErNvMV18Yl",
        "result": "rainy, 57°F"
      }
    ]
  }
] | `Opt-In` | ![Development](https://img.shields.io/badge/-development-blue) | +| [`gen_ai.output.messages`](/docs/registry/attributes/gen-ai.md) | any | Messages returned by the model where each message represents a specific model response (choice, candidate). [12] | [
  {
    "role": "assistant",
    "parts": [
      {
        "type": "text",
        "content": "The weather in Paris is currently rainy with a temperature of 57°F."
      }
    ],
    "finish_reason": "stop"
  }
] | `Opt-In` | ![Development](https://img.shields.io/badge/-development-blue) | +| [`gen_ai.system_instructions`](/docs/registry/attributes/gen-ai.md) | any | The system message or instructions provided to the GenAI model separately from the chat history. [13] | [
  {
    "type": "text",
    "content": "You are an Agent that greet users, always use greetings tool to respond"
  }
]; [
  {
    "type": "text",
    "content": "You are a language translator."
  },
  {
    "type": "text",
    "content": "Your mission is to translate text in English to French."
  }
] | `Opt-In` | ![Development](https://img.shields.io/badge/-development-blue) | **[1] `gen_ai.operation.name`:** If one of the predefined values applies, but specific system uses a different name it's RECOMMENDED to document it in the semantic conventions for specific GenAI system and use system-specific name in the instrumentation. If a different name is not documented, instrumentation libraries SHOULD use applicable predefined value. @@ -132,6 +135,62 @@ Additional output format details may be recorded in the future in the `gen_ai.ou **[10] `server.address`:** When observed from the client side, and when communicating through an intermediary, `server.address` SHOULD represent the server address behind any intermediaries, for example proxies, if it's available. +**[11] `gen_ai.input.messages`:** Instrumentations MUST follow [Input messages JSON schema](/docs/gen-ai/gen-ai-input-messages.json). +When the attribute is recorded on events, it MUST be recorded in structured +form. When recorded on spans, it MAY be recorded as a JSON string if structured +format is not supported and SHOULD be recorded in structured form otherwise. + +Messages MUST be provided in the order they were sent to the model. +Instrumentations MAY provide a way for users to filter or truncate +input messages. + +> [!Warning] +> This attribute is likely to contain sensitive information including user/PII data. + +See [Recording content on attributes](/docs/gen-ai/gen-ai-spans.md#recording-content-on-attributes) +section for more details. + +**[12] `gen_ai.output.messages`:** Instrumentations MUST follow [Output messages JSON schema](/docs/gen-ai/gen-ai-output-messages.json) + +Each message represents a single output choice/candidate generated by +the model. Each message corresponds to exactly one generation +(choice/candidate) and vice versa - one choice cannot be split across +multiple messages or one message cannot contain parts from multiple choices. + +When the attribute is recorded on events, it MUST be recorded in structured +form. When recorded on spans, it MAY be recorded as a JSON string if structured +format is not supported and SHOULD be recorded in structured form otherwise. + +Instrumentations MAY provide a way for users to filter or truncate +output messages. + +> [!Warning] +> This attribute is likely to contain sensitive information including user/PII data. + +See [Recording content on attributes](/docs/gen-ai/gen-ai-spans.md#recording-content-on-attributes) +section for more details. + +**[13] `gen_ai.system_instructions`:** This attribute SHOULD be used when the corresponding provider or API +allows to provide system instructions or messages separately from the +chat history. + +Instructions that are part of the chat history SHOULD be recorded in +`gen_ai.input.messages` attribute instead. + +Instrumentations MUST follow [System instructions JSON schema](/docs/gen-ai/gen-ai-system-instructions.json). + +When recorded on spans, it MAY be recorded as a JSON string if structured +format is not supported and SHOULD be recorded in structured form otherwise. + +Instrumentations MAY provide a way for users to filter or truncate +system instructions. + +> [!Warning] +> This attribute may contain sensitive information. + +See [Recording content on attributes](/docs/gen-ai/gen-ai-spans.md#recording-content-on-attributes) +section for more details. + --- `error.type` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. @@ -177,9 +236,9 @@ Additional output format details may be recorded in the future in the `gen_ai.ou | `azure.ai.openai` | [Azure OpenAI](https://azure.microsoft.com/products/ai-services/openai-service/) | ![Development](https://img.shields.io/badge/-development-blue) | | `cohere` | [Cohere](https://cohere.com/) | ![Development](https://img.shields.io/badge/-development-blue) | | `deepseek` | [DeepSeek](https://www.deepseek.com/) | ![Development](https://img.shields.io/badge/-development-blue) | -| `gcp.gemini` | [Gemini](https://cloud.google.com/products/gemini) [11] | ![Development](https://img.shields.io/badge/-development-blue) | -| `gcp.gen_ai` | Any Google generative AI endpoint [12] | ![Development](https://img.shields.io/badge/-development-blue) | -| `gcp.vertex_ai` | [Vertex AI](https://cloud.google.com/vertex-ai) [13] | ![Development](https://img.shields.io/badge/-development-blue) | +| `gcp.gemini` | [Gemini](https://cloud.google.com/products/gemini) [14] | ![Development](https://img.shields.io/badge/-development-blue) | +| `gcp.gen_ai` | Any Google generative AI endpoint [15] | ![Development](https://img.shields.io/badge/-development-blue) | +| `gcp.vertex_ai` | [Vertex AI](https://cloud.google.com/vertex-ai) [16] | ![Development](https://img.shields.io/badge/-development-blue) | | `groq` | [Groq](https://groq.com/) | ![Development](https://img.shields.io/badge/-development-blue) | | `ibm.watsonx.ai` | [IBM Watsonx AI](https://www.ibm.com/products/watsonx-ai) | ![Development](https://img.shields.io/badge/-development-blue) | | `mistral_ai` | [Mistral AI](https://mistral.ai/) | ![Development](https://img.shields.io/badge/-development-blue) | @@ -187,11 +246,11 @@ Additional output format details may be recorded in the future in the `gen_ai.ou | `perplexity` | [Perplexity](https://www.perplexity.ai/) | ![Development](https://img.shields.io/badge/-development-blue) | | `x_ai` | [xAI](https://x.ai/) | ![Development](https://img.shields.io/badge/-development-blue) | -**[11]:** Used when accessing the 'generativelanguage.googleapis.com' endpoint. Also known as the AI Studio API. +**[14]:** Used when accessing the 'generativelanguage.googleapis.com' endpoint. Also known as the AI Studio API. -**[12]:** May be used when specific backend is unknown. +**[15]:** May be used when specific backend is unknown. -**[13]:** Used when accessing the 'aiplatform.googleapis.com' endpoint. +**[16]:** Used when accessing the 'aiplatform.googleapis.com' endpoint. diff --git a/docs/gen-ai/azure-ai-inference.md b/docs/gen-ai/azure-ai-inference.md index c24042cb5f..44e994522b 100644 --- a/docs/gen-ai/azure-ai-inference.md +++ b/docs/gen-ai/azure-ai-inference.md @@ -87,6 +87,9 @@ model name is available and `{gen_ai.operation.name}` otherwise. | [`gen_ai.usage.input_tokens`](/docs/registry/attributes/gen-ai.md) | int | The number of prompt tokens as reported in the usage prompt_tokens property of the response. | `100` | `Recommended` | ![Development](https://img.shields.io/badge/-development-blue) | | [`gen_ai.usage.output_tokens`](/docs/registry/attributes/gen-ai.md) | int | The number of completion tokens as reported in the usage completion_tokens property of the response. | `180` | `Recommended` | ![Development](https://img.shields.io/badge/-development-blue) | | [`server.address`](/docs/registry/attributes/server.md) | string | GenAI server address. [10] | `example.com`; `10.1.2.80`; `/tmp/my.sock` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`gen_ai.input.messages`](/docs/registry/attributes/gen-ai.md) | any | The chat history provided to the model as an input. [11] | [
  {
    "role": "user",
    "parts": [
      {
        "type": "text",
        "content": "Weather in Paris?"
      }
    ]
  },
  {
    "role": "assistant",
    "parts": [
      {
        "type": "tool_call",
        "id": "call_VSPygqKTWdrhaFErNvMV18Yl",
        "name": "get_weather",
        "arguments": {
          "location": "Paris"
        }
      }
    ]
  },
  {
    "role": "tool",
    "parts": [
      {
        "type": "tool_call_response",
        "id": " call_VSPygqKTWdrhaFErNvMV18Yl",
        "result": "rainy, 57°F"
      }
    ]
  }
] | `Opt-In` | ![Development](https://img.shields.io/badge/-development-blue) | +| [`gen_ai.output.messages`](/docs/registry/attributes/gen-ai.md) | any | Messages returned by the model where each message represents a specific model response (choice, candidate). [12] | [
  {
    "role": "assistant",
    "parts": [
      {
        "type": "text",
        "content": "The weather in Paris is currently rainy with a temperature of 57°F."
      }
    ],
    "finish_reason": "stop"
  }
] | `Opt-In` | ![Development](https://img.shields.io/badge/-development-blue) | +| [`gen_ai.system_instructions`](/docs/registry/attributes/gen-ai.md) | any | The system message or instructions provided to the GenAI model separately from the chat history. [13] | [
  {
    "type": "text",
    "content": "You are an Agent that greet users, always use greetings tool to respond"
  }
]; [
  {
    "type": "text",
    "content": "You are a language translator."
  },
  {
    "type": "text",
    "content": "Your mission is to translate text in English to French."
  }
] | `Opt-In` | ![Development](https://img.shields.io/badge/-development-blue) | **[1] `gen_ai.operation.name`:** If one of the predefined values applies, but specific system uses a different name it's RECOMMENDED to document it in the semantic conventions for specific GenAI system and use system-specific name in the instrumentation. If a different name is not documented, instrumentation libraries SHOULD use applicable predefined value. @@ -133,6 +136,62 @@ Additional output format details may be recorded in the future in the **[10] `server.address`:** When observed from the client side, and when communicating through an intermediary, `server.address` SHOULD represent the server address behind any intermediaries, for example proxies, if it's available. +**[11] `gen_ai.input.messages`:** Instrumentations MUST follow [Input messages JSON schema](/docs/gen-ai/gen-ai-input-messages.json). +When the attribute is recorded on events, it MUST be recorded in structured +form. When recorded on spans, it MAY be recorded as a JSON string if structured +format is not supported and SHOULD be recorded in structured form otherwise. + +Messages MUST be provided in the order they were sent to the model. +Instrumentations MAY provide a way for users to filter or truncate +input messages. + +> [!Warning] +> This attribute is likely to contain sensitive information including user/PII data. + +See [Recording content on attributes](/docs/gen-ai/gen-ai-spans.md#recording-content-on-attributes) +section for more details. + +**[12] `gen_ai.output.messages`:** Instrumentations MUST follow [Output messages JSON schema](/docs/gen-ai/gen-ai-output-messages.json) + +Each message represents a single output choice/candidate generated by +the model. Each message corresponds to exactly one generation +(choice/candidate) and vice versa - one choice cannot be split across +multiple messages or one message cannot contain parts from multiple choices. + +When the attribute is recorded on events, it MUST be recorded in structured +form. When recorded on spans, it MAY be recorded as a JSON string if structured +format is not supported and SHOULD be recorded in structured form otherwise. + +Instrumentations MAY provide a way for users to filter or truncate +output messages. + +> [!Warning] +> This attribute is likely to contain sensitive information including user/PII data. + +See [Recording content on attributes](/docs/gen-ai/gen-ai-spans.md#recording-content-on-attributes) +section for more details. + +**[13] `gen_ai.system_instructions`:** This attribute SHOULD be used when the corresponding provider or API +allows to provide system instructions or messages separately from the +chat history. + +Instructions that are part of the chat history SHOULD be recorded in +`gen_ai.input.messages` attribute instead. + +Instrumentations MUST follow [System instructions JSON schema](/docs/gen-ai/gen-ai-system-instructions.json). + +When recorded on spans, it MAY be recorded as a JSON string if structured +format is not supported and SHOULD be recorded in structured form otherwise. + +Instrumentations MAY provide a way for users to filter or truncate +system instructions. + +> [!Warning] +> This attribute may contain sensitive information. + +See [Recording content on attributes](/docs/gen-ai/gen-ai-spans.md#recording-content-on-attributes) +section for more details. + --- `error.type` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. diff --git a/docs/gen-ai/gen-ai-agent-spans.md b/docs/gen-ai/gen-ai-agent-spans.md index d1e492dcc2..8b65c022b2 100644 --- a/docs/gen-ai/gen-ai-agent-spans.md +++ b/docs/gen-ai/gen-ai-agent-spans.md @@ -79,6 +79,7 @@ Semantic conventions for individual GenAI systems and frameworks MAY specify dif | [`gen_ai.request.model`](/docs/registry/attributes/gen-ai.md) | string | The name of the GenAI model a request is being made to. [4] | `gpt-4` | `Conditionally Required` If available. | ![Development](https://img.shields.io/badge/-development-blue) | | [`server.port`](/docs/registry/attributes/server.md) | int | GenAI server port. [5] | `80`; `8080`; `443` | `Conditionally Required` If `server.address` is set. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | | [`server.address`](/docs/registry/attributes/server.md) | string | GenAI server address. [6] | `example.com`; `10.1.2.80`; `/tmp/my.sock` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`gen_ai.system_instructions`](/docs/registry/attributes/gen-ai.md) | any | The system message or instructions provided to the GenAI model separately from the chat history. | [
  {
    "type": "text",
    "content": "You are an Agent that greet users, always use greetings tool to respond"
  }
]; [
  {
    "type": "text",
    "content": "You are a language translator."
  },
  {
    "type": "text",
    "content": "Your mission is to translate text in English to French."
  }
] | `Opt-In` | ![Development](https://img.shields.io/badge/-development-blue) | **[1] `gen_ai.operation.name`:** If one of the predefined values applies, but specific system uses a different name it's RECOMMENDED to document it in the semantic conventions for specific GenAI system and use system-specific name in the instrumentation. If a different name is not documented, instrumentation libraries SHOULD use applicable predefined value. @@ -215,6 +216,9 @@ Semantic conventions for individual GenAI systems and frameworks MAY specify dif | [`gen_ai.usage.input_tokens`](/docs/registry/attributes/gen-ai.md) | int | The number of tokens used in the GenAI input (prompt). | `100` | `Recommended` | ![Development](https://img.shields.io/badge/-development-blue) | | [`gen_ai.usage.output_tokens`](/docs/registry/attributes/gen-ai.md) | int | The number of tokens used in the GenAI response (completion). | `180` | `Recommended` | ![Development](https://img.shields.io/badge/-development-blue) | | [`server.address`](/docs/registry/attributes/server.md) | string | GenAI server address. [11] | `example.com`; `10.1.2.80`; `/tmp/my.sock` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`gen_ai.input.messages`](/docs/registry/attributes/gen-ai.md) | any | The chat history provided to the model as an input. [12] | [
  {
    "role": "user",
    "parts": [
      {
        "type": "text",
        "content": "Weather in Paris?"
      }
    ]
  },
  {
    "role": "assistant",
    "parts": [
      {
        "type": "tool_call",
        "id": "call_VSPygqKTWdrhaFErNvMV18Yl",
        "name": "get_weather",
        "arguments": {
          "location": "Paris"
        }
      }
    ]
  },
  {
    "role": "tool",
    "parts": [
      {
        "type": "tool_call_response",
        "id": " call_VSPygqKTWdrhaFErNvMV18Yl",
        "result": "rainy, 57°F"
      }
    ]
  }
] | `Opt-In` | ![Development](https://img.shields.io/badge/-development-blue) | +| [`gen_ai.output.messages`](/docs/registry/attributes/gen-ai.md) | any | Messages returned by the model where each message represents a specific model response (choice, candidate). [13] | [
  {
    "role": "assistant",
    "parts": [
      {
        "type": "text",
        "content": "The weather in Paris is currently rainy with a temperature of 57°F."
      }
    ],
    "finish_reason": "stop"
  }
] | `Opt-In` | ![Development](https://img.shields.io/badge/-development-blue) | +| [`gen_ai.system_instructions`](/docs/registry/attributes/gen-ai.md) | any | The system message or instructions provided to the GenAI model separately from the chat history. [14] | [
  {
    "type": "text",
    "content": "You are an Agent that greet users, always use greetings tool to respond"
  }
]; [
  {
    "type": "text",
    "content": "You are a language translator."
  },
  {
    "type": "text",
    "content": "Your mission is to translate text in English to French."
  }
] | `Opt-In` | ![Development](https://img.shields.io/badge/-development-blue) | **[1] `gen_ai.operation.name`:** If one of the predefined values applies, but specific system uses a different name it's RECOMMENDED to document it in the semantic conventions for specific GenAI system and use system-specific name in the instrumentation. If a different name is not documented, instrumentation libraries SHOULD use applicable predefined value. @@ -271,6 +275,62 @@ Additional output format details may be recorded in the future in the `gen_ai.ou **[11] `server.address`:** When observed from the client side, and when communicating through an intermediary, `server.address` SHOULD represent the server address behind any intermediaries, for example proxies, if it's available. +**[12] `gen_ai.input.messages`:** Instrumentations MUST follow [Input messages JSON schema](/docs/gen-ai/gen-ai-input-messages.json). +When the attribute is recorded on events, it MUST be recorded in structured +form. When recorded on spans, it MAY be recorded as a JSON string if structured +format is not supported and SHOULD be recorded in structured form otherwise. + +Messages MUST be provided in the order they were sent to the model. +Instrumentations MAY provide a way for users to filter or truncate +input messages. + +> [!Warning] +> This attribute is likely to contain sensitive information including user/PII data. + +See [Recording content on attributes](/docs/gen-ai/gen-ai-spans.md#recording-content-on-attributes) +section for more details. + +**[13] `gen_ai.output.messages`:** Instrumentations MUST follow [Output messages JSON schema](/docs/gen-ai/gen-ai-output-messages.json) + +Each message represents a single output choice/candidate generated by +the model. Each message corresponds to exactly one generation +(choice/candidate) and vice versa - one choice cannot be split across +multiple messages or one message cannot contain parts from multiple choices. + +When the attribute is recorded on events, it MUST be recorded in structured +form. When recorded on spans, it MAY be recorded as a JSON string if structured +format is not supported and SHOULD be recorded in structured form otherwise. + +Instrumentations MAY provide a way for users to filter or truncate +output messages. + +> [!Warning] +> This attribute is likely to contain sensitive information including user/PII data. + +See [Recording content on attributes](/docs/gen-ai/gen-ai-spans.md#recording-content-on-attributes) +section for more details. + +**[14] `gen_ai.system_instructions`:** This attribute SHOULD be used when the corresponding provider or API +allows to provide system instructions or messages separately from the +chat history. + +Instructions that are part of the chat history SHOULD be recorded in +`gen_ai.input.messages` attribute instead. + +Instrumentations MUST follow [System instructions JSON schema](/docs/gen-ai/gen-ai-system-instructions.json). + +When recorded on spans, it MAY be recorded as a JSON string if structured +format is not supported and SHOULD be recorded in structured form otherwise. + +Instrumentations MAY provide a way for users to filter or truncate +system instructions. + +> [!Warning] +> This attribute may contain sensitive information. + +See [Recording content on attributes](/docs/gen-ai/gen-ai-spans.md#recording-content-on-attributes) +section for more details. + --- `error.type` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. @@ -316,9 +376,9 @@ Additional output format details may be recorded in the future in the `gen_ai.ou | `azure.ai.openai` | [Azure OpenAI](https://azure.microsoft.com/products/ai-services/openai-service/) | ![Development](https://img.shields.io/badge/-development-blue) | | `cohere` | [Cohere](https://cohere.com/) | ![Development](https://img.shields.io/badge/-development-blue) | | `deepseek` | [DeepSeek](https://www.deepseek.com/) | ![Development](https://img.shields.io/badge/-development-blue) | -| `gcp.gemini` | [Gemini](https://cloud.google.com/products/gemini) [12] | ![Development](https://img.shields.io/badge/-development-blue) | -| `gcp.gen_ai` | Any Google generative AI endpoint [13] | ![Development](https://img.shields.io/badge/-development-blue) | -| `gcp.vertex_ai` | [Vertex AI](https://cloud.google.com/vertex-ai) [14] | ![Development](https://img.shields.io/badge/-development-blue) | +| `gcp.gemini` | [Gemini](https://cloud.google.com/products/gemini) [15] | ![Development](https://img.shields.io/badge/-development-blue) | +| `gcp.gen_ai` | Any Google generative AI endpoint [16] | ![Development](https://img.shields.io/badge/-development-blue) | +| `gcp.vertex_ai` | [Vertex AI](https://cloud.google.com/vertex-ai) [17] | ![Development](https://img.shields.io/badge/-development-blue) | | `groq` | [Groq](https://groq.com/) | ![Development](https://img.shields.io/badge/-development-blue) | | `ibm.watsonx.ai` | [IBM Watsonx AI](https://www.ibm.com/products/watsonx-ai) | ![Development](https://img.shields.io/badge/-development-blue) | | `mistral_ai` | [Mistral AI](https://mistral.ai/) | ![Development](https://img.shields.io/badge/-development-blue) | @@ -326,11 +386,11 @@ Additional output format details may be recorded in the future in the `gen_ai.ou | `perplexity` | [Perplexity](https://www.perplexity.ai/) | ![Development](https://img.shields.io/badge/-development-blue) | | `x_ai` | [xAI](https://x.ai/) | ![Development](https://img.shields.io/badge/-development-blue) | -**[12]:** Used when accessing the 'generativelanguage.googleapis.com' endpoint. Also known as the AI Studio API. +**[15]:** Used when accessing the 'generativelanguage.googleapis.com' endpoint. Also known as the AI Studio API. -**[13]:** May be used when specific backend is unknown. +**[16]:** May be used when specific backend is unknown. -**[14]:** Used when accessing the 'aiplatform.googleapis.com' endpoint. +**[17]:** Used when accessing the 'aiplatform.googleapis.com' endpoint. diff --git a/docs/gen-ai/gen-ai-events.md b/docs/gen-ai/gen-ai-events.md index f1f957750f..54b20c33d5 100644 --- a/docs/gen-ai/gen-ai-events.md +++ b/docs/gen-ai/gen-ai-events.md @@ -2,22 +2,13 @@ linkTitle: Events ---> -# Semantic conventions for generative AI events +# Semantic conventions for Generative AI events **Status**: [Development][DocumentStatus] -- [Event: `gen_ai.system.message`](#event-gen_aisystemmessage) -- [Event: `gen_ai.user.message`](#event-gen_aiusermessage) -- [Event: `gen_ai.assistant.message`](#event-gen_aiassistantmessage) -- [Event: `gen_ai.tool.message`](#event-gen_aitoolmessage) -- [Event: `gen_ai.choice`](#event-gen_aichoice) -- [Custom events](#custom-events) -- [Examples](#examples) - - [Chat completion](#chat-completion) - - [Tools](#tools) - - [Chat completion with multiple choices](#chat-completion-with-multiple-choices) +- [Event: `event.gen_ai.client.inference.operation.details`](#event-eventgen_aiclientinferenceoperationdetails) @@ -47,27 +38,9 @@ GenAI instrumentations MAY capture user inputs sent to the model and responses r > Note: > Events are in-development and not yet available in some languages. Check [spec-compliance matrix](https://github.com/open-telemetry/opentelemetry-specification/tree/v1.47.0/spec-compliance-matrix.md#logs) to see the implementation status in corresponding language. -Instrumentations MAY capture inputs and outputs if and only if application has enabled the collection of this data. -This is for three primary reasons: +## Event: `event.gen_ai.client.inference.operation.details` -1. Data privacy concerns. End users of GenAI applications may input sensitive information or personally identifiable information (PII) that they do not wish to be sent to a telemetry backend. -2. Data size concerns. Although there is no specified limit to sizes, there are practical limitations in programming languages and telemetry systems. Some GenAI systems allow for extremely large context windows that end users may take full advantage of. -3. Performance concerns. Sending large amounts of data to a telemetry backend may cause performance issues for the application. - -Body fields that contain user input, model output, or other potentially sensitive and verbose data -SHOULD NOT be captured by default. - -Semantic conventions for individual systems which extend content events SHOULD document all additional body fields and specify whether they -should be captured by default or need application to opt into capturing them. - -Telemetry consumers SHOULD expect to receive unknown body fields. - -Instrumentations SHOULD NOT capture undocumented body fields and MUST follow the documented defaults for known fields. -Instrumentations MAY offer configuration options allowing to disable events or allowing to capture all fields. - -## Event: `gen_ai.system.message` - - + @@ -76,690 +49,164 @@ Instrumentations MAY offer configuration options allowing to disable events or a **Status:** ![Development](https://img.shields.io/badge/-development-blue) -The event name MUST be `gen_ai.system.message`. - -This event describes the system instructions passed to the GenAI model. - -| Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | -|---|---|---|---|---|---| -| [`gen_ai.provider.name`](/docs/registry/attributes/gen-ai.md) | string | The Generative AI provider as identified by the client or server instrumentation. [1] | `openai`; `gcp.gen_ai`; `gcp.vertex_ai` | `Recommended` | ![Development](https://img.shields.io/badge/-development-blue) | - -**[1] `gen_ai.provider.name`:** The attribute SHOULD be set based on the instrumentation's best -knowledge and may differ from the actual model provider. - -Multiple providers, including Azure OpenAI, Gemini, and AI hosting platforms -are accessible using the OpenAI REST API and corresponding client libraries, -but may proxy or host models from different providers. - -The `gen_ai.request.model`, `gen_ai.response.model`, and `server.address` -attributes may help identify the actual system in use. - -The `gen_ai.provider.name` attribute acts as a discriminator that -identifies the GenAI telemetry format flavor specific to that provider -within GenAI semantic conventions. -It SHOULD be set consistently with provider-specific attributes and signals. -For example, GenAI spans, metrics, and events related to AWS Bedrock -should have the `gen_ai.provider.name` set to `aws.bedrock` and include -applicable `aws.bedrock.*` attributes and are not expected to include -`openai.*` attributes. - ---- - -`gen_ai.provider.name` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. - -| Value | Description | Stability | -|---|---|---| -| `anthropic` | [Anthropic](https://www.anthropic.com/) | ![Development](https://img.shields.io/badge/-development-blue) | -| `aws.bedrock` | [AWS Bedrock](https://aws.amazon.com/bedrock) | ![Development](https://img.shields.io/badge/-development-blue) | -| `azure.ai.inference` | Azure AI Inference | ![Development](https://img.shields.io/badge/-development-blue) | -| `azure.ai.openai` | [Azure OpenAI](https://azure.microsoft.com/products/ai-services/openai-service/) | ![Development](https://img.shields.io/badge/-development-blue) | -| `cohere` | [Cohere](https://cohere.com/) | ![Development](https://img.shields.io/badge/-development-blue) | -| `deepseek` | [DeepSeek](https://www.deepseek.com/) | ![Development](https://img.shields.io/badge/-development-blue) | -| `gcp.gemini` | [Gemini](https://cloud.google.com/products/gemini) [2] | ![Development](https://img.shields.io/badge/-development-blue) | -| `gcp.gen_ai` | Any Google generative AI endpoint [3] | ![Development](https://img.shields.io/badge/-development-blue) | -| `gcp.vertex_ai` | [Vertex AI](https://cloud.google.com/vertex-ai) [4] | ![Development](https://img.shields.io/badge/-development-blue) | -| `groq` | [Groq](https://groq.com/) | ![Development](https://img.shields.io/badge/-development-blue) | -| `ibm.watsonx.ai` | [IBM Watsonx AI](https://www.ibm.com/products/watsonx-ai) | ![Development](https://img.shields.io/badge/-development-blue) | -| `mistral_ai` | [Mistral AI](https://mistral.ai/) | ![Development](https://img.shields.io/badge/-development-blue) | -| `openai` | [OpenAI](https://openai.com/) | ![Development](https://img.shields.io/badge/-development-blue) | -| `perplexity` | [Perplexity](https://www.perplexity.ai/) | ![Development](https://img.shields.io/badge/-development-blue) | -| `x_ai` | [xAI](https://x.ai/) | ![Development](https://img.shields.io/badge/-development-blue) | - -**[2]:** Used when accessing the 'generativelanguage.googleapis.com' endpoint. Also known as the AI Studio API. - -**[3]:** May be used when specific backend is unknown. - -**[4]:** Used when accessing the 'aiplatform.googleapis.com' endpoint. - -**Body fields:** - -:warning: Body fields will be moved to complex attributes once the -semantic convention tooling supports complex attributes -(see [#1870](https://github.com/open-telemetry/semantic-conventions/issues/1870)). - -| Body Field | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | -|---|---|---|---|---|---| -| `content` | undefined | The contents of the system message. | `You're a helpful bot` | `Opt-In` | ![Development](https://img.shields.io/badge/-development-blue) | -| `role` | string | The actual role of the message author as passed in the message. | `system`; `instruction` | `Conditionally Required` if available and not equal to `system`. | ![Development](https://img.shields.io/badge/-development-blue) | - - - - - - -## Event: `gen_ai.user.message` - - - - - - - - -**Status:** ![Development](https://img.shields.io/badge/-development-blue) +The event name MUST be `gen_ai.client.inference.operation.details`. -The event name MUST be `gen_ai.user.message`. +Describes the details of a GenAI completion request including chat history and parameters. -This event describes the user message passed to the GenAI model. +This event is opt-in and could be used to store input and output details independently from traces. | Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | |---|---|---|---|---|---| -| [`gen_ai.provider.name`](/docs/registry/attributes/gen-ai.md) | string | The Generative AI provider as identified by the client or server instrumentation. [1] | `openai`; `gcp.gen_ai`; `gcp.vertex_ai` | `Recommended` | ![Development](https://img.shields.io/badge/-development-blue) | - -**[1] `gen_ai.provider.name`:** The attribute SHOULD be set based on the instrumentation's best -knowledge and may differ from the actual model provider. - -Multiple providers, including Azure OpenAI, Gemini, and AI hosting platforms -are accessible using the OpenAI REST API and corresponding client libraries, -but may proxy or host models from different providers. - -The `gen_ai.request.model`, `gen_ai.response.model`, and `server.address` -attributes may help identify the actual system in use. +| [`gen_ai.operation.name`](/docs/registry/attributes/gen-ai.md) | string | The name of the operation being performed. [1] | `chat`; `generate_content`; `text_completion` | `Required` | ![Development](https://img.shields.io/badge/-development-blue) | +| [`error.type`](/docs/registry/attributes/error.md) | string | Describes a class of error the operation ended with. [2] | `timeout`; `java.net.UnknownHostException`; `server_certificate_invalid`; `500` | `Conditionally Required` if the operation ended in an error | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`gen_ai.conversation.id`](/docs/registry/attributes/gen-ai.md) | string | The unique identifier for a conversation (session, thread), used to store and correlate messages within this conversation. [3] | `conv_5j66UpCpwteGg4YSxUnt7lPY` | `Conditionally Required` when available | ![Development](https://img.shields.io/badge/-development-blue) | +| [`gen_ai.output.type`](/docs/registry/attributes/gen-ai.md) | string | Represents the content type requested by the client. [4] | `text`; `json`; `image` | `Conditionally Required` [5] | ![Development](https://img.shields.io/badge/-development-blue) | +| [`gen_ai.request.choice.count`](/docs/registry/attributes/gen-ai.md) | int | The target number of candidate completions to return. | `3` | `Conditionally Required` if available, in the request, and !=1 | ![Development](https://img.shields.io/badge/-development-blue) | +| [`gen_ai.request.model`](/docs/registry/attributes/gen-ai.md) | string | The name of the GenAI model a request is being made to. [6] | `gpt-4` | `Conditionally Required` If available. | ![Development](https://img.shields.io/badge/-development-blue) | +| [`gen_ai.request.seed`](/docs/registry/attributes/gen-ai.md) | int | Requests with same seed value more likely to return same result. | `100` | `Conditionally Required` if applicable and if the request includes a seed | ![Development](https://img.shields.io/badge/-development-blue) | +| [`server.port`](/docs/registry/attributes/server.md) | int | GenAI server port. [7] | `80`; `8080`; `443` | `Conditionally Required` If `server.address` is set. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`gen_ai.request.frequency_penalty`](/docs/registry/attributes/gen-ai.md) | double | The frequency penalty setting for the GenAI request. | `0.1` | `Recommended` | ![Development](https://img.shields.io/badge/-development-blue) | +| [`gen_ai.request.max_tokens`](/docs/registry/attributes/gen-ai.md) | int | The maximum number of tokens the model generates for a request. | `100` | `Recommended` | ![Development](https://img.shields.io/badge/-development-blue) | +| [`gen_ai.request.presence_penalty`](/docs/registry/attributes/gen-ai.md) | double | The presence penalty setting for the GenAI request. | `0.1` | `Recommended` | ![Development](https://img.shields.io/badge/-development-blue) | +| [`gen_ai.request.stop_sequences`](/docs/registry/attributes/gen-ai.md) | string[] | List of sequences that the model will use to stop generating further tokens. | `["forest", "lived"]` | `Recommended` | ![Development](https://img.shields.io/badge/-development-blue) | +| [`gen_ai.request.temperature`](/docs/registry/attributes/gen-ai.md) | double | The temperature setting for the GenAI request. | `0.0` | `Recommended` | ![Development](https://img.shields.io/badge/-development-blue) | +| [`gen_ai.request.top_p`](/docs/registry/attributes/gen-ai.md) | double | The top_p sampling setting for the GenAI request. | `1.0` | `Recommended` | ![Development](https://img.shields.io/badge/-development-blue) | +| [`gen_ai.response.finish_reasons`](/docs/registry/attributes/gen-ai.md) | string[] | Array of reasons the model stopped generating tokens, corresponding to each generation received. | `["stop"]`; `["stop", "length"]` | `Recommended` | ![Development](https://img.shields.io/badge/-development-blue) | +| [`gen_ai.response.id`](/docs/registry/attributes/gen-ai.md) | string | The unique identifier for the completion. | `chatcmpl-123` | `Recommended` | ![Development](https://img.shields.io/badge/-development-blue) | +| [`gen_ai.response.model`](/docs/registry/attributes/gen-ai.md) | string | The name of the model that generated the response. [8] | `gpt-4-0613` | `Recommended` | ![Development](https://img.shields.io/badge/-development-blue) | +| [`gen_ai.usage.input_tokens`](/docs/registry/attributes/gen-ai.md) | int | The number of tokens used in the GenAI input (prompt). | `100` | `Recommended` | ![Development](https://img.shields.io/badge/-development-blue) | +| [`gen_ai.usage.output_tokens`](/docs/registry/attributes/gen-ai.md) | int | The number of tokens used in the GenAI response (completion). | `180` | `Recommended` | ![Development](https://img.shields.io/badge/-development-blue) | +| [`server.address`](/docs/registry/attributes/server.md) | string | GenAI server address. [9] | `example.com`; `10.1.2.80`; `/tmp/my.sock` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`gen_ai.input.messages`](/docs/registry/attributes/gen-ai.md) | any | The chat history provided to the model as an input. [10] | [
  {
    "role": "user",
    "parts": [
      {
        "type": "text",
        "content": "Weather in Paris?"
      }
    ]
  },
  {
    "role": "assistant",
    "parts": [
      {
        "type": "tool_call",
        "id": "call_VSPygqKTWdrhaFErNvMV18Yl",
        "name": "get_weather",
        "arguments": {
          "location": "Paris"
        }
      }
    ]
  },
  {
    "role": "tool",
    "parts": [
      {
        "type": "tool_call_response",
        "id": " call_VSPygqKTWdrhaFErNvMV18Yl",
        "result": "rainy, 57°F"
      }
    ]
  }
] | `Opt-In` | ![Development](https://img.shields.io/badge/-development-blue) | +| [`gen_ai.output.messages`](/docs/registry/attributes/gen-ai.md) | any | Messages returned by the model where each message represents a specific model response (choice, candidate). [11] | [
  {
    "role": "assistant",
    "parts": [
      {
        "type": "text",
        "content": "The weather in Paris is currently rainy with a temperature of 57°F."
      }
    ],
    "finish_reason": "stop"
  }
] | `Opt-In` | ![Development](https://img.shields.io/badge/-development-blue) | +| [`gen_ai.system_instructions`](/docs/registry/attributes/gen-ai.md) | any | The system message or instructions provided to the GenAI model separately from the chat history. [12] | [
  {
    "type": "text",
    "content": "You are an Agent that greet users, always use greetings tool to respond"
  }
]; [
  {
    "type": "text",
    "content": "You are a language translator."
  },
  {
    "type": "text",
    "content": "Your mission is to translate text in English to French."
  }
] | `Opt-In` | ![Development](https://img.shields.io/badge/-development-blue) | + +**[1] `gen_ai.operation.name`:** If one of the predefined values applies, but specific system uses a different name it's RECOMMENDED to document it in the semantic conventions for specific GenAI system and use system-specific name in the instrumentation. If a different name is not documented, instrumentation libraries SHOULD use applicable predefined value. + +**[2] `error.type`:** The `error.type` SHOULD match the error code returned by the Generative AI provider or the client library, +the canonical name of exception that occurred, or another low-cardinality error identifier. +Instrumentations SHOULD document the list of errors they report. + +**[3] `gen_ai.conversation.id`:** Instrumentations SHOULD populate conversation id when they have it readily available +for a given operation, for example: + +- when client framework being instrumented manages conversation history +(see [LlamaIndex chat store](https://docs.llamaindex.ai/en/stable/module_guides/storing/chat_stores/)) + +- when instrumenting GenAI client libraries that maintain conversation on the backend side +(see [AWS Bedrock agent sessions](https://docs.aws.amazon.com/bedrock/latest/userguide/agents-session-state.html), +[OpenAI Assistant threads](https://platform.openai.com/docs/api-reference/threads)) + +Application developers that manage conversation history MAY add conversation id to GenAI and other +spans or logs using custom span or log record processors or hooks provided by instrumentation +libraries. + +**[4] `gen_ai.output.type`:** This attribute SHOULD be used when the client requests output of a specific type. The model may return zero or more outputs of this type. +This attribute specifies the output modality and not the actual output format. For example, if an image is requested, the actual output could be a URL pointing to an image file. +Additional output format details may be recorded in the future in the `gen_ai.output.{type}.*` attributes. + +**[5] `gen_ai.output.type`:** when applicable and if the request includes an output format. + +**[6] `gen_ai.request.model`:** The name of the GenAI model a request is being made to. If the model is supplied by a vendor, then the value must be the exact name of the model requested. If the model is a fine-tuned custom model, the value should have a more specific name than the base model that's been fine-tuned. + +**[7] `server.port`:** When observed from the client side, and when communicating through an intermediary, `server.port` SHOULD represent the server port behind any intermediaries, for example proxies, if it's available. + +**[8] `gen_ai.response.model`:** If available. The name of the GenAI model that provided the response. If the model is supplied by a vendor, then the value must be the exact name of the model actually used. If the model is a fine-tuned custom model, the value should have a more specific name than the base model that's been fine-tuned. + +**[9] `server.address`:** When observed from the client side, and when communicating through an intermediary, `server.address` SHOULD represent the server address behind any intermediaries, for example proxies, if it's available. + +**[10] `gen_ai.input.messages`:** Instrumentations MUST follow [Input messages JSON schema](/docs/gen-ai/gen-ai-input-messages.json). +When the attribute is recorded on events, it MUST be recorded in structured +form. When recorded on spans, it MAY be recorded as a JSON string if structured +format is not supported and SHOULD be recorded in structured form otherwise. + +Messages MUST be provided in the order they were sent to the model. +Instrumentations MAY provide a way for users to filter or truncate +input messages. -The `gen_ai.provider.name` attribute acts as a discriminator that -identifies the GenAI telemetry format flavor specific to that provider -within GenAI semantic conventions. -It SHOULD be set consistently with provider-specific attributes and signals. -For example, GenAI spans, metrics, and events related to AWS Bedrock -should have the `gen_ai.provider.name` set to `aws.bedrock` and include -applicable `aws.bedrock.*` attributes and are not expected to include -`openai.*` attributes. +> [!Warning] +> This attribute is likely to contain sensitive information including user/PII data. ---- +See [Recording content on attributes](/docs/gen-ai/gen-ai-spans.md#recording-content-on-attributes) +section for more details. -`gen_ai.provider.name` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. +**[11] `gen_ai.output.messages`:** Instrumentations MUST follow [Output messages JSON schema](/docs/gen-ai/gen-ai-output-messages.json) -| Value | Description | Stability | -|---|---|---| -| `anthropic` | [Anthropic](https://www.anthropic.com/) | ![Development](https://img.shields.io/badge/-development-blue) | -| `aws.bedrock` | [AWS Bedrock](https://aws.amazon.com/bedrock) | ![Development](https://img.shields.io/badge/-development-blue) | -| `azure.ai.inference` | Azure AI Inference | ![Development](https://img.shields.io/badge/-development-blue) | -| `azure.ai.openai` | [Azure OpenAI](https://azure.microsoft.com/products/ai-services/openai-service/) | ![Development](https://img.shields.io/badge/-development-blue) | -| `cohere` | [Cohere](https://cohere.com/) | ![Development](https://img.shields.io/badge/-development-blue) | -| `deepseek` | [DeepSeek](https://www.deepseek.com/) | ![Development](https://img.shields.io/badge/-development-blue) | -| `gcp.gemini` | [Gemini](https://cloud.google.com/products/gemini) [2] | ![Development](https://img.shields.io/badge/-development-blue) | -| `gcp.gen_ai` | Any Google generative AI endpoint [3] | ![Development](https://img.shields.io/badge/-development-blue) | -| `gcp.vertex_ai` | [Vertex AI](https://cloud.google.com/vertex-ai) [4] | ![Development](https://img.shields.io/badge/-development-blue) | -| `groq` | [Groq](https://groq.com/) | ![Development](https://img.shields.io/badge/-development-blue) | -| `ibm.watsonx.ai` | [IBM Watsonx AI](https://www.ibm.com/products/watsonx-ai) | ![Development](https://img.shields.io/badge/-development-blue) | -| `mistral_ai` | [Mistral AI](https://mistral.ai/) | ![Development](https://img.shields.io/badge/-development-blue) | -| `openai` | [OpenAI](https://openai.com/) | ![Development](https://img.shields.io/badge/-development-blue) | -| `perplexity` | [Perplexity](https://www.perplexity.ai/) | ![Development](https://img.shields.io/badge/-development-blue) | -| `x_ai` | [xAI](https://x.ai/) | ![Development](https://img.shields.io/badge/-development-blue) | - -**[2]:** Used when accessing the 'generativelanguage.googleapis.com' endpoint. Also known as the AI Studio API. - -**[3]:** May be used when specific backend is unknown. - -**[4]:** Used when accessing the 'aiplatform.googleapis.com' endpoint. - -**Body fields:** - -:warning: Body fields will be moved to complex attributes once the -semantic convention tooling supports complex attributes -(see [#1870](https://github.com/open-telemetry/semantic-conventions/issues/1870)). - -| Body Field | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | -|---|---|---|---|---|---| -| `content` | undefined | The contents of the user message. | `What's the weather in Paris?` | `Opt-In` | ![Development](https://img.shields.io/badge/-development-blue) | -| `role` | string | The actual role of the message author as passed in the message. | `user`; `customer` | `Conditionally Required` if available and not equal to `user`. | ![Development](https://img.shields.io/badge/-development-blue) | +Each message represents a single output choice/candidate generated by +the model. Each message corresponds to exactly one generation +(choice/candidate) and vice versa - one choice cannot be split across +multiple messages or one message cannot contain parts from multiple choices. - - - - +When the attribute is recorded on events, it MUST be recorded in structured +form. When recorded on spans, it MAY be recorded as a JSON string if structured +format is not supported and SHOULD be recorded in structured form otherwise. -## Event: `gen_ai.assistant.message` +Instrumentations MAY provide a way for users to filter or truncate +output messages. - - - - - - +> [!Warning] +> This attribute is likely to contain sensitive information including user/PII data. -**Status:** ![Development](https://img.shields.io/badge/-development-blue) +See [Recording content on attributes](/docs/gen-ai/gen-ai-spans.md#recording-content-on-attributes) +section for more details. -The event name MUST be `gen_ai.assistant.message`. +**[12] `gen_ai.system_instructions`:** This attribute SHOULD be used when the corresponding provider or API +allows to provide system instructions or messages separately from the +chat history. -This event describes the assistant message passed to GenAI system. +Instructions that are part of the chat history SHOULD be recorded in +`gen_ai.input.messages` attribute instead. -| Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | -|---|---|---|---|---|---| -| [`gen_ai.provider.name`](/docs/registry/attributes/gen-ai.md) | string | The Generative AI provider as identified by the client or server instrumentation. [1] | `openai`; `gcp.gen_ai`; `gcp.vertex_ai` | `Recommended` | ![Development](https://img.shields.io/badge/-development-blue) | +Instrumentations MUST follow [System instructions JSON schema](/docs/gen-ai/gen-ai-system-instructions.json). -**[1] `gen_ai.provider.name`:** The attribute SHOULD be set based on the instrumentation's best -knowledge and may differ from the actual model provider. +When recorded on spans, it MAY be recorded as a JSON string if structured +format is not supported and SHOULD be recorded in structured form otherwise. -Multiple providers, including Azure OpenAI, Gemini, and AI hosting platforms -are accessible using the OpenAI REST API and corresponding client libraries, -but may proxy or host models from different providers. +Instrumentations MAY provide a way for users to filter or truncate +system instructions. -The `gen_ai.request.model`, `gen_ai.response.model`, and `server.address` -attributes may help identify the actual system in use. +> [!Warning] +> This attribute may contain sensitive information. -The `gen_ai.provider.name` attribute acts as a discriminator that -identifies the GenAI telemetry format flavor specific to that provider -within GenAI semantic conventions. -It SHOULD be set consistently with provider-specific attributes and signals. -For example, GenAI spans, metrics, and events related to AWS Bedrock -should have the `gen_ai.provider.name` set to `aws.bedrock` and include -applicable `aws.bedrock.*` attributes and are not expected to include -`openai.*` attributes. +See [Recording content on attributes](/docs/gen-ai/gen-ai-spans.md#recording-content-on-attributes) +section for more details. --- -`gen_ai.provider.name` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. +`error.type` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. | Value | Description | Stability | |---|---|---| -| `anthropic` | [Anthropic](https://www.anthropic.com/) | ![Development](https://img.shields.io/badge/-development-blue) | -| `aws.bedrock` | [AWS Bedrock](https://aws.amazon.com/bedrock) | ![Development](https://img.shields.io/badge/-development-blue) | -| `azure.ai.inference` | Azure AI Inference | ![Development](https://img.shields.io/badge/-development-blue) | -| `azure.ai.openai` | [Azure OpenAI](https://azure.microsoft.com/products/ai-services/openai-service/) | ![Development](https://img.shields.io/badge/-development-blue) | -| `cohere` | [Cohere](https://cohere.com/) | ![Development](https://img.shields.io/badge/-development-blue) | -| `deepseek` | [DeepSeek](https://www.deepseek.com/) | ![Development](https://img.shields.io/badge/-development-blue) | -| `gcp.gemini` | [Gemini](https://cloud.google.com/products/gemini) [2] | ![Development](https://img.shields.io/badge/-development-blue) | -| `gcp.gen_ai` | Any Google generative AI endpoint [3] | ![Development](https://img.shields.io/badge/-development-blue) | -| `gcp.vertex_ai` | [Vertex AI](https://cloud.google.com/vertex-ai) [4] | ![Development](https://img.shields.io/badge/-development-blue) | -| `groq` | [Groq](https://groq.com/) | ![Development](https://img.shields.io/badge/-development-blue) | -| `ibm.watsonx.ai` | [IBM Watsonx AI](https://www.ibm.com/products/watsonx-ai) | ![Development](https://img.shields.io/badge/-development-blue) | -| `mistral_ai` | [Mistral AI](https://mistral.ai/) | ![Development](https://img.shields.io/badge/-development-blue) | -| `openai` | [OpenAI](https://openai.com/) | ![Development](https://img.shields.io/badge/-development-blue) | -| `perplexity` | [Perplexity](https://www.perplexity.ai/) | ![Development](https://img.shields.io/badge/-development-blue) | -| `x_ai` | [xAI](https://x.ai/) | ![Development](https://img.shields.io/badge/-development-blue) | - -**[2]:** Used when accessing the 'generativelanguage.googleapis.com' endpoint. Also known as the AI Studio API. - -**[3]:** May be used when specific backend is unknown. - -**[4]:** Used when accessing the 'aiplatform.googleapis.com' endpoint. - -**Body fields:** - -:warning: Body fields will be moved to complex attributes once the -semantic convention tooling supports complex attributes -(see [#1870](https://github.com/open-telemetry/semantic-conventions/issues/1870)). - -| Body Field | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | -|---|---|---|---|---|---| -| `content` | undefined | The contents of the tool message. | `The weather in Paris is rainy and overcast, with temperatures around 57°F` | `Opt-In` | ![Development](https://img.shields.io/badge/-development-blue) | -| `role` | string | The actual role of the message author as passed in the message. | `assistant`; `bot` | `Conditionally Required` if available and not equal to `assistant`. | ![Development](https://img.shields.io/badge/-development-blue) | -| `tool_calls`: | map[] | The tool calls generated by the model, such as function calls. | | `Conditionally Required` if available | ![Development](https://img.shields.io/badge/-development-blue) | -|   `function`: | map | The function call. | | `Required` | ![Development](https://img.shields.io/badge/-development-blue) | -|     `arguments` | undefined | The arguments of the function as provided in the LLM response. [1] | `{\"location\": \"Paris\"}` | `Opt-In` | ![Development](https://img.shields.io/badge/-development-blue) | -|     `name` | string | The name of the function. | `get_weather` | `Required` | ![Development](https://img.shields.io/badge/-development-blue) | -|   `id` | string | The id of the tool call. | `call_mszuSIzqtI65i1wAUOE8w5H4` | `Required` | ![Development](https://img.shields.io/badge/-development-blue) | -|   `type` | enum | The type of the tool. | `function` | `Required` | ![Development](https://img.shields.io/badge/-development-blue) | - -**[1]:** Models usually return arguments as a JSON string. In this case, it's RECOMMENDED to provide arguments as is without attempting to deserialize them. -Semantic conventions for individual systems MAY specify a different type for arguments field. - -`type` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. - -| Value | Description | Stability | -|---|---|---| -| `function` | Function | ![Development](https://img.shields.io/badge/-development-blue) | - - - - - - -## Event: `gen_ai.tool.message` - - - - - - - - -**Status:** ![Development](https://img.shields.io/badge/-development-blue) - -The event name MUST be `gen_ai.tool.message`. - -This event describes the response from a tool or function call passed to the GenAI model. - -| Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | -|---|---|---|---|---|---| -| [`gen_ai.provider.name`](/docs/registry/attributes/gen-ai.md) | string | The Generative AI provider as identified by the client or server instrumentation. [1] | `openai`; `gcp.gen_ai`; `gcp.vertex_ai` | `Recommended` | ![Development](https://img.shields.io/badge/-development-blue) | - -**[1] `gen_ai.provider.name`:** The attribute SHOULD be set based on the instrumentation's best -knowledge and may differ from the actual model provider. - -Multiple providers, including Azure OpenAI, Gemini, and AI hosting platforms -are accessible using the OpenAI REST API and corresponding client libraries, -but may proxy or host models from different providers. - -The `gen_ai.request.model`, `gen_ai.response.model`, and `server.address` -attributes may help identify the actual system in use. - -The `gen_ai.provider.name` attribute acts as a discriminator that -identifies the GenAI telemetry format flavor specific to that provider -within GenAI semantic conventions. -It SHOULD be set consistently with provider-specific attributes and signals. -For example, GenAI spans, metrics, and events related to AWS Bedrock -should have the `gen_ai.provider.name` set to `aws.bedrock` and include -applicable `aws.bedrock.*` attributes and are not expected to include -`openai.*` attributes. +| `_OTHER` | A fallback error value to be used when the instrumentation doesn't define a custom value. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | --- -`gen_ai.provider.name` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. +`gen_ai.operation.name` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. | Value | Description | Stability | |---|---|---| -| `anthropic` | [Anthropic](https://www.anthropic.com/) | ![Development](https://img.shields.io/badge/-development-blue) | -| `aws.bedrock` | [AWS Bedrock](https://aws.amazon.com/bedrock) | ![Development](https://img.shields.io/badge/-development-blue) | -| `azure.ai.inference` | Azure AI Inference | ![Development](https://img.shields.io/badge/-development-blue) | -| `azure.ai.openai` | [Azure OpenAI](https://azure.microsoft.com/products/ai-services/openai-service/) | ![Development](https://img.shields.io/badge/-development-blue) | -| `cohere` | [Cohere](https://cohere.com/) | ![Development](https://img.shields.io/badge/-development-blue) | -| `deepseek` | [DeepSeek](https://www.deepseek.com/) | ![Development](https://img.shields.io/badge/-development-blue) | -| `gcp.gemini` | [Gemini](https://cloud.google.com/products/gemini) [2] | ![Development](https://img.shields.io/badge/-development-blue) | -| `gcp.gen_ai` | Any Google generative AI endpoint [3] | ![Development](https://img.shields.io/badge/-development-blue) | -| `gcp.vertex_ai` | [Vertex AI](https://cloud.google.com/vertex-ai) [4] | ![Development](https://img.shields.io/badge/-development-blue) | -| `groq` | [Groq](https://groq.com/) | ![Development](https://img.shields.io/badge/-development-blue) | -| `ibm.watsonx.ai` | [IBM Watsonx AI](https://www.ibm.com/products/watsonx-ai) | ![Development](https://img.shields.io/badge/-development-blue) | -| `mistral_ai` | [Mistral AI](https://mistral.ai/) | ![Development](https://img.shields.io/badge/-development-blue) | -| `openai` | [OpenAI](https://openai.com/) | ![Development](https://img.shields.io/badge/-development-blue) | -| `perplexity` | [Perplexity](https://www.perplexity.ai/) | ![Development](https://img.shields.io/badge/-development-blue) | -| `x_ai` | [xAI](https://x.ai/) | ![Development](https://img.shields.io/badge/-development-blue) | - -**[2]:** Used when accessing the 'generativelanguage.googleapis.com' endpoint. Also known as the AI Studio API. - -**[3]:** May be used when specific backend is unknown. - -**[4]:** Used when accessing the 'aiplatform.googleapis.com' endpoint. - -**Body fields:** - -:warning: Body fields will be moved to complex attributes once the -semantic convention tooling supports complex attributes -(see [#1870](https://github.com/open-telemetry/semantic-conventions/issues/1870)). - -| Body Field | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | -|---|---|---|---|---|---| -| `content` | undefined | The contents of the tool message. | `rainy, 57°F` | `Opt-In` | ![Development](https://img.shields.io/badge/-development-blue) | -| `id` | string | Tool call id that this message is responding to. | `call_mszuSIzqtI65i1wAUOE8w5H4` | `Required` | ![Development](https://img.shields.io/badge/-development-blue) | -| `role` | string | The actual role of the message author as passed in the message. | `tool`; `function` | `Conditionally Required` if available and not equal to `tool`. | ![Development](https://img.shields.io/badge/-development-blue) | - - - - - - -## Event: `gen_ai.choice` - - - - - - - - -**Status:** ![Development](https://img.shields.io/badge/-development-blue) - -The event name MUST be `gen_ai.choice`. - -This event describes the Gen AI response message. - -| Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | -|---|---|---|---|---|---| -| [`gen_ai.provider.name`](/docs/registry/attributes/gen-ai.md) | string | The Generative AI provider as identified by the client or server instrumentation. [1] | `openai`; `gcp.gen_ai`; `gcp.vertex_ai` | `Recommended` | ![Development](https://img.shields.io/badge/-development-blue) | - -**[1] `gen_ai.provider.name`:** The attribute SHOULD be set based on the instrumentation's best -knowledge and may differ from the actual model provider. - -Multiple providers, including Azure OpenAI, Gemini, and AI hosting platforms -are accessible using the OpenAI REST API and corresponding client libraries, -but may proxy or host models from different providers. - -The `gen_ai.request.model`, `gen_ai.response.model`, and `server.address` -attributes may help identify the actual system in use. - -The `gen_ai.provider.name` attribute acts as a discriminator that -identifies the GenAI telemetry format flavor specific to that provider -within GenAI semantic conventions. -It SHOULD be set consistently with provider-specific attributes and signals. -For example, GenAI spans, metrics, and events related to AWS Bedrock -should have the `gen_ai.provider.name` set to `aws.bedrock` and include -applicable `aws.bedrock.*` attributes and are not expected to include -`openai.*` attributes. +| `chat` | Chat completion operation such as [OpenAI Chat API](https://platform.openai.com/docs/api-reference/chat) | ![Development](https://img.shields.io/badge/-development-blue) | +| `create_agent` | Create GenAI agent | ![Development](https://img.shields.io/badge/-development-blue) | +| `embeddings` | Embeddings operation such as [OpenAI Create embeddings API](https://platform.openai.com/docs/api-reference/embeddings/create) | ![Development](https://img.shields.io/badge/-development-blue) | +| `execute_tool` | Execute a tool | ![Development](https://img.shields.io/badge/-development-blue) | +| `generate_content` | Multimodal content generation operation such as [Gemini Generate Content](https://ai.google.dev/api/generate-content) | ![Development](https://img.shields.io/badge/-development-blue) | +| `invoke_agent` | Invoke GenAI agent | ![Development](https://img.shields.io/badge/-development-blue) | +| `text_completion` | Text completions operation such as [OpenAI Completions API (Legacy)](https://platform.openai.com/docs/api-reference/completions) | ![Development](https://img.shields.io/badge/-development-blue) | --- -`gen_ai.provider.name` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. - -| Value | Description | Stability | -|---|---|---| -| `anthropic` | [Anthropic](https://www.anthropic.com/) | ![Development](https://img.shields.io/badge/-development-blue) | -| `aws.bedrock` | [AWS Bedrock](https://aws.amazon.com/bedrock) | ![Development](https://img.shields.io/badge/-development-blue) | -| `azure.ai.inference` | Azure AI Inference | ![Development](https://img.shields.io/badge/-development-blue) | -| `azure.ai.openai` | [Azure OpenAI](https://azure.microsoft.com/products/ai-services/openai-service/) | ![Development](https://img.shields.io/badge/-development-blue) | -| `cohere` | [Cohere](https://cohere.com/) | ![Development](https://img.shields.io/badge/-development-blue) | -| `deepseek` | [DeepSeek](https://www.deepseek.com/) | ![Development](https://img.shields.io/badge/-development-blue) | -| `gcp.gemini` | [Gemini](https://cloud.google.com/products/gemini) [2] | ![Development](https://img.shields.io/badge/-development-blue) | -| `gcp.gen_ai` | Any Google generative AI endpoint [3] | ![Development](https://img.shields.io/badge/-development-blue) | -| `gcp.vertex_ai` | [Vertex AI](https://cloud.google.com/vertex-ai) [4] | ![Development](https://img.shields.io/badge/-development-blue) | -| `groq` | [Groq](https://groq.com/) | ![Development](https://img.shields.io/badge/-development-blue) | -| `ibm.watsonx.ai` | [IBM Watsonx AI](https://www.ibm.com/products/watsonx-ai) | ![Development](https://img.shields.io/badge/-development-blue) | -| `mistral_ai` | [Mistral AI](https://mistral.ai/) | ![Development](https://img.shields.io/badge/-development-blue) | -| `openai` | [OpenAI](https://openai.com/) | ![Development](https://img.shields.io/badge/-development-blue) | -| `perplexity` | [Perplexity](https://www.perplexity.ai/) | ![Development](https://img.shields.io/badge/-development-blue) | -| `x_ai` | [xAI](https://x.ai/) | ![Development](https://img.shields.io/badge/-development-blue) | - -**[2]:** Used when accessing the 'generativelanguage.googleapis.com' endpoint. Also known as the AI Studio API. - -**[3]:** May be used when specific backend is unknown. - -**[4]:** Used when accessing the 'aiplatform.googleapis.com' endpoint. - -**Body fields:** - -:warning: Body fields will be moved to complex attributes once the -semantic convention tooling supports complex attributes -(see [#1870](https://github.com/open-telemetry/semantic-conventions/issues/1870)). - -| Body Field | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | -|---|---|---|---|---|---| -| `finish_reason` | enum | The reason the model stopped generating tokens. | `stop`; `tool_calls`; `content_filter` | `Required` | ![Development](https://img.shields.io/badge/-development-blue) | -| `index` | int | The index of the choice in the list of choices. | `0`; `1` | `Required` | ![Development](https://img.shields.io/badge/-development-blue) | -| `message`: | map | GenAI response message. | | `Recommended` | ![Development](https://img.shields.io/badge/-development-blue) | -|   `content` | undefined | The contents of the assistant message. | `The weather in Paris is rainy and overcast, with temperatures around 57°F` | `Opt-In` | ![Development](https://img.shields.io/badge/-development-blue) | -|   `role` | string | The actual role of the message author as passed in the message. | `assistant`; `bot` | `Conditionally Required` if available and not equal to `assistant`. | ![Development](https://img.shields.io/badge/-development-blue) | -| `tool_calls`: | map[] | The tool calls generated by the model, such as function calls. | | `Conditionally Required` if available | ![Development](https://img.shields.io/badge/-development-blue) | -|   `function`: | map | The function that the model called. | | `Required` | ![Development](https://img.shields.io/badge/-development-blue) | -|     `arguments` | undefined | The arguments of the function as provided in the LLM response. [1] | `{\"location\": \"Paris\"}` | `Opt-In` | ![Development](https://img.shields.io/badge/-development-blue) | -|     `name` | string | The name of the function. | `get_weather` | `Required` | ![Development](https://img.shields.io/badge/-development-blue) | -|   `id` | string | The id of the tool call. | `call_mszuSIzqtI65i1wAUOE8w5H4` | `Required` | ![Development](https://img.shields.io/badge/-development-blue) | -|   `type` | enum | The type of the tool. | `function` | `Required` | ![Development](https://img.shields.io/badge/-development-blue) | - -**[1]:** Models usually return arguments as a JSON string. In this case, it's RECOMMENDED to provide arguments as is without attempting to deserialize them. -Semantic conventions for individual systems MAY specify a different type for arguments field. - -`finish_reason` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. - -| Value | Description | Stability | -|---|---|---| -| `content_filter` | Content Filter | ![Development](https://img.shields.io/badge/-development-blue) | -| `error` | Error | ![Development](https://img.shields.io/badge/-development-blue) | -| `length` | Length | ![Development](https://img.shields.io/badge/-development-blue) | -| `stop` | Stop | ![Development](https://img.shields.io/badge/-development-blue) | -| `tool_calls` | Tool Calls | ![Development](https://img.shields.io/badge/-development-blue) | - -`type` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. +`gen_ai.output.type` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. | Value | Description | Stability | |---|---|---| -| `function` | Function | ![Development](https://img.shields.io/badge/-development-blue) | +| `image` | Image | ![Development](https://img.shields.io/badge/-development-blue) | +| `json` | JSON object with known or unknown schema | ![Development](https://img.shields.io/badge/-development-blue) | +| `speech` | Speech | ![Development](https://img.shields.io/badge/-development-blue) | +| `text` | Plain text | ![Development](https://img.shields.io/badge/-development-blue) | -## Custom events - -System-specific events that are not covered in this document SHOULD be documented in corresponding Semantic Conventions extensions and -SHOULD follow `{gen_ai.provider.name}.*` naming pattern. - -## Examples - -### Chat completion - -This is an example of telemetry generated for a chat completion call with system and user messages. - -```mermaid -%%{init: -{ - "sequence": { "messageAlign": "left", "htmlLabels":true }, - "themeVariables": { "noteBkgColor" : "green", "noteTextColor": "black", "activationBkgColor": "green", "htmlLabels":true } -} -}%% -sequenceDiagram - participant A as Application - participant I as Instrumented Client - participant M as Model - A->>+I: #U+200D - I->>M: gen_ai.system.message: You are a helpful bot
gen_ai.user.message: Tell me a joke about OpenTelemetry - Note left of I: GenAI Client span - I-->M: gen_ai.choice: Why did the developer bring OpenTelemetry to the party? Because it always knows how to trace the fun! - I-->>-A: #U+200D -``` - -**GenAI Client span:** - -| Attribute name | Value | -|---------------------------------|--------------------------------------------| -| Span name | `"chat gpt-4"` | -| `gen_ai.provider.name` | `"openai"` | -| `gen_ai.request.model` | `"gpt-4"` | -| `gen_ai.request.max_tokens` | `200` | -| `gen_ai.request.top_p` | `1.0` | -| `gen_ai.response.id` | `"chatcmpl-9J3uIL87gldCFtiIbyaOvTeYBRA3l"` | -| `gen_ai.response.model` | `"gpt-4-0613"` | -| `gen_ai.usage.output_tokens` | `47` | -| `gen_ai.usage.input_tokens` | `52` | -| `gen_ai.response.finish_reasons`| `["stop"]` | - -**Events:** - -1. `gen_ai.system.message` - - | Property | Value | - |---------------------|-------------------------------------------------------| - | `gen_ai.provider.name`| `"openai"` | - | Event body (with content enabled) | `{"content": "You're a helpful bot"}` | - -2. `gen_ai.user.message` - - | Property | Value | - |---------------------|-------------------------------------------------------| - | `gen_ai.provider.name`| `"openai"` | - | Event body (with content enabled) | `{"content":"Tell me a joke about OpenTelemetry"}` | - -3. `gen_ai.choice` - - | Property | Value | - |---------------------|-------------------------------------------------------| - | `gen_ai.provider.name`| `"openai"` | - | Event body (with content enabled) | `{"index":0,"finish_reason":"stop","message":{"content":"Why did the developer bring OpenTelemetry to the party? Because it always knows how to trace the fun!"}}` | - | Event body (without content) | `{"index":0,"finish_reason":"stop","message":{}}` | - -### Tools - -This is an example of telemetry generated for a chat completion call with user message and function definition -that results in a model requesting application to call provided function. Application executes a function and -requests another completion now with the tool response. - -```mermaid -%%{init: -{ - "sequence": { "messageAlign": "left", "htmlLabels":true }, - "themeVariables": { "noteBkgColor" : "green", "noteTextColor": "black", "activationBkgColor": "green", "htmlLabels":true } -} -}%% -sequenceDiagram - participant A as Application - participant I as Instrumented Client - participant M as Model - A->>+I: #U+200D - I->>M: gen_ai.user.message: What's the weather in Paris? - Note left of I: GenAI Client span 1 - I-->M: gen_ai.choice: Call to the get_weather tool with Paris as the location argument. - I-->>-A: #U+200D - A -->> A: parse tool parameters
execute tool
update chat history - A->>+I: #U+200D - I->>M: gen_ai.user.message: What's the weather in Paris?
gen_ai.assistant.message: get_weather tool call
gen_ai.tool.message: rainy, 57°F - Note left of I: GenAI Client span 2 - I-->M: gen_ai.choice: The weather in Paris is rainy and overcast, with temperatures around 57°F - I-->>-A: #U+200D -``` - -Here's the telemetry generated for each step in this scenario: - -**GenAI Client span 1:** - -| Attribute name | Value | -|---------------------|-------------------------------------------------------| -| Span name | `"chat gpt-4"` | -| `gen_ai.provider.name`| `"openai"` | -| `gen_ai.request.model`| `"gpt-4"` | -| `gen_ai.request.max_tokens`| `200` | -| `gen_ai.request.top_p`| `1.0` | -| `gen_ai.response.id`| `"chatcmpl-9J3uIL87gldCFtiIbyaOvTeYBRA3l"` | -| `gen_ai.response.model`| `"gpt-4-0613"` | -| `gen_ai.usage.output_tokens`| `17` | -| `gen_ai.usage.input_tokens`| `47` | -| `gen_ai.response.finish_reasons`| `["tool_calls"]` | - - **Events**: - - All the following events are parented to the **GenAI chat span 1**. - - 1. `gen_ai.user.message` (not reported when capturing content is disabled) - - | Property | Value | - |---------------------|-------------------------------------------------------| - | `gen_ai.provider.name`| `"openai"` | - | Event body | `{"content":"What's the weather in Paris?"}` | - - 2. `gen_ai.choice` - - | Property | Value | - |---------------------|-------------------------------------------------------| - | `gen_ai.provider.name`| `"openai"` | - | Event body (with content) | `{"index":0,"finish_reason":"tool_calls","message":{"tool_calls":[{"id":"call_VSPygqKTWdrhaFErNvMV18Yl","function":{"name":"get_weather","arguments":"{\"location\":\"Paris\"}"},"type":"function"}]}` | - | Event body (without content) | `{"index":0,"finish_reason":"tool_calls","message":{"tool_calls":[{"id":"call_VSPygqKTWdrhaFErNvMV18Yl","function":{"name":"get_weather"},"type":"function"}]}` | - -**GenAI Client span 2:** - - | Attribute name | Value | - |---------------------------------|-------------------------------------------------------| - | Span name | `"chat gpt-4"` | - | `gen_ai.provider.name` | `"openai"` | - | `gen_ai.request.model` | `"gpt-4"` | - | `gen_ai.request.max_tokens` | `200` | - | `gen_ai.request.top_p` | `1.0` | - | `gen_ai.response.id` | `"chatcmpl-call_VSPygqKTWdrhaFErNvMV18Yl"` | - | `gen_ai.response.model` | `"gpt-4-0613"` | - | `gen_ai.usage.output_tokens` | `52` | - | `gen_ai.usage.input_tokens` | `47` | - | `gen_ai.response.finish_reasons`| `["stop"]` | - - **Events**: - - All the following events are parented to the **GenAI chat span 2**. - - In this example, the event content matches the original messages, but applications may also drop messages or change their content. - - 1. `gen_ai.user.message` - - | Property | Value | - |----------------------------------|------------------------------------------------------------| - | `gen_ai.provider.name` | `"openai"` | - | Event body | `{"content":"What's the weather in Paris?"}` | - - 2. `gen_ai.assistant.message` - - | Property | Value | - |----------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------| - | `gen_ai.provider.name` | `"openai"` | - | Event body (content enabled) | `{"tool_calls":[{"id":"call_VSPygqKTWdrhaFErNvMV18Yl","function":{"name":"get_weather","arguments":"{\"location\":\"Paris\"}"},"type":"function"}]}` | - | Event body (content not enabled) | `{"tool_calls":[{"id":"call_VSPygqKTWdrhaFErNvMV18Yl","function":{"name":"get_weather"},"type":"function"}]}` | - - 3. `gen_ai.tool.message` - - | Property | Value | - |----------------------------------|------------------------------------------------------------------------------------------------| - | `gen_ai.provider.name` | `"openai"` | - | Event body (content enabled) | `{"content":"rainy, 57°F","id":"call_VSPygqKTWdrhaFErNvMV18Yl"}` | - | Event body (content not enabled) | `{"id":"call_VSPygqKTWdrhaFErNvMV18Yl"}` | - - 4. `gen_ai.choice` - - | Property | Value | - |----------------------------------|-------------------------------------------------------------------------------------------------------------------------------| - | `gen_ai.provider.name` | `"openai"` | - | Event body (content enabled) | `{"index":0,"finish_reason":"stop","message":{"content":"The weather in Paris is rainy and overcast, with temperatures around 57°F"}}` | - | Event body (content not enabled) | `{"index":0,"finish_reason":"stop","message":{}}` | - -### Chat completion with multiple choices - -This example covers the scenario when user requests model to generate two completions for the same prompt : - -```mermaid -%%{init: -{ - "sequence": { "messageAlign": "left", "htmlLabels":true }, - "themeVariables": { "noteBkgColor" : "green", "noteTextColor": "black", "activationBkgColor": "green", "htmlLabels":true } -} -}%% -sequenceDiagram - participant A as Application - participant I as Instrumented Client - participant M as Model - A->>+I: #U+200D - I->>M: gen_ai.system.message - "You are a helpful bot"
gen_ai.user.message - "Tell me a joke about OpenTelemetry" - Note left of I: GenAI Client span - I-->M: gen_ai.choice - Why did the developer bring OpenTelemetry to the party? Because it always knows how to trace the fun!
gen_ai.choice - Why did OpenTelemetry get promoted? It had great span of control! - I-->>-A: #U+200D -``` - -**GenAI Client Span**: - -| Attribute name | Value | -|---------------------|--------------------------------------------| -| Span name | `"chat gpt-4"` | -| `gen_ai.provider.name`| `"openai"` | -| `gen_ai.request.model`| `"gpt-4"` | -| `gen_ai.request.max_tokens`| `200` | -| `gen_ai.request.top_p`| `1.0` | -| `gen_ai.response.id`| `"chatcmpl-9J3uIL87gldCFtiIbyaOvTeYBRA3l"` | -| `gen_ai.response.model`| `"gpt-4-0613"` | -| `gen_ai.usage.output_tokens`| `77` | -| `gen_ai.usage.input_tokens`| `52` | -| `gen_ai.response.finish_reasons`| `["stop", "stop"]` | - -**Events**: - -All events are parented to the GenAI chat span above. - -1. `gen_ai.system.message`: the same as in the [Chat Completion](#chat-completion) example -2. `gen_ai.user.message`: the same as in the [Chat Completion](#chat-completion) example -3. `gen_ai.choice` - - | Property | Value | - |------------------------------|-------------------------------------------------------| - | `gen_ai.provider.name` | `"openai"` | - | Event body (content enabled) | `{"index":0,"finish_reason":"stop","message":{"content":"Why did the developer bring OpenTelemetry to the party? Because it always knows how to trace the fun!"}}` | - -4. `gen_ai.choice` - - | Property | Value | - |------------------------------|-------------------------------------------------------| - | `gen_ai.provider.name` | `"openai"` | - | Event body (content enabled) | `{"index":1,"finish_reason":"stop","message":{"content":"Why did OpenTelemetry get promoted? It had great span of control!"}}` | - [DocumentStatus]: https://opentelemetry.io/docs/specs/otel/document-status diff --git a/docs/gen-ai/gen-ai-input-messages.json b/docs/gen-ai/gen-ai-input-messages.json new file mode 100644 index 0000000000..22910f300c --- /dev/null +++ b/docs/gen-ai/gen-ai-input-messages.json @@ -0,0 +1,179 @@ +{ + "$defs": { + "ChatMessage": { + "additionalProperties": true, + "properties": { + "role": { + "anyOf": [ + { + "$ref": "#/$defs/Role" + }, + { + "type": "string" + } + ], + "description": "Role of the entity that created the message.", + "title": "Role" + }, + "parts": { + "description": "List of message parts that make up the message content.", + "items": { + "anyOf": [ + { + "$ref": "#/$defs/TextPart" + }, + { + "$ref": "#/$defs/ToolCallRequestPart" + }, + { + "$ref": "#/$defs/ToolCallResponsePart" + }, + { + "$ref": "#/$defs/GenericPart" + } + ] + }, + "title": "Parts", + "type": "array" + } + }, + "required": [ + "role", + "parts" + ], + "title": "ChatMessage", + "type": "object" + }, + "GenericPart": { + "additionalProperties": true, + "description": "Represents an arbitrary message part with any type and properties.\nThis allows for extensibility with custom message part types.", + "properties": { + "type": { + "description": "The type of the content captured in this part.", + "title": "Type", + "type": "string" + } + }, + "required": [ + "type" + ], + "title": "GenericPart", + "type": "object" + }, + "Role": { + "enum": [ + "system", + "user", + "assistant", + "tool" + ], + "title": "Role", + "type": "string" + }, + "TextPart": { + "additionalProperties": true, + "description": "Represents text content sent to or received from the model.", + "properties": { + "type": { + "const": "text", + "description": "The type of the content captured in this part.", + "title": "Type", + "type": "string" + }, + "content": { + "description": "Text content sent to or received from the model.", + "title": "Content", + "type": "string" + } + }, + "required": [ + "type", + "content" + ], + "title": "TextPart", + "type": "object" + }, + "ToolCallRequestPart": { + "additionalProperties": true, + "description": "Represents a tool call requested by the model.", + "properties": { + "type": { + "const": "tool_call", + "description": "The type of the content captured in this part.", + "title": "Type", + "type": "string" + }, + "id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Unique identifier for the tool call.", + "title": "Id" + }, + "name": { + "description": "Name of the tool.", + "title": "Name", + "type": "string" + }, + "arguments": { + "default": null, + "description": "Arguments for the tool call.", + "title": "Arguments" + } + }, + "required": [ + "type", + "name" + ], + "title": "ToolCallRequestPart", + "type": "object" + }, + "ToolCallResponsePart": { + "additionalProperties": true, + "description": "Represents a tool call result sent to the model or a built-in tool call outcome and details.", + "properties": { + "type": { + "const": "tool_call_response", + "description": "The type of the content captured in this part.", + "title": "Type", + "type": "string" + }, + "id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Unique tool call identifier.", + "title": "Id" + }, + "response": { + "description": "Tool call response.", + "title": "Response" + } + }, + "required": [ + "type", + "response" + ], + "title": "ToolCallResponsePart", + "type": "object" + } + }, + "description": "Represents the list of input messages sent to the model.", + "items": { + "$ref": "#/$defs/ChatMessage" + }, + "title": "InputMessages", + "type": "array" +} \ No newline at end of file diff --git a/docs/gen-ai/gen-ai-output-messages.json b/docs/gen-ai/gen-ai-output-messages.json new file mode 100644 index 0000000000..d1f6d95337 --- /dev/null +++ b/docs/gen-ai/gen-ai-output-messages.json @@ -0,0 +1,205 @@ +{ + "$defs": { + "FinishReason": { + "description": "Represents the reason for finishing the generation.", + "enum": [ + "stop", + "length", + "content_filter", + "tool_call", + "error" + ], + "title": "FinishReason", + "type": "string" + }, + "GenericPart": { + "additionalProperties": true, + "description": "Represents an arbitrary message part with any type and properties.\nThis allows for extensibility with custom message part types.", + "properties": { + "type": { + "description": "The type of the content captured in this part.", + "title": "Type", + "type": "string" + } + }, + "required": [ + "type" + ], + "title": "GenericPart", + "type": "object" + }, + "OutputMessage": { + "additionalProperties": true, + "description": "Represents an output message generated by the model or agent. The output message captures\nspecific response (choice, candidate).", + "properties": { + "role": { + "anyOf": [ + { + "$ref": "#/$defs/Role" + }, + { + "type": "string" + } + ], + "description": "Role of the entity that created the message.", + "title": "Role" + }, + "parts": { + "description": "List of message parts that make up the message content.", + "items": { + "anyOf": [ + { + "$ref": "#/$defs/TextPart" + }, + { + "$ref": "#/$defs/ToolCallRequestPart" + }, + { + "$ref": "#/$defs/ToolCallResponsePart" + }, + { + "$ref": "#/$defs/GenericPart" + } + ] + }, + "title": "Parts", + "type": "array" + }, + "finish_reason": { + "anyOf": [ + { + "$ref": "#/$defs/FinishReason" + }, + { + "type": "string" + } + ], + "description": "Reason for finishing the generation.", + "title": "Finish Reason" + } + }, + "required": [ + "role", + "parts", + "finish_reason" + ], + "title": "OutputMessage", + "type": "object" + }, + "Role": { + "enum": [ + "system", + "user", + "assistant", + "tool" + ], + "title": "Role", + "type": "string" + }, + "TextPart": { + "additionalProperties": true, + "description": "Represents text content sent to or received from the model.", + "properties": { + "type": { + "const": "text", + "description": "The type of the content captured in this part.", + "title": "Type", + "type": "string" + }, + "content": { + "description": "Text content sent to or received from the model.", + "title": "Content", + "type": "string" + } + }, + "required": [ + "type", + "content" + ], + "title": "TextPart", + "type": "object" + }, + "ToolCallRequestPart": { + "additionalProperties": true, + "description": "Represents a tool call requested by the model.", + "properties": { + "type": { + "const": "tool_call", + "description": "The type of the content captured in this part.", + "title": "Type", + "type": "string" + }, + "id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Unique identifier for the tool call.", + "title": "Id" + }, + "name": { + "description": "Name of the tool.", + "title": "Name", + "type": "string" + }, + "arguments": { + "default": null, + "description": "Arguments for the tool call.", + "title": "Arguments" + } + }, + "required": [ + "type", + "name" + ], + "title": "ToolCallRequestPart", + "type": "object" + }, + "ToolCallResponsePart": { + "additionalProperties": true, + "description": "Represents a tool call result sent to the model or a built-in tool call outcome and details.", + "properties": { + "type": { + "const": "tool_call_response", + "description": "The type of the content captured in this part.", + "title": "Type", + "type": "string" + }, + "id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Unique tool call identifier.", + "title": "Id" + }, + "response": { + "description": "Tool call response.", + "title": "Response" + } + }, + "required": [ + "type", + "response" + ], + "title": "ToolCallResponsePart", + "type": "object" + } + }, + "description": "Represents the list of output messages generated by the model or agent.", + "items": { + "$ref": "#/$defs/OutputMessage" + }, + "title": "OutputMessages", + "type": "array" +} \ No newline at end of file diff --git a/docs/gen-ai/gen-ai-spans.md b/docs/gen-ai/gen-ai-spans.md index bdbc957f11..d8d6c48de0 100644 --- a/docs/gen-ai/gen-ai-spans.md +++ b/docs/gen-ai/gen-ai-spans.md @@ -12,7 +12,11 @@ linkTitle: Spans - [Inference](#inference) - [Embeddings](#embeddings) - [Execute tool span](#execute-tool-span) -- [Capturing inputs and outputs](#capturing-inputs-and-outputs) +- [Capturing instructions, inputs, and outputs](#capturing-instructions-inputs-and-outputs) + - [Full (buffered) content](#full-buffered-content) + - [Recording content on attributes](#recording-content-on-attributes) + - [Uploading content to external storage](#uploading-content-to-external-storage) + - [Streaming chunks](#streaming-chunks) @@ -87,6 +91,9 @@ client or when the GenAI call happens over instrumented protocol such as HTTP. | [`gen_ai.usage.input_tokens`](/docs/registry/attributes/gen-ai.md) | int | The number of tokens used in the GenAI input (prompt). | `100` | `Recommended` | ![Development](https://img.shields.io/badge/-development-blue) | | [`gen_ai.usage.output_tokens`](/docs/registry/attributes/gen-ai.md) | int | The number of tokens used in the GenAI response (completion). | `180` | `Recommended` | ![Development](https://img.shields.io/badge/-development-blue) | | [`server.address`](/docs/registry/attributes/server.md) | string | GenAI server address. [10] | `example.com`; `10.1.2.80`; `/tmp/my.sock` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`gen_ai.input.messages`](/docs/registry/attributes/gen-ai.md) | any | The chat history provided to the model as an input. [11] | [
  {
    "role": "user",
    "parts": [
      {
        "type": "text",
        "content": "Weather in Paris?"
      }
    ]
  },
  {
    "role": "assistant",
    "parts": [
      {
        "type": "tool_call",
        "id": "call_VSPygqKTWdrhaFErNvMV18Yl",
        "name": "get_weather",
        "arguments": {
          "location": "Paris"
        }
      }
    ]
  },
  {
    "role": "tool",
    "parts": [
      {
        "type": "tool_call_response",
        "id": " call_VSPygqKTWdrhaFErNvMV18Yl",
        "result": "rainy, 57°F"
      }
    ]
  }
] | `Opt-In` | ![Development](https://img.shields.io/badge/-development-blue) | +| [`gen_ai.output.messages`](/docs/registry/attributes/gen-ai.md) | any | Messages returned by the model where each message represents a specific model response (choice, candidate). [12] | [
  {
    "role": "assistant",
    "parts": [
      {
        "type": "text",
        "content": "The weather in Paris is currently rainy with a temperature of 57°F."
      }
    ],
    "finish_reason": "stop"
  }
] | `Opt-In` | ![Development](https://img.shields.io/badge/-development-blue) | +| [`gen_ai.system_instructions`](/docs/registry/attributes/gen-ai.md) | any | The system message or instructions provided to the GenAI model separately from the chat history. [13] | [
  {
    "type": "text",
    "content": "You are an Agent that greet users, always use greetings tool to respond"
  }
]; [
  {
    "type": "text",
    "content": "You are a language translator."
  },
  {
    "type": "text",
    "content": "Your mission is to translate text in English to French."
  }
] | `Opt-In` | ![Development](https://img.shields.io/badge/-development-blue) | **[1] `gen_ai.operation.name`:** If one of the predefined values applies, but specific system uses a different name it's RECOMMENDED to document it in the semantic conventions for specific GenAI system and use system-specific name in the instrumentation. If a different name is not documented, instrumentation libraries SHOULD use applicable predefined value. @@ -141,6 +148,62 @@ Additional output format details may be recorded in the future in the `gen_ai.ou **[10] `server.address`:** When observed from the client side, and when communicating through an intermediary, `server.address` SHOULD represent the server address behind any intermediaries, for example proxies, if it's available. +**[11] `gen_ai.input.messages`:** Instrumentations MUST follow [Input messages JSON schema](/docs/gen-ai/gen-ai-input-messages.json). +When the attribute is recorded on events, it MUST be recorded in structured +form. When recorded on spans, it MAY be recorded as a JSON string if structured +format is not supported and SHOULD be recorded in structured form otherwise. + +Messages MUST be provided in the order they were sent to the model. +Instrumentations MAY provide a way for users to filter or truncate +input messages. + +> [!Warning] +> This attribute is likely to contain sensitive information including user/PII data. + +See [Recording content on attributes](/docs/gen-ai/gen-ai-spans.md#recording-content-on-attributes) +section for more details. + +**[12] `gen_ai.output.messages`:** Instrumentations MUST follow [Output messages JSON schema](/docs/gen-ai/gen-ai-output-messages.json) + +Each message represents a single output choice/candidate generated by +the model. Each message corresponds to exactly one generation +(choice/candidate) and vice versa - one choice cannot be split across +multiple messages or one message cannot contain parts from multiple choices. + +When the attribute is recorded on events, it MUST be recorded in structured +form. When recorded on spans, it MAY be recorded as a JSON string if structured +format is not supported and SHOULD be recorded in structured form otherwise. + +Instrumentations MAY provide a way for users to filter or truncate +output messages. + +> [!Warning] +> This attribute is likely to contain sensitive information including user/PII data. + +See [Recording content on attributes](/docs/gen-ai/gen-ai-spans.md#recording-content-on-attributes) +section for more details. + +**[13] `gen_ai.system_instructions`:** This attribute SHOULD be used when the corresponding provider or API +allows to provide system instructions or messages separately from the +chat history. + +Instructions that are part of the chat history SHOULD be recorded in +`gen_ai.input.messages` attribute instead. + +Instrumentations MUST follow [System instructions JSON schema](/docs/gen-ai/gen-ai-system-instructions.json). + +When recorded on spans, it MAY be recorded as a JSON string if structured +format is not supported and SHOULD be recorded in structured form otherwise. + +Instrumentations MAY provide a way for users to filter or truncate +system instructions. + +> [!Warning] +> This attribute may contain sensitive information. + +See [Recording content on attributes](/docs/gen-ai/gen-ai-spans.md#recording-content-on-attributes) +section for more details. + --- `error.type` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. @@ -186,9 +249,9 @@ Additional output format details may be recorded in the future in the `gen_ai.ou | `azure.ai.openai` | [Azure OpenAI](https://azure.microsoft.com/products/ai-services/openai-service/) | ![Development](https://img.shields.io/badge/-development-blue) | | `cohere` | [Cohere](https://cohere.com/) | ![Development](https://img.shields.io/badge/-development-blue) | | `deepseek` | [DeepSeek](https://www.deepseek.com/) | ![Development](https://img.shields.io/badge/-development-blue) | -| `gcp.gemini` | [Gemini](https://cloud.google.com/products/gemini) [11] | ![Development](https://img.shields.io/badge/-development-blue) | -| `gcp.gen_ai` | Any Google generative AI endpoint [12] | ![Development](https://img.shields.io/badge/-development-blue) | -| `gcp.vertex_ai` | [Vertex AI](https://cloud.google.com/vertex-ai) [13] | ![Development](https://img.shields.io/badge/-development-blue) | +| `gcp.gemini` | [Gemini](https://cloud.google.com/products/gemini) [14] | ![Development](https://img.shields.io/badge/-development-blue) | +| `gcp.gen_ai` | Any Google generative AI endpoint [15] | ![Development](https://img.shields.io/badge/-development-blue) | +| `gcp.vertex_ai` | [Vertex AI](https://cloud.google.com/vertex-ai) [16] | ![Development](https://img.shields.io/badge/-development-blue) | | `groq` | [Groq](https://groq.com/) | ![Development](https://img.shields.io/badge/-development-blue) | | `ibm.watsonx.ai` | [IBM Watsonx AI](https://www.ibm.com/products/watsonx-ai) | ![Development](https://img.shields.io/badge/-development-blue) | | `mistral_ai` | [Mistral AI](https://mistral.ai/) | ![Development](https://img.shields.io/badge/-development-blue) | @@ -196,11 +259,11 @@ Additional output format details may be recorded in the future in the `gen_ai.ou | `perplexity` | [Perplexity](https://www.perplexity.ai/) | ![Development](https://img.shields.io/badge/-development-blue) | | `x_ai` | [xAI](https://x.ai/) | ![Development](https://img.shields.io/badge/-development-blue) | -**[11]:** Used when accessing the 'generativelanguage.googleapis.com' endpoint. Also known as the AI Studio API. +**[14]:** Used when accessing the 'generativelanguage.googleapis.com' endpoint. Also known as the AI Studio API. -**[12]:** May be used when specific backend is unknown. +**[15]:** May be used when specific backend is unknown. -**[13]:** Used when accessing the 'aiplatform.googleapis.com' endpoint. +**[16]:** Used when accessing the 'aiplatform.googleapis.com' endpoint. @@ -351,8 +414,113 @@ Datastore: A tool used by the agent to access and query structured or unstructur -## Capturing inputs and outputs +## Capturing instructions, inputs, and outputs + +### Full (buffered) content + +Model instructions, user messages, and model outputs are considered sensitive and +are often large in size. + +Recording large or sensitive content in telemetry may be problematic due to high +storage costs, regulatory requirements, or the need to enforce different access +models for operational and user data. + +OpenTelemetry instrumentations SHOULD NOT capture them by default, but SHOULD +provide an option for users to opt in. + +Application developers should choose an appropriate usage pattern based on +application needs and maturity: + +1. [Default] Don't record instructions, inputs, or outputs. + +2. Record instructions, inputs, and outputs on the GenAI spans using corresponding + attributes (`gen_ai.system.instructions`, `gen_ai.input.messages`, + `gen_ai.output.messages`). + + This approach is best suited for situations where telemetry volume is manageable + and either privacy regulations do not apply or the telemetry storage complies + with them, for example, in pre-production environments. + + See [Recording content on attributes](#recording-content-on-attributes) + section for more details. + +3. Store content externally and record references on the spans. + + This pattern is recommended in production environments where telemetry volume + is a concern or sensitive data needs to be handled securely. Using external + storage enables separate access controls. + + See [Uploading content to external storage](#uploading-content-to-external-storage) + section for more details. + +#### Recording content on attributes + +The content captured in `gen_ai.system.instructions`, `gen_ai.input.messages`, +and `gen_ai.output.messages` attributes is likely to be large. + +It may contain media, and even in the text form, it may be larger than +observability backend limits for telemetry envelopes or attribute values. + +The inputs and outputs attributes follow common structure +formally defined in [inputs JSON schema](./gen-ai-input-messages.json) and +[outputs JSON schema](./gen-ai-output-messages.json). See also their representation +in [Python code](./non-normative/models.ipynb). + +> [!NOTE] +> +> Recording structured attributes is supported on events (or logs) and may not +> yet be supported on spans. See [OTEP: Extending attributes to support complex values](https://github.com/open-telemetry/opentelemetry-specification/blob/main/oteps/4485-extending-attributes-to-support-complex-values.md) +> for the details. + +If structured attributes are not yet supported on spans in a given language, the +corresponding attribute value SHOULD be serialized to JSON string on spans and +recorded in its structured form on events. + +Instrumentation MAY provide a configuration option allowing to truncate properties +such as individual message contents, preserving JSON structure. + +#### Uploading content to external storage + +Instrumentations MAY support user-defined in-process hooks to handle content upload. + +The hook SHOULD operate independently of the opt-in flags that control capturing of +`gen_ai.system.instructions`, `gen_ai.input.messages`, and `gen_ai.output.messages`. + +If such a hook is supported and configured, instrumentations SHOULD invoke it regardless +of the span sampling decision with: + +- the instructions, [inputs](./gen-ai-input-messages.json), and + [outputs](./gen-ai-output-messages.json) object using formats defined in this convention + and before they are serialized to JSON string; +- the span instance + +The hook implementation SHOULD be able to enrich and modify provided span, instructions, +and message objects. + +If instrumentation is configured to also record `gen_ai.system.instructions`, +`gen_ai.input.messages`, and `gen_ai.output.messages` attributes, it SHOULD do it +after calling the hook and SHOULD record values that were potentially modified within +the hook implementation. + +The hook API SHOULD be generic. The application or distro is responsible for the hook +implementation including + +- the uploading process either in synchronous or asynchronous way, +- recording references to the uploaded content on the span, +- handling content in a different way. + +Application or OpenTelemetry distributions MAY also implement content uploading +in the telemetry processing pipeline (in-process or via a collector), based on the +`gen_ai.system.instructions`, `gen_ai.input.messages`, and `gen_ai.output.messages` +attributes. Given the potential data volume, it is RECOMMENDED to tune batching +and export settings accordingly in the OpenTelemetry SDK pipeline. + +TODO: document a common approach to record references to externally stored content. + +Check out [LLM call examples](./non-normative/examples-llm-calls.md). + +### Streaming chunks -User inputs and model responses may be recorded as events parented to GenAI operation span. See [Semantic Conventions for GenAI events](./gen-ai-events.md) for the details. +TODO [DocumentStatus]: https://opentelemetry.io/docs/specs/otel/document-status diff --git a/docs/gen-ai/gen-ai-system-instructions.json b/docs/gen-ai/gen-ai-system-instructions.json new file mode 100644 index 0000000000..067f88bfc3 --- /dev/null +++ b/docs/gen-ai/gen-ai-system-instructions.json @@ -0,0 +1,138 @@ +{ + "$defs": { + "GenericPart": { + "additionalProperties": true, + "description": "Represents an arbitrary message part with any type and properties.\nThis allows for extensibility with custom message part types.", + "properties": { + "type": { + "description": "The type of the content captured in this part.", + "title": "Type", + "type": "string" + } + }, + "required": [ + "type" + ], + "title": "GenericPart", + "type": "object" + }, + "TextPart": { + "additionalProperties": true, + "description": "Represents text content sent to or received from the model.", + "properties": { + "type": { + "const": "text", + "description": "The type of the content captured in this part.", + "title": "Type", + "type": "string" + }, + "content": { + "description": "Text content sent to or received from the model.", + "title": "Content", + "type": "string" + } + }, + "required": [ + "type", + "content" + ], + "title": "TextPart", + "type": "object" + }, + "ToolCallRequestPart": { + "additionalProperties": true, + "description": "Represents a tool call requested by the model.", + "properties": { + "type": { + "const": "tool_call", + "description": "The type of the content captured in this part.", + "title": "Type", + "type": "string" + }, + "id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Unique identifier for the tool call.", + "title": "Id" + }, + "name": { + "description": "Name of the tool.", + "title": "Name", + "type": "string" + }, + "arguments": { + "default": null, + "description": "Arguments for the tool call.", + "title": "Arguments" + } + }, + "required": [ + "type", + "name" + ], + "title": "ToolCallRequestPart", + "type": "object" + }, + "ToolCallResponsePart": { + "additionalProperties": true, + "description": "Represents a tool call result sent to the model or a built-in tool call outcome and details.", + "properties": { + "type": { + "const": "tool_call_response", + "description": "The type of the content captured in this part.", + "title": "Type", + "type": "string" + }, + "id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Unique tool call identifier.", + "title": "Id" + }, + "response": { + "description": "Tool call response.", + "title": "Response" + } + }, + "required": [ + "type", + "response" + ], + "title": "ToolCallResponsePart", + "type": "object" + } + }, + "description": "Represents the list of input messages sent to the model.", + "items": { + "anyOf": [ + { + "$ref": "#/$defs/TextPart" + }, + { + "$ref": "#/$defs/ToolCallRequestPart" + }, + { + "$ref": "#/$defs/ToolCallResponsePart" + }, + { + "$ref": "#/$defs/GenericPart" + } + ] + }, + "title": "SystemInstructions", + "type": "array" +} \ No newline at end of file diff --git a/docs/gen-ai/non-normative/examples-llm-calls.md b/docs/gen-ai/non-normative/examples-llm-calls.md new file mode 100644 index 0000000000..780a79a079 --- /dev/null +++ b/docs/gen-ai/non-normative/examples-llm-calls.md @@ -0,0 +1,654 @@ +# LLM call examples + + + +- [Simple chat completion](#simple-chat-completion) + - [GenAI client span when content capturing is disabled](#genai-client-span-when-content-capturing-is-disabled) + - [GenAI client span when content capturing is enabled on span attributes](#genai-client-span-when-content-capturing-is-enabled-on-span-attributes) + - [GenAI telemetry when content capturing is enabled on event attributes](#genai-telemetry-when-content-capturing-is-enabled-on-event-attributes) +- [Tool calls (functions)](#tool-calls-functions) + - [GenAI client spans when content capturing is disabled](#genai-client-spans-when-content-capturing-is-disabled) + - [GenAI client spans when content capturing is enabled on span attributes](#genai-client-spans-when-content-capturing-is-enabled-on-span-attributes) +- [System instructions along with chat history (content enabled)](#system-instructions-along-with-chat-history-content-enabled) +- [Tool calls (built-in)](#tool-calls-built-in) +- [Chat completion with multiple choices](#chat-completion-with-multiple-choices) + - [GenAI client span when content capturing is enabled on span attributes](#genai-client-span-when-content-capturing-is-enabled-on-span-attributes-1) + + + +## Simple chat completion + +This is an example of telemetry generated for a chat completion call with +system and user messages. + +```mermaid +%%{init: +{ + "sequence": { "messageAlign": "left", "htmlLabels":true }, + "themeVariables": { "noteBkgColor" : "green", "noteTextColor": "black", "activationBkgColor": "green", "htmlLabels":true } +} +}%% +sequenceDiagram + participant A as Application + participant I as Instrumented Client + participant M as Model + A->>+I: #U+200D + I->>M: input = [system: You are a helpful bot, user: Tell me a joke about OpenTelemetry] + Note left of I: GenAI Client span + I-->M: assistant: Why did the developer bring OpenTelemetry to the party? Because it always knows how to trace the fun! + I-->>-A: #U+200D +``` + +### GenAI client span when content capturing is disabled + +| Property | Value | +|---------------------------------|--------------------------------------------| +| Span name | `"chat gpt-4"` | +| Trace id | `"4bf92f3577b34da6a3ce929d0e0e4736"` | +| Span id | `"00f067aa0ba902b7"` | +| `gen_ai.provider.name` | `"openai"` | +| `gen_ai.operation.name` | `"chat"` | +| `gen_ai.request.model` | `"gpt-4"` | +| `gen_ai.request.max_tokens` | `200` | +| `gen_ai.request.top_p` | `1.0` | +| `gen_ai.response.id` | `"chatcmpl-9J3uIL87gldCFtiIbyaOvTeYBRA3l"` | +| `gen_ai.response.model` | `"gpt-4-0613"` | +| `gen_ai.usage.output_tokens` | `47` | +| `gen_ai.usage.input_tokens` | `52` | +| `gen_ai.response.finish_reasons`| `["stop"]` | + +### GenAI client span when content capturing is enabled on span attributes + +| Property | Value | +|---------------------------------|--------------------------------------------| +| Span name | `"chat gpt-4"` | +| Trace id | `"4bf92f3577b34da6a3ce929d0e0e4736"` | +| Span id | `"00f067aa0ba902b7"` | +| `gen_ai.provider.name` | `"openai"` | +| `gen_ai.operation.name` | `"chat"` | +| `gen_ai.request.model` | `"gpt-4"` | +| `gen_ai.request.max_tokens` | `200` | +| `gen_ai.request.top_p` | `1.0` | +| `gen_ai.response.id` | `"chatcmpl-9J3uIL87gldCFtiIbyaOvTeYBRA3l"` | +| `gen_ai.response.model` | `"gpt-4-0613"` | +| `gen_ai.usage.output_tokens` | `47` | +| `gen_ai.usage.input_tokens` | `52` | +| `gen_ai.response.finish_reasons`| `["stop"]` | +| `gen_ai.input.messages` | [`gen_ai.input.messages`](#gen-ai-input-messages-simple) | +| `gen_ai.output.messages` | [`gen_ai.output.messages`](#gen-ai-output-messages-simple) | + +`gen_ai.input.messages` value + +```json +[ + { + "role": "system", + "parts": [ + { + "type": "text", + "content": "You are a helpful bot" + } + ] + }, + { + "role": "user", + "parts": [ + { + "type": "text", + "content": "Tell me a joke about OpenTelemetry" + } + ] + } +] +``` + +`gen_ai.output.messages` value + +```json +[ + { + "role": "assistant", + "parts": [ + { + "type": "text", + "content": " Why did the developer bring OpenTelemetry to the party? Because it always knows how to trace the fun!" + } + ], + "finish_reason": "stop" + } +] +``` + +### GenAI telemetry when content capturing is enabled on event attributes + +Span: + +| Property | Value | +|---------------------------------|--------------------------------------------| +| Span name | `"chat gpt-4"` | +| Trace id | `"4bf92f3577b34da6a3ce929d0e0e4736"` | +| Span id | `"00f067aa0ba902b7"` | +| `gen_ai.provider.name` | `"openai"` | +| `gen_ai.operation.name` | `"chat"` | +| `gen_ai.request.model` | `"gpt-4"` | +| `gen_ai.request.max_tokens` | `200` | +| `gen_ai.request.top_p` | `1.0` | +| `gen_ai.response.id` | `"chatcmpl-9J3uIL87gldCFtiIbyaOvTeYBRA3l"` | +| `gen_ai.response.model` | `"gpt-4-0613"` | +| `gen_ai.usage.output_tokens` | `47` | +| `gen_ai.usage.input_tokens` | `52` | +| `gen_ai.response.finish_reasons`| `["stop"]` | + +Event: + +| Property | Value | +|---------------------------------|--------------------------------------------| +| Trace id | `"4bf92f3577b34da6a3ce929d0e0e4736"` | +| Span id | `"00f067aa0ba902b7"` | +| `gen_ai.provider.name` | `"openai"` | +| `gen_ai.operation.name` | `"chat"` | +| `gen_ai.request.model` | `"gpt-4"` | +| `gen_ai.request.max_tokens` | `200` | +| `gen_ai.request.top_p` | `1.0` | +| `gen_ai.response.id` | `"chatcmpl-9J3uIL87gldCFtiIbyaOvTeYBRA3l"` | +| `gen_ai.response.model` | `"gpt-4-0613"` | +| `gen_ai.usage.output_tokens` | `47` | +| `gen_ai.usage.input_tokens` | `52` | +| `gen_ai.response.finish_reasons`| `["stop"]` | +| `gen_ai.input.messages` | [`gen_ai.input.messages`](#gen-ai-input-messages-event) | +| `gen_ai.output.messages` | [`gen_ai.output.messages`](#gen-ai-output-messages-event) | + +`gen_ai.input.messages` value + +```json +[ + { + "role": "system", + "parts": [ + { + "type": "text", + "content": "You are a helpful bot" + } + ] + }, + { + "role": "user", + "parts": [ + { + "type": "text", + "content": "Tell me a joke about OpenTelemetry" + } + ] + } +] +``` + +`gen_ai.output.messages` value + +```json +[ + { + "role": "assistant", + "parts": [ + { + "type": "text", + "content": " Why did the developer bring OpenTelemetry to the party? Because it always knows how to trace the fun!" + } + ], + "finish_reason": "stop" + } +] +``` + +## Tool calls (functions) + +This is an example of telemetry generated for a chat completion call with user message and function definition that results in a model requesting application to call provided function. Application executes a function and requests another completion now with the tool response. + +```mermaid +%%{init: +{ + "sequence": { "messageAlign": "left", "htmlLabels":true }, + "themeVariables": { "noteBkgColor" : "green", "noteTextColor": "black", "activationBkgColor": "green", "htmlLabels":true } +} +}%% +sequenceDiagram + participant A as Application + participant I as Instrumented Client + participant M as Model + A->>+I: #U+200D + I->>M: input = [user: What's the weather in Paris?] + Note left of I: GenAI Client span 1 + I-->M: assistant: Call to the get_weather tool with Paris as the location argument. + I-->>-A: #U+200D + A -->> A: parse tool parameters
execute tool
update chat history + A->>+I: #U+200D + I->>M: input = [user: What's the weather in Paris?, assistant: get_weather tool call, tool: rainy, 57°F] + Note left of I: GenAI Client span 2 + I-->M: assistant: The weather in Paris is rainy and overcast, with temperatures around 57°F + I-->>-A: #U+200D +``` + +### GenAI client spans when content capturing is disabled + +The relationship between below spans depends on how user application code is written. +They are likely to be siblings if there is an encompassing span. + +**GenAI client span 1:** + +| Property | Value | +|-------------------------------- | --------------------------------------------| +| Span name | `"chat gpt-4"` | +| `gen_ai.provider.name` | `"openai"` | +| `gen_ai.operation.name` | `"chat"` | +| `gen_ai.request.model` | `"gpt-4"` | +| `gen_ai.request.max_tokens` | `200` | +| `gen_ai.request.top_p` | `1.0` | +| `gen_ai.response.id` | `"chatcmpl-9J3uIL87gldCFtiIbyaOvTeYBRA3l"` | +| `gen_ai.response.model` | `"gpt-4-0613"` | +| `gen_ai.usage.output_tokens` | `17` | +| `gen_ai.usage.input_tokens` | `47` | +| `gen_ai.response.finish_reasons`| `["tool_calls"]` | + +**Tool call:** + +If tool call is [instrumented according to execute-tool span definition](../gen-ai-spans.md#execute-tool-span), it may look like + +| Property | Value | +|---------------------------------|---------------------------------------------| +| Span name | `"execute_tool get_weather"` | +| `gen_ai.tool.call.id` | `"call_VSPygqKTWdrhaFErNvMV18Yl"` | +| `gen_ai.tool.name` | `"get_weather"` | +| `gen_ai.operation.name` | `"execute_tool"` | +| `gen_ai.tool.type` | `"function"` | + +**GenAI client span 2:** + +| Property | Value | +|---------------------------------|---------------------------------------------| +| Span name | `"chat gpt-4"` | +| `gen_ai.provider.name` | `"openai"` | +| `gen_ai.request.model` | `"gpt-4"` | +| `gen_ai.request.max_tokens` | `200` | +| `gen_ai.request.top_p` | `1.0` | +| `gen_ai.response.id` | `"chatcmpl-call_VSPygqKTWdrhaFErNvMV18Yl"` | +| `gen_ai.response.model` | `"gpt-4-0613"` | +| `gen_ai.usage.output_tokens` | `52` | +| `gen_ai.usage.input_tokens` | `97` | +| `gen_ai.response.finish_reasons`| `["stop"]` | + +### GenAI client spans when content capturing is enabled on span attributes + +The relationship between below spans depends on how user application code is written. +They are likely to be siblings if there is an encompassing span. + +**GenAI client span 1:** + +| Property | Value | +|-------------------------------- | --------------------------------------------| +| Span name | `"chat gpt-4"` | +| `gen_ai.provider.name` | `"openai"` | +| `gen_ai.operation.name` | `"chat"` | +| `gen_ai.request.model` | `"gpt-4"` | +| `gen_ai.request.max_tokens` | `200` | +| `gen_ai.request.top_p` | `1.0` | +| `gen_ai.response.id` | `"chatcmpl-9J3uIL87gldCFtiIbyaOvTeYBRA3l"` | +| `gen_ai.response.model` | `"gpt-4-0613"` | +| `gen_ai.usage.output_tokens` | `17` | +| `gen_ai.usage.input_tokens` | `47` | +| `gen_ai.response.finish_reasons`| `["tool_calls"]` | +| `gen_ai.input.messages` | `gen_ai.input.messages` value | +| `gen_ai.output.messages` | `gen_ai.output.messages` value | + +`gen_ai.input.messages` value + +```json +[ + { + "role": "user", + "parts": [ + { + "type": "text", + "content": "Weather in Paris?" + } + ] + } +] +``` + +`gen_ai.output.messages` value + +```json +[ + { + "role": "assistant", + "parts": [ + { + "type": "tool_call", + "id": "call_VSPygqKTWdrhaFErNvMV18Yl", + "name": "get_weather", + "arguments": { + "location": "Paris" + } + } + ], + "finish_reason": "tool_call" + } +] +``` + +**Tool call:** + +If tool call is [instrumented according to execute-tool span definition](../gen-ai-spans.md#execute-tool-span), it may look like this: + +| Property | Value | +|---------------------------------|---------------------------------------------| +| Span name | `"execute_tool get_weather"` | +| `gen_ai.tool.call.id` | `"call_VSPygqKTWdrhaFErNvMV18Yl"` | +| `gen_ai.tool.name` | `"get_weather"` | +| `gen_ai.operation.name` | `"execute_tool"` | +| `gen_ai.tool.type` | `"function"` | + +**GenAI client span 2:** + +| Property | Value | +|---------------------------------|---------------------------------------------| +| Span name | `"chat gpt-4"` | +| `gen_ai.provider.name` | `"openai"` | +| `gen_ai.request.model` | `"gpt-4"` | +| `gen_ai.request.max_tokens` | `200` | +| `gen_ai.request.top_p` | `1.0` | +| `gen_ai.response.id` | `"chatcmpl-call_VSPygqKTWdrhaFErNvMV18Yl"` | +| `gen_ai.response.model` | `"gpt-4-0613"` | +| `gen_ai.usage.output_tokens` | `52` | +| `gen_ai.usage.input_tokens` | `97` | +| `gen_ai.response.finish_reasons`| `["stop"]` | +| `gen_ai.input.messages` | `gen_ai.input.messages` value | +| `gen_ai.output.messages` | `gen_ai.output.messages` value | + +`gen_ai.input.messages` value + +```json +[ + { + "role": "user", + "parts": [ + { + "type": "text", + "content": "Weather in Paris?" + } + ] + }, + { + "role": "assistant", + "parts": [ + { + "type": "tool_call", + "id": "call_VSPygqKTWdrhaFErNvMV18Yl", + "name": "get_weather", + "arguments": { + "location": "Paris" + } + } + ] + }, + { + "role": "tool", + "parts": [ + { + "type": "tool_call_response", + "id": " call_VSPygqKTWdrhaFErNvMV18Yl", + "response": "rainy, 57°F" + } + ] + } +] +``` + +`gen_ai.output.messages` value + +```json +[ + { + "role": "assistant", + "parts": [ + { + "type": "text", + "content": "The weather in Paris is currently rainy with a temperature of 57°F." + } + ], + "finish_reason": "stop" + } +] +``` + +## System instructions along with chat history (content enabled) + +Some providers allow to provide instructions separately from the chat history provided in the inputs +or in addition to `system` (`deveoper`, etc) message provided in the input. + +This example demonstrates en edge case when conflicting instructions are provided +to the OpenAI responses API. In this case instructions are recorded in the `gen_ai.system_instructions` attribute. + +```py +response = openai.responses.create( + model="gpt-4", + instructions="You must never tell jokes", + input=[{"role": "system", "content": "You are a helpful assistant"}, {"role": "user", "content": "Tell me a joke"}]) +``` + +Span: + +| Property | Value | +|---------------------------------|--------------------------------------------| +| Span name | `"chat gpt-4"` | +| `gen_ai.provider.name` | `"openai"` | +| `gen_ai.operation.name` | `"chat"` | +| `gen_ai.request.model` | `"gpt-4"` | +| `gen_ai.response.id` | `"chatcmpl-9J3uIL87gldCFtiIbyaOvTeYBRA3l"` | +| `gen_ai.response.model` | `"gpt-4-0613"` | +| `gen_ai.usage.output_tokens` | `10` | +| `gen_ai.usage.input_tokens` | `28` | +| `gen_ai.response.finish_reasons`| `["stop"]` | +| `gen_ai.system_instructions` | [`gen_ai.system_instructions`](#gen-ai-system-instructions) | +| `gen_ai.input.messages` | [`gen_ai.input.messages`](#gen-ai-input-messages-instructions) | +| `gen_ai.output.messages` | [`gen_ai.output.messages`](#gen-ai-output-messages-instructions) | + +`gen_ai.system_instructions` value + +```json +[ + { + "type": "text", + "content": "You must never tell jokes" + } +] +``` + +`gen_ai.input.messages` value + +```json +[ + { + "role": "system", + "parts": [ + { + "type": "text", + "content": "You are a helpful bot" + } + ] + }, + { + "role": "user", + "parts": [ + { + "type": "text", + "content": "Tell me a joke about OpenTelemetry" + } + ] + } +] +``` + +`gen_ai.output.messages` value + +```json +[ + { + "role": "assistant", + "parts": [ + { + "type": "text", + "content": "I'm sorry, but I can't assist with that" + } + ], + "finish_reason": "stop" + } +] +``` + +## Tool calls (built-in) + +> [!NOTE] +> +> The format of `gen_ai.output.messages` is not yet specified for built-in tool calls (check [#2585](https://github.com/open-telemetry/semantic-conventions/issues/2585) +> for the details). + +This is an example of telemetry generated for a chat completion call with `code_interpreter` tool that results in +a model provider executing a tool and returning response along with tool call details. + +```mermaid +%%{init: +{ + "sequence": { "messageAlign": "left", "htmlLabels":true }, + "themeVariables": { "noteBkgColor" : "green", "noteTextColor": "black", "activationBkgColor": "green", "htmlLabels":true } +} +}%% +sequenceDiagram + participant A as Application + participant I as Instrumented Client + participant M as Model + + A ->>+ I: + I ->> M: input = [system: You are a helpful bot, user: Write Python code that generates a random number, executes it, and returns the result.] + Note left of I: GenAI Client span + I --> M: tool:code='import random ....'
assistant: The generated random number is 95. + I -->>- A: +``` + +**GenAI client span:** + +| Property | Value | +|-------------------------------- | --------------------------------------------| +| Span name | `"chat gpt-4"` | +| `gen_ai.provider.name` | `"openai"` | +| `gen_ai.operation.name` | `"chat"` | +| `gen_ai.request.model` | `"gpt-4"` | +| `gen_ai.request.max_tokens` | `200` | +| `gen_ai.request.top_p` | `1.0` | +| `gen_ai.response.id` | `"chatcmpl-9J3uIL87gldCFtiIbyaOvTeYBRA3l"` | +| `gen_ai.response.model` | `"gpt-4-0613"` | +| `gen_ai.usage.output_tokens` | `44` | +| `gen_ai.usage.input_tokens` | `385` | +| `gen_ai.response.finish_reasons`| `["stop"]` | +| `gen_ai.input.messages` | `gen_ai.input.messages` value | +| `gen_ai.output.messages` | `gen_ai.output.messages` value | + +`gen_ai.input.messages` value + +TODO + +`gen_ai.output.messages` value + +TODO + +## Chat completion with multiple choices + +This example covers the scenario when user requests model to generate two completions for the same prompt: + +```mermaid +%%{init: +{ + "sequence": { "messageAlign": "left", "htmlLabels":true }, + "themeVariables": { "noteBkgColor" : "green", "noteTextColor": "black", "activationBkgColor": "green", "htmlLabels":true } +} +}%% +sequenceDiagram + participant A as Application + participant I as Instrumented Client + participant M as Model + A->>+I: #U+200D + I->>M: input = [system: You are a helpful bot, user: Tell me a joke about OpenTelemetry] + Note left of I: GenAI Client span + I-->M: assistant: Why did the developer bring OpenTelemetry to the party? Because it always knows how to trace the fun!
assistant: Why did OpenTelemetry get promoted? It had great span of control! + I-->>-A: #U+200D +``` + +### GenAI client span when content capturing is enabled on span attributes + +| Property | Value | +|---------------------------------|--------------------------------------------| +| Span name | `"chat gpt-4"` | +| `gen_ai.provider.name` | `"openai"` | +| `gen_ai.operation.name` | `"chat"` | +| `gen_ai.request.model` | `"gpt-4"` | +| `gen_ai.request.max_tokens` | `200` | +| `gen_ai.request.top_p` | `1.0` | +| `gen_ai.response.id` | `"chatcmpl-9J3uIL87gldCFtiIbyaOvTeYBRA3l"` | +| `gen_ai.response.model` | `"gpt-4-0613"` | +| `gen_ai.usage.output_tokens` | `77` | +| `gen_ai.usage.input_tokens` | `52` | +| `gen_ai.response.finish_reasons`| `["stop", "stop"]` | +| `gen_ai.input.messages` | `gen_ai.input.messages` value | +| `gen_ai.output.messages` | `gen_ai.output.messages` value | + +`gen_ai.input.messages` value + +```json +[ + { + "role": "system", + "parts": [ + { + "type": "text", + "content": "You are a helpful bot" + } + ] + }, + { + "role": "user", + "parts": [ + { + "type": "text", + "content": "Tell me a joke about OpenTelemetry" + } + ] + } +] +``` + +`gen_ai.output.messages` value + +```json +[ + { + "role": "assistant", + "parts": [ + { + "type": "text", + "content": " Why did the developer bring OpenTelemetry to the party? Because it always knows how to trace the fun!" + } + ], + "finish_reason": "stop" + }, + { + "role": "assistant", + "parts": [ + { + "type": "text", + "content": " Why did OpenTelemetry get promoted? It had great span of control!" + } + ], + "finish_reason": "stop" + } +] +``` diff --git a/docs/gen-ai/non-normative/models.ipynb b/docs/gen-ai/non-normative/models.ipynb new file mode 100644 index 0000000000..891bed9423 --- /dev/null +++ b/docs/gen-ai/non-normative/models.ipynb @@ -0,0 +1,248 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "05733998", + "metadata": {}, + "source": [ + "# GenAI messages Python models\n", + "\n", + "This file defines Python models for system instructions, input, and output messages.\n", + "These models are provided for reference only.\n", + "\n", + "The model definitions are based on [Pydantic](https://github.com/pydantic/pydantic)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3c4ec73b", + "metadata": { + "vscode": { + "languageId": "shellscript" + } + }, + "outputs": [], + "source": [ + "pip install pydantic~=2.0" + ] + }, + { + "cell_type": "markdown", + "id": "b335c0ec", + "metadata": { + "vscode": { + "languageId": "shellscript" + } + }, + "source": [ + "## Common Code" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "5124fe15", + "metadata": {}, + "outputs": [], + "source": [ + "from enum import Enum\n", + "import json\n", + "from typing import Any, List, Literal, Optional, Union\n", + "from pydantic import BaseModel, Field, RootModel\n", + "\n", + "class TextPart(BaseModel):\n", + " \"\"\"\n", + " Represents text content sent to or received from the model.\n", + " \"\"\"\n", + " type: Literal['text'] = Field(description=\"The type of the content captured in this part.\")\n", + " content: str = Field(description=\"Text content sent to or received from the model.\")\n", + "\n", + " class Config:\n", + " extra = \"allow\"\n", + "\n", + "class ToolCallRequestPart(BaseModel):\n", + " \"\"\"\n", + " Represents a tool call requested by the model.\n", + " \"\"\"\n", + " type: Literal[\"tool_call\"] = Field(description=\"The type of the content captured in this part.\")\n", + " id: Optional[str] = Field(default=None, description=\"Unique identifier for the tool call.\")\n", + " name: str = Field(description=\"Name of the tool.\")\n", + " arguments: Any = Field(None, description=\"Arguments for the tool call.\")\n", + "\n", + " class Config:\n", + " extra = \"allow\"\n", + "\n", + "class ToolCallResponsePart(BaseModel):\n", + " \"\"\"\n", + " Represents a tool call result sent to the model or a built-in tool call outcome and details.\n", + " \"\"\"\n", + " type: Literal['tool_call_response'] = Field(description=\"The type of the content captured in this part.\")\n", + " id: Optional[str] = Field(default=None, description=\"Unique tool call identifier.\")\n", + " response: Any = Field(description=\"Tool call response.\")\n", + "\n", + " class Config:\n", + " extra = \"allow\"\n", + "\n", + "class GenericPart(BaseModel):\n", + " \"\"\"\n", + " Represents an arbitrary message part with any type and properties.\n", + " This allows for extensibility with custom message part types.\n", + " \"\"\"\n", + " type: str = Field(description=\"The type of the content captured in this part.\")\n", + "\n", + " class Config:\n", + " extra = \"allow\"\n", + "\n", + "# This Union without discriminator will generate anyOf in JSON schema\n", + "MessagePart = Union[\n", + " TextPart,\n", + " ToolCallRequestPart,\n", + " ToolCallResponsePart,\n", + " GenericPart, # Catch-all for any other type\n", + " # Add other message part types here as needed,\n", + " # e.g. image URL, image blob, audio URL, structured output, hosted tool call, etc.\n", + "]\n", + "\n", + "class Role(str, Enum):\n", + " SYSTEM = \"system\"\n", + " USER = \"user\"\n", + " ASSISTANT = \"assistant\"\n", + " TOOL = \"tool\"\n", + "\n", + "class ChatMessage(BaseModel):\n", + " role: Union[Role, str] = Field(\n", + " description=\"Role of the entity that created the message.\")\n", + " parts: List[MessagePart] = Field(\n", + " description=\"List of message parts that make up the message content.\")\n", + "\n", + " class Config:\n", + " extra = \"allow\"" + ] + }, + { + "cell_type": "markdown", + "id": "bd7b678f", + "metadata": {}, + "source": [ + "\n", + "## `gen_ai.input.messages` model\n", + "\n", + "Corresponding attribute: [`gen_ai.input.messages`](/docs/registry/attributes/gen-ai.md#gen-ai-input-messages).\n", + "JSON schema: [`gen_ai.input.messages.json`](../gen-ai-input-messages.json)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0133d3a6", + "metadata": {}, + "outputs": [], + "source": [ + "class InputMessages(RootModel[List[ChatMessage]]):\n", + " \"\"\"\n", + " Represents the list of input messages sent to the model.\n", + " \"\"\"\n", + " pass\n", + "\n", + "# Print the JSON schema for the InputMessages model\n", + "print(json.dumps(InputMessages.model_json_schema(), indent=4))" + ] + }, + { + "cell_type": "markdown", + "id": "033e5960", + "metadata": {}, + "source": [ + "## `gen_ai.output.messages` model\n", + "\n", + "Corresponding attribute: [`gen_ai.output.messages`](/docs/registry/attributes/gen-ai.md#gen-ai-output-messages).\n", + "JSON schema: [`gen_ai-output-messages.json`](../gen-ai-output-messages.json)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "12a12112", + "metadata": {}, + "outputs": [], + "source": [ + "class FinishReason(str, Enum):\n", + " \"\"\"\n", + " Represents the reason for finishing the generation.\n", + " \"\"\"\n", + "\n", + " STOP = \"stop\"\n", + " LENGTH = \"length\"\n", + " CONTENT_FILTER = \"content_filter\"\n", + " TOOL_CALL = \"tool_call\"\n", + " ERROR = \"error\"\n", + "\n", + "class OutputMessage(ChatMessage):\n", + " \"\"\"\n", + " Represents an output message generated by the model or agent. The output message captures\n", + " specific response (choice, candidate).\n", + " \"\"\"\n", + " finish_reason: Union[FinishReason, str] = Field(description=\"Reason for finishing the generation.\")\n", + "\n", + "class OutputMessages(RootModel[List[OutputMessage]]):\n", + " \"\"\"\n", + " Represents the list of output messages generated by the model or agent.\n", + " \"\"\"\n", + " pass\n", + "\n", + "# Print the JSON schema for the OutputMessages model\n", + "print(json.dumps(OutputMessages.model_json_schema(), indent=4))" + ] + }, + { + "cell_type": "markdown", + "id": "5c035888", + "metadata": {}, + "source": [ + "## `gen_ai.system_instructions` model\n", + "\n", + "Corresponding attribute: [`gen_ai.system_instructions`](/docs/registry/attributes/gen-ai.md#gen-ai-system-instructions).\n", + "JSON schema: [`gen_ai-system-instructions.json`](../gen-ai-system-instructions.json)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "faa33b95", + "metadata": {}, + "outputs": [], + "source": [ + "class SystemInstructions(RootModel[List[MessagePart]]):\n", + " \"\"\"\n", + " Represents the list of input messages sent to the model.\n", + " \"\"\"\n", + " pass\n", + "\n", + "# Print the JSON schema for the SystemInstructions model\n", + "print(json.dumps(SystemInstructions.model_json_schema(), indent=4))" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.5" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/gen-ai/openai.md b/docs/gen-ai/openai.md index e06b16bd82..ea111685c3 100644 --- a/docs/gen-ai/openai.md +++ b/docs/gen-ai/openai.md @@ -90,6 +90,9 @@ Semantic Conventions for [OpenAI](https://openai.com/) client spans extend and o | [`gen_ai.usage.output_tokens`](/docs/registry/attributes/gen-ai.md) | int | The number of tokens used in the GenAI response (completion). | `180` | `Recommended` | ![Development](https://img.shields.io/badge/-development-blue) | | [`openai.response.system_fingerprint`](/docs/registry/attributes/openai.md) | string | A fingerprint to track any eventual change in the Generative AI environment. | `fp_44709d6fcb` | `Recommended` | ![Development](https://img.shields.io/badge/-development-blue) | | [`server.address`](/docs/registry/attributes/server.md) | string | GenAI server address. [11] | `example.com`; `10.1.2.80`; `/tmp/my.sock` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`gen_ai.input.messages`](/docs/registry/attributes/gen-ai.md) | any | The chat history provided to the model as an input. [12] | [
  {
    "role": "user",
    "parts": [
      {
        "type": "text",
        "content": "Weather in Paris?"
      }
    ]
  },
  {
    "role": "assistant",
    "parts": [
      {
        "type": "tool_call",
        "id": "call_VSPygqKTWdrhaFErNvMV18Yl",
        "name": "get_weather",
        "arguments": {
          "location": "Paris"
        }
      }
    ]
  },
  {
    "role": "tool",
    "parts": [
      {
        "type": "tool_call_response",
        "id": " call_VSPygqKTWdrhaFErNvMV18Yl",
        "result": "rainy, 57°F"
      }
    ]
  }
] | `Opt-In` | ![Development](https://img.shields.io/badge/-development-blue) | +| [`gen_ai.output.messages`](/docs/registry/attributes/gen-ai.md) | any | Messages returned by the model where each message represents a specific model response (choice, candidate). [13] | [
  {
    "role": "assistant",
    "parts": [
      {
        "type": "text",
        "content": "The weather in Paris is currently rainy with a temperature of 57°F."
      }
    ],
    "finish_reason": "stop"
  }
] | `Opt-In` | ![Development](https://img.shields.io/badge/-development-blue) | +| [`gen_ai.system_instructions`](/docs/registry/attributes/gen-ai.md) | any | The system message or instructions provided to the GenAI model separately from the chat history. [14] | [
  {
    "type": "text",
    "content": "You are an Agent that greet users, always use greetings tool to respond"
  }
]; [
  {
    "type": "text",
    "content": "You are a language translator."
  },
  {
    "type": "text",
    "content": "Your mission is to translate text in English to French."
  }
] | `Opt-In` | ![Development](https://img.shields.io/badge/-development-blue) | **[1] `gen_ai.operation.name`:** If one of the predefined values applies, but specific system uses a different name it's RECOMMENDED to document it in the semantic conventions for specific GenAI system and use system-specific name in the instrumentation. If a different name is not documented, instrumentation libraries SHOULD use applicable predefined value. @@ -138,6 +141,62 @@ Additional output format details may be recorded in the future in the **[11] `server.address`:** When observed from the client side, and when communicating through an intermediary, `server.address` SHOULD represent the server address behind any intermediaries, for example proxies, if it's available. +**[12] `gen_ai.input.messages`:** Instrumentations MUST follow [Input messages JSON schema](/docs/gen-ai/gen-ai-input-messages.json). +When the attribute is recorded on events, it MUST be recorded in structured +form. When recorded on spans, it MAY be recorded as a JSON string if structured +format is not supported and SHOULD be recorded in structured form otherwise. + +Messages MUST be provided in the order they were sent to the model. +Instrumentations MAY provide a way for users to filter or truncate +input messages. + +> [!Warning] +> This attribute is likely to contain sensitive information including user/PII data. + +See [Recording content on attributes](/docs/gen-ai/gen-ai-spans.md#recording-content-on-attributes) +section for more details. + +**[13] `gen_ai.output.messages`:** Instrumentations MUST follow [Output messages JSON schema](/docs/gen-ai/gen-ai-output-messages.json) + +Each message represents a single output choice/candidate generated by +the model. Each message corresponds to exactly one generation +(choice/candidate) and vice versa - one choice cannot be split across +multiple messages or one message cannot contain parts from multiple choices. + +When the attribute is recorded on events, it MUST be recorded in structured +form. When recorded on spans, it MAY be recorded as a JSON string if structured +format is not supported and SHOULD be recorded in structured form otherwise. + +Instrumentations MAY provide a way for users to filter or truncate +output messages. + +> [!Warning] +> This attribute is likely to contain sensitive information including user/PII data. + +See [Recording content on attributes](/docs/gen-ai/gen-ai-spans.md#recording-content-on-attributes) +section for more details. + +**[14] `gen_ai.system_instructions`:** This attribute SHOULD be used when the corresponding provider or API +allows to provide system instructions or messages separately from the +chat history. + +Instructions that are part of the chat history SHOULD be recorded in +`gen_ai.input.messages` attribute instead. + +Instrumentations MUST follow [System instructions JSON schema](/docs/gen-ai/gen-ai-system-instructions.json). + +When recorded on spans, it MAY be recorded as a JSON string if structured +format is not supported and SHOULD be recorded in structured form otherwise. + +Instrumentations MAY provide a way for users to filter or truncate +system instructions. + +> [!Warning] +> This attribute may contain sensitive information. + +See [Recording content on attributes](/docs/gen-ai/gen-ai-spans.md#recording-content-on-attributes) +section for more details. + --- `error.type` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. diff --git a/docs/registry/attributes/gen-ai.md b/docs/registry/attributes/gen-ai.md index 4425237c90..b02050ac2c 100644 --- a/docs/registry/attributes/gen-ai.md +++ b/docs/registry/attributes/gen-ai.md @@ -18,11 +18,13 @@ This document defines the attributes used to describe telemetry in the context o | `gen_ai.agent.name` | string | Human-readable name of the GenAI agent provided by the application. | `Math Tutor`; `Fiction Writer` | ![Development](https://img.shields.io/badge/-development-blue) | | `gen_ai.conversation.id` | string | The unique identifier for a conversation (session, thread), used to store and correlate messages within this conversation. | `conv_5j66UpCpwteGg4YSxUnt7lPY` | ![Development](https://img.shields.io/badge/-development-blue) | | `gen_ai.data_source.id` | string | The data source identifier. [1] | `H7STPQYOND` | ![Development](https://img.shields.io/badge/-development-blue) | -| `gen_ai.operation.name` | string | The name of the operation being performed. [2] | `chat`; `generate_content`; `text_completion` | ![Development](https://img.shields.io/badge/-development-blue) | -| `gen_ai.output.type` | string | Represents the content type requested by the client. [3] | `text`; `json`; `image` | ![Development](https://img.shields.io/badge/-development-blue) | -| `gen_ai.provider.name` | string | The Generative AI provider as identified by the client or server instrumentation. [4] | `openai`; `gcp.gen_ai`; `gcp.vertex_ai` | ![Development](https://img.shields.io/badge/-development-blue) | +| `gen_ai.input.messages` | any | The chat history provided to the model as an input. [2] | [
  {
    "role": "user",
    "parts": [
      {
        "type": "text",
        "content": "Weather in Paris?"
      }
    ]
  },
  {
    "role": "assistant",
    "parts": [
      {
        "type": "tool_call",
        "id": "call_VSPygqKTWdrhaFErNvMV18Yl",
        "name": "get_weather",
        "arguments": {
          "location": "Paris"
        }
      }
    ]
  },
  {
    "role": "tool",
    "parts": [
      {
        "type": "tool_call_response",
        "id": " call_VSPygqKTWdrhaFErNvMV18Yl",
        "result": "rainy, 57°F"
      }
    ]
  }
] | ![Development](https://img.shields.io/badge/-development-blue) | +| `gen_ai.operation.name` | string | The name of the operation being performed. [3] | `chat`; `generate_content`; `text_completion` | ![Development](https://img.shields.io/badge/-development-blue) | +| `gen_ai.output.messages` | any | Messages returned by the model where each message represents a specific model response (choice, candidate). [4] | [
  {
    "role": "assistant",
    "parts": [
      {
        "type": "text",
        "content": "The weather in Paris is currently rainy with a temperature of 57°F."
      }
    ],
    "finish_reason": "stop"
  }
] | ![Development](https://img.shields.io/badge/-development-blue) | +| `gen_ai.output.type` | string | Represents the content type requested by the client. [5] | `text`; `json`; `image` | ![Development](https://img.shields.io/badge/-development-blue) | +| `gen_ai.provider.name` | string | The Generative AI provider as identified by the client or server instrumentation. [6] | `openai`; `gcp.gen_ai`; `gcp.vertex_ai` | ![Development](https://img.shields.io/badge/-development-blue) | | `gen_ai.request.choice.count` | int | The target number of candidate completions to return. | `3` | ![Development](https://img.shields.io/badge/-development-blue) | -| `gen_ai.request.encoding_formats` | string[] | The encoding formats requested in an embeddings operation, if specified. [5] | `["base64"]`; `["float", "binary"]` | ![Development](https://img.shields.io/badge/-development-blue) | +| `gen_ai.request.encoding_formats` | string[] | The encoding formats requested in an embeddings operation, if specified. [7] | `["base64"]`; `["float", "binary"]` | ![Development](https://img.shields.io/badge/-development-blue) | | `gen_ai.request.frequency_penalty` | double | The frequency penalty setting for the GenAI request. | `0.1` | ![Development](https://img.shields.io/badge/-development-blue) | | `gen_ai.request.max_tokens` | int | The maximum number of tokens the model generates for a request. | `100` | ![Development](https://img.shields.io/badge/-development-blue) | | `gen_ai.request.model` | string | The name of the GenAI model a request is being made to. | `gpt-4` | ![Development](https://img.shields.io/badge/-development-blue) | @@ -35,23 +37,59 @@ This document defines the attributes used to describe telemetry in the context o | `gen_ai.response.finish_reasons` | string[] | Array of reasons the model stopped generating tokens, corresponding to each generation received. | `["stop"]`; `["stop", "length"]` | ![Development](https://img.shields.io/badge/-development-blue) | | `gen_ai.response.id` | string | The unique identifier for the completion. | `chatcmpl-123` | ![Development](https://img.shields.io/badge/-development-blue) | | `gen_ai.response.model` | string | The name of the model that generated the response. | `gpt-4-0613` | ![Development](https://img.shields.io/badge/-development-blue) | +| `gen_ai.system_instructions` | any | The system message or instructions provided to the GenAI model separately from the chat history. [8] | [
  {
    "type": "text",
    "content": "You are an Agent that greet users, always use greetings tool to respond"
  }
]; [
  {
    "type": "text",
    "content": "You are a language translator."
  },
  {
    "type": "text",
    "content": "Your mission is to translate text in English to French."
  }
] | ![Development](https://img.shields.io/badge/-development-blue) | | `gen_ai.token.type` | string | The type of token being counted. | `input`; `output` | ![Development](https://img.shields.io/badge/-development-blue) | | `gen_ai.tool.call.id` | string | The tool call identifier. | `call_mszuSIzqtI65i1wAUOE8w5H4` | ![Development](https://img.shields.io/badge/-development-blue) | | `gen_ai.tool.description` | string | The tool description. | `Multiply two numbers` | ![Development](https://img.shields.io/badge/-development-blue) | | `gen_ai.tool.name` | string | Name of the tool utilized by the agent. | `Flights` | ![Development](https://img.shields.io/badge/-development-blue) | -| `gen_ai.tool.type` | string | Type of the tool utilized by the agent [6] | `function`; `extension`; `datastore` | ![Development](https://img.shields.io/badge/-development-blue) | +| `gen_ai.tool.type` | string | Type of the tool utilized by the agent [9] | `function`; `extension`; `datastore` | ![Development](https://img.shields.io/badge/-development-blue) | | `gen_ai.usage.input_tokens` | int | The number of tokens used in the GenAI input (prompt). | `100` | ![Development](https://img.shields.io/badge/-development-blue) | | `gen_ai.usage.output_tokens` | int | The number of tokens used in the GenAI response (completion). | `180` | ![Development](https://img.shields.io/badge/-development-blue) | **[1] `gen_ai.data_source.id`:** Data sources are used by AI agents and RAG applications to store grounding data. A data source may be an external database, object store, document collection, website, or any other storage system used by the GenAI agent or application. The `gen_ai.data_source.id` SHOULD match the identifier used by the GenAI system rather than a name specific to the external storage, such as a database or object store. Semantic conventions referencing `gen_ai.data_source.id` MAY also leverage additional attributes, such as `db.*`, to further identify and describe the data source. -**[2] `gen_ai.operation.name`:** If one of the predefined values applies, but specific system uses a different name it's RECOMMENDED to document it in the semantic conventions for specific GenAI system and use system-specific name in the instrumentation. If a different name is not documented, instrumentation libraries SHOULD use applicable predefined value. +**[2] `gen_ai.input.messages`:** Instrumentations MUST follow [Input messages JSON schema](/docs/gen-ai/gen-ai-input-messages.json). +When the attribute is recorded on events, it MUST be recorded in structured +form. When recorded on spans, it MAY be recorded as a JSON string if structured +format is not supported and SHOULD be recorded in structured form otherwise. -**[3] `gen_ai.output.type`:** This attribute SHOULD be used when the client requests output of a specific type. The model may return zero or more outputs of this type. +Messages MUST be provided in the order they were sent to the model. +Instrumentations MAY provide a way for users to filter or truncate +input messages. + +> [!Warning] +> This attribute is likely to contain sensitive information including user/PII data. + +See [Recording content on attributes](/docs/gen-ai/gen-ai-spans.md#recording-content-on-attributes) +section for more details. + +**[3] `gen_ai.operation.name`:** If one of the predefined values applies, but specific system uses a different name it's RECOMMENDED to document it in the semantic conventions for specific GenAI system and use system-specific name in the instrumentation. If a different name is not documented, instrumentation libraries SHOULD use applicable predefined value. + +**[4] `gen_ai.output.messages`:** Instrumentations MUST follow [Output messages JSON schema](/docs/gen-ai/gen-ai-output-messages.json) + +Each message represents a single output choice/candidate generated by +the model. Each message corresponds to exactly one generation +(choice/candidate) and vice versa - one choice cannot be split across +multiple messages or one message cannot contain parts from multiple choices. + +When the attribute is recorded on events, it MUST be recorded in structured +form. When recorded on spans, it MAY be recorded as a JSON string if structured +format is not supported and SHOULD be recorded in structured form otherwise. + +Instrumentations MAY provide a way for users to filter or truncate +output messages. + +> [!Warning] +> This attribute is likely to contain sensitive information including user/PII data. + +See [Recording content on attributes](/docs/gen-ai/gen-ai-spans.md#recording-content-on-attributes) +section for more details. + +**[5] `gen_ai.output.type`:** This attribute SHOULD be used when the client requests output of a specific type. The model may return zero or more outputs of this type. This attribute specifies the output modality and not the actual output format. For example, if an image is requested, the actual output could be a URL pointing to an image file. Additional output format details may be recorded in the future in the `gen_ai.output.{type}.*` attributes. -**[4] `gen_ai.provider.name`:** The attribute SHOULD be set based on the instrumentation's best +**[6] `gen_ai.provider.name`:** The attribute SHOULD be set based on the instrumentation's best knowledge and may differ from the actual model provider. Multiple providers, including Azure OpenAI, Gemini, and AI hosting platforms @@ -70,9 +108,30 @@ should have the `gen_ai.provider.name` set to `aws.bedrock` and include applicable `aws.bedrock.*` attributes and are not expected to include `openai.*` attributes. -**[5] `gen_ai.request.encoding_formats`:** In some GenAI systems the encoding formats are called embedding types. Also, some GenAI systems only accept a single format per request. +**[7] `gen_ai.request.encoding_formats`:** In some GenAI systems the encoding formats are called embedding types. Also, some GenAI systems only accept a single format per request. -**[6] `gen_ai.tool.type`:** Extension: A tool executed on the agent-side to directly call external APIs, bridging the gap between the agent and real-world systems. +**[8] `gen_ai.system_instructions`:** This attribute SHOULD be used when the corresponding provider or API +allows to provide system instructions or messages separately from the +chat history. + +Instructions that are part of the chat history SHOULD be recorded in +`gen_ai.input.messages` attribute instead. + +Instrumentations MUST follow [System instructions JSON schema](/docs/gen-ai/gen-ai-system-instructions.json). + +When recorded on spans, it MAY be recorded as a JSON string if structured +format is not supported and SHOULD be recorded in structured form otherwise. + +Instrumentations MAY provide a way for users to filter or truncate +system instructions. + +> [!Warning] +> This attribute may contain sensitive information. + +See [Recording content on attributes](/docs/gen-ai/gen-ai-spans.md#recording-content-on-attributes) +section for more details. + +**[9] `gen_ai.tool.type`:** Extension: A tool executed on the agent-side to directly call external APIs, bridging the gap between the agent and real-world systems. Agent-side operations involve actions that are performed by the agent on the server or within the agent's controlled environment. Function: A tool executed on the client-side, where the agent generates parameters for a predefined function, and the client executes the logic. Client-side operations are actions taken on the user's end or within the client application. @@ -115,9 +174,9 @@ Datastore: A tool used by the agent to access and query structured or unstructur | `azure.ai.openai` | [Azure OpenAI](https://azure.microsoft.com/products/ai-services/openai-service/) | ![Development](https://img.shields.io/badge/-development-blue) | | `cohere` | [Cohere](https://cohere.com/) | ![Development](https://img.shields.io/badge/-development-blue) | | `deepseek` | [DeepSeek](https://www.deepseek.com/) | ![Development](https://img.shields.io/badge/-development-blue) | -| `gcp.gemini` | [Gemini](https://cloud.google.com/products/gemini) [7] | ![Development](https://img.shields.io/badge/-development-blue) | -| `gcp.gen_ai` | Any Google generative AI endpoint [8] | ![Development](https://img.shields.io/badge/-development-blue) | -| `gcp.vertex_ai` | [Vertex AI](https://cloud.google.com/vertex-ai) [9] | ![Development](https://img.shields.io/badge/-development-blue) | +| `gcp.gemini` | [Gemini](https://cloud.google.com/products/gemini) [10] | ![Development](https://img.shields.io/badge/-development-blue) | +| `gcp.gen_ai` | Any Google generative AI endpoint [11] | ![Development](https://img.shields.io/badge/-development-blue) | +| `gcp.vertex_ai` | [Vertex AI](https://cloud.google.com/vertex-ai) [12] | ![Development](https://img.shields.io/badge/-development-blue) | | `groq` | [Groq](https://groq.com/) | ![Development](https://img.shields.io/badge/-development-blue) | | `ibm.watsonx.ai` | [IBM Watsonx AI](https://www.ibm.com/products/watsonx-ai) | ![Development](https://img.shields.io/badge/-development-blue) | | `mistral_ai` | [Mistral AI](https://mistral.ai/) | ![Development](https://img.shields.io/badge/-development-blue) | @@ -125,11 +184,11 @@ Datastore: A tool used by the agent to access and query structured or unstructur | `perplexity` | [Perplexity](https://www.perplexity.ai/) | ![Development](https://img.shields.io/badge/-development-blue) | | `x_ai` | [xAI](https://x.ai/) | ![Development](https://img.shields.io/badge/-development-blue) | -**[7]:** Used when accessing the 'generativelanguage.googleapis.com' endpoint. Also known as the AI Studio API. +**[10]:** Used when accessing the 'generativelanguage.googleapis.com' endpoint. Also known as the AI Studio API. -**[8]:** May be used when specific backend is unknown. +**[11]:** May be used when specific backend is unknown. -**[9]:** Used when accessing the 'aiplatform.googleapis.com' endpoint. +**[12]:** Used when accessing the 'aiplatform.googleapis.com' endpoint. --- @@ -166,20 +225,20 @@ Describes deprecated `gen_ai` attributes. | `azure.ai.openai` | Azure OpenAI | ![Development](https://img.shields.io/badge/-development-blue) | | `cohere` | Cohere | ![Development](https://img.shields.io/badge/-development-blue) | | `deepseek` | DeepSeek | ![Development](https://img.shields.io/badge/-development-blue) | -| `gcp.gemini` | Gemini [10] | ![Development](https://img.shields.io/badge/-development-blue) | -| `gcp.gen_ai` | Any Google generative AI endpoint [11] | ![Development](https://img.shields.io/badge/-development-blue) | -| `gcp.vertex_ai` | Vertex AI [12] | ![Development](https://img.shields.io/badge/-development-blue) | +| `gcp.gemini` | Gemini [13] | ![Development](https://img.shields.io/badge/-development-blue) | +| `gcp.gen_ai` | Any Google generative AI endpoint [14] | ![Development](https://img.shields.io/badge/-development-blue) | +| `gcp.vertex_ai` | Vertex AI [15] | ![Development](https://img.shields.io/badge/-development-blue) | | `groq` | Groq | ![Development](https://img.shields.io/badge/-development-blue) | | `ibm.watsonx.ai` | IBM Watsonx AI | ![Development](https://img.shields.io/badge/-development-blue) | | `mistral_ai` | Mistral AI | ![Development](https://img.shields.io/badge/-development-blue) | | `openai` | OpenAI | ![Development](https://img.shields.io/badge/-development-blue) | | `perplexity` | Perplexity | ![Development](https://img.shields.io/badge/-development-blue) | -**[10]:** This refers to the 'generativelanguage.googleapis.com' endpoint. Also known as the AI Studio API. May use common attributes prefixed with 'gcp.gen_ai.'. +**[13]:** This refers to the 'generativelanguage.googleapis.com' endpoint. Also known as the AI Studio API. May use common attributes prefixed with 'gcp.gen_ai.'. -**[11]:** May be used when specific backend is unknown. May use common attributes prefixed with 'gcp.gen_ai.'. +**[14]:** May be used when specific backend is unknown. May use common attributes prefixed with 'gcp.gen_ai.'. -**[12]:** This refers to the 'aiplatform.googleapis.com' endpoint. May use common attributes prefixed with 'gcp.gen_ai.'. +**[15]:** This refers to the 'aiplatform.googleapis.com' endpoint. May use common attributes prefixed with 'gcp.gen_ai.'. ## Deprecated OpenAI GenAI Attributes diff --git a/model/gen-ai/deprecated/events-deprecated.yaml b/model/gen-ai/deprecated/events-deprecated.yaml new file mode 100644 index 0000000000..281d7ec1b9 --- /dev/null +++ b/model/gen-ai/deprecated/events-deprecated.yaml @@ -0,0 +1,340 @@ +groups: + - id: gen_ai.deprecated.event.attributes + type: attribute_group + stability: development + brief: > + Describes common Gen AI event attributes. + attributes: + - ref: gen_ai.system + + - id: event.gen_ai.system.message + name: gen_ai.system.message + type: event + stability: development + deprecated: + reason: uncategorized + note: > + Chat history is reported on `gen_ai.system_instructions` attribute on + spans or `gen_ai.client.inference.operation.details` event. + brief: > + This event describes the system instructions passed to the GenAI model. + extends: gen_ai.common.event.attributes + body: + id: gen_ai.system.message + requirement_level: opt_in + stability: development + type: map + fields: + - id: content + type: undefined + stability: development + brief: > + The contents of the system message. + examples: ["You're a helpful bot"] + requirement_level: opt_in + - id: role + type: string + stability: development + brief: > + The actual role of the message author as passed in the message. + examples: ["system", "instruction"] + requirement_level: + conditionally_required: if available and not equal to `system`. + + - id: event.gen_ai.user.message + name: gen_ai.user.message + type: event + stability: development + brief: > + This event describes the user message passed to the GenAI model. + deprecated: + reason: uncategorized + note: > + Chat history is reported on `gen_ai.input.messages` attribute on spans + or `gen_ai.client.inference.operation.details` event. + extends: gen_ai.common.event.attributes + body: + id: gen_ai.user.message + requirement_level: opt_in + stability: development + type: map + fields: + - id: content + type: undefined + stability: development + brief: > + The contents of the user message. + examples: ["What's the weather in Paris?"] + requirement_level: opt_in + - id: role + type: string + stability: development + brief: > + The actual role of the message author as passed in the message. + examples: ["user", "customer"] + requirement_level: + conditionally_required: if available and not equal to `user`. + + - id: event.gen_ai.assistant.message + name: gen_ai.assistant.message + type: event + stability: development + brief: > + This event describes the assistant message passed to GenAI system. + deprecated: + reason: uncategorized + note: > + Chat history is reported on `gen_ai.input.messages` attribute on spans + or `gen_ai.client.inference.operation.details` event. + extends: gen_ai.common.event.attributes + body: + id: gen_ai.assistant.message + requirement_level: opt_in + stability: development + type: map + fields: + - id: content + type: undefined + stability: development + brief: > + The contents of the tool message. + examples: ["The weather in Paris is rainy and overcast, with temperatures around 57°F"] + requirement_level: opt_in + - id: role + type: string + stability: development + brief: > + The actual role of the message author as passed in the message. + examples: ["assistant", "bot"] + requirement_level: + conditionally_required: if available and not equal to `assistant`. + - id: tool_calls + type: map[] + stability: development + brief: > + The tool calls generated by the model, such as function calls. + requirement_level: + conditionally_required: if available + fields: + - id: id + type: string + stability: development + brief: > + The id of the tool call. + examples: ["call_mszuSIzqtI65i1wAUOE8w5H4"] + requirement_level: required + - id: type + type: enum + members: + - id: function + value: 'function' + brief: Function + stability: development + stability: development + brief: > + The type of the tool. + examples: ["function"] + requirement_level: required + - id: function + type: map + stability: development + brief: > + The function call. + requirement_level: required + fields: + - id: name + type: string + stability: development + brief: > + The name of the function. + examples: ["get_weather"] + requirement_level: required + - id: arguments + type: undefined + stability: development + brief: > + The arguments of the function as provided in the LLM response. + note: > + Models usually return arguments as a JSON string. In this case, it's + RECOMMENDED to provide arguments as is without attempting to deserialize them. + + Semantic conventions for individual systems MAY specify a different type for + arguments field. + examples: ['{\"location\": \"Paris\"}'] + requirement_level: opt_in + + - id: event.gen_ai.tool.message + name: gen_ai.tool.message + type: event + stability: development + brief: > + This event describes the response from a tool or function call passed to the GenAI model. + extends: gen_ai.common.event.attributes + deprecated: + reason: uncategorized + note: > + Chat history is reported on `gen_ai.input.messages` attribute on spans + or `gen_ai.client.inference.operation.details` event. + body: + id: gen_ai.tool.message + requirement_level: opt_in + stability: development + type: map + fields: + - id: content + type: undefined + stability: development + brief: > + The contents of the tool message. + examples: ["rainy, 57°F"] + requirement_level: opt_in + - id: role + type: string + stability: development + brief: > + The actual role of the message author as passed in the message. + examples: ["tool", "function"] + requirement_level: + conditionally_required: if available and not equal to `tool`. + - id: id + type: string + stability: development + brief: > + Tool call id that this message is responding to. + examples: ["call_mszuSIzqtI65i1wAUOE8w5H4"] + requirement_level: required + + - id: event.gen_ai.choice + name: gen_ai.choice + type: event + stability: development + brief: > + This event describes the Gen AI response message. + deprecated: + reason: uncategorized + note: > + Chat history is reported on `gen_ai.output.messages` attribute on spans + or `gen_ai.client.inference.operation.details` event. + extends: gen_ai.common.event.attributes + body: + id: gen_ai.choice + requirement_level: opt_in + stability: development + type: map + note: > + If GenAI model returns multiple choices, each choice SHOULD be recorded as an individual event. + When response is streamed, instrumentations that report response events MUST reconstruct and report + the full message and MUST NOT report individual chunks as events. + If the request to GenAI model fails with an error before content is received, + instrumentation SHOULD report an event with truncated content (if enabled). + If `finish_reason` was not received, it MUST be set to `error`. + fields: + - id: index + type: int + stability: development + brief: > + The index of the choice in the list of choices. + examples: [0, 1] + requirement_level: required + - id: finish_reason + type: enum + members: + - id: stop + value: 'stop' + stability: development + brief: Stop + - id: tool_calls + value: 'tool_calls' + stability: development + brief: Tool Calls + - id: content_filter + value: 'content_filter' + stability: development + brief: Content Filter + - id: length + value: 'length' + stability: development + brief: Length + - id: error + value: 'error' + stability: development + brief: Error + stability: development + brief: > + The reason the model stopped generating tokens. + requirement_level: required + - id: message + type: map + stability: development + brief: > + GenAI response message. + requirement_level: recommended + fields: + - id: content + type: undefined + stability: development + brief: > + The contents of the assistant message. + examples: ["The weather in Paris is rainy and overcast, with temperatures around 57°F"] + requirement_level: opt_in + - id: role + type: string + stability: development + brief: > + The actual role of the message author as passed in the message. + examples: ["assistant", "bot"] + requirement_level: + conditionally_required: if available and not equal to `assistant`. + - id: tool_calls + type: map[] + stability: development + brief: > + The tool calls generated by the model, such as function calls. + requirement_level: + conditionally_required: if available + fields: + - id: id + type: string + stability: development + brief: > + The id of the tool call. + examples: ["call_mszuSIzqtI65i1wAUOE8w5H4"] + requirement_level: required + - id: type + type: enum + members: + - id: function + value: 'function' + brief: Function + stability: development + stability: development + brief: > + The type of the tool. + requirement_level: required + - id: function + type: map + stability: development + brief: > + The function that the model called. + requirement_level: required + fields: + - id: name + type: string + stability: development + brief: > + The name of the function. + examples: ["get_weather"] + requirement_level: required + - id: arguments + type: undefined + stability: development + brief: > + The arguments of the function as provided in the LLM response. + note: > + Models usually return arguments as a JSON string. In this case, it's + RECOMMENDED to provide arguments as is without attempting to deserialize them. + + Semantic conventions for individual systems MAY specify a different type for + arguments field. + examples: ['{\"location\": \"Paris\"}'] + requirement_level: opt_in diff --git a/model/gen-ai/deprecated/registry-deprecated.yaml b/model/gen-ai/deprecated/registry-deprecated.yaml index 876412a7ff..9ff1803571 100644 --- a/model/gen-ai/deprecated/registry-deprecated.yaml +++ b/model/gen-ai/deprecated/registry-deprecated.yaml @@ -1,4 +1,12 @@ groups: + - id: gen_ai.common.event.attributes + type: attribute_group + stability: development + brief: > + Describes common Gen AI event attributes. + attributes: + - ref: gen_ai.system + - id: registry.gen_ai.deprecated type: attribute_group brief: Describes deprecated `gen_ai` attributes. diff --git a/model/gen-ai/events.yaml b/model/gen-ai/events.yaml index 0f72e19b5e..bb4cde64cc 100644 --- a/model/gen-ai/events.yaml +++ b/model/gen-ai/events.yaml @@ -1,315 +1,12 @@ groups: - - id: gen_ai.common.event.attributes - type: attribute_group - stability: development - brief: > - Describes common Gen AI event attributes. - attributes: - - ref: gen_ai.provider.name - - - id: event.gen_ai.system.message - name: gen_ai.system.message - type: event - stability: development - brief: > - This event describes the system instructions passed to the GenAI model. - extends: gen_ai.common.event.attributes - body: - id: gen_ai.system.message - requirement_level: opt_in - stability: development - type: map - fields: - - id: content - type: undefined - stability: development - brief: > - The contents of the system message. - examples: ["You're a helpful bot"] - requirement_level: opt_in - - id: role - type: string - stability: development - brief: > - The actual role of the message author as passed in the message. - examples: ["system", "instruction"] - requirement_level: - conditionally_required: if available and not equal to `system`. - - - id: event.gen_ai.user.message - name: gen_ai.user.message - type: event - stability: development - brief: > - This event describes the user message passed to the GenAI model. - extends: gen_ai.common.event.attributes - body: - id: gen_ai.user.message - requirement_level: opt_in - stability: development - type: map - fields: - - id: content - type: undefined - stability: development - brief: > - The contents of the user message. - examples: ["What's the weather in Paris?"] - requirement_level: opt_in - - id: role - type: string - stability: development - brief: > - The actual role of the message author as passed in the message. - examples: ["user", "customer"] - requirement_level: - conditionally_required: if available and not equal to `user`. - - - id: event.gen_ai.assistant.message - name: gen_ai.assistant.message - type: event - stability: development - brief: > - This event describes the assistant message passed to GenAI system. - extends: gen_ai.common.event.attributes - body: - id: gen_ai.assistant.message - requirement_level: opt_in - stability: development - type: map - fields: - - id: content - type: undefined - stability: development - brief: > - The contents of the tool message. - examples: ["The weather in Paris is rainy and overcast, with temperatures around 57°F"] - requirement_level: opt_in - - id: role - type: string - stability: development - brief: > - The actual role of the message author as passed in the message. - examples: ["assistant", "bot"] - requirement_level: - conditionally_required: if available and not equal to `assistant`. - - id: tool_calls - type: map[] - stability: development - brief: > - The tool calls generated by the model, such as function calls. - requirement_level: - conditionally_required: if available - fields: - - id: id - type: string - stability: development - brief: > - The id of the tool call. - examples: ["call_mszuSIzqtI65i1wAUOE8w5H4"] - requirement_level: required - - id: type - type: enum - members: - - id: function - value: 'function' - brief: Function - stability: development - stability: development - brief: > - The type of the tool. - examples: ["function"] - requirement_level: required - - id: function - type: map - stability: development - brief: > - The function call. - requirement_level: required - fields: - - id: name - type: string - stability: development - brief: > - The name of the function. - examples: ["get_weather"] - requirement_level: required - - id: arguments - type: undefined - stability: development - brief: > - The arguments of the function as provided in the LLM response. - note: > - Models usually return arguments as a JSON string. In this case, it's - RECOMMENDED to provide arguments as is without attempting to deserialize them. - - Semantic conventions for individual systems MAY specify a different type for - arguments field. - examples: ['{\"location\": \"Paris\"}'] - requirement_level: opt_in - - - id: event.gen_ai.tool.message - name: gen_ai.tool.message - type: event - stability: development - brief: > - This event describes the response from a tool or function call passed to the GenAI model. - extends: gen_ai.common.event.attributes - body: - id: gen_ai.tool.message - requirement_level: opt_in - stability: development - type: map - fields: - - id: content - type: undefined - stability: development - brief: > - The contents of the tool message. - examples: ["rainy, 57°F"] - requirement_level: opt_in - - id: role - type: string - stability: development - brief: > - The actual role of the message author as passed in the message. - examples: ["tool", "function"] - requirement_level: - conditionally_required: if available and not equal to `tool`. - - id: id - type: string - stability: development - brief: > - Tool call id that this message is responding to. - examples: ["call_mszuSIzqtI65i1wAUOE8w5H4"] - requirement_level: required - - - id: event.gen_ai.choice - name: gen_ai.choice + - id: event.gen_ai.client.inference.operation.details + name: gen_ai.client.inference.operation.details type: event stability: development brief: > - This event describes the Gen AI response message. - extends: gen_ai.common.event.attributes - body: - id: gen_ai.choice - requirement_level: opt_in - stability: development - type: map - note: > - If GenAI model returns multiple choices, each choice SHOULD be recorded as an individual event. - When response is streamed, instrumentations that report response events MUST reconstruct and report - the full message and MUST NOT report individual chunks as events. - If the request to GenAI model fails with an error before content is received, - instrumentation SHOULD report an event with truncated content (if enabled). - If `finish_reason` was not received, it MUST be set to `error`. - fields: - - id: index - type: int - stability: development - brief: > - The index of the choice in the list of choices. - examples: [0, 1] - requirement_level: required - - id: finish_reason - type: enum - members: - - id: stop - value: 'stop' - stability: development - brief: Stop - - id: tool_calls - value: 'tool_calls' - stability: development - brief: Tool Calls - - id: content_filter - value: 'content_filter' - stability: development - brief: Content Filter - - id: length - value: 'length' - stability: development - brief: Length - - id: error - value: 'error' - stability: development - brief: Error - stability: development - brief: > - The reason the model stopped generating tokens. - requirement_level: required - - id: message - type: map - stability: development - brief: > - GenAI response message. - requirement_level: recommended - fields: - - id: content - type: undefined - stability: development - brief: > - The contents of the assistant message. - examples: ["The weather in Paris is rainy and overcast, with temperatures around 57°F"] - requirement_level: opt_in - - id: role - type: string - stability: development - brief: > - The actual role of the message author as passed in the message. - examples: ["assistant", "bot"] - requirement_level: - conditionally_required: if available and not equal to `assistant`. - - id: tool_calls - type: map[] - stability: development - brief: > - The tool calls generated by the model, such as function calls. - requirement_level: - conditionally_required: if available - fields: - - id: id - type: string - stability: development - brief: > - The id of the tool call. - examples: ["call_mszuSIzqtI65i1wAUOE8w5H4"] - requirement_level: required - - id: type - type: enum - members: - - id: function - value: 'function' - brief: Function - stability: development - stability: development - brief: > - The type of the tool. - requirement_level: required - - id: function - type: map - stability: development - brief: > - The function that the model called. - requirement_level: required - fields: - - id: name - type: string - stability: development - brief: > - The name of the function. - examples: ["get_weather"] - requirement_level: required - - id: arguments - type: undefined - stability: development - brief: > - The arguments of the function as provided in the LLM response. - note: > - Models usually return arguments as a JSON string. In this case, it's - RECOMMENDED to provide arguments as is without attempting to deserialize them. - - Semantic conventions for individual systems MAY specify a different type for - arguments field. - examples: ['{\"location\": \"Paris\"}'] - requirement_level: opt_in + Describes the details of a GenAI completion request including chat history + and parameters. + note: > + This event is opt-in and could be used to store input and output details + independently from traces. + extends: attributes.gen_ai.inference.client diff --git a/model/gen-ai/registry.yaml b/model/gen-ai/registry.yaml index 433d5736bd..84c735f655 100644 --- a/model/gen-ai/registry.yaml +++ b/model/gen-ai/registry.yaml @@ -332,3 +332,143 @@ groups: Additional output format details may be recorded in the future in the `gen_ai.output.{type}.*` attributes. + - id: gen_ai.system_instructions + stability: development + type: any + brief: The system message or instructions provided to the GenAI model + separately from the chat history. + note: | + This attribute SHOULD be used when the corresponding provider or API + allows to provide system instructions or messages separately from the + chat history. + + Instructions that are part of the chat history SHOULD be recorded in + `gen_ai.input.messages` attribute instead. + + Instrumentations MUST follow [System instructions JSON schema](/docs/gen-ai/gen-ai-system-instructions.json). + + When recorded on spans, it MAY be recorded as a JSON string if structured + format is not supported and SHOULD be recorded in structured form otherwise. + + Instrumentations MAY provide a way for users to filter or truncate + system instructions. + + > [!Warning] + > This attribute may contain sensitive information. + + See [Recording content on attributes](/docs/gen-ai/gen-ai-spans.md#recording-content-on-attributes) + section for more details. + examples: + - | + [ + { + "type": "text", + "content": "You are an Agent that greet users, always use greetings tool to respond" + } + ] + - | + [ + { + "type": "text", + "content": "You are a language translator." + }, + { + "type": "text", + "content": "Your mission is to translate text in English to French." + } + ] + - id: gen_ai.input.messages + stability: development + type: any + brief: > + The chat history provided to the model as an input. + note: | + Instrumentations MUST follow [Input messages JSON schema](/docs/gen-ai/gen-ai-input-messages.json). + When the attribute is recorded on events, it MUST be recorded in structured + form. When recorded on spans, it MAY be recorded as a JSON string if structured + format is not supported and SHOULD be recorded in structured form otherwise. + + Messages MUST be provided in the order they were sent to the model. + Instrumentations MAY provide a way for users to filter or truncate + input messages. + + > [!Warning] + > This attribute is likely to contain sensitive information including user/PII data. + + See [Recording content on attributes](/docs/gen-ai/gen-ai-spans.md#recording-content-on-attributes) + section for more details. + examples: + - | + [ + { + "role": "user", + "parts": [ + { + "type": "text", + "content": "Weather in Paris?" + } + ] + }, + { + "role": "assistant", + "parts": [ + { + "type": "tool_call", + "id": "call_VSPygqKTWdrhaFErNvMV18Yl", + "name": "get_weather", + "arguments": { + "location": "Paris" + } + } + ] + }, + { + "role": "tool", + "parts": [ + { + "type": "tool_call_response", + "id": " call_VSPygqKTWdrhaFErNvMV18Yl", + "result": "rainy, 57°F" + } + ] + } + ] + - id: gen_ai.output.messages + stability: development + type: any + brief: Messages returned by the model where each message represents + a specific model response (choice, candidate). + note: | + Instrumentations MUST follow [Output messages JSON schema](/docs/gen-ai/gen-ai-output-messages.json) + + Each message represents a single output choice/candidate generated by + the model. Each message corresponds to exactly one generation + (choice/candidate) and vice versa - one choice cannot be split across + multiple messages or one message cannot contain parts from multiple choices. + + When the attribute is recorded on events, it MUST be recorded in structured + form. When recorded on spans, it MAY be recorded as a JSON string if structured + format is not supported and SHOULD be recorded in structured form otherwise. + + Instrumentations MAY provide a way for users to filter or truncate + output messages. + + > [!Warning] + > This attribute is likely to contain sensitive information including user/PII data. + + See [Recording content on attributes](/docs/gen-ai/gen-ai-spans.md#recording-content-on-attributes) + section for more details. + examples: + - | + [ + { + "role": "assistant", + "parts": [ + { + "type": "text", + "content": "The weather in Paris is currently rainy with a temperature of 57°F." + } + ], + "finish_reason": "stop" + } + ] diff --git a/model/gen-ai/spans.yaml b/model/gen-ai/spans.yaml index 902204ba6e..07bcf43ec9 100644 --- a/model/gen-ai/spans.yaml +++ b/model/gen-ai/spans.yaml @@ -89,6 +89,13 @@ groups: spans or logs using custom span or log record processors or hooks provided by instrumentation libraries. + - ref: gen_ai.system_instructions + requirement_level: opt_in + - ref: gen_ai.input.messages + requirement_level: opt_in + - ref: gen_ai.output.messages + requirement_level: opt_in + - id: span.gen_ai.inference.client type: span stability: development @@ -231,6 +238,9 @@ groups: - ref: gen_ai.agent.description requirement_level: conditionally_required: If provided by the application. + - ref: gen_ai.system_instructions + requirement_level: opt_in + note: "" # note is not needed here - id: span.gen_ai.invoke_agent.client type: span @@ -260,6 +270,12 @@ groups: - ref: gen_ai.data_source.id requirement_level: conditionally_required: if applicable. + - ref: gen_ai.system_instructions + requirement_level: opt_in + - ref: gen_ai.input.messages + requirement_level: opt_in + - ref: gen_ai.output.messages + requirement_level: opt_in - id: span.gen_ai.execute_tool.internal type: span diff --git a/templates/registry/markdown/event_macros.j2 b/templates/registry/markdown/event_macros.j2 index ad054ace31..87cef4737a 100644 --- a/templates/registry/markdown/event_macros.j2 +++ b/templates/registry/markdown/event_macros.j2 @@ -17,7 +17,7 @@ The event SHOULD be associated with one of the following entities: {% endfor %} {% endif %} {% endmacro %} -{% macro body(body) %}{% if body %}**Body fields:** +{% macro body(body) %}{% if body and body.type != "undefined" %}**Body fields:** :warning: Body fields will be moved to complex attributes once the semantic convention tooling supports complex attributes diff --git a/templates/registry/markdown/examples_macros.j2 b/templates/registry/markdown/examples_macros.j2 index bbd840d67f..bd4ed1cc6c 100644 --- a/templates/registry/markdown/examples_macros.j2 +++ b/templates/registry/markdown/examples_macros.j2 @@ -1,4 +1,23 @@ -{% macro print_examples(examples) %}{%- for e in examples %}{%if loop.first == false %}; {% endif %}`{{ e | trim }}`{%- endfor %}{% endmacro %} +{%- macro escape_multiline_markdown_cell(value) -%} + {%- if '\n' in value -%} + {%- for line in value.split('\n') -%} + {%- set rendered = '' -%} + {%- set ns = namespace(started=False,rendered='') -%} + {%- for c in line -%} + {%- if not ns.started and c == ' ' -%} + {%- set ns.rendered = ns.rendered ~ ' ' -%} + {%- else -%} + {%- set ns.rendered = ns.rendered ~ c-%} + {%- set ns.started = True -%} + {%- endif -%} + {%- endfor -%} + {{ ns.rendered }}{%- if not loop.last -%}
{% endif -%} + {%- endfor -%} + {%- else -%} + `{{- value }}` + {%- endif -%} +{%- endmacro -%} +{% macro print_examples(examples) %}{%- for e in examples %}{%if loop.first == false %}; {% endif %}{{ escape_multiline_markdown_cell(e | trim) }}{%- endfor %}{% endmacro %} {% macro format(item) %}{%- if item.examples %} {%- if "[]" in item.type and "template" not in item.type %}