paid-python 0.0.5a40__py3-none-any.whl → 0.1.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- paid/client.py +339 -233
- paid/logger.py +21 -0
- paid/tracing/__init__.py +4 -4
- paid/tracing/autoinstrumentation.py +6 -3
- paid/tracing/context_manager.py +243 -0
- paid/tracing/distributed_tracing.py +113 -0
- paid/tracing/signal.py +58 -28
- paid/tracing/tracing.py +105 -447
- paid/tracing/wrappers/anthropic/anthropicWrapper.py +11 -72
- paid/tracing/wrappers/bedrock/bedrockWrapper.py +3 -32
- paid/tracing/wrappers/gemini/geminiWrapper.py +10 -46
- paid/tracing/wrappers/langchain/paidLangChainCallback.py +3 -38
- paid/tracing/wrappers/llamaindex/llamaIndexWrapper.py +4 -38
- paid/tracing/wrappers/mistral/mistralWrapper.py +7 -118
- paid/tracing/wrappers/openai/openAiWrapper.py +56 -323
- paid/tracing/wrappers/openai_agents/openaiAgentsHook.py +8 -76
- {paid_python-0.0.5a40.dist-info → paid_python-0.1.1.dist-info}/METADATA +131 -192
- {paid_python-0.0.5a40.dist-info → paid_python-0.1.1.dist-info}/RECORD +20 -17
- {paid_python-0.0.5a40.dist-info → paid_python-0.1.1.dist-info}/LICENSE +0 -0
- {paid_python-0.0.5a40.dist-info → paid_python-0.1.1.dist-info}/WHEEL +0 -0
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
import typing
|
|
2
2
|
|
|
3
|
-
from opentelemetry import trace
|
|
4
3
|
from opentelemetry.trace import Status, StatusCode
|
|
5
4
|
|
|
6
5
|
from paid.tracing.tracing import (
|
|
7
6
|
get_paid_tracer,
|
|
8
|
-
logger,
|
|
9
|
-
paid_external_agent_id_var,
|
|
10
|
-
paid_external_customer_id_var,
|
|
11
|
-
paid_token_var,
|
|
12
7
|
)
|
|
13
8
|
|
|
14
9
|
try:
|
|
@@ -23,54 +18,28 @@ except ImportError:
|
|
|
23
18
|
|
|
24
19
|
|
|
25
20
|
class PaidAnthropic:
|
|
26
|
-
def __init__(self, anthropic_client: Anthropic
|
|
21
|
+
def __init__(self, anthropic_client: Anthropic):
|
|
27
22
|
self.anthropic = anthropic_client
|
|
28
|
-
self.tracer = get_paid_tracer()
|
|
29
|
-
self.optional_tracing = optional_tracing
|
|
30
23
|
|
|
31
24
|
@property
|
|
32
25
|
def messages(self):
|
|
33
|
-
return MessagesWrapper(self.anthropic
|
|
26
|
+
return MessagesWrapper(self.anthropic)
|
|
34
27
|
|
|
35
28
|
|
|
36
29
|
class MessagesWrapper:
|
|
37
|
-
def __init__(self, anthropic_client: Anthropic
|
|
30
|
+
def __init__(self, anthropic_client: Anthropic):
|
|
38
31
|
self.anthropic = anthropic_client
|
|
39
|
-
self.tracer = tracer
|
|
40
|
-
self.optional_tracing = optional_tracing
|
|
41
32
|
|
|
42
33
|
def create(
|
|
43
34
|
self, *, model: ModelParam, messages: typing.Iterable[MessageParam], max_tokens: int, **kwargs
|
|
44
35
|
) -> typing.Any:
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
logger.info(f"{self.__class__.__name__} No tracing, calling Anthropic directly.")
|
|
49
|
-
return self.anthropic.messages.create(model=model, messages=messages, max_tokens=max_tokens, **kwargs)
|
|
50
|
-
raise RuntimeError("No OTEL span found. Make sure to call this method from Paid.trace().")
|
|
51
|
-
|
|
52
|
-
external_customer_id = paid_external_customer_id_var.get()
|
|
53
|
-
external_agent_id = paid_external_agent_id_var.get()
|
|
54
|
-
token = paid_token_var.get()
|
|
55
|
-
|
|
56
|
-
if not (external_customer_id and token):
|
|
57
|
-
if self.optional_tracing:
|
|
58
|
-
logger.info(f"{self.__class__.__name__} No external_customer_id or token, calling Anthropic directly")
|
|
59
|
-
return self.anthropic.messages.create(model=model, messages=messages, max_tokens=max_tokens, **kwargs)
|
|
60
|
-
raise RuntimeError(
|
|
61
|
-
"Missing required tracing information: external_customer_id or token."
|
|
62
|
-
" Make sure to call this method from Paid.trace()."
|
|
63
|
-
)
|
|
64
|
-
|
|
65
|
-
with self.tracer.start_as_current_span("anthropic.messages.create") as span:
|
|
36
|
+
tracer = get_paid_tracer()
|
|
37
|
+
|
|
38
|
+
with tracer.start_as_current_span("anthropic.messages.create") as span:
|
|
66
39
|
attributes = {
|
|
67
40
|
"gen_ai.system": "anthropic",
|
|
68
41
|
"gen_ai.operation.name": "messages",
|
|
69
|
-
"external_customer_id": external_customer_id,
|
|
70
|
-
"token": token,
|
|
71
42
|
}
|
|
72
|
-
if external_agent_id:
|
|
73
|
-
attributes["external_agent_id"] = external_agent_id
|
|
74
43
|
|
|
75
44
|
try:
|
|
76
45
|
response = self.anthropic.messages.create(
|
|
@@ -104,58 +73,28 @@ class MessagesWrapper:
|
|
|
104
73
|
|
|
105
74
|
|
|
106
75
|
class PaidAsyncAnthropic:
|
|
107
|
-
def __init__(self, anthropic_client: AsyncAnthropic
|
|
76
|
+
def __init__(self, anthropic_client: AsyncAnthropic):
|
|
108
77
|
self.anthropic = anthropic_client
|
|
109
|
-
self.tracer = get_paid_tracer()
|
|
110
|
-
self.optional_tracing = optional_tracing
|
|
111
78
|
|
|
112
79
|
@property
|
|
113
80
|
def messages(self):
|
|
114
|
-
return AsyncMessagesWrapper(self.anthropic
|
|
81
|
+
return AsyncMessagesWrapper(self.anthropic)
|
|
115
82
|
|
|
116
83
|
|
|
117
84
|
class AsyncMessagesWrapper:
|
|
118
|
-
def __init__(self, anthropic_client: AsyncAnthropic
|
|
85
|
+
def __init__(self, anthropic_client: AsyncAnthropic):
|
|
119
86
|
self.anthropic = anthropic_client
|
|
120
|
-
self.tracer = tracer
|
|
121
|
-
self.optional_tracing = optional_tracing
|
|
122
87
|
|
|
123
88
|
async def create(
|
|
124
89
|
self, *, model: ModelParam, messages: typing.Iterable[MessageParam], max_tokens: int, **kwargs
|
|
125
90
|
) -> typing.Any:
|
|
126
|
-
|
|
127
|
-
if current_span == trace.INVALID_SPAN:
|
|
128
|
-
if self.optional_tracing:
|
|
129
|
-
logger.info(f"{self.__class__.__name__} No tracing, calling Anthropic directly.")
|
|
130
|
-
return await self.anthropic.messages.create(
|
|
131
|
-
model=model, messages=messages, max_tokens=max_tokens, **kwargs
|
|
132
|
-
)
|
|
133
|
-
raise RuntimeError("No OTEL span found. Make sure to call this method from Paid.trace().")
|
|
134
|
-
|
|
135
|
-
external_customer_id = paid_external_customer_id_var.get()
|
|
136
|
-
external_agent_id = paid_external_agent_id_var.get()
|
|
137
|
-
token = paid_token_var.get()
|
|
138
|
-
|
|
139
|
-
if not (external_customer_id and token):
|
|
140
|
-
if self.optional_tracing:
|
|
141
|
-
logger.info(f"{self.__class__.__name__} No external_customer_id or token, calling Anthropic directly")
|
|
142
|
-
return await self.anthropic.messages.create(
|
|
143
|
-
model=model, messages=messages, max_tokens=max_tokens, **kwargs
|
|
144
|
-
)
|
|
145
|
-
raise RuntimeError(
|
|
146
|
-
"Missing required tracing information: external_customer_id or token."
|
|
147
|
-
" Make sure to call this method from Paid.trace()."
|
|
148
|
-
)
|
|
91
|
+
tracer = get_paid_tracer()
|
|
149
92
|
|
|
150
|
-
with
|
|
93
|
+
with tracer.start_as_current_span("anthropic.messages.create") as span:
|
|
151
94
|
attributes = {
|
|
152
95
|
"gen_ai.system": "anthropic",
|
|
153
96
|
"gen_ai.operation.name": "messages",
|
|
154
|
-
"external_customer_id": external_customer_id,
|
|
155
|
-
"token": token,
|
|
156
97
|
}
|
|
157
|
-
if external_agent_id:
|
|
158
|
-
attributes["external_agent_id"] = external_agent_id
|
|
159
98
|
|
|
160
99
|
try:
|
|
161
100
|
response = await self.anthropic.messages.create(
|
|
@@ -1,53 +1,24 @@
|
|
|
1
1
|
from typing import Any, Dict, List
|
|
2
2
|
|
|
3
|
-
from opentelemetry import trace
|
|
4
3
|
from opentelemetry.trace import Status, StatusCode
|
|
5
4
|
|
|
6
5
|
from paid.tracing.tracing import (
|
|
7
6
|
get_paid_tracer,
|
|
8
|
-
logger,
|
|
9
|
-
paid_external_agent_id_var,
|
|
10
|
-
paid_external_customer_id_var,
|
|
11
|
-
paid_token_var,
|
|
12
7
|
)
|
|
13
8
|
|
|
14
9
|
|
|
15
10
|
class PaidBedrock:
|
|
16
|
-
def __init__(self, bedrock_client: Any
|
|
11
|
+
def __init__(self, bedrock_client: Any):
|
|
17
12
|
self.bedrock_client = bedrock_client
|
|
18
|
-
self.tracer = get_paid_tracer()
|
|
19
|
-
self.optional_tracing = optional_tracing
|
|
20
13
|
|
|
21
14
|
def converse(self, *, modelId: str, messages: List[Dict[str, Any]], **kwargs) -> Dict[str, Any]:
|
|
22
|
-
|
|
23
|
-
if current_span == trace.INVALID_SPAN:
|
|
24
|
-
if self.optional_tracing:
|
|
25
|
-
logger.info(f"{self.__class__.__name__} No tracing, calling Bedrock directly.")
|
|
26
|
-
return self.bedrock_client.converse(modelId=modelId, messages=messages, **kwargs)
|
|
27
|
-
raise RuntimeError("No OTEL span found. Make sure to call this method from Paid.trace().")
|
|
15
|
+
tracer = get_paid_tracer()
|
|
28
16
|
|
|
29
|
-
|
|
30
|
-
external_agent_id = paid_external_agent_id_var.get()
|
|
31
|
-
token = paid_token_var.get()
|
|
32
|
-
|
|
33
|
-
if not (external_customer_id and token):
|
|
34
|
-
if self.optional_tracing:
|
|
35
|
-
logger.info(f"{self.__class__.__name__} No external_customer_id or token, calling Bedrock directly")
|
|
36
|
-
return self.bedrock_client.converse(modelId=modelId, messages=messages, **kwargs)
|
|
37
|
-
raise RuntimeError(
|
|
38
|
-
"Missing required tracing information: external_customer_id or token."
|
|
39
|
-
" Make sure to call this method from Paid.trace()."
|
|
40
|
-
)
|
|
41
|
-
|
|
42
|
-
with self.tracer.start_as_current_span("bedrock.converse") as span:
|
|
17
|
+
with tracer.start_as_current_span("bedrock.converse") as span:
|
|
43
18
|
attributes = {
|
|
44
19
|
"gen_ai.system": "bedrock",
|
|
45
20
|
"gen_ai.operation.name": "converse",
|
|
46
|
-
"external_customer_id": external_customer_id,
|
|
47
|
-
"token": token,
|
|
48
21
|
}
|
|
49
|
-
if external_agent_id:
|
|
50
|
-
attributes["external_agent_id"] = external_agent_id
|
|
51
22
|
|
|
52
23
|
try:
|
|
53
24
|
response = self.bedrock_client.converse(modelId=modelId, messages=messages, **kwargs)
|
|
@@ -6,16 +6,10 @@ https://github.com/paid-ai/sdk-wrapper-codegen
|
|
|
6
6
|
|
|
7
7
|
from typing import Union
|
|
8
8
|
|
|
9
|
-
from opentelemetry import trace
|
|
10
9
|
from opentelemetry.trace import Status, StatusCode
|
|
11
10
|
|
|
12
|
-
from paid.
|
|
13
|
-
|
|
14
|
-
logger,
|
|
15
|
-
paid_external_agent_id_var,
|
|
16
|
-
paid_external_customer_id_var,
|
|
17
|
-
paid_token_var,
|
|
18
|
-
)
|
|
11
|
+
from paid.logger import logger
|
|
12
|
+
from paid.tracing.tracing import get_paid_tracer
|
|
19
13
|
|
|
20
14
|
try:
|
|
21
15
|
from google import genai
|
|
@@ -30,65 +24,35 @@ except ImportError:
|
|
|
30
24
|
class PaidGemini:
|
|
31
25
|
"""OpenTelemetry instrumented wrapper for Gemini Python SDK SDK."""
|
|
32
26
|
|
|
33
|
-
def __init__(self, original_client: genai.Client
|
|
27
|
+
def __init__(self, original_client: genai.Client):
|
|
34
28
|
self._client = original_client
|
|
35
|
-
self.tracer = get_paid_tracer()
|
|
36
|
-
self.optional_tracing = optional_tracing
|
|
37
29
|
|
|
38
30
|
@property
|
|
39
31
|
def models(self):
|
|
40
32
|
"""Access models with OTEL instrumentation."""
|
|
41
|
-
return ModelsWrapper(self._client
|
|
33
|
+
return ModelsWrapper(self._client)
|
|
42
34
|
|
|
43
35
|
|
|
44
36
|
class ModelsWrapper:
|
|
45
37
|
"""Wrapper for models with OTEL instrumentation."""
|
|
46
38
|
|
|
47
|
-
def __init__(self, original_client: genai.Client
|
|
39
|
+
def __init__(self, original_client: genai.Client):
|
|
48
40
|
self._client = original_client
|
|
49
|
-
self.tracer = tracer
|
|
50
|
-
self.optional_tracing = optional_tracing
|
|
51
41
|
|
|
52
42
|
def generate_content(self, **kwargs) -> GenerateContentResponse:
|
|
53
43
|
"""GenerateContentResponse method with OTEL instrumentation."""
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
if self.optional_tracing:
|
|
58
|
-
logger.info(f"{self.__class__.__name__} No tracing wasn't enabled, only calling the client.")
|
|
59
|
-
return self._client.models.generate_content(**kwargs)
|
|
60
|
-
raise RuntimeError("No OTEL span found. Make sure to call this method from Paid.trace().")
|
|
61
|
-
|
|
62
|
-
external_customer_id = paid_external_customer_id_var.get()
|
|
63
|
-
external_agent_id = paid_external_agent_id_var.get()
|
|
64
|
-
token = paid_token_var.get()
|
|
65
|
-
|
|
66
|
-
if not (external_customer_id and token):
|
|
67
|
-
if self.optional_tracing:
|
|
68
|
-
logger.info(
|
|
69
|
-
f"{self.__class__.__name__} No external_customer_id or token, so no tracing, only calling the client."
|
|
70
|
-
)
|
|
71
|
-
return self._client.models.generate_content(**kwargs)
|
|
72
|
-
raise RuntimeError(
|
|
73
|
-
"Missing required tracing information: external_customer_id or token."
|
|
74
|
-
" Make sure to call this method from Paid.trace()."
|
|
75
|
-
)
|
|
76
|
-
|
|
77
|
-
with self.tracer.start_as_current_span("gemini.models.generate_content") as span:
|
|
44
|
+
tracer = get_paid_tracer()
|
|
45
|
+
|
|
46
|
+
with tracer.start_as_current_span("gemini.models.generate_content") as span:
|
|
78
47
|
try:
|
|
79
48
|
# Execute the original method
|
|
80
49
|
response = self._client.models.generate_content(**kwargs)
|
|
81
50
|
if response.usage_metadata is None:
|
|
82
|
-
|
|
83
|
-
|
|
51
|
+
logger.error("should be unreachable: response.usage_metadata is None, cannot extract usage data")
|
|
52
|
+
return response
|
|
84
53
|
|
|
85
54
|
# Set OTEL attributes (best-effort)
|
|
86
55
|
attributes: dict[str, Union[str, int]] = {}
|
|
87
|
-
attributes["external_customer_id"] = external_customer_id
|
|
88
|
-
attributes["token"] = token
|
|
89
|
-
if external_agent_id:
|
|
90
|
-
attributes["external_agent_id"] = external_agent_id
|
|
91
|
-
|
|
92
56
|
attributes["gen_ai.system"] = "gemini"
|
|
93
57
|
attributes["gen_ai.operation.name"] = "generate_content"
|
|
94
58
|
try:
|
|
@@ -2,10 +2,9 @@ import time
|
|
|
2
2
|
from typing import Any, Dict, List, Optional, Sequence
|
|
3
3
|
from uuid import UUID
|
|
4
4
|
|
|
5
|
-
from opentelemetry import trace
|
|
6
5
|
from opentelemetry.trace import Status, StatusCode
|
|
7
6
|
|
|
8
|
-
from paid.tracing.tracing import get_paid_tracer
|
|
7
|
+
from paid.tracing.tracing import get_paid_tracer
|
|
9
8
|
|
|
10
9
|
try:
|
|
11
10
|
from langchain_core.callbacks import BaseCallbackHandler # type: ignore
|
|
@@ -44,7 +43,6 @@ class PaidLangChainCallback(BaseCallbackHandler):
|
|
|
44
43
|
def __init__(self):
|
|
45
44
|
"""Initialize the callback handler."""
|
|
46
45
|
super().__init__()
|
|
47
|
-
self.tracer = get_paid_tracer()
|
|
48
46
|
self._spans: Dict[str, Any] = {} # Track active spans by run_id
|
|
49
47
|
self._start_times: Dict[str, float] = {} # Track start times
|
|
50
48
|
|
|
@@ -56,27 +54,10 @@ class PaidLangChainCallback(BaseCallbackHandler):
|
|
|
56
54
|
|
|
57
55
|
def _start_span(self, run_id: UUID, span_name: str, **attributes: Any) -> Optional[Any]:
|
|
58
56
|
"""Start a new span and store it."""
|
|
59
|
-
|
|
60
|
-
current_span = trace.get_current_span()
|
|
61
|
-
if current_span == trace.INVALID_SPAN:
|
|
62
|
-
logger.info(f"{self.__class__.__name__} No active span found - LangChain operations will not be traced")
|
|
63
|
-
return None
|
|
64
|
-
|
|
65
|
-
# Get context variables
|
|
66
|
-
external_customer_id = paid_external_customer_id_var.get()
|
|
67
|
-
token = paid_token_var.get()
|
|
68
|
-
|
|
69
|
-
# Check if required context is available
|
|
70
|
-
if not (external_customer_id and token):
|
|
71
|
-
logger.info(
|
|
72
|
-
f"{self.__class__.__name__} Missing required tracing information "
|
|
73
|
-
f"(external_customer_id={bool(external_customer_id)}, token={bool(token)}) - "
|
|
74
|
-
f"LangChain operation '{span_name}' will not be traced"
|
|
75
|
-
)
|
|
76
|
-
return None
|
|
57
|
+
tracer = get_paid_tracer()
|
|
77
58
|
|
|
78
59
|
# Create child span
|
|
79
|
-
span =
|
|
60
|
+
span = tracer.start_span(span_name)
|
|
80
61
|
|
|
81
62
|
# Set common attributes
|
|
82
63
|
base_attributes = {
|
|
@@ -84,11 +65,6 @@ class PaidLangChainCallback(BaseCallbackHandler):
|
|
|
84
65
|
"langchain.run_id": str(run_id),
|
|
85
66
|
}
|
|
86
67
|
|
|
87
|
-
if external_customer_id:
|
|
88
|
-
base_attributes["external_customer_id"] = external_customer_id
|
|
89
|
-
if token:
|
|
90
|
-
base_attributes["token"] = token
|
|
91
|
-
|
|
92
68
|
# Add custom attributes
|
|
93
69
|
base_attributes.update(attributes)
|
|
94
70
|
span.set_attributes(base_attributes)
|
|
@@ -97,8 +73,6 @@ class PaidLangChainCallback(BaseCallbackHandler):
|
|
|
97
73
|
self._spans[str(run_id)] = span
|
|
98
74
|
self._start_times[str(run_id)] = time.time()
|
|
99
75
|
|
|
100
|
-
logger.info(f"{self.__class__.__name__} Started span '{span_name}' for run_id={run_id}")
|
|
101
|
-
|
|
102
76
|
return span
|
|
103
77
|
|
|
104
78
|
def _end_span(self, run_id: UUID, error: Optional[BaseException] = None, **attributes):
|
|
@@ -107,9 +81,6 @@ class PaidLangChainCallback(BaseCallbackHandler):
|
|
|
107
81
|
span = self._spans.get(span_key)
|
|
108
82
|
|
|
109
83
|
if not span:
|
|
110
|
-
logger.info(
|
|
111
|
-
f"{self.__class__.__name__} No span found for run_id={run_id} - span was not created or already ended"
|
|
112
|
-
)
|
|
113
84
|
return
|
|
114
85
|
|
|
115
86
|
try:
|
|
@@ -126,10 +97,8 @@ class PaidLangChainCallback(BaseCallbackHandler):
|
|
|
126
97
|
if error:
|
|
127
98
|
span.set_status(Status(StatusCode.ERROR, str(error)))
|
|
128
99
|
span.record_exception(error)
|
|
129
|
-
logger.info(f"{self.__class__.__name__} Ended span with error for run_id={run_id}: {error}")
|
|
130
100
|
else:
|
|
131
101
|
span.set_status(Status(StatusCode.OK))
|
|
132
|
-
logger.info(f"{self.__class__.__name__} Successfully ended span for run_id={run_id}")
|
|
133
102
|
|
|
134
103
|
finally:
|
|
135
104
|
span.end()
|
|
@@ -149,14 +118,10 @@ class PaidLangChainCallback(BaseCallbackHandler):
|
|
|
149
118
|
) -> Any:
|
|
150
119
|
"""Called when LLM starts running."""
|
|
151
120
|
if not metadata:
|
|
152
|
-
logger.info(f"{self.__class__.__name__} No metadata provided for LLM start (run_id={run_id})")
|
|
153
121
|
return None
|
|
154
122
|
|
|
155
123
|
model_type = metadata.get("ls_model_type", "unknown")
|
|
156
124
|
model_name = metadata.get("ls_model_name", "unknown")
|
|
157
|
-
logger.info(
|
|
158
|
-
f"{self.__class__.__name__} LLM start - model_type={model_type}, model_name={model_name}, run_id={run_id}"
|
|
159
|
-
)
|
|
160
125
|
span_name = self._get_span_name(f"trace.{model_type}", model_name)
|
|
161
126
|
|
|
162
127
|
attributes = {
|
|
@@ -1,15 +1,8 @@
|
|
|
1
1
|
from typing import Any, Sequence, cast
|
|
2
2
|
|
|
3
|
-
from opentelemetry import trace
|
|
4
3
|
from opentelemetry.trace import Status, StatusCode
|
|
5
4
|
|
|
6
|
-
from paid.tracing.tracing import
|
|
7
|
-
get_paid_tracer,
|
|
8
|
-
logger,
|
|
9
|
-
paid_external_agent_id_var,
|
|
10
|
-
paid_external_customer_id_var,
|
|
11
|
-
paid_token_var,
|
|
12
|
-
)
|
|
5
|
+
from paid.tracing.tracing import get_paid_tracer
|
|
13
6
|
|
|
14
7
|
try:
|
|
15
8
|
from llama_index.core.llms import ChatMessage, ChatResponse
|
|
@@ -23,44 +16,17 @@ except ImportError:
|
|
|
23
16
|
|
|
24
17
|
|
|
25
18
|
class PaidLlamaIndexOpenAI:
|
|
26
|
-
def __init__(self, openai_client: OpenAI
|
|
19
|
+
def __init__(self, openai_client: OpenAI):
|
|
27
20
|
self.openai = openai_client
|
|
28
|
-
self.tracer = get_paid_tracer()
|
|
29
|
-
self.optional_tracing = optional_tracing
|
|
30
21
|
|
|
31
22
|
def chat(self, messages: Sequence[ChatMessage], **kwargs: Any) -> ChatResponse:
|
|
32
|
-
|
|
33
|
-
current_span = trace.get_current_span()
|
|
34
|
-
if current_span == trace.INVALID_SPAN:
|
|
35
|
-
if self.optional_tracing:
|
|
36
|
-
logger.info(f"{self.__class__.__name__} No tracing, calling LlamaIndex OpenAI directly.")
|
|
37
|
-
return self.openai.chat(messages=messages, **kwargs)
|
|
38
|
-
raise RuntimeError("No OTEL span found. Make sure to call this method from Paid.trace().")
|
|
23
|
+
tracer = get_paid_tracer()
|
|
39
24
|
|
|
40
|
-
|
|
41
|
-
external_agent_id = paid_external_agent_id_var.get()
|
|
42
|
-
token = paid_token_var.get()
|
|
43
|
-
|
|
44
|
-
if not (external_customer_id and token):
|
|
45
|
-
if self.optional_tracing:
|
|
46
|
-
logger.info(
|
|
47
|
-
f"{self.__class__.__name__} No external_customer_id or token, calling LlamaIndex OpenAI directly"
|
|
48
|
-
)
|
|
49
|
-
return self.openai.chat(messages=messages, **kwargs)
|
|
50
|
-
raise RuntimeError(
|
|
51
|
-
"Missing required tracing information: external_customer_id or token."
|
|
52
|
-
" Make sure to call this method from Paid.trace()."
|
|
53
|
-
)
|
|
54
|
-
|
|
55
|
-
with self.tracer.start_as_current_span("openai.chat") as span:
|
|
25
|
+
with tracer.start_as_current_span("openai.chat") as span:
|
|
56
26
|
attributes = {
|
|
57
27
|
"gen_ai.system": "openai",
|
|
58
28
|
"gen_ai.operation.name": "chat",
|
|
59
|
-
"external_customer_id": external_customer_id,
|
|
60
|
-
"token": token,
|
|
61
29
|
}
|
|
62
|
-
if external_agent_id:
|
|
63
|
-
attributes["external_agent_id"] = external_agent_id
|
|
64
30
|
span.set_attributes(attributes)
|
|
65
31
|
|
|
66
32
|
try:
|
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
from typing import Any, Dict, List, Optional, Union
|
|
2
2
|
|
|
3
|
-
from opentelemetry import trace
|
|
4
3
|
from opentelemetry.trace import Status, StatusCode
|
|
5
4
|
|
|
6
5
|
from paid.tracing.tracing import (
|
|
7
6
|
get_paid_tracer,
|
|
8
|
-
logger,
|
|
9
|
-
paid_external_agent_id_var,
|
|
10
|
-
paid_external_customer_id_var,
|
|
11
|
-
paid_token_var,
|
|
12
7
|
)
|
|
13
8
|
|
|
14
9
|
try:
|
|
@@ -22,21 +17,17 @@ except ImportError:
|
|
|
22
17
|
|
|
23
18
|
|
|
24
19
|
class PaidMistral:
|
|
25
|
-
def __init__(self, mistral_client: Mistral
|
|
20
|
+
def __init__(self, mistral_client: Mistral):
|
|
26
21
|
self.mistral = mistral_client
|
|
27
|
-
self.tracer = get_paid_tracer()
|
|
28
|
-
self.optional_tracing = optional_tracing
|
|
29
22
|
|
|
30
23
|
@property
|
|
31
24
|
def ocr(self):
|
|
32
|
-
return OCRWrapper(self.mistral
|
|
25
|
+
return OCRWrapper(self.mistral)
|
|
33
26
|
|
|
34
27
|
|
|
35
28
|
class OCRWrapper:
|
|
36
|
-
def __init__(self, mistral_client: Mistral
|
|
29
|
+
def __init__(self, mistral_client: Mistral):
|
|
37
30
|
self.mistral = mistral_client
|
|
38
|
-
self.tracer = tracer
|
|
39
|
-
self.optional_tracing = optional_tracing
|
|
40
31
|
|
|
41
32
|
def process(
|
|
42
33
|
self,
|
|
@@ -75,56 +66,9 @@ class OCRWrapper:
|
|
|
75
66
|
timeout_ms: Override default request timeout in milliseconds
|
|
76
67
|
http_headers: Additional headers to set or replace on requests
|
|
77
68
|
"""
|
|
78
|
-
|
|
79
|
-
current_span = trace.get_current_span()
|
|
80
|
-
if current_span == trace.INVALID_SPAN:
|
|
81
|
-
if self.optional_tracing:
|
|
82
|
-
logger.info(f"{self.__class__.__name__} No tracing, calling Mistral directly.")
|
|
83
|
-
return self.mistral.ocr.process(
|
|
84
|
-
model=model,
|
|
85
|
-
document=document,
|
|
86
|
-
id=id,
|
|
87
|
-
pages=pages,
|
|
88
|
-
include_image_base64=include_image_base64,
|
|
89
|
-
image_limit=image_limit,
|
|
90
|
-
image_min_size=image_min_size,
|
|
91
|
-
bbox_annotation_format=bbox_annotation_format,
|
|
92
|
-
document_annotation_format=document_annotation_format,
|
|
93
|
-
retries=retries,
|
|
94
|
-
server_url=server_url,
|
|
95
|
-
timeout_ms=timeout_ms,
|
|
96
|
-
http_headers=http_headers,
|
|
97
|
-
)
|
|
98
|
-
raise RuntimeError("No OTEL span found. Make sure to call this method from Paid.trace().")
|
|
99
|
-
|
|
100
|
-
external_customer_id = paid_external_customer_id_var.get()
|
|
101
|
-
external_agent_id = paid_external_agent_id_var.get()
|
|
102
|
-
token = paid_token_var.get()
|
|
103
|
-
|
|
104
|
-
if not (external_customer_id and token):
|
|
105
|
-
if self.optional_tracing:
|
|
106
|
-
logger.info(f"{self.__class__.__name__} No external_customer_id or token, calling Mistral directly")
|
|
107
|
-
return self.mistral.ocr.process(
|
|
108
|
-
model=model,
|
|
109
|
-
document=document,
|
|
110
|
-
id=id,
|
|
111
|
-
pages=pages,
|
|
112
|
-
include_image_base64=include_image_base64,
|
|
113
|
-
image_limit=image_limit,
|
|
114
|
-
image_min_size=image_min_size,
|
|
115
|
-
bbox_annotation_format=bbox_annotation_format,
|
|
116
|
-
document_annotation_format=document_annotation_format,
|
|
117
|
-
retries=retries,
|
|
118
|
-
server_url=server_url,
|
|
119
|
-
timeout_ms=timeout_ms,
|
|
120
|
-
http_headers=http_headers,
|
|
121
|
-
)
|
|
122
|
-
raise RuntimeError(
|
|
123
|
-
"Missing required tracing information: external_customer_id or token."
|
|
124
|
-
" Make sure to call this method from Paid.trace()."
|
|
125
|
-
)
|
|
69
|
+
tracer = get_paid_tracer()
|
|
126
70
|
|
|
127
|
-
with
|
|
71
|
+
with tracer.start_as_current_span("mistral.ocr.process") as span:
|
|
128
72
|
attributes = {
|
|
129
73
|
"gen_ai.system": "mistral",
|
|
130
74
|
"gen_ai.operation.name": "ocr",
|
|
@@ -132,10 +76,6 @@ class OCRWrapper:
|
|
|
132
76
|
if bbox_annotation_format or document_annotation_format:
|
|
133
77
|
attributes["gen_ai.ocr.annotated"] = "true"
|
|
134
78
|
|
|
135
|
-
attributes["external_customer_id"] = external_customer_id
|
|
136
|
-
attributes["token"] = token
|
|
137
|
-
if external_agent_id:
|
|
138
|
-
attributes["external_agent_id"] = external_agent_id
|
|
139
79
|
span.set_attributes(attributes)
|
|
140
80
|
|
|
141
81
|
try:
|
|
@@ -212,56 +152,9 @@ class OCRWrapper:
|
|
|
212
152
|
timeout_ms: Override default request timeout in milliseconds
|
|
213
153
|
http_headers: Additional headers to set or replace on requests
|
|
214
154
|
"""
|
|
215
|
-
|
|
216
|
-
current_span = trace.get_current_span()
|
|
217
|
-
if current_span == trace.INVALID_SPAN:
|
|
218
|
-
if self.optional_tracing:
|
|
219
|
-
logger.info(f"{self.__class__.__name__} No tracing, calling Mistral directly.")
|
|
220
|
-
return await self.mistral.ocr.process_async(
|
|
221
|
-
model=model,
|
|
222
|
-
document=document,
|
|
223
|
-
id=id,
|
|
224
|
-
pages=pages,
|
|
225
|
-
include_image_base64=include_image_base64,
|
|
226
|
-
image_limit=image_limit,
|
|
227
|
-
image_min_size=image_min_size,
|
|
228
|
-
bbox_annotation_format=bbox_annotation_format,
|
|
229
|
-
document_annotation_format=document_annotation_format,
|
|
230
|
-
retries=retries,
|
|
231
|
-
server_url=server_url,
|
|
232
|
-
timeout_ms=timeout_ms,
|
|
233
|
-
http_headers=http_headers,
|
|
234
|
-
)
|
|
235
|
-
raise RuntimeError("No OTEL span found. Make sure to call this method from Paid.trace().")
|
|
236
|
-
|
|
237
|
-
external_customer_id = paid_external_customer_id_var.get()
|
|
238
|
-
external_agent_id = paid_external_agent_id_var.get()
|
|
239
|
-
token = paid_token_var.get()
|
|
240
|
-
|
|
241
|
-
if not (external_customer_id and token):
|
|
242
|
-
if self.optional_tracing:
|
|
243
|
-
logger.info(f"{self.__class__.__name__} No external_customer_id or token, calling Mistral directly")
|
|
244
|
-
return await self.mistral.ocr.process_async(
|
|
245
|
-
model=model,
|
|
246
|
-
document=document,
|
|
247
|
-
id=id,
|
|
248
|
-
pages=pages,
|
|
249
|
-
include_image_base64=include_image_base64,
|
|
250
|
-
image_limit=image_limit,
|
|
251
|
-
image_min_size=image_min_size,
|
|
252
|
-
bbox_annotation_format=bbox_annotation_format,
|
|
253
|
-
document_annotation_format=document_annotation_format,
|
|
254
|
-
retries=retries,
|
|
255
|
-
server_url=server_url,
|
|
256
|
-
timeout_ms=timeout_ms,
|
|
257
|
-
http_headers=http_headers,
|
|
258
|
-
)
|
|
259
|
-
raise RuntimeError(
|
|
260
|
-
"Missing required tracing information: external_customer_id or token."
|
|
261
|
-
" Make sure to call this method from Paid.trace()."
|
|
262
|
-
)
|
|
155
|
+
tracer = get_paid_tracer()
|
|
263
156
|
|
|
264
|
-
with
|
|
157
|
+
with tracer.start_as_current_span("mistral.ocr.process_async") as span:
|
|
265
158
|
attributes = {
|
|
266
159
|
"gen_ai.system": "mistral",
|
|
267
160
|
"gen_ai.operation.name": "ocr",
|
|
@@ -269,10 +162,6 @@ class OCRWrapper:
|
|
|
269
162
|
if bbox_annotation_format or document_annotation_format:
|
|
270
163
|
attributes["gen_ai.ocr.annotated"] = "true"
|
|
271
164
|
|
|
272
|
-
attributes["external_customer_id"] = external_customer_id
|
|
273
|
-
attributes["token"] = token
|
|
274
|
-
if external_agent_id:
|
|
275
|
-
attributes["external_agent_id"] = external_agent_id
|
|
276
165
|
span.set_attributes(attributes)
|
|
277
166
|
|
|
278
167
|
try:
|