tracecast 0.2.7__tar.gz → 0.2.8__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.
- {tracecast-0.2.7/tracecast.egg-info → tracecast-0.2.8}/PKG-INFO +1 -1
- {tracecast-0.2.7 → tracecast-0.2.8}/pyproject.toml +1 -1
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/__init__.py +2 -2
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/instrument.py +18 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/instrumentors/openai_inst.py +36 -24
- {tracecast-0.2.7 → tracecast-0.2.8/tracecast.egg-info}/PKG-INFO +1 -1
- {tracecast-0.2.7 → tracecast-0.2.8}/LICENSE +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/README.md +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/setup.cfg +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tests/test_aggregator_graph.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tests/test_context_propagation.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tests/test_cost_calculator.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tests/test_dashboard_mount.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tests/test_dashboard_pushdown.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tests/test_dashboard_sessions.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tests/test_decorators.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tests/test_e2e_langgraph.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tests/test_exporters_db.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tests/test_integration_frameworks.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tests/test_integration_langchain.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tests/test_json_exporter.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tests/test_langchain_callback.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tests/test_llm_wrappers.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tests/test_logging.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tests/test_mongo_exporter.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tests/test_prompt_dashboard.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tests/test_prompts.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tests/test_roundtrip.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tests/test_schema_v2.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tests/test_score.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tests/test_score_dashboard.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tests/test_scoring_api.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tests/test_serve.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tests/test_span.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tests/test_streaming.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tests/test_token_counter.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tests/test_trace.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tests/test_trace_span.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tests/test_tracer.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/core/__init__.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/core/cost_calculator.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/core/logger.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/core/scoring.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/core/token_counter.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/core/tracer.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/dashboard/__init__.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/dashboard/aggregator.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/dashboard/asgi_middleware.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/dashboard/blueprint.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/dashboard/eval_reader.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/dashboard/prompt_reader.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/dashboard/reader.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/dashboard/router.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/dashboard/score_reader.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/dashboard/standalone.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/dashboard/static/assets/index-B07hiBI2.js +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/dashboard/static/assets/index-BMIlEmLS.js +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/dashboard/static/assets/index-CY5YOA8F.js +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/dashboard/static/assets/index-DllJJzmE.css +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/dashboard/static/assets/index-Dt0awpJJ.js +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/dashboard/static/index.html +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/decorators.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/eval/__init__.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/eval/cli.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/eval/compare.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/eval/dataset.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/eval/decorator.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/eval/judge.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/eval/metrics.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/eval/models.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/eval/online.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/eval/runner.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/eval/scorers.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/exporters/__init__.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/exporters/_eval_store.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/exporters/base.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/exporters/dict_exporter.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/exporters/json_file.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/exporters/mongo.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/exporters/postgres.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/exporters/query.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/instrumentors/__init__.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/instrumentors/_llamaindex_handler.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/instrumentors/_streaming.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/instrumentors/anthropic_inst.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/instrumentors/base.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/instrumentors/crewai_inst.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/instrumentors/gemini_inst.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/instrumentors/langchain_inst.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/instrumentors/llamaindex_inst.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/integrations/__init__.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/integrations/langchain.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/integrations/llm.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/middleware.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/models/__init__.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/models/score.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/models/span.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/models/trace.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/prompts/__init__.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/prompts/client.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/prompts/models.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast/serve.py +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast.egg-info/SOURCES.txt +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast.egg-info/dependency_links.txt +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast.egg-info/entry_points.txt +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast.egg-info/requires.txt +0 -0
- {tracecast-0.2.7 → tracecast-0.2.8}/tracecast.egg-info/top_level.txt +0 -0
|
@@ -8,7 +8,7 @@ from .decorators import trace_cast, trace_span, set_default_tracer
|
|
|
8
8
|
from .core.scoring import score
|
|
9
9
|
from .prompts import create_prompt, get_prompt, set_label, PromptVersion
|
|
10
10
|
from .integrations.llm import trace_llm_call, wrap_openai, wrap_anthropic
|
|
11
|
-
from .instrument import auto_instrument
|
|
11
|
+
from .instrument import auto_instrument, instrument_openai
|
|
12
12
|
from .exporters.dict_exporter import DictExporter
|
|
13
13
|
|
|
14
14
|
__all__ = [
|
|
@@ -18,5 +18,5 @@ __all__ = [
|
|
|
18
18
|
"trace_cast", "trace_span", "set_default_tracer", "score",
|
|
19
19
|
"create_prompt", "get_prompt", "set_label", "PromptVersion",
|
|
20
20
|
"trace_llm_call", "wrap_openai", "wrap_anthropic",
|
|
21
|
-
"auto_instrument", "DictExporter",
|
|
21
|
+
"auto_instrument", "instrument_openai", "DictExporter",
|
|
22
22
|
]
|
|
@@ -34,6 +34,24 @@ def auto_instrument(tracer: Optional[Tracer] = None) -> None:
|
|
|
34
34
|
_instrumented = True
|
|
35
35
|
|
|
36
36
|
|
|
37
|
+
def instrument_openai(*, chat: bool = True, embeddings: bool = True, audio: bool = True) -> None:
|
|
38
|
+
"""Patch only the requested OpenAI API surfaces, independent of auto_instrument().
|
|
39
|
+
|
|
40
|
+
Use `chat=False` when chat completions are already traced through another
|
|
41
|
+
mechanism (e.g. a manually-wired LangChain callback) and you only want to
|
|
42
|
+
add embeddings/audio coverage — re-patching chat.completions in that case
|
|
43
|
+
would produce duplicate spans for every chat call.
|
|
44
|
+
"""
|
|
45
|
+
from .instrumentors.openai_inst import OpenAIInstrumentor
|
|
46
|
+
with _lock:
|
|
47
|
+
inst = _registry.get("openai")
|
|
48
|
+
if inst is None:
|
|
49
|
+
inst = OpenAIInstrumentor()
|
|
50
|
+
_registry["openai"] = inst
|
|
51
|
+
if not inst.is_patched():
|
|
52
|
+
inst.patch(chat=chat, embeddings=embeddings, audio=audio)
|
|
53
|
+
|
|
54
|
+
|
|
37
55
|
def _reset() -> None:
|
|
38
56
|
global _instrumented
|
|
39
57
|
with _lock:
|
|
@@ -32,33 +32,44 @@ class OpenAIInstrumentor(BaseInstrumentor):
|
|
|
32
32
|
self._original_speech_create: Optional[Any] = None
|
|
33
33
|
self._patched: bool = False
|
|
34
34
|
|
|
35
|
-
def patch(self) -> None:
|
|
35
|
+
def patch(self, *, chat: bool = True, embeddings: bool = True, audio: bool = True) -> None:
|
|
36
|
+
"""Patch the requested OpenAI API surfaces.
|
|
37
|
+
|
|
38
|
+
`chat=False` lets callers add embeddings/audio coverage without
|
|
39
|
+
re-patching chat.completions — needed when chat completions are
|
|
40
|
+
already traced through another mechanism (e.g. a manually-wired
|
|
41
|
+
LangChain callback), where re-patching would double-count spans.
|
|
42
|
+
"""
|
|
36
43
|
if self._patched:
|
|
37
44
|
return
|
|
38
|
-
import openai.resources.chat.completions as mod
|
|
39
45
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
46
|
+
if chat:
|
|
47
|
+
import openai.resources.chat.completions as mod
|
|
48
|
+
|
|
49
|
+
# Sync
|
|
50
|
+
self._original_create = mod.Completions.create
|
|
51
|
+
self_ref = self
|
|
52
|
+
_orig_create = self._original_create
|
|
44
53
|
|
|
45
|
-
|
|
46
|
-
|
|
54
|
+
def patched_create(client_self, *args, **kwargs):
|
|
55
|
+
return self_ref._intercept(client_self, args, kwargs, _orig_create)
|
|
47
56
|
|
|
48
|
-
|
|
57
|
+
mod.Completions.create = patched_create
|
|
49
58
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
59
|
+
# Async
|
|
60
|
+
if hasattr(mod, "AsyncCompletions"):
|
|
61
|
+
self._original_acreate = mod.AsyncCompletions.create
|
|
62
|
+
_orig_acreate = self._original_acreate
|
|
54
63
|
|
|
55
|
-
|
|
56
|
-
|
|
64
|
+
async def patched_acreate(client_self, *args, **kwargs):
|
|
65
|
+
return await self_ref._async_intercept(client_self, args, kwargs, _orig_acreate)
|
|
57
66
|
|
|
58
|
-
|
|
67
|
+
mod.AsyncCompletions.create = patched_acreate
|
|
59
68
|
|
|
60
|
-
|
|
61
|
-
|
|
69
|
+
if embeddings:
|
|
70
|
+
self._patch_embeddings()
|
|
71
|
+
if audio:
|
|
72
|
+
self._patch_audio()
|
|
62
73
|
|
|
63
74
|
self._patched = True
|
|
64
75
|
|
|
@@ -108,12 +119,13 @@ class OpenAIInstrumentor(BaseInstrumentor):
|
|
|
108
119
|
def unpatch(self) -> None:
|
|
109
120
|
if not self._patched:
|
|
110
121
|
return
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
122
|
+
if self._original_create is not None:
|
|
123
|
+
import openai.resources.chat.completions as mod
|
|
124
|
+
mod.Completions.create = self._original_create
|
|
125
|
+
if self._original_acreate is not None:
|
|
126
|
+
mod.AsyncCompletions.create = self._original_acreate
|
|
127
|
+
self._original_create = None
|
|
128
|
+
self._original_acreate = None
|
|
117
129
|
|
|
118
130
|
if self._original_embeddings_create is not None:
|
|
119
131
|
import openai.resources.embeddings as emb_mod
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|