braintrust 0.4.1 → 0.4.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1047e872fe3a0acf40117bd9a0fcbf4e5024edbe3c1eb3d3bd1e32f60e5ffb18
4
- data.tar.gz: e4c412abf3cf748ff157248feb821724ba4ffb76b67aecd8d1735179572afa93
3
+ metadata.gz: 1afc7372056311aec7ccaaae11c5d7a9204cdfc826a34db1bd67126769d253e3
4
+ data.tar.gz: 6492ea96b8f616c05241983baaeb935cdc3d206ced063781c44981b6d0817e64
5
5
  SHA512:
6
- metadata.gz: 41f183ac2bb20f64bca5c576f0decabdea9b7a4bcb46cbcf0c66292eb34f7e75a3b91516cd5520b4a3e207669eff0fa212afd1f75c1d6b172a44ea27bbc91e4b
7
- data.tar.gz: 8a98b9ea710b69ac0b4e22cbdbed2b55bfab0d25db5fda2afc872931ce27a4eb9183433db03be6cedcb295dfca2f1fa43583620d848c55e9fa8b19629ecbfb8e
6
+ metadata.gz: e6471fc6f3b8beba508dfef0deebfa5f10b1044aaf44817cfb341a71396655ec034b9eca70aaf2e4efb0afa9007a5c284564b3d3471ba1dd18edfd336ea51cb8
7
+ data.tar.gz: 333ad63d354f902c5e4c5d25d2d67e5ed4f4843fcbfeb7c33a6f273de9dcd7b1c77202417816dd9b834881a3d3a833c68418e81c9a1365ec2e503da3ada027ac
@@ -166,14 +166,14 @@ module Braintrust
166
166
  record
167
167
  end
168
168
 
169
- # Build origin JSON for tracing/linking
169
+ # Build origin pointer for tracing/linking
170
170
  # @param raw [Hash] Raw record from API
171
171
  # @param dataset_id [String] Dataset ID (fallback if not in record)
172
- # @return [String, nil] JSON-serialized origin, or nil if record lacks required fields
172
+ # @return [Hash, nil] Origin pointer, or nil if record lacks required fields
173
173
  def build_origin(raw, dataset_id)
174
174
  return nil unless raw["id"] && raw["_xact_id"]
175
175
 
