braintrust 0.3.14__py3-none-any.whl → 0.4.0__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.
- braintrust/__init__.py +4 -0
- braintrust/_generated_types.py +1200 -611
- braintrust/audit.py +2 -2
- braintrust/cli/eval.py +6 -7
- braintrust/cli/push.py +11 -11
- braintrust/conftest.py +1 -0
- braintrust/context.py +12 -17
- braintrust/contrib/temporal/__init__.py +16 -27
- braintrust/contrib/temporal/test_temporal.py +8 -3
- braintrust/devserver/auth.py +8 -8
- braintrust/devserver/cache.py +3 -4
- braintrust/devserver/cors.py +8 -7
- braintrust/devserver/dataset.py +3 -5
- braintrust/devserver/eval_hooks.py +7 -6
- braintrust/devserver/schemas.py +22 -19
- braintrust/devserver/server.py +19 -12
- braintrust/devserver/test_cached_login.py +4 -4
- braintrust/framework.py +128 -140
- braintrust/framework2.py +88 -87
- braintrust/functions/invoke.py +93 -53
- braintrust/functions/stream.py +3 -2
- braintrust/generated_types.py +17 -1
- braintrust/git_fields.py +11 -11
- braintrust/gitutil.py +2 -3
- braintrust/graph_util.py +10 -10
- braintrust/id_gen.py +2 -2
- braintrust/logger.py +346 -357
- braintrust/merge_row_batch.py +10 -9
- braintrust/oai.py +107 -24
- braintrust/otel/__init__.py +49 -49
- braintrust/otel/context.py +16 -30
- braintrust/otel/test_distributed_tracing.py +14 -11
- braintrust/otel/test_otel_bt_integration.py +32 -31
- braintrust/parameters.py +8 -8
- braintrust/prompt.py +14 -14
- braintrust/prompt_cache/disk_cache.py +5 -4
- braintrust/prompt_cache/lru_cache.py +3 -2
- braintrust/prompt_cache/prompt_cache.py +13 -14
- braintrust/queue.py +4 -4
- braintrust/score.py +4 -4
- braintrust/serializable_data_class.py +4 -4
- braintrust/span_identifier_v1.py +1 -2
- braintrust/span_identifier_v2.py +3 -4
- braintrust/span_identifier_v3.py +23 -20
- braintrust/span_identifier_v4.py +34 -25
- braintrust/test_framework.py +16 -6
- braintrust/test_helpers.py +5 -5
- braintrust/test_id_gen.py +2 -3
- braintrust/test_otel.py +61 -53
- braintrust/test_queue.py +0 -1
- braintrust/test_score.py +1 -3
- braintrust/test_span_components.py +29 -44
- braintrust/util.py +9 -8
- braintrust/version.py +2 -2
- braintrust/wrappers/_anthropic_utils.py +4 -4
- braintrust/wrappers/agno/__init__.py +3 -4
- braintrust/wrappers/agno/agent.py +1 -2
- braintrust/wrappers/agno/function_call.py +1 -2
- braintrust/wrappers/agno/model.py +1 -2
- braintrust/wrappers/agno/team.py +1 -2
- braintrust/wrappers/agno/utils.py +12 -12
- braintrust/wrappers/anthropic.py +7 -8
- braintrust/wrappers/claude_agent_sdk/__init__.py +3 -4
- braintrust/wrappers/claude_agent_sdk/_wrapper.py +29 -27
- braintrust/wrappers/dspy.py +15 -17
- braintrust/wrappers/google_genai/__init__.py +16 -16
- braintrust/wrappers/langchain.py +22 -24
- braintrust/wrappers/litellm.py +4 -3
- braintrust/wrappers/openai.py +15 -15
- braintrust/wrappers/pydantic_ai.py +1204 -0
- braintrust/wrappers/test_agno.py +0 -1
- braintrust/wrappers/test_dspy.py +0 -1
- braintrust/wrappers/test_google_genai.py +2 -3
- braintrust/wrappers/test_litellm.py +0 -1
- braintrust/wrappers/test_oai_attachments.py +322 -0
- braintrust/wrappers/test_pydantic_ai_integration.py +1788 -0
- braintrust/wrappers/{test_pydantic_ai.py → test_pydantic_ai_wrap_openai.py} +1 -2
- {braintrust-0.3.14.dist-info → braintrust-0.4.0.dist-info}/METADATA +3 -2
- braintrust-0.4.0.dist-info/RECORD +120 -0
- braintrust-0.3.14.dist-info/RECORD +0 -117
- {braintrust-0.3.14.dist-info → braintrust-0.4.0.dist-info}/WHEEL +0 -0
- {braintrust-0.3.14.dist-info → braintrust-0.4.0.dist-info}/entry_points.txt +0 -0
- {braintrust-0.3.14.dist-info → braintrust-0.4.0.dist-info}/top_level.txt +0 -0
braintrust/framework2.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import dataclasses
|
|
2
2
|
import json
|
|
3
|
-
from
|
|
3
|
+
from collections.abc import Callable
|
|
4
|
+
from typing import Any, overload
|
|
4
5
|
|
|
5
6
|
import slugify
|
|
6
7
|
from braintrust.logger import api_conn, app_conn, login
|
|
@@ -20,7 +21,7 @@ from .util import eprint
|
|
|
20
21
|
|
|
21
22
|
class ProjectIdCache:
|
|
22
23
|
def __init__(self):
|
|
23
|
-
self._cache:
|
|
24
|
+
self._cache: dict[Project, str] = {}
|
|
24
25
|
|
|
25
26
|
def get(self, project: "Project") -> str:
|
|
26
27
|
if project not in self._cache:
|
|
@@ -31,8 +32,8 @@ class ProjectIdCache:
|
|
|
31
32
|
|
|
32
33
|
class _GlobalState:
|
|
33
34
|
def __init__(self):
|
|
34
|
-
self.functions:
|
|
35
|
-
self.prompts:
|
|
35
|
+
self.functions: list[CodeFunction] = []
|
|
36
|
+
self.prompts: list[CodePrompt] = []
|
|
36
37
|
|
|
37
38
|
|
|
38
39
|
global_ = _GlobalState()
|
|
@@ -47,11 +48,11 @@ class CodeFunction:
|
|
|
47
48
|
name: str
|
|
48
49
|
slug: str
|
|
49
50
|
type_: str
|
|
50
|
-
description:
|
|
51
|
+
description: str | None
|
|
51
52
|
parameters: Any
|
|
52
53
|
returns: Any
|
|
53
|
-
if_exists:
|
|
54
|
-
metadata:
|
|
54
|
+
if_exists: IfExists | None
|
|
55
|
+
metadata: dict[str, Any] | None = None
|
|
55
56
|
|
|
56
57
|
|
|
57
58
|
@dataclasses.dataclass
|
|
@@ -62,17 +63,17 @@ class CodePrompt:
|
|
|
62
63
|
name: str
|
|
63
64
|
slug: str
|
|
64
65
|
prompt: PromptData
|
|
65
|
-
tool_functions:
|
|
66
|
-
description:
|
|
67
|
-
function_type:
|
|
68
|
-
id:
|
|
69
|
-
if_exists:
|
|
70
|
-
metadata:
|
|
71
|
-
|
|
72
|
-
def to_function_definition(self, if_exists:
|
|
66
|
+
tool_functions: list[CodeFunction | SavedFunctionId]
|
|
67
|
+
description: str | None
|
|
68
|
+
function_type: str | None
|
|
69
|
+
id: str | None
|
|
70
|
+
if_exists: IfExists | None
|
|
71
|
+
metadata: dict[str, Any] | None = None
|
|
72
|
+
|
|
73
|
+
def to_function_definition(self, if_exists: IfExists | None, project_ids: ProjectIdCache) -> dict[str, Any]:
|
|
73
74
|
prompt_data = self.prompt
|
|
74
75
|
if len(self.tool_functions) > 0:
|
|
75
|
-
resolvable_tool_functions:
|
|
76
|
+
resolvable_tool_functions: list[Any] = []
|
|
76
77
|
for f in self.tool_functions:
|
|
77
78
|
if isinstance(f, CodeFunction):
|
|
78
79
|
resolvable_tool_functions.append(
|
|
@@ -85,7 +86,7 @@ class CodePrompt:
|
|
|
85
86
|
else:
|
|
86
87
|
resolvable_tool_functions.append(f)
|
|
87
88
|
prompt_data["tool_functions"] = resolvable_tool_functions
|
|
88
|
-
j:
|
|
89
|
+
j: dict[str, Any] = {
|
|
89
90
|
"project_id": project_ids.get(self.project),
|
|
90
91
|
"name": self.name,
|
|
91
92
|
"slug": self.slug,
|
|
@@ -116,13 +117,13 @@ class ToolBuilder:
|
|
|
116
117
|
self,
|
|
117
118
|
*,
|
|
118
119
|
handler: Callable[..., Any],
|
|
119
|
-
name:
|
|
120
|
-
slug:
|
|
121
|
-
description:
|
|
120
|
+
name: str | None = None,
|
|
121
|
+
slug: str | None = None,
|
|
122
|
+
description: str | None = None,
|
|
122
123
|
parameters: Any = None,
|
|
123
124
|
returns: Any = None,
|
|
124
|
-
if_exists:
|
|
125
|
-
metadata:
|
|
125
|
+
if_exists: IfExists | None = None,
|
|
126
|
+
metadata: dict[str, Any] | None = None,
|
|
126
127
|
) -> CodeFunction:
|
|
127
128
|
"""Creates a tool.
|
|
128
129
|
|
|
@@ -175,48 +176,48 @@ class PromptBuilder:
|
|
|
175
176
|
def create(
|
|
176
177
|
self,
|
|
177
178
|
*,
|
|
178
|
-
name:
|
|
179
|
-
slug:
|
|
180
|
-
description:
|
|
181
|
-
id:
|
|
179
|
+
name: str | None = None,
|
|
180
|
+
slug: str | None = None,
|
|
181
|
+
description: str | None = None,
|
|
182
|
+
id: str | None = None,
|
|
182
183
|
prompt: str,
|
|
183
184
|
model: str,
|
|
184
|
-
params:
|
|
185
|
-
tools:
|
|
186
|
-
if_exists:
|
|
187
|
-
metadata:
|
|
185
|
+
params: ModelParams | None = None,
|
|
186
|
+
tools: list[CodeFunction | SavedFunctionId | ToolFunctionDefinition] | None = None,
|
|
187
|
+
if_exists: IfExists | None = None,
|
|
188
|
+
metadata: dict[str, Any] | None = None,
|
|
188
189
|
) -> CodePrompt: ...
|
|
189
190
|
|
|
190
191
|
@overload # messages only, no prompt
|
|
191
192
|
def create(
|
|
192
193
|
self,
|
|
193
194
|
*,
|
|
194
|
-
name:
|
|
195
|
-
slug:
|
|
196
|
-
description:
|
|
197
|
-
id:
|
|
198
|
-
messages:
|
|
195
|
+
name: str | None = None,
|
|
196
|
+
slug: str | None = None,
|
|
197
|
+
description: str | None = None,
|
|
198
|
+
id: str | None = None,
|
|
199
|
+
messages: list[ChatCompletionMessageParam],
|
|
199
200
|
model: str,
|
|
200
|
-
params:
|
|
201
|
-
tools:
|
|
202
|
-
if_exists:
|
|
203
|
-
metadata:
|
|
201
|
+
params: ModelParams | None = None,
|
|
202
|
+
tools: list[CodeFunction | SavedFunctionId | ToolFunctionDefinition] | None = None,
|
|
203
|
+
if_exists: IfExists | None = None,
|
|
204
|
+
metadata: dict[str, Any] | None = None,
|
|
204
205
|
) -> CodePrompt: ...
|
|
205
206
|
|
|
206
207
|
def create(
|
|
207
208
|
self,
|
|
208
209
|
*,
|
|
209
|
-
name:
|
|
210
|
-
slug:
|
|
211
|
-
description:
|
|
212
|
-
id:
|
|
213
|
-
prompt:
|
|
214
|
-
messages:
|
|
210
|
+
name: str | None = None,
|
|
211
|
+
slug: str | None = None,
|
|
212
|
+
description: str | None = None,
|
|
213
|
+
id: str | None = None,
|
|
214
|
+
prompt: str | None = None,
|
|
215
|
+
messages: list[ChatCompletionMessageParam] | None = None,
|
|
215
216
|
model: str,
|
|
216
|
-
params:
|
|
217
|
-
tools:
|
|
218
|
-
if_exists:
|
|
219
|
-
metadata:
|
|
217
|
+
params: ModelParams | None = None,
|
|
218
|
+
tools: list[CodeFunction | SavedFunctionId | ToolFunctionDefinition] | None = None,
|
|
219
|
+
if_exists: IfExists | None = None,
|
|
220
|
+
metadata: dict[str, Any] | None = None,
|
|
220
221
|
):
|
|
221
222
|
"""Creates a prompt.
|
|
222
223
|
|
|
@@ -239,8 +240,8 @@ class PromptBuilder:
|
|
|
239
240
|
if not slug:
|
|
240
241
|
slug = slugify.slugify(name)
|
|
241
242
|
|
|
242
|
-
tool_functions:
|
|
243
|
-
raw_tools:
|
|
243
|
+
tool_functions: list[CodeFunction | SavedFunctionId] = []
|
|
244
|
+
raw_tools: list[ToolFunctionDefinition] = []
|
|
244
245
|
for tool in tools or []:
|
|
245
246
|
if isinstance(tool, CodeFunction):
|
|
246
247
|
tool_functions.append(tool)
|
|
@@ -298,11 +299,11 @@ class ScorerBuilder:
|
|
|
298
299
|
def create(
|
|
299
300
|
self,
|
|
300
301
|
*,
|
|
301
|
-
name:
|
|
302
|
-
slug:
|
|
303
|
-
description:
|
|
304
|
-
if_exists:
|
|
305
|
-
metadata:
|
|
302
|
+
name: str | None = None,
|
|
303
|
+
slug: str | None = None,
|
|
304
|
+
description: str | None = None,
|
|
305
|
+
if_exists: IfExists | None = None,
|
|
306
|
+
metadata: dict[str, Any] | None = None,
|
|
306
307
|
handler: Callable[..., Any],
|
|
307
308
|
parameters: Any,
|
|
308
309
|
returns: Any = None,
|
|
@@ -313,16 +314,16 @@ class ScorerBuilder:
|
|
|
313
314
|
def create(
|
|
314
315
|
self,
|
|
315
316
|
*,
|
|
316
|
-
name:
|
|
317
|
-
slug:
|
|
318
|
-
description:
|
|
319
|
-
if_exists:
|
|
320
|
-
metadata:
|
|
317
|
+
name: str | None = None,
|
|
318
|
+
slug: str | None = None,
|
|
319
|
+
description: str | None = None,
|
|
320
|
+
if_exists: IfExists | None = None,
|
|
321
|
+
metadata: dict[str, Any] | None = None,
|
|
321
322
|
prompt: str,
|
|
322
323
|
model: str,
|
|
323
|
-
params:
|
|
324
|
+
params: ModelParams | None = None,
|
|
324
325
|
use_cot: bool,
|
|
325
|
-
choice_scores:
|
|
326
|
+
choice_scores: dict[str, float],
|
|
326
327
|
) -> CodePrompt: ...
|
|
327
328
|
|
|
328
329
|
# LLM scorer with messages.
|
|
@@ -330,38 +331,38 @@ class ScorerBuilder:
|
|
|
330
331
|
def create(
|
|
331
332
|
self,
|
|
332
333
|
*,
|
|
333
|
-
name:
|
|
334
|
-
slug:
|
|
335
|
-
description:
|
|
336
|
-
if_exists:
|
|
337
|
-
metadata:
|
|
338
|
-
messages:
|
|
334
|
+
name: str | None = None,
|
|
335
|
+
slug: str | None = None,
|
|
336
|
+
description: str | None = None,
|
|
337
|
+
if_exists: IfExists | None = None,
|
|
338
|
+
metadata: dict[str, Any] | None = None,
|
|
339
|
+
messages: list[ChatCompletionMessageParam],
|
|
339
340
|
model: str,
|
|
340
|
-
params:
|
|
341
|
+
params: ModelParams | None = None,
|
|
341
342
|
use_cot: bool,
|
|
342
|
-
choice_scores:
|
|
343
|
+
choice_scores: dict[str, float],
|
|
343
344
|
) -> CodePrompt: ...
|
|
344
345
|
|
|
345
346
|
def create(
|
|
346
347
|
self,
|
|
347
348
|
*,
|
|
348
|
-
name:
|
|
349
|
-
slug:
|
|
350
|
-
description:
|
|
351
|
-
if_exists:
|
|
352
|
-
metadata:
|
|
349
|
+
name: str | None = None,
|
|
350
|
+
slug: str | None = None,
|
|
351
|
+
description: str | None = None,
|
|
352
|
+
if_exists: IfExists | None = None,
|
|
353
|
+
metadata: dict[str, Any] | None = None,
|
|
353
354
|
# Code scorer params.
|
|
354
|
-
handler:
|
|
355
|
+
handler: Callable[..., Any] | None = None,
|
|
355
356
|
parameters: Any = None,
|
|
356
357
|
returns: Any = None,
|
|
357
358
|
# LLM scorer params.
|
|
358
|
-
prompt:
|
|
359
|
-
messages:
|
|
360
|
-
model:
|
|
361
|
-
params:
|
|
362
|
-
use_cot:
|
|
363
|
-
choice_scores:
|
|
364
|
-
) ->
|
|
359
|
+
prompt: str | None = None,
|
|
360
|
+
messages: list[ChatCompletionMessageParam] | None = None,
|
|
361
|
+
model: str | None = None,
|
|
362
|
+
params: ModelParams | None = None,
|
|
363
|
+
use_cot: bool | None = None,
|
|
364
|
+
choice_scores: dict[str, float] | None = None,
|
|
365
|
+
) -> CodeFunction | CodePrompt:
|
|
365
366
|
"""Creates a scorer.
|
|
366
367
|
|
|
367
368
|
Args:
|
|
@@ -462,8 +463,8 @@ class Project:
|
|
|
462
463
|
self.prompts = PromptBuilder(self)
|
|
463
464
|
self.scorers = ScorerBuilder(self)
|
|
464
465
|
|
|
465
|
-
self._publishable_code_functions:
|
|
466
|
-
self._publishable_prompts:
|
|
466
|
+
self._publishable_code_functions: list[CodeFunction] = []
|
|
467
|
+
self._publishable_prompts: list[CodePrompt] = []
|
|
467
468
|
|
|
468
469
|
def add_code_function(self, fn: CodeFunction):
|
|
469
470
|
self._publishable_code_functions.append(fn)
|
|
@@ -483,7 +484,7 @@ class Project:
|
|
|
483
484
|
login()
|
|
484
485
|
project_id_cache = ProjectIdCache()
|
|
485
486
|
|
|
486
|
-
definitions:
|
|
487
|
+
definitions: list[dict[str, Any]] = []
|
|
487
488
|
if self._publishable_code_functions:
|
|
488
489
|
eprint(
|
|
489
490
|
f"{bcolors.WARNING}Code functions cannot be published directly. Use `braintrust push` instead.{bcolors.ENDC}"
|
braintrust/functions/invoke.py
CHANGED
|
@@ -1,38 +1,58 @@
|
|
|
1
|
-
from typing import Any,
|
|
1
|
+
from typing import Any, Literal, TypedDict, TypeVar, overload
|
|
2
2
|
|
|
3
3
|
from sseclient import SSEClient
|
|
4
4
|
|
|
5
|
+
from .._generated_types import FunctionTypeEnum, InvokeContext
|
|
5
6
|
from ..logger import Exportable, get_span_parent_object, login, proxy_conn
|
|
6
7
|
from ..util import response_raise_for_status
|
|
7
8
|
from .constants import INVOKE_API_VERSION
|
|
8
9
|
from .stream import BraintrustInvokeError, BraintrustStream
|
|
9
10
|
|
|
10
11
|
T = TypeVar("T")
|
|
11
|
-
ModeType = Literal["auto", "parallel"]
|
|
12
|
+
ModeType = Literal["auto", "parallel", "json", "text"]
|
|
13
|
+
ObjectType = Literal["project_logs", "experiment", "dataset", "playground_logs"]
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class SpanScope(TypedDict):
|
|
17
|
+
"""Scope for operating on a single span."""
|
|
18
|
+
|
|
19
|
+
type: Literal["span"]
|
|
20
|
+
id: str
|
|
21
|
+
root_span_id: str
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class TraceScope(TypedDict):
|
|
25
|
+
"""Scope for operating on an entire trace."""
|
|
26
|
+
|
|
27
|
+
type: Literal["trace"]
|
|
28
|
+
root_span_id: str
|
|
12
29
|
|
|
13
30
|
|
|
14
31
|
@overload
|
|
15
32
|
def invoke(
|
|
16
33
|
# the permutations of arguments for a function id
|
|
17
|
-
function_id:
|
|
18
|
-
version:
|
|
19
|
-
prompt_session_id:
|
|
20
|
-
prompt_session_function_id:
|
|
21
|
-
project_name:
|
|
22
|
-
|
|
23
|
-
|
|
34
|
+
function_id: str | None = None,
|
|
35
|
+
version: str | None = None,
|
|
36
|
+
prompt_session_id: str | None = None,
|
|
37
|
+
prompt_session_function_id: str | None = None,
|
|
38
|
+
project_name: str | None = None,
|
|
39
|
+
project_id: str | None = None,
|
|
40
|
+
slug: str | None = None,
|
|
41
|
+
global_function: str | None = None,
|
|
42
|
+
function_type: FunctionTypeEnum | None = None,
|
|
24
43
|
# arguments to the function
|
|
25
44
|
input: Any = None,
|
|
26
|
-
messages:
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
45
|
+
messages: list[Any] | None = None,
|
|
46
|
+
context: InvokeContext | None = None,
|
|
47
|
+
metadata: dict[str, Any] | None = None,
|
|
48
|
+
tags: list[str] | None = None,
|
|
49
|
+
parent: Exportable | str | None = None,
|
|
50
|
+
stream: Literal[False] | None = None,
|
|
51
|
+
mode: ModeType | None = None,
|
|
52
|
+
strict: bool | None = None,
|
|
53
|
+
org_name: str | None = None,
|
|
54
|
+
api_key: str | None = None,
|
|
55
|
+
app_url: str | None = None,
|
|
36
56
|
force_login: bool = False,
|
|
37
57
|
) -> T: ...
|
|
38
58
|
|
|
@@ -40,52 +60,58 @@ def invoke(
|
|
|
40
60
|
@overload
|
|
41
61
|
def invoke(
|
|
42
62
|
# the permutations of arguments for a function id
|
|
43
|
-
function_id:
|
|
44
|
-
version:
|
|
45
|
-
prompt_session_id:
|
|
46
|
-
prompt_session_function_id:
|
|
47
|
-
project_name:
|
|
48
|
-
|
|
49
|
-
|
|
63
|
+
function_id: str | None = None,
|
|
64
|
+
version: str | None = None,
|
|
65
|
+
prompt_session_id: str | None = None,
|
|
66
|
+
prompt_session_function_id: str | None = None,
|
|
67
|
+
project_name: str | None = None,
|
|
68
|
+
project_id: str | None = None,
|
|
69
|
+
slug: str | None = None,
|
|
70
|
+
global_function: str | None = None,
|
|
71
|
+
function_type: FunctionTypeEnum | None = None,
|
|
50
72
|
# arguments to the function
|
|
51
73
|
input: Any = None,
|
|
52
|
-
messages:
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
74
|
+
messages: list[Any] | None = None,
|
|
75
|
+
context: InvokeContext | None = None,
|
|
76
|
+
metadata: dict[str, Any] | None = None,
|
|
77
|
+
tags: list[str] | None = None,
|
|
78
|
+
parent: Exportable | str | None = None,
|
|
56
79
|
stream: Literal[True] = True,
|
|
57
|
-
mode:
|
|
58
|
-
strict:
|
|
59
|
-
org_name:
|
|
60
|
-
api_key:
|
|
61
|
-
app_url:
|
|
80
|
+
mode: ModeType | None = None,
|
|
81
|
+
strict: bool | None = None,
|
|
82
|
+
org_name: str | None = None,
|
|
83
|
+
api_key: str | None = None,
|
|
84
|
+
app_url: str | None = None,
|
|
62
85
|
force_login: bool = False,
|
|
63
86
|
) -> BraintrustStream: ...
|
|
64
87
|
|
|
65
88
|
|
|
66
89
|
def invoke(
|
|
67
90
|
# the permutations of arguments for a function id
|
|
68
|
-
function_id:
|
|
69
|
-
version:
|
|
70
|
-
prompt_session_id:
|
|
71
|
-
prompt_session_function_id:
|
|
72
|
-
project_name:
|
|
73
|
-
|
|
74
|
-
|
|
91
|
+
function_id: str | None = None,
|
|
92
|
+
version: str | None = None,
|
|
93
|
+
prompt_session_id: str | None = None,
|
|
94
|
+
prompt_session_function_id: str | None = None,
|
|
95
|
+
project_name: str | None = None,
|
|
96
|
+
project_id: str | None = None,
|
|
97
|
+
slug: str | None = None,
|
|
98
|
+
global_function: str | None = None,
|
|
99
|
+
function_type: FunctionTypeEnum | None = None,
|
|
75
100
|
# arguments to the function
|
|
76
101
|
input: Any = None,
|
|
77
|
-
messages:
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
102
|
+
messages: list[Any] | None = None,
|
|
103
|
+
context: InvokeContext | None = None,
|
|
104
|
+
metadata: dict[str, Any] | None = None,
|
|
105
|
+
tags: list[str] | None = None,
|
|
106
|
+
parent: Exportable | str | None = None,
|
|
81
107
|
stream: bool = False,
|
|
82
|
-
mode:
|
|
83
|
-
strict:
|
|
84
|
-
org_name:
|
|
85
|
-
api_key:
|
|
86
|
-
app_url:
|
|
108
|
+
mode: ModeType | None = None,
|
|
109
|
+
strict: bool | None = None,
|
|
110
|
+
org_name: str | None = None,
|
|
111
|
+
api_key: str | None = None,
|
|
112
|
+
app_url: str | None = None,
|
|
87
113
|
force_login: bool = False,
|
|
88
|
-
) ->
|
|
114
|
+
) -> BraintrustStream | T:
|
|
89
115
|
"""
|
|
90
116
|
Invoke a Braintrust function, returning a `BraintrustStream` or the value as a plain
|
|
91
117
|
Python object.
|
|
@@ -93,6 +119,8 @@ def invoke(
|
|
|
93
119
|
Args:
|
|
94
120
|
input: The input to the function. This will be logged as the `input` field in the span.
|
|
95
121
|
messages: Additional OpenAI-style messages to add to the prompt (only works for llm functions).
|
|
122
|
+
context: Context for functions that operate on spans/traces (e.g., facets). Should contain
|
|
123
|
+
`object_type`, `object_id`, and `scope` fields.
|
|
96
124
|
metadata: Additional metadata to add to the span. This will be logged as the `metadata` field in the span.
|
|
97
125
|
It will also be available as the {{metadata}} field in the prompt and as the `metadata` argument
|
|
98
126
|
to the function.
|
|
@@ -118,8 +146,12 @@ def invoke(
|
|
|
118
146
|
prompt_session_id: The ID of the prompt session to invoke the function from.
|
|
119
147
|
prompt_session_function_id: The ID of the function in the prompt session to invoke.
|
|
120
148
|
project_name: The name of the project containing the function to invoke.
|
|
149
|
+
project_id: The ID of the project to use for execution context (API keys, project defaults, etc.).
|
|
150
|
+
This is not the project the function belongs to, but the project context for the invocation.
|
|
121
151
|
slug: The slug of the function to invoke.
|
|
122
152
|
global_function: The name of the global function to invoke.
|
|
153
|
+
function_type: The type of the global function to invoke. If unspecified, defaults to 'scorer'
|
|
154
|
+
for backward compatibility.
|
|
123
155
|
|
|
124
156
|
Returns:
|
|
125
157
|
The output of the function. If `stream` is True, returns a `BraintrustStream`,
|
|
@@ -149,6 +181,8 @@ def invoke(
|
|
|
149
181
|
function_id_args["slug"] = slug
|
|
150
182
|
if global_function is not None:
|
|
151
183
|
function_id_args["global_function"] = global_function
|
|
184
|
+
if function_type is not None:
|
|
185
|
+
function_id_args["function_type"] = function_type
|
|
152
186
|
|
|
153
187
|
request = dict(
|
|
154
188
|
input=input,
|
|
@@ -161,12 +195,18 @@ def invoke(
|
|
|
161
195
|
)
|
|
162
196
|
if messages is not None:
|
|
163
197
|
request["messages"] = messages
|
|
198
|
+
if context is not None:
|
|
199
|
+
request["context"] = context
|
|
164
200
|
if mode is not None:
|
|
165
201
|
request["mode"] = mode
|
|
166
202
|
if strict is not None:
|
|
167
203
|
request["strict"] = strict
|
|
168
204
|
|
|
169
205
|
headers = {"Accept": "text/event-stream" if stream else "application/json"}
|
|
206
|
+
if project_id is not None:
|
|
207
|
+
headers["x-bt-project-id"] = project_id
|
|
208
|
+
if org_name is not None:
|
|
209
|
+
headers["x-bt-org-name"] = org_name
|
|
170
210
|
|
|
171
211
|
resp = proxy_conn().post("function/invoke", json=request, headers=headers, stream=stream)
|
|
172
212
|
if resp.status_code == 500:
|
|
@@ -180,7 +220,7 @@ def invoke(
|
|
|
180
220
|
return resp.json()
|
|
181
221
|
|
|
182
222
|
|
|
183
|
-
def init_function(project_name: str, slug: str, version:
|
|
223
|
+
def init_function(project_name: str, slug: str, version: str | None = None):
|
|
184
224
|
"""
|
|
185
225
|
Creates a function that can be used as either a task or scorer in the Eval framework.
|
|
186
226
|
When used as a task, it will invoke the specified Braintrust function with the input.
|
braintrust/functions/stream.py
CHANGED
|
@@ -7,8 +7,9 @@ with utility methods to make them easy to log and convert into various formats.
|
|
|
7
7
|
|
|
8
8
|
import dataclasses
|
|
9
9
|
import json
|
|
10
|
+
from collections.abc import Generator
|
|
10
11
|
from itertools import tee
|
|
11
|
-
from typing import
|
|
12
|
+
from typing import Literal, Union
|
|
12
13
|
|
|
13
14
|
from sseclient import SSEClient
|
|
14
15
|
|
|
@@ -87,7 +88,7 @@ class BraintrustStream:
|
|
|
87
88
|
with utility methods to make them easy to log and convert into various formats.
|
|
88
89
|
"""
|
|
89
90
|
|
|
90
|
-
def __init__(self, base_stream:
|
|
91
|
+
def __init__(self, base_stream: SSEClient | list[BraintrustStreamChunk]):
|
|
91
92
|
"""
|
|
92
93
|
Initialize a BraintrustStream.
|
|
93
94
|
|
braintrust/generated_types.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""Auto-generated file (internal git SHA
|
|
1
|
+
"""Auto-generated file (internal git SHA 547fa17c0937e0e25fdf9214487be6f31c91a37a) -- do not modify"""
|
|
2
2
|
|
|
3
3
|
from ._generated_types import (
|
|
4
4
|
Acl,
|
|
@@ -32,6 +32,7 @@ from ._generated_types import (
|
|
|
32
32
|
ExperimentEvent,
|
|
33
33
|
ExtendedSavedFunctionId,
|
|
34
34
|
ExternalAttachmentReference,
|
|
35
|
+
FacetData,
|
|
35
36
|
Function,
|
|
36
37
|
FunctionData,
|
|
37
38
|
FunctionFormat,
|
|
@@ -47,10 +48,15 @@ from ._generated_types import (
|
|
|
47
48
|
GraphNode,
|
|
48
49
|
Group,
|
|
49
50
|
IfExists,
|
|
51
|
+
InvokeContext,
|
|
50
52
|
InvokeFunction,
|
|
51
53
|
InvokeParent,
|
|
54
|
+
InvokeScope,
|
|
55
|
+
MCPServer,
|
|
52
56
|
MessageRole,
|
|
53
57
|
ModelParams,
|
|
58
|
+
NullableFunctionTypeEnum,
|
|
59
|
+
NullableSavedFunctionId,
|
|
54
60
|
ObjectReference,
|
|
55
61
|
ObjectReferenceNullish,
|
|
56
62
|
OnlineScoreConfig,
|
|
@@ -86,11 +92,13 @@ from ._generated_types import (
|
|
|
86
92
|
ServiceToken,
|
|
87
93
|
SpanAttributes,
|
|
88
94
|
SpanIFrame,
|
|
95
|
+
SpanScope,
|
|
89
96
|
SpanType,
|
|
90
97
|
SSEConsoleEventData,
|
|
91
98
|
SSEProgressEventData,
|
|
92
99
|
StreamingMode,
|
|
93
100
|
ToolFunctionDefinition,
|
|
101
|
+
TraceScope,
|
|
94
102
|
UploadStatus,
|
|
95
103
|
User,
|
|
96
104
|
View,
|
|
@@ -131,6 +139,7 @@ __all__ = [
|
|
|
131
139
|
"ExperimentEvent",
|
|
132
140
|
"ExtendedSavedFunctionId",
|
|
133
141
|
"ExternalAttachmentReference",
|
|
142
|
+
"FacetData",
|
|
134
143
|
"Function",
|
|
135
144
|
"FunctionData",
|
|
136
145
|
"FunctionFormat",
|
|
@@ -146,10 +155,15 @@ __all__ = [
|
|
|
146
155
|
"GraphNode",
|
|
147
156
|
"Group",
|
|
148
157
|
"IfExists",
|
|
158
|
+
"InvokeContext",
|
|
149
159
|
"InvokeFunction",
|
|
150
160
|
"InvokeParent",
|
|
161
|
+
"InvokeScope",
|
|
162
|
+
"MCPServer",
|
|
151
163
|
"MessageRole",
|
|
152
164
|
"ModelParams",
|
|
165
|
+
"NullableFunctionTypeEnum",
|
|
166
|
+
"NullableSavedFunctionId",
|
|
153
167
|
"ObjectReference",
|
|
154
168
|
"ObjectReferenceNullish",
|
|
155
169
|
"OnlineScoreConfig",
|
|
@@ -187,9 +201,11 @@ __all__ = [
|
|
|
187
201
|
"ServiceToken",
|
|
188
202
|
"SpanAttributes",
|
|
189
203
|
"SpanIFrame",
|
|
204
|
+
"SpanScope",
|
|
190
205
|
"SpanType",
|
|
191
206
|
"StreamingMode",
|
|
192
207
|
"ToolFunctionDefinition",
|
|
208
|
+
"TraceScope",
|
|
193
209
|
"UploadStatus",
|
|
194
210
|
"User",
|
|
195
211
|
"View",
|
braintrust/git_fields.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from dataclasses import dataclass, field
|
|
2
|
-
from typing import
|
|
2
|
+
from typing import Literal
|
|
3
3
|
|
|
4
4
|
from .serializable_data_class import SerializableDataClass
|
|
5
5
|
|
|
@@ -8,21 +8,21 @@ from .serializable_data_class import SerializableDataClass
|
|
|
8
8
|
class RepoInfo(SerializableDataClass):
|
|
9
9
|
"""Information about the current HEAD of the repo."""
|
|
10
10
|
|
|
11
|
-
commit:
|
|
12
|
-
branch:
|
|
13
|
-
tag:
|
|
14
|
-
dirty:
|
|
15
|
-
author_name:
|
|
16
|
-
author_email:
|
|
17
|
-
commit_message:
|
|
18
|
-
commit_time:
|
|
19
|
-
git_diff:
|
|
11
|
+
commit: str | None = None
|
|
12
|
+
branch: str | None = None
|
|
13
|
+
tag: str | None = None
|
|
14
|
+
dirty: bool | None = None
|
|
15
|
+
author_name: str | None = None
|
|
16
|
+
author_email: str | None = None
|
|
17
|
+
commit_message: str | None = None
|
|
18
|
+
commit_time: str | None = None
|
|
19
|
+
git_diff: str | None = None
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
@dataclass
|
|
23
23
|
class GitMetadataSettings(SerializableDataClass):
|
|
24
24
|
collect: Literal["all", "some", "none"] = "all"
|
|
25
|
-
fields:
|
|
25
|
+
fields: list[str] | None = field(default_factory=list)
|
|
26
26
|
|
|
27
27
|
@classmethod
|
|
28
28
|
def merge(cls, s1: "GitMetadataSettings", s2: "GitMetadataSettings") -> "GitMetadataSettings":
|