openlit 1.34.11__tar.gz → 1.34.13__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.11 → openlit-1.34.13}/PKG-INFO +1 -1
  2. {openlit-1.34.11 → openlit-1.34.13}/pyproject.toml +1 -1
  3. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/__helpers.py +3 -3
  4. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/ai21/__init__.py +10 -8
  5. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/ai21/ai21.py +15 -27
  6. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/ai21/async_ai21.py +15 -27
  7. openlit-1.34.13/src/openlit/instrumentation/ai21/utils.py +317 -0
  8. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/openai/__init__.py +3 -3
  9. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/vllm/__init__.py +5 -7
  10. openlit-1.34.13/src/openlit/instrumentation/vllm/utils.py +143 -0
  11. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/vllm/vllm.py +3 -8
  12. openlit-1.34.11/src/openlit/instrumentation/ai21/utils.py +0 -300
  13. openlit-1.34.11/src/openlit/instrumentation/vllm/utils.py +0 -161
  14. {openlit-1.34.11 → openlit-1.34.13}/LICENSE +0 -0
  15. {openlit-1.34.11 → openlit-1.34.13}/README.md +0 -0
  16. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/__init__.py +0 -0
  17. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/evals/__init__.py +0 -0
  18. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/evals/all.py +0 -0
  19. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/evals/bias_detection.py +0 -0
  20. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/evals/hallucination.py +0 -0
  21. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/evals/toxicity.py +0 -0
  22. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/evals/utils.py +0 -0
  23. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/guard/__init__.py +0 -0
  24. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/guard/all.py +0 -0
  25. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/guard/prompt_injection.py +0 -0
  26. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/guard/restrict_topic.py +0 -0
  27. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/guard/sensitive_topic.py +0 -0
  28. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/guard/utils.py +0 -0
  29. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/ag2/__init__.py +0 -0
  30. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/ag2/ag2.py +0 -0
  31. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/anthropic/__init__.py +0 -0
  32. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/anthropic/anthropic.py +0 -0
  33. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/anthropic/async_anthropic.py +0 -0
  34. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/anthropic/utils.py +0 -0
  35. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/assemblyai/__init__.py +0 -0
  36. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/assemblyai/assemblyai.py +0 -0
  37. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/assemblyai/utils.py +0 -0
  38. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/astra/__init__.py +0 -0
  39. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/astra/astra.py +0 -0
  40. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/astra/async_astra.py +0 -0
  41. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/astra/utils.py +0 -0
  42. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/azure_ai_inference/__init__.py +0 -0
  43. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/azure_ai_inference/async_azure_ai_inference.py +0 -0
  44. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/azure_ai_inference/azure_ai_inference.py +0 -0
  45. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/azure_ai_inference/utils.py +0 -0
  46. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/bedrock/__init__.py +0 -0
  47. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/bedrock/bedrock.py +0 -0
  48. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/bedrock/utils.py +0 -0
  49. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/chroma/__init__.py +0 -0
  50. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/chroma/chroma.py +0 -0
  51. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/cohere/__init__.py +0 -0
  52. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/cohere/async_cohere.py +0 -0
  53. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/cohere/cohere.py +0 -0
  54. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/controlflow/__init__.py +0 -0
  55. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/controlflow/controlflow.py +0 -0
  56. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/crawl4ai/__init__.py +0 -0
  57. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/crawl4ai/async_crawl4ai.py +0 -0
  58. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/crawl4ai/crawl4ai.py +0 -0
  59. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/crewai/__init__.py +0 -0
  60. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/crewai/crewai.py +0 -0
  61. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/dynamiq/__init__.py +0 -0
  62. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/dynamiq/dynamiq.py +0 -0
  63. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/elevenlabs/__init__.py +0 -0
  64. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/elevenlabs/async_elevenlabs.py +0 -0
  65. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/elevenlabs/elevenlabs.py +0 -0
  66. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/elevenlabs/utils.py +0 -0
  67. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/embedchain/__init__.py +0 -0
  68. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/embedchain/embedchain.py +0 -0
  69. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/firecrawl/__init__.py +0 -0
  70. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/firecrawl/firecrawl.py +0 -0
  71. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/google_ai_studio/__init__.py +0 -0
  72. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/google_ai_studio/async_google_ai_studio.py +0 -0
  73. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/google_ai_studio/google_ai_studio.py +0 -0
  74. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/google_ai_studio/utils.py +0 -0
  75. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/gpt4all/__init__.py +0 -0
  76. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/gpt4all/gpt4all.py +0 -0
  77. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/gpt4all/utils.py +0 -0
  78. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/gpu/__init__.py +0 -0
  79. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/groq/__init__.py +0 -0
  80. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/groq/async_groq.py +0 -0
  81. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/groq/groq.py +0 -0
  82. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/groq/utils.py +0 -0
  83. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/haystack/__init__.py +0 -0
  84. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/haystack/haystack.py +0 -0
  85. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/julep/__init__.py +0 -0
  86. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/julep/async_julep.py +0 -0
  87. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/julep/julep.py +0 -0
  88. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/langchain/__init__.py +0 -0
  89. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/langchain/async_langchain.py +0 -0
  90. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/langchain/langchain.py +0 -0
  91. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/letta/__init__.py +0 -0
  92. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/letta/letta.py +0 -0
  93. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/litellm/__init__.py +0 -0
  94. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/litellm/async_litellm.py +0 -0
  95. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/litellm/litellm.py +0 -0
  96. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/llamaindex/__init__.py +0 -0
  97. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/llamaindex/llamaindex.py +0 -0
  98. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/mem0/__init__.py +0 -0
  99. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/mem0/mem0.py +0 -0
  100. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/milvus/__init__.py +0 -0
  101. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/milvus/milvus.py +0 -0
  102. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/mistral/__init__.py +0 -0
  103. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/mistral/async_mistral.py +0 -0
  104. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/mistral/mistral.py +0 -0
  105. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/multion/__init__.py +0 -0
  106. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/multion/async_multion.py +0 -0
  107. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/multion/multion.py +0 -0
  108. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/ollama/__init__.py +0 -0
  109. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/ollama/async_ollama.py +0 -0
  110. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/ollama/ollama.py +0 -0
  111. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/ollama/utils.py +0 -0
  112. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/openai/async_openai.py +0 -0
  113. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/openai/openai.py +0 -0
  114. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/openai_agents/__init__.py +0 -0
  115. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/openai_agents/openai_agents.py +0 -0
  116. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/phidata/__init__.py +0 -0
  117. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/phidata/phidata.py +0 -0
  118. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/pinecone/__init__.py +0 -0
  119. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/pinecone/pinecone.py +0 -0
  120. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/premai/__init__.py +0 -0
  121. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/premai/premai.py +0 -0
  122. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/premai/utils.py +0 -0
  123. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/pydantic_ai/__init__.py +0 -0
  124. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/pydantic_ai/pydantic_ai.py +0 -0
  125. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/pydantic_ai/utils.py +0 -0
  126. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/qdrant/__init__.py +0 -0
  127. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/qdrant/async_qdrant.py +0 -0
  128. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/qdrant/qdrant.py +0 -0
  129. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/reka/__init__.py +0 -0
  130. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/reka/async_reka.py +0 -0
  131. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/reka/reka.py +0 -0
  132. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/reka/utils.py +0 -0
  133. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/together/__init__.py +0 -0
  134. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/together/async_together.py +0 -0
  135. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/together/together.py +0 -0
  136. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/together/utils.py +0 -0
  137. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/transformers/__init__.py +0 -0
  138. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/transformers/transformers.py +0 -0
  139. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/transformers/utils.py +0 -0
  140. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/vertexai/__init__.py +0 -0
  141. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/vertexai/async_vertexai.py +0 -0
  142. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/instrumentation/vertexai/vertexai.py +0 -0
  143. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/otel/events.py +0 -0
  144. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/otel/metrics.py +0 -0
  145. {openlit-1.34.11 → openlit-1.34.13}/src/openlit/otel/tracing.py +0 -0
  146. {openlit-1.34.11 → openlit-1.34.13}/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.11
