langtrace-python-sdk 2.1.29__py3-none-any.whl → 2.2.1__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.
Files changed (55) hide show
  1. examples/cohere_example/chat.py +1 -0
  2. examples/cohere_example/chat_stream.py +3 -0
  3. examples/gemini_example/__init__.py +6 -0
  4. examples/gemini_example/function_tools.py +62 -0
  5. examples/gemini_example/main.py +91 -0
  6. examples/langchain_example/__init__.py +8 -0
  7. examples/langchain_example/groq_example.py +28 -15
  8. examples/ollama_example/basic.py +1 -0
  9. examples/openai_example/__init__.py +1 -0
  10. examples/openai_example/async_tool_calling_nonstreaming.py +1 -1
  11. examples/openai_example/chat_completion.py +1 -1
  12. examples/openai_example/embeddings_create.py +1 -0
  13. examples/openai_example/images_edit.py +2 -2
  14. examples/vertexai_example/__init__.py +6 -0
  15. examples/vertexai_example/main.py +214 -0
  16. langtrace_python_sdk/constants/instrumentation/common.py +2 -0
  17. langtrace_python_sdk/constants/instrumentation/gemini.py +12 -0
  18. langtrace_python_sdk/constants/instrumentation/vertexai.py +42 -0
  19. langtrace_python_sdk/instrumentation/__init__.py +4 -0
  20. langtrace_python_sdk/instrumentation/anthropic/patch.py +68 -96
  21. langtrace_python_sdk/instrumentation/chroma/patch.py +29 -29
  22. langtrace_python_sdk/instrumentation/cohere/patch.py +143 -242
  23. langtrace_python_sdk/instrumentation/gemini/__init__.py +3 -0
  24. langtrace_python_sdk/instrumentation/gemini/instrumentation.py +36 -0
  25. langtrace_python_sdk/instrumentation/gemini/patch.py +186 -0
  26. langtrace_python_sdk/instrumentation/groq/patch.py +82 -125
  27. langtrace_python_sdk/instrumentation/ollama/patch.py +62 -65
  28. langtrace_python_sdk/instrumentation/openai/patch.py +190 -494
  29. langtrace_python_sdk/instrumentation/qdrant/patch.py +6 -6
  30. langtrace_python_sdk/instrumentation/vertexai/__init__.py +3 -0
  31. langtrace_python_sdk/instrumentation/vertexai/instrumentation.py +33 -0
  32. langtrace_python_sdk/instrumentation/vertexai/patch.py +131 -0
  33. langtrace_python_sdk/langtrace.py +5 -0
  34. langtrace_python_sdk/utils/__init__.py +14 -3
  35. langtrace_python_sdk/utils/llm.py +311 -6
  36. langtrace_python_sdk/version.py +1 -1
  37. {langtrace_python_sdk-2.1.29.dist-info → langtrace_python_sdk-2.2.1.dist-info}/METADATA +26 -19
  38. {langtrace_python_sdk-2.1.29.dist-info → langtrace_python_sdk-2.2.1.dist-info}/RECORD +55 -36
  39. tests/anthropic/test_anthropic.py +28 -27
  40. tests/cohere/test_cohere_chat.py +36 -36
  41. tests/cohere/test_cohere_embed.py +12 -9
  42. tests/cohere/test_cohere_rerank.py +18 -11
  43. tests/groq/cassettes/test_async_chat_completion.yaml +113 -0
  44. tests/groq/cassettes/test_async_chat_completion_streaming.yaml +2232 -0
  45. tests/groq/cassettes/test_chat_completion.yaml +114 -0
  46. tests/groq/cassettes/test_chat_completion_streaming.yaml +2512 -0
  47. tests/groq/conftest.py +33 -0
  48. tests/groq/test_groq.py +142 -0
  49. tests/openai/cassettes/test_async_chat_completion_streaming.yaml +28 -28
  50. tests/openai/test_chat_completion.py +53 -67
  51. tests/openai/test_image_generation.py +47 -24
  52. tests/utils.py +40 -5
  53. {langtrace_python_sdk-2.1.29.dist-info → langtrace_python_sdk-2.2.1.dist-info}/WHEEL +0 -0
  54. {langtrace_python_sdk-2.1.29.dist-info → langtrace_python_sdk-2.2.1.dist-info}/entry_points.txt +0 -0
  55. {langtrace_python_sdk-2.1.29.dist-info → langtrace_python_sdk-2.2.1.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()
@@ -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-9deeLdQVwFn9pGfxPrHrnGhzMINed","object":"chat.completion.chunk","created":1719238077,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"logprobs":null,"finish_reason":null}]}
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-9deeLdQVwFn9pGfxPrHrnGhzMINed","object":"chat.completion.chunk","created":1719238077,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"This"},"logprobs":null,"finish_reason":null}]}
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-9deeLdQVwFn9pGfxPrHrnGhzMINed","object":"chat.completion.chunk","created":1719238077,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"
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-9deeLdQVwFn9pGfxPrHrnGhzMINed","object":"chat.completion.chunk","created":1719238077,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"
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-9deeLdQVwFn9pGfxPrHrnGhzMINed","object":"chat.completion.chunk","created":1719238077,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"
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-9deeLdQVwFn9pGfxPrHrnGhzMINed","object":"chat.completion.chunk","created":1719238077,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"."},"logprobs":null,"finish_reason":null}]}
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-9deeLdQVwFn9pGfxPrHrnGhzMINed","object":"chat.completion.chunk","created":1719238077,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"
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-9deeLdQVwFn9pGfxPrHrnGhzMINed","object":"chat.completion.chunk","created":1719238077,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"
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-9deeLdQVwFn9pGfxPrHrnGhzMINed","object":"chat.completion.chunk","created":1719238077,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"
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-9deeLdQVwFn9pGfxPrHrnGhzMINed","object":"chat.completion.chunk","created":1719238077,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"
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-9deeLdQVwFn9pGfxPrHrnGhzMINed","object":"chat.completion.chunk","created":1719238077,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"."},"logprobs":null,"finish_reason":null}]}
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-9deeLdQVwFn9pGfxPrHrnGhzMINed","object":"chat.completion.chunk","created":1719238077,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"
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-9deeLdQVwFn9pGfxPrHrnGhzMINed","object":"chat.completion.chunk","created":1719238077,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"
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-9deeLdQVwFn9pGfxPrHrnGhzMINed","object":"chat.completion.chunk","created":1719238077,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"
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-9deeLdQVwFn9pGfxPrHrnGhzMINed","object":"chat.completion.chunk","created":1719238077,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"
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-9deeLdQVwFn9pGfxPrHrnGhzMINed","object":"chat.completion.chunk","created":1719238077,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"."},"logprobs":null,"finish_reason":null}]}
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-9deeLdQVwFn9pGfxPrHrnGhzMINed","object":"chat.completion.chunk","created":1719238077,"model":"gpt-4-0613","system_fingerprint":null,"choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}]}
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
- - 898d497cff180da3-MRS
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
- - Mon, 24 Jun 2024 14:07:57 GMT
114
+ - Wed, 26 Jun 2024 13:19:12 GMT
115
115
  Server:
