langtrace-python-sdk 2.1.29__py3-none-any.whl → 2.2.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- examples/cohere_example/chat.py +1 -0
- examples/cohere_example/chat_stream.py +3 -0
- examples/dspy_example/math_problems_cot_parallel.py +59 -0
- examples/gemini_example/__init__.py +6 -0
- examples/gemini_example/function_tools.py +62 -0
- examples/gemini_example/main.py +91 -0
- examples/langchain_example/__init__.py +8 -0
- examples/langchain_example/groq_example.py +28 -15
- examples/ollama_example/basic.py +1 -0
- examples/openai_example/__init__.py +1 -0
- examples/openai_example/async_tool_calling_nonstreaming.py +1 -1
- examples/openai_example/chat_completion.py +1 -1
- examples/openai_example/embeddings_create.py +1 -0
- examples/openai_example/images_edit.py +2 -2
- examples/vertexai_example/__init__.py +6 -0
- examples/vertexai_example/main.py +214 -0
- langtrace_python_sdk/constants/instrumentation/common.py +2 -0
- langtrace_python_sdk/constants/instrumentation/gemini.py +12 -0
- langtrace_python_sdk/constants/instrumentation/vertexai.py +42 -0
- langtrace_python_sdk/instrumentation/__init__.py +4 -0
- langtrace_python_sdk/instrumentation/anthropic/patch.py +68 -96
- langtrace_python_sdk/instrumentation/chroma/patch.py +29 -29
- langtrace_python_sdk/instrumentation/cohere/patch.py +143 -242
- langtrace_python_sdk/instrumentation/dspy/instrumentation.py +2 -2
- langtrace_python_sdk/instrumentation/dspy/patch.py +36 -36
- langtrace_python_sdk/instrumentation/gemini/__init__.py +3 -0
- langtrace_python_sdk/instrumentation/gemini/instrumentation.py +36 -0
- langtrace_python_sdk/instrumentation/gemini/patch.py +186 -0
- langtrace_python_sdk/instrumentation/groq/patch.py +82 -125
- langtrace_python_sdk/instrumentation/ollama/patch.py +62 -65
- langtrace_python_sdk/instrumentation/openai/patch.py +190 -494
- langtrace_python_sdk/instrumentation/qdrant/patch.py +6 -6
- langtrace_python_sdk/instrumentation/vertexai/__init__.py +3 -0
- langtrace_python_sdk/instrumentation/vertexai/instrumentation.py +33 -0
- langtrace_python_sdk/instrumentation/vertexai/patch.py +131 -0
- langtrace_python_sdk/langtrace.py +5 -0
- langtrace_python_sdk/utils/__init__.py +14 -3
- langtrace_python_sdk/utils/llm.py +311 -6
- langtrace_python_sdk/version.py +1 -1
- {langtrace_python_sdk-2.1.29.dist-info → langtrace_python_sdk-2.2.2.dist-info}/METADATA +26 -19
- {langtrace_python_sdk-2.1.29.dist-info → langtrace_python_sdk-2.2.2.dist-info}/RECORD +58 -38
- tests/anthropic/test_anthropic.py +28 -27
- tests/cohere/test_cohere_chat.py +36 -36
- tests/cohere/test_cohere_embed.py +12 -9
- tests/cohere/test_cohere_rerank.py +18 -11
- tests/groq/cassettes/test_async_chat_completion.yaml +113 -0
- tests/groq/cassettes/test_async_chat_completion_streaming.yaml +2232 -0
- tests/groq/cassettes/test_chat_completion.yaml +114 -0
- tests/groq/cassettes/test_chat_completion_streaming.yaml +2512 -0
- tests/groq/conftest.py +33 -0
- tests/groq/test_groq.py +142 -0
- tests/openai/cassettes/test_async_chat_completion_streaming.yaml +28 -28
- tests/openai/test_chat_completion.py +53 -67
- tests/openai/test_image_generation.py +47 -24
- tests/utils.py +40 -5
- {langtrace_python_sdk-2.1.29.dist-info → langtrace_python_sdk-2.2.2.dist-info}/WHEEL +0 -0
- {langtrace_python_sdk-2.1.29.dist-info → langtrace_python_sdk-2.2.2.dist-info}/entry_points.txt +0 -0
- {langtrace_python_sdk-2.1.29.dist-info → langtrace_python_sdk-2.2.2.dist-info}/licenses/LICENSE +0 -0
tests/groq/conftest.py
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import pytest
|
|
3
|
+
|
|
4
|
+
from groq import Groq, AsyncGroq
|
|
5
|
+
from langtrace_python_sdk.instrumentation import GroqInstrumentation
|
|
6
|
+
from dotenv import load_dotenv
|
|
7
|
+
|
|
8
|
+
load_dotenv()
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@pytest.fixture(autouse=True)
|
|
12
|
+
def environment():
|
|
13
|
+
os.environ["GROQ_API_KEY"] = "test_api_key"
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@pytest.fixture
|
|
17
|
+
def groq_client():
|
|
18
|
+
return Groq()
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@pytest.fixture
|
|
22
|
+
def async_groq_client():
|
|
23
|
+
return AsyncGroq()
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@pytest.fixture(scope="module")
|
|
27
|
+
def vcr_config():
|
|
28
|
+
return {"filter_headers": ["authorization", "api-key"]}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@pytest.fixture(scope="session", autouse=True)
|
|
32
|
+
def instrument():
|
|
33
|
+
GroqInstrumentation().instrument()
|
tests/groq/test_groq.py
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
from langtrace_python_sdk.constants import LANGTRACE_SDK_NAME
|
|
2
|
+
from langtrace_python_sdk.constants.instrumentation.groq import APIS
|
|
3
|
+
import pytest
|
|
4
|
+
from langtrace.trace_attributes import SpanAttributes
|
|
5
|
+
from importlib_metadata import version as v
|
|
6
|
+
from tests.utils import (
|
|
7
|
+
assert_completion_in_events,
|
|
8
|
+
assert_prompt_in_events,
|
|
9
|
+
assert_response_format,
|
|
10
|
+
assert_token_count,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@pytest.mark.vcr
|
|
15
|
+
def test_chat_completion(exporter, groq_client):
|
|
16
|
+
chat_completion = groq_client.chat.completions.create(
|
|
17
|
+
messages=[
|
|
18
|
+
{
|
|
19
|
+
"role": "user",
|
|
20
|
+
"content": "Explain the importance of low latency LLMs",
|
|
21
|
+
}
|
|
22
|
+
],
|
|
23
|
+
model="llama3-8b-8192",
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
spans = exporter.get_finished_spans()
|
|
27
|
+
groq_span = spans[-1]
|
|
28
|
+
|
|
29
|
+
assert groq_span.name == "groq.chat.completions.create"
|
|
30
|
+
attributes = groq_span.attributes
|
|
31
|
+
assert attributes.get(SpanAttributes.LANGTRACE_SDK_NAME) == LANGTRACE_SDK_NAME
|
|
32
|
+
assert attributes.get(SpanAttributes.LANGTRACE_SERVICE_NAME) == "Groq"
|
|
33
|
+
assert attributes.get(SpanAttributes.LANGTRACE_SERVICE_TYPE) == "llm"
|
|
34
|
+
assert attributes.get(SpanAttributes.LANGTRACE_SERVICE_VERSION) == v("groq")
|
|
35
|
+
assert attributes.get(SpanAttributes.LANGTRACE_VERSION) == v(LANGTRACE_SDK_NAME)
|
|
36
|
+
assert attributes.get(SpanAttributes.LLM_URL) == "https://api.groq.com"
|
|
37
|
+
assert (
|
|
38
|
+
attributes.get(SpanAttributes.LLM_PATH) == APIS["CHAT_COMPLETION"]["ENDPOINT"]
|
|
39
|
+
)
|
|
40
|
+
assert_token_count(attributes)
|
|
41
|
+
assert_prompt_in_events(groq_span.events)
|
|
42
|
+
assert_completion_in_events(groq_span.events)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@pytest.mark.vcr()
|
|
46
|
+
@pytest.mark.asyncio()
|
|
47
|
+
async def test_async_chat_completion(exporter, async_groq_client):
|
|
48
|
+
chat_completion = await async_groq_client.chat.completions.create(
|
|
49
|
+
messages=[
|
|
50
|
+
{
|
|
51
|
+
"role": "user",
|
|
52
|
+
"content": "Explain the importance of low latency LLMs",
|
|
53
|
+
}
|
|
54
|
+
],
|
|
55
|
+
model="llama3-8b-8192",
|
|
56
|
+
)
|
|
57
|
+
spans = exporter.get_finished_spans()
|
|
58
|
+
groq_span = spans[-1]
|
|
59
|
+
|
|
60
|
+
assert groq_span.name == "groq.chat.completions.create"
|
|
61
|
+
attributes = groq_span.attributes
|
|
62
|
+
assert attributes.get(SpanAttributes.LANGTRACE_SDK_NAME) == LANGTRACE_SDK_NAME
|
|
63
|
+
assert attributes.get(SpanAttributes.LANGTRACE_SERVICE_NAME) == "Groq"
|
|
64
|
+
assert attributes.get(SpanAttributes.LANGTRACE_SERVICE_TYPE) == "llm"
|
|
65
|
+
assert attributes.get(SpanAttributes.LANGTRACE_SERVICE_VERSION) == v("groq")
|
|
66
|
+
assert attributes.get(SpanAttributes.LANGTRACE_VERSION) == v(LANGTRACE_SDK_NAME)
|
|
67
|
+
assert attributes.get(SpanAttributes.LLM_URL) == "https://api.groq.com"
|
|
68
|
+
assert (
|
|
69
|
+
attributes.get(SpanAttributes.LLM_PATH) == APIS["CHAT_COMPLETION"]["ENDPOINT"]
|
|
70
|
+
)
|
|
71
|
+
assert_token_count(attributes)
|
|
72
|
+
assert_prompt_in_events(groq_span.events)
|
|
73
|
+
assert_completion_in_events(groq_span.events)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
@pytest.mark.vcr()
|
|
77
|
+
def test_chat_completion_streaming(exporter, groq_client):
|
|
78
|
+
chat_completion = groq_client.chat.completions.create(
|
|
79
|
+
messages=[
|
|
80
|
+
{
|
|
81
|
+
"role": "user",
|
|
82
|
+
"content": "Explain the importance of low latency LLMs",
|
|
83
|
+
}
|
|
84
|
+
],
|
|
85
|
+
stream=True,
|
|
86
|
+
model="llama3-8b-8192",
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
for _ in chat_completion:
|
|
90
|
+
pass
|
|
91
|
+
|
|
92
|
+
spans = exporter.get_finished_spans()
|
|
93
|
+
groq_span = spans[-1]
|
|
94
|
+
assert groq_span.name == "groq.chat.completions.create"
|
|
95
|
+
attributes = groq_span.attributes
|
|
96
|
+
assert attributes.get(SpanAttributes.LANGTRACE_SDK_NAME) == LANGTRACE_SDK_NAME
|
|
97
|
+
assert attributes.get(SpanAttributes.LANGTRACE_SERVICE_NAME) == "Groq"
|
|
98
|
+
assert attributes.get(SpanAttributes.LANGTRACE_SERVICE_TYPE) == "llm"
|
|
99
|
+
assert attributes.get(SpanAttributes.LANGTRACE_SERVICE_VERSION) == v("groq")
|
|
100
|
+
assert attributes.get(SpanAttributes.LANGTRACE_VERSION) == v(LANGTRACE_SDK_NAME)
|
|
101
|
+
assert attributes.get(SpanAttributes.LLM_URL) == "https://api.groq.com"
|
|
102
|
+
assert (
|
|
103
|
+
attributes.get(SpanAttributes.LLM_PATH) == APIS["CHAT_COMPLETION"]["ENDPOINT"]
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
assert_token_count(attributes)
|
|
107
|
+
assert_completion_in_events(groq_span.events)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
@pytest.mark.vcr()
|
|
111
|
+
@pytest.mark.asyncio()
|
|
112
|
+
async def test_async_chat_completion_streaming(async_groq_client, exporter):
|
|
113
|
+
chat_completion = await async_groq_client.chat.completions.create(
|
|
114
|
+
messages=[
|
|
115
|
+
{
|
|
116
|
+
"role": "user",
|
|
117
|
+
"content": "Explain the importance of low latency LLMs",
|
|
118
|
+
}
|
|
119
|
+
],
|
|
120
|
+
stream=True,
|
|
121
|
+
model="llama3-8b-8192",
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
async for _ in chat_completion:
|
|
125
|
+
pass
|
|
126
|
+
|
|
127
|
+
spans = exporter.get_finished_spans()
|
|
128
|
+
groq_span = spans[-1]
|
|
129
|
+
assert groq_span.name == "groq.chat.completions.create"
|
|
130
|
+
attributes = groq_span.attributes
|
|
131
|
+
assert attributes.get(SpanAttributes.LANGTRACE_SDK_NAME) == LANGTRACE_SDK_NAME
|
|
132
|
+
assert attributes.get(SpanAttributes.LANGTRACE_SERVICE_NAME) == "Groq"
|
|
133
|
+
assert attributes.get(SpanAttributes.LANGTRACE_SERVICE_TYPE) == "llm"
|
|
134
|
+
assert attributes.get(SpanAttributes.LANGTRACE_SERVICE_VERSION) == v("groq")
|
|
135
|
+
assert attributes.get(SpanAttributes.LANGTRACE_VERSION) == v(LANGTRACE_SDK_NAME)
|
|
136
|
+
assert attributes.get(SpanAttributes.LLM_URL) == "https://api.groq.com"
|
|
137
|
+
assert (
|
|
138
|
+
attributes.get(SpanAttributes.LLM_PATH) == APIS["CHAT_COMPLETION"]["ENDPOINT"]
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
assert_token_count(attributes)
|
|
142
|
+
assert_completion_in_events(groq_span.events)
|
|
@@ -6,7 +6,7 @@ interactions:
|
|
|
6
6
|
accept:
|
|
7
7
|
- application/json
|
|
8
8
|
accept-encoding:
|
|
9
|
-
- gzip, deflate
|
|
9
|
+
- gzip, deflate, br
|
|
10
10
|
connection:
|
|
11
11
|
- keep-alive
|
|
12
12
|
content-length:
|
|
@@ -35,66 +35,66 @@ interactions:
|
|
|
35
35
|
uri: https://api.openai.com/v1/chat/completions
|
|
36
36
|
response:
|
|
37
37
|
body:
|
|
38
|
-
string: 'data: {"id":"chatcmpl-
|
|
38
|
+
string: 'data: {"id":"chatcmpl-9eMqF91g3NE1pyxZvquq7cplPnrXE","object":"chat.completion.chunk","created":1719407951,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"logprobs":null,"finish_reason":null}]}
|
|
39
39
|
|
|
40
40
|
|
|
41
|
-
data: {"id":"chatcmpl-
|
|
41
|
+
data: {"id":"chatcmpl-9eMqF91g3NE1pyxZvquq7cplPnrXE","object":"chat.completion.chunk","created":1719407951,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"This"},"logprobs":null,"finish_reason":null}]}
|
|
42
42
|
|
|
43
43
|
|
|
44
|
-
data: {"id":"chatcmpl-
|
|
44
|
+
data: {"id":"chatcmpl-9eMqF91g3NE1pyxZvquq7cplPnrXE","object":"chat.completion.chunk","created":1719407951,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"
|
|
45
45
|
is"},"logprobs":null,"finish_reason":null}]}
|
|
46
46
|
|
|
47
47
|
|
|
48
|
-
data: {"id":"chatcmpl-
|
|
48
|
+
data: {"id":"chatcmpl-9eMqF91g3NE1pyxZvquq7cplPnrXE","object":"chat.completion.chunk","created":1719407951,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"
|
|
49
49
|
a"},"logprobs":null,"finish_reason":null}]}
|
|
50
50
|
|
|
51
51
|
|
|
52
|
-
data: {"id":"chatcmpl-
|
|
52
|
+
data: {"id":"chatcmpl-9eMqF91g3NE1pyxZvquq7cplPnrXE","object":"chat.completion.chunk","created":1719407951,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"
|
|
53
53
|
test"},"logprobs":null,"finish_reason":null}]}
|
|
54
54
|
|
|
55
55
|
|
|
56
|
-
data: {"id":"chatcmpl-
|
|
56
|
+
data: {"id":"chatcmpl-9eMqF91g3NE1pyxZvquq7cplPnrXE","object":"chat.completion.chunk","created":1719407951,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"."},"logprobs":null,"finish_reason":null}]}
|
|
57
57
|
|
|
58
58
|
|
|
59
|
-
data: {"id":"chatcmpl-
|
|
59
|
+
data: {"id":"chatcmpl-9eMqF91g3NE1pyxZvquq7cplPnrXE","object":"chat.completion.chunk","created":1719407951,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"
|
|
60
60
|
This"},"logprobs":null,"finish_reason":null}]}
|
|
61
61
|
|
|
62
62
|
|
|
63
|
-
data: {"id":"chatcmpl-
|
|
63
|
+
data: {"id":"chatcmpl-9eMqF91g3NE1pyxZvquq7cplPnrXE","object":"chat.completion.chunk","created":1719407951,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"
|
|
64
64
|
is"},"logprobs":null,"finish_reason":null}]}
|
|
65
65
|
|
|
66
66
|
|
|
67
|
-
data: {"id":"chatcmpl-
|
|
67
|
+
data: {"id":"chatcmpl-9eMqF91g3NE1pyxZvquq7cplPnrXE","object":"chat.completion.chunk","created":1719407951,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"
|
|
68
68
|
a"},"logprobs":null,"finish_reason":null}]}
|
|
69
69
|
|
|
70
70
|
|
|
71
|
-
data: {"id":"chatcmpl-
|
|
71
|
+
data: {"id":"chatcmpl-9eMqF91g3NE1pyxZvquq7cplPnrXE","object":"chat.completion.chunk","created":1719407951,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"
|
|
72
72
|
test"},"logprobs":null,"finish_reason":null}]}
|
|
73
73
|
|
|
74
74
|
|
|
75
|
-
data: {"id":"chatcmpl-
|
|
75
|
+
data: {"id":"chatcmpl-9eMqF91g3NE1pyxZvquq7cplPnrXE","object":"chat.completion.chunk","created":1719407951,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"."},"logprobs":null,"finish_reason":null}]}
|
|
76
76
|
|
|
77
77
|
|
|
78
|
-
data: {"id":"chatcmpl-
|
|
78
|
+
data: {"id":"chatcmpl-9eMqF91g3NE1pyxZvquq7cplPnrXE","object":"chat.completion.chunk","created":1719407951,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"
|
|
79
79
|
This"},"logprobs":null,"finish_reason":null}]}
|
|
80
80
|
|
|
81
81
|
|
|
82
|
-
data: {"id":"chatcmpl-
|
|
82
|
+
data: {"id":"chatcmpl-9eMqF91g3NE1pyxZvquq7cplPnrXE","object":"chat.completion.chunk","created":1719407951,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"
|
|
83
83
|
is"},"logprobs":null,"finish_reason":null}]}
|
|
84
84
|
|
|
85
85
|
|
|
86
|
-
data: {"id":"chatcmpl-
|
|
86
|
+
data: {"id":"chatcmpl-9eMqF91g3NE1pyxZvquq7cplPnrXE","object":"chat.completion.chunk","created":1719407951,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"
|
|
87
87
|
a"},"logprobs":null,"finish_reason":null}]}
|
|
88
88
|
|
|
89
89
|
|
|
90
|
-
data: {"id":"chatcmpl-
|
|
90
|
+
data: {"id":"chatcmpl-9eMqF91g3NE1pyxZvquq7cplPnrXE","object":"chat.completion.chunk","created":1719407951,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"
|
|
91
91
|
test"},"logprobs":null,"finish_reason":null}]}
|
|
92
92
|
|
|
93
93
|
|
|
94
|
-
data: {"id":"chatcmpl-
|
|
94
|
+
data: {"id":"chatcmpl-9eMqF91g3NE1pyxZvquq7cplPnrXE","object":"chat.completion.chunk","created":1719407951,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"."},"logprobs":null,"finish_reason":null}]}
|
|
95
95
|
|
|
96
96
|
|
|
97
|
-
data: {"id":"chatcmpl-
|
|
97
|
+
data: {"id":"chatcmpl-9eMqF91g3NE1pyxZvquq7cplPnrXE","object":"chat.completion.chunk","created":1719407951,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}]}
|
|
98
98
|
|
|
99
99
|
|
|
100
100
|
data: [DONE]
|
|
@@ -105,20 +105,20 @@ interactions:
|
|
|
105
105
|
CF-Cache-Status:
|
|
106
106
|
- DYNAMIC
|
|
107
107
|
CF-RAY:
|
|
108
|
-
-
|
|
108
|
+
- 899d7cd0ed680db9-MRS
|
|
109
109
|
Connection:
|
|
110
110
|
- keep-alive
|
|
111
111
|
Content-Type:
|
|
112
112
|
- text/event-stream; charset=utf-8
|
|
113
113
|
Date:
|
|
114
|
-
-
|
|
114
|
+
- Wed, 26 Jun 2024 13:19:12 GMT
|
|
115
115
|
Server:
|
|
116
116
|
- cloudflare
|
|
117
117
|
Set-Cookie:
|
|
118
|
-
- __cf_bm=
|
|
119
|
-
path=/; expires=
|
|
118
|
+
- __cf_bm=Koulk3jjfKTtiwmlpNUH5Uye51Zphg2V.pD_ZnQF2ZE-1719407952-1.0.1.1-1_bGj0x07cc6IT0NHiXCIjjTnk5qDAJ.123pg_4.g85iZakVAGtWPnz7bbLr8y8IBPOXwA7X5KnPl67mbAHuFQ;
|
|
119
|
+
path=/; expires=Wed, 26-Jun-24 13:49:12 GMT; domain=.api.openai.com; HttpOnly;
|
|
120
120
|
Secure; SameSite=None
|
|
121
|
-
- _cfuvid=
|
|
121
|
+
- _cfuvid=Di5O_shad8PpLIGwUHtQVySW5EcyGPn98xWvMpFs.fc-1719407952314-0.0.1.1-604800000;
|
|
122
122
|
path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None
|
|
123
123
|
Transfer-Encoding:
|
|
124
124
|
- chunked
|
|
@@ -127,7 +127,7 @@ interactions:
|
|
|
127
127
|
openai-organization:
|
|
128
128
|
- scale3-1
|
|
129
129
|
openai-processing-ms:
|
|
130
|
-
- '
|
|
130
|
+
- '206'
|
|
131
131
|
openai-version:
|
|
132
132
|
- '2020-10-01'
|
|
133
133
|
strict-transport-security:
|
|
@@ -135,17 +135,17 @@ interactions:
|
|
|
135
135
|
x-ratelimit-limit-requests:
|
|
136
136
|
- '10000'
|
|
137
137
|
x-ratelimit-limit-tokens:
|
|
138
|
-
- '
|
|
138
|
+
- '1000000'
|
|
139
139
|
x-ratelimit-remaining-requests:
|
|
140
140
|
- '9999'
|
|
141
141
|
x-ratelimit-remaining-tokens:
|
|
142
|
-
- '
|
|
142
|
+
- '999975'
|
|
143
143
|
x-ratelimit-reset-requests:
|
|
144
144
|
- 6ms
|
|
145
145
|
x-ratelimit-reset-tokens:
|
|
146
|
-
-
|
|
146
|
+
- 1ms
|
|
147
147
|
x-request-id:
|
|
148
|
-
-
|
|
148
|
+
- 98bad879df65b3adda303922fbc539cf
|
|
149
149
|
status:
|
|
150
150
|
code: 200
|
|
151
151
|
message: OK
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import pytest
|
|
2
2
|
import json
|
|
3
3
|
from langtrace_python_sdk.constants.instrumentation.openai import APIS
|
|
4
|
-
from tests.utils import
|
|
4
|
+
from tests.utils import (
|
|
5
|
+
assert_completion_in_events,
|
|
6
|
+
assert_prompt_in_events,
|
|
7
|
+
assert_response_format,
|
|
8
|
+
assert_token_count,
|
|
9
|
+
)
|
|
5
10
|
from importlib_metadata import version as v
|
|
11
|
+
from langtrace.trace_attributes import SpanAttributes
|
|
6
12
|
|
|
7
13
|
|
|
8
14
|
@pytest.mark.vcr()
|
|
@@ -22,33 +28,22 @@ def test_chat_completion(exporter, openai_client):
|
|
|
22
28
|
assert completion_span.name == "openai.chat.completions.create"
|
|
23
29
|
|
|
24
30
|
attributes = completion_span.attributes
|
|
25
|
-
assert attributes.get("langtrace.sdk.name") == "langtrace-python-sdk"
|
|
26
|
-
assert attributes.get("langtrace.service.name") == "OpenAI"
|
|
27
|
-
assert attributes.get("langtrace.service.type") == "llm"
|
|
28
|
-
assert attributes.get("langtrace.service.version") == v("openai")
|
|
29
|
-
assert attributes.get("langtrace.version") == v("langtrace-python-sdk")
|
|
30
|
-
assert attributes.get("url.full") == "https://api.openai.com/v1/"
|
|
31
|
-
assert attributes.get("llm.api") == APIS["CHAT_COMPLETION"]["ENDPOINT"]
|
|
32
|
-
assert attributes.get("llm.model") == "gpt-4-0613"
|
|
33
|
-
assert attributes.get("llm.prompts") == json.dumps(messages_value)
|
|
34
|
-
assert attributes.get("llm.stream") is False
|
|
35
31
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
assert
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
32
|
+
assert attributes.get(SpanAttributes.LANGTRACE_SDK_NAME) == "langtrace-python-sdk"
|
|
33
|
+
assert attributes.get(SpanAttributes.LANGTRACE_SERVICE_NAME) == "OpenAI"
|
|
34
|
+
assert attributes.get(SpanAttributes.LANGTRACE_SERVICE_TYPE) == "llm"
|
|
35
|
+
assert attributes.get(SpanAttributes.LANGTRACE_SERVICE_VERSION) == v("openai")
|
|
36
|
+
assert attributes.get(SpanAttributes.LANGTRACE_VERSION) == v("langtrace-python-sdk")
|
|
37
|
+
assert attributes.get(SpanAttributes.LLM_URL) == "https://api.openai.com/v1/"
|
|
38
|
+
assert (
|
|
39
|
+
attributes.get(SpanAttributes.LLM_PATH) == APIS["CHAT_COMPLETION"]["ENDPOINT"]
|
|
40
|
+
)
|
|
41
|
+
assert attributes.get(SpanAttributes.LLM_RESPONSE_MODEL) == "gpt-4-0613"
|
|
42
|
+
assert_prompt_in_events(completion_span.events)
|
|
43
|
+
assert_completion_in_events(completion_span.events)
|
|
44
|
+
assert attributes.get(SpanAttributes.LLM_IS_STREAMING) is False
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
assert isinstance(langtrace_responses, list)
|
|
48
|
-
for langtrace_response in langtrace_responses:
|
|
49
|
-
assert isinstance(langtrace_response, dict)
|
|
50
|
-
assert "role" in langtrace_response
|
|
51
|
-
assert "content" in langtrace_response
|
|
46
|
+
assert_token_count(attributes)
|
|
52
47
|
|
|
53
48
|
|
|
54
49
|
@pytest.mark.vcr()
|
|
@@ -64,6 +59,7 @@ def test_chat_completion_streaming(exporter, openai_client):
|
|
|
64
59
|
|
|
65
60
|
chunk_count = 0
|
|
66
61
|
response = openai_client.chat.completions.create(**kwargs)
|
|
62
|
+
|
|
67
63
|
for _ in response:
|
|
68
64
|
chunk_count += 1
|
|
69
65
|
|
|
@@ -73,36 +69,24 @@ def test_chat_completion_streaming(exporter, openai_client):
|
|
|
73
69
|
assert streaming_span.name == "openai.chat.completions.create"
|
|
74
70
|
attributes = streaming_span.attributes
|
|
75
71
|
|
|
76
|
-
assert attributes.get(
|
|
77
|
-
assert attributes.get(
|
|
78
|
-
assert attributes.get(
|
|
79
|
-
assert attributes.get(
|
|
80
|
-
assert attributes.get(
|
|
81
|
-
assert attributes.get(
|
|
82
|
-
assert
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
assert attributes.get(
|
|
72
|
+
assert attributes.get(SpanAttributes.LANGTRACE_SDK_NAME) == "langtrace-python-sdk"
|
|
73
|
+
assert attributes.get(SpanAttributes.LANGTRACE_SERVICE_NAME) == "OpenAI"
|
|
74
|
+
assert attributes.get(SpanAttributes.LANGTRACE_SERVICE_TYPE) == "llm"
|
|
75
|
+
assert attributes.get(SpanAttributes.LANGTRACE_SERVICE_VERSION) == v("openai")
|
|
76
|
+
assert attributes.get(SpanAttributes.LANGTRACE_VERSION) == v("langtrace-python-sdk")
|
|
77
|
+
assert attributes.get(SpanAttributes.LLM_URL) == "https://api.openai.com/v1/"
|
|
78
|
+
assert (
|
|
79
|
+
attributes.get(SpanAttributes.LLM_PATH) == APIS["CHAT_COMPLETION"]["ENDPOINT"]
|
|
80
|
+
)
|
|
81
|
+
assert attributes.get(SpanAttributes.LLM_RESPONSE_MODEL) == "gpt-4-0613"
|
|
82
|
+
assert_prompt_in_events(streaming_span.events)
|
|
83
|
+
assert_completion_in_events(streaming_span.events)
|
|
84
|
+
assert attributes.get(SpanAttributes.LLM_IS_STREAMING) is True
|
|
86
85
|
|
|
87
86
|
events = streaming_span.events
|
|
88
|
-
assert len(events) -
|
|
87
|
+
assert len(events) - 4 == chunk_count # -2 for start and end events
|
|
89
88
|
|
|
90
89
|
assert_token_count(attributes)
|
|
91
|
-
assert_response_format(attributes)
|
|
92
|
-
|
|
93
|
-
langtrace_responses = json.loads(attributes.get("llm.responses"))
|
|
94
|
-
assert isinstance(langtrace_responses, list)
|
|
95
|
-
for langtrace_response in langtrace_responses:
|
|
96
|
-
assert isinstance(langtrace_response, dict)
|
|
97
|
-
assert "role" in langtrace_response
|
|
98
|
-
assert "content" in langtrace_response
|
|
99
|
-
|
|
100
|
-
langtrace_responses = json.loads(attributes.get("llm.responses"))
|
|
101
|
-
assert isinstance(langtrace_responses, list)
|
|
102
|
-
for langtrace_response in langtrace_responses:
|
|
103
|
-
assert isinstance(langtrace_response, dict)
|
|
104
|
-
assert "role" in langtrace_response
|
|
105
|
-
assert "content" in langtrace_response
|
|
106
90
|
|
|
107
91
|
|
|
108
92
|
@pytest.mark.vcr()
|
|
@@ -118,9 +102,9 @@ async def test_async_chat_completion_streaming(exporter, async_openai_client):
|
|
|
118
102
|
}
|
|
119
103
|
|
|
120
104
|
chunk_count = 0
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
105
|
+
response = await async_openai_client.chat.completions.create(**kwargs)
|
|
106
|
+
async for chunk in response:
|
|
107
|
+
chunk_count += 1
|
|
124
108
|
|
|
125
109
|
spans = exporter.get_finished_spans()
|
|
126
110
|
streaming_span = spans[-1]
|
|
@@ -128,19 +112,21 @@ async def test_async_chat_completion_streaming(exporter, async_openai_client):
|
|
|
128
112
|
assert streaming_span.name == "openai.chat.completions.create"
|
|
129
113
|
attributes = streaming_span.attributes
|
|
130
114
|
|
|
131
|
-
assert attributes.get(
|
|
132
|
-
assert attributes.get(
|
|
133
|
-
assert attributes.get(
|
|
134
|
-
assert attributes.get(
|
|
135
|
-
assert attributes.get(
|
|
136
|
-
assert attributes.get(
|
|
137
|
-
assert
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
assert attributes.get(
|
|
115
|
+
assert attributes.get(SpanAttributes.LANGTRACE_SDK_NAME) == "langtrace-python-sdk"
|
|
116
|
+
assert attributes.get(SpanAttributes.LANGTRACE_SERVICE_NAME) == "OpenAI"
|
|
117
|
+
assert attributes.get(SpanAttributes.LANGTRACE_SERVICE_TYPE) == "llm"
|
|
118
|
+
assert attributes.get(SpanAttributes.LANGTRACE_SERVICE_VERSION) == v("openai")
|
|
119
|
+
assert attributes.get(SpanAttributes.LANGTRACE_VERSION) == v("langtrace-python-sdk")
|
|
120
|
+
assert attributes.get(SpanAttributes.LLM_URL) == "https://api.openai.com/v1/"
|
|
121
|
+
assert (
|
|
122
|
+
attributes.get(SpanAttributes.LLM_PATH) == APIS["CHAT_COMPLETION"]["ENDPOINT"]
|
|
123
|
+
)
|
|
124
|
+
assert attributes.get(SpanAttributes.LLM_RESPONSE_MODEL) == "gpt-4-0613"
|
|
125
|
+
assert_prompt_in_events(streaming_span.events)
|
|
126
|
+
assert_completion_in_events(streaming_span.events)
|
|
127
|
+
assert attributes.get(SpanAttributes.LLM_IS_STREAMING) is True
|
|
141
128
|
|
|
142
129
|
events = streaming_span.events
|
|
143
|
-
assert len(events) -
|
|
130
|
+
assert len(events) - 4 == chunk_count # -2 for start and end events
|
|
144
131
|
|
|
145
132
|
assert_token_count(attributes)
|
|
146
|
-
assert_response_format(attributes)
|
|
@@ -2,6 +2,7 @@ import pytest
|
|
|
2
2
|
import json
|
|
3
3
|
from langtrace_python_sdk.constants.instrumentation.openai import APIS
|
|
4
4
|
from importlib_metadata import version as v
|
|
5
|
+
from langtrace.trace_attributes import SpanAttributes
|
|
5
6
|
|
|
6
7
|
|
|
7
8
|
@pytest.mark.vcr()
|
|
@@ -20,23 +21,34 @@ def test_image_generation(openai_client, exporter):
|
|
|
20
21
|
assert image_generation_span.name == "openai.images.generate"
|
|
21
22
|
|
|
22
23
|
attributes = image_generation_span.attributes
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
assert attributes.get(
|
|
26
|
-
|
|
27
|
-
assert attributes.get(
|
|
28
|
-
assert attributes.get(
|
|
29
|
-
assert attributes.get(
|
|
30
|
-
assert attributes.get(
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
24
|
+
events = image_generation_span.events
|
|
25
|
+
|
|
26
|
+
assert attributes.get(SpanAttributes.LANGTRACE_SDK_NAME) == "langtrace-python-sdk"
|
|
27
|
+
|
|
28
|
+
assert attributes.get(SpanAttributes.LANGTRACE_SERVICE_NAME) == "OpenAI"
|
|
29
|
+
assert attributes.get(SpanAttributes.LANGTRACE_SERVICE_TYPE) == "llm"
|
|
30
|
+
assert attributes.get(SpanAttributes.LANGTRACE_SERVICE_VERSION) == v("openai")
|
|
31
|
+
assert attributes.get(SpanAttributes.LANGTRACE_VERSION) == v("langtrace-python-sdk")
|
|
32
|
+
assert attributes.get(SpanAttributes.LLM_URL) == "https://api.openai.com/v1/"
|
|
33
|
+
|
|
34
|
+
assert (
|
|
35
|
+
attributes.get(SpanAttributes.LLM_PATH) == APIS["IMAGES_GENERATION"]["ENDPOINT"]
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
assert attributes.get(SpanAttributes.LLM_REQUEST_MODEL) == llm_model_value
|
|
39
|
+
|
|
40
|
+
# prompts = json.loads(attributes.get(SpanAttributes.LLM_PROMPTS))
|
|
41
|
+
# assert prompts[0]["content"] == prompt
|
|
42
|
+
|
|
43
|
+
langtrace_responses = json.loads(
|
|
44
|
+
events[-1].attributes.get(SpanAttributes.LLM_COMPLETIONS)
|
|
45
|
+
)
|
|
35
46
|
assert isinstance(langtrace_responses, list)
|
|
36
47
|
for langtrace_response in langtrace_responses:
|
|
37
48
|
assert isinstance(langtrace_response, dict)
|
|
38
49
|
assert "role" in langtrace_response
|
|
39
50
|
assert "content" in langtrace_response
|
|
51
|
+
|
|
40
52
|
assert response.data[0].url == langtrace_response["content"]["url"]
|
|
41
53
|
assert (
|
|
42
54
|
response.data[0].revised_prompt
|
|
@@ -61,23 +73,34 @@ async def test_async_image_generation(async_openai_client, exporter):
|
|
|
61
73
|
assert image_generation_span.name == "openai.images.generate"
|
|
62
74
|
|
|
63
75
|
attributes = image_generation_span.attributes
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
assert attributes.get(
|
|
67
|
-
|
|
68
|
-
assert attributes.get(
|
|
69
|
-
assert attributes.get(
|
|
70
|
-
assert attributes.get(
|
|
71
|
-
assert attributes.get(
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
+
events = image_generation_span.events
|
|
77
|
+
|
|
78
|
+
assert attributes.get(SpanAttributes.LANGTRACE_SDK_NAME) == "langtrace-python-sdk"
|
|
79
|
+
|
|
80
|
+
assert attributes.get(SpanAttributes.LANGTRACE_SERVICE_NAME) == "OpenAI"
|
|
81
|
+
assert attributes.get(SpanAttributes.LANGTRACE_SERVICE_TYPE) == "llm"
|
|
82
|
+
assert attributes.get(SpanAttributes.LANGTRACE_SERVICE_VERSION) == v("openai")
|
|
83
|
+
assert attributes.get(SpanAttributes.LANGTRACE_VERSION) == v("langtrace-python-sdk")
|
|
84
|
+
assert attributes.get(SpanAttributes.LLM_URL) == "https://api.openai.com/v1/"
|
|
85
|
+
|
|
86
|
+
assert (
|
|
87
|
+
attributes.get(SpanAttributes.LLM_PATH) == APIS["IMAGES_GENERATION"]["ENDPOINT"]
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
assert attributes.get(SpanAttributes.LLM_REQUEST_MODEL) == llm_model_value
|
|
91
|
+
|
|
92
|
+
# prompts = json.loads(attributes.get(SpanAttributes.LLM_PROMPTS))
|
|
93
|
+
# assert prompts[0]["content"] == prompt
|
|
94
|
+
|
|
95
|
+
langtrace_responses = json.loads(
|
|
96
|
+
events[-1].attributes.get(SpanAttributes.LLM_COMPLETIONS)
|
|
97
|
+
)
|
|
76
98
|
assert isinstance(langtrace_responses, list)
|
|
77
99
|
for langtrace_response in langtrace_responses:
|
|
78
100
|
assert isinstance(langtrace_response, dict)
|
|
79
101
|
assert "role" in langtrace_response
|
|
80
102
|
assert "content" in langtrace_response
|
|
103
|
+
|
|
81
104
|
assert response.data[0].url == langtrace_response["content"]["url"]
|
|
82
105
|
assert (
|
|
83
106
|
response.data[0].revised_prompt
|