braintrust 0.3.10__tar.gz → 0.3.12__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.
- {braintrust-0.3.10 → braintrust-0.3.12}/PKG-INFO +1 -1
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/devserver/auth.py +3 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/devserver/cors.py +1 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/devserver/server.py +6 -3
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/devserver/test_server_integration.py +4 -5
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/oai.py +1 -1
- braintrust-0.3.12/src/braintrust/version.py +4 -0
- braintrust-0.3.12/src/braintrust/wrappers/test_openrouter.py +144 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust.egg-info/PKG-INFO +1 -1
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust.egg-info/SOURCES.txt +1 -0
- braintrust-0.3.10/src/braintrust/version.py +0 -4
- {braintrust-0.3.10 → braintrust-0.3.12}/README.md +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/setup.cfg +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/setup.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/__init__.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/_generated_types.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/audit.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/aws.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/bt_json.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/cli/__init__.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/cli/__main__.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/cli/eval.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/cli/install/__init__.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/cli/install/api.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/cli/install/bump_versions.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/cli/install/logs.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/cli/install/redshift.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/cli/install/run_migrations.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/cli/push.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/conftest.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/context.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/contrib/__init__.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/contrib/temporal/__init__.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/contrib/temporal/test_temporal.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/db_fields.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/devserver/__init__.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/devserver/cache.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/devserver/dataset.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/devserver/eval_hooks.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/devserver/schemas.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/devserver/test_cached_login.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/devserver/test_lru_cache.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/framework.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/framework2.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/functions/__init__.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/functions/constants.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/functions/invoke.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/functions/stream.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/generated_types.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/git_fields.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/gitutil.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/graph_util.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/http_headers.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/id_gen.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/logger.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/merge_row_batch.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/object.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/otel/__init__.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/otel/context.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/otel/test_distributed_tracing.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/otel/test_otel_bt_integration.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/parameters.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/prompt.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/prompt_cache/__init__.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/prompt_cache/disk_cache.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/prompt_cache/lru_cache.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/prompt_cache/prompt_cache.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/prompt_cache/test_disk_cache.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/prompt_cache/test_lru_cache.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/prompt_cache/test_prompt_cache.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/py.typed +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/queue.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/resource_manager.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/score.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/serializable_data_class.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/span_identifier_v1.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/span_identifier_v2.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/span_identifier_v3.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/span_identifier_v4.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/span_types.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/test_framework.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/test_framework2.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/test_helpers.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/test_id_gen.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/test_logger.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/test_otel.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/test_queue.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/test_serializable_data_class.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/test_span_components.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/test_util.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/test_version.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/util.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/wrappers/__init__.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/wrappers/_anthropic_utils.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/wrappers/agno/__init__.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/wrappers/agno/agent.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/wrappers/agno/function_call.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/wrappers/agno/model.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/wrappers/agno/team.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/wrappers/agno/utils.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/wrappers/anthropic.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/wrappers/claude_agent_sdk/__init__.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/wrappers/claude_agent_sdk/_wrapper.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/wrappers/claude_agent_sdk/test_wrapper.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/wrappers/dspy.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/wrappers/google_genai/__init__.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/wrappers/langchain.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/wrappers/litellm.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/wrappers/openai.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/wrappers/test_agno.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/wrappers/test_anthropic.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/wrappers/test_dspy.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/wrappers/test_google_genai.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/wrappers/test_litellm.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/wrappers/test_openai.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/wrappers/test_pydantic_ai.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/wrappers/test_utils.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/xact_ids.py +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust.egg-info/dependency_links.txt +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust.egg-info/entry_points.txt +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust.egg-info/requires.txt +0 -0
- {braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust.egg-info/top_level.txt +0 -0
|
@@ -10,6 +10,7 @@ from ..logger import BraintrustState
|
|
|
10
10
|
ORIGIN_HEADER = "origin"
|
|
11
11
|
BRAINTRUST_AUTH_TOKEN_HEADER = "x-bt-auth-token"
|
|
12
12
|
BRAINTRUST_ORG_NAME_HEADER = "x-bt-org-name"
|
|
13
|
+
BRAINTRUST_PROJECT_ID_HEADER = "x-bt-project-id"
|
|
13
14
|
|
|
14
15
|
|
|
15
16
|
@dataclass
|
|
@@ -17,6 +18,7 @@ class RequestContext:
|
|
|
17
18
|
app_origin: Optional[str]
|
|
18
19
|
token: Optional[str]
|
|
19
20
|
org_name: Optional[str]
|
|
21
|
+
project_id: Optional[str]
|
|
20
22
|
state: Optional[BraintrustState]
|
|
21
23
|
|
|
22
24
|
|
|
@@ -56,6 +58,7 @@ class AuthorizationMiddleware(BaseHTTPMiddleware):
|
|
|
56
58
|
app_origin=extract_allowed_origin(request.headers.get(ORIGIN_HEADER)),
|
|
57
59
|
token=None,
|
|
58
60
|
org_name=request.headers.get(BRAINTRUST_ORG_NAME_HEADER),
|
|
61
|
+
project_id=request.headers.get(BRAINTRUST_PROJECT_ID_HEADER),
|
|
59
62
|
state=None,
|
|
60
63
|
)
|
|
61
64
|
|
|
@@ -196,7 +196,7 @@ async def run_eval(request: Request) -> Union[JSONResponse, StreamingResponse]:
|
|
|
196
196
|
"state": state,
|
|
197
197
|
"scores": evaluator.scores
|
|
198
198
|
+ [
|
|
199
|
-
make_scorer(state, score["name"], score["function_id"])
|
|
199
|
+
make_scorer(state, score["name"], score["function_id"], ctx.project_id)
|
|
200
200
|
for score in eval_data.get("scores", [])
|
|
201
201
|
],
|
|
202
202
|
"stream": stream_fn,
|
|
@@ -305,7 +305,7 @@ def snake_to_camel(snake_str: str) -> str:
|
|
|
305
305
|
return components[0] + "".join(x.title() for x in components[1:]) if components else snake_str
|
|
306
306
|
|
|
307
307
|
|
|
308
|
-
def make_scorer(state: BraintrustState, name: str, score: FunctionId) -> EvalScorer[Any, Any]:
|
|
308
|
+
def make_scorer(state: BraintrustState, name: str, score: FunctionId, project_id: Optional[str] = None) -> EvalScorer[Any, Any]:
|
|
309
309
|
def scorer_fn(input, output, expected, metadata):
|
|
310
310
|
request = {
|
|
311
311
|
**score,
|
|
@@ -315,7 +315,10 @@ def make_scorer(state: BraintrustState, name: str, score: FunctionId) -> EvalSco
|
|
|
315
315
|
"mode": "auto",
|
|
316
316
|
"strict": True,
|
|
317
317
|
}
|
|
318
|
-
|
|
318
|
+
headers = {"Accept": "application/json"}
|
|
319
|
+
if project_id:
|
|
320
|
+
headers["x-bt-project-id"] = project_id
|
|
321
|
+
result = state.proxy_conn().post("function/invoke", json=request, headers=headers)
|
|
319
322
|
result.raise_for_status()
|
|
320
323
|
data = result.json()
|
|
321
324
|
return data
|
|
@@ -4,7 +4,6 @@ from pathlib import Path
|
|
|
4
4
|
from typing import Any
|
|
5
5
|
|
|
6
6
|
import pytest
|
|
7
|
-
|
|
8
7
|
from braintrust.framework import _evals
|
|
9
8
|
from braintrust.test_helpers import has_devserver_installed
|
|
10
9
|
|
|
@@ -28,9 +27,8 @@ def client():
|
|
|
28
27
|
pytest.skip("Devserver dependencies not installed (requires .[cli])")
|
|
29
28
|
|
|
30
29
|
# Import CLI dependencies inside the fixture
|
|
31
|
-
from starlette.testclient import TestClient
|
|
32
|
-
|
|
33
30
|
from braintrust.devserver.server import create_app
|
|
31
|
+
from starlette.testclient import TestClient
|
|
34
32
|
|
|
35
33
|
# Use the real simple_eval.py example
|
|
36
34
|
eval_file = Path(__file__).parent.parent.parent.parent / "examples" / "evals" / "simple_eval.py"
|
|
@@ -39,8 +37,8 @@ def client():
|
|
|
39
37
|
_evals.clear()
|
|
40
38
|
|
|
41
39
|
# Load the eval file to register evaluators (but don't run them)
|
|
42
|
-
spec = __import__(
|
|
43
|
-
module = __import__(
|
|
40
|
+
spec = __import__("importlib.util").util.spec_from_file_location("simple_eval", str(eval_file))
|
|
41
|
+
module = __import__("importlib.util").util.module_from_spec(spec)
|
|
44
42
|
|
|
45
43
|
# Get evaluators from the module without executing Eval()
|
|
46
44
|
# We need to parse the file and extract the Evaluator definition
|
|
@@ -134,6 +132,7 @@ def parse_sse_events(response_text: str) -> list[dict[str, Any]]:
|
|
|
134
132
|
return events
|
|
135
133
|
|
|
136
134
|
|
|
135
|
+
@pytest.mark.skip
|
|
137
136
|
@pytest.mark.vcr
|
|
138
137
|
def test_eval_sse_streaming(client, api_key, org_name):
|
|
139
138
|
"""
|
|
@@ -845,7 +845,7 @@ def _parse_metrics_from_usage(usage: Any) -> Dict[str, Any]:
|
|
|
845
845
|
|
|
846
846
|
|
|
847
847
|
def _is_numeric(v):
|
|
848
|
-
return isinstance(v, (int, float, complex))
|
|
848
|
+
return isinstance(v, (int, float, complex)) and not isinstance(v, bool)
|
|
849
849
|
|
|
850
850
|
|
|
851
851
|
def prettify_params(params: Dict[str, Any]) -> Dict[str, Any]:
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Tests to ensure wrap_openai works correctly with OpenRouter.
|
|
3
|
+
|
|
4
|
+
OpenRouter is a popular API gateway that provides access to multiple LLM providers
|
|
5
|
+
through an OpenAI-compatible interface. This test validates that our wrapper handles
|
|
6
|
+
OpenRouter-specific response fields correctly (e.g., boolean `is_byok` in usage).
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import os
|
|
10
|
+
import time
|
|
11
|
+
|
|
12
|
+
import pytest
|
|
13
|
+
from braintrust import logger, wrap_openai
|
|
14
|
+
from braintrust.test_helpers import init_test_logger
|
|
15
|
+
from braintrust.wrappers.test_utils import assert_metrics_are_valid
|
|
16
|
+
from openai import AsyncOpenAI, OpenAI
|
|
17
|
+
|
|
18
|
+
PROJECT_NAME = "test-openrouter"
|
|
19
|
+
TEST_MODEL = "openai/gpt-4o-mini"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@pytest.fixture(scope="module")
|
|
23
|
+
def vcr_config():
|
|
24
|
+
return {
|
|
25
|
+
"filter_headers": [
|
|
26
|
+
"authorization",
|
|
27
|
+
]
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@pytest.fixture
|
|
32
|
+
def memory_logger():
|
|
33
|
+
init_test_logger(PROJECT_NAME)
|
|
34
|
+
with logger._internal_with_memory_background_logger() as bgl:
|
|
35
|
+
yield bgl
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _get_client():
|
|
39
|
+
return OpenAI(
|
|
40
|
+
base_url="https://openrouter.ai/api/v1",
|
|
41
|
+
api_key=os.environ.get("OPENROUTER_API_KEY"),
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _get_async_client():
|
|
46
|
+
return AsyncOpenAI(
|
|
47
|
+
base_url="https://openrouter.ai/api/v1",
|
|
48
|
+
api_key=os.environ.get("OPENROUTER_API_KEY"),
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@pytest.mark.vcr
|
|
53
|
+
def test_openrouter_chat_completion_sync(memory_logger):
|
|
54
|
+
assert not memory_logger.pop()
|
|
55
|
+
|
|
56
|
+
client = wrap_openai(_get_client())
|
|
57
|
+
|
|
58
|
+
start = time.time()
|
|
59
|
+
response = client.chat.completions.create(
|
|
60
|
+
model=TEST_MODEL,
|
|
61
|
+
messages=[{"role": "user", "content": "What is 2+2? Reply with just the number."}],
|
|
62
|
+
max_tokens=10,
|
|
63
|
+
)
|
|
64
|
+
end = time.time()
|
|
65
|
+
|
|
66
|
+
assert response
|
|
67
|
+
assert response.choices[0].message.content
|
|
68
|
+
assert "4" in response.choices[0].message.content
|
|
69
|
+
|
|
70
|
+
spans = memory_logger.pop()
|
|
71
|
+
assert len(spans) == 1
|
|
72
|
+
span = spans[0]
|
|
73
|
+
|
|
74
|
+
metrics = span["metrics"]
|
|
75
|
+
assert_metrics_are_valid(metrics, start, end)
|
|
76
|
+
|
|
77
|
+
# Ensure no boolean values in metrics (the original bug with is_byok)
|
|
78
|
+
for key, value in metrics.items():
|
|
79
|
+
assert not isinstance(value, bool), f"Metric {key} should not be a boolean"
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
@pytest.mark.vcr
|
|
83
|
+
@pytest.mark.asyncio
|
|
84
|
+
async def test_openrouter_chat_completion_async(memory_logger):
|
|
85
|
+
"""Test that wrap_openai works with OpenRouter's async client."""
|
|
86
|
+
assert not memory_logger.pop()
|
|
87
|
+
|
|
88
|
+
client = wrap_openai(_get_async_client())
|
|
89
|
+
|
|
90
|
+
start = time.time()
|
|
91
|
+
response = await client.chat.completions.create(
|
|
92
|
+
model=TEST_MODEL,
|
|
93
|
+
messages=[{"role": "user", "content": "What is 3+3? Reply with just the number."}],
|
|
94
|
+
max_tokens=10,
|
|
95
|
+
)
|
|
96
|
+
end = time.time()
|
|
97
|
+
|
|
98
|
+
assert response
|
|
99
|
+
assert response.choices[0].message.content
|
|
100
|
+
assert "6" in response.choices[0].message.content
|
|
101
|
+
|
|
102
|
+
spans = memory_logger.pop()
|
|
103
|
+
assert len(spans) == 1
|
|
104
|
+
span = spans[0]
|
|
105
|
+
|
|
106
|
+
metrics = span["metrics"]
|
|
107
|
+
assert_metrics_are_valid(metrics, start, end)
|
|
108
|
+
|
|
109
|
+
for key, value in metrics.items():
|
|
110
|
+
assert not isinstance(value, bool), f"Metric {key} should not be a boolean"
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
@pytest.mark.vcr
|
|
114
|
+
def test_openrouter_streaming_sync(memory_logger):
|
|
115
|
+
"""Test that wrap_openai works with OpenRouter's streaming responses."""
|
|
116
|
+
assert not memory_logger.pop()
|
|
117
|
+
|
|
118
|
+
client = wrap_openai(_get_client())
|
|
119
|
+
|
|
120
|
+
start = time.time()
|
|
121
|
+
chunks = []
|
|
122
|
+
stream = client.chat.completions.create(
|
|
123
|
+
model=TEST_MODEL,
|
|
124
|
+
messages=[{"role": "user", "content": "What is 5+5? Reply with just the number."}],
|
|
125
|
+
max_tokens=10,
|
|
126
|
+
stream=True,
|
|
127
|
+
)
|
|
128
|
+
for chunk in stream:
|
|
129
|
+
chunks.append(chunk)
|
|
130
|
+
end = time.time()
|
|
131
|
+
|
|
132
|
+
assert chunks
|
|
133
|
+
content = "".join(c.choices[0].delta.content or "" for c in chunks if c.choices)
|
|
134
|
+
assert "10" in content
|
|
135
|
+
|
|
136
|
+
spans = memory_logger.pop()
|
|
137
|
+
assert len(spans) == 1
|
|
138
|
+
span = spans[0]
|
|
139
|
+
|
|
140
|
+
metrics = span["metrics"]
|
|
141
|
+
assert_metrics_are_valid(metrics, start, end)
|
|
142
|
+
|
|
143
|
+
for key, value in metrics.items():
|
|
144
|
+
assert not isinstance(value, bool), f"Metric {key} should not be a boolean"
|
|
@@ -104,6 +104,7 @@ src/braintrust/wrappers/test_dspy.py
|
|
|
104
104
|
src/braintrust/wrappers/test_google_genai.py
|
|
105
105
|
src/braintrust/wrappers/test_litellm.py
|
|
106
106
|
src/braintrust/wrappers/test_openai.py
|
|
107
|
+
src/braintrust/wrappers/test_openrouter.py
|
|
107
108
|
src/braintrust/wrappers/test_pydantic_ai.py
|
|
108
109
|
src/braintrust/wrappers/test_utils.py
|
|
109
110
|
src/braintrust/wrappers/agno/__init__.py
|
|
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
|
{braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/wrappers/claude_agent_sdk/__init__.py
RENAMED
|
File without changes
|
{braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/wrappers/claude_agent_sdk/_wrapper.py
RENAMED
|
File without changes
|
{braintrust-0.3.10 → braintrust-0.3.12}/src/braintrust/wrappers/claude_agent_sdk/test_wrapper.py
RENAMED
|
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
|