openlit 1.34.30__py3-none-any.whl → 1.34.31__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 (168) hide show
  1. openlit/__helpers.py +235 -86
  2. openlit/__init__.py +16 -13
  3. openlit/_instrumentors.py +2 -1
  4. openlit/evals/all.py +50 -21
  5. openlit/evals/bias_detection.py +47 -20
  6. openlit/evals/hallucination.py +53 -22
  7. openlit/evals/toxicity.py +50 -21
  8. openlit/evals/utils.py +54 -30
  9. openlit/guard/all.py +61 -19
  10. openlit/guard/prompt_injection.py +34 -14
  11. openlit/guard/restrict_topic.py +46 -15
  12. openlit/guard/sensitive_topic.py +34 -14
  13. openlit/guard/utils.py +58 -22
  14. openlit/instrumentation/ag2/__init__.py +24 -8
  15. openlit/instrumentation/ag2/ag2.py +34 -13
  16. openlit/instrumentation/ag2/async_ag2.py +34 -13
  17. openlit/instrumentation/ag2/utils.py +133 -30
  18. openlit/instrumentation/ai21/__init__.py +43 -14
  19. openlit/instrumentation/ai21/ai21.py +47 -21
  20. openlit/instrumentation/ai21/async_ai21.py +47 -21
  21. openlit/instrumentation/ai21/utils.py +299 -78
  22. openlit/instrumentation/anthropic/__init__.py +21 -4
  23. openlit/instrumentation/anthropic/anthropic.py +28 -17
  24. openlit/instrumentation/anthropic/async_anthropic.py +28 -17
  25. openlit/instrumentation/anthropic/utils.py +145 -35
  26. openlit/instrumentation/assemblyai/__init__.py +11 -2
  27. openlit/instrumentation/assemblyai/assemblyai.py +15 -4
  28. openlit/instrumentation/assemblyai/utils.py +120 -25
  29. openlit/instrumentation/astra/__init__.py +43 -10
  30. openlit/instrumentation/astra/astra.py +28 -5
  31. openlit/instrumentation/astra/async_astra.py +28 -5
  32. openlit/instrumentation/astra/utils.py +151 -55
  33. openlit/instrumentation/azure_ai_inference/__init__.py +43 -10
  34. openlit/instrumentation/azure_ai_inference/async_azure_ai_inference.py +53 -21
  35. openlit/instrumentation/azure_ai_inference/azure_ai_inference.py +53 -21
  36. openlit/instrumentation/azure_ai_inference/utils.py +307 -83
  37. openlit/instrumentation/bedrock/__init__.py +21 -4
  38. openlit/instrumentation/bedrock/bedrock.py +63 -25
  39. openlit/instrumentation/bedrock/utils.py +139 -30
  40. openlit/instrumentation/chroma/__init__.py +89 -16
  41. openlit/instrumentation/chroma/chroma.py +28 -6
  42. openlit/instrumentation/chroma/utils.py +167 -51
  43. openlit/instrumentation/cohere/__init__.py +63 -18
  44. openlit/instrumentation/cohere/async_cohere.py +63 -24
  45. openlit/instrumentation/cohere/cohere.py +63 -24
  46. openlit/instrumentation/cohere/utils.py +286 -73
  47. openlit/instrumentation/controlflow/__init__.py +35 -9
  48. openlit/instrumentation/controlflow/controlflow.py +66 -33
  49. openlit/instrumentation/crawl4ai/__init__.py +25 -10
  50. openlit/instrumentation/crawl4ai/async_crawl4ai.py +78 -31
  51. openlit/instrumentation/crawl4ai/crawl4ai.py +78 -31
  52. openlit/instrumentation/crewai/__init__.py +40 -15
  53. openlit/instrumentation/crewai/async_crewai.py +32 -7
  54. openlit/instrumentation/crewai/crewai.py +32 -7
  55. openlit/instrumentation/crewai/utils.py +159 -56
  56. openlit/instrumentation/dynamiq/__init__.py +46 -12
  57. openlit/instrumentation/dynamiq/dynamiq.py +74 -33
  58. openlit/instrumentation/elevenlabs/__init__.py +23 -4
  59. openlit/instrumentation/elevenlabs/async_elevenlabs.py +16 -4
  60. openlit/instrumentation/elevenlabs/elevenlabs.py +16 -4
  61. openlit/instrumentation/elevenlabs/utils.py +128 -25
  62. openlit/instrumentation/embedchain/__init__.py +11 -2
  63. openlit/instrumentation/embedchain/embedchain.py +68 -35
  64. openlit/instrumentation/firecrawl/__init__.py +24 -7
  65. openlit/instrumentation/firecrawl/firecrawl.py +46 -20
  66. openlit/instrumentation/google_ai_studio/__init__.py +45 -10
  67. openlit/instrumentation/google_ai_studio/async_google_ai_studio.py +67 -44
  68. openlit/instrumentation/google_ai_studio/google_ai_studio.py +67 -44
  69. openlit/instrumentation/google_ai_studio/utils.py +180 -67
  70. openlit/instrumentation/gpt4all/__init__.py +22 -7
  71. openlit/instrumentation/gpt4all/gpt4all.py +67 -29
  72. openlit/instrumentation/gpt4all/utils.py +285 -61
  73. openlit/instrumentation/gpu/__init__.py +128 -47
  74. openlit/instrumentation/groq/__init__.py +21 -4
  75. openlit/instrumentation/groq/async_groq.py +33 -21
  76. openlit/instrumentation/groq/groq.py +33 -21
  77. openlit/instrumentation/groq/utils.py +192 -55
  78. openlit/instrumentation/haystack/__init__.py +70 -24
  79. openlit/instrumentation/haystack/async_haystack.py +28 -6
  80. openlit/instrumentation/haystack/haystack.py +28 -6
  81. openlit/instrumentation/haystack/utils.py +196 -74
  82. openlit/instrumentation/julep/__init__.py +69 -19
  83. openlit/instrumentation/julep/async_julep.py +53 -27
  84. openlit/instrumentation/julep/julep.py +53 -28
  85. openlit/instrumentation/langchain/__init__.py +74 -63
  86. openlit/instrumentation/langchain/callback_handler.py +1100 -0
  87. openlit/instrumentation/langchain_community/__init__.py +13 -2
  88. openlit/instrumentation/langchain_community/async_langchain_community.py +23 -5
  89. openlit/instrumentation/langchain_community/langchain_community.py +23 -5
  90. openlit/instrumentation/langchain_community/utils.py +35 -9
  91. openlit/instrumentation/letta/__init__.py +68 -15
  92. openlit/instrumentation/letta/letta.py +99 -54
  93. openlit/instrumentation/litellm/__init__.py +43 -14
  94. openlit/instrumentation/litellm/async_litellm.py +51 -26
  95. openlit/instrumentation/litellm/litellm.py +51 -26
  96. openlit/instrumentation/litellm/utils.py +304 -102
  97. openlit/instrumentation/llamaindex/__init__.py +267 -90
  98. openlit/instrumentation/llamaindex/async_llamaindex.py +28 -6
  99. openlit/instrumentation/llamaindex/llamaindex.py +28 -6
  100. openlit/instrumentation/llamaindex/utils.py +204 -91
  101. openlit/instrumentation/mem0/__init__.py +11 -2
  102. openlit/instrumentation/mem0/mem0.py +50 -29
  103. openlit/instrumentation/milvus/__init__.py +10 -2
  104. openlit/instrumentation/milvus/milvus.py +31 -6
  105. openlit/instrumentation/milvus/utils.py +166 -67
  106. openlit/instrumentation/mistral/__init__.py +63 -18
  107. openlit/instrumentation/mistral/async_mistral.py +63 -24
  108. openlit/instrumentation/mistral/mistral.py +63 -24
  109. openlit/instrumentation/mistral/utils.py +277 -69
  110. openlit/instrumentation/multion/__init__.py +69 -19
  111. openlit/instrumentation/multion/async_multion.py +57 -26
  112. openlit/instrumentation/multion/multion.py +57 -26
  113. openlit/instrumentation/ollama/__init__.py +39 -18
  114. openlit/instrumentation/ollama/async_ollama.py +57 -26
  115. openlit/instrumentation/ollama/ollama.py +57 -26
  116. openlit/instrumentation/ollama/utils.py +226 -50
  117. openlit/instrumentation/openai/__init__.py +156 -32
  118. openlit/instrumentation/openai/async_openai.py +147 -67
  119. openlit/instrumentation/openai/openai.py +150 -67
  120. openlit/instrumentation/openai/utils.py +657 -185
  121. openlit/instrumentation/openai_agents/__init__.py +5 -1
  122. openlit/instrumentation/openai_agents/processor.py +110 -90
  123. openlit/instrumentation/phidata/__init__.py +13 -5
  124. openlit/instrumentation/phidata/phidata.py +67 -32
  125. openlit/instrumentation/pinecone/__init__.py +48 -9
  126. openlit/instrumentation/pinecone/async_pinecone.py +27 -5
  127. openlit/instrumentation/pinecone/pinecone.py +27 -5
  128. openlit/instrumentation/pinecone/utils.py +153 -47
  129. openlit/instrumentation/premai/__init__.py +22 -7
  130. openlit/instrumentation/premai/premai.py +51 -26
  131. openlit/instrumentation/premai/utils.py +246 -59
  132. openlit/instrumentation/pydantic_ai/__init__.py +49 -22
  133. openlit/instrumentation/pydantic_ai/pydantic_ai.py +69 -16
  134. openlit/instrumentation/pydantic_ai/utils.py +89 -24
  135. openlit/instrumentation/qdrant/__init__.py +19 -4
  136. openlit/instrumentation/qdrant/async_qdrant.py +33 -7
  137. openlit/instrumentation/qdrant/qdrant.py +33 -7
  138. openlit/instrumentation/qdrant/utils.py +228 -93
  139. openlit/instrumentation/reka/__init__.py +23 -10
  140. openlit/instrumentation/reka/async_reka.py +17 -11
  141. openlit/instrumentation/reka/reka.py +17 -11
  142. openlit/instrumentation/reka/utils.py +138 -36
  143. openlit/instrumentation/together/__init__.py +44 -12
  144. openlit/instrumentation/together/async_together.py +50 -27
  145. openlit/instrumentation/together/together.py +50 -27
  146. openlit/instrumentation/together/utils.py +301 -71
  147. openlit/instrumentation/transformers/__init__.py +2 -1
  148. openlit/instrumentation/transformers/transformers.py +13 -3
  149. openlit/instrumentation/transformers/utils.py +139 -36
  150. openlit/instrumentation/vertexai/__init__.py +81 -16
  151. openlit/instrumentation/vertexai/async_vertexai.py +33 -15
  152. openlit/instrumentation/vertexai/utils.py +123 -27
  153. openlit/instrumentation/vertexai/vertexai.py +33 -15
  154. openlit/instrumentation/vllm/__init__.py +12 -5
  155. openlit/instrumentation/vllm/utils.py +121 -31
  156. openlit/instrumentation/vllm/vllm.py +16 -10
  157. openlit/otel/events.py +35 -10
  158. openlit/otel/metrics.py +32 -24
  159. openlit/otel/tracing.py +24 -9
  160. openlit/semcov/__init__.py +72 -6
  161. {openlit-1.34.30.dist-info → openlit-1.34.31.dist-info}/METADATA +2 -1
  162. openlit-1.34.31.dist-info/RECORD +166 -0
  163. openlit/instrumentation/langchain/async_langchain.py +0 -102
  164. openlit/instrumentation/langchain/langchain.py +0 -102
  165. openlit/instrumentation/langchain/utils.py +0 -252
  166. openlit-1.34.30.dist-info/RECORD +0 -168
  167. {openlit-1.34.30.dist-info → openlit-1.34.31.dist-info}/LICENSE +0 -0
  168. {openlit-1.34.30.dist-info → openlit-1.34.31.dist-info}/WHEEL +0 -0
