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
@@ -1,4 +1,5 @@
1
1
  """Initializer of Auto Instrumentation of LangChain Community Functions"""
2
+
2
3
  from typing import Collection
3
4
  import importlib.metadata
4
5
  from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
@@ -40,6 +41,7 @@ WRAPPED_METHODS = [
40
41
  },
41
42
  ]
42
43
 
44
+
43
45
  class LangChainCommunityInstrumentor(BaseInstrumentor):
44
46
  """
45
47
  An instrumentor for LangChain Community client library.
@@ -66,8 +68,17 @@ class LangChainCommunityInstrumentor(BaseInstrumentor):
66
68
  wrap_function_wrapper(
67
69
  wrap_package,
68
70
  wrap_object,
69
- wrapper(gen_ai_endpoint, version, environment, application_name,
70
- tracer, pricing_info, capture_message_content, metrics, disable_metrics),
71
+ wrapper(
72
+ gen_ai_endpoint,
73
+ version,
74
+ environment,
75
+ application_name,
76
+ tracer,
77
+ pricing_info,
78
+ capture_message_content,
79
+ metrics,
80
+ disable_metrics,
81
+ ),
71
82
  )
72
83
 
73
84
  def _uninstrument(self, **kwargs):
@@ -12,8 +12,18 @@ from openlit.instrumentation.langchain_community.utils import process_general_re
12
12
  # Initialize logger for LangChain Community instrumentation
13
13
  logger = logging.getLogger(__name__)
14
14
 
15
- def async_general_wrap(gen_ai_endpoint, version, environment, application_name, tracer, pricing_info,
16
- capture_message_content, metrics, disable_metrics):
15
+
16
+ def async_general_wrap(
17
+ gen_ai_endpoint,
18
+ version,
19
+ environment,
20
+ application_name,
21
+ tracer,
22
+ pricing_info,
23
+ capture_message_content,
24
+ metrics,
25
+ disable_metrics,
26
+ ):
17
27
  """
18
28
  Generates a telemetry wrapper for GenAI operations.
19
29
  """
@@ -28,15 +38,23 @@ def async_general_wrap(gen_ai_endpoint, version, environment, application_name,
28
38
  server_port = "80"
29
39
 
30
40
  # Get the parent span from the tracer
31
- with tracer.start_as_current_span(gen_ai_endpoint, kind=trace.SpanKind.CLIENT) as span:
41
+ with tracer.start_as_current_span(
42
+ gen_ai_endpoint, kind=trace.SpanKind.CLIENT
43
+ ) as span:
32
44
  try:
33
45
  # Call the original async function
34
46
  response = await wrapped(*args, **kwargs)
35
47
 
36
48
  # Process the response using the utility function
37
49
  response = process_general_response(
38
- response, gen_ai_endpoint, server_port, server_address,
39
- environment, application_name, span, version
50
+ response,
51
+ gen_ai_endpoint,
52
+ server_port,
53
+ server_address,
54
+ environment,
55
+ application_name,
56
+ span,
57
+ version,
40
58
  )
41
59
 
42
60
  span.set_status(Status(StatusCode.OK))
@@ -12,8 +12,18 @@ from openlit.instrumentation.langchain_community.utils import process_general_re
12
12
  # Initialize logger for LangChain Community instrumentation
13
13
  logger = logging.getLogger(__name__)
14
14
 
15
- def general_wrap(gen_ai_endpoint, version, environment, application_name, tracer, pricing_info,
16
- capture_message_content, metrics, disable_metrics):
15
+
16
+ def general_wrap(
17
+ gen_ai_endpoint,
18
+ version,
19
+ environment,
20
+ application_name,
21
+ tracer,
22
+ pricing_info,
23
+ capture_message_content,
24
+ metrics,
25
+ disable_metrics,
26
+ ):
17
27
  """
18
28
  Generates a telemetry wrapper for GenAI operations.
