openlit 1.34.13__tar.gz → 1.34.14__tar.gz

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 (146) hide show
  1. {openlit-1.34.13 → openlit-1.34.14}/PKG-INFO +1 -1
  2. {openlit-1.34.13 → openlit-1.34.14}/pyproject.toml +1 -1
  3. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/transformers/__init__.py +12 -5
  4. openlit-1.34.14/src/openlit/instrumentation/transformers/transformers.py +53 -0
  5. openlit-1.34.14/src/openlit/instrumentation/transformers/utils.py +199 -0
  6. openlit-1.34.13/src/openlit/instrumentation/transformers/transformers.py +0 -60
  7. openlit-1.34.13/src/openlit/instrumentation/transformers/utils.py +0 -183
  8. {openlit-1.34.13 → openlit-1.34.14}/LICENSE +0 -0
  9. {openlit-1.34.13 → openlit-1.34.14}/README.md +0 -0
  10. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/__helpers.py +0 -0
  11. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/__init__.py +0 -0
  12. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/evals/__init__.py +0 -0
  13. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/evals/all.py +0 -0
  14. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/evals/bias_detection.py +0 -0
  15. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/evals/hallucination.py +0 -0
  16. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/evals/toxicity.py +0 -0
  17. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/evals/utils.py +0 -0
  18. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/guard/__init__.py +0 -0
  19. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/guard/all.py +0 -0
  20. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/guard/prompt_injection.py +0 -0
  21. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/guard/restrict_topic.py +0 -0
  22. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/guard/sensitive_topic.py +0 -0
  23. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/guard/utils.py +0 -0
  24. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/ag2/__init__.py +0 -0
  25. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/ag2/ag2.py +0 -0
  26. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/ai21/__init__.py +0 -0
  27. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/ai21/ai21.py +0 -0
  28. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/ai21/async_ai21.py +0 -0
  29. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/ai21/utils.py +0 -0
  30. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/anthropic/__init__.py +0 -0
  31. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/anthropic/anthropic.py +0 -0
  32. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/anthropic/async_anthropic.py +0 -0
  33. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/anthropic/utils.py +0 -0
  34. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/assemblyai/__init__.py +0 -0
  35. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/assemblyai/assemblyai.py +0 -0
  36. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/assemblyai/utils.py +0 -0
  37. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/astra/__init__.py +0 -0
  38. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/astra/astra.py +0 -0
  39. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/astra/async_astra.py +0 -0
  40. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/astra/utils.py +0 -0
  41. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/azure_ai_inference/__init__.py +0 -0
  42. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/azure_ai_inference/async_azure_ai_inference.py +0 -0
  43. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/azure_ai_inference/azure_ai_inference.py +0 -0
  44. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/azure_ai_inference/utils.py +0 -0
  45. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/bedrock/__init__.py +0 -0
  46. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/bedrock/bedrock.py +0 -0
  47. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/bedrock/utils.py +0 -0
  48. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/chroma/__init__.py +0 -0
  49. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/chroma/chroma.py +0 -0
  50. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/cohere/__init__.py +0 -0
  51. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/cohere/async_cohere.py +0 -0
  52. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/cohere/cohere.py +0 -0
  53. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/controlflow/__init__.py +0 -0
  54. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/controlflow/controlflow.py +0 -0
  55. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/crawl4ai/__init__.py +0 -0
  56. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/crawl4ai/async_crawl4ai.py +0 -0
  57. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/crawl4ai/crawl4ai.py +0 -0
  58. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/crewai/__init__.py +0 -0
  59. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/crewai/crewai.py +0 -0
  60. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/dynamiq/__init__.py +0 -0
  61. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/dynamiq/dynamiq.py +0 -0
  62. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/elevenlabs/__init__.py +0 -0
  63. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/elevenlabs/async_elevenlabs.py +0 -0
  64. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/elevenlabs/elevenlabs.py +0 -0
  65. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/elevenlabs/utils.py +0 -0
  66. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/embedchain/__init__.py +0 -0
  67. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/embedchain/embedchain.py +0 -0
  68. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/firecrawl/__init__.py +0 -0
  69. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/firecrawl/firecrawl.py +0 -0
  70. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/google_ai_studio/__init__.py +0 -0
  71. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/google_ai_studio/async_google_ai_studio.py +0 -0
  72. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/google_ai_studio/google_ai_studio.py +0 -0
  73. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/google_ai_studio/utils.py +0 -0
  74. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/gpt4all/__init__.py +0 -0
  75. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/gpt4all/gpt4all.py +0 -0
  76. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/gpt4all/utils.py +0 -0
  77. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/gpu/__init__.py +0 -0
  78. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/groq/__init__.py +0 -0
  79. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/groq/async_groq.py +0 -0
  80. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/groq/groq.py +0 -0
  81. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/groq/utils.py +0 -0
  82. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/haystack/__init__.py +0 -0
  83. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/haystack/haystack.py +0 -0
  84. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/julep/__init__.py +0 -0
  85. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/julep/async_julep.py +0 -0
  86. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/julep/julep.py +0 -0
  87. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/langchain/__init__.py +0 -0
  88. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/langchain/async_langchain.py +0 -0
  89. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/langchain/langchain.py +0 -0
  90. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/letta/__init__.py +0 -0
  91. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/letta/letta.py +0 -0
  92. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/litellm/__init__.py +0 -0
  93. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/litellm/async_litellm.py +0 -0
  94. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/litellm/litellm.py +0 -0
  95. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/llamaindex/__init__.py +0 -0
  96. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/llamaindex/llamaindex.py +0 -0
  97. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/mem0/__init__.py +0 -0
  98. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/mem0/mem0.py +0 -0
  99. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/milvus/__init__.py +0 -0
  100. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/milvus/milvus.py +0 -0
  101. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/mistral/__init__.py +0 -0
  102. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/mistral/async_mistral.py +0 -0
  103. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/mistral/mistral.py +0 -0
  104. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/multion/__init__.py +0 -0
  105. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/multion/async_multion.py +0 -0
  106. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/multion/multion.py +0 -0
  107. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/ollama/__init__.py +0 -0
  108. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/ollama/async_ollama.py +0 -0
  109. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/ollama/ollama.py +0 -0
  110. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/ollama/utils.py +0 -0
  111. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/openai/__init__.py +0 -0
  112. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/openai/async_openai.py +0 -0
  113. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/openai/openai.py +0 -0
  114. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/openai_agents/__init__.py +0 -0
  115. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/openai_agents/openai_agents.py +0 -0
  116. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/phidata/__init__.py +0 -0
  117. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/phidata/phidata.py +0 -0
  118. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/pinecone/__init__.py +0 -0
  119. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/pinecone/pinecone.py +0 -0
  120. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/premai/__init__.py +0 -0
  121. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/premai/premai.py +0 -0
  122. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/premai/utils.py +0 -0
  123. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/pydantic_ai/__init__.py +0 -0
  124. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/pydantic_ai/pydantic_ai.py +0 -0
  125. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/pydantic_ai/utils.py +0 -0
  126. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/qdrant/__init__.py +0 -0
  127. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/qdrant/async_qdrant.py +0 -0
  128. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/qdrant/qdrant.py +0 -0
  129. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/reka/__init__.py +0 -0
  130. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/reka/async_reka.py +0 -0
  131. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/reka/reka.py +0 -0
  132. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/reka/utils.py +0 -0
  133. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/together/__init__.py +0 -0
  134. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/together/async_together.py +0 -0
  135. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/together/together.py +0 -0
  136. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/together/utils.py +0 -0
  137. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/vertexai/__init__.py +0 -0
  138. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/vertexai/async_vertexai.py +0 -0
  139. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/vertexai/vertexai.py +0 -0
  140. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/vllm/__init__.py +0 -0
  141. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/vllm/utils.py +0 -0
  142. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/instrumentation/vllm/vllm.py +0 -0
  143. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/otel/events.py +0 -0
  144. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/otel/metrics.py +0 -0
  145. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/otel/tracing.py +0 -0
  146. {openlit-1.34.13 → openlit-1.34.14}/src/openlit/semcov/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: openlit