@@ -5,7 +5,11 @@ Module for monitoring multion calls.
5
5
 
6
6
  import logging
7
7
  from opentelemetry.trace import SpanKind, Status, StatusCode
8
- from opentelemetry.sdk.resources import SERVICE_NAME, TELEMETRY_SDK_NAME, DEPLOYMENT_ENVIRONMENT
8
+ from opentelemetry.sdk.resources import (
9
+ SERVICE_NAME,
10
+ TELEMETRY_SDK_NAME,
11
+ DEPLOYMENT_ENVIRONMENT,
12
+ )
9
13
  from openlit.__helpers import (
10
14
  handle_exception,
11
15
  )
@@ -14,8 +18,18 @@ from openlit.semcov import SemanticConvention
14
18
  # Initialize logger for logging potential issues and operations
15
19
  logger = logging.getLogger(__name__)
16
20
 
17
- def async_multion_wrap(gen_ai_endpoint, version, environment, application_name,
18
- tracer, pricing_info, capture_message_content, metrics, disable_metrics):
21
+
22
+ def async_multion_wrap(
23
+ gen_ai_endpoint,
24
+ version,
25
+ environment,
26
+ application_name,
27
+ tracer,
28
+ pricing_info,
29
+ capture_message_content,
30
+ metrics,
31
+ disable_metrics,
32
+ ):
19
33
  """
20
34
  Generates a telemetry wrapper for chat completions to collect metrics.
21
35
 
@@ -50,36 +64,47 @@ def async_multion_wrap(gen_ai_endpoint, version, environment, application_name,
50
64
  """