19
29
  """
@@ -28,15 +38,23 @@ def general_wrap(gen_ai_endpoint, version, environment, application_name, tracer
28
38
  server_port = "80"
29
39
 
30
40
  # Get the parent span from the tracer
31
- with tracer.start_as_current_span(gen_ai_endpoint, kind=trace.SpanKind.CLIENT) as span:
41
+ with tracer.start_as_current_span(
42
+ gen_ai_endpoint, kind=trace.SpanKind.CLIENT
43
+ ) as span:
32
44
  try:
33
45
  # Call the original function
34
46
  response = wrapped(*args, **kwargs)
35
47
 
36
48
  # Process the response using the utility function
37
49
  response = process_general_response(
38
- response, gen_ai_endpoint, server_port, server_address,
39
- environment, application_name, span, version
50
+ response,
51
+ gen_ai_endpoint,
52
+ server_port,
53
+ server_address,
54
+ environment,
55
+ application_name,
56
+ span,
57
+ version,
40
58
  )
41
59
 
42
60
  span.set_status(Status(StatusCode.OK))
@@ -5,8 +5,17 @@ Utility functions for LangChain Community instrumentation.
5
5
  from opentelemetry.trace import Status, StatusCode
6
6
  from openlit.semcov import SemanticConvention
7
7
 
8
- def process_general_response(response, gen_ai_endpoint, server_port, server_address,
9
- environment, application_name, span, version="1.0.0"):
8
+
9
+ def process_general_response(
10
+ response,
11
+ gen_ai_endpoint,
12
+ server_port,
13
+ server_address,
14
+ environment,
15
+ application_name,
16
+ span,
17
+ version="1.0.0",
18
+ ):
10
19
  """
11
20
  Process general LangChain Community operations (document loading, text splitting) and generate telemetry.
12
21
 
