openlit 1.34.30__py3-none-any.whl → 1.34.32__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 +19 -14
  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 +113 -6
  15. openlit/instrumentation/ag2/ag2.py +459 -17
  16. openlit/instrumentation/ag2/async_ag2.py +459 -17
  17. openlit/instrumentation/ag2/utils.py +475 -31
  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 +82 -6
  161. {openlit-1.34.30.dist-info → openlit-1.34.32.dist-info}/METADATA +2 -1
  162. openlit-1.34.32.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.32.dist-info}/LICENSE +0 -0
  168. {openlit-1.34.30.dist-info → openlit-1.34.32.dist-info}/WHEEL +0 -0
openlit/guard/utils.py CHANGED
@@ -16,6 +16,7 @@ from openlit.semcov import SemanticConvention
16
16
  # Initialize logger for logging potential issues and operations
17
17
  logger = logging.getLogger(__name__)
18
18
 
19
+
19
20
  class JsonOutput(BaseModel):
20
21
  """
21
22
  A model representing the structure of JSON output for prompt injection detection.
@@ -34,13 +35,17 @@ class JsonOutput(BaseModel):
34
35
  classification: str
35
36
  explanation: str
36
37
 
37
- def setup_provider(provider: Optional[str], api_key: Optional[str],
38
- model: Optional[str],
39
- base_url: Optional[str]) -> Tuple[Optional[str], Optional[str], Optional[str]]:
38
+
39
+ def setup_provider(
40
+ provider: Optional[str],
41
+ api_key: Optional[str],
42
+ model: Optional[str],
43
+ base_url: Optional[str],
44
+ ) -> Tuple[Optional[str], Optional[str], Optional[str]]:
40
45
  """Function to setup LLM provider"""
41
46
  provider_configs = {
42
47
  "openai": {"env_var": "OPENAI_API_KEY"},
43
- "anthropic": {"env_var": "ANTHROPIC_API_KEY"}
48
+ "anthropic": {"env_var": "ANTHROPIC_API_KEY"},
44
49
  }
45
50
 
46
51
  if provider is None:
@@ -60,7 +65,9 @@ def setup_provider(provider: Optional[str], api_key: Optional[str],
60
65
 
61
66
  if not api_key:
62
67
  # pylint: disable=line-too-long
63
- raise ValueError(f"API key required via 'api_key' parameter or '{env_var}' environment variable")
68
+ raise ValueError(
69
+ f"API key required via 'api_key' parameter or '{env_var}' environment variable"
70
+ )
64
71
 
65
72
  return api_key, model, base_url
66
73
 
@@ -69,6 +76,7 @@ def format_prompt(system_prompt: str, text: str) -> str:
69
76
  """Function to format the prompt"""
70
77
  return system_prompt.replace("{{prompt}}", text)
71
78
 
79
+
72
80
  def llm_response(provider: str, prompt: str, model: str, base_url: str) -> str:
73
81
  """Function to get LLM response based on provider"""
74
82
  # pylint: disable=no-else-return
@@ -79,6 +87,7 @@ def llm_response(provider: str, prompt: str, model: str, base_url: str) -> str:
79
87
  else:
80
88
  raise ValueError(f"Unsupported provider: {provider}")
81
89
 
90
+
82
91
  def llm_response_openai(prompt: str, model: str, base_url: str) -> str:
83
92
  """Function to make LLM call to OpenAI"""
84
93
  client = OpenAI(base_url=base_url)
@@ -95,10 +104,11 @@ def llm_response_openai(prompt: str, model: str, base_url: str) -> str:
95
104
  {"role": "user", "content": prompt},
96
105
  ],
97
106
  temperature=0.0,
98
- response_format=JsonOutput
107
+ response_format=JsonOutput,
99
108
  )
100
109
  return response.choices[0].message.content
101
110
 
111
+
102
112
  def llm_response_anthropic(prompt: str, model: str) -> str:
103
113
  """Function to make LLM call to Anthropic"""
104
114
  client = Anthropic()
@@ -113,26 +123,42 @@ def llm_response_anthropic(prompt: str, model: str) -> str:
113
123
  "input_schema": {
114
124
  "type": "object",
115
125
  "properties": {
116
- "verdict": {"type": "string", "description": "Verdict of guardrail"},
126
+ "verdict": {
127
+ "type": "string",
128
+ "description": "Verdict of guardrail",
129
+ },
117
130
  "guard": {"type": "string", "description": "Type of guard"},
118
- "score": {"type": "number", "description": "Prompt score from Guard."},
119
- "classification": {"type": "string", "description": "Incorrect prompt type"},
120
- "explanation": {"type": "string", "description": "Reason for classification"}
131
+ "score": {
132
+ "type": "number",
133
+ "description": "Prompt score from Guard.",
134
+ },
135
+ "classification": {
136
+ "type": "string",
137
+ "description": "Incorrect prompt type",
138
+ },
139
+ "explanation": {
140
+ "type": "string",
141
+ "description": "Reason for classification",
142
+ },
121
143
  },
122
- "required": ["verdict", "guard", "score", "classification", "explanation"]
123
- }
144
+ "required": [
145
+ "verdict",
146
+ "guard",
147
+ "score",
148
+ "classification",
149
+ "explanation",
150
+ ],
151
+ },
124
152
  }
125
153
  ]
126
154
 
127
155
  response = client.messages.create(
128
156
  model=model,
129
- messages=[
130
- {"role": "user", "content": prompt}
131
- ],
157
+ messages=[{"role": "user", "content": prompt}],
132
158
  max_tokens=2000,
133
159
  temperature=0.0,
134
160
  tools=tools,
135
- stream=False
161
+ stream=False,
136
162
  )
137
163
 
138
164
  for content in response.content:
@@ -142,6 +168,7 @@ def llm_response_anthropic(prompt: str, model: str) -> str:
142
168
 
143
169
  return response
144
170
 
171
+
145
172
  def parse_llm_response(response) -> JsonOutput:
146
173
  """