51
65
 
52
66
  # pylint: disable=line-too-long
53
- with tracer.start_as_current_span(gen_ai_endpoint, kind= SpanKind.CLIENT) as span:
67
+ with tracer.start_as_current_span(
68
+ gen_ai_endpoint, kind=SpanKind.CLIENT
69
+ ) as span:
54
70
  response = await wrapped(*args, **kwargs)
55
71
 
56
72
  try:
57
73
  # Set base span attribues
58
74
  span.set_attribute(TELEMETRY_SDK_NAME, "openlit")
59
- span.set_attribute(SemanticConvention.GEN_AI_SYSTEM,
60
- SemanticConvention.GEN_AI_SYSTEM_MULTION)
61
- span.set_attribute(SemanticConvention.GEN_AI_OPERATION,
62
- SemanticConvention.GEN_AI_OPERATION_TYPE_AGENT)
63
- span.set_attribute(SemanticConvention.GEN_AI_ENDPOINT,
64
- gen_ai_endpoint)
65
- span.set_attribute(SERVICE_NAME,
66
- application_name)
67
- span.set_attribute(DEPLOYMENT_ENVIRONMENT,
68
- environment)
75
+ span.set_attribute(
76
+ SemanticConvention.GEN_AI_SYSTEM,
77
+ SemanticConvention.GEN_AI_SYSTEM_MULTION,
78
+ )
79
+ span.set_attribute(
80
+ SemanticConvention.GEN_AI_OPERATION,
81
+ SemanticConvention.GEN_AI_OPERATION_TYPE_AGENT,
82
+ )
83
+ span.set_attribute(SemanticConvention.GEN_AI_ENDPOINT, gen_ai_endpoint)
84
+ span.set_attribute(SERVICE_NAME, application_name)
85
+ span.set_attribute(DEPLOYMENT_ENVIRONMENT, environment)
69
86
 