3
+ Version: 1.34.13
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.11"
3
+ version = "1.34.13"
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"
@@ -346,12 +346,12 @@ def common_span_attributes(scope, gen_ai_operation, gen_ai_system, server_addres
346
346
  scope._span.set_attribute(SemanticConvention.SERVER_ADDRESS, server_address)
347
347
  scope._span.set_attribute(SemanticConvention.SERVER_PORT, server_port)
348
348
  scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_MODEL, request_model)
349
- scope._span.set_attribute(SemanticConvention.GEN_AI_RESPONSE_MODEL, scope._response_model)
349
+ scope._span.set_attribute(SemanticConvention.GEN_AI_RESPONSE_MODEL, response_model)
350
350
  scope._span.set_attribute(DEPLOYMENT_ENVIRONMENT, environment)
351
351
  scope._span.set_attribute(SERVICE_NAME, application_name)
352
352
  scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_IS_STREAM, is_stream)
353
- scope._span.set_attribute(SemanticConvention.GEN_AI_SERVER_TBT, scope._tbt)
354
- scope._span.set_attribute(SemanticConvention.GEN_AI_SERVER_TTFT, scope._ttft)
353
+ scope._span.set_attribute(SemanticConvention.GEN_AI_SERVER_TBT, tbt)
354
+ scope._span.set_attribute(SemanticConvention.GEN_AI_SERVER_TTFT, ttft)
355
355
  scope._span.set_attribute(SemanticConvention.GEN_AI_SDK_VERSION, version)
356
356
 
357
357
  def record_completion_metrics(metrics, gen_ai_operation, gen_ai_system, server_address, server_port,
@@ -1,4 +1,3 @@
1
- # pylint: disable=useless-return, bad-staticmethod-argument, disable=duplicate-code
2
1
  """Initializer of Auto Instrumentation of AI21 Functions"""
3
2
 
4
3
  from typing import Collection
@@ -33,34 +32,37 @@ class AI21Instrumentor(BaseInstrumentor):
33
32
  disable_metrics = kwargs.get("disable_metrics")
34
33
  version = importlib.metadata.version("ai21")
35
34
 
36
- #sync
35
+ # Chat completions
37
36
  wrap_function_wrapper(
38
37
  "ai21.clients.studio.resources.chat.chat_completions",
39
38
  "ChatCompletions.create",
40
39
  chat(version, environment, application_name,
41
- tracer, pricing_info, capture_message_content, metrics, disable_metrics),
40
+ tracer, pricing_info, capture_message_content, metrics, disable_metrics),
42
41
  )
42
+
43
+ # RAG completions
43
44
  wrap_function_wrapper(
44
45
  "ai21.clients.studio.resources.studio_conversational_rag",
45
46
  "StudioConversationalRag.create",
46
47
  chat_rag(version, environment, application_name,
47
- tracer, pricing_info, capture_message_content, metrics, disable_metrics),
48
+ tracer, pricing_info, capture_message_content, metrics, disable_metrics),
48
49
  )
49
50
 
50
- #Async
51
+ # Async chat completions
51
52
  wrap_function_wrapper(
52
53
  "ai21.clients.studio.resources.chat.async_chat_completions",
53
54
  "AsyncChatCompletions.create",
54
55
  async_chat(version, environment, application_name,
55
- tracer, pricing_info, capture_message_content, metrics, disable_metrics),
56
+ tracer, pricing_info, capture_message_content, metrics, disable_metrics),
56
57
  )
58
+
59
+ # Async RAG completions
57
60
  wrap_function_wrapper(
58
61
  "ai21.clients.studio.resources.studio_conversational_rag",
59
62
  "AsyncStudioConversationalRag.create",
60
63
  async_chat_rag(version, environment, application_name,
61
- tracer, pricing_info, capture_message_content, metrics, disable_metrics),
64
+ tracer, pricing_info, capture_message_content, metrics, disable_metrics),
62
65
  )
63
66
 
64
67
  def _uninstrument(self, **kwargs):
65
- # Proper uninstrumentation logic to revert patched methods
66
68
  pass
@@ -1,8 +1,7 @@
1
1
  """
2
- Module for monitoring AI21 calls.
2
+ Module for monitoring AI21 API calls.
3
3
  """
4
4
 
5
- import logging
6
5
  import time
7
6
  from opentelemetry.trace import SpanKind