147
174
  Parses the LLM response into a JsonOutput object.
@@ -163,8 +190,14 @@ def parse_llm_response(response) -> JsonOutput:
163
190
  return JsonOutput(**data)
164
191
  except (json.JSONDecodeError, TypeError) as e:
165
192
  logger.error("Error parsing LLM response: '%s'", e)
166
- return JsonOutput(score=0, classification="none", explanation="none",
167
- verdict="none", guard="none")
193
+ return JsonOutput(
194
+ score=0,
195
+ classification="none",
196
+ explanation="none",
197
+ verdict="none",
198
+ guard="none",
199
+ )
200
+
168
201
 
169
202
  def custom_rule_detection(text: str, custom_rules: list) -> JsonOutput:
170
203
  """
@@ -183,10 +216,12 @@ def custom_rule_detection(text: str, custom_rules: list) -> JsonOutput:
183
216
  guard=rule.get("guard", "prompt_injection"),
184
217
  score=rule.get("score", 0.5),
185
218
  classification=rule.get("classification", "custom"),
186
- explanation=rule.get("explanation", "Matched custom rule pattern.")
219
+ explanation=rule.get("explanation", "Matched custom rule pattern."),
187
220
  )
188
- return JsonOutput(score=0, classification="none", explanation="none",
189
- verdict="none", guard="none")
221
+ return JsonOutput(
222
+ score=0, classification="none", explanation="none", verdict="none", guard="none"
223
+ )
224
+
190
225
 
191
226
  def guard_metrics():
192
227
  """
@@ -204,11 +239,12 @@ def guard_metrics():
204
239
  guard_requests = meter.create_counter(
205
240
  name=SemanticConvention.GUARD_REQUESTS,
206
241
  description="Counter for Guard requests",
207
- unit="1"
242
+ unit="1",
208
243
  )
209
244
 
210
245
  return guard_requests
211
246
 
247
+
212
248
  def guard_metric_attributes(verdict, score, validator, classification, explanation):