70
87
  if gen_ai_endpoint == "multion.browse":
71
- span.set_attribute(SemanticConvention.GEN_AI_AGENT_BROWSE_URL,
72
- kwargs.get("url", ""))
73
- span.set_attribute(SemanticConvention.GEN_AI_AGENT_STEP_COUNT,
74
- response.metadata.step_count)
75
- span.set_attribute(SemanticConvention.GEN_AI_AGENT_RESPONSE_TIME,
76
- response.metadata.processing_time)
88
+ span.set_attribute(
89
+ SemanticConvention.GEN_AI_AGENT_BROWSE_URL,
90
+ kwargs.get("url", ""),
91
+ )
92
+ span.set_attribute(
93
+ SemanticConvention.GEN_AI_AGENT_STEP_COUNT,
94
+ response.metadata.step_count,
95
+ )
96
+ span.set_attribute(
97
+ SemanticConvention.GEN_AI_AGENT_RESPONSE_TIME,
98
+ response.metadata.processing_time,
99
+ )
77
100
 
78
101
  if capture_message_content:
79
102
  span.add_event(
80
103
  name=SemanticConvention.GEN_AI_CONTENT_PROMPT_EVENT,
81
104
  attributes={
82
- SemanticConvention.GEN_AI_CONTENT_PROMPT: kwargs.get("cmd", ""),
105
+ SemanticConvention.GEN_AI_CONTENT_PROMPT: kwargs.get(
106
+ "cmd", ""
107
+ ),
83
108
  },
84
109
  )
85
110
  span.add_event(
@@ -89,14 +114,18 @@ def async_multion_wrap(gen_ai_endpoint, version, environment, application_name,
89
114
  },
90
115
  )
91
116
  elif gen_ai_endpoint == "multion.retrieve":
92
- span.set_attribute(SemanticConvention.GEN_AI_AGENT_BROWSE_URL,
93
- kwargs.get("url", ""))
117
+ span.set_attribute(
118
+ SemanticConvention.GEN_AI_AGENT_BROWSE_URL,
119
+ kwargs.get("url", ""),
120
+ )
94
121
 
