openlit 1.19.0__py3-none-any.whl → 1.21.0__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.
openlit/__init__.py CHANGED
@@ -33,6 +33,7 @@ from openlit.instrumentation.ollama import OllamaInstrumentor
33
33
  from openlit.instrumentation.gpt4all import GPT4AllInstrumentor
34
34
  from openlit.instrumentation.elevenlabs import ElevenLabsInstrumentor
35
35
  from openlit.instrumentation.vllm import VLLMInstrumentor
36
+ from openlit.instrumentation.google_ai_studio import GoogleAIStudioInstrumentor
36
37
  from openlit.instrumentation.langchain import LangChainInstrumentor
37
38
  from openlit.instrumentation.llamaindex import LlamaIndexInstrumentor
38
39
  from openlit.instrumentation.haystack import HaystackInstrumentor
@@ -196,6 +197,7 @@ def init(environment="default", application_name="default", tracer=None, otlp_en
196
197
  "gpt4all": "gpt4all",
197
198
  "elevenlabs": "elevenlabs",
198
199
  "vllm": "vllm",
200
+ "google-ai-studio": "google.generativeai",
199
201
  "langchain": "langchain",
200
202
  "llama_index": "llama_index",
201
203
  "haystack": "haystack",
@@ -273,6 +275,7 @@ def init(environment="default", application_name="default", tracer=None, otlp_en
273
275
  "gpt4all": GPT4AllInstrumentor(),
274
276
  "elevenlabs": ElevenLabsInstrumentor(),
275
277
  "vllm": VLLMInstrumentor(),
278
+ "google-ai-studio": GoogleAIStudioInstrumentor(),
276
279
  "langchain": LangChainInstrumentor(),
277
280
  "llama_index": LlamaIndexInstrumentor(),
278
281
  "haystack": HaystackInstrumentor(),
@@ -0,0 +1,56 @@
1
+ # pylint: disable=useless-return, bad-staticmethod-argument, disable=duplicate-code
2
+ """Initializer of Auto Instrumentation of Google AI Studio Functions"""
3
+
4
+ from typing import Collection
5
+ import importlib.metadata
6
+ from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
7
+ from wrapt import wrap_function_wrapper
8
+
9
+ from openlit.instrumentation.google_ai_studio.google_ai_studio import (
10
+ generate
11
+ )
12
+
13
+ from openlit.instrumentation.google_ai_studio.async_google_ai_studio import (
14
+ async_generate
15
+ )
16
+
17
+ _instruments = ("google-generativeai >= 0.2.0",)
18
+
19
+ class GoogleAIStudioInstrumentor(BaseInstrumentor):
20
+ """
21
+ An instrumentor for google-generativeai's client library.
22
+ """
23
+
24
+ def instrumentation_dependencies(self) -> Collection[str]:
25
+ return _instruments
26
+
27
+ def _instrument(self, **kwargs):
28
+ application_name = kwargs.get("application_name", "default_application")
29
+ environment = kwargs.get("environment", "default_environment")
30
+ tracer = kwargs.get("tracer")
31
+ metrics = kwargs.get("metrics_dict")
32
+ pricing_info = kwargs.get("pricing_info", {})
33
+ trace_content = kwargs.get("trace_content", False)
34
+ disable_metrics = kwargs.get("disable_metrics")
35
+ version = importlib.metadata.version("ollama")
36
+
37
+ # sync generate
38
+ wrap_function_wrapper(
39
+ "google.generativeai.generative_models",
40
+ "GenerativeModel.generate_content",
41
+ generate("google_ai_studio.generate_content", version, environment, application_name,
42
+ tracer, pricing_info, trace_content, metrics, disable_metrics),
43
+ )
44
+
45
+ # async generate
46
+ wrap_function_wrapper(
47
+ "google.generativeai.generative_models",
48
+ "GenerativeModel.generate_content_async",
49
+ async_generate("google_ai_studio.generate_content", version, environment,
50
+ application_name, tracer, pricing_info, trace_content, metrics,
51
+ disable_metrics),
52
+ )
53
+
54
+ def _uninstrument(self, **kwargs):
55
+ # Proper uninstrumentation logic to revert patched methods
56
+ pass
@@ -0,0 +1,263 @@
1
+ # pylint: disable=duplicate-code, broad-exception-caught, too-many-statements, unused-argument, possibly-used-before-assignment, protected-access
2
+ """
3
+ Module for monitoring Google AI Studio API calls.
4
+ """
5
+
6
+ import logging
7
+ from opentelemetry.trace import SpanKind, Status, StatusCode
8
+ from opentelemetry.sdk.resources import TELEMETRY_SDK_NAME
9
+ from openlit.__helpers import (
10
+ handle_exception,
11
+ get_chat_model_cost,
12
+ )
13
+ from openlit.semcov import SemanticConvetion
14
+
15
+ # Initialize logger for logging potential issues and operations
16
+ logger = logging.getLogger(__name__)
17
+
18
+ def async_generate(gen_ai_endpoint, version, environment, application_name,
19
+ tracer, pricing_info, trace_content, metrics, disable_metrics):
20
+ """
21
+ Generates a telemetry wrapper for chat to collect metrics.
22
+
23
+ Args:
24
+ gen_ai_endpoint: Endpoint identifier for logging and tracing.
25
+ version: Version of the monitoring package.
26
+ environment: Deployment environment (e.g., production, staging).
27
+ application_name: Name of the application using the Google AI Studio API.
28
+ tracer: OpenTelemetry tracer for creating spans.
29
+ pricing_info: Information used for calculating the cost of Google AI Studio usage.
30
+ trace_content: Flag indicating whether to trace the actual content.
31
+
32
+ Returns:
33
+ A function that wraps the chat method to add telemetry.
34
+ """
35
+
36
+ async def wrapper(wrapped, instance, args, kwargs):
37
+ """
38
+ Wraps the 'chat' API call to add telemetry.
39
+
40
+ This collects metrics such as execution time, cost, and token usage, and handles errors
41
+ gracefully, adding details to the trace for observability.
42
+
43
+ Args:
44
+ wrapped: The original 'chat' method to be wrapped.
45
+ instance: The instance of the class where the original method is defined.
46
+ args: Positional arguments for the 'chat' method.
47
+ kwargs: Keyword arguments for the 'chat' method.
48
+
49
+ Returns:
50
+ The response from the original 'chat' method.
51
+ """
52
+ # pylint: disable=no-else-return
53
+ if kwargs.get('stream', False) is True:
54
+ # Special handling for streaming response to accommodate the nature of data flow
55
+ async def stream_generator():
56
+ with tracer.start_as_current_span(gen_ai_endpoint, kind= SpanKind.CLIENT) as span:
57
+ # Placeholder for aggregating streaming response
58
+ llmresponse = ""
59
+
60
+ # Loop through streaming events capturing relevant details
61
+ async for chunk in await wrapped(*args, **kwargs):
62
+ # Collect message IDs and aggregated response from events
63
+ content = chunk.text
64
+ if content:
65
+ llmresponse += content
66
+
67
+ input_tokens = chunk.usage_metadata.prompt_token_count
68
+ output_tokens = chunk.usage_metadata.candidates_token_count
69
+ yield chunk
70
+
71
+ # Handling exception ensure observability without disrupting operation
72
+ try:
73
+ prompt = ""
74
+ for arg in args:
75
+ if isinstance(arg, str):
76
+ prompt = f"{prompt}{arg}\n"
77
+ elif isinstance(arg, list):
78
+ for subarg in arg:
79
+ prompt = f"{prompt}{subarg}\n"
80
+ if hasattr(instance, "_model_id"):
81
+ model = instance._model_id
82
+ if hasattr(instance, "_model_name"):
83
+ model = instance._model_name.replace("publishers/google/models/", "")
84
+ if model.startswith("models/"):
85
+ model = model[len("models/"):]
86
+
87
+ total_tokens = input_tokens + output_tokens
88
+ # Calculate cost of the operation
89
+ cost = get_chat_model_cost(model,
90
+ pricing_info, input_tokens,
91
+ output_tokens)
92
+
93
+ # Set Span attributes
94
+ span.set_attribute(TELEMETRY_SDK_NAME, "openlit")
95
+ span.set_attribute(SemanticConvetion.GEN_AI_SYSTEM,
96
+ SemanticConvetion.GEN_AI_SYSTEM_GOOGLE_AI_STUDIO)
97
+ span.set_attribute(SemanticConvetion.GEN_AI_TYPE,
98
+ SemanticConvetion.GEN_AI_TYPE_CHAT)
99
+ span.set_attribute(SemanticConvetion.GEN_AI_ENDPOINT,
100
+ gen_ai_endpoint)
101
+ span.set_attribute(SemanticConvetion.GEN_AI_ENVIRONMENT,
102
+ environment)
103
+ span.set_attribute(SemanticConvetion.GEN_AI_APPLICATION_NAME,
104
+ application_name)
105
+ span.set_attribute(SemanticConvetion.GEN_AI_REQUEST_MODEL,
106
+ model)
107
+ span.set_attribute(SemanticConvetion.GEN_AI_REQUEST_IS_STREAM,
108
+ True)
109
+ span.set_attribute(SemanticConvetion.GEN_AI_USAGE_PROMPT_TOKENS,
110
+ input_tokens)
111
+ span.set_attribute(SemanticConvetion.GEN_AI_USAGE_COMPLETION_TOKENS,
112
+ output_tokens)
113
+ span.set_attribute(SemanticConvetion.GEN_AI_USAGE_TOTAL_TOKENS,
114
+ total_tokens)
115
+ span.set_attribute(SemanticConvetion.GEN_AI_USAGE_COST,
116
+ cost)
117
+ if trace_content:
118
+ span.add_event(
119
+ name=SemanticConvetion.GEN_AI_CONTENT_PROMPT_EVENT,
120
+ attributes={
121
+ SemanticConvetion.GEN_AI_CONTENT_PROMPT: prompt,
122
+ },
123
+ )
124
+ span.add_event(
125
+ name=SemanticConvetion.GEN_AI_CONTENT_COMPLETION_EVENT,
126
+ attributes={
127
+ SemanticConvetion.GEN_AI_CONTENT_COMPLETION: llmresponse,
128
+ },
129
+ )
130
+
131
+ span.set_status(Status(StatusCode.OK))
132
+
133
+ if disable_metrics is False:
134
+ attributes = {
135
+ TELEMETRY_SDK_NAME:
136
+ "openlit",
137
+ SemanticConvetion.GEN_AI_APPLICATION_NAME:
138
+ application_name,
139
+ SemanticConvetion.GEN_AI_SYSTEM:
140
+ SemanticConvetion.GEN_AI_SYSTEM_GOOGLE_AI_STUDIO,
141
+ SemanticConvetion.GEN_AI_ENVIRONMENT:
142
+ environment,
143
+ SemanticConvetion.GEN_AI_TYPE:
144
+ SemanticConvetion.GEN_AI_TYPE_CHAT,
145
+ SemanticConvetion.GEN_AI_REQUEST_MODEL:
146
+ model
147
+ }
148
+
149
+ metrics["genai_requests"].add(1, attributes)
150
+ metrics["genai_total_tokens"].add(
151
+ total_tokens, attributes
152
+ )
153
+ metrics["genai_completion_tokens"].add(output_tokens, attributes)
154
+ metrics["genai_prompt_tokens"].add(input_tokens, attributes)
155
+ metrics["genai_cost"].record(cost, attributes)
156
+
157
+ except Exception as e:
158
+ handle_exception(span, e)
159
+ logger.error("Error in trace creation: %s", e)
160
+
161
+ return stream_generator()
162
+ else:
163
+ # pylint: disable=line-too-long
164
+ with tracer.start_as_current_span(gen_ai_endpoint, kind= SpanKind.CLIENT) as span:
165
+ response = await wrapped(*args, **kwargs)
166
+
167
+ try:
168
+ prompt = ""
169
+ for arg in args:
170
+ if isinstance(arg, str):
171
+ prompt = f"{prompt}{arg}\n"
172
+ elif isinstance(arg, list):
173
+ for subarg in arg:
174
+ prompt = f"{prompt}{subarg}\n"
175
+ if hasattr(instance, "_model_id"):
176
+ model = instance._model_id
177
+ if hasattr(instance, "_model_name"):
178
+ model = instance._model_name.replace("publishers/google/models/", "")
179
+ if model.startswith("models/"):
180
+ model = model[len("models/"):]
181
+
182
+ # Set base span attribues
183
+ span.set_attribute(TELEMETRY_SDK_NAME, "openlit")
184
+ span.set_attribute(SemanticConvetion.GEN_AI_SYSTEM,
185
+ SemanticConvetion.GEN_AI_SYSTEM_GOOGLE_AI_STUDIO)
186
+ span.set_attribute(SemanticConvetion.GEN_AI_TYPE,
187
+ SemanticConvetion.GEN_AI_TYPE_CHAT)
188
+ span.set_attribute(SemanticConvetion.GEN_AI_ENDPOINT,
189
+ gen_ai_endpoint)
190
+ span.set_attribute(SemanticConvetion.GEN_AI_ENVIRONMENT,
191
+ environment)
192
+ span.set_attribute(SemanticConvetion.GEN_AI_APPLICATION_NAME,
193
+ application_name)
194
+ span.set_attribute(SemanticConvetion.GEN_AI_REQUEST_MODEL,
195
+ model)
196
+ span.set_attribute(SemanticConvetion.GEN_AI_REQUEST_IS_STREAM,
197
+ False)
198
+
199
+ if trace_content:
200
+ span.add_event(
201
+ name=SemanticConvetion.GEN_AI_CONTENT_PROMPT_EVENT,
202
+ attributes={
203
+ SemanticConvetion.GEN_AI_CONTENT_PROMPT: prompt,
204
+ },
205
+ )
206
+ span.add_event(
207
+ name=SemanticConvetion.GEN_AI_CONTENT_COMPLETION_EVENT,
208
+ attributes={
209
+ SemanticConvetion.GEN_AI_CONTENT_COMPLETION: response.text,
210
+ },
211
+ )
212
+
213
+ prompt_tokens = response.usage_metadata.prompt_token_count
214
+ completion_tokens = response.usage_metadata.candidates_token_count
215
+ total_tokens = response.usage_metadata.total_token_count
216
+ # Calculate cost of the operation
217
+ cost = get_chat_model_cost(model,
218
+ pricing_info, prompt_tokens, completion_tokens)
219
+
220
+ span.set_attribute(SemanticConvetion.GEN_AI_USAGE_PROMPT_TOKENS,
221
+ prompt_tokens)
222
+ span.set_attribute(SemanticConvetion.GEN_AI_USAGE_COMPLETION_TOKENS,
223
+ completion_tokens)
224
+ span.set_attribute(SemanticConvetion.GEN_AI_USAGE_TOTAL_TOKENS,
225
+ total_tokens)
226
+ span.set_attribute(SemanticConvetion.GEN_AI_USAGE_COST,
227
+ cost)
228
+
229
+ span.set_status(Status(StatusCode.OK))
230
+
231
+ if disable_metrics is False:
232
+ attributes = {
233
+ TELEMETRY_SDK_NAME:
234
+ "openlit",
235
+ SemanticConvetion.GEN_AI_APPLICATION_NAME:
236
+ application_name,
237
+ SemanticConvetion.GEN_AI_SYSTEM:
238
+ SemanticConvetion.GEN_AI_SYSTEM_GOOGLE_AI_STUDIO,
239
+ SemanticConvetion.GEN_AI_ENVIRONMENT:
240
+ environment,
241
+ SemanticConvetion.GEN_AI_TYPE:
242
+ SemanticConvetion.GEN_AI_TYPE_CHAT,
243
+ SemanticConvetion.GEN_AI_REQUEST_MODEL:
244
+ model
245
+ }
246
+
247
+ metrics["genai_requests"].add(1, attributes)
248
+ metrics["genai_total_tokens"].add(total_tokens, attributes)
249
+ metrics["genai_completion_tokens"].add(completion_tokens, attributes)
250
+ metrics["genai_prompt_tokens"].add(prompt_tokens, attributes)
251
+ metrics["genai_cost"].record(cost, attributes)
252
+
253
+ # Return original response
254
+ return response
255
+
256
+ except Exception as e:
257
+ handle_exception(span, e)
258
+ logger.error("Error in trace creation: %s", e)
259
+
260
+ # Return original response
261
+ return response
262
+
263
+ return wrapper
@@ -0,0 +1,265 @@
1
+ # pylint: disable=duplicate-code, broad-exception-caught, too-many-statements, unused-argument, possibly-used-before-assignment, protected-access
2
+ """
3
+ Module for monitoring Google AI Studio API calls.
4
+ """
5
+
6
+ import logging
7
+ from opentelemetry.trace import SpanKind, Status, StatusCode
8
+ from opentelemetry.sdk.resources import TELEMETRY_SDK_NAME
9
+ from openlit.__helpers import (
10
+ handle_exception,
11
+ get_chat_model_cost,
12
+ )
13
+ from openlit.semcov import SemanticConvetion
14
+
15
+ # Initialize logger for logging potential issues and operations
16
+ logger = logging.getLogger(__name__)
17
+
18
+ def generate(gen_ai_endpoint, version, environment, application_name,
19
+ tracer, pricing_info, trace_content, metrics, disable_metrics):
20
+ """
21
+ Generates a telemetry wrapper for chat to collect metrics.
22
+
23
+ Args:
24
+ gen_ai_endpoint: Endpoint identifier for logging and tracing.
25
+ version: Version of the monitoring package.
26
+ environment: Deployment environment (e.g., production, staging).
27
+ application_name: Name of the application using the Google AI Studio API.
28
+ tracer: OpenTelemetry tracer for creating spans.
29
+ pricing_info: Information used for calculating the cost of Google AI Studio usage.
30
+ trace_content: Flag indicating whether to trace the actual content.
31
+
32
+ Returns:
33
+ A function that wraps the chat method to add telemetry.
34
+ """
35
+
36
+ def wrapper(wrapped, instance, args, kwargs):
37
+ """
38
+ Wraps the 'chat' API call to add telemetry.
39
+
40
+ This collects metrics such as execution time, cost, and token usage, and handles errors
41
+ gracefully, adding details to the trace for observability.
42
+
43
+ Args:
44
+ wrapped: The original 'chat' method to be wrapped.
45
+ instance: The instance of the class where the original method is defined.
46
+ args: Positional arguments for the 'chat' method.
47
+ kwargs: Keyword arguments for the 'chat' method.
48
+
49
+ Returns:
50
+ The response from the original 'chat' method.
51
+ """
52
+ # pylint: disable=no-else-return
53
+ if kwargs.get("stream", False) is True:
54
+ # Special handling for streaming response to accommodate the nature of data flow
55
+ def stream_generator():
56
+ with tracer.start_as_current_span(gen_ai_endpoint, kind= SpanKind.CLIENT) as span:
57
+ # Placeholder for aggregating streaming response
58
+ llmresponse = ""
59
+
60
+ # Loop through streaming events capturing relevant details
61
+ for chunk in wrapped(*args, **kwargs):
62
+ # Collect message IDs and aggregated response from events
63
+ content = chunk.text
64
+ if content:
65
+ llmresponse += content
66
+
67
+ input_tokens = chunk.usage_metadata.prompt_token_count
68
+ output_tokens = chunk.usage_metadata.candidates_token_count
69
+ yield chunk
70
+
71
+ # Handling exception ensure observability without disrupting operation
72
+ try:
73
+ prompt = ""
74
+ for arg in args:
75
+ if isinstance(arg, str):
76
+ prompt = f"{prompt}{arg}\n"
77
+ elif isinstance(arg, list):
78
+ for subarg in arg:
79
+ prompt = f"{prompt}{subarg}\n"
80
+ if hasattr(instance, "_model_id"):
81
+ model = instance._model_id
82
+ if hasattr(instance, "_model_name"):
83
+ model = instance._model_name.replace("publishers/google/models/", "")
84
+ if model.startswith("models/"):
85
+ model = model[len("models/"):]
86
+
87
+ total_tokens = input_tokens + output_tokens
88
+ # Calculate cost of the operation
89
+ cost = get_chat_model_cost(model,
90
+ pricing_info, input_tokens,
91
+ output_tokens)
92
+
93
+ # Set Span attributes
94
+ span.set_attribute(TELEMETRY_SDK_NAME, "openlit")
95
+ span.set_attribute(SemanticConvetion.GEN_AI_SYSTEM,
96
+ SemanticConvetion.GEN_AI_SYSTEM_GOOGLE_AI_STUDIO)
97
+ span.set_attribute(SemanticConvetion.GEN_AI_TYPE,
98
+ SemanticConvetion.GEN_AI_TYPE_CHAT)
99
+ span.set_attribute(SemanticConvetion.GEN_AI_ENDPOINT,
100
+ gen_ai_endpoint)
101
+ span.set_attribute(SemanticConvetion.GEN_AI_ENVIRONMENT,
102
+ environment)
103
+ span.set_attribute(SemanticConvetion.GEN_AI_APPLICATION_NAME,
104
+ application_name)
105
+ span.set_attribute(SemanticConvetion.GEN_AI_REQUEST_MODEL,
106
+ model)
107
+ span.set_attribute(SemanticConvetion.GEN_AI_REQUEST_IS_STREAM,
108
+ True)
109
+ span.set_attribute(SemanticConvetion.GEN_AI_USAGE_PROMPT_TOKENS,
110
+ input_tokens)
111
+ span.set_attribute(SemanticConvetion.GEN_AI_USAGE_COMPLETION_TOKENS,
112
+ output_tokens)
113
+ span.set_attribute(SemanticConvetion.GEN_AI_USAGE_TOTAL_TOKENS,
114
+ total_tokens)
115
+ span.set_attribute(SemanticConvetion.GEN_AI_USAGE_COST,
116
+ cost)
117
+ if trace_content:
118
+ span.add_event(
119
+ name=SemanticConvetion.GEN_AI_CONTENT_PROMPT_EVENT,
120
+ attributes={
121
+ SemanticConvetion.GEN_AI_CONTENT_PROMPT: prompt,
122
+ },
123
+ )
124
+ span.add_event(
125
+ name=SemanticConvetion.GEN_AI_CONTENT_COMPLETION_EVENT,
126
+ attributes={
127
+ SemanticConvetion.GEN_AI_CONTENT_COMPLETION: llmresponse,
128
+ },
129
+ )
130
+
131
+ span.set_status(Status(StatusCode.OK))
132
+
133
+ if disable_metrics is False:
134
+ attributes = {
135
+ TELEMETRY_SDK_NAME:
136
+ "openlit",
137
+ SemanticConvetion.GEN_AI_APPLICATION_NAME:
138
+ application_name,
139
+ SemanticConvetion.GEN_AI_SYSTEM:
140
+ SemanticConvetion.GEN_AI_SYSTEM_GOOGLE_AI_STUDIO,
141
+ SemanticConvetion.GEN_AI_ENVIRONMENT:
142
+ environment,
143
+ SemanticConvetion.GEN_AI_TYPE:
144
+ SemanticConvetion.GEN_AI_TYPE_CHAT,
145
+ SemanticConvetion.GEN_AI_REQUEST_MODEL:
146
+ model
147
+ }
148
+
149
+ metrics["genai_requests"].add(1, attributes)
150
+ metrics["genai_total_tokens"].add(
151
+ total_tokens, attributes
152
+ )
153
+ metrics["genai_completion_tokens"].add(output_tokens, attributes)
154
+ metrics["genai_prompt_tokens"].add(input_tokens, attributes)
155
+ metrics["genai_cost"].record(cost, attributes)
156
+
157
+ except Exception as e:
158
+ handle_exception(span, e)
159
+ logger.error("Error in trace creation: %s", e)
160
+
161
+ return stream_generator()
162
+ else:
163
+ # pylint: disable=line-too-long
164
+ with tracer.start_as_current_span(gen_ai_endpoint, kind= SpanKind.CLIENT) as span:
165
+ response = wrapped(*args, **kwargs)
166
+
167
+ # print(instance._system_instruction.__dict__["_pb"].parts[0].text)
168
+ try:
169
+ prompt = ""
170
+ for arg in args:
171
+ if isinstance(arg, str):
172
+ prompt = f"{prompt}{arg}\n"
173
+ elif isinstance(arg, list):
174
+ for subarg in arg:
175
+ prompt = f"{prompt}{subarg}\n"
176
+
177
+ if hasattr(instance, "_model_id"):
178
+ model = instance._model_id
179
+ if hasattr(instance, "_model_name"):
180
+ model = instance._model_name.replace("publishers/google/models/", "")
181
+ if model.startswith("models/"):
182
+ model = model[len("models/"):]
183
+
184
+ # Set base span attribues
185
+ span.set_attribute(TELEMETRY_SDK_NAME, "openlit")
186
+ span.set_attribute(SemanticConvetion.GEN_AI_SYSTEM,
187
+ SemanticConvetion.GEN_AI_SYSTEM_GOOGLE_AI_STUDIO)
188
+ span.set_attribute(SemanticConvetion.GEN_AI_TYPE,
189
+ SemanticConvetion.GEN_AI_TYPE_CHAT)
190
+ span.set_attribute(SemanticConvetion.GEN_AI_ENDPOINT,
191
+ gen_ai_endpoint)
192
+ span.set_attribute(SemanticConvetion.GEN_AI_ENVIRONMENT,
193
+ environment)
194
+ span.set_attribute(SemanticConvetion.GEN_AI_APPLICATION_NAME,
195
+ application_name)
196
+ span.set_attribute(SemanticConvetion.GEN_AI_REQUEST_MODEL,
197
+ model)
198
+ span.set_attribute(SemanticConvetion.GEN_AI_REQUEST_IS_STREAM,
199
+ False)
200
+
201
+ if trace_content:
202
+ span.add_event(
203
+ name=SemanticConvetion.GEN_AI_CONTENT_PROMPT_EVENT,
204
+ attributes={
205
+ SemanticConvetion.GEN_AI_CONTENT_PROMPT: prompt,
206
+ },
207
+ )
208
+ span.add_event(
209
+ name=SemanticConvetion.GEN_AI_CONTENT_COMPLETION_EVENT,
210
+ attributes={
211
+ SemanticConvetion.GEN_AI_CONTENT_COMPLETION: response.text,
212
+ },
213
+ )
214
+
215
+ prompt_tokens = response.usage_metadata.prompt_token_count
216
+ completion_tokens = response.usage_metadata.candidates_token_count
217
+ total_tokens = response.usage_metadata.total_token_count
218
+ # Calculate cost of the operation
219
+ cost = get_chat_model_cost(model,
220
+ pricing_info, prompt_tokens, completion_tokens)
221
+
222
+ span.set_attribute(SemanticConvetion.GEN_AI_USAGE_PROMPT_TOKENS,
223
+ prompt_tokens)
224
+ span.set_attribute(SemanticConvetion.GEN_AI_USAGE_COMPLETION_TOKENS,
225
+ completion_tokens)
226
+ span.set_attribute(SemanticConvetion.GEN_AI_USAGE_TOTAL_TOKENS,
227
+ total_tokens)
228
+ span.set_attribute(SemanticConvetion.GEN_AI_USAGE_COST,
229
+ cost)
230
+
231
+ span.set_status(Status(StatusCode.OK))
232
+
233
+ if disable_metrics is False:
234
+ attributes = {
235
+ TELEMETRY_SDK_NAME:
236
+ "openlit",
237
+ SemanticConvetion.GEN_AI_APPLICATION_NAME:
238
+ application_name,
239
+ SemanticConvetion.GEN_AI_SYSTEM:
240
+ SemanticConvetion.GEN_AI_SYSTEM_GOOGLE_AI_STUDIO,
241
+ SemanticConvetion.GEN_AI_ENVIRONMENT:
242
+ environment,
243
+ SemanticConvetion.GEN_AI_TYPE:
244
+ SemanticConvetion.GEN_AI_TYPE_CHAT,
245
+ SemanticConvetion.GEN_AI_REQUEST_MODEL:
246
+ model
247
+ }
248
+
249
+ metrics["genai_requests"].add(1, attributes)
250
+ metrics["genai_total_tokens"].add(total_tokens, attributes)
251
+ metrics["genai_completion_tokens"].add(completion_tokens, attributes)
252
+ metrics["genai_prompt_tokens"].add(prompt_tokens, attributes)
253
+ metrics["genai_cost"].record(cost, attributes)
254
+
255
+ # Return original response
256
+ return response
257
+
258
+ except Exception as e:
259
+ handle_exception(span, e)
260
+ logger.error("Error in trace creation: %s", e)
261
+
262
+ # Return original response
263
+ return response
264
+
265
+ return wrapper
@@ -102,6 +102,7 @@ class SemanticConvetion:
102
102
  GEN_AI_SYSTEM_GPT4ALL = "gpt4all"
103
103
  GEN_AI_SYSTEM_ELEVENLABS = "elevenlabs"
104
104
  GEN_AI_SYSTEM_VLLM = "vLLM"
105
+ GEN_AI_SYSTEM_GOOGLE_AI_STUDIO = "google-ai-studio"
105
106
  GEN_AI_SYSTEM_LANGCHAIN = "langchain"
106
107
  GEN_AI_SYSTEM_LLAMAINDEX = "llama_index"
107
108
  GEN_AI_SYSTEM_HAYSTACK = "haystack"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: openlit
3
- Version: 1.19.0
3
+ Version: 1.21.0
4
4
  Summary: OpenTelemetry-native Auto instrumentation library for monitoring LLM Applications and GPUs, facilitating the integration of observability into your GenAI-driven projects
5
5
  Home-page: https://github.com/openlit/openlit/tree/main/openlit/python
6
6
  Keywords: OpenTelemetry,otel,otlp,llm,tracing,openai,anthropic,claude,cohere,llm monitoring,observability,monitoring,gpt,Generative AI,chatGPT,gpu
@@ -60,7 +60,7 @@ This project adheres to the [Semantic Conventions](https://github.com/open-telem
60
60
  | [✅ Ollama](https://docs.openlit.io/latest/integrations/ollama) | [✅ Pinecone](https://docs.openlit.io/latest/integrations/pinecone) | [✅ LiteLLM](https://docs.openlit.io/latest/integrations/litellm) | |
61
61
  | [✅ Anthropic](https://docs.openlit.io/latest/integrations/anthropic) | [✅ Qdrant](https://docs.openlit.io/latest/integrations/qdrant) | [✅ LlamaIndex](https://docs.openlit.io/latest/integrations/llama-index) | |
62
62
  | [✅ GPT4All](https://docs.openlit.io/latest/integrations/gpt4all) | [✅ Milvus](https://docs.openlit.io/latest/integrations/milvus) | [✅ Haystack](https://docs.openlit.io/latest/integrations/haystack) | |
63
- | [✅ Cohere](https://docs.openlit.io/latest/integrations/cohere) | | [✅ EmbedChain](https://docs.openlit.io/latest/integrations/embedchain) | |
63
+ | [✅ Cohere](https://docs.openlit.io/latest/integrations/cohere) | | [✅ EmbedChain](https://docs.openlit.io/latest/integrations/embedchain) | |
64
64
  | [✅ Mistral](https://docs.openlit.io/latest/integrations/mistral) | | [✅ Guardrails](https://docs.openlit.io/latest/integrations/guardrails) | |
65
65
  | [✅ Azure OpenAI](https://docs.openlit.io/latest/integrations/azure-openai) | | | |
66
66
  | [✅ HuggingFace Transformers](https://docs.openlit.io/latest/integrations/huggingface) | | | |
@@ -70,6 +70,7 @@ This project adheres to the [Semantic Conventions](https://github.com/open-telem
70
70
  | [✅ ElevenLabs](https://docs.openlit.io/latest/integrations/elevenlabs) | | | |
71
71
  | [✅ vLLM](https://docs.openlit.io/latest/integrations/vllm) | | | |
72
72
  | [✅ OLA Krutrim](https://docs.openlit.io/latest/integrations/krutrim) | | | |
73
+ | [✅ Google AI Studio](https://docs.openlit.io/latest/integrations/google-ai-studio) | | | |
73
74
 
74
75
  ## Supported Destinations
75
76
  - [✅ OpenTelemetry Collector](https://docs.openlit.io/latest/connections/otelcol)
@@ -1,5 +1,5 @@
1
1
  openlit/__helpers.py,sha256=lrn4PBs9owDudiCY2NBoVbAi7AU_HtUpyOj0oqPBsPY,5545
2
- openlit/__init__.py,sha256=LfU5w-D62u5pY70DdNbv5_DGtqeL1Yb0TlY-l0NAn8I,15103
2
+ openlit/__init__.py,sha256=fqeMFg76VYEX4VdxTn76Fh-0kbrN5_Sk8ahlm7Xlp9k,15296
3
3
  openlit/instrumentation/anthropic/__init__.py,sha256=oaU53BOPyfUKbEzYvLr1DPymDluurSnwo4Hernf2XdU,1955
4
4
  openlit/instrumentation/anthropic/anthropic.py,sha256=y7CEGhKOGHWt8G_5Phr4qPJTfPGRJIAr9Yk6nM3CcvM,16775
5
5
  openlit/instrumentation/anthropic/async_anthropic.py,sha256=Zz1KRKIG9wGn0quOoLvjORC-49IvHQpJ6GBdB-4PfCQ,16816
@@ -14,6 +14,9 @@ openlit/instrumentation/elevenlabs/async_elevenlabs.py,sha256=yMYACh95SFr5EYklKn
14
14
  openlit/instrumentation/elevenlabs/elevenlabs.py,sha256=mFnD7sgT47OxaXJz0Vc1nrNjXEpcGQDj5run3gA48Lw,6089
15
15
  openlit/instrumentation/embedchain/__init__.py,sha256=8TYk1OEbz46yF19dr-gB_x80VZMagU3kJ8-QihPXTeA,1929
16
16
  openlit/instrumentation/embedchain/embedchain.py,sha256=SLlr7qieT3kp4M6OYSRy8FaVCXQ2t3oPyIiE99ioNE4,7892
17
+ openlit/instrumentation/google_ai_studio/__init__.py,sha256=vG4WzaavOiiwI3r5stDMotM5TSBxdcxQhC3W4XjJIG8,2146
18
+ openlit/instrumentation/google_ai_studio/async_google_ai_studio.py,sha256=20MHsp-tAONxOtmCFg5WDvktTdRce5CyH3_9w0b_AqI,13587
19
+ openlit/instrumentation/google_ai_studio/google_ai_studio.py,sha256=vIJjzl5Fkgsf3vfaqmxhtSFvOpXK-wGC-JFhEXGP50M,13636
17
20
  openlit/instrumentation/gpt4all/__init__.py,sha256=-59CP2B3-HGZJ_vC-fI9Dt-0BuQXRhSCWCjnaGeU15Q,1802
18
21
  openlit/instrumentation/gpt4all/gpt4all.py,sha256=dbxqZeuTrv_y6wyDOIEmC8-Dc4iCGgLpj3l5JiodLMI,18787
19
22
  openlit/instrumentation/gpu/__init__.py,sha256=Dj2MLar0DB20-t6W3pfR-3jfR_mwg4SYwhzIrH_n9sU,5596
@@ -52,8 +55,8 @@ openlit/instrumentation/vllm/__init__.py,sha256=OVWalQ1dXvip1DUsjUGaHX4J-2FrSp-T
52
55
  openlit/instrumentation/vllm/vllm.py,sha256=lDzM7F5pgxvh8nKL0dcKB4TD0Mc9wXOWeXOsOGN7Wd8,6527
53
56
  openlit/otel/metrics.py,sha256=O7NoaDz0bY19mqpE4-0PcKwEe-B-iJFRgOCaanAuZAc,4291
54
57
  openlit/otel/tracing.py,sha256=vL1ifMbARPBpqK--yXYsCM6y5dSu5LFIKqkhZXtYmUc,3712
55
- openlit/semcov/__init__.py,sha256=EvoNOKtc7UKwLZ3Gp0-B1zwmeTcAIbx8O7wvAw8wXP4,7498
56
- openlit-1.19.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
57
- openlit-1.19.0.dist-info/METADATA,sha256=7P2h2TmPkrD-DTeqa0qqaC_oiqp8LdcEZ-pjuVepCjY,14746
58
- openlit-1.19.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
59
- openlit-1.19.0.dist-info/RECORD,,
58
+ openlit/semcov/__init__.py,sha256=56daxsJtWFqp87TTT3R5OxSeMH7eOZqb4k-7AELirTI,7554
59
+ openlit-1.21.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
60
+ openlit-1.21.0.dist-info/METADATA,sha256=1zrrmnjPv-UMLhm5DARcS9FylVEbOSUjvJpj1flSDAc,14934
61
+ openlit-1.21.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
62
+ openlit-1.21.0.dist-info/RECORD,,