213
249
  """
214
250
  Initializes OpenTelemetry attributes for metrics.
@@ -6,14 +6,25 @@ from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
6
6
  from wrapt import wrap_function_wrapper
7
7
 
8
8
  from openlit.instrumentation.ag2.ag2 import (
9
- conversable_agent, agent_run
9
+ conversable_agent,
10
+ agent_run,
11
+ agent_generate_reply,
12
+ agent_receive,
13
+ agent_send,
14
+ groupchat_manager_run_chat,
15
+ groupchat_select_speaker,
10
16
  )
11
17
  from openlit.instrumentation.ag2.async_ag2 import (
12
- async_conversable_agent, async_agent_run
18
+ async_conversable_agent,
19
+ async_agent_run,
20
+ async_agent_generate_reply,
21
+ async_agent_receive,
22
+ async_agent_send,
13
23
  )
14
24
 
15
25
  _instruments = ("ag2 >= 0.3.2",)
16
26
 
27
+
17
28
  class AG2Instrumentor(BaseInstrumentor):
18
29
  """
19
30
  An instrumentor for AG2 client library.
@@ -36,16 +47,112 @@ class AG2Instrumentor(BaseInstrumentor):
36
47
  wrap_function_wrapper(
37
48
  "autogen.agentchat.conversable_agent",
38
49
  "ConversableAgent.__init__",
39
- conversable_agent(version, environment, application_name,
40
- tracer, pricing_info, capture_message_content, metrics, disable_metrics),
50
+ conversable_agent(
51
+ version,
52
+ environment,
53
+ application_name,
54
+ tracer,
55
+ pricing_info,
56
+ capture_message_content,
57
+ metrics,
58
+ disable_metrics,
59
+ ),
41
60
  )
42
61
 
43
62
  # sync agent run
44
63
  wrap_function_wrapper(
45
64
  "autogen.agentchat.conversable_agent",
46
65
  "ConversableAgent.run",
47
- agent_run(version, environment, application_name,
48
- tracer, pricing_info, capture_message_content, metrics, disable_metrics),
66
+ agent_run(
67
+ version,
68
+ environment,
69
+ application_name,
70
+ tracer,
71
+ pricing_info,
72
+ capture_message_content,
73
+ metrics,
74
+ disable_metrics,
75
+ ),
76
+ )
77
+
78
+ # sync agent generate_reply
79
+ wrap_function_wrapper(
80
+ "autogen.agentchat.conversable_agent",
81
+ "ConversableAgent.generate_reply",
82
+ agent_generate_reply(
83
+ version,
84
+ environment,
85
+ application_name,
86
+ tracer,
87
+ pricing_info,
88
+ capture_message_content,
89
+ metrics,
90
+ disable_metrics,
91
+ ),
92
+ )
93
+
94
+ # sync agent receive
95
+ wrap_function_wrapper(
96
+ "autogen.agentchat.conversable_agent",
97
+ "ConversableAgent.receive",
98
+ agent_receive(
99
+ version,
100
+ environment,
101
+ application_name,
102
+ tracer,
103
+ pricing_info,
104
+ capture_message_content,
105
+ metrics,
106
+ disable_metrics,
107
+ ),
108
+ )
109
+
110
+ # sync agent send
111
+ wrap_function_wrapper(
112
+ "autogen.agentchat.conversable_agent",
113
+ "ConversableAgent.send",
114
+ agent_send(
115
+ version,
116
+ environment,
117
+ application_name,
118
+ tracer,
119
+ pricing_info,
120
+ capture_message_content,
121
+ metrics,
122
+ disable_metrics,
123
+ ),
124
+ )
125
+
126
+ # sync groupchat manager run_chat
127
+ wrap_function_wrapper(
128
+ "autogen.agentchat.groupchat",
129
+ "GroupChatManager.run_chat",
130
+ groupchat_manager_run_chat(
131
+ version,
132
+ environment,
133
+ application_name,
134
+ tracer,
135
+ pricing_info,
136
+ capture_message_content,
137
+ metrics,
138
+ disable_metrics,
139
+ ),
140
+ )
141
+
142
+ # sync groupchat select_speaker
143
+ wrap_function_wrapper(
144
+ "autogen.agentchat.groupchat",
145
+ "GroupChat.select_speaker",
146
+ groupchat_select_speaker(
147
+ version,
148
+ environment,
149
+ application_name,
150
+ tracer,
151
+ pricing_info,
152
+ capture_message_content,
153
+ metrics,
154
+ disable_metrics,
155
+ ),
49
156
  )
50
157
 
51
158
  def _uninstrument(self, **kwargs):