paid-python 0.4.0__tar.gz → 0.4.1a0__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.
- {paid_python-0.4.0 → paid_python-0.4.1a0}/PKG-INFO +1 -1
- {paid_python-0.4.0 → paid_python-0.4.1a0}/pyproject.toml +12 -5
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/client.py +23 -2
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/tracing/__init__.py +1 -1
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/tracing/autoinstrumentation.py +1 -2
- {paid_python-0.4.0/src/paid/_vendor → paid_python-0.4.1a0/vendor/patched-instrumentation-openllmetry/packages/opentelemetry-instrumentation-openai}/opentelemetry/instrumentation/openai/__init__.py +6 -6
- {paid_python-0.4.0/src/paid/_vendor → paid_python-0.4.1a0/vendor/patched-instrumentation-openllmetry/packages/opentelemetry-instrumentation-openai}/opentelemetry/instrumentation/openai/shared/__init__.py +2 -2
- paid_python-0.4.1a0/vendor/patched-instrumentation-openllmetry/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/shared/audio_wrappers.py +247 -0
- {paid_python-0.4.0/src/paid/_vendor → paid_python-0.4.1a0/vendor/patched-instrumentation-openllmetry/packages/opentelemetry-instrumentation-openai}/opentelemetry/instrumentation/openai/shared/chat_wrappers.py +5 -5
- {paid_python-0.4.0/src/paid/_vendor → paid_python-0.4.1a0/vendor/patched-instrumentation-openllmetry/packages/opentelemetry-instrumentation-openai}/opentelemetry/instrumentation/openai/shared/completion_wrappers.py +5 -5
- {paid_python-0.4.0/src/paid/_vendor → paid_python-0.4.1a0/vendor/patched-instrumentation-openllmetry/packages/opentelemetry-instrumentation-openai}/opentelemetry/instrumentation/openai/shared/embeddings_wrappers.py +5 -5
- {paid_python-0.4.0/src/paid/_vendor → paid_python-0.4.1a0/vendor/patched-instrumentation-openllmetry/packages/opentelemetry-instrumentation-openai}/opentelemetry/instrumentation/openai/shared/event_emitter.py +2 -2
- {paid_python-0.4.0/src/paid/_vendor → paid_python-0.4.1a0/vendor/patched-instrumentation-openllmetry/packages/opentelemetry-instrumentation-openai}/opentelemetry/instrumentation/openai/shared/image_gen_wrappers.py +3 -3
- {paid_python-0.4.0/src/paid/_vendor → paid_python-0.4.1a0/vendor/patched-instrumentation-openllmetry/packages/opentelemetry-instrumentation-openai}/opentelemetry/instrumentation/openai/utils.py +24 -1
- {paid_python-0.4.0/src/paid/_vendor → paid_python-0.4.1a0/vendor/patched-instrumentation-openllmetry/packages/opentelemetry-instrumentation-openai}/opentelemetry/instrumentation/openai/v0/__init__.py +6 -6
- {paid_python-0.4.0/src/paid/_vendor → paid_python-0.4.1a0/vendor/patched-instrumentation-openllmetry/packages/opentelemetry-instrumentation-openai}/opentelemetry/instrumentation/openai/v1/__init__.py +45 -9
- {paid_python-0.4.0/src/paid/_vendor → paid_python-0.4.1a0/vendor/patched-instrumentation-openllmetry/packages/opentelemetry-instrumentation-openai}/opentelemetry/instrumentation/openai/v1/assistant_wrappers.py +6 -6
- {paid_python-0.4.0/src/paid/_vendor → paid_python-0.4.1a0/vendor/patched-instrumentation-openllmetry/packages/opentelemetry-instrumentation-openai}/opentelemetry/instrumentation/openai/v1/event_handler_wrapper.py +4 -4
- {paid_python-0.4.0/src/paid/_vendor → paid_python-0.4.1a0/vendor/patched-instrumentation-openllmetry/packages/opentelemetry-instrumentation-openai}/opentelemetry/instrumentation/openai/v1/responses_wrappers.py +186 -69
- paid_python-0.4.1a0/vendor/patched-instrumentation-openllmetry/packages/opentelemetry-instrumentation-openai/opentelemetry/instrumentation/openai/version.py +1 -0
- paid_python-0.4.0/src/paid/_vendor/__init__.py +0 -0
- paid_python-0.4.0/src/paid/_vendor/opentelemetry/__init__.py +0 -0
- paid_python-0.4.0/src/paid/_vendor/opentelemetry/instrumentation/__init__.py +0 -0
- paid_python-0.4.0/src/paid/_vendor/opentelemetry/instrumentation/openai/version.py +0 -1
- {paid_python-0.4.0 → paid_python-0.4.1a0}/LICENSE +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/README.md +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/__init__.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/agents/__init__.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/agents/client.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/agents/raw_client.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/contacts/__init__.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/contacts/client.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/contacts/raw_client.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/core/__init__.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/core/api_error.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/core/client_wrapper.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/core/datetime_utils.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/core/file.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/core/force_multipart.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/core/http_client.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/core/http_response.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/core/jsonable_encoder.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/core/pydantic_utilities.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/core/query_encoder.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/core/remove_none_from_dict.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/core/request_options.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/core/serialization.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/customers/__init__.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/customers/client.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/customers/raw_client.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/environment.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/errors/__init__.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/errors/bad_request_error.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/errors/forbidden_error.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/errors/not_found_error.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/logger.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/orders/__init__.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/orders/client.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/orders/lines/__init__.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/orders/lines/client.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/orders/lines/raw_client.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/orders/raw_client.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/py.typed +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/tracing/context_data.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/tracing/context_manager.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/tracing/distributed_tracing.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/tracing/signal.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/tracing/tracing.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/tracing/wrappers/__init__.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/tracing/wrappers/anthropic/__init__.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/tracing/wrappers/anthropic/anthropicWrapper.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/tracing/wrappers/bedrock/__init__.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/tracing/wrappers/bedrock/bedrockWrapper.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/tracing/wrappers/gemini/__init__.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/tracing/wrappers/gemini/geminiWrapper.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/tracing/wrappers/langchain/__init__.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/tracing/wrappers/langchain/paidLangChainCallback.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/tracing/wrappers/llamaindex/__init__.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/tracing/wrappers/llamaindex/llamaIndexWrapper.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/tracing/wrappers/mistral/__init__.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/tracing/wrappers/mistral/mistralWrapper.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/tracing/wrappers/openai/__init__.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/tracing/wrappers/openai/openAiWrapper.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/tracing/wrappers/openai_agents/__init__.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/tracing/wrappers/openai_agents/openaiAgentsHook.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/tracing/wrappers/utils.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/types/__init__.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/types/address.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/types/agent.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/types/agent_attribute.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/types/agent_price_point.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/types/agent_price_point_tiers.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/types/agent_update.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/types/api_error.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/types/billing_frequency.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/types/charge_type.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/types/contact.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/types/cost_amount.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/types/cost_trace.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/types/cost_traces_response.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/types/creation_source.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/types/creation_state.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/types/customer.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/types/customer_update.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/types/entitlement_usage.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/types/error.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/types/order.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/types/order_line.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/types/order_line_attribute.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/types/order_line_attribute_create.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/types/order_line_attribute_pricing.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/types/order_line_create.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/types/pagination_meta.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/types/price_point.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/types/pricing.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/types/pricing_model_type.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/types/salutation.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/types/signal.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/types/tax_exempt_status.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/types/tier.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/usage/__init__.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/usage/client.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/usage/raw_client.py +0 -0
- {paid_python-0.4.0 → paid_python-0.4.1a0}/src/paid/version.py +0 -0
- {paid_python-0.4.0/src/paid/_vendor → paid_python-0.4.1a0/vendor/patched-instrumentation-openllmetry/packages/opentelemetry-instrumentation-openai}/opentelemetry/instrumentation/openai/shared/config.py +0 -0
- {paid_python-0.4.0/src/paid/_vendor → paid_python-0.4.1a0/vendor/patched-instrumentation-openllmetry/packages/opentelemetry-instrumentation-openai}/opentelemetry/instrumentation/openai/shared/event_models.py +0 -0
- {paid_python-0.4.0/src/paid/_vendor → paid_python-0.4.1a0/vendor/patched-instrumentation-openllmetry/packages/opentelemetry-instrumentation-openai}/opentelemetry/instrumentation/openai/shared/span_utils.py +0 -0
|
@@ -3,7 +3,7 @@ name = "paid-python"
|
|
|
3
3
|
|
|
4
4
|
[tool.poetry]
|
|
5
5
|
name = "paid-python"
|
|
6
|
-
version = "0.4.
|
|
6
|
+
version = "0.4.1-alpha0"
|
|
7
7
|
description = ""
|
|
8
8
|
readme = "README.md"
|
|
9
9
|
authors = []
|
|
@@ -26,7 +26,8 @@ classifiers = [
|
|
|
26
26
|
"Typing :: Typed"
|
|
27
27
|
]
|
|
28
28
|
packages = [
|
|
29
|
-
{ include = "paid", from = "src"}
|
|
29
|
+
{ include = "paid", from = "src"},
|
|
30
|
+
{ include = "opentelemetry", from = "vendor/patched-instrumentation-openllmetry/packages/opentelemetry-instrumentation-openai" },
|
|
30
31
|
]
|
|
31
32
|
|
|
32
33
|
[project.urls]
|
|
@@ -44,7 +45,7 @@ opentelemetry-exporter-otlp-proto-http = ">=1.23.0"
|
|
|
44
45
|
mutagen = ">=1.47.0"
|
|
45
46
|
python-dotenv = ">=0.15.0"
|
|
46
47
|
opentelemetry-instrumentation-anthropic = ">=0.47.0"
|
|
47
|
-
# opentelemetry-instrumentation-openai is vendored from
|
|
48
|
+
# opentelemetry-instrumentation-openai is vendored from git a submodule under vendor/patched-instrumentation-openllmetry
|
|
48
49
|
openinference-instrumentation-langchain = ">=0.1.55"
|
|
49
50
|
openinference-instrumentation-openai-agents = ">=1.0.0"
|
|
50
51
|
openinference-instrumentation-bedrock = ">=0.1.0"
|
|
@@ -71,9 +72,15 @@ openai = ">=1.12.0"
|
|
|
71
72
|
[tool.pytest.ini_options]
|
|
72
73
|
testpaths = [ "tests" ]
|
|
73
74
|
asyncio_mode = "auto"
|
|
75
|
+
# TODO(Ata): remove this once the openai instrumentation isn't vendored anymore
|
|
76
|
+
norecursedirs = ["vendor/patched-instrumentation-openllmetry"]
|
|
74
77
|
|
|
75
78
|
[tool.mypy]
|
|
76
79
|
plugins = ["pydantic.mypy"]
|
|
80
|
+
exclude = [
|
|
81
|
+
# TODO(Ata): remove this once the openai instrumentation isn't vendored anymore
|
|
82
|
+
"^vendor/patched-instrumentation-openllmetry/",
|
|
83
|
+
]
|
|
77
84
|
|
|
78
85
|
[[tool.mypy.overrides]]
|
|
79
86
|
module = [
|
|
@@ -87,8 +94,8 @@ module = [
|
|
|
87
94
|
"agents",
|
|
88
95
|
"agents.*",
|
|
89
96
|
"langchain_core.*",
|
|
90
|
-
"
|
|
91
|
-
"
|
|
97
|
+
"opentelemetry.instrumentation.openai", # TODO(Ata): remove this once the openai instrumentation isn't vendored anymore
|
|
98
|
+
"opentelemetry.instrumentation.openai.*",
|
|
92
99
|
]
|
|
93
100
|
ignore_missing_imports = true
|
|
94
101
|
ignore_errors = true # remove once openai instrumentor is upstream
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
# This file was auto-generated by Fern from our API Definition.
|
|
2
|
+
import os
|
|
2
3
|
import typing
|
|
3
4
|
import warnings
|
|
4
5
|
|
|
5
6
|
import httpx
|
|
7
|
+
from dotenv import load_dotenv
|
|
8
|
+
|
|
9
|
+
# Load environment variables from .env file
|
|
10
|
+
load_dotenv()
|
|
6
11
|
from .agents.client import AgentsClient, AsyncAgentsClient
|
|
7
12
|
from .contacts.client import AsyncContactsClient, ContactsClient
|
|
8
13
|
from .core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
|
|
@@ -60,11 +65,19 @@ class Paid:
|
|
|
60
65
|
*,
|
|
61
66
|
base_url: typing.Optional[str] = None,
|
|
62
67
|
environment: PaidEnvironment = PaidEnvironment.PRODUCTION,
|
|
63
|
-
token: typing.Union[str, typing.Callable[[], str]],
|
|
68
|
+
token: typing.Optional[typing.Union[str, typing.Callable[[], str]]] = None,
|
|
64
69
|
timeout: typing.Optional[float] = None,
|
|
65
70
|
follow_redirects: typing.Optional[bool] = True,
|
|
66
71
|
httpx_client: typing.Optional[httpx.Client] = None,
|
|
67
72
|
):
|
|
73
|
+
# If token is not provided, try to get it from environment variable
|
|
74
|
+
if token is None:
|
|
75
|
+
token = os.environ.get("PAID_API_KEY")
|
|
76
|
+
if token is None:
|
|
77
|
+
raise ValueError(
|
|
78
|
+
"API token must be provided either via the 'token' parameter or the 'PAID_API_KEY' environment variable"
|
|
79
|
+
)
|
|
80
|
+
|
|
68
81
|
_defaulted_timeout = (
|
|
69
82
|
timeout if timeout is not None else 60 if httpx_client is None else httpx_client.timeout.read
|
|
70
83
|
)
|
|
@@ -338,11 +351,19 @@ class AsyncPaid:
|
|
|
338
351
|
*,
|
|
339
352
|
base_url: typing.Optional[str] = None,
|
|
340
353
|
environment: PaidEnvironment = PaidEnvironment.PRODUCTION,
|
|
341
|
-
token: typing.Union[str, typing.Callable[[], str]],
|
|
354
|
+
token: typing.Optional[typing.Union[str, typing.Callable[[], str]]] = None,
|
|
342
355
|
timeout: typing.Optional[float] = None,
|
|
343
356
|
follow_redirects: typing.Optional[bool] = True,
|
|
344
357
|
httpx_client: typing.Optional[httpx.AsyncClient] = None,
|
|
345
358
|
):
|
|
359
|
+
# If token is not provided, try to get it from environment variable
|
|
360
|
+
if token is None:
|
|
361
|
+
token = os.environ.get("PAID_API_KEY")
|
|
362
|
+
if token is None:
|
|
363
|
+
raise ValueError(
|
|
364
|
+
"API token must be provided either via the 'token' parameter or the 'PAID_API_KEY' environment variable"
|
|
365
|
+
)
|
|
366
|
+
|
|
346
367
|
_defaulted_timeout = (
|
|
347
368
|
timeout if timeout is not None else 60 if httpx_client is None else httpx_client.timeout.read
|
|
348
369
|
)
|
|
@@ -7,7 +7,7 @@ from .distributed_tracing import (
|
|
|
7
7
|
unset_tracing_token,
|
|
8
8
|
)
|
|
9
9
|
from .signal import signal
|
|
10
|
-
from .tracing import
|
|
10
|
+
from .tracing import get_paid_tracer_provider, initialize_tracing
|
|
11
11
|
|
|
12
12
|
__all__ = [
|
|
13
13
|
"generate_tracing_token",
|
|
@@ -22,8 +22,7 @@ except ImportError:
|
|
|
22
22
|
ANTHROPIC_AVAILABLE = False
|
|
23
23
|
|
|
24
24
|
try:
|
|
25
|
-
|
|
26
|
-
from paid._vendor.opentelemetry.instrumentation.openai import OpenAIInstrumentor # remove once openai instrumentor is upstream
|
|
25
|
+
from opentelemetry.instrumentation.openai import OpenAIInstrumentor
|
|
27
26
|
|
|
28
27
|
OPENAI_AVAILABLE = True
|
|
29
28
|
except ImportError:
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
from typing import Callable, Collection, Optional
|
|
2
2
|
|
|
3
3
|
from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
|
|
4
|
-
from
|
|
5
|
-
from
|
|
4
|
+
from opentelemetry.instrumentation.openai.shared.config import Config
|
|
5
|
+
from opentelemetry.instrumentation.openai.utils import is_openai_v1
|
|
6
6
|
from typing_extensions import Coroutine
|
|
7
7
|
|
|
8
8
|
_instruments = ("openai >= 0.27.0",)
|
|
@@ -35,20 +35,20 @@ class OpenAIInstrumentor(BaseInstrumentor):
|
|
|
35
35
|
|
|
36
36
|
def _instrument(self, **kwargs):
|
|
37
37
|
if is_openai_v1():
|
|
38
|
-
from
|
|
38
|
+
from opentelemetry.instrumentation.openai.v1 import OpenAIV1Instrumentor
|
|
39
39
|
|
|
40
40
|
OpenAIV1Instrumentor().instrument(**kwargs)
|
|
41
41
|
else:
|
|
42
|
-
from
|
|
42
|
+
from opentelemetry.instrumentation.openai.v0 import OpenAIV0Instrumentor
|
|
43
43
|
|
|
44
44
|
OpenAIV0Instrumentor().instrument(**kwargs)
|
|
45
45
|
|
|
46
46
|
def _uninstrument(self, **kwargs):
|
|
47
47
|
if is_openai_v1():
|
|
48
|
-
from
|
|
48
|
+
from opentelemetry.instrumentation.openai.v1 import OpenAIV1Instrumentor
|
|
49
49
|
|
|
50
50
|
OpenAIV1Instrumentor().uninstrument(**kwargs)
|
|
51
51
|
else:
|
|
52
|
-
from
|
|
52
|
+
from opentelemetry.instrumentation.openai.v0 import OpenAIV0Instrumentor
|
|
53
53
|
|
|
54
54
|
OpenAIV0Instrumentor().uninstrument(**kwargs)
|
|
@@ -5,8 +5,8 @@ import openai
|
|
|
5
5
|
import pydantic
|
|
6
6
|
from importlib.metadata import version
|
|
7
7
|
|
|
8
|
-
from
|
|
9
|
-
from
|
|
8
|
+
from opentelemetry.instrumentation.openai.shared.config import Config
|
|
9
|
+
from opentelemetry.instrumentation.openai.utils import (
|
|
10
10
|
dont_throw,
|
|
11
11
|
is_openai_v1,
|
|
12
12
|
)
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import time
|
|
3
|
+
|
|
4
|
+
from opentelemetry import context as context_api
|
|
5
|
+
from opentelemetry.instrumentation.openai.shared import (
|
|
6
|
+
_set_client_attributes,
|
|
7
|
+
_set_request_attributes,
|
|
8
|
+
_set_response_attributes,
|
|
9
|
+
_set_span_attribute,
|
|
10
|
+
metric_shared_attributes,
|
|
11
|
+
model_as_dict,
|
|
12
|
+
)
|
|
13
|
+
from opentelemetry.instrumentation.openai.utils import (
|
|
14
|
+
_with_audio_telemetry_wrapper,
|
|
15
|
+
dont_throw,
|
|
16
|
+
is_openai_v1,
|
|
17
|
+
start_as_current_span_async,
|
|
18
|
+
)
|
|
19
|
+
from opentelemetry.instrumentation.utils import _SUPPRESS_INSTRUMENTATION_KEY
|
|
20
|
+
from opentelemetry.metrics import Counter, Histogram
|
|
21
|
+
from opentelemetry.semconv.attributes.error_attributes import ERROR_TYPE
|
|
22
|
+
from opentelemetry.semconv_ai import (
|
|
23
|
+
SUPPRESS_LANGUAGE_MODEL_INSTRUMENTATION_KEY,
|
|
24
|
+
SpanAttributes,
|
|
25
|
+
)
|
|
26
|
+
from opentelemetry.trace import SpanKind, Status, StatusCode
|
|
27
|
+
|
|
28
|
+
SPAN_NAME = "openai.audio.transcriptions"
|
|
29
|
+
|
|
30
|
+
logger = logging.getLogger(__name__)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _get_audio_duration(file):
|
|
34
|
+
"""
|
|
35
|
+
Extract audio duration from file object.
|
|
36
|
+
Returns duration in seconds, or None if unable to determine.
|
|
37
|
+
"""
|
|
38
|
+
try:
|
|
39
|
+
# Try to get duration from common audio libraries
|
|
40
|
+
# First check if it's a file-like object with a name attribute
|
|
41
|
+
if hasattr(file, "name"):
|
|
42
|
+
file_path = file.name
|
|
43
|
+
elif isinstance(file, (str, bytes)):
|
|
44
|
+
# If it's a path string or bytes
|
|
45
|
+
return None
|
|
46
|
+
else:
|
|
47
|
+
# If it's a file-like object without name, we can't easily determine duration
|
|
48
|
+
return None
|
|
49
|
+
|
|
50
|
+
# Try mutagen (supports many formats)
|
|
51
|
+
try:
|
|
52
|
+
from mutagen import File as MutagenFile
|
|
53
|
+
|
|
54
|
+
audio = MutagenFile(file_path)
|
|
55
|
+
if audio and hasattr(audio.info, "length"):
|
|
56
|
+
return audio.info.length
|
|
57
|
+
except (ImportError, Exception):
|
|
58
|
+
pass
|
|
59
|
+
|
|
60
|
+
except Exception as e:
|
|
61
|
+
logger.debug(f"Unable to extract audio duration: {e}")
|
|
62
|
+
|
|
63
|
+
return None
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@_with_audio_telemetry_wrapper
|
|
67
|
+
def transcription_wrapper(
|
|
68
|
+
tracer,
|
|
69
|
+
duration_histogram: Histogram,
|
|
70
|
+
exception_counter: Counter,
|
|
71
|
+
wrapped,
|
|
72
|
+
instance,
|
|
73
|
+
args,
|
|
74
|
+
kwargs,
|
|
75
|
+
):
|
|
76
|
+
if context_api.get_value(_SUPPRESS_INSTRUMENTATION_KEY) or context_api.get_value(
|
|
77
|
+
SUPPRESS_LANGUAGE_MODEL_INSTRUMENTATION_KEY
|
|
78
|
+
):
|
|
79
|
+
return wrapped(*args, **kwargs)
|
|
80
|
+
|
|
81
|
+
with tracer.start_as_current_span(
|
|
82
|
+
name=SPAN_NAME,
|
|
83
|
+
kind=SpanKind.CLIENT,
|
|
84
|
+
) as span:
|
|
85
|
+
_handle_request(span, kwargs, instance)
|
|
86
|
+
|
|
87
|
+
try:
|
|
88
|
+
# record time for duration
|
|
89
|
+
start_time = time.time()
|
|
90
|
+
response = wrapped(*args, **kwargs)
|
|
91
|
+
end_time = time.time()
|
|
92
|
+
except Exception as e: # pylint: disable=broad-except
|
|
93
|
+
end_time = time.time()
|
|
94
|
+
duration = end_time - start_time if "start_time" in locals() else 0
|
|
95
|
+
attributes = {
|
|
96
|
+
"error.type": e.__class__.__name__,
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
# if there are legal duration, record it
|
|
100
|
+
if duration > 0 and duration_histogram:
|
|
101
|
+
duration_histogram.record(duration, attributes=attributes)
|
|
102
|
+
if exception_counter:
|
|
103
|
+
exception_counter.add(1, attributes=attributes)
|
|
104
|
+
|
|
105
|
+
span.set_attribute(ERROR_TYPE, e.__class__.__name__)
|
|
106
|
+
span.record_exception(e)
|
|
107
|
+
span.set_status(Status(StatusCode.ERROR, str(e)))
|
|
108
|
+
span.end()
|
|
109
|
+
|
|
110
|
+
raise
|
|
111
|
+
|
|
112
|
+
duration = end_time - start_time
|
|
113
|
+
|
|
114
|
+
_handle_response(
|
|
115
|
+
response,
|
|
116
|
+
span,
|
|
117
|
+
instance,
|
|
118
|
+
duration_histogram,
|
|
119
|
+
duration,
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
return response
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
@_with_audio_telemetry_wrapper
|
|
126
|
+
async def atranscription_wrapper(
|
|
127
|
+
tracer,
|
|
128
|
+
duration_histogram: Histogram,
|
|
129
|
+
exception_counter: Counter,
|
|
130
|
+
wrapped,
|
|
131
|
+
instance,
|
|
132
|
+
args,
|
|
133
|
+
kwargs,
|
|
134
|
+
):
|
|
135
|
+
if context_api.get_value(_SUPPRESS_INSTRUMENTATION_KEY) or context_api.get_value(
|
|
136
|
+
SUPPRESS_LANGUAGE_MODEL_INSTRUMENTATION_KEY
|
|
137
|
+
):
|
|
138
|
+
return await wrapped(*args, **kwargs)
|
|
139
|
+
|
|
140
|
+
async with start_as_current_span_async(
|
|
141
|
+
tracer=tracer,
|
|
142
|
+
name=SPAN_NAME,
|
|
143
|
+
kind=SpanKind.CLIENT,
|
|
144
|
+
) as span:
|
|
145
|
+
_handle_request(span, kwargs, instance)
|
|
146
|
+
|
|
147
|
+
try:
|
|
148
|
+
# record time for duration
|
|
149
|
+
start_time = time.time()
|
|
150
|
+
response = await wrapped(*args, **kwargs)
|
|
151
|
+
end_time = time.time()
|
|
152
|
+
except Exception as e: # pylint: disable=broad-except
|
|
153
|
+
end_time = time.time()
|
|
154
|
+
duration = end_time - start_time if "start_time" in locals() else 0
|
|
155
|
+
attributes = {
|
|
156
|
+
"error.type": e.__class__.__name__,
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
# if there are legal duration, record it
|
|
160
|
+
if duration > 0 and duration_histogram:
|
|
161
|
+
duration_histogram.record(duration, attributes=attributes)
|
|
162
|
+
if exception_counter:
|
|
163
|
+
exception_counter.add(1, attributes=attributes)
|
|
164
|
+
|
|
165
|
+
span.set_attribute(ERROR_TYPE, e.__class__.__name__)
|
|
166
|
+
span.record_exception(e)
|
|
167
|
+
span.set_status(Status(StatusCode.ERROR, str(e)))
|
|
168
|
+
span.end()
|
|
169
|
+
|
|
170
|
+
raise
|
|
171
|
+
|
|
172
|
+
duration = end_time - start_time
|
|
173
|
+
|
|
174
|
+
_handle_response(
|
|
175
|
+
response,
|
|
176
|
+
span,
|
|
177
|
+
instance,
|
|
178
|
+
duration_histogram,
|
|
179
|
+
duration,
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
return response
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
@dont_throw
|
|
186
|
+
def _handle_request(span, kwargs, instance):
|
|
187
|
+
_set_request_attributes(span, kwargs, instance)
|
|
188
|
+
_set_client_attributes(span, instance)
|
|
189
|
+
|
|
190
|
+
# Extract and set audio duration
|
|
191
|
+
file_param = kwargs.get("file")
|
|
192
|
+
if file_param:
|
|
193
|
+
audio_duration = _get_audio_duration(file_param)
|
|
194
|
+
if audio_duration is not None:
|
|
195
|
+
# _set_span_attribute(
|
|
196
|
+
# span, SpanAttributes.LLM_OPENAI_AUDIO_INPUT_DURATION_SECONDS, audio_duration
|
|
197
|
+
# )
|
|
198
|
+
# TODO(Ata): come back here later when semconv is published
|
|
199
|
+
_set_span_attribute(
|
|
200
|
+
span, 'gen_ai.openai.audio.input.duration_seconds', audio_duration
|
|
201
|
+
)
|
|
202
|
+
else:
|
|
203
|
+
print("REMOVE ME : ATA-DBG : COULD NOT READ AUDIO FILE WITH MUTAGEN")
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
@dont_throw
|
|
207
|
+
def _handle_response(
|
|
208
|
+
response,
|
|
209
|
+
span,
|
|
210
|
+
instance=None,
|
|
211
|
+
duration_histogram=None,
|
|
212
|
+
duration=None,
|
|
213
|
+
):
|
|
214
|
+
if is_openai_v1():
|
|
215
|
+
response_dict = model_as_dict(response)
|
|
216
|
+
else:
|
|
217
|
+
response_dict = response
|
|
218
|
+
|
|
219
|
+
# metrics record
|
|
220
|
+
_set_transcription_metrics(
|
|
221
|
+
instance,
|
|
222
|
+
duration_histogram,
|
|
223
|
+
response_dict,
|
|
224
|
+
duration,
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
# span attributes
|
|
228
|
+
_set_response_attributes(span, response_dict)
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
def _set_transcription_metrics(
|
|
232
|
+
instance,
|
|
233
|
+
duration_histogram,
|
|
234
|
+
response_dict,
|
|
235
|
+
duration,
|
|
236
|
+
):
|
|
237
|
+
from opentelemetry.instrumentation.openai.shared import _get_openai_base_url
|
|
238
|
+
|
|
239
|
+
shared_attributes = metric_shared_attributes(
|
|
240
|
+
response_model=response_dict.get("model") or None,
|
|
241
|
+
operation="audio.transcriptions",
|
|
242
|
+
server_address=_get_openai_base_url(instance),
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
# duration metrics
|
|
246
|
+
if duration and isinstance(duration, (float, int)) and duration_histogram:
|
|
247
|
+
duration_histogram.record(duration, attributes=shared_attributes)
|
|
@@ -8,7 +8,7 @@ from typing import List, Optional, Union
|
|
|
8
8
|
|
|
9
9
|
from opentelemetry import context as context_api
|
|
10
10
|
import pydantic
|
|
11
|
-
from
|
|
11
|
+
from opentelemetry.instrumentation.openai.shared import (
|
|
12
12
|
OPENAI_LLM_USAGE_TOKEN_TYPES,
|
|
13
13
|
_get_openai_base_url,
|
|
14
14
|
_set_client_attributes,
|
|
@@ -24,14 +24,14 @@ from paid._vendor.opentelemetry.instrumentation.openai.shared import (
|
|
|
24
24
|
propagate_trace_context,
|
|
25
25
|
set_tools_attributes,
|
|
26
26
|
)
|
|
27
|
-
from
|
|
28
|
-
from
|
|
29
|
-
from
|
|
27
|
+
from opentelemetry.instrumentation.openai.shared.config import Config
|
|
28
|
+
from opentelemetry.instrumentation.openai.shared.event_emitter import emit_event
|
|
29
|
+
from opentelemetry.instrumentation.openai.shared.event_models import (
|
|
30
30
|
ChoiceEvent,
|
|
31
31
|
MessageEvent,
|
|
32
32
|
ToolCall,
|
|
33
33
|
)
|
|
34
|
-
from
|
|
34
|
+
from opentelemetry.instrumentation.openai.utils import (
|
|
35
35
|
_with_chat_telemetry_wrapper,
|
|
36
36
|
dont_throw,
|
|
37
37
|
is_openai_v1,
|
|
@@ -2,7 +2,7 @@ import logging
|
|
|
2
2
|
|
|
3
3
|
from opentelemetry import context as context_api
|
|
4
4
|
from opentelemetry import trace
|
|
5
|
-
from
|
|
5
|
+
from opentelemetry.instrumentation.openai.shared import (
|
|
6
6
|
_set_client_attributes,
|
|
7
7
|
_set_functions_attributes,
|
|
8
8
|
_set_request_attributes,
|
|
@@ -13,14 +13,14 @@ from paid._vendor.opentelemetry.instrumentation.openai.shared import (
|
|
|
13
13
|
model_as_dict,
|
|
14
14
|
propagate_trace_context,
|
|
15
15
|
)
|
|
16
|
-
from
|
|
16
|
+
from opentelemetry.instrumentation.openai.shared.config import Config
|
|
17
17
|
from opentelemetry.semconv.attributes.error_attributes import ERROR_TYPE
|
|
18
|
-
from
|
|
19
|
-
from
|
|
18
|
+
from opentelemetry.instrumentation.openai.shared.event_emitter import emit_event
|
|
19
|
+
from opentelemetry.instrumentation.openai.shared.event_models import (
|
|
20
20
|
ChoiceEvent,
|
|
21
21
|
MessageEvent,
|
|
22
22
|
)
|
|
23
|
-
from
|
|
23
|
+
from opentelemetry.instrumentation.openai.utils import (
|
|
24
24
|
_with_tracer_wrapper,
|
|
25
25
|
dont_throw,
|
|
26
26
|
is_openai_v1,
|
|
@@ -3,7 +3,7 @@ import time
|
|
|
3
3
|
from collections.abc import Iterable
|
|
4
4
|
|
|
5
5
|
from opentelemetry import context as context_api
|
|
6
|
-
from
|
|
6
|
+
from opentelemetry.instrumentation.openai.shared import (
|
|
7
7
|
OPENAI_LLM_USAGE_TOKEN_TYPES,
|
|
8
8
|
_get_openai_base_url,
|
|
9
9
|
_set_client_attributes,
|
|
@@ -15,13 +15,13 @@ from paid._vendor.opentelemetry.instrumentation.openai.shared import (
|
|
|
15
15
|
model_as_dict,
|
|
16
16
|
propagate_trace_context,
|
|
17
17
|
)
|
|
18
|
-
from
|
|
19
|
-
from
|
|
20
|
-
from
|
|
18
|
+
from opentelemetry.instrumentation.openai.shared.config import Config
|
|
19
|
+
from opentelemetry.instrumentation.openai.shared.event_emitter import emit_event
|
|
20
|
+
from opentelemetry.instrumentation.openai.shared.event_models import (
|
|
21
21
|
ChoiceEvent,
|
|
22
22
|
MessageEvent,
|
|
23
23
|
)
|
|
24
|
-
from
|
|
24
|
+
from opentelemetry.instrumentation.openai.utils import (
|
|
25
25
|
_with_embeddings_telemetry_wrapper,
|
|
26
26
|
dont_throw,
|
|
27
27
|
is_openai_v1,
|
|
@@ -3,11 +3,11 @@ from enum import Enum
|
|
|
3
3
|
from typing import Union
|
|
4
4
|
|
|
5
5
|
from opentelemetry._logs import LogRecord
|
|
6
|
-
from
|
|
6
|
+
from opentelemetry.instrumentation.openai.shared.event_models import (
|
|
7
7
|
ChoiceEvent,
|
|
8
8
|
MessageEvent,
|
|
9
9
|
)
|
|
10
|
-
from
|
|
10
|
+
from opentelemetry.instrumentation.openai.utils import (
|
|
11
11
|
should_emit_events,
|
|
12
12
|
should_send_prompts,
|
|
13
13
|
)
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import time
|
|
2
2
|
|
|
3
3
|
from opentelemetry import context as context_api
|
|
4
|
-
from
|
|
5
|
-
from
|
|
4
|
+
from opentelemetry.instrumentation.openai import is_openai_v1
|
|
5
|
+
from opentelemetry.instrumentation.openai.shared import (
|
|
6
6
|
_get_openai_base_url,
|
|
7
7
|
metric_shared_attributes,
|
|
8
8
|
model_as_dict,
|
|
9
9
|
)
|
|
10
|
-
from
|
|
10
|
+
from opentelemetry.instrumentation.openai.utils import (
|
|
11
11
|
_with_image_gen_metric_wrapper,
|
|
12
12
|
)
|
|
13
13
|
from opentelemetry.instrumentation.utils import _SUPPRESS_INSTRUMENTATION_KEY
|
|
@@ -9,7 +9,7 @@ from packaging import version as pkg_version
|
|
|
9
9
|
|
|
10
10
|
from opentelemetry import context as context_api
|
|
11
11
|
from opentelemetry._logs import Logger
|
|
12
|
-
from
|
|
12
|
+
from opentelemetry.instrumentation.openai.shared.config import Config
|
|
13
13
|
|
|
14
14
|
import openai
|
|
15
15
|
|
|
@@ -83,6 +83,29 @@ def _with_embeddings_telemetry_wrapper(func):
|
|
|
83
83
|
return _with_embeddings_telemetry
|
|
84
84
|
|
|
85
85
|
|
|
86
|
+
def _with_audio_telemetry_wrapper(func):
|
|
87
|
+
"""Wrapper to convert the audio wrapper function into the expected format for wrapt."""
|
|
88
|
+
def _with_audio_telemetry(
|
|
89
|
+
tracer,
|
|
90
|
+
duration_histogram,
|
|
91
|
+
exception_counter,
|
|
92
|
+
):
|
|
93
|
+
def wrapper(wrapped, instance, args, kwargs):
|
|
94
|
+
return func(
|
|
95
|
+
tracer,
|
|
96
|
+
duration_histogram,
|
|
97
|
+
exception_counter,
|
|
98
|
+
wrapped,
|
|
99
|
+
instance,
|
|
100
|
+
args,
|
|
101
|
+
kwargs,
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
return wrapper
|
|
105
|
+
|
|
106
|
+
return _with_audio_telemetry
|
|
107
|
+
|
|
108
|
+
|
|
86
109
|
def _with_chat_telemetry_wrapper(func):
|
|
87
110
|
def _with_chat_telemetry(
|
|
88
111
|
tracer,
|
|
@@ -2,21 +2,21 @@ from typing import Collection
|
|
|
2
2
|
|
|
3
3
|
from opentelemetry._logs import get_logger
|
|
4
4
|
from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
|
|
5
|
-
from
|
|
5
|
+
from opentelemetry.instrumentation.openai.shared.chat_wrappers import (
|
|
6
6
|
achat_wrapper,
|
|
7
7
|
chat_wrapper,
|
|
8
8
|
)
|
|
9
|
-
from
|
|
9
|
+
from opentelemetry.instrumentation.openai.shared.completion_wrappers import (
|
|
10
10
|
acompletion_wrapper,
|
|
11
11
|
completion_wrapper,
|
|
12
12
|
)
|
|
13
|
-
from
|
|
14
|
-
from
|
|
13
|
+
from opentelemetry.instrumentation.openai.shared.config import Config
|
|
14
|
+
from opentelemetry.instrumentation.openai.shared.embeddings_wrappers import (
|
|
15
15
|
aembeddings_wrapper,
|
|
16
16
|
embeddings_wrapper,
|
|
17
17
|
)
|
|
18
|
-
from
|
|
19
|
-
from
|
|
18
|
+
from opentelemetry.instrumentation.openai.utils import is_metrics_enabled
|
|
19
|
+
from opentelemetry.instrumentation.openai.version import __version__
|
|
20
20
|
from opentelemetry.instrumentation.utils import unwrap
|
|
21
21
|
from opentelemetry.metrics import get_meter
|
|
22
22
|
from opentelemetry.semconv._incubating.metrics import gen_ai_metrics as GenAIMetrics
|