176
- Internal::Origin.to_json(
176
+ Internal::Origin.build(
177
177
  object_type: "dataset",
178
178
  object_id: raw["dataset_id"] || dataset_id,
179
179
  id: raw["id"],
@@ -95,7 +95,7 @@ module Braintrust
95
95
  set_json_attr(eval_span, "braintrust.expected_json", kase.expected) unless kase.expected.nil?
96
96
  set_json_attr(eval_span, "braintrust.metadata", kase.metadata) if kase.metadata
97
97
  eval_span.set_attribute("braintrust.tags", kase.tags) if kase.tags
98
- eval_span.set_attribute("braintrust.origin", kase.origin) if kase.origin
98
+ set_json_attr(eval_span, "braintrust.origin", kase.origin) if kase.origin
99
99
 
100
100
  # Run task
101
101
  begin
@@ -275,9 +275,7 @@ module Braintrust
275
275
  def report_progress(eval_span, kase, **fields)
276
276
  return unless eval_context.on_progress
277
277
  progress = {"id" => eval_span.context.hex_span_id}.merge(fields.transform_keys(&:to_s))
278
- if kase.origin
279
- progress["origin"] = kase.origin.is_a?(String) ? JSON.parse(kase.origin) : kase.origin
280
- end
278
+ progress["origin"] = kase.origin if kase.origin
281
279
  eval_context.on_progress.call(progress)
282
280
  rescue => e
283
281
  Braintrust.logger.warn("on_progress callback error: #{e.message}")
@@ -336,7 +336,7 @@ module Braintrust
336
336
  # Use pinned version if available, otherwise compute from max(_xact_id)
337
337
  version = dataset_obj.version
338
338
  version ||= cases
339
- .filter_map { |c| c[:origin] && JSON.parse(c[:origin])["_xact_id"] }
339
+ .filter_map { |c| c[:origin]&.dig("_xact_id") }
340
340
  .max
341
341
 
342
342
  {cases: cases, dataset_id: dataset_obj.id, dataset_version: version}
@@ -1,27 +1,27 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "json"
4
-
5
3
  module Braintrust
6
4
  module Internal
7
- # Origin provides serialization for source object pointers in Braintrust.
8
- # Used internally to link spans back to their source records (e.g., dataset rows).
5
+ # Origin builds source object pointers, which link spans back to the record
6
+ # they came from (e.g., a dataset row). Pointers stay Hashes internally and
7
+ # are serialized once at the boundary that needs them, so that inbound
8
+ # pointers from the wire and ones we build here have the same shape.
9
9
  module Origin
10
- # Serialize an origin pointer to JSON
10
+ # Build an origin pointer
11
11
  # @param object_type [String] Type of source object (e.g., "dataset", "playground_logs")
12
12
  # @param object_id [String] ID of the source object
13
13
  # @param id [String] ID of the specific record within the source
14
14
  # @param xact_id [String] Transaction ID
15
15
  # @param created [String, nil] Creation timestamp
16
- # @return [String] JSON-serialized origin
17
- def self.to_json(object_type:, object_id:, id:, xact_id:, created:)
18
- JSON.dump({
19
- object_type: object_type,
20
- object_id: object_id,
21
- id: id,
22
- _xact_id: xact_id,
23
- created: created
24
- })
16
+ # @return [Hash] Origin pointer with string keys, matching the wire format
17
+ def self.build(object_type:, object_id:, id:, xact_id:, created:)
18
+ {
19
+ "object_type" => object_type,
20
+ "object_id" => object_id,
21
+ "id" => id,
22
+ "_xact_id" => xact_id,
23
+ "created" => created
24
+ }
25
25
  end
26
26
  end
27
27
  end
@@ -2,12 +2,19 @@
2
2
 
3
3
  require "json"
4
4
 
5
+ require_relative "../../eval/case"
6
+
5
7
  module Braintrust
6
8
  module Server
7
9
  module Services
8
10
  # Framework-agnostic service for running evaluations and streaming SSE results.
9
11
  # Must be long-lived (not per-request) to preserve the @state_cache across requests.
10
12
  class Eval
13
+ # Row fields this SDK understands, derived from the Case contract so that
14
+ # adding a field there carries it through here. Anything else on an
15
+ # inbound row is a field this version has no code for, and is ignored.
16
+ CASE_FIELDS = Braintrust::Eval::Case.members.map(&:to_s).freeze
17
+
11
18
  def initialize(evaluators)
12
19
  @evaluators = evaluators
13
20
  @state_mutex = Mutex.new
@@ -177,9 +184,10 @@ module Braintrust
177
184
  # Returns [cases, dataset] where exactly one is non-nil.
178
185
  def resolve_data_source(data)
179
186
  if data.key?("data")
180
- cases = data["data"].map do |d|
181
- {input: d["input"], expected: d["expected"]}
182
- end
187
+ # Rows arrive inline from the Playground carrying tags, metadata and
188
+ # an origin pointer back to the row they came from. Carry them all:
189
+ # the Playground matches streamed results to its grid by origin.
190
+ cases = data["data"].map { |row| row.slice(*CASE_FIELDS).transform_keys(&:to_sym) }
183
191
  [cases, nil]
184
192
  elsif data.key?("dataset_id")
185
193
  [nil, Braintrust::Dataset::ID.new(id: data["dataset_id"])]
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Braintrust
4
- VERSION = "0.4.1"
4
+ VERSION = "0.4.2"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: braintrust
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Braintrust