95
122
  if capture_message_content:
96
123
  span.add_event(
97
124
  name=SemanticConvention.GEN_AI_CONTENT_PROMPT_EVENT,
98
125
  attributes={
99
- SemanticConvention.GEN_AI_CONTENT_PROMPT: kwargs.get("cmd", ""),
126
+ SemanticConvention.GEN_AI_CONTENT_PROMPT: kwargs.get(
127
+ "cmd", ""
128
+ ),
100
129
  },
101
130
  )
102
131
  span.add_event(
@@ -107,8 +136,10 @@ def async_multion_wrap(gen_ai_endpoint, version, environment, application_name,
107
136
  )
108
137
 
109
138
  elif gen_ai_endpoint == "multion.sessions.create":
110
- span.set_attribute(SemanticConvention.GEN_AI_AGENT_BROWSE_URL,
111
- kwargs.get("url", ""))
139
+ span.set_attribute(
140
+ SemanticConvention.GEN_AI_AGENT_BROWSE_URL,
141
+ kwargs.get("url", ""),
142
+ )
112
143
 
113
144
  if capture_message_content:
114
145
  span.add_event(
@@ -5,7 +5,11 @@ Module for monitoring multion calls.
5
5
 
6
6
  import logging
7
7
  from opentelemetry.trace import SpanKind, Status, StatusCode
8
- from opentelemetry.sdk.resources import SERVICE_NAME, TELEMETRY_SDK_NAME, DEPLOYMENT_ENVIRONMENT
8
+ from opentelemetry.sdk.resources import (
9
+ SERVICE_NAME,
10
+ TELEMETRY_SDK_NAME,
11
+ DEPLOYMENT_ENVIRONMENT,
12
+ )
9
13
  from openlit.__helpers import (
10
14
  handle_exception,
11
15
  )
@@ -14,8 +18,18 @@ from openlit.semcov import SemanticConvention
14
18
  # Initialize logger for logging potential issues and operations
15
19
  logger = logging.getLogger(__name__)
16
20
 
17
- def multion_wrap(gen_ai_endpoint, version, environment, application_name,
18
- tracer, pricing_info, capture_message_content, metrics, disable_metrics):
21
+
22
+ def multion_wrap(
23
+ gen_ai_endpoint,
24
+ version,
25
+ environment,
26
+ application_name,
27
+ tracer,
28
+ pricing_info,
29
+ capture_message_content,
30
+ metrics,
31
+ disable_metrics,
32
+ ):
19
33
  """
20
34
  Generates a telemetry wrapper for chat completions to collect metrics.
21
35
 
@@ -50,36 +64,47 @@ def multion_wrap(gen_ai_endpoint, version, environment, application_name,
50
64
  """
51
65
 
52
66
  # pylint: disable=line-too-long
53
- with tracer.start_as_current_span(gen_ai_endpoint, kind= SpanKind.CLIENT) as span:
67
+ with tracer.start_as_current_span(
68
+ gen_ai_endpoint, kind=SpanKind.CLIENT
69
+ ) as span:
54
70
  response = wrapped(*args, **kwargs)
55
71
 
56
72
  try:
57
73
  # Set base span attribues
58
74
  span.set_attribute(TELEMETRY_SDK_NAME, "openlit")
59
- span.set_attribute(SemanticConvention.GEN_AI_SYSTEM,
60
- SemanticConvention.GEN_AI_SYSTEM_MULTION)
61
- span.set_attribute(SemanticConvention.GEN_AI_OPERATION,
62
- SemanticConvention.GEN_AI_OPERATION_TYPE_AGENT)
63
- span.set_attribute(SemanticConvention.GEN_AI_ENDPOINT,
64
- gen_ai_endpoint)
65
- span.set_attribute(SERVICE_NAME,
66
- application_name)
67
- span.set_attribute(DEPLOYMENT_ENVIRONMENT,
68
- environment)
75
+ span.set_attribute(
76
+ SemanticConvention.GEN_AI_SYSTEM,
77
+ SemanticConvention.GEN_AI_SYSTEM_MULTION,
78
+ )
79
+ span.set_attribute(
80
+ SemanticConvention.GEN_AI_OPERATION,
81
+ SemanticConvention.GEN_AI_OPERATION_TYPE_AGENT,
82
+ )
83
+ span.set_attribute(SemanticConvention.GEN_AI_ENDPOINT, gen_ai_endpoint)
84
+ span.set_attribute(SERVICE_NAME, application_name)
85
+ span.set_attribute(DEPLOYMENT_ENVIRONMENT, environment)
69
86
 
70
87
  if gen_ai_endpoint == "multion.browse":
71
- span.set_attribute(SemanticConvention.GEN_AI_AGENT_BROWSE_URL,
72
- kwargs.get("url", ""))
73
- span.set_attribute(SemanticConvention.GEN_AI_AGENT_STEP_COUNT,
74
- response.metadata.step_count)
75
- span.set_attribute(SemanticConvention.GEN_AI_AGENT_RESPONSE_TIME,
76
- response.metadata.processing_time)
88
+ span.set_attribute(
89
+ SemanticConvention.GEN_AI_AGENT_BROWSE_URL,
90
+ kwargs.get("url", ""),
91
+ )
92
+ span.set_attribute(
93
+ SemanticConvention.GEN_AI_AGENT_STEP_COUNT,
94
+ response.metadata.step_count,
95
+ )
96
+ span.set_attribute(
97
+ SemanticConvention.GEN_AI_AGENT_RESPONSE_TIME,
98
+ response.metadata.processing_time,
99
+ )
77
100
 
78
101
  if capture_message_content:
79
102
  span.add_event(
80
103
  name=SemanticConvention.GEN_AI_CONTENT_PROMPT_EVENT,
81
104
  attributes={
82
- SemanticConvention.GEN_AI_CONTENT_PROMPT: kwargs.get("cmd", ""),
105
+ SemanticConvention.GEN_AI_CONTENT_PROMPT: kwargs.get(
106
+ "cmd", ""
107
+ ),
83
108
  },
84
109
  )
85
110
  span.add_event(
@@ -89,14 +114,18 @@ def multion_wrap(gen_ai_endpoint, version, environment, application_name,
89
114
  },
90
115
  )
91
116
  elif gen_ai_endpoint == "multion.retrieve":
92
- span.set_attribute(SemanticConvention.GEN_AI_AGENT_BROWSE_URL,
93
- kwargs.get("url", ""))
117
+ span.set_attribute(
118
+ SemanticConvention.GEN_AI_AGENT_BROWSE_URL,
119
+ kwargs.get("url", ""),
120
+ )
94
121
 
95
122
  if capture_message_content:
96
123
  span.add_event(
97
124
  name=SemanticConvention.GEN_AI_CONTENT_PROMPT_EVENT,
98
125
  attributes={
99
- SemanticConvention.GEN_AI_CONTENT_PROMPT: kwargs.get("cmd", ""),
126
+ SemanticConvention.GEN_AI_CONTENT_PROMPT: kwargs.get(
127
+ "cmd", ""
128
+ ),
100
129
  },
101
130
  )
102
131
  span.add_event(
@@ -107,8 +136,10 @@ def multion_wrap(gen_ai_endpoint, version, environment, application_name,
107
136
  )
108
137
 
109
138
  elif gen_ai_endpoint == "multion.sessions.create":
110
- span.set_attribute(SemanticConvention.GEN_AI_AGENT_BROWSE_URL,
111
- kwargs.get("url", ""))
139
+ span.set_attribute(
140
+ SemanticConvention.GEN_AI_AGENT_BROWSE_URL,
141
+ kwargs.get("url", ""),
142
+ )
112
143
 
113
144
  if capture_message_content:
114
145
  span.add_event(
@@ -7,15 +7,12 @@ import importlib.metadata
7
7
  from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
8
8
  from wrapt import wrap_function_wrapper
9
9
 
10
- from openlit.instrumentation.ollama.ollama import (
11
- chat, embeddings
12
- )
13
- from openlit.instrumentation.ollama.async_ollama import (
14
- async_chat, async_embeddings
15
- )
10
+ from openlit.instrumentation.ollama.ollama import chat, embeddings
11
+ from openlit.instrumentation.ollama.async_ollama import async_chat, async_embeddings
16
12
 
17
13
  _instruments = ("ollama >= 0.2.0",)
18
14
 
15
+
19
16
  # Dispatch wrapper to route instrumentation to chat or embeddings based on path
20
17
  def _dispatch(sync_chat_wrap, sync_emb_wrap):
21
18
  def wrapper(wrapped, instance, args, kwargs):
@@ -26,8 +23,10 @@ def _dispatch(sync_chat_wrap, sync_emb_wrap):
26
23
  if op == "embeddings":
27
24
  return sync_emb_wrap(wrapped, instance, args, kwargs)
28
25
  return wrapped(*args, **kwargs)
26
+
29
27
  return wrapper
30
28
 
29
+
31
30
  def _dispatch_async(async_chat_wrap, async_emb_wrap):
32
31
  async def wrapper(wrapped, instance, args, kwargs):
33
32
  if len(args) > 2 and isinstance(args[2], str):
@@ -37,8 +36,10 @@ def _dispatch_async(async_chat_wrap, async_emb_wrap):
37
36
  if op == "embeddings":
38
37
  return await async_emb_wrap(wrapped, instance, args, kwargs)
39
38
  return await wrapped(*args, **kwargs)
39
+
40
40
  return wrapper
41
41
 
42
+
42
43
  class OllamaInstrumentor(BaseInstrumentor):
43
44
  """
44
45
  An instrumentor for Ollama client library.
@@ -59,24 +60,44 @@ class OllamaInstrumentor(BaseInstrumentor):
59
60
 
60
61
  # Build wrapper factories for chat and embeddings
61
62
  sync_chat_wrap = chat(
62
- version, environment, application_name,
63
- tracer, pricing_info,
64
- capture_message_content, metrics, disable_metrics
63
+ version,
64
+ environment,
65
+ application_name,
66
+ tracer,
67
+ pricing_info,
68
+ capture_message_content,
69
+ metrics,
70
+ disable_metrics,
65
71
  )
66
72
  sync_emb_wrap = embeddings(
67
- version, environment, application_name,
68
- tracer, pricing_info,
69
- capture_message_content, metrics, disable_metrics
73
+ version,
74
+ environment,
75
+ application_name,
76
+ tracer,
77
+ pricing_info,
78
+ capture_message_content,
79
+ metrics,
80
+ disable_metrics,
70
81
  )
71
82
  async_chat_wrap = async_chat(
72
- version, environment, application_name,
73
- tracer, pricing_info,
74
- capture_message_content, metrics, disable_metrics
83
+ version,
84
+ environment,
85
+ application_name,
86
+ tracer,
87
+ pricing_info,
88
+ capture_message_content,
89
+ metrics,
90
+ disable_metrics,
75
91
  )
76
92
  async_emb_wrap = async_embeddings(
77
- version, environment, application_name,
78
- tracer, pricing_info,
79
- capture_message_content, metrics, disable_metrics
93
+ version,
94
+ environment,
95
+ application_name,
96
+ tracer,
97
+ pricing_info,
98
+ capture_message_content,
99
+ metrics,
100
+ disable_metrics,
80
101
  )
81
102
 
82
103
  # Patch underlying request methods to ensure instrumentation regardless of import order
@@ -4,20 +4,26 @@ Module for monitoring Ollama API calls.
4
4
 
5
5
  import time
6
6
  from opentelemetry.trace import SpanKind
7
- from openlit.__helpers import (
8
- handle_exception,
9
- set_server_address_and_port
10
- )
7
+ from openlit.__helpers import handle_exception, set_server_address_and_port
11
8
  from openlit.instrumentation.ollama.utils import (
12
9
  process_chunk,
13
10
  process_chat_response,
14
11
  process_streaming_chat_response,
15
- process_embedding_response
12
+ process_embedding_response,
16
13
  )
17
14
  from openlit.semcov import SemanticConvention
18
15
 
19
- def async_chat(version, environment, application_name,
20
- tracer, pricing_info, capture_message_content, metrics, disable_metrics):
16
+
17
+ def async_chat(
18
+ version,
19
+ environment,
20
+ application_name,
21
+ tracer,
22
+ pricing_info,
23
+ capture_message_content,
24
+ metrics,
25
+ disable_metrics,
26
+ ):
21
27
  """
22
28
  Generates a telemetry wrapper for Ollama async chat function call
23
29
  """
@@ -28,15 +34,15 @@ def async_chat(version, environment, application_name,
28
34
  """
29
35
 
30
36
  def __init__(
31
- self,
32
- wrapped,
33
- span,
34
- span_name,
35
- kwargs,
36
- server_address,
37
- server_port,
38
- args,
39
- ):
37
+ self,
38
+ wrapped,
39
+ span,
40
+ span_name,
41
+ kwargs,
42
+ server_address,
43
+ server_port,
44
+ args,
45
+ ):
40
46
  self.__wrapped__ = wrapped
41
47
  self._span = span
42
48
  self._llmresponse = ""
@@ -78,7 +84,9 @@ def async_chat(version, environment, application_name,
78
84
  return chunk
79
85
  except StopAsyncIteration:
80
86
  try:
81
- with tracer.start_as_current_span(self._span_name, kind=SpanKind.CLIENT) as self._span:
87
+ with tracer.start_as_current_span(
88
+ self._span_name, kind=SpanKind.CLIENT
89
+ ) as self._span:
82
90
  process_streaming_chat_response(
83
91
  self,
84
92
  pricing_info=pricing_info,
@@ -87,7 +95,7 @@ def async_chat(version, environment, application_name,
87
95
  metrics=metrics,
88
96
  capture_message_content=capture_message_content,
89
97
  disable_metrics=disable_metrics,
90
- version=version
98
+ version=version,
91
99
  )
92
100
  except Exception as e:
93
101
  handle_exception(self._span, e)
@@ -101,7 +109,9 @@ def async_chat(version, environment, application_name,
101
109
 
102
110
  streaming = kwargs.get("stream", False)
103
111
 
104
- server_address, server_port = set_server_address_and_port(instance, "127.0.0.1", 11434)
112
+ server_address, server_port = set_server_address_and_port(
113
+ instance, "127.0.0.1", 11434
114
+ )
105
115
  json_body = kwargs.get("json", {}) or {}
106
116
  request_model = json_body.get("model") or kwargs.get("model")
107
117
 
@@ -110,7 +120,15 @@ def async_chat(version, environment, application_name,
110
120
  if streaming:
111
121
  awaited_wrapped = await wrapped(*args, **kwargs)
112
122
  span = tracer.start_span(span_name, kind=SpanKind.CLIENT)
113
- return TracedAsyncStream(awaited_wrapped, span, span_name, kwargs, server_address, server_port, args)
123
+ return TracedAsyncStream(
124
+ awaited_wrapped,
125
+ span,
126
+ span_name,
127
+ kwargs,
128
+ server_address,
129
+ server_port,
130
+ args,
131
+ )
114
132
 
115
133
  else:
116
134
  with tracer.start_as_current_span(span_name, kind=SpanKind.CLIENT) as span:
@@ -133,7 +151,7 @@ def async_chat(version, environment, application_name,
133
151
  capture_message_content=capture_message_content,
134
152
  disable_metrics=disable_metrics,
135
153
  version=version,
136
- **kwargs
154
+ **kwargs,
137
155
  )
138
156
 
139
157
  except Exception as e:
@@ -143,8 +161,17 @@ def async_chat(version, environment, application_name,
143
161
 
144
162
  return wrapper
145
163
 
146
- def async_embeddings(version, environment, application_name,
147
- tracer, pricing_info, capture_message_content, metrics, disable_metrics):
164
+
165
+ def async_embeddings(
166
+ version,
167
+ environment,
168
+ application_name,
169
+ tracer,
170
+ pricing_info,
171
+ capture_message_content,
172
+ metrics,
173
+ disable_metrics,
174
+ ):
148
175
  """
149
176
  Generates a telemetry wrapper for Ollama async embeddings function call
150
177
  """
@@ -154,10 +181,14 @@ def async_embeddings(version, environment, application_name,
154
181
  Wraps the Ollama async embeddings function call.
155
182
  """
156
183
 
157
- server_address, server_port = set_server_address_and_port(instance, "127.0.0.1", 11434)
184
+ server_address, server_port = set_server_address_and_port(
185
+ instance, "127.0.0.1", 11434
186
+ )
158
187
  request_model = kwargs.get("model")
159
188
 
160
- span_name = f"{SemanticConvention.GEN_AI_OPERATION_TYPE_EMBEDDING} {request_model}"
189
+ span_name = (
190
+ f"{SemanticConvention.GEN_AI_OPERATION_TYPE_EMBEDDING} {request_model}"
191
+ )
161
192
 
162
193
  with tracer.start_as_current_span(span_name, kind=SpanKind.CLIENT) as span:
163
194
  start_time = time.monotonic()
@@ -179,7 +210,7 @@ def async_embeddings(version, environment, application_name,
179
210
  capture_message_content=capture_message_content,
180
211
  disable_metrics=disable_metrics,
181
212
  version=version,
182
- **kwargs
213
+ **kwargs,
183
214
  )
184
215
 
185
216
  except Exception as e: