netra-sdk 0.1.29__tar.gz → 0.1.31__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.
Potentially problematic release.
This version of netra-sdk might be problematic. Click here for more details.
- {netra_sdk-0.1.29 → netra_sdk-0.1.31}/PKG-INFO +2 -1
- {netra_sdk-0.1.29 → netra_sdk-0.1.31}/README.md +1 -0
- {netra_sdk-0.1.29 → netra_sdk-0.1.31}/netra/__init__.py +25 -0
- {netra_sdk-0.1.29 → netra_sdk-0.1.31}/netra/config.py +2 -0
- {netra_sdk-0.1.29 → netra_sdk-0.1.31}/netra/decorators.py +27 -2
- {netra_sdk-0.1.29 → netra_sdk-0.1.31}/netra/instrumentation/__init__.py +24 -0
- {netra_sdk-0.1.29 → netra_sdk-0.1.31}/netra/instrumentation/instruments.py +2 -0
- netra_sdk-0.1.31/netra/instrumentation/litellm/__init__.py +161 -0
- netra_sdk-0.1.31/netra/instrumentation/litellm/wrappers.py +557 -0
- netra_sdk-0.1.31/netra/instrumentation/pydantic_ai/version.py +1 -0
- netra_sdk-0.1.31/netra/processors/__init__.py +4 -0
- netra_sdk-0.1.31/netra/processors/instrumentation_span_processor.py +102 -0
- {netra_sdk-0.1.29 → netra_sdk-0.1.31}/netra/session_manager.py +88 -0
- {netra_sdk-0.1.29 → netra_sdk-0.1.31}/netra/span_wrapper.py +14 -0
- {netra_sdk-0.1.29 → netra_sdk-0.1.31}/netra/tracer.py +3 -2
- netra_sdk-0.1.31/netra/version.py +1 -0
- {netra_sdk-0.1.29 → netra_sdk-0.1.31}/pyproject.toml +1 -1
- netra_sdk-0.1.29/netra/processors/__init__.py +0 -3
- netra_sdk-0.1.29/netra/version.py +0 -1
- {netra_sdk-0.1.29 → netra_sdk-0.1.31}/LICENCE +0 -0
- {netra_sdk-0.1.29 → netra_sdk-0.1.31}/netra/anonymizer/__init__.py +0 -0
- {netra_sdk-0.1.29 → netra_sdk-0.1.31}/netra/anonymizer/anonymizer.py +0 -0
- {netra_sdk-0.1.29 → netra_sdk-0.1.31}/netra/anonymizer/base.py +0 -0
- {netra_sdk-0.1.29 → netra_sdk-0.1.31}/netra/anonymizer/fp_anonymizer.py +0 -0
- {netra_sdk-0.1.29 → netra_sdk-0.1.31}/netra/exceptions/__init__.py +0 -0
- {netra_sdk-0.1.29 → netra_sdk-0.1.31}/netra/exceptions/injection.py +0 -0
- {netra_sdk-0.1.29 → netra_sdk-0.1.31}/netra/exceptions/pii.py +0 -0
- {netra_sdk-0.1.29 → netra_sdk-0.1.31}/netra/input_scanner.py +0 -0
- {netra_sdk-0.1.29 → netra_sdk-0.1.31}/netra/instrumentation/aiohttp/__init__.py +0 -0
- {netra_sdk-0.1.29 → netra_sdk-0.1.31}/netra/instrumentation/aiohttp/version.py +0 -0
- {netra_sdk-0.1.29 → netra_sdk-0.1.31}/netra/instrumentation/cohere/__init__.py +0 -0
- {netra_sdk-0.1.29 → netra_sdk-0.1.31}/netra/instrumentation/cohere/version.py +0 -0
- {netra_sdk-0.1.29 → netra_sdk-0.1.31}/netra/instrumentation/fastapi/__init__.py +0 -0
- {netra_sdk-0.1.29 → netra_sdk-0.1.31}/netra/instrumentation/fastapi/version.py +0 -0
- {netra_sdk-0.1.29 → netra_sdk-0.1.31}/netra/instrumentation/google_genai/__init__.py +0 -0
- {netra_sdk-0.1.29 → netra_sdk-0.1.31}/netra/instrumentation/google_genai/config.py +0 -0
- {netra_sdk-0.1.29 → netra_sdk-0.1.31}/netra/instrumentation/google_genai/utils.py +0 -0
- {netra_sdk-0.1.29 → netra_sdk-0.1.31}/netra/instrumentation/google_genai/version.py +0 -0
- {netra_sdk-0.1.29 → netra_sdk-0.1.31}/netra/instrumentation/httpx/__init__.py +0 -0
- {netra_sdk-0.1.29 → netra_sdk-0.1.31}/netra/instrumentation/httpx/version.py +0 -0
- {netra_sdk-0.1.29/netra/instrumentation/pydantic_ai → netra_sdk-0.1.31/netra/instrumentation/litellm}/version.py +0 -0
- {netra_sdk-0.1.29 → netra_sdk-0.1.31}/netra/instrumentation/mistralai/__init__.py +0 -0
- {netra_sdk-0.1.29 → netra_sdk-0.1.31}/netra/instrumentation/mistralai/config.py +0 -0
- {netra_sdk-0.1.29 → netra_sdk-0.1.31}/netra/instrumentation/mistralai/utils.py +0 -0
- {netra_sdk-0.1.29 → netra_sdk-0.1.31}/netra/instrumentation/mistralai/version.py +0 -0
- {netra_sdk-0.1.29 → netra_sdk-0.1.31}/netra/instrumentation/openai/__init__.py +0 -0
- {netra_sdk-0.1.29 → netra_sdk-0.1.31}/netra/instrumentation/openai/version.py +0 -0
- {netra_sdk-0.1.29 → netra_sdk-0.1.31}/netra/instrumentation/openai/wrappers.py +0 -0
- {netra_sdk-0.1.29 → netra_sdk-0.1.31}/netra/instrumentation/pydantic_ai/__init__.py +0 -0
- {netra_sdk-0.1.29 → netra_sdk-0.1.31}/netra/instrumentation/pydantic_ai/utils.py +0 -0
- {netra_sdk-0.1.29 → netra_sdk-0.1.31}/netra/instrumentation/pydantic_ai/wrappers.py +0 -0
- {netra_sdk-0.1.29 → netra_sdk-0.1.31}/netra/instrumentation/weaviate/__init__.py +0 -0
- {netra_sdk-0.1.29 → netra_sdk-0.1.31}/netra/instrumentation/weaviate/version.py +0 -0
- {netra_sdk-0.1.29 → netra_sdk-0.1.31}/netra/pii.py +0 -0
- {netra_sdk-0.1.29 → netra_sdk-0.1.31}/netra/processors/session_span_processor.py +0 -0
- {netra_sdk-0.1.29 → netra_sdk-0.1.31}/netra/scanner.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: netra-sdk
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.31
|
|
4
4
|
Summary: A Python SDK for AI application observability that provides OpenTelemetry-based monitoring, tracing, and PII protection for LLM and vector database applications. Enables easy instrumentation, session tracking, and privacy-focused data collection for AI systems in production environments.
|
|
5
5
|
License: Apache-2.0
|
|
6
6
|
Keywords: netra,tracing,observability,sdk,ai,llm,vector,database
|
|
@@ -303,6 +303,7 @@ async def async_span(data):
|
|
|
303
303
|
- **CrewAI** - Multi-agent AI systems
|
|
304
304
|
- **Pydantic AI** - AI model communication standard
|
|
305
305
|
- **MCP (Model Context Protocol)** - AI model communication standard
|
|
306
|
+
- **LiteLLM** - LLM provider agnostic client
|
|
306
307
|
|
|
307
308
|
## 🛡️ Privacy Protection & Security
|
|
308
309
|
|
|
@@ -223,6 +223,7 @@ async def async_span(data):
|
|
|
223
223
|
- **CrewAI** - Multi-agent AI systems
|
|
224
224
|
- **Pydantic AI** - AI model communication standard
|
|
225
225
|
- **MCP (Model Context Protocol)** - AI model communication standard
|
|
226
|
+
- **LiteLLM** - LLM provider agnostic client
|
|
226
227
|
|
|
227
228
|
## 🛡️ Privacy Protection & Security
|
|
228
229
|
|
|
@@ -255,5 +255,30 @@ class Netra:
|
|
|
255
255
|
"""
|
|
256
256
|
return SpanWrapper(name, attributes, module_name)
|
|
257
257
|
|
|
258
|
+
@classmethod
|
|
259
|
+
def set_input(cls, value: Any, span_name: Optional[str] = None) -> None:
|
|
260
|
+
"""
|
|
261
|
+
Set custom attribute `netra.span.input` on a target span.
|
|
262
|
+
|
|
263
|
+
Args:
|
|
264
|
+
value: Input payload to record (string or JSON-serializable object)
|
|
265
|
+
span_name: Optional. When provided, sets the attribute on the span registered
|
|
266
|
+
with this name. Otherwise sets on the active span.
|
|
267
|
+
"""
|
|
268
|
+
SessionManager.set_attribute_on_target_span(f"{Config.LIBRARY_NAME}.span.input", value, span_name)
|
|
269
|
+
|
|
270
|
+
@classmethod
|
|
271
|
+
def set_output(cls, value: Any, span_name: Optional[str] = None) -> None:
|
|
272
|
+
"""
|
|
273
|
+
Set custom attribute `netra.span.output` on a target span.
|
|
274
|
+
|
|
275
|
+
Args:
|
|
276
|
+
value: Output payload to record (string or JSON-serializable object)
|
|
277
|
+
span_name: Optional. When provided, sets the attribute on the span registered
|
|
278
|
+
with this name. Otherwise sets on the active span.
|
|
279
|
+
"""
|
|
280
|
+
if value:
|
|
281
|
+
SessionManager.set_attribute_on_target_span(f"{Config.LIBRARY_NAME}.span.output", value, span_name)
|
|
282
|
+
|
|
258
283
|
|
|
259
284
|
__all__ = ["Netra", "UsageModel", "ActionModel"]
|
|
@@ -7,6 +7,7 @@ Decorators can be applied to both functions and classes.
|
|
|
7
7
|
import functools
|
|
8
8
|
import inspect
|
|
9
9
|
import json
|
|
10
|
+
import logging
|
|
10
11
|
from typing import Any, Awaitable, Callable, Dict, Optional, ParamSpec, Tuple, TypeVar, Union, cast
|
|
11
12
|
|
|
12
13
|
from opentelemetry import trace
|
|
@@ -14,6 +15,8 @@ from opentelemetry import trace
|
|
|
14
15
|
from .config import Config
|
|
15
16
|
from .session_manager import SessionManager
|
|
16
17
|
|
|
18
|
+
logger = logging.getLogger(__name__)
|
|
19
|
+
|
|
17
20
|
P = ParamSpec("P")
|
|
18
21
|
R = TypeVar("R")
|
|
19
22
|
|
|
@@ -84,6 +87,13 @@ def _create_function_wrapper(func: Callable[P, R], entity_type: str, name: Optio
|
|
|
84
87
|
|
|
85
88
|
tracer = trace.get_tracer(module_name)
|
|
86
89
|
with tracer.start_as_current_span(span_name) as span:
|
|
90
|
+
# Register the span by name for cross-context attribute setting
|
|
91
|
+
try:
|
|
92
|
+
SessionManager.register_span(span_name, span)
|
|
93
|
+
SessionManager.set_current_span(span)
|
|
94
|
+
except Exception:
|
|
95
|
+
logger.exception("Failed to register span '%s' with SessionManager", span_name)
|
|
96
|
+
|
|
87
97
|
_add_span_attributes(span, func, args, kwargs, entity_type)
|
|
88
98
|
try:
|
|
89
99
|
result = await cast(Awaitable[Any], func(*args, **kwargs))
|
|
@@ -93,7 +103,11 @@ def _create_function_wrapper(func: Callable[P, R], entity_type: str, name: Optio
|
|
|
93
103
|
span.set_attribute(f"{Config.LIBRARY_NAME}.entity.error", str(e))
|
|
94
104
|
raise
|
|
95
105
|
finally:
|
|
96
|
-
#
|
|
106
|
+
# Unregister and pop entity from stack after function call is done
|
|
107
|
+
try:
|
|
108
|
+
SessionManager.unregister_span(span_name, span)
|
|
109
|
+
except Exception:
|
|
110
|
+
logger.exception("Failed to unregister span '%s' from SessionManager", span_name)
|
|
97
111
|
SessionManager.pop_entity(entity_type)
|
|
98
112
|
|
|
99
113
|
return cast(Callable[P, R], async_wrapper)
|
|
@@ -107,6 +121,13 @@ def _create_function_wrapper(func: Callable[P, R], entity_type: str, name: Optio
|
|
|
107
121
|
|
|
108
122
|
tracer = trace.get_tracer(module_name)
|
|
109
123
|
with tracer.start_as_current_span(span_name) as span:
|
|
124
|
+
# Register the span by name for cross-context attribute setting
|
|
125
|
+
try:
|
|
126
|
+
SessionManager.register_span(span_name, span)
|
|
127
|
+
SessionManager.set_current_span(span)
|
|
128
|
+
except Exception:
|
|
129
|
+
logger.exception("Failed to register span '%s' with SessionManager", span_name)
|
|
130
|
+
|
|
110
131
|
_add_span_attributes(span, func, args, kwargs, entity_type)
|
|
111
132
|
try:
|
|
112
133
|
result = func(*args, **kwargs)
|
|
@@ -116,7 +137,11 @@ def _create_function_wrapper(func: Callable[P, R], entity_type: str, name: Optio
|
|
|
116
137
|
span.set_attribute(f"{Config.LIBRARY_NAME}.entity.error", str(e))
|
|
117
138
|
raise
|
|
118
139
|
finally:
|
|
119
|
-
#
|
|
140
|
+
# Unregister and pop entity from stack after function call is done
|
|
141
|
+
try:
|
|
142
|
+
SessionManager.unregister_span(span_name, span)
|
|
143
|
+
except Exception:
|
|
144
|
+
logger.exception("Failed to unregister span '%s' from SessionManager", span_name)
|
|
120
145
|
SessionManager.pop_entity(entity_type)
|
|
121
146
|
|
|
122
147
|
return cast(Callable[P, R], sync_wrapper)
|
|
@@ -93,6 +93,10 @@ def init_instrumentations(
|
|
|
93
93
|
if CustomInstruments.MISTRALAI in netra_custom_instruments:
|
|
94
94
|
init_mistral_instrumentor()
|
|
95
95
|
|
|
96
|
+
# Initialize LiteLLM instrumentation.
|
|
97
|
+
if CustomInstruments.LITELLM in netra_custom_instruments:
|
|
98
|
+
init_litellm_instrumentation()
|
|
99
|
+
|
|
96
100
|
# Initialize OpenAI instrumentation.
|
|
97
101
|
if CustomInstruments.OPENAI in netra_custom_instruments:
|
|
98
102
|
init_openai_instrumentation()
|
|
@@ -435,6 +439,26 @@ def init_mistral_instrumentor() -> bool:
|
|
|
435
439
|
return False
|
|
436
440
|
|
|
437
441
|
|
|
442
|
+
def init_litellm_instrumentation() -> bool:
|
|
443
|
+
"""Initialize LiteLLM instrumentation.
|
|
444
|
+
|
|
445
|
+
Returns:
|
|
446
|
+
bool: True if initialization was successful, False otherwise.
|
|
447
|
+
"""
|
|
448
|
+
try:
|
|
449
|
+
if is_package_installed("litellm"):
|
|
450
|
+
from netra.instrumentation.litellm import LiteLLMInstrumentor
|
|
451
|
+
|
|
452
|
+
instrumentor = LiteLLMInstrumentor()
|
|
453
|
+
if not instrumentor.is_instrumented_by_opentelemetry:
|
|
454
|
+
instrumentor.instrument()
|
|
455
|
+
return True
|
|
456
|
+
except Exception as e:
|
|
457
|
+
logging.error(f"Error initializing LiteLLM instrumentor: {e}")
|
|
458
|
+
Telemetry().log_exception(e)
|
|
459
|
+
return False
|
|
460
|
+
|
|
461
|
+
|
|
438
462
|
def init_openai_instrumentation() -> bool:
|
|
439
463
|
"""Initialize OpenAI instrumentation.
|
|
440
464
|
|
|
@@ -8,6 +8,7 @@ class CustomInstruments(Enum):
|
|
|
8
8
|
AIOHTTP = "aiohttp"
|
|
9
9
|
COHEREAI = "cohere_ai"
|
|
10
10
|
HTTPX = "httpx"
|
|
11
|
+
LITELLM = "litellm"
|
|
11
12
|
MISTRALAI = "mistral_ai"
|
|
12
13
|
OPENAI = "openai"
|
|
13
14
|
PYDANTIC_AI = "pydantic_ai"
|
|
@@ -127,6 +128,7 @@ class InstrumentSet(Enum):
|
|
|
127
128
|
KAFKA_PYTHON = "kafka_python"
|
|
128
129
|
LANCEDB = "lancedb"
|
|
129
130
|
LANGCHAIN = "langchain"
|
|
131
|
+
LITELLM = "litellm"
|
|
130
132
|
LLAMA_INDEX = "llama_index"
|
|
131
133
|
LOGGING = "logging"
|
|
132
134
|
MARQO = "marqo"
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import time
|
|
3
|
+
from typing import Any, Collection, Dict, Optional
|
|
4
|
+
|
|
5
|
+
from opentelemetry import context as context_api
|
|
6
|
+
from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
|
|
7
|
+
from opentelemetry.instrumentation.utils import _SUPPRESS_INSTRUMENTATION_KEY, unwrap
|
|
8
|
+
from opentelemetry.trace import SpanKind, Tracer, get_tracer
|
|
9
|
+
from opentelemetry.trace.status import Status, StatusCode
|
|
10
|
+
from wrapt import wrap_function_wrapper
|
|
11
|
+
|
|
12
|
+
from netra.instrumentation.litellm.version import __version__
|
|
13
|
+
from netra.instrumentation.litellm.wrappers import (
|
|
14
|
+
acompletion_wrapper,
|
|
15
|
+
aembedding_wrapper,
|
|
16
|
+
aimage_generation_wrapper,
|
|
17
|
+
completion_wrapper,
|
|
18
|
+
embedding_wrapper,
|
|
19
|
+
image_generation_wrapper,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
logger = logging.getLogger(__name__)
|
|
23
|
+
|
|
24
|
+
_instruments = ("litellm >= 1.0.0",)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class LiteLLMInstrumentor(BaseInstrumentor): # type: ignore[misc]
|
|
28
|
+
"""
|
|
29
|
+
Custom LiteLLM instrumentor for Netra SDK with enhanced support for:
|
|
30
|
+
- completion() and acompletion() methods
|
|
31
|
+
- embedding() and aembedding() methods
|
|
32
|
+
- image_generation() and aimage_generation() methods
|
|
33
|
+
- Proper streaming/non-streaming span handling
|
|
34
|
+
- Integration with Netra tracing
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
def instrumentation_dependencies(self) -> Collection[str]:
|
|
38
|
+
return _instruments
|
|
39
|
+
|
|
40
|
+
def _instrument(self, **kwargs): # type: ignore[no-untyped-def]
|
|
41
|
+
"""Instrument LiteLLM methods"""
|
|
42
|
+
tracer_provider = kwargs.get("tracer_provider")
|
|
43
|
+
tracer = get_tracer(__name__, __version__, tracer_provider)
|
|
44
|
+
|
|
45
|
+
logger.debug("Starting LiteLLM instrumentation...")
|
|
46
|
+
|
|
47
|
+
# Force import litellm to ensure it's available for wrapping
|
|
48
|
+
try:
|
|
49
|
+
import litellm
|
|
50
|
+
except ImportError as e:
|
|
51
|
+
logger.error(f"Failed to import litellm: {e}")
|
|
52
|
+
return
|
|
53
|
+
|
|
54
|
+
# Store original functions for uninstrumentation
|
|
55
|
+
self._original_completion = getattr(litellm, "completion", None)
|
|
56
|
+
self._original_acompletion = getattr(litellm, "acompletion", None)
|
|
57
|
+
self._original_embedding = getattr(litellm, "embedding", None)
|
|
58
|
+
self._original_aembedding = getattr(litellm, "aembedding", None)
|
|
59
|
+
self._original_image_generation = getattr(litellm, "image_generation", None)
|
|
60
|
+
self._original_aimage_generation = getattr(litellm, "aimage_generation", None)
|
|
61
|
+
|
|
62
|
+
# Chat completions - use direct monkey patching with proper function wrapping
|
|
63
|
+
if self._original_completion:
|
|
64
|
+
try:
|
|
65
|
+
|
|
66
|
+
def instrumented_completion(*args, **kwargs): # type: ignore[no-untyped-def]
|
|
67
|
+
wrapper = completion_wrapper(tracer)
|
|
68
|
+
return wrapper(self._original_completion, None, args, kwargs)
|
|
69
|
+
|
|
70
|
+
litellm.completion = instrumented_completion
|
|
71
|
+
except Exception as e:
|
|
72
|
+
logger.error(f"Failed to monkey-patch litellm.completion: {e}")
|
|
73
|
+
|
|
74
|
+
if self._original_acompletion:
|
|
75
|
+
try:
|
|
76
|
+
|
|
77
|
+
async def instrumented_acompletion(*args, **kwargs): # type: ignore[no-untyped-def]
|
|
78
|
+
wrapper = acompletion_wrapper(tracer)
|
|
79
|
+
return await wrapper(self._original_acompletion, None, args, kwargs)
|
|
80
|
+
|
|
81
|
+
litellm.acompletion = instrumented_acompletion
|
|
82
|
+
except Exception as e:
|
|
83
|
+
logger.error(f"Failed to monkey-patch litellm.acompletion: {e}")
|
|
84
|
+
|
|
85
|
+
# Embeddings
|
|
86
|
+
if self._original_embedding:
|
|
87
|
+
try:
|
|
88
|
+
|
|
89
|
+
def instrumented_embedding(*args, **kwargs): # type: ignore[no-untyped-def]
|
|
90
|
+
wrapper = embedding_wrapper(tracer)
|
|
91
|
+
return wrapper(self._original_embedding, None, args, kwargs)
|
|
92
|
+
|
|
93
|
+
litellm.embedding = instrumented_embedding
|
|
94
|
+
except Exception as e:
|
|
95
|
+
logger.error(f"Failed to monkey-patch litellm.embedding: {e}")
|
|
96
|
+
|
|
97
|
+
if self._original_aembedding:
|
|
98
|
+
try:
|
|
99
|
+
|
|
100
|
+
async def instrumented_aembedding(*args, **kwargs): # type: ignore[no-untyped-def]
|
|
101
|
+
wrapper = aembedding_wrapper(tracer)
|
|
102
|
+
return await wrapper(self._original_aembedding, None, args, kwargs)
|
|
103
|
+
|
|
104
|
+
litellm.aembedding = instrumented_aembedding
|
|
105
|
+
except Exception as e:
|
|
106
|
+
logger.error(f"Failed to monkey-patch litellm.aembedding: {e}")
|
|
107
|
+
|
|
108
|
+
# Image generation
|
|
109
|
+
if self._original_image_generation:
|
|
110
|
+
try:
|
|
111
|
+
|
|
112
|
+
def instrumented_image_generation(*args, **kwargs): # type: ignore[no-untyped-def]
|
|
113
|
+
wrapper = image_generation_wrapper(tracer)
|
|
114
|
+
return wrapper(self._original_image_generation, None, args, kwargs)
|
|
115
|
+
|
|
116
|
+
litellm.image_generation = instrumented_image_generation
|
|
117
|
+
except Exception as e:
|
|
118
|
+
logger.error(f"Failed to monkey-patch litellm.image_generation: {e}")
|
|
119
|
+
|
|
120
|
+
if self._original_aimage_generation:
|
|
121
|
+
try:
|
|
122
|
+
|
|
123
|
+
async def instrumented_aimage_generation(*args, **kwargs): # type: ignore[no-untyped-def]
|
|
124
|
+
wrapper = aimage_generation_wrapper(tracer)
|
|
125
|
+
return await wrapper(self._original_aimage_generation, None, args, kwargs)
|
|
126
|
+
|
|
127
|
+
litellm.aimage_generation = instrumented_aimage_generation
|
|
128
|
+
except Exception as e:
|
|
129
|
+
logger.error(f"Failed to monkey-patch litellm.aimage_generation: {e}")
|
|
130
|
+
|
|
131
|
+
def _uninstrument(self, **kwargs): # type: ignore[no-untyped-def]
|
|
132
|
+
"""Uninstrument LiteLLM methods"""
|
|
133
|
+
try:
|
|
134
|
+
import litellm
|
|
135
|
+
|
|
136
|
+
# Restore original functions
|
|
137
|
+
if hasattr(self, "_original_completion") and self._original_completion:
|
|
138
|
+
litellm.completion = self._original_completion
|
|
139
|
+
|
|
140
|
+
if hasattr(self, "_original_acompletion") and self._original_acompletion:
|
|
141
|
+
litellm.acompletion = self._original_acompletion
|
|
142
|
+
|
|
143
|
+
if hasattr(self, "_original_embedding") and self._original_embedding:
|
|
144
|
+
litellm.embedding = self._original_embedding
|
|
145
|
+
|
|
146
|
+
if hasattr(self, "_original_aembedding") and self._original_aembedding:
|
|
147
|
+
litellm.aembedding = self._original_aembedding
|
|
148
|
+
|
|
149
|
+
if hasattr(self, "_original_image_generation") and self._original_image_generation:
|
|
150
|
+
litellm.image_generation = self._original_image_generation
|
|
151
|
+
|
|
152
|
+
if hasattr(self, "_original_aimage_generation") and self._original_aimage_generation:
|
|
153
|
+
litellm.aimage_generation = self._original_aimage_generation
|
|
154
|
+
|
|
155
|
+
except ImportError:
|
|
156
|
+
pass
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def should_suppress_instrumentation() -> bool:
|
|
160
|
+
"""Check if instrumentation should be suppressed"""
|
|
161
|
+
return context_api.get_value(_SUPPRESS_INSTRUMENTATION_KEY) is True
|