3
- Version: 1.34.13
3
+ Version: 1.34.14
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
  License: Apache-2.0
6
6
  Keywords: OpenTelemetry,otel,otlp,llm,tracing,openai,anthropic,claude,cohere,llm monitoring,observability,monitoring,gpt,Generative AI,chatGPT,gpu
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "openlit"
3
- version = "1.34.13"
3
+ version = "1.34.14"
4
4
  description = "OpenTelemetry-native Auto instrumentation library for monitoring LLM Applications and GPUs, facilitating the integration of observability into your GenAI-driven projects"
5
5
  authors = ["OpenLIT"]
6
6
  license = "Apache-2.0"
@@ -30,12 +30,19 @@ class TransformersInstrumentor(BaseInstrumentor):
30
30
  version = importlib.metadata.version("transformers")
31
31
 
32
32
  wrap_function_wrapper(
33
- "transformers",
34
- "TextGenerationPipeline.__call__",
35
- pipeline_wrapper(version, environment, application_name,
36
- tracer, pricing_info, capture_message_content, metrics, disable_metrics),
33
+ "transformers",
34
+ "TextGenerationPipeline.__call__",
35
+ pipeline_wrapper(
36
+ version,
37
+ environment,
38
+ application_name,
39
+ tracer,
40
+ pricing_info,
41
+ capture_message_content,
42
+ metrics,
43
+ disable_metrics
44
+ ),
37
45
  )
