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 @@ -25,6 +25,7 @@
GEN_AI_OPENAI_REQUEST_SERVICE_TIER,
GEN_AI_OPENAI_RESPONSE_SERVICE_TIER,
GEN_AI_OPERATION_NAME,
GEN_AI_REQUEST_CHOICE_COUNT,
GEN_AI_REQUEST_FREQUENCY_PENALTY,
GEN_AI_REQUEST_MAX_TOKENS,
GEN_AI_REQUEST_MODEL,
Expand Down Expand Up @@ -141,6 +142,8 @@ def _is_set(value):
if client := getattr(instance, "_client", None):
span_attributes.update(_attributes_from_client(client))

if _is_set(choice_count := kwargs.get("n")) and choice_count != 1:
span_attributes[GEN_AI_REQUEST_CHOICE_COUNT] = choice_count
if _is_set(frequency_penalty := kwargs.get("frequency_penalty")):
span_attributes[GEN_AI_REQUEST_FREQUENCY_PENALTY] = frequency_penalty
if _is_set(max_tokens := kwargs.get("max_completion_tokens", kwargs.get("max_tokens"))):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
interactions:
- request:
body: |-
{
"messages": [
{
"role": "user",
"content": "Answer in up to 3 words: Which ocean contains Bouvet Island?"
}
],
"model": "gpt-4o-mini",
"n": 1
}
headers:
accept:
- application/json
accept-encoding:
- gzip, deflate, zstd
authorization:
- Bearer test_openai_api_key
connection:
- keep-alive
content-length:
- '139'
content-type:
- application/json
host:
- api.openai.com
user-agent:
- OpenAI/Python 1.66.5
x-stainless-arch:
- arm64
x-stainless-async:
- 'false'
x-stainless-lang:
- python
x-stainless-os:
- MacOS
x-stainless-package-version:
- 1.66.5
x-stainless-read-timeout:
- '600'
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.12.0
method: POST
uri: https://api.openai.com/v1/chat/completions
response:
body:
string: |-
{
"id": "chatcmpl-BL8K8arBjCHMDOxqQd5YGBeYphZGG",
"object": "chat.completion",
"created": 1744376584,
"model": "gpt-4o-mini-2024-07-18",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "Atlantic Ocean.",
"refusal": null,
"annotations": []
},
"logprobs": null,
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 22,
"completion_tokens": 5,
"total_tokens": 27,
"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_44added55e"
}
headers:
CF-RAY:
- 92eaae915b15e51d-TXL
Connection:
- keep-alive
Content-Type:
- application/json
Date:
- Fri, 11 Apr 2025 13:03:04 GMT
Server:
- cloudflare
Set-Cookie: test_set_cookie
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:
- '827'
openai-organization: test_openai_org_id
openai-processing-ms:
- '170'
openai-version:
- '2020-10-01'
strict-transport-security:
- max-age=31536000; includeSubDomains; preload
x-ratelimit-limit-requests:
- '200'
x-ratelimit-limit-tokens:
- '100000'
x-ratelimit-remaining-requests:
- '197'
x-ratelimit-remaining-tokens:
- '99925'
x-ratelimit-reset-requests:
- 19m29.225s
x-ratelimit-reset-tokens:
- 32m9.545s
x-request-id:
- req_5ec52b920fea0d555ec3dbf813300fad
status:
code: 200
message: OK
version: 1
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
GEN_AI_OPENAI_REQUEST_SERVICE_TIER,
GEN_AI_OPENAI_RESPONSE_SERVICE_TIER,
GEN_AI_OPERATION_NAME,
GEN_AI_REQUEST_CHOICE_COUNT,
GEN_AI_REQUEST_FREQUENCY_PENALTY,
GEN_AI_REQUEST_MAX_TOKENS,
GEN_AI_REQUEST_MODEL,
Expand Down Expand Up @@ -330,6 +331,7 @@ def test_chat_multiple_choices_with_capture_message_content(
address, port = address_and_port(client)
assert dict(span.attributes) == {
GEN_AI_OPERATION_NAME: "chat",
GEN_AI_REQUEST_CHOICE_COUNT: 2,
GEN_AI_REQUEST_MODEL: TEST_CHAT_MODEL,
GEN_AI_SYSTEM: "openai",
GEN_AI_RESPONSE_ID: "chatcmpl-AfhuHpVEbcYGlsFuHOP60MtU4tIq9",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
GEN_AI_OPENAI_REQUEST_SERVICE_TIER,
GEN_AI_OPENAI_RESPONSE_SERVICE_TIER,
GEN_AI_OPERATION_NAME,
GEN_AI_REQUEST_CHOICE_COUNT,
GEN_AI_REQUEST_FREQUENCY_PENALTY,
GEN_AI_REQUEST_MAX_TOKENS,
GEN_AI_REQUEST_MODEL,
Expand Down Expand Up @@ -130,6 +131,28 @@ def test_chat(default_openai_env, trace_exporter, metrics_reader, logs_exporter)
)


@pytest.mark.vcr()
def test_chat_n_1(default_openai_env, trace_exporter, metrics_reader, logs_exporter):
client = openai.OpenAI()

messages = [
{
"role": "user",
"content": TEST_CHAT_INPUT,
}
]

chat_completion = client.chat.completions.create(model=TEST_CHAT_MODEL, messages=messages, n=1)

assert chat_completion.choices[0].message.content == "Atlantic Ocean."

spans = trace_exporter.get_finished_spans()
assert len(spans) == 1

span = spans[0]
assert GEN_AI_REQUEST_CHOICE_COUNT not in span.attributes


@pytest.mark.skipif(OPENAI_VERSION < (1, 8, 0), reason="LegacyAPIResponse available")
@pytest.mark.vcr()
def test_chat_with_raw_response(default_openai_env, trace_exporter, metrics_reader, logs_exporter):
Expand Down Expand Up @@ -471,6 +494,7 @@ def test_chat_multiple_choices_with_capture_message_content(
address, port = address_and_port(client)
assert dict(span.attributes) == {
GEN_AI_OPERATION_NAME: "chat",
GEN_AI_REQUEST_CHOICE_COUNT: 2,
GEN_AI_REQUEST_MODEL: TEST_CHAT_MODEL,
GEN_AI_SYSTEM: "openai",
GEN_AI_RESPONSE_ID: "chatcmpl-AfhuHpVEbcYGlsFuHOP60MtU4tIq9",
Expand Down