@@ -25,9 +34,14 @@ def process_general_response(response, gen_ai_endpoint, server_port, server_addr
25
34
  """
26
35
 
27
36
  # Set span attributes for general operations
28
- span.set_attribute(SemanticConvention.GEN_AI_SYSTEM, SemanticConvention.GEN_AI_SYSTEM_LANGCHAIN)
37
+ span.set_attribute(
38
+ SemanticConvention.GEN_AI_SYSTEM, SemanticConvention.GEN_AI_SYSTEM_LANGCHAIN
39
+ )
29
40
  span.set_attribute(SemanticConvention.GEN_AI_ENDPOINT, gen_ai_endpoint)
30
- span.set_attribute(SemanticConvention.GEN_AI_OPERATION, SemanticConvention.GEN_AI_OPERATION_TYPE_FRAMEWORK)
41
+ span.set_attribute(
42
+ SemanticConvention.GEN_AI_OPERATION,
43
+ SemanticConvention.GEN_AI_OPERATION_TYPE_FRAMEWORK,
44
+ )
31
45
  span.set_attribute(SemanticConvention.GEN_AI_SDK_VERSION, version)
32
46
  span.set_attribute(SemanticConvention.GEN_AI_ENVIRONMENT, environment)
33
47
  span.set_attribute(SemanticConvention.GEN_AI_APPLICATION_NAME, application_name)
@@ -38,9 +52,13 @@ def process_general_response(response, gen_ai_endpoint, server_port, server_addr
38
52
  if hasattr(response, "__iter__") and len(response) > 0:
39
53
  # For document loaders, try to get source from first document
40
54
  first_doc = response[0]
41
- if hasattr(first_doc, "metadata") and isinstance(first_doc.metadata, dict):
55
+ if hasattr(first_doc, "metadata") and isinstance(
56
+ first_doc.metadata, dict
57
+ ):
42
58
  source = first_doc.metadata.get("source", "unknown")
43
- span.set_attribute(SemanticConvention.GEN_AI_RETRIEVAL_SOURCE, source)
59
+ span.set_attribute(
60
+ SemanticConvention.GEN_AI_RETRIEVAL_SOURCE, source
61
+ )
44
62
 
45
63
  # Count number of documents loaded
46
64
  span.set_attribute("gen_ai.retrieval.documents.count", len(response))
@@ -49,17 +67,25 @@ def process_general_response(response, gen_ai_endpoint, server_port, server_addr
49
67
  pass
50
68
 
51
69
  # For text splitting operations
52
- elif gen_ai_endpoint and ("split_documents" in gen_ai_endpoint or "create_documents" in gen_ai_endpoint):
70
+ elif gen_ai_endpoint and (
71
+ "split_documents" in gen_ai_endpoint or "create_documents" in gen_ai_endpoint
72
+ ):
53
73
  try:
54
74
  if hasattr(response, "__iter__") and len(response) > 0:
55
75
  # Count number of text chunks created
56
76
  span.set_attribute("gen_ai.text_splitter.chunks.count", len(response))
57
77
 
58
78
  # Try to get average chunk size
59
- total_chars = sum(len(doc.page_content) for doc in response if hasattr(doc, "page_content"))
79
+ total_chars = sum(
80
+ len(doc.page_content)
81
+ for doc in response
82
+ if hasattr(doc, "page_content")
83
+ )
60
84
  if total_chars > 0:
61
85
  avg_chunk_size = total_chars // len(response)
62
- span.set_attribute("gen_ai.text_splitter.avg_chunk_size", avg_chunk_size)
86
+ span.set_attribute(
87
+ "gen_ai.text_splitter.avg_chunk_size", avg_chunk_size
88
+ )
63
89
  except (AttributeError, TypeError):
64
90
  # If we cant extract chunk information, just continue without it
65
91
  pass
@@ -6,12 +6,11 @@ import importlib.metadata
6
6
  from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
7
7
  from wrapt import wrap_function_wrapper
8
8
 
9
- from openlit.instrumentation.letta.letta import (
10
- create_agent, send_message
11
- )
9
+ from openlit.instrumentation.letta.letta import create_agent, send_message
12
10
 
13
11
  _instruments = ("letta >= 0.6.2",)
14
12
 
13
+
15
14
  class LettaInstrumentor(BaseInstrumentor):
16
15
  """
17
16
  An instrumentor for Letta's client library.
@@ -33,43 +32,97 @@ class LettaInstrumentor(BaseInstrumentor):
33
32
  wrap_function_wrapper(
34
33
  "letta.client.client",
35
34
  "LocalClient.create_agent",
36
- create_agent("letta.create_agent", version, environment, application_name,
37
- tracer, pricing_info, capture_message_content, metrics, disable_metrics),
35
+ create_agent(
36
+ "letta.create_agent",
37
+ version,
38
+ environment,
39
+ application_name,
40
+ tracer,
41
+ pricing_info,
42
+ capture_message_content,
43
+ metrics,
44
+ disable_metrics,
45
+ ),
38
46
  )
39
47
 
40
48
  wrap_function_wrapper(
41
49
  "letta.client.client",
42
50
  "LocalClient.get_agent",
43
- create_agent("letta.get_agent", version, environment, application_name,
44
- tracer, pricing_info, capture_message_content, metrics, disable_metrics),
51
+ create_agent(
52
+ "letta.get_agent",
53
+ version,
54
+ environment,
55
+ application_name,
56
+ tracer,
57
+ pricing_info,
58
+ capture_message_content,
59
+ metrics,
60
+ disable_metrics,
61
+ ),
45
62
  )
46
63
 
47
64
  wrap_function_wrapper(
48
65
  "letta.client.client",
49
66
  "LocalClient.send_message",
50
- send_message("letta.send_message", version, environment, application_name,
51
- tracer, pricing_info, capture_message_content, metrics, disable_metrics),
67
+ send_message(
68
+ "letta.send_message",
69
+ version,
70
+ environment,
71
+ application_name,
72
+ tracer,
73
+ pricing_info,
74
+ capture_message_content,
75
+ metrics,
76
+ disable_metrics,
77
+ ),
52
78
  )
53
79
 
54
80
  wrap_function_wrapper(
55
81
  "letta.client.client",
56
82
  "RESTClient.create_agent",
57
- create_agent("letta.create_agent", version, environment, application_name,
58
- tracer, pricing_info, capture_message_content, metrics, disable_metrics),
83
+ create_agent(
84
+ "letta.create_agent",
85
+ version,
86
+ environment,
87
+ application_name,
88
+ tracer,
89
+ pricing_info,
90
+ capture_message_content,
91
+ metrics,
92
+ disable_metrics,
93
+ ),
59
94
  )
60
95
 
61
96
  wrap_function_wrapper(
62
97
  "letta.client.client",
63
98
  "RESTClient.get_agent",
64
- create_agent("letta.get_agent", version, environment, application_name,
65
- tracer, pricing_info, capture_message_content, metrics, disable_metrics),
99
+ create_agent(
100
+ "letta.get_agent",
101
+ version,
102
+ environment,
103
+ application_name,
104
+ tracer,
105
+ pricing_info,
106
+ capture_message_content,
107
+ metrics,
108
+ disable_metrics,
109
+ ),
66
110
  )
67
111
 
68
112
  wrap_function_wrapper(
69
113
  "letta.client.client",
70
114
  "RESTClient.send_message",
71
- send_message("letta.send_message", version, environment, application_name,
72
- tracer, pricing_info, capture_message_content, metrics, disable_metrics),
115
+ send_message(
116
+ "letta.send_message",
117
+ version,
118
+ environment,
119
+ application_name,
120
+ tracer,
121
+ pricing_info,
122
+ capture_message_content,
123
+ metrics,
124
+ disable_metrics,
125
+ ),
73
126
  )
74
127
 
75
128
  def _uninstrument(self, **kwargs):
@@ -5,17 +5,29 @@ Module for monitoring Letta 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
9
- from openlit.__helpers import (
10
- handle_exception, get_chat_model_cost
8
+ from opentelemetry.sdk.resources import (
9
+ SERVICE_NAME,
10
+ TELEMETRY_SDK_NAME,
11
+ DEPLOYMENT_ENVIRONMENT,
11
12
  )
13
+ from openlit.__helpers import handle_exception, get_chat_model_cost
12
14
  from openlit.semcov import SemanticConvention
13
15
 
14
16
  # Initialize logger for logging potential issues and operations
15
17
  logger = logging.getLogger(__name__)
16
18
 
17
- def create_agent(gen_ai_endpoint, version, environment, application_name,
18
- tracer, pricing_info, capture_message_content, metrics, disable_metrics):
19
+
20
+ def create_agent(
21
+ gen_ai_endpoint,
22
+ version,
23
+ environment,
24
+ application_name,
25
+ tracer,
26
+ pricing_info,
27
+ capture_message_content,
28
+ metrics,
29
+ disable_metrics,
30
+ ):
19
31
  """
20
32
  Generates a telemetry wrapper for chat completions to collect metrics.
21
33
 
@@ -50,34 +62,39 @@ def create_agent(gen_ai_endpoint, version, environment, application_name,
50
62
  """
51
63
 
52
64
  # pylint: disable=line-too-long
53
- with tracer.start_as_current_span(gen_ai_endpoint, kind= SpanKind.CLIENT) as span:
65
+ with tracer.start_as_current_span(
66
+ gen_ai_endpoint, kind=SpanKind.CLIENT
67
+ ) as span:
54
68
  response = wrapped(*args, **kwargs)
55
69
 
56
70
  try:
57
71
  # Set base span attribues
58
72
  span.set_attribute(TELEMETRY_SDK_NAME, "openlit")
59
- span.set_attribute(SemanticConvention.GEN_AI_SYSTEM,
60
- SemanticConvention.GEN_AI_SYSTEM_LETTA)
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)
69
- span.set_attribute(SemanticConvention.GEN_AI_AGENT_ID,
70
- response.id)
71
- span.set_attribute(SemanticConvention.GEN_AI_AGENT_ROLE,
72
- response.name)
73
- span.set_attribute(SemanticConvention.GEN_AI_AGENT_INSTRUCTIONS,
74
- response.system)
75
- span.set_attribute(SemanticConvention.GEN_AI_REQUEST_MODEL,
76
- response.llm_config.model)
77
- span.set_attribute(SemanticConvention.GEN_AI_AGENT_TYPE,
78
- response.agent_type)
79
- span.set_attribute(SemanticConvention.GEN_AI_AGENT_TOOLS,
80
- response.tool_names)
73
+ span.set_attribute(
74
+ SemanticConvention.GEN_AI_SYSTEM,
75
+ SemanticConvention.GEN_AI_SYSTEM_LETTA,
76
+ )
77
+ span.set_attribute(
78
+ SemanticConvention.GEN_AI_OPERATION,
79
+ SemanticConvention.GEN_AI_OPERATION_TYPE_AGENT,
80
+ )
81
+ span.set_attribute(SemanticConvention.GEN_AI_ENDPOINT, gen_ai_endpoint)
82
+ span.set_attribute(SERVICE_NAME, application_name)
83
+ span.set_attribute(DEPLOYMENT_ENVIRONMENT, environment)
84
+ span.set_attribute(SemanticConvention.GEN_AI_AGENT_ID, response.id)
85
+ span.set_attribute(SemanticConvention.GEN_AI_AGENT_ROLE, response.name)
86
+ span.set_attribute(
87
+ SemanticConvention.GEN_AI_AGENT_INSTRUCTIONS, response.system
88
+ )
89
+ span.set_attribute(
90
+ SemanticConvention.GEN_AI_REQUEST_MODEL, response.llm_config.model
91
+ )
92
+ span.set_attribute(
93
+ SemanticConvention.GEN_AI_AGENT_TYPE, response.agent_type
94
+ )
95
+ span.set_attribute(
96
+ SemanticConvention.GEN_AI_AGENT_TOOLS, response.tool_names
97
+ )
81
98
 
82
99
  span.set_status(Status(StatusCode.OK))
83
100
 
@@ -93,8 +110,18 @@ def create_agent(gen_ai_endpoint, version, environment, application_name,
93
110
 
94
111
  return wrapper
95
112
 
96
- def send_message(gen_ai_endpoint, version, environment, application_name,
97
- tracer, pricing_info, capture_message_content, metrics, disable_metrics):
113
+
114
+ def send_message(
115
+ gen_ai_endpoint,
116
+ version,
117
+ environment,
118
+ application_name,
119
+ tracer,
120
+ pricing_info,
121
+ capture_message_content,
122
+ metrics,
123
+ disable_metrics,
124
+ ):
98
125
  """
99
126
  Generates a telemetry wrapper for chat completions to collect metrics.
100
127
 
@@ -129,47 +156,65 @@ def send_message(gen_ai_endpoint, version, environment, application_name,
129
156
  """
130
157
 
131
158
  # pylint: disable=line-too-long
132
- with tracer.start_as_current_span(gen_ai_endpoint, kind= SpanKind.CLIENT) as span:
159
+ with tracer.start_as_current_span(
160
+ gen_ai_endpoint, kind=SpanKind.CLIENT
161
+ ) as span:
133
162
  response = wrapped(*args, **kwargs)
134
163
 
135
164
  try:
136
165
  # Calculate cost of the operation
137
- cost = get_chat_model_cost(kwargs.get("model", "gpt-4o"),
138
- pricing_info, response.usage.prompt_tokens,
139
- response.usage.completion_tokens)
166
+ cost = get_chat_model_cost(
167
+ kwargs.get("model", "gpt-4o"),
168
+ pricing_info,
169
+ response.usage.prompt_tokens,
170
+ response.usage.completion_tokens,
171
+ )
140
172
  # Set base span attribues
141
173
  span.set_attribute(TELEMETRY_SDK_NAME, "openlit")
142
- span.set_attribute(SemanticConvention.GEN_AI_SYSTEM,
143
- SemanticConvention.GEN_AI_SYSTEM_LETTA)
144
- span.set_attribute(SemanticConvention.GEN_AI_OPERATION,
145
- SemanticConvention.GEN_AI_OPERATION_TYPE_AGENT)
146
- span.set_attribute(SemanticConvention.GEN_AI_ENDPOINT,
147
- gen_ai_endpoint)
148
- span.set_attribute(SERVICE_NAME,
149
- application_name)
150
- span.set_attribute(SemanticConvention.GEN_AI_AGENT_STEP_COUNT,
151
- response.usage.step_count)
152
- span.set_attribute(SemanticConvention.GEN_AI_USAGE_INPUT_TOKENS,
153
- response.usage.prompt_tokens)
154
- span.set_attribute(SemanticConvention.GEN_AI_USAGE_OUTPUT_TOKENS,
155
- response.usage.completion_tokens)
156
- span.set_attribute(SemanticConvention.GEN_AI_USAGE_TOTAL_TOKENS,
157
- response.usage.total_tokens)
158
- span.set_attribute(SemanticConvention.GEN_AI_USAGE_COST,
159
- cost)
174
+ span.set_attribute(
175
+ SemanticConvention.GEN_AI_SYSTEM,
176
+ SemanticConvention.GEN_AI_SYSTEM_LETTA,
177
+ )
178
+ span.set_attribute(
179
+ SemanticConvention.GEN_AI_OPERATION,
180
+ SemanticConvention.GEN_AI_OPERATION_TYPE_AGENT,
181
+ )
182
+ span.set_attribute(SemanticConvention.GEN_AI_ENDPOINT, gen_ai_endpoint)
183
+ span.set_attribute(SERVICE_NAME, application_name)
184
+ span.set_attribute(
185
+ SemanticConvention.GEN_AI_AGENT_STEP_COUNT,
186
+ response.usage.step_count,
187
+ )
188
+ span.set_attribute(
189
+ SemanticConvention.GEN_AI_USAGE_INPUT_TOKENS,
190
+ response.usage.prompt_tokens,
191
+ )
192
+ span.set_attribute(
193
+ SemanticConvention.GEN_AI_USAGE_OUTPUT_TOKENS,
194
+ response.usage.completion_tokens,
195
+ )
196
+ span.set_attribute(
197
+ SemanticConvention.GEN_AI_USAGE_TOTAL_TOKENS,
198
+ response.usage.total_tokens,
199
+ )
200
+ span.set_attribute(SemanticConvention.GEN_AI_USAGE_COST, cost)
160
201
 
161
202
  if capture_message_content:
162
203
  span.add_event(
163
204
  name=SemanticConvention.GEN_AI_CONTENT_PROMPT_EVENT,
164
205
  attributes={
165
- SemanticConvention.GEN_AI_CONTENT_PROMPT: kwargs.get("message", ""),
206
+ SemanticConvention.GEN_AI_CONTENT_PROMPT: kwargs.get(
207
+ "message", ""
208
+ ),
166
209
  },
167
210
  )
168
211
  span.add_event(
169
212
  name=SemanticConvention.GEN_AI_CONTENT_COMPLETION_EVENT,
170
213
  # pylint: disable=line-too-long
171
214
  attributes={
172
- SemanticConvention.GEN_AI_CONTENT_COMPLETION: str(response.messages),
215
+ SemanticConvention.GEN_AI_CONTENT_COMPLETION: str(
216
+ response.messages
217
+ ),
173
218
  },
174
219
  )
175
220
 
@@ -5,15 +5,12 @@ import importlib.metadata
5
5
  from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
6
6
  from wrapt import wrap_function_wrapper
7
7
 
8
- from openlit.instrumentation.litellm.litellm import (
9
- completion, embedding
10
- )
11
- from openlit.instrumentation.litellm.async_litellm import (
12
- acompletion, aembedding
13
- )
8
+ from openlit.instrumentation.litellm.litellm import completion, embedding
9
+ from openlit.instrumentation.litellm.async_litellm import acompletion, aembedding
14
10
 
15
11
  _instruments = ("litellm >= 1.52.6",)
16
12
 
13
+
17
14
  class LiteLLMInstrumentor(BaseInstrumentor):
18
15
  """
19
16
  An instrumentor for LiteLLM client library.
@@ -36,32 +33,64 @@ class LiteLLMInstrumentor(BaseInstrumentor):
36
33
  wrap_function_wrapper(
37
34
  "litellm",
38
35
  "completion",
39
- completion(version, environment, application_name,
40
- tracer, pricing_info, capture_message_content, metrics, disable_metrics),
36
+ completion(
37
+ version,
38
+ environment,
39
+ application_name,
40
+ tracer,
41
+ pricing_info,
42
+ capture_message_content,
43
+ metrics,
44
+ disable_metrics,
45
+ ),
41
46
  )
42
47
 
43
48
  # Async chat completions
44
49
  wrap_function_wrapper(
45
50
  "litellm",
46
51
  "acompletion",
47
- acompletion(version, environment, application_name,
48
- tracer, pricing_info, capture_message_content, metrics, disable_metrics),
52
+ acompletion(
53
+ version,
54
+ environment,
55
+ application_name,
56
+ tracer,
57
+ pricing_info,
58
+ capture_message_content,
59
+ metrics,
60
+ disable_metrics,
61
+ ),
49
62
  )
50
63
 
51
64
  # Embeddings
52
65
  wrap_function_wrapper(
53
66
  "litellm",
54
67
  "embedding",
55
- embedding(version, environment, application_name,
56
- tracer, pricing_info, capture_message_content, metrics, disable_metrics),
68
+ embedding(
69
+ version,
70
+ environment,
71
+ application_name,
72
+ tracer,
73
+ pricing_info,
74
+ capture_message_content,
75
+ metrics,
76
+ disable_metrics,
77
+ ),
57
78
  )
58
79
 
59
80
  # Async embeddings
60
81
  wrap_function_wrapper(
61
82
  "litellm",
62
83
  "aembedding",
63
- aembedding(version, environment, application_name,
64
- tracer, pricing_info, capture_message_content, metrics, disable_metrics),
84
+ aembedding(
85
+ version,
86
+ environment,
87
+ application_name,
88
+ tracer,
89
+ pricing_info,
90
+ capture_message_content,
91
+ metrics,
92
+ disable_metrics,
93
+ ),
65
94
  )
66
95
 
67
96
  def _uninstrument(self, **kwargs):