116
116
  - cloudflare
117
117
  Set-Cookie:
118
- - __cf_bm=9.DjXDRH6yqveelPQR44ZtyVUYJzgnA0G.nzqFBokzU-1719238077-1.0.1.1-aMCvEWGLFuE6ItsOru0NDaEtwnP4gVQChxLODAqfb5jmClZJa8lKqg.tNgoeMSGnxhnih1YJRhw2gq02fThn1g;
119
- path=/; expires=Mon, 24-Jun-24 14:37:57 GMT; domain=.api.openai.com; HttpOnly;
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=O9yzYcvRGvChbCerFoeKPvIqX_jwhxHPRVMMxoF4wLY-1719238077679-0.0.1.1-604800000;
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
- - '193'
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
- - '300000'
138
+ - '1000000'
139
139
  x-ratelimit-remaining-requests:
140
140
  - '9999'
141
141
  x-ratelimit-remaining-tokens:
142
- - '299975'
142
+ - '999975'
143
143
  x-ratelimit-reset-requests:
144
144
  - 6ms
145
145
  x-ratelimit-reset-tokens:
146
- - 5ms
146
+ - 1ms
147
147
  x-request-id:
148
- - ae303b10004d584d9da9cb432917ef64
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 assert_response_format, assert_token_count
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
- assert_token_count(attributes)
37
- assert_response_format(attributes)
38
-
39
- langtrace_responses = json.loads(attributes.get("llm.responses"))
40
- assert isinstance(langtrace_responses, list)
41
- for langtrace_response in langtrace_responses:
42
- assert isinstance(langtrace_response, dict)
43
- assert "role" in langtrace_response
44
- assert "content" in langtrace_response
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
- langtrace_responses = json.loads(attributes.get("llm.responses"))
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("langtrace.sdk.name") == "langtrace-python-sdk"
77
- assert attributes.get("langtrace.service.name") == "OpenAI"
78
- assert attributes.get("langtrace.service.type") == "llm"
79
- assert attributes.get("langtrace.service.version") == v("openai")
80
- assert attributes.get("langtrace.version") == v("langtrace-python-sdk")
81
- assert attributes.get("url.full") == "https://api.openai.com/v1/"
82
- assert attributes.get("llm.api") == APIS["CHAT_COMPLETION"]["ENDPOINT"]
83
- assert attributes.get("llm.model") == "gpt-4-0613"
84
- assert attributes.get("llm.prompts") == json.dumps(messages_value)
85
- assert attributes.get("llm.stream") is True
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) - 2 == chunk_count # -2 for start and end 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
- with await async_openai_client.chat.completions.create(**kwargs) as response:
122
- async for _ in response:
123
- chunk_count += 1
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("langtrace.sdk.name") == "langtrace-python-sdk"
132
- assert attributes.get("langtrace.service.name") == "OpenAI"
133
- assert attributes.get("langtrace.service.type") == "llm"
134
- assert attributes.get("langtrace.service.version") == v("openai")
135
- assert attributes.get("langtrace.version") == v("langtrace-python-sdk")
136
- assert attributes.get("url.full") == "https://api.openai.com/v1/"
137
- assert attributes.get("llm.api") == APIS["CHAT_COMPLETION"]["ENDPOINT"]
138
- assert attributes.get("llm.model") == "gpt-4-0613"
139
- assert attributes.get("llm.prompts") == json.dumps(messages_value)
140
- assert attributes.get("llm.stream") is True
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) - 2 == chunk_count # -2 for start and end 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
- assert attributes.get("langtrace.sdk.name") == "langtrace-python-sdk"
24
- assert attributes.get("langtrace.service.name") == "OpenAI"
25
- assert attributes.get("langtrace.service.type") == "llm"
26
- assert attributes.get("langtrace.service.version") == v("openai")
27
- assert attributes.get("langtrace.version") == v("langtrace-python-sdk")
28
- assert attributes.get("url.full") == "https://api.openai.com/v1/"
29
- assert attributes.get("llm.api") == APIS["IMAGES_GENERATION"]["ENDPOINT"]
30
- assert attributes.get("llm.model") == llm_model_value
31
- prompts = json.loads(attributes.get("llm.prompts"))
32
- assert prompts[0]["content"] == prompt
33
-
34
- langtrace_responses = json.loads(attributes.get("llm.responses"))
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
- assert attributes.get("langtrace.sdk.name") == "langtrace-python-sdk"
65
- assert attributes.get("langtrace.service.name") == "OpenAI"
66
- assert attributes.get("langtrace.service.type") == "llm"
67
- assert attributes.get("langtrace.service.version") == v("openai")
68
- assert attributes.get("langtrace.version") == v("langtrace-python-sdk")
69
- assert attributes.get("url.full") == "https://api.openai.com/v1/"
70
- assert attributes.get("llm.api") == APIS["IMAGES_GENERATION"]["ENDPOINT"]
71
- assert attributes.get("llm.model") == llm_model_value
72
- prompts = json.loads(attributes.get("llm.prompts"))
73
- assert prompts[0]["content"] == prompt
74
-
75
- langtrace_responses = json.loads(attributes.get("llm.responses"))
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