braintrust 0.0.97 → 0.0.98

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.
package/dist/browser.js CHANGED
@@ -12,7 +12,7 @@ var DefaultAsyncLocalStorage = class {
12
12
  }
13
13
  };
14
14
  var iso = {
15
- getRepoStatus: async (_settings) => void 0,
15
+ getRepoInfo: async (_settings) => void 0,
16
16
  getPastNAncestors: async () => [],
17
17
  getEnv: (_name) => void 0,
18
18
  getCallerLocation: () => void 0,
@@ -70,9 +70,10 @@ function v4(options, buf, offset) {
70
70
  }
71
71
  var v4_default = v4;
72
72
 
73
- // ../core/js/dist/index.mjs
73
+ // ../core/js/dist/main/index.mjs
74
74
  var TRANSACTION_ID_FIELD = "_xact_id";
75
75
  var IS_MERGE_FIELD = "_is_merge";
76
+ var MERGE_PATHS_FIELD = "_merge_paths";
76
77
  var AUDIT_SOURCE_FIELD = "_audit_source";
77
78
  var AUDIT_METADATA_FIELD = "_audit_metadata";
78
79
  var VALID_SOURCES = ["app", "api", "external"];
@@ -131,6 +132,54 @@ function mergeRowBatch(rows) {
131
132
  out.push(...Object.values(rowGroups));
132
133
  return out;
133
134
  }
135
+ var DEFAULT_IS_LEGACY_DATASET = true;
136
+ function ensureDatasetRecord(r, legacy) {
137
+ if (legacy) {
138
+ return ensureLegacyDatasetRecord(r);
139
+ } else {
140
+ return ensureNewDatasetRecord(r);
141
+ }
142
+ }
143
+ function ensureLegacyDatasetRecord(r) {
144
+ if ("output" in r) {
145
+ return r;
146
+ }
147
+ const row = {
148
+ ...r,
149
+ output: r.expected
150
+ };
151
+ delete row.expected;
152
+ return row;
153
+ }
154
+ function ensureNewDatasetRecord(r) {
155
+ if ("expected" in r) {
156
+ return r;
157
+ }
158
+ const row = {
159
+ ...r,
160
+ expected: r.output
161
+ };
162
+ delete row.output;
163
+ return row;
164
+ }
165
+ function makeLegacyEvent(e) {
166
+ if (!("dataset_id" in e) || !("expected" in e)) {
167
+ return e;
168
+ }
169
+ const event = {
170
+ ...e,
171
+ output: e.expected
172
+ };
173
+ delete event.expected;
174
+ if (MERGE_PATHS_FIELD in event) {
175
+ for (const path of event[MERGE_PATHS_FIELD] || []) {
176
+ if (path.length > 0 && path[0] === "expected") {
177
+ path[0] = "output";
178
+ }
179
+ }
180
+ }
181
+ return event;
182
+ }
134
183
  var SpanTypeAttribute = /* @__PURE__ */ ((SpanTypeAttribute2) => {
135
184
  SpanTypeAttribute2["LLM"] = "llm";
136
185
  SpanTypeAttribute2["SCORE"] = "score";
@@ -596,6 +645,9 @@ var MaxRequestSize = 6 * 1024 * 1024;
596
645
  function constructJsonArray(items) {
597
646
  return `[${items.join(",")}]`;
598
647
  }
648
+ function constructLogs3Data(items) {
649
+ return `{"rows": ${constructJsonArray(items)}, "api_version": 2}`;
650
+ }
599
651
  var DefaultBatchSize = 100;
600
652
  var NumRetries = 3;
601
653
  function now() {
@@ -654,11 +706,20 @@ var BackgroundLogger = class {
654
706
  }
655
707
  postPromises.push(
656
708
  (async () => {
657
- const itemsS = constructJsonArray(items);
709
+ const dataS = constructLogs3Data(items);
658
710
  for (let i = 0; i < NumRetries; i++) {
659
711
  const startTime = now();
660
712
  try {
661
- return (await (await this.logConn.get()).post_json("logs", itemsS)).map((res) => res.id);
713
+ try {
714
+ return (await (await this.logConn.get()).post_json("logs3", dataS)).ids.map((res) => res.id);
715
+ } catch (e) {
716
+ const legacyDataS = constructJsonArray(
717
+ items.map(
718
+ (r) => JSON.stringify(makeLegacyEvent(JSON.parse(r)))
719
+ )
720
+ );
721
+ return (await (await this.logConn.get()).post_json("logs", legacyDataS)).map((res) => res.id);
722
+ }
662
723
  } catch (e) {
663
724
  const retryingText = i + 1 === NumRetries ? "" : " Retrying";
664
725
  const errMsg = (() => {
@@ -669,7 +730,7 @@ var BackgroundLogger = class {
669
730
  }
670
731
  })();
671
732
  console.warn(
672
- `log request failed. Elapsed time: ${(now() - startTime) / 1e3} seconds. Payload size: ${itemsS.length}. Error: ${errMsg}.${retryingText}`
733
+ `log request failed. Elapsed time: ${(now() - startTime) / 1e3} seconds. Payload size: ${dataS.length}. Error: ${errMsg}.${retryingText}`
673
734
  );
674
735
  }
675
736
  }
@@ -697,8 +758,21 @@ var BackgroundLogger = class {
697
758
  }
698
759
  }
699
760
  };
700
- function init(project, options = {}) {
761
+ function init(projectOrOptions, optionalOptions) {
762
+ const options = (() => {
763
+ if (typeof projectOrOptions === "string") {
764
+ return { ...optionalOptions, project: projectOrOptions };
765
+ } else {
766
+ if (optionalOptions !== void 0) {
767
+ throw new Error(
768
+ "Cannot specify options struct as both parameters. Must call either init(project, options) or init(options)."
769
+ );
770
+ }
771
+ return projectOrOptions;
772
+ }
773
+ })();
701
774
  const {
775
+ project,
702
776
  experiment,
703
777
  description,
704
778
  dataset,
@@ -710,47 +784,55 @@ function init(project, options = {}) {
710
784
  apiKey,
711
785
  orgName,
712
786
  metadata,
713
- gitMetadataSettings
714
- } = options || {};
787
+ gitMetadataSettings,
788
+ projectId,
789
+ baseExperimentId,
790
+ repoInfo
791
+ } = options;
715
792
  if (open && update) {
716
793
  throw new Error("Cannot open and update an experiment at the same time");
717
794
  }
718
795
  if (open || update) {
719
796
  if (isEmpty(experiment)) {
720
797
  const action = open ? "open" : "update";
721
- throw new Error(`Cannot ${action} an experiment without specifying its name`);
798
+ throw new Error(
799
+ `Cannot ${action} an experiment without specifying its name`
800
+ );
722
801
  }
723
- const lazyMetadata2 = new LazyValue(async () => {
724
- await login({
725
- orgName,
726
- apiKey,
727
- appUrl
728
- });
729
- const args = {
730
- project_name: project,
731
- org_name: _state.orgName,
732
- experiment_name: experiment
733
- };
734
- const response = await _state.apiConn().post_json("api/experiment/get", args);
735
- if (response.length === 0) {
736
- throw new Error(
737
- `Experiment ${experiment} not found in project ${project}.`
738
- );
739
- }
740
- const info = response[0];
741
- return {
742
- project: {
743
- id: info.project_id,
744
- name: "",
745
- fullInfo: {}
746
- },
747
- experiment: {
748
- id: info.id,
749
- name: info.name,
750
- fullInfo: info
802
+ const lazyMetadata2 = new LazyValue(
803
+ async () => {
804
+ await login({
805
+ orgName,
806
+ apiKey,
807
+ appUrl
808
+ });
809
+ const args = {
810
+ project_name: project,
811
+ project_id: projectId,
812
+ org_name: _state.orgName,
813
+ experiment_name: experiment
814
+ };
815
+ const response = await _state.apiConn().post_json("api/experiment/get", args);
816
+ if (response.length === 0) {
817
+ throw new Error(
818
+ `Experiment ${experiment} not found in project ${projectId ?? project}.`
819
+ );
751
820
  }
752
- };
753
- });
821
+ const info = response[0];
822
+ return {
823
+ project: {
824
+ id: info.project_id,
825
+ name: "",
826
+ fullInfo: {}
827
+ },
828
+ experiment: {
829
+ id: info.id,
830
+ name: info.name,
831
+ fullInfo: info
832
+ }
833
+ };
834
+ }
835
+ );
754
836
  if (open) {
755
837
  return new ReadonlyExperiment(
756
838
  lazyMetadata2
@@ -772,6 +854,7 @@ function init(project, options = {}) {
772
854
  });
773
855
  const args = {
774
856
  project_name: project,
857
+ project_id: projectId,
775
858
  org_id: _state.orgId
776
859
  };
777
860
  if (experiment) {
@@ -780,22 +863,29 @@ function init(project, options = {}) {
780
863
  if (description) {
781
864
  args["description"] = description;
782
865
  }
783
- let mergedGitMetadataSettings = {
784
- ..._state.gitMetadataSettings || {
785
- collect: "all"
866
+ const repoInfoArg = await (async () => {
867
+ if (repoInfo) {
868
+ return repoInfo;
786
869
  }
787
- };
788
- if (gitMetadataSettings) {
789
- mergedGitMetadataSettings = mergeGitMetadataSettings(
790
- mergedGitMetadataSettings,
791
- gitMetadataSettings
792
- );
793
- }
794
- const repoStatus = await isomorph_default.getRepoStatus(gitMetadataSettings);
795
- if (repoStatus) {
796
- args["repo_info"] = repoStatus;
870
+ let mergedGitMetadataSettings = {
871
+ ..._state.gitMetadataSettings || {
872
+ collect: "all"
873
+ }
874
+ };
875
+ if (gitMetadataSettings) {
876
+ mergedGitMetadataSettings = mergeGitMetadataSettings(
877
+ mergedGitMetadataSettings,
878
+ gitMetadataSettings
879
+ );
880
+ }
881
+ return await isomorph_default.getRepoInfo(mergedGitMetadataSettings);
882
+ })();
883
+ if (repoInfoArg) {
884
+ args["repo_info"] = repoInfoArg;
797
885
  }
798
- if (baseExperiment) {
886
+ if (baseExperimentId) {
887
+ args["base_exp_id"] = baseExperimentId;
888
+ } else if (baseExperiment) {
799
889
  args["base_experiment"] = baseExperiment;
800
890
  } else {
801
891
  args["ancestor_commits"] = await isomorph_default.getPastNAncestors();
@@ -846,6 +936,21 @@ function init(project, options = {}) {
846
936
  }
847
937
  return ret;
848
938
  }
939
+ function initExperiment(projectOrOptions, optionalOptions) {
940
+ const options = (() => {
941
+ if (typeof projectOrOptions === "string") {
942
+ return { ...optionalOptions, project: projectOrOptions };
943
+ } else {
944
+ if (optionalOptions !== void 0) {
945
+ throw new Error(
946
+ "Cannot specify options struct as both parameters. Must call either init(project, options) or init(options)."
947
+ );
948
+ }
949
+ return projectOrOptions;
950
+ }
951
+ })();
952
+ return init(options);
953
+ }
849
954
  function withExperiment(project, callback, options = {}) {
850
955
  console.warn(
851
956
  "withExperiment is deprecated and will be removed in a future version of braintrust. Simply create the experiment with `init`."
@@ -860,8 +965,30 @@ function withLogger(callback, options = {}) {
860
965
  const logger = initLogger(options);
861
966
  return callback(logger);
862
967
  }
863
- function initDataset(project, options = {}) {
864
- const { dataset, description, version, appUrl, apiKey, orgName } = options || {};
968
+ function initDataset(projectOrOptions, optionalOptions) {
969
+ const options = (() => {
970
+ if (typeof projectOrOptions === "string") {
971
+ return { ...optionalOptions, project: projectOrOptions };
972
+ } else {
973
+ if (optionalOptions !== void 0) {
974
+ throw new Error(
975
+ "Cannot specify options struct as both parameters. Must call either initDataset(project, options) or initDataset(options)."
976
+ );
977
+ }
978
+ return projectOrOptions;
979
+ }
980
+ })();
981
+ const {
982
+ project,
983
+ dataset,
984
+ description,
985
+ version,
986
+ appUrl,
987
+ apiKey,
988
+ orgName,
989
+ projectId,
990
+ useOutput: legacy
991
+ } = options;
865
992
  const lazyMetadata = new LazyValue(
866
993
  async () => {
867
994
  await login({
@@ -872,6 +999,7 @@ function initDataset(project, options = {}) {
872
999
  const args = {
873
1000
  org_id: _state.orgId,
874
1001
  project_name: project,
1002
+ project_id: projectId,
875
1003
  dataset_name: dataset,
876
1004
  description
877
1005
  };
@@ -890,7 +1018,7 @@ function initDataset(project, options = {}) {
890
1018
  };
891
1019
  }
892
1020
  );
893
- return new Dataset(lazyMetadata, version);
1021
+ return new Dataset(lazyMetadata, version, legacy);
894
1022
  }
895
1023
  function withDataset(project, callback, options = {}) {
896
1024
  console.warn(
@@ -960,15 +1088,27 @@ function initLogger(options = {}) {
960
1088
  return ret;
961
1089
  }
962
1090
  async function login(options = {}) {
1091
+ let { forceLogin = false } = options || {};
1092
+ if (_state.loggedIn && !forceLogin) {
1093
+ let checkUpdatedParam2 = function(varname, arg, orig) {
1094
+ if (!isEmpty(arg) && !isEmpty(orig) && arg !== orig) {
1095
+ throw new Error(
1096
+ `Re-logging in with different ${varname} (${arg}) than original (${orig}). To force re-login, pass \`forceLogin: true\``
1097
+ );
1098
+ }
1099
+ };
1100
+ var checkUpdatedParam = checkUpdatedParam2;
1101
+ ;
1102
+ checkUpdatedParam2("appUrl", options.appUrl, _state.appUrl);
1103
+ checkUpdatedParam2("apiKey", options.apiKey ? HTTPConnection.sanitize_token(options.apiKey) : void 0, _state.loginToken);
1104
+ checkUpdatedParam2("orgName", options.orgName, _state.orgName);
1105
+ return;
1106
+ }
963
1107
  const {
964
1108
  appUrl = isomorph_default.getEnv("BRAINTRUST_APP_URL") || "https://www.braintrustdata.com",
965
1109
  apiKey = isomorph_default.getEnv("BRAINTRUST_API_KEY"),
966
1110
  orgName = isomorph_default.getEnv("BRAINTRUST_ORG_NAME")
967
1111
  } = options || {};
968
- let { forceLogin = false } = options || {};
969
- if (_state.loggedIn && !forceLogin) {
970
- return;
971
- }
972
1112
  _state.resetLoginInfo();
973
1113
  _state.appUrl = appUrl;
974
1114
  let conn = null;
@@ -1177,9 +1317,10 @@ function validateAndSanitizeExperimentLogFullArgs(event, hasDataset) {
1177
1317
  return event;
1178
1318
  }
1179
1319
  var ObjectFetcher = class {
1180
- constructor(objectType, pinnedVersion) {
1320
+ constructor(objectType, pinnedVersion, mutateRecord) {
1181
1321
  this.objectType = objectType;
1182
1322
  this.pinnedVersion = pinnedVersion;
1323
+ this.mutateRecord = mutateRecord;
1183
1324
  this._fetchedData = void 0;
1184
1325
  }
1185
1326
  get id() {
@@ -1200,12 +1341,24 @@ var ObjectFetcher = class {
1200
1341
  async fetchedData() {
1201
1342
  if (this._fetchedData === void 0) {
1202
1343
  const state = await this.getState();
1203
- const resp = await state.logConn().get(`object/${this.objectType}`, {
1204
- id: await this.id,
1205
- fmt: "json2",
1206
- version: this.pinnedVersion
1207
- });
1208
- this._fetchedData = await resp.json();
1344
+ let data = void 0;
1345
+ try {
1346
+ const resp = await state.logConn().get(`object3/${this.objectType}`, {
1347
+ id: await this.id,
1348
+ fmt: "json2",
1349
+ version: this.pinnedVersion,
1350
+ api_version: "2"
1351
+ });
1352
+ data = await resp.json();
1353
+ } catch (e) {
1354
+ const resp = await state.logConn().get(`object/${this.objectType}`, {
1355
+ id: await this.id,
1356
+ fmt: "json2",
1357
+ version: this.pinnedVersion
1358
+ });
1359
+ data = await resp.json();
1360
+ }
1361
+ this._fetchedData = this.mutateRecord ? data?.map(this.mutateRecord) : data;
1209
1362
  }
1210
1363
  return this._fetchedData || [];
1211
1364
  }
@@ -1454,11 +1607,18 @@ var ReadonlyExperiment = class extends ObjectFetcher {
1454
1607
  if (record.root_span_id !== record.span_id) {
1455
1608
  continue;
1456
1609
  }
1457
- const { output, expected } = record;
1458
- yield {
1459
- input: record.input,
1460
- expected: expected ?? output
1461
- };
1610
+ const { output, expected: expectedRecord } = record;
1611
+ const expected = expectedRecord ?? output;
1612
+ if (isEmpty(expected)) {
1613
+ yield {
1614
+ input: record.input
1615
+ };
1616
+ } else {
1617
+ yield {
1618
+ input: record.input,
1619
+ expected
1620
+ };
1621
+ }
1462
1622
  }
1463
1623
  }
1464
1624
  };
@@ -1591,8 +1751,18 @@ var SpanImpl = class _SpanImpl {
1591
1751
  }
1592
1752
  };
1593
1753
  var Dataset = class extends ObjectFetcher {
1594
- constructor(lazyMetadata, pinnedVersion) {
1595
- super("dataset", pinnedVersion);
1754
+ constructor(lazyMetadata, pinnedVersion, legacy) {
1755
+ const isLegacyDataset = legacy ?? DEFAULT_IS_LEGACY_DATASET;
1756
+ if (isLegacyDataset) {
1757
+ console.warn(
1758
+ `Records will be fetched from this dataset in the legacy format, with the "expected" field renamed to "output". Please update your code to use "expected", and use \`braintrust.initDataset()\` with \`{ useOutput: false }\`, which will become the default in a future version of Braintrust.`
1759
+ );
1760
+ }
1761
+ super(
1762
+ "dataset",
1763
+ pinnedVersion,
1764
+ (r) => ensureDatasetRecord(r, isLegacyDataset)
1765
+ );
1596
1766
  this.lazyMetadata = lazyMetadata;
1597
1767
  const logConn = new LazyValue(
1598
1768
  () => this.getState().then((state) => state.logConn())
@@ -1624,19 +1794,21 @@ var Dataset = class extends ObjectFetcher {
1624
1794
  *
1625
1795
  * @param event The event to log.
1626
1796
  * @param event.input The argument that uniquely define an input case (an arbitrary, JSON serializable object).
1627
- * @param event.output The output of your application, including post-processing (an arbitrary, JSON serializable object).
1797
+ * @param event.expected The output of your application, including post-processing (an arbitrary, JSON serializable object).
1628
1798
  * @param event.metadata (Optional) a dictionary with additional data about the test example, model outputs, or just
1629
1799
  * about anything else that's relevant, that you can use to help find and analyze examples later. For example, you could log the
1630
1800
  * `prompt`, example's `id`, or anything else that would be useful to slice/dice later. The values in `metadata` can be any
1631
1801
  * JSON-serializable type, but its keys must be strings.
1632
1802
  * @param event.id (Optional) a unique identifier for the event. If you don't provide one, Braintrust will generate one for you.
1803
+ * @param event.output: (Deprecated) The output of your application. Use `expected` instead.
1633
1804
  * @returns The `id` of the logged record.
1634
1805
  */
1635
1806
  insert({
1636
1807
  input,
1637
- output,
1808
+ expected,
1638
1809
  metadata,
1639
- id
1810
+ id,
1811
+ output
1640
1812
  }) {
1641
1813
  if (metadata !== void 0) {
1642
1814
  for (const key of Object.keys(metadata)) {
@@ -1645,11 +1817,16 @@ var Dataset = class extends ObjectFetcher {
1645
1817
  }
1646
1818
  }
1647
1819
  }
1820
+ if (expected && output) {
1821
+ throw new Error(
1822
+ "Only one of expected or output (deprecated) can be specified. Prefer expected."
1823
+ );
1824
+ }
1648
1825
  const rowId = id || v4_default();
1649
1826
  const args = new LazyValue(async () => ({
1650
1827
  id: rowId,
1651
- inputs: input,
1652
- output,
1828
+ input,
1829
+ expected: expected === void 0 ? output : expected,
1653
1830
  project_id: (await this.project).id,
1654
1831
  dataset_id: await this.id,
1655
1832
  created: (/* @__PURE__ */ new Date()).toISOString(),
@@ -1968,7 +2145,6 @@ var WrapperStream = class {
1968
2145
  // src/browser.ts
1969
2146
  configureBrowser();
1970
2147
  export {
1971
- Dataset,
1972
2148
  Experiment,
1973
2149
  Logger,
1974
2150
  NOOP_SPAN,
@@ -1983,6 +2159,7 @@ export {
1983
2159
  getSpanParentObject,
1984
2160
  init,
1985
2161
  initDataset,
2162
+ initExperiment,
1986
2163
  initLogger,
1987
2164
  log,
1988
2165
  login,