38
46
 
39
47
  def _uninstrument(self, **kwargs):
40
- # Proper uninstrumentation logic to revert patched methods
41
48
  pass
@@ -0,0 +1,53 @@
1
+ """
2
+ Module for monitoring HF Transformers API calls.
3
+ """
4
+
5
+ import time
6
+ from opentelemetry.trace import SpanKind
7
+ from openlit.__helpers import set_server_address_and_port
8
+ from openlit.instrumentation.transformers.utils import process_chat_response
9
+ from openlit.semcov import SemanticConvention
10
+
11
+
12
+ def pipeline_wrapper(version, environment, application_name, tracer, pricing_info,
13
+ capture_message_content, metrics, disable_metrics):
14
+ """
15
+ Generates a telemetry wrapper for GenAI function call
16
+ """
17
+
18
+ def wrapper(wrapped, instance, args, kwargs):
19
+ """
20
+ Wraps the GenAI function call.
21
+ """
22
+
23
+ server_address, server_port = set_server_address_and_port(instance, "127.0.0.1", 80)
24
+ request_model = instance.model.config.name_or_path
25
+
26
+ span_name = f"{SemanticConvention.GEN_AI_OPERATION_TYPE_CHAT} {request_model}"
27
+
28
+ with tracer.start_as_current_span(span_name, kind=SpanKind.CLIENT) as span:
29
+ start_time = time.time()
30
+ response = wrapped(*args, **kwargs)
31
+
32
+ response = process_chat_response(
33
+ instance=instance,
34
+ response=response,
35
+ request_model=request_model,
36
+ pricing_info=pricing_info,
37
+ server_port=server_port,
38
+ server_address=server_address,
39
+ environment=environment,
40
+ application_name=application_name,
41
+ metrics=metrics,
42
+ start_time=start_time,
43
+ span=span,
44
+ args=args,
45
+ kwargs=kwargs,
46
+ capture_message_content=capture_message_content,
47
+ disable_metrics=disable_metrics,
48
+ version=version,
49
+ )
50
+
51
+ return response
52
+
53
+ return wrapper
@@ -0,0 +1,199 @@
1
+ """
2
+ HF Transformers OpenTelemetry instrumentation utility functions
3
+ """
4
+ import time
5
+
6
+ from opentelemetry.trace import Status, StatusCode
7
+
8
+ from openlit.__helpers import (
9
+ general_tokens,
10
+ get_chat_model_cost,
11
+ common_span_attributes,
12
+ record_completion_metrics,
13
+ )
14
+ from openlit.semcov import SemanticConvention
15
+
16
+ def format_content(content):
17
+ """
18
+ Format content to a consistent structure.
19
+ """
20
+ if isinstance(content, str):
21
+ return content
22
+ elif isinstance(content, list):
23
+ # Check if its a list of chat messages (like in the test case)
24
+ if (len(content) > 0 and isinstance(content[0], dict) and
25
+ "role" in content[0] and "content" in content[0]):
26
+ # Handle chat message format like Groq
27
+ formatted_messages = []
28
+ for message in content:
29
+ role = message["role"]
30
+ msg_content = message["content"]
31
+
32
+ if isinstance(msg_content, list):
33
+ content_str = ", ".join(
34
+ f'{item["type"]}: {item["text"] if "text" in item else item.get("image_url", str(item))}'
35
+ if isinstance(item, dict) and "type" in item
36
+ else str(item)
37
+ for item in msg_content
38
+ )
39
+ formatted_messages.append(f"{role}: {content_str}")
40
+ else:
41
+ formatted_messages.append(f"{role}: {msg_content}")
42
+ return "\n".join(formatted_messages)
43
+ else:
44
+ # Handle other list formats (transformers responses)
45
+ formatted_content = []
46
+ for item in content:
47
+ if isinstance(item, str):
48
+ formatted_content.append(item)
49
+ elif isinstance(item, dict):
50
+ # Handle dict format for transformers
51
+ if "generated_text" in item:
52
+ formatted_content.append(str(item["generated_text"]))
53
+ else:
54
+ formatted_content.append(str(item))
55
+ else:
56
+ formatted_content.append(str(item))
57
+ return " ".join(formatted_content)
58
+ else:
59
+ return str(content)
60
+
61
+ def common_chat_logic(scope, pricing_info, environment, application_name, metrics,
62
+ capture_message_content, disable_metrics, version, args, kwargs, is_stream):
63
+
64
+ """
65
+ Process chat request and generate Telemetry
66
+ """
67
+
68
+ scope._end_time = time.time()
69
+ forward_params = scope._instance._forward_params
70
+ request_model = scope._instance.model.config.name_or_path
71
+
72
+ input_tokens = general_tokens(scope._prompt)
73
+ output_tokens = general_tokens(scope._completion)
74
+
75
+ cost = get_chat_model_cost(request_model, pricing_info, input_tokens, output_tokens)
76
+
77
+ # Common Span Attributes
78
+ common_span_attributes(scope,
79
+ SemanticConvention.GEN_AI_OPERATION_TYPE_CHAT, SemanticConvention.GEN_AI_SYSTEM_HUGGING_FACE,
80
+ scope._server_address, scope._server_port, request_model, request_model,
81
+ environment, application_name, is_stream, scope._tbt, scope._ttft, version)
82
+
83
+ # Set request parameters from forward_params
84
+ if forward_params.get("temperature") is not None:
85
+ scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_TEMPERATURE, forward_params["temperature"])
86
+ if forward_params.get("top_k") is not None:
87
+ scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_TOP_K, forward_params["top_k"])
88
+ if forward_params.get("top_p") is not None:
89
+ scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_TOP_P, forward_params["top_p"])
90
+ if forward_params.get("max_length") is not None:
91
+ scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_MAX_TOKENS, forward_params["max_length"])
92
+
93
+ # Set token usage and cost attributes
94
+ scope._span.set_attribute(SemanticConvention.GEN_AI_USAGE_INPUT_TOKENS, input_tokens)
95
+ scope._span.set_attribute(SemanticConvention.GEN_AI_USAGE_OUTPUT_TOKENS, output_tokens)
96
+ scope._span.set_attribute(SemanticConvention.GEN_AI_CLIENT_TOKEN_USAGE, input_tokens + output_tokens)
97
+ scope._span.set_attribute(SemanticConvention.GEN_AI_USAGE_COST, cost)
98
+
99
+ # Span Attributes for Content
100
+ if capture_message_content:
101
+ scope._span.set_attribute(SemanticConvention.GEN_AI_CONTENT_PROMPT, scope._prompt)
102
+ scope._span.set_attribute(SemanticConvention.GEN_AI_CONTENT_COMPLETION, scope._completion)
103
+
104
+ # To be removed once the change to span_attributes (from span events) is complete
105
+ scope._span.add_event(
106
+ name=SemanticConvention.GEN_AI_CONTENT_PROMPT_EVENT,
107
+ attributes={
108
+ SemanticConvention.GEN_AI_CONTENT_PROMPT: scope._prompt,
109
+ },
110
+ )
111
+ scope._span.add_event(
112
+ name=SemanticConvention.GEN_AI_CONTENT_COMPLETION_EVENT,
113
+ attributes={
114
+ SemanticConvention.GEN_AI_CONTENT_COMPLETION: scope._completion,
115
+ },
116
+ )
117
+
118
+ scope._span.set_status(Status(StatusCode.OK))
119
+
120
+ # Record metrics using the standardized helper function
121
+ if not disable_metrics:
122
+ record_completion_metrics(metrics, SemanticConvention.GEN_AI_OPERATION_TYPE_CHAT,
123
+ SemanticConvention.GEN_AI_SYSTEM_HUGGING_FACE, scope._server_address, scope._server_port,
124
+ request_model, request_model, environment, application_name, scope._start_time, scope._end_time,
125
+ cost, input_tokens, output_tokens, scope._tbt, scope._ttft)
126
+
127
+ def process_chat_response(instance, response, request_model, pricing_info, server_port, server_address,
128
+ environment, application_name, metrics, start_time,
129
+ span, args, kwargs, capture_message_content=False, disable_metrics=False, version="1.0.0"):
130
+ """
131
+ Process chat request and generate Telemetry
132
+ """
133
+
134
+ scope = type("GenericScope", (), {})()
135
+ scope._instance = instance
136
+ scope._start_time = start_time
137
+ scope._end_time = time.time()
138
+ scope._span = span
139
+ scope._server_address = server_address
140
+ scope._server_port = server_port
141
+ scope._kwargs = kwargs
142
+ scope._args = args
143
+
144
+ # Extract prompt from args or kwargs
145
+ if args and len(args) > 0:
146
+ scope._prompt = args[0]
147
+ else:
148
+ scope._prompt = (
149
+ kwargs.get("text_inputs") or
150
+ (kwargs.get("image") and kwargs.get("question") and
151
+ ("image: " + kwargs.get("image") + " question:" + kwargs.get("question"))) or
152
+ kwargs.get("fallback") or
153
+ ""
154
+ )
155
+ scope._prompt = format_content(scope._prompt)
156
+
157
+ # Process response based on task type
158
+ task = kwargs.get("task", "text-generation")
159
+
160
+ if task == "text-generation":
161
+ # Handle text generation responses
162
+ if isinstance(response, list) and len(response) > 0:
163
+ first_entry = response[0]
164
+ if isinstance(first_entry, dict):
165
+ if isinstance(first_entry.get("generated_text"), list):
166
+ # Handle nested list format
167
+ last_element = first_entry.get("generated_text")[-1]
168
+ scope._completion = last_element.get("content", str(last_element))
169
+ else:
170
+ # Handle standard format
171
+ scope._completion = first_entry.get("generated_text", "")
172
+ else:
173
+ scope._completion = str(first_entry)
174
+ else:
175
+ scope._completion = ""
176
+
177
+ elif task == "automatic-speech-recognition":
178
+ scope._completion = response.get("text", "") if isinstance(response, dict) else ""
179
+
180
+ elif task == "image-classification":
181
+ scope._completion = str(response[0]) if isinstance(response, list) and len(response) > 0 else ""
182
+
183
+ elif task == "visual-question-answering":
184
+ if isinstance(response, list) and len(response) > 0 and isinstance(response[0], dict):
185
+ scope._completion = response[0].get("answer", "")
186
+ else:
187
+ scope._completion = ""
188
+ else:
189
+ # Default handling for other tasks
190
+ scope._completion = format_content(response)
191
+
192
+ # Initialize timing attributes
193
+ scope._tbt = 0
194
+ scope._ttft = scope._end_time - scope._start_time
195
+
196
+ common_chat_logic(scope, pricing_info, environment, application_name, metrics,
197
+ capture_message_content, disable_metrics, version, args, kwargs, is_stream=False)
198
+
199
+ return response
@@ -1,60 +0,0 @@
1
- """
2
- Module for monitoring HF Transformers API calls.
3
- """
4
-
5
- import logging
6
- import time
7
- from opentelemetry.trace import SpanKind
8
- from openlit.__helpers import (
9
- set_server_address_and_port
10
- )
11
- from openlit.instrumentation.transformers.utils import (
12
- process_chat_response,
13
- )
14
- from openlit.semcov import SemanticConvention
15
-
16
- # Initialize logger for logging potential issues and operations
17
- logger = logging.getLogger(__name__)
18
-
19
- def pipeline_wrapper(version, environment, application_name,
20
- tracer, pricing_info, capture_message_content, metrics, disable_metrics):
21
- """
22
- Generates a telemetry wrapper for GenAI function call
23
- """
24
-
25
- def wrapper(wrapped, instance, args, kwargs):
26
- """
27
- Wraps the GenAI function call.
28
- """
29
-
30
- server_address, server_port = set_server_address_and_port(instance, "127.0.0.1", 80)
31
- request_model = instance.model.config.name_or_path
32
-
33
- span_name = f"{SemanticConvention.GEN_AI_OPERATION_TYPE_CHAT} {request_model}"
34
-
35
- with tracer.start_as_current_span(span_name, kind= SpanKind.CLIENT) as span:
36
- start_time = time.time()
37
- response = wrapped(*args, **kwargs)
38
-
39
- response = process_chat_response(
40
- instance = instance,
41
- response=response,
42
- request_model=request_model,
43
- pricing_info=pricing_info,
44
- server_port=server_port,
45
- server_address=server_address,
46
- environment=environment,
47
- application_name=application_name,
48
- metrics=metrics,
49
- start_time=start_time,
50
- span=span,
51
- args=args,
52
- kwargs=kwargs,
53
- capture_message_content=capture_message_content,
54
- disable_metrics=disable_metrics,
55
- version=version,
56
- )
57
-
58
- return response
59
-
60
- return wrapper
@@ -1,183 +0,0 @@
1
- """
2
- HF Transformers OpenTelemetry instrumentation utility functions
3
- """
4
- import time
5
-
6
- from opentelemetry.sdk.resources import SERVICE_NAME, TELEMETRY_SDK_NAME, DEPLOYMENT_ENVIRONMENT
7
- from opentelemetry.trace import Status, StatusCode
8
-
9
- from openlit.__helpers import (
10
- response_as_dict,
11
- calculate_tbt,
12
- general_tokens,
13
- get_chat_model_cost,
14
- create_metrics_attributes,
15
- format_and_concatenate
16
- )
17
- from openlit.semcov import SemanticConvention
18
-
19
- def common_chat_logic(scope, pricing_info, environment, application_name, metrics,
20
- capture_message_content, disable_metrics, version, args, kwargs, is_stream):
21
-
22
- """
23
- Process chat request and generate Telemetry
24
- """
25
-
26
- scope._end_time = time.time()
27
- if len(scope._timestamps) > 1:
28
- scope._tbt = calculate_tbt(scope._timestamps)
29
-
30
- forward_params = scope._instance._forward_params
31
- request_model = scope._instance.model.config.name_or_path
32
-
33
- input_tokens = general_tokens(scope._prompt)
34
- output_tokens = general_tokens(scope._llmresponse)
35
-
36
- cost = get_chat_model_cost(request_model, pricing_info, input_tokens, output_tokens)
37
-
38
- # Set Span attributes (OTel Semconv)
39
- scope._span.set_attribute(TELEMETRY_SDK_NAME, "openlit")
40
- scope._span.set_attribute(SemanticConvention.GEN_AI_OPERATION, SemanticConvention.GEN_AI_OPERATION_TYPE_CHAT)
41
- scope._span.set_attribute(SemanticConvention.GEN_AI_SYSTEM, SemanticConvention.GEN_AI_SYSTEM_HUGGING_FACE)
42
- scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_MODEL, request_model)
43
- scope._span.set_attribute(SemanticConvention.SERVER_PORT, scope._server_port)
44
-
45
- # List of attributes and their config keys
46
- attributes = [
47
- (SemanticConvention.GEN_AI_REQUEST_TEMPERATURE, "temperature"),
48
- (SemanticConvention.GEN_AI_REQUEST_TOP_K, "top_k"),
49
- (SemanticConvention.GEN_AI_REQUEST_TOP_P, "top_p"),
50
- (SemanticConvention.GEN_AI_REQUEST_MAX_TOKENS, "max_length"),
51
- ]
52
-
53
- # Set each attribute if the corresponding value exists and is not None
54
- for attribute, key in attributes:
55
- value = forward_params.get(key)
56
- if value is not None:
57
- scope._span.set_attribute(attribute, value)
58
-
59
- scope._span.set_attribute(SemanticConvention.GEN_AI_RESPONSE_MODEL, request_model)
60
- scope._span.set_attribute(SemanticConvention.GEN_AI_USAGE_INPUT_TOKENS, input_tokens)
61
- scope._span.set_attribute(SemanticConvention.GEN_AI_USAGE_OUTPUT_TOKENS, output_tokens)
62
- scope._span.set_attribute(SemanticConvention.SERVER_ADDRESS, scope._server_address)
63
- scope._span.set_attribute(DEPLOYMENT_ENVIRONMENT, environment)
64
- scope._span.set_attribute(SERVICE_NAME, application_name)
65
- scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_IS_STREAM, is_stream)
66
- scope._span.set_attribute(SemanticConvention.GEN_AI_CLIENT_TOKEN_USAGE, input_tokens + output_tokens)
67
- scope._span.set_attribute(SemanticConvention.GEN_AI_USAGE_COST, cost)
68
- scope._span.set_attribute(SemanticConvention.GEN_AI_SERVER_TBT, scope._tbt)
69
- scope._span.set_attribute(SemanticConvention.GEN_AI_SERVER_TTFT, scope._ttft)
70
- scope._span.set_attribute(SemanticConvention.GEN_AI_SDK_VERSION, version)
71
-
72
- # To be removed one the change to span_attributes (from span events) is complete
73
- if capture_message_content:
74
- scope._span.set_attribute(SemanticConvention.GEN_AI_CONTENT_PROMPT, scope._prompt)
75
- scope._span.set_attribute(SemanticConvention.GEN_AI_CONTENT_COMPLETION, scope._llmresponse)
76
-
77
- scope._span.add_event(
78
- name=SemanticConvention.GEN_AI_CONTENT_PROMPT_EVENT,
79
- attributes={
80
- SemanticConvention.GEN_AI_CONTENT_PROMPT: scope._prompt,
81
- },
82
- )
83
- scope._span.add_event(
84
- name=SemanticConvention.GEN_AI_CONTENT_COMPLETION_EVENT,
85
- attributes={
86
- SemanticConvention.GEN_AI_CONTENT_COMPLETION: scope._llmresponse,
87
- },
88
- )
89
-
90
- scope._span.set_status(Status(StatusCode.OK))
91
-
92
- if not disable_metrics:
93
- metrics_attributes = create_metrics_attributes(
94
- service_name=application_name,
95
- deployment_environment=environment,
96
- operation=SemanticConvention.GEN_AI_OPERATION_TYPE_CHAT,
97
- system=SemanticConvention.GEN_AI_SYSTEM_HUGGING_FACE,
98
- request_model=request_model,
99
- server_address=scope._server_address,
100
- server_port=scope._server_port,
101
- response_model=request_model,
102
- )
103
-
104
- metrics["genai_client_usage_tokens"].record(input_tokens + output_tokens, metrics_attributes)
105
- metrics["genai_client_operation_duration"].record(scope._end_time - scope._start_time, metrics_attributes)
106
- metrics["genai_server_tbt"].record(scope._tbt, metrics_attributes)
107
- metrics["genai_server_ttft"].record(scope._ttft, metrics_attributes)
108
- metrics["genai_requests"].add(1, metrics_attributes)
109
- metrics["genai_completion_tokens"].add(output_tokens, metrics_attributes)
110
- metrics["genai_prompt_tokens"].add(input_tokens, metrics_attributes)
111
- metrics["genai_cost"].record(cost, metrics_attributes)
112
-
113
- def process_chat_response(instance, response, request_model, pricing_info, server_port, server_address,
114
- environment, application_name, metrics, start_time,
115
- span, args, kwargs, capture_message_content=False, disable_metrics=False, version="1.0.0"):
116
- """
117
- Process chat request and generate Telemetry
118
- """
119
-
120
- self = type("GenericScope", (), {})()
121
- response_dict = response_as_dict(response)
122
-
123
- # pylint: disable = no-member
124
- self._instance = instance
125
- self._start_time = start_time
126
- self._end_time = time.time()
127
- self._span = span
128
- self._timestamps = []
129
- self._ttft, self._tbt = self._end_time - self._start_time, 0
130
- self._server_address, self._server_port = server_address, server_port
131
- self._kwargs = kwargs
132
- self._args = args
133
-
134
- if self._args and len(self._args) > 0:
135
- self._prompt = args[0]
136
- else:
137
- self._prompt = (
138
- kwargs.get("text_inputs") or
139
- (kwargs.get("image") and kwargs.get("question") and
140
- ("image: " + kwargs.get("image") + " question:" + kwargs.get("question"))) or
141
- kwargs.get("fallback") or
142
- ""
143
- )
144
- self._prompt = format_and_concatenate(self._prompt)
145
-
146
- self._llmresponse = []
147
- if self._kwargs.get("task", "text-generation") == "text-generation":
148
- first_entry = response_dict[0]
149
-
150
- if isinstance(first_entry, dict) and isinstance(first_entry.get("generated_text"), list):
151
- last_element = first_entry.get("generated_text")[-1]
152
- self._llmresponse = last_element.get("content", last_element)
153
- else:
154
- def extract_text(entry):
155
- if isinstance(entry, dict):
156
- return entry.get("generated_text")
157
- if isinstance(entry, list):
158
- return " ".join(
159
- extract_text(sub_entry) for sub_entry in entry if isinstance(sub_entry, dict)
160
- )
161
- return ""
162
-
163
- # Process and collect all generated texts
164
- self._llmresponse = [
165
- extract_text(entry) for entry in response_dict
166
- ]
167
-
168
- # Join all non-empty responses into a single string
169
- self._llmresponse = " ".join(filter(None, self._llmresponse))
170
-
171
- elif self._kwargs.get("task", "text-generation") == "automatic-speech-recognition":
172
- self._llmresponse = response_dict.get("text", "")
173
-
174
- elif self._kwargs.get("task", "text-generation") == "image-classification":
175
- self._llmresponse = str(response_dict[0])
176
-
177
- elif self._kwargs.get("task", "text-generation") == "visual-question-answering":
178
- self._llmresponse = str(response_dict[0]).get("answer")
179
-
180
- common_chat_logic(self, pricing_info, environment, application_name, metrics,
181
- capture_message_content, disable_metrics, version, args, kwargs, is_stream=False)
182
-
183
- return response
File without changes
File without changes