8
7
  from openlit.__helpers import (
@@ -15,14 +14,10 @@ from openlit.instrumentation.ai21.utils import (
15
14
  process_streaming_chat_response,
16
15
  process_chat_rag_response
17
16
  )
18
-
19
17
  from openlit.semcov import SemanticConvention
20
18
 
21
- # Initialize logger for logging potential issues and operations
22
- logger = logging.getLogger(__name__)
23
-
24
- def chat(version, environment, application_name,
25
- tracer, pricing_info, capture_message_content, metrics, disable_metrics):
19
+ def chat(version, environment, application_name, tracer, pricing_info,
20
+ capture_message_content, metrics, disable_metrics):
26
21
  """
27
22
  Generates a telemetry wrapper for GenAI function call
28
23
  """
@@ -45,14 +40,12 @@ def chat(version, environment, application_name,
45
40
  self.__wrapped__ = wrapped
46
41
  self._span = span
47
42
  self._span_name = span_name
48
- # Placeholder for aggregating streaming response
49
43
  self._llmresponse = ""
50
44
  self._response_id = ""
51
45
  self._finish_reason = ""
46
+ self._tools = None
52
47
  self._input_tokens = 0
53
48
  self._output_tokens = 0
54
- self._choices = []
55
-
56
49
  self._args = args
57
50
  self._kwargs = kwargs
58
51
  self._start_time = time.time()
@@ -83,9 +76,8 @@ def chat(version, environment, application_name,
83
76
  process_chunk(self, chunk)
84
77
  return chunk
85
78
  except StopIteration:
86
- # Handling exception ensure observability without disrupting operation
87
79
  try:
88
- with tracer.start_as_current_span(self._span_name, kind= SpanKind.CLIENT) as self._span:
80
+ with tracer.start_as_current_span(self._span_name, kind=SpanKind.CLIENT) as self._span:
89
81
  process_streaming_chat_response(
90
82
  self,
91
83
  pricing_info=pricing_info,
@@ -96,34 +88,31 @@ def chat(version, environment, application_name,
96
88
  disable_metrics=disable_metrics,
97
89
  version=version
98
90
  )
91
+
99
92
  except Exception as e:
100
93
  handle_exception(self._span, e)
101
- logger.error("Error in trace creation: %s", e)
94
+
102
95
  raise
103
96
 
104
97
  def wrapper(wrapped, instance, args, kwargs):
105
98
  """
106
99
  Wraps the GenAI function call.
107
100
  """
108
-
109
101
  # Check if streaming is enabled for the API call
110
102
  streaming = kwargs.get("stream", False)
111
-
112
103
  server_address, server_port = set_server_address_and_port(instance, "api.ai21.com", 443)
113
104
  request_model = kwargs.get("model", "jamba-1.5-mini")
114
105
 
115
106
  span_name = f"{SemanticConvention.GEN_AI_OPERATION_TYPE_CHAT} {request_model}"
116
107
 
117
- # pylint: disable=no-else-return
118
108
  if streaming:
119
- # Special handling for streaming response to accommodate the nature of data flow
109
+ # Special handling for streaming response
120
110
  awaited_wrapped = wrapped(*args, **kwargs)
121
111
  span = tracer.start_span(span_name, kind=SpanKind.CLIENT)
122
112
  return TracedSyncStream(awaited_wrapped, span, span_name, kwargs, server_address, server_port)
123
-
124
- # Handling for non-streaming responses
125
113
  else:
126
- with tracer.start_as_current_span(span_name, kind= SpanKind.CLIENT) as span:
114
+ # Handling for non-streaming responses
115
+ with tracer.start_as_current_span(span_name, kind=SpanKind.CLIENT) as span:
127
116
  start_time = time.time()
128
117
  response = wrapped(*args, **kwargs)
129
118
 
@@ -152,23 +141,22 @@ def chat(version, environment, application_name,
152
141
 
153
142
  return wrapper
154
143
 
155
- def chat_rag(version, environment, application_name,
156
- tracer, pricing_info, capture_message_content, metrics, disable_metrics):
144
+ def chat_rag(version, environment, application_name, tracer, pricing_info,
145
+ capture_message_content, metrics, disable_metrics):
157
146
  """
158
- Generates a telemetry wrapper for GenAI function call
147
+ Generates a telemetry wrapper for GenAI RAG function call
159
148
  """
160
149
 
161
150
  def wrapper(wrapped, instance, args, kwargs):
162
151
  """
163
- Wraps the GenAI function call.
152
+ Wraps the GenAI RAG function call.
164
153
  """
165
-
166
154
  server_address, server_port = set_server_address_and_port(instance, "api.ai21.com", 443)
167
155
  request_model = kwargs.get("model", "jamba-1.5-mini")
168
156
 
169
157
  span_name = f"{SemanticConvention.GEN_AI_OPERATION_TYPE_CHAT} {request_model}"
170
158
 
171
- with tracer.start_as_current_span(span_name, kind= SpanKind.CLIENT) as span:
159
+ with tracer.start_as_current_span(span_name, kind=SpanKind.CLIENT) as span:
172
160
  start_time = time.time()
173
161
  response = wrapped(*args, **kwargs)
174
162
 
@@ -1,8 +1,7 @@
1
1
  """
2
- Module for monitoring AI21 calls.
2
+ Module for monitoring AI21 API calls (async version).
3
3
  """
4
4
 
5
- import logging
6
5
  import time
7
6
  from opentelemetry.trace import SpanKind
8
7
  from openlit.__helpers import (
@@ -15,21 +14,17 @@ from openlit.instrumentation.ai21.utils import (
15
14
  process_streaming_chat_response,
16
15
  process_chat_rag_response
17
16
  )
18
-
19
17
  from openlit.semcov import SemanticConvention
20
18
 
21
- # Initialize logger for logging potential issues and operations
22
- logger = logging.getLogger(__name__)
23
-
24
- def async_chat(version, environment, application_name,
25
- tracer, pricing_info, capture_message_content, metrics, disable_metrics):
19
+ def async_chat(version, environment, application_name, tracer, pricing_info,
20
+ capture_message_content, metrics, disable_metrics):
26
21
  """
27
22
  Generates a telemetry wrapper for GenAI function call
28
23
  """
29
24
 
30
25
  class TracedAsyncStream:
31
26
  """
32
- Wrapper for streaming responses to collect telemetry.
27
+ Wrapper for async streaming responses to collect telemetry.
33
28
  """
34
29
 
35
30
  def __init__(
@@ -45,14 +40,12 @@ def async_chat(version, environment, application_name,
45
40
  self.__wrapped__ = wrapped
46
41
  self._span = span
47
42
  self._span_name = span_name
48
- # Placeholder for aggregating streaming response
49
43
  self._llmresponse = ""
50
44
  self._response_id = ""
51
45
  self._finish_reason = ""
46
+ self._tools = None
52
47
  self._input_tokens = 0
53
48
  self._output_tokens = 0
54
- self._choices = []
55
-
56
49
  self._args = args
57
50
  self._kwargs = kwargs
58
51
  self._start_time = time.time()
@@ -83,9 +76,8 @@ def async_chat(version, environment, application_name,
83
76
  process_chunk(self, chunk)
84
77
  return chunk
85
78
  except StopAsyncIteration:
86
- # Handling exception ensure observability without disrupting operation
87
79
  try:
88
- with tracer.start_as_current_span(self._span_name, kind= SpanKind.CLIENT) as self._span:
80
+ with tracer.start_as_current_span(self._span_name, kind=SpanKind.CLIENT) as self._span:
89
81
  process_streaming_chat_response(
90
82
  self,
91
83
  pricing_info=pricing_info,
@@ -96,6 +88,7 @@ def async_chat(version, environment, application_name,
96
88
  disable_metrics=disable_metrics,
97
89
  version=version
98
90
  )
91
+
99
92
  except Exception as e:
100
93
  handle_exception(self._span, e)
101
94
 
@@ -105,25 +98,21 @@ def async_chat(version, environment, application_name,
105
98
  """
106
99
  Wraps the GenAI function call.
107
100
  """
108
-
109
101
  # Check if streaming is enabled for the API call
110
102
  streaming = kwargs.get("stream", False)
111
-
112
103
  server_address, server_port = set_server_address_and_port(instance, "api.ai21.com", 443)
113
104
  request_model = kwargs.get("model", "jamba-1.5-mini")
114
105
 
115
106
  span_name = f"{SemanticConvention.GEN_AI_OPERATION_TYPE_CHAT} {request_model}"
116
107
 
117
- # pylint: disable=no-else-return
118
108
  if streaming:
119
- # Special handling for streaming response to accommodate the nature of data flow
109
+ # Special handling for streaming response
120
110
  awaited_wrapped = await wrapped(*args, **kwargs)
121
111
  span = tracer.start_span(span_name, kind=SpanKind.CLIENT)
122
112
  return TracedAsyncStream(awaited_wrapped, span, span_name, kwargs, server_address, server_port)
123
-
124
- # Handling for non-streaming responses
125
113
  else:
126
- with tracer.start_as_current_span(span_name, kind= SpanKind.CLIENT) as span:
114
+ # Handling for non-streaming responses
115
+ with tracer.start_as_current_span(span_name, kind=SpanKind.CLIENT) as span:
127
116
  start_time = time.time()
128
117
  response = await wrapped(*args, **kwargs)
129
118
 
@@ -152,23 +141,22 @@ def async_chat(version, environment, application_name,
152
141
 
153
142
  return wrapper
154
143
 
155
- def async_chat_rag(version, environment, application_name,
156
- tracer, pricing_info, capture_message_content, metrics, disable_metrics):
144
+ def async_chat_rag(version, environment, application_name, tracer, pricing_info,
145
+ capture_message_content, metrics, disable_metrics):
157
146
  """
158
- Generates a telemetry wrapper for GenAI function call
147
+ Generates a telemetry wrapper for GenAI RAG function call
159
148
  """
160
149
 
161
150
  async def wrapper(wrapped, instance, args, kwargs):
162
151
  """
163
- Wraps the GenAI function call.
152
+ Wraps the GenAI RAG function call.
164
153
  """
165
-
166
154
  server_address, server_port = set_server_address_and_port(instance, "api.ai21.com", 443)
167
155
  request_model = kwargs.get("model", "jamba-1.5-mini")
168
156
 
169
157
  span_name = f"{SemanticConvention.GEN_AI_OPERATION_TYPE_CHAT} {request_model}"
170
158
 
171
- with tracer.start_as_current_span(span_name, kind= SpanKind.CLIENT) as span:
159
+ with tracer.start_as_current_span(span_name, kind=SpanKind.CLIENT) as span:
172
160
  start_time = time.time()
173
161
  response = await wrapped(*args, **kwargs)
174
162
 
@@ -0,0 +1,317 @@
1
+ """
2
+ AI21 OpenTelemetry instrumentation utility functions
3
+ """
4
+
5
+ import time
6
+
7
+ from opentelemetry.trace import Status, StatusCode
8
+
9
+ from openlit.__helpers import (
10
+ calculate_ttft,
11
+ response_as_dict,
12
+ calculate_tbt,
13
+ general_tokens,
14
+ get_chat_model_cost,
15
+ common_span_attributes,
16
+ record_completion_metrics,
17
+ )
18
+ from openlit.semcov import SemanticConvention
19
+
20
+ def format_content(messages):
21
+ """
22
+ Process a list of messages to extract content.
23
+ """
24
+
25
+ formatted_messages = []
26
+ for message in messages:
27
+ # Handle different message formats
28
+ if hasattr(message, "role") and (hasattr(message, "content") or hasattr(message, "text")):
29
+ # ChatMessage object (AI21 format)
30
+ role = str(message.role) if hasattr(message.role, 'value') else str(message.role)
31
+ content = getattr(message, "content", None) or getattr(message, "text", "")
32
+ elif isinstance(message, dict):
33
+ # Dictionary format
34
+ role = message["role"]
35
+ content = message["content"]
36
+ else:
37
+ # Fallback - try to extract as string
38
+ role = str(getattr(message, "role", "unknown"))
39
+ content = str(getattr(message, "content", "") or getattr(message, "text", ""))
40
+
41
+ if isinstance(content, list):
42
+ content_str = ", ".join(
43
+ f'{item["type"]}: {item["text"] if "text" in item else item["image_url"]}'
44
+ if "type" in item else f'text: {item["text"]}'
45
+ for item in content
46
+ )
47
+ formatted_messages.append(f"{role}: {content_str}")
48
+ else:
49
+ formatted_messages.append(f"{role}: {content}")
50
+
51
+ return "\n".join(formatted_messages)
52
+
53
+ def process_chunk(scope, chunk):
54
+ """
55
+ Process a chunk of response data and update state.
56
+ """
57
+
58
+ end_time = time.time()
59
+ # Record the timestamp for the current chunk
60
+ scope._timestamps.append(end_time)
61
+
62
+ if len(scope._timestamps) == 1:
63
+ # Calculate time to first chunk
64
+ scope._ttft = calculate_ttft(scope._timestamps, scope._start_time)
65
+
66
+ chunked = response_as_dict(chunk)
67
+
68
+ # Collect message IDs and aggregated response from events
69
+ if (len(chunked.get("choices", [])) > 0 and
70
+ "delta" in chunked.get("choices")[0] and
71
+ "content" in chunked.get("choices")[0].get("delta", {})):
72
+
73
+ content = chunked.get("choices")[0].get("delta").get("content")
74
+ if content:
75
+ scope._llmresponse += content
76
+
77
+ if chunked.get("usage"):
78
+ scope._input_tokens = chunked.get("usage").get("prompt_tokens")
79
+ scope._output_tokens = chunked.get("usage").get("completion_tokens")
80
+ scope._response_id = chunked.get("id")
81
+ scope._finish_reason = chunked.get("choices", [{}])[0].get("finish_reason")
82
+ scope._end_time = time.time()
83
+
84
+ def common_chat_logic(scope, pricing_info, environment, application_name, metrics,
85
+ capture_message_content, disable_metrics, version, is_stream):
86
+ """
87
+ Process chat request and generate Telemetry
88
+ """
89
+
90
+ if len(scope._timestamps) > 1:
91
+ scope._tbt = calculate_tbt(scope._timestamps)
92
+
93
+ prompt = format_content(scope._kwargs.get("messages", []))
94
+ request_model = scope._kwargs.get("model", "jamba-1.5-mini")
95
+
96
+ cost = get_chat_model_cost(request_model, pricing_info, scope._input_tokens, scope._output_tokens)
97
+
98
+ # Common Span Attributes
99
+ common_span_attributes(scope,
100
+ SemanticConvention.GEN_AI_OPERATION_TYPE_CHAT, SemanticConvention.GEN_AI_SYSTEM_AI21,
101
+ scope._server_address, scope._server_port, request_model, request_model,
102
+ environment, application_name, is_stream, scope._tbt, scope._ttft, version)
103
+
104
+ # Span Attributes for Request parameters
105
+ scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_SEED, scope._kwargs.get("seed", ""))
106
+ scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_FREQUENCY_PENALTY, scope._kwargs.get("frequency_penalty", 0.0))
107
+ scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_MAX_TOKENS, scope._kwargs.get("max_tokens", -1))
108
+ scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_PRESENCE_PENALTY, scope._kwargs.get("presence_penalty", 0.0))
109
+ scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_STOP_SEQUENCES, scope._kwargs.get("stop", []))
110
+ scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_TEMPERATURE, scope._kwargs.get("temperature", 0.4))
111
+ scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_TOP_P, scope._kwargs.get("top_p", 1.0))
112
+
113
+ # Span Attributes for Response parameters
114
+ scope._span.set_attribute(SemanticConvention.GEN_AI_RESPONSE_ID, scope._response_id)
115
+ scope._span.set_attribute(SemanticConvention.GEN_AI_RESPONSE_FINISH_REASON, [scope._finish_reason])
116
+ scope._span.set_attribute(SemanticConvention.GEN_AI_OUTPUT_TYPE, "text" if isinstance(scope._llmresponse, str) else "json")
117
+
118
+ # Span Attributes for Cost and Tokens
119
+ scope._span.set_attribute(SemanticConvention.GEN_AI_USAGE_INPUT_TOKENS, scope._input_tokens)
120
+ scope._span.set_attribute(SemanticConvention.GEN_AI_USAGE_OUTPUT_TOKENS, scope._output_tokens)
121
+ scope._span.set_attribute(SemanticConvention.GEN_AI_CLIENT_TOKEN_USAGE, scope._input_tokens + scope._output_tokens)
122
+ scope._span.set_attribute(SemanticConvention.GEN_AI_USAGE_COST, cost)
123
+
124
+ # Span Attributes for Tools
125
+ if scope._tools:
126
+ scope._span.set_attribute(SemanticConvention.GEN_AI_TOOL_NAME, scope._tools.get("function", {}).get("name", ""))
127
+ scope._span.set_attribute(SemanticConvention.GEN_AI_TOOL_CALL_ID, str(scope._tools.get("id", "")))
128
+ scope._span.set_attribute(SemanticConvention.GEN_AI_TOOL_ARGS, str(scope._tools.get("function", {}).get("arguments", "")))
129
+
130
+ # Span Attributes for Content
131
+ if capture_message_content:
132
+ scope._span.set_attribute(SemanticConvention.GEN_AI_CONTENT_PROMPT, prompt)
133
+ scope._span.set_attribute(SemanticConvention.GEN_AI_CONTENT_COMPLETION, scope._llmresponse)
134
+
135
+ # To be removed once the change to span_attributes (from span events) is complete
136
+ scope._span.add_event(
137
+ name=SemanticConvention.GEN_AI_CONTENT_PROMPT_EVENT,
138
+ attributes={
139
+ SemanticConvention.GEN_AI_CONTENT_PROMPT: prompt,
140
+ },
141
+ )
142
+ scope._span.add_event(
143
+ name=SemanticConvention.GEN_AI_CONTENT_COMPLETION_EVENT,
144
+ attributes={
145
+ SemanticConvention.GEN_AI_CONTENT_COMPLETION: scope._llmresponse,
146
+ },
147
+ )
148
+
149
+ scope._span.set_status(Status(StatusCode.OK))
150
+
151
+ # Metrics
152
+ if not disable_metrics:
153
+ record_completion_metrics(metrics, SemanticConvention.GEN_AI_OPERATION_TYPE_CHAT, SemanticConvention.GEN_AI_SYSTEM_AI21,
154
+ scope._server_address, scope._server_port, request_model, request_model, environment,
155
+ application_name, scope._start_time, scope._end_time, scope._input_tokens, scope._output_tokens,
156
+ cost, scope._tbt, scope._ttft)
157
+
158
+ def process_streaming_chat_response(scope, pricing_info, environment, application_name, metrics,
159
+ capture_message_content=False, disable_metrics=False, version=""):
160
+ """
161
+ Process streaming chat request and generate Telemetry
162
+ """
163
+
164
+ common_chat_logic(scope, pricing_info, environment, application_name, metrics,
165
+ capture_message_content, disable_metrics, version, is_stream=True)
166
+
167
+ def process_chat_response(response, request_model, pricing_info, server_port, server_address,
168
+ environment, application_name, metrics, start_time, span, capture_message_content=False,
169
+ disable_metrics=False, version="1.0.0", **kwargs):
170
+ """
171
+ Process chat request and generate Telemetry
172
+ """
173
+
174
+ # Create scope object
175
+ scope = type("GenericScope", (), {})()
176
+ response_dict = response_as_dict(response)
177
+
178
+ scope._start_time = start_time
179
+ scope._end_time = time.time()
180
+ scope._span = span
181
+ scope._llmresponse = " ".join(
182
+ (choice.get("message", {}).get("content") or "")
183
+ for choice in response_dict.get("choices", [])
184
+ )
185
+ scope._response_id = response_dict.get("id")
186
+ scope._input_tokens = response_dict.get("usage", {}).get("prompt_tokens", 0)
187
+ scope._output_tokens = response_dict.get("usage", {}).get("completion_tokens", 0)
188
+ scope._timestamps = []
189
+ scope._ttft, scope._tbt = scope._end_time - scope._start_time, 0
190
+ scope._server_address, scope._server_port = server_address, server_port
191
+ scope._kwargs = kwargs
192
+ scope._finish_reason = str(response_dict.get("choices", [])[0].get("finish_reason", ""))
193
+
194
+ # Handle tool calls
195
+ if scope._kwargs.get("tools"):
196
+ scope._tools = response_dict.get("choices", [{}])[0].get("message", {}).get("tool_calls")
197
+ else:
198
+ scope._tools = None
199
+
200
+ common_chat_logic(scope, pricing_info, environment, application_name, metrics,
201
+ capture_message_content, disable_metrics, version, is_stream=False)
202
+
203
+ return response
204
+
205
+ def common_chat_rag_logic(scope, pricing_info, environment, application_name, metrics,
206
+ capture_message_content, disable_metrics, version):
207
+ """
208
+ Process RAG chat request and generate Telemetry
209
+ """
210
+
211
+ prompt = format_content(scope._kwargs.get("messages", []))
212
+ request_model = scope._kwargs.get("model", "jamba-1.5-mini")
213
+
214
+ cost = get_chat_model_cost(request_model, pricing_info, scope._input_tokens, scope._output_tokens)
215
+
216
+ # Common Span Attributes
217
+ common_span_attributes(scope,
218
+ SemanticConvention.GEN_AI_OPERATION_TYPE_CHAT, SemanticConvention.GEN_AI_SYSTEM_AI21,
219
+ scope._server_address, scope._server_port, request_model, scope._response_model,
220
+ environment, application_name, False, scope._tbt, scope._ttft, version)
221
+
222
+ # RAG-specific span attributes
223
+ scope._span.set_attribute(SemanticConvention.GEN_AI_RAG_MAX_SEGMENTS, scope._kwargs.get("max_segments", -1))
224
+ scope._span.set_attribute(SemanticConvention.GEN_AI_RAG_STRATEGY, scope._kwargs.get("retrieval_strategy", "segments"))
225
+ scope._span.set_attribute(SemanticConvention.GEN_AI_RAG_MAX_NEIGHBORS, scope._kwargs.get("max_neighbors", -1))
226
+ scope._span.set_attribute(SemanticConvention.GEN_AI_RAG_FILE_IDS, str(scope._kwargs.get("file_ids", "")))
227
+ scope._span.set_attribute(SemanticConvention.GEN_AI_RAG_DOCUMENTS_PATH, scope._kwargs.get("path", ""))
228
+ scope._span.set_attribute(SemanticConvention.GEN_AI_RAG_SIMILARITY_THRESHOLD,
229
+ scope._kwargs.get("retrieval_similarity_threshold", -1))
230
+
231
+ # Standard span attributes
232
+ scope._span.set_attribute(SemanticConvention.GEN_AI_RESPONSE_ID, scope._response_id)
233
+ scope._span.set_attribute(SemanticConvention.GEN_AI_OUTPUT_TYPE, "text" if isinstance(scope._llmresponse, str) else "json")
234
+ scope._span.set_attribute(SemanticConvention.GEN_AI_USAGE_INPUT_TOKENS, scope._input_tokens)
235
+ scope._span.set_attribute(SemanticConvention.GEN_AI_USAGE_OUTPUT_TOKENS, scope._output_tokens)
236
+ scope._span.set_attribute(SemanticConvention.GEN_AI_CLIENT_TOKEN_USAGE, scope._input_tokens + scope._output_tokens)
237
+ scope._span.set_attribute(SemanticConvention.GEN_AI_USAGE_COST, cost)
238
+
239
+ # Handle tool calls
240
+ if scope._kwargs.get("tools"):
241
+ scope._span.set_attribute(SemanticConvention.GEN_AI_TOOL_CALLS,
242
+ str(scope._choices[0].get("message", {}).get("tool_calls", "")))
243
+
244
+ # Content attributes
245
+ if capture_message_content:
246
+ scope._span.set_attribute(SemanticConvention.GEN_AI_CONTENT_PROMPT, prompt)
247
+ scope._span.set_attribute(SemanticConvention.GEN_AI_CONTENT_COMPLETION, scope._llmresponse)
248
+
249
+ # To be removed once the change to span_attributes (from span events) is complete
250
+ scope._span.add_event(
251
+ name=SemanticConvention.GEN_AI_CONTENT_PROMPT_EVENT,
252
+ attributes={
253
+ SemanticConvention.GEN_AI_CONTENT_PROMPT: prompt,
254
+ },
255
+ )
256
+ scope._span.add_event(
257
+ name=SemanticConvention.GEN_AI_CONTENT_COMPLETION_EVENT,
258
+ attributes={
259
+ SemanticConvention.GEN_AI_CONTENT_COMPLETION: scope._llmresponse,
260
+ },
261
+ )
262
+
263
+ scope._span.set_status(Status(StatusCode.OK))
264
+
265
+ # Metrics
266
+ if not disable_metrics:
267
+ record_completion_metrics(metrics, SemanticConvention.GEN_AI_OPERATION_TYPE_CHAT, SemanticConvention.GEN_AI_SYSTEM_AI21,
268
+ scope._server_address, scope._server_port, request_model, scope._response_model, environment,
269
+ application_name, scope._start_time, scope._end_time, scope._input_tokens, scope._output_tokens,
270
+ cost, scope._tbt, scope._ttft)
271
+
272
+ def process_chat_rag_response(response, request_model, pricing_info, server_port, server_address,
273
+ environment, application_name, metrics, start_time, span, capture_message_content=False,
274
+ disable_metrics=False, version="1.0.0", **kwargs):
275
+ """
276
+ Process RAG chat request and generate Telemetry
277
+ """
278
+
279
+ # Create scope object
280
+ scope = type("GenericScope", (), {})()
281
+ response_dict = response_as_dict(response)
282
+
283
+ scope._start_time = start_time
284
+ scope._end_time = time.time()
285
+ scope._span = span
286
+
287
+ # Format input messages and calculate input tokens
288
+ prompt = format_content(kwargs.get("messages", []))
289
+ input_tokens = general_tokens(prompt)
290
+
291
+ # Process response choices
292
+ choices = response_dict.get("choices", [])
293
+ aggregated_completion = []
294
+ output_tokens = 0
295
+
296
+ for i in range(kwargs.get("n", 1)):
297
+ content = choices[i].get("content", "")
298
+ aggregated_completion.append(content)
299
+ output_tokens += general_tokens(content)
300
+
301
+ scope._llmresponse = "".join(aggregated_completion)
302
+ scope._response_id = response_dict.get("id", "")
303
+ scope._response_model = request_model
304
+ scope._input_tokens = input_tokens
305
+ scope._output_tokens = output_tokens
306
+ scope._timestamps = []
307
+ scope._ttft, scope._tbt = scope._end_time - scope._start_time, 0
308
+ scope._server_address, scope._server_port = server_address, server_port
309
+ scope._kwargs = kwargs
310
+ scope._finish_reason = ""
311
+ scope._tools = None
312
+ scope._choices = choices
313
+
314
+ common_chat_rag_logic(scope, pricing_info, environment, application_name, metrics,
315
+ capture_message_content, disable_metrics, version)
316
+
317
+ return response