Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Unreleased

- Fix `AttributeError` when handling `LegacyAPIResponse` (from `with_raw_response`)
([#4002](https://github.com/open-telemetry/opentelemetry-python-contrib/issues/4002))
([#4017](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/4017))
- Add support for chat completions choice count and stop sequences span attributes
([#4028](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/4028))

## Version 2.2b0 (2025-11-25)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,8 @@ def get_llm_request_attributes(
client_instance,
operation_name=GenAIAttributes.GenAiOperationNameValues.CHAT.value,
):
# pylint: disable=too-many-branches

attributes = {
GenAIAttributes.GEN_AI_OPERATION_NAME: operation_name,
GenAIAttributes.GEN_AI_SYSTEM: GenAIAttributes.GenAiSystemValues.OPENAI.value,
Expand Down Expand Up @@ -222,6 +224,20 @@ def get_llm_request_attributes(
}
)

if (choice_count := kwargs.get("n")) is not None:
# Only add non default, meaningful values
if isinstance(choice_count, int) and choice_count != 1:
attributes[GenAIAttributes.GEN_AI_REQUEST_CHOICE_COUNT] = (
choice_count
)

if (stop_sequences := kwargs.get("stop")) is not None:
if isinstance(stop_sequences, str):
stop_sequences = [stop_sequences]
attributes[GenAIAttributes.GEN_AI_REQUEST_STOP_SEQUENCES] = (
stop_sequences
)

if (response_format := kwargs.get("response_format")) is not None:
# response_format may be string or object with a string in the `type` key
if isinstance(response_format, Mapping):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
interactions:
- request:
body: |-
{
"messages": [
{
"role": "user",
"content": "Say this is a test"
}
],
"model": "gpt-4o-mini",
"stop": "stop"
}
headers:
Accept:
- application/json
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
Content-Length:
- '105'
Content-Type:
- application/json
Host:
- api.openai.com
User-Agent:
- OpenAI/Python 1.109.1
X-Stainless-Arch:
- x64
X-Stainless-Async:
- 'false'
X-Stainless-Lang:
- python
X-Stainless-OS:
- Linux
X-Stainless-Package-Version:
- 1.109.1
X-Stainless-Runtime:
- CPython
X-Stainless-Runtime-Version:
- 3.12.12
authorization:
- Bearer test_openai_api_key
x-stainless-read-timeout:
- '600'
x-stainless-retry-count:
- '0'
method: POST
uri: https://api.openai.com/v1/chat/completions
response:
body:
string: |-
{
"id": "chatcmpl-Clubs1bbZwGUeDKpnPUWDMEhSbquh",
"object": "chat.completion",
"created": 1765535060,
"model": "gpt-4o-mini-2024-07-18",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "This is a test. How can I assist you further?",
"refusal": null,
"annotations": []
},
"logprobs": null,
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 12,
"completion_tokens": 12,
"total_tokens": 24,
"prompt_tokens_details": {
"cached_tokens": 0,
"audio_tokens": 0
},
"completion_tokens_details": {
"reasoning_tokens": 0,
"audio_tokens": 0,
"accepted_prediction_tokens": 0,
"rejected_prediction_tokens": 0
}
},
"service_tier": "default",
"system_fingerprint": "fp_11f3029f6b"
}
headers:
CF-RAY:
- 9acc82e96fde4bf3-MXP
Connection:
- keep-alive
Content-Type:
- application/json
Date:
- Fri, 12 Dec 2025 10:24:20 GMT
Server:
- cloudflare
Set-Cookie: test_set_cookie
Strict-Transport-Security:
- max-age=31536000; includeSubDomains; preload
Transfer-Encoding:
- chunked
X-Content-Type-Options:
- nosniff
access-control-expose-headers:
- X-Request-ID
alt-svc:
- h3=":443"; ma=86400
cf-cache-status:
- DYNAMIC
content-length:
- '852'
openai-organization: test_openai_org_id
openai-processing-ms:
- '500'
openai-project:
- proj_Pf1eM5R55Z35wBy4rt8PxAGq
openai-version:
- '2020-10-01'
x-envoy-upstream-service-time:
- '826'
x-openai-proxy-wasm:
- v0.1
x-ratelimit-limit-requests:
- '10000'
x-ratelimit-limit-tokens:
- '10000000'
x-ratelimit-remaining-requests:
- '9999'
x-ratelimit-remaining-tokens:
- '9999993'
x-ratelimit-reset-requests:
- 6ms
x-ratelimit-reset-tokens:
- 0s
x-request-id:
- req_993163a7581641b7b9aee6e03ef4ca3a
status:
code: 200
message: OK
version: 1
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
interactions:
- request:
body: |-
{
"messages": [
{
"role": "user",
"content": "Say this is a test"
}
],
"model": "gpt-4o-mini",
"n": 1
}
headers:
Accept:
- application/json
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
Content-Length:
- '97'
Content-Type:
- application/json
Host:
- api.openai.com
User-Agent:
- OpenAI/Python 1.109.1
X-Stainless-Arch:
- x64
X-Stainless-Async:
- 'false'
X-Stainless-Lang:
- python
X-Stainless-OS:
- Linux
X-Stainless-Package-Version:
- 1.109.1
X-Stainless-Runtime:
- CPython
X-Stainless-Runtime-Version:
- 3.12.12
authorization:
- Bearer test_openai_api_key
x-stainless-read-timeout:
- '600'
x-stainless-retry-count:
- '0'
method: POST
uri: https://api.openai.com/v1/chat/completions
response:
body:
string: |-
{
"id": "chatcmpl-ClubqNLub25QPdqxjOslny04PLCYZ",
"object": "chat.completion",
"created": 1765535058,
"model": "gpt-4o-mini-2024-07-18",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "This is a test. How can I assist you today?",
"refusal": null,
"annotations": []
},
"logprobs": null,
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 12,
"completion_tokens": 12,
"total_tokens": 24,
"prompt_tokens_details": {
"cached_tokens": 0,
"audio_tokens": 0
},
"completion_tokens_details": {
"reasoning_tokens": 0,
"audio_tokens": 0,
"accepted_prediction_tokens": 0,
"rejected_prediction_tokens": 0
}
},
"service_tier": "default",
"system_fingerprint": "fp_11f3029f6b"
}
headers:
CF-RAY:
- 9acc82ddddd4edba-MXP
Connection:
- keep-alive
Content-Type:
- application/json
Date:
- Fri, 12 Dec 2025 10:24:19 GMT
Server:
- cloudflare
Set-Cookie: test_set_cookie
Strict-Transport-Security:
- max-age=31536000; includeSubDomains; preload
Transfer-Encoding:
- chunked
X-Content-Type-Options:
- nosniff
access-control-expose-headers:
- X-Request-ID
alt-svc:
- h3=":443"; ma=86400
cf-cache-status:
- DYNAMIC
content-length:
- '850'
openai-organization: test_openai_org_id
openai-processing-ms:
- '405'
openai-project:
- proj_Pf1eM5R55Z35wBy4rt8PxAGq
openai-version:
- '2020-10-01'
x-envoy-upstream-service-time:
- '529'
x-openai-proxy-wasm:
- v0.1
x-ratelimit-limit-requests:
- '10000'
x-ratelimit-limit-tokens:
- '10000000'
x-ratelimit-remaining-requests:
- '9999'
x-ratelimit-remaining-tokens:
- '9999993'
x-ratelimit-reset-requests:
- 6ms
x-ratelimit-reset-tokens:
- 0s
x-request-id:
- req_2b15771f24a4465fb5fc43b797f39e04
status:
code: 200
message: OK
version: 1
Loading