braintrust 0.0.89 → 0.0.91

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/index.js CHANGED
@@ -7766,7 +7766,9 @@ async function getRepoStatus() {
7766
7766
  async () => (await git.raw(["rev-parse", "--abbrev-ref", "HEAD"])).trim()
7767
7767
  );
7768
7768
  if (dirty) {
7769
- git_diff = await attempt(async () => truncateToByteLimit(await git.raw(["diff", "HEAD"])));
7769
+ git_diff = await attempt(
7770
+ async () => truncateToByteLimit(await git.raw(["diff", "HEAD"]))
7771
+ );
7770
7772
  }
7771
7773
  return {
7772
7774
  commit,
@@ -7875,6 +7877,10 @@ var v4_default = v4;
7875
7877
  // ../core/js/dist/index.mjs
7876
7878
  var TRANSACTION_ID_FIELD = "_xact_id";
7877
7879
  var IS_MERGE_FIELD = "_is_merge";
7880
+ var AUDIT_SOURCE_FIELD = "_audit_source";
7881
+ var AUDIT_METADATA_FIELD = "_audit_metadata";
7882
+ var VALID_SOURCES = ["app", "api", "external"];
7883
+ var PARENT_ID_FIELD = "_parent_id";
7878
7884
  function mergeDicts(mergeInto, mergeFrom) {
7879
7885
  for (const [k, mergeFromV] of Object.entries(mergeFrom)) {
7880
7886
  const mergeIntoV = mergeInto[k];
@@ -7887,6 +7893,7 @@ function mergeDicts(mergeInto, mergeFrom) {
7887
7893
  mergeInto[k] = mergeFromV;
7888
7894
  }
7889
7895
  }
7896
+ return mergeInto;
7890
7897
  }
7891
7898
  function generateMergedRowKey(row) {
7892
7899
  return JSON.stringify(
@@ -7928,6 +7935,15 @@ function mergeRowBatch(rows) {
7928
7935
  out.push(...Object.values(rowGroups));
7929
7936
  return out;
7930
7937
  }
7938
+ var SpanTypeAttribute = /* @__PURE__ */ ((SpanTypeAttribute2) => {
7939
+ SpanTypeAttribute2["LLM"] = "llm";
7940
+ SpanTypeAttribute2["SCORE"] = "score";
7941
+ SpanTypeAttribute2["FUNCTION"] = "function";
7942
+ SpanTypeAttribute2["EVAL"] = "eval";
7943
+ SpanTypeAttribute2["TASK"] = "task";
7944
+ SpanTypeAttribute2["TOOL"] = "tool";
7945
+ return SpanTypeAttribute2;
7946
+ })(SpanTypeAttribute || {});
7931
7947
 
7932
7948
  // src/util.ts
7933
7949
  var GLOBAL_PROJECT = "Global";
@@ -7950,6 +7966,9 @@ function runFinally(f, finallyF) {
7950
7966
  function getCurrentUnixTimestamp() {
7951
7967
  return (/* @__PURE__ */ new Date()).getTime() / 1e3;
7952
7968
  }
7969
+ function isEmpty(a) {
7970
+ return a === void 0 || a === null;
7971
+ }
7953
7972
 
7954
7973
  // src/logger.ts
7955
7974
  var NoopSpan = class {
@@ -7961,6 +7980,8 @@ var NoopSpan = class {
7961
7980
  }
7962
7981
  log(_) {
7963
7982
  }
7983
+ logFeedback(event) {
7984
+ }
7964
7985
  traced(callback, _1) {
7965
7986
  return callback(this);
7966
7987
  }
@@ -8135,6 +8156,70 @@ var HTTPConnection = class _HTTPConnection {
8135
8156
  return await resp.json();
8136
8157
  }
8137
8158
  };
8159
+ function logFeedbackImpl(bgLogger, parentIds, {
8160
+ id,
8161
+ expected,
8162
+ scores,
8163
+ metadata: inputMetadata,
8164
+ comment,
8165
+ source: inputSource
8166
+ }) {
8167
+ const source = inputSource ?? "external";
8168
+ if (!VALID_SOURCES.includes(source)) {
8169
+ throw new Error(`source must be one of ${VALID_SOURCES}`);
8170
+ }
8171
+ if (isEmpty(scores) && isEmpty(expected) && isEmpty(comment)) {
8172
+ throw new Error(
8173
+ "At least one of scores, expected, or comment must be specified"
8174
+ );
8175
+ }
8176
+ const validatedEvent = validateAndSanitizeExperimentLogPartialArgs({
8177
+ scores,
8178
+ metadata: inputMetadata,
8179
+ expected
8180
+ });
8181
+ let { metadata, ...updateEvent } = validatedEvent;
8182
+ updateEvent = Object.fromEntries(
8183
+ Object.entries(updateEvent).filter(([_, v]) => !isEmpty(v))
8184
+ );
8185
+ const trueParentIds = (async () => {
8186
+ const { kind, ...ids } = await parentIds;
8187
+ return ids;
8188
+ })();
8189
+ if (Object.keys(updateEvent).length > 0) {
8190
+ const record = (async () => {
8191
+ return {
8192
+ id,
8193
+ ...updateEvent,
8194
+ ...await trueParentIds,
8195
+ [AUDIT_SOURCE_FIELD]: source,
8196
+ [AUDIT_METADATA_FIELD]: metadata,
8197
+ [IS_MERGE_FIELD]: true
8198
+ };
8199
+ })();
8200
+ bgLogger.log([record]);
8201
+ }
8202
+ if (!isEmpty(comment)) {
8203
+ const record = (async () => {
8204
+ return {
8205
+ id: v4_default(),
8206
+ created: (/* @__PURE__ */ new Date()).toISOString(),
8207
+ origin: {
8208
+ // NOTE: We do not know (or care?) what the transaction id of the row that
8209
+ // we're commenting on is here, so we omit it.
8210
+ id
8211
+ },
8212
+ comment: {
8213
+ text: comment
8214
+ },
8215
+ ...await trueParentIds,
8216
+ [AUDIT_SOURCE_FIELD]: source,
8217
+ [AUDIT_METADATA_FIELD]: metadata
8218
+ };
8219
+ })();
8220
+ bgLogger.log([record]);
8221
+ }
8222
+ }
8138
8223
  var Logger = class {
8139
8224
  constructor(lazyMetadata, logOptions = {}) {
8140
8225
  // For type identification.
@@ -8213,6 +8298,14 @@ var Logger = class {
8213
8298
  })();
8214
8299
  }
8215
8300
  }
8301
+ async lazyParentIds() {
8302
+ return {
8303
+ kind: "project_log",
8304
+ org_id: await this.org_id,
8305
+ project_id: (await this.project).id,
8306
+ log_id: "g"
8307
+ };
8308
+ }
8216
8309
  /**
8217
8310
  * Lower-level alternative to `traced`, which does not automatically end the span or mark it as current.
8218
8311
  *
@@ -8220,19 +8313,27 @@ var Logger = class {
8220
8313
  */
8221
8314
  startSpan(args) {
8222
8315
  const { name, ...argsRest } = args ?? {};
8223
- const parentIds = (async () => ({
8224
- kind: "project_log",
8225
- org_id: await this.org_id,
8226
- project_id: (await this.project).id,
8227
- log_id: "g"
8228
- }))();
8229
8316
  return new SpanImpl({
8230
- parentIds,
8317
+ parentIds: this.lazyParentIds(),
8231
8318
  bgLogger: this.bgLogger,
8232
8319
  name: name ?? "root",
8233
8320
  ...argsRest
8234
8321
  });
8235
8322
  }
8323
+ /**
8324
+ * Log feedback to an event. Feedback is used to save feedback scores, set an expected value, or add a comment.
8325
+ *
8326
+ * @param event
8327
+ * @param event.id The id of the event to log feedback for. This is the `id` returned by `log` or accessible as the `id` field of a span.
8328
+ * @param event.scores (Optional) a dictionary of numeric values (between 0 and 1) to log. These scores will be merged into the existing scores for the event.
8329
+ * @param event.expected (Optional) the ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to determine if your `output` value is correct or not.
8330
+ * @param event.comment (Optional) an optional comment string to log about the event.
8331
+ * @param event.metadata (Optional) a dictionary with additional data about the feedback. If you have a `user_id`, you can log it here and access it in the Braintrust UI.
8332
+ * @param event.source (Optional) the source of the feedback. Must be one of "external" (default), "app", or "api".
8333
+ */
8334
+ logFeedback(event) {
8335
+ logFeedbackImpl(this.bgLogger, this.lazyParentIds(), event);
8336
+ }
8236
8337
  /*
8237
8338
  * Flush any pending logs to the server.
8238
8339
  */
@@ -8824,6 +8925,13 @@ var Experiment = class {
8824
8925
  () => span.end()
8825
8926
  );
8826
8927
  }
8928
+ async lazyParentIds() {
8929
+ return {
8930
+ kind: "experiment",
8931
+ project_id: (await this.project).id,
8932
+ experiment_id: await this.id
8933
+ };
8934
+ }
8827
8935
  /**
8828
8936
  * Lower-level alternative to `traced`, which does not automatically end the span or mark it as current.
8829
8937
  *
@@ -8831,13 +8939,8 @@ var Experiment = class {
8831
8939
  */
8832
8940
  startSpan(args) {
8833
8941
  const { name, ...argsRest } = args ?? {};
8834
- const parentIds = (async () => ({
8835
- kind: "experiment",
8836
- project_id: (await this.project).id,
8837
- experiment_id: await this.id
8838
- }))();
8839
8942
  return new SpanImpl({
8840
- parentIds,
8943
+ parentIds: this.lazyParentIds(),
8841
8944
  bgLogger: this.bgLogger,
8842
8945
  name: name ?? "root",
8843
8946
  ...argsRest
@@ -8899,6 +9002,20 @@ var Experiment = class {
8899
9002
  metrics
8900
9003
  };
8901
9004
  }
9005
+ /**
9006
+ * Log feedback to an event in the experiment. Feedback is used to save feedback scores, set an expected value, or add a comment.
9007
+ *
9008
+ * @param event
9009
+ * @param event.id The id of the event to log feedback for. This is the `id` returned by `log` or accessible as the `id` field of a span.
9010
+ * @param event.scores (Optional) a dictionary of numeric values (between 0 and 1) to log. These scores will be merged into the existing scores for the event.
9011
+ * @param event.expected (Optional) the ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to determine if your `output` value is correct or not.
9012
+ * @param event.comment (Optional) an optional comment string to log about the event.
9013
+ * @param event.metadata (Optional) a dictionary with additional data about the feedback. If you have a `user_id`, you can log it here and access it in the Braintrust UI.
9014
+ * @param event.source (Optional) the source of the feedback. Must be one of "external" (default), "app", or "api".
9015
+ */
9016
+ logFeedback(event) {
9017
+ logFeedbackImpl(this.bgLogger, this.lazyParentIds(), event);
9018
+ }
8902
9019
  /**
8903
9020
  * Flush any pending rows to the server.
8904
9021
  */
@@ -8949,10 +9066,12 @@ var SpanImpl = class _SpanImpl {
8949
9066
  this.rowIds = {
8950
9067
  id,
8951
9068
  span_id,
8952
- root_span_id: args.parentSpanInfo?.root_span_id ?? span_id
9069
+ root_span_id: "parentSpanInfo" in args && args.parentSpanInfo?.root_span_id ? args.parentSpanInfo.root_span_id : span_id
8953
9070
  };
8954
- if (args.parentSpanInfo) {
9071
+ if ("parentSpanInfo" in args && args.parentSpanInfo?.span_id) {
8955
9072
  this.internalData.span_parents = [args.parentSpanInfo.span_id];
9073
+ } else if ("parentId" in args && !isEmpty(args.parentId)) {
9074
+ this.rowIds[PARENT_ID_FIELD] = args.parentId;
8956
9075
  }
8957
9076
  this.isMerge = false;
8958
9077
  const { id: _id, ...eventRest } = args.event ?? {};
@@ -8976,16 +9095,26 @@ var SpanImpl = class _SpanImpl {
8976
9095
  if (sanitizedAndInternalData.metrics?.end) {
8977
9096
  this.loggedEndTime = sanitizedAndInternalData.metrics?.end;
8978
9097
  }
9098
+ const parentIds = (async () => {
9099
+ const { kind, ...ids } = await this.parentIds;
9100
+ return ids;
9101
+ })();
8979
9102
  const record = (async () => {
8980
9103
  return {
8981
9104
  ...sanitizedAndInternalData,
8982
9105
  ...this.rowIds,
8983
- ...await this.parentIds,
9106
+ ...await parentIds,
8984
9107
  [IS_MERGE_FIELD]: this.isMerge
8985
9108
  };
8986
9109
  })();
8987
9110
  this.bgLogger.log([record]);
8988
9111
  }
9112
+ logFeedback(event) {
9113
+ logFeedbackImpl(this.bgLogger, this.parentIds, {
9114
+ ...event,
9115
+ id: this.id
9116
+ });
9117
+ }
8989
9118
  traced(callback, args) {
8990
9119
  const { setCurrent, ...argsRest } = args ?? {};
8991
9120
  const span = this.startSpan(argsRest);
@@ -9375,7 +9504,7 @@ async function runEvaluator(experiment, evaluator, progressReporter, filters) {
9375
9504
  }
9376
9505
  span.log({ input: datum.input, output });
9377
9506
  },
9378
- { name: "task" }
9507
+ { name: "task", spanAttributes: { type: SpanTypeAttribute.TASK } }
9379
9508
  );
9380
9509
  rootSpan.log({ output });
9381
9510
  const scoringArgs = { ...datum, metadata, output };
@@ -9398,6 +9527,9 @@ async function runEvaluator(experiment, evaluator, progressReporter, filters) {
9398
9527
  },
9399
9528
  {
9400
9529
  name: score.name || `scorer_${score_idx}`,
9530
+ spanAttributes: {
9531
+ type: SpanTypeAttribute.SCORE
9532
+ },
9401
9533
  event: { input: scoringArgs }
9402
9534
  }
9403
9535
  );
@@ -9437,6 +9569,9 @@ async function runEvaluator(experiment, evaluator, progressReporter, filters) {
9437
9569
  } else {
9438
9570
  return await experiment.traced(callback, {
9439
9571
  name: "eval",
9572
+ spanAttributes: {
9573
+ type: SpanTypeAttribute.EVAL
9574
+ },
9440
9575
  event: {
9441
9576
  input: datum.input,
9442
9577
  expected: datum.expected
@@ -9532,6 +9667,7 @@ function wrapOpenAI(openai) {
9532
9667
  return openai;
9533
9668
  }
9534
9669
  }
9670
+ globalThis.__inherited_braintrust_wrap_openai = wrapOpenAI;
9535
9671
  function wrapOpenAIv4(openai) {
9536
9672
  let completionProxy = new Proxy(openai.chat.completions, {
9537
9673
  get(target, name, receiver) {
@@ -9550,6 +9686,15 @@ function wrapOpenAIv4(openai) {
9550
9686
  return Reflect.get(target, name, receiver);
9551
9687
  }
9552
9688
  });
9689
+ let embeddingProxy = new Proxy(openai.embeddings, {
9690
+ get(target, name, receiver) {
9691
+ const baseVal = Reflect.get(target, name, receiver);
9692
+ if (name === "create") {
9693
+ return wrapEmbeddings(baseVal.bind(target));
9694
+ }
9695
+ return baseVal;
9696
+ }
9697
+ });
9553
9698
  let betaProxy;
9554
9699
  if (openai.beta?.chat?.completions?.stream) {
9555
9700
  let betaChatCompletionProxy = new Proxy(openai?.beta?.chat.completions, {
@@ -9583,6 +9728,9 @@ function wrapOpenAIv4(openai) {
9583
9728
  if (name === "chat") {
9584
9729
  return chatProxy;
9585
9730
  }
9731
+ if (name === "embeddings") {
9732
+ return embeddingProxy;
9733
+ }
9586
9734
  if (name === "beta" && betaProxy) {
9587
9735
  return betaProxy;
9588
9736
  }
@@ -9592,10 +9740,13 @@ function wrapOpenAIv4(openai) {
9592
9740
  return proxy;
9593
9741
  }
9594
9742
  function wrapBetaChatCompletion(completion) {
9595
- return async (params) => {
9743
+ return (params) => {
9596
9744
  const { messages, ...rest } = params;
9597
9745
  const span = startSpan({
9598
9746
  name: "OpenAI Chat Completion",
9747
+ spanAttributes: {
9748
+ type: SpanTypeAttribute.LLM
9749
+ },
9599
9750
  event: {
9600
9751
  input: messages,
9601
9752
  metadata: {
@@ -9604,7 +9755,7 @@ function wrapBetaChatCompletion(completion) {
9604
9755
  }
9605
9756
  });
9606
9757
  const startTime = getCurrentUnixTimestamp();
9607
- const ret = await completion(params);
9758
+ const ret = completion(params);
9608
9759
  let first2 = true;
9609
9760
  ret.on("chunk", (_chunk) => {
9610
9761
  if (first2) {
@@ -9629,10 +9780,13 @@ function wrapBetaChatCompletion(completion) {
9629
9780
  };
9630
9781
  }
9631
9782
  function wrapChatCompletion(completion) {
9632
- return async (params) => {
9783
+ return async (params, options) => {
9633
9784
  const { messages, ...rest } = params;
9634
9785
  const span = startSpan({
9635
9786
  name: "OpenAI Chat Completion",
9787
+ spanAttributes: {
9788
+ type: SpanTypeAttribute.LLM
9789
+ },
9636
9790
  event: {
9637
9791
  input: messages,
9638
9792
  metadata: {
@@ -9642,11 +9796,14 @@ function wrapChatCompletion(completion) {
9642
9796
  });
9643
9797
  if (params.stream) {
9644
9798
  const startTime = getCurrentUnixTimestamp();
9645
- const ret = await completion(params);
9799
+ const ret = await completion(params, options);
9646
9800
  return new WrapperStream(span, startTime, ret);
9647
9801
  } else {
9648
9802
  try {
9649
- const ret = await completion(params);
9803
+ const ret = await completion(
9804
+ params,
9805
+ options
9806
+ );
9650
9807
  const { messages: messages2, ...rest2 } = params;
9651
9808
  span.log({
9652
9809
  input: messages2,
@@ -9667,6 +9824,37 @@ function wrapChatCompletion(completion) {
9667
9824
  }
9668
9825
  };
9669
9826
  }
9827
+ function wrapEmbeddings(create) {
9828
+ return async (params, options) => {
9829
+ const { input, ...rest } = params;
9830
+ return traced(
9831
+ async (span) => {
9832
+ const result = await create(params, options);
9833
+ const output = result.data[0];
9834
+ span.log({
9835
+ output,
9836
+ metrics: {
9837
+ tokens: result.usage?.total_tokens,
9838
+ prompt_tokens: result.usage?.prompt_tokens
9839
+ }
9840
+ });
9841
+ return result;
9842
+ },
9843
+ {
9844
+ name: "OpenAI Embedding",
9845
+ spanAttributes: {
9846
+ type: SpanTypeAttribute.LLM
9847
+ },
9848
+ event: {
9849
+ input,
9850
+ metadata: {
9851
+ ...rest
9852
+ }
9853
+ }
9854
+ }
9855
+ );
9856
+ };
9857
+ }
9670
9858
  var WrapperStream = class {
9671
9859
  constructor(span, startTime, iter) {
9672
9860
  this.span = span;
package/dist/logger.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /// <reference lib="dom" />
2
- import { IS_MERGE_FIELD } from "@braintrust/core";
2
+ import { IS_MERGE_FIELD, PARENT_ID_FIELD, Source, AUDIT_SOURCE_FIELD, AUDIT_METADATA_FIELD } from "@braintrust/core";
3
3
  import { IsoAsyncLocalStorage } from "./isomorph";
4
4
  export type Metadata = Record<string, unknown>;
5
5
  export type SetCurrentArg = {
@@ -10,6 +10,7 @@ export type StartSpanArgs = {
10
10
  name?: string;
11
11
  spanAttributes?: Record<any, any>;
12
12
  startTime?: number;
13
+ parentId?: string;
13
14
  event?: StartSpanEventArgs;
14
15
  };
15
16
  export type EndSpanArgs = {
@@ -41,6 +42,12 @@ export interface Span {
41
42
  * @param event: Data to be logged. See `Experiment.log` for full details.
42
43
  */
43
44
  log(event: ExperimentLogPartialArgs): void;
45
+ /**
46
+ * Add feedback to the current span. Unlike `Experiment.logFeedback` and `Logger.logFeedback`, this method does not accept an id parameter, because it logs feedback to the current span.
47
+ *
48
+ * @param event: Data to be logged. See `Experiment.logFeedback` for full details.
49
+ */
50
+ logFeedback(event: Omit<LogFeedbackFullArgs, "id">): void;
44
51
  /**
45
52
  * Create a new span and run the provided callback. This is useful if you want to log more detailed trace information beyond the scope of a single log event. Data logged over several calls to `Span.log` will be merged into one logical row.
46
53
  *
@@ -51,6 +58,7 @@ export interface Span {
51
58
  * @param args.span_attributes Optional additional attributes to attach to the span, such as a type name.
52
59
  * @param args.start_time Optional start time of the span, as a timestamp in seconds.
53
60
  * @param args.setCurrent If true (the default), the span will be marked as the currently-active span for the duration of the callback.
61
+ * @param args.parentId Optional id of the parent span. If not provided, the current span will be used (depending on context). This is useful for adding spans to an existing trace.
54
62
  * @param args.event Data to be logged. See `Experiment.log` for full details.
55
63
  * @Returns The result of running `callback`.
56
64
  */
@@ -88,6 +96,7 @@ export declare class NoopSpan implements Span {
88
96
  kind: "span";
89
97
  constructor();
90
98
  log(_: ExperimentLogPartialArgs): void;
99
+ logFeedback(event: Omit<LogFeedbackFullArgs, "id">): void;
91
100
  traced<R>(callback: (span: Span) => R, _1: StartSpanArgs & SetCurrentArg): R;
92
101
  startSpan(_1?: StartSpanArgs): this;
93
102
  end(args?: EndSpanArgs): number;
@@ -183,12 +192,25 @@ export declare class Logger<IsAsyncFlush extends boolean> {
183
192
  * See `Span.traced` for full details.
184
193
  */
185
194
  traced<R>(callback: (span: Span) => R, args?: StartSpanArgs & SetCurrentArg): PromiseUnless<IsAsyncFlush, R>;
195
+ private lazyParentIds;
186
196
  /**
187
197
  * Lower-level alternative to `traced`, which does not automatically end the span or mark it as current.
188
198
  *
189
199
  * See `traced` for full details.
190
200
  */
191
201
  startSpan(args?: StartSpanArgs): Span;
202
+ /**
203
+ * Log feedback to an event. Feedback is used to save feedback scores, set an expected value, or add a comment.
204
+ *
205
+ * @param event
206
+ * @param event.id The id of the event to log feedback for. This is the `id` returned by `log` or accessible as the `id` field of a span.
207
+ * @param event.scores (Optional) a dictionary of numeric values (between 0 and 1) to log. These scores will be merged into the existing scores for the event.
208
+ * @param event.expected (Optional) the ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to determine if your `output` value is correct or not.
209
+ * @param event.comment (Optional) an optional comment string to log about the event.
210
+ * @param event.metadata (Optional) a dictionary with additional data about the feedback. If you have a `user_id`, you can log it here and access it in the Braintrust UI.
211
+ * @param event.source (Optional) the source of the feedback. Must be one of "external" (default), "app", or "api".
212
+ */
213
+ logFeedback(event: LogFeedbackFullArgs): void;
192
214
  flush(): Promise<void>;
193
215
  get asyncFlush(): IsAsyncFlush | undefined;
194
216
  }
@@ -211,10 +233,25 @@ export type OtherExperimentLogFields = {
211
233
  };
212
234
  export type ExperimentLogPartialArgs = Partial<OtherExperimentLogFields> & Partial<InputField | InputsField>;
213
235
  export type ExperimentLogFullArgs = Partial<Omit<OtherExperimentLogFields, "scores">> & Required<Pick<OtherExperimentLogFields, "scores">> & Partial<InputField | InputsField> & Partial<IdField>;
236
+ export type LogFeedbackFullArgs = IdField & Partial<Omit<OtherExperimentLogFields, "output" | "metrics" | "datasetRecordId"> & {
237
+ comment: string;
238
+ source: Source;
239
+ }>;
240
+ export type LogCommentFullArgs = IdField & {
241
+ created: string;
242
+ origin: {
243
+ id: string;
244
+ };
245
+ comment: {
246
+ text: string;
247
+ };
248
+ [AUDIT_SOURCE_FIELD]: Source;
249
+ [AUDIT_METADATA_FIELD]?: Record<string, unknown>;
250
+ } & Omit<ParentExperimentIds | ParentProjectLogIds, "kind">;
214
251
  type ExperimentEvent = Partial<InputField> & Partial<OtherExperimentLogFields> & {
215
252
  id: string;
216
- span_id: string;
217
- root_span_id: string;
253
+ span_id?: string;
254
+ root_span_id?: string;
218
255
  project_id: string;
219
256
  experiment_id: string;
220
257
  [IS_MERGE_FIELD]: boolean;
@@ -222,6 +259,9 @@ type ExperimentEvent = Partial<InputField> & Partial<OtherExperimentLogFields> &
222
259
  created: string;
223
260
  span_parents: string[];
224
261
  span_attributes: Record<string, unknown>;
262
+ [PARENT_ID_FIELD]: string;
263
+ [AUDIT_SOURCE_FIELD]: Source;
264
+ [AUDIT_METADATA_FIELD]?: Record<string, unknown>;
225
265
  }>;
226
266
  interface DatasetEvent {
227
267
  inputs?: unknown;
@@ -236,7 +276,18 @@ type LoggingEvent = Omit<ExperimentEvent, "experiment_id"> & {
236
276
  org_id: string;
237
277
  log_id: "g";
238
278
  };
239
- type BackgroundLogEvent = ExperimentEvent | DatasetEvent | LoggingEvent;
279
+ export type CommentEvent = IdField & {
280
+ created: string;
281
+ origin: {
282
+ id: string;
283
+ };
284
+ comment: {
285
+ text: string;
286
+ };
287
+ [AUDIT_SOURCE_FIELD]: Source;
288
+ [AUDIT_METADATA_FIELD]?: Record<string, unknown>;
289
+ } & Omit<ParentExperimentIds | ParentProjectLogIds, "kind">;
290
+ type BackgroundLogEvent = ExperimentEvent | DatasetEvent | LoggingEvent | CommentEvent;
240
291
  export interface DatasetRecord {
241
292
  id: string;
242
293
  input: any;
@@ -467,6 +518,7 @@ export declare class Experiment {
467
518
  * See `Span.traced` for full details.
468
519
  */
469
520
  traced<R>(callback: (span: Span) => R, args?: StartSpanArgs & SetCurrentArg): R;
521
+ private lazyParentIds;
470
522
  /**
471
523
  * Lower-level alternative to `traced`, which does not automatically end the span or mark it as current.
472
524
  *
@@ -485,6 +537,18 @@ export declare class Experiment {
485
537
  readonly summarizeScores?: boolean;
486
538
  readonly comparisonExperimentId?: string;
487
539
  }): Promise<ExperimentSummary>;
540
+ /**
541
+ * Log feedback to an event in the experiment. Feedback is used to save feedback scores, set an expected value, or add a comment.
542
+ *
543
+ * @param event
544
+ * @param event.id The id of the event to log feedback for. This is the `id` returned by `log` or accessible as the `id` field of a span.
545
+ * @param event.scores (Optional) a dictionary of numeric values (between 0 and 1) to log. These scores will be merged into the existing scores for the event.
546
+ * @param event.expected (Optional) the ground truth value (an arbitrary, JSON serializable object) that you'd compare to `output` to determine if your `output` value is correct or not.
547
+ * @param event.comment (Optional) an optional comment string to log about the event.
548
+ * @param event.metadata (Optional) a dictionary with additional data about the feedback. If you have a `user_id`, you can log it here and access it in the Braintrust UI.
549
+ * @param event.source (Optional) the source of the feedback. Must be one of "external" (default), "app", or "api".
550
+ */
551
+ logFeedback(event: LogFeedbackFullArgs): void;
488
552
  /**
489
553
  * Flush any pending rows to the server.
490
554
  */
@@ -521,17 +585,21 @@ export declare class SpanImpl implements Span {
521
585
  constructor(args: {
522
586
  parentIds: Promise<ParentExperimentIds | ParentProjectLogIds>;
523
587
  bgLogger: BackgroundLogger;
588
+ } & Omit<StartSpanArgs, "parentId"> & ({
524
589
  parentSpanInfo?: {
525
590
  span_id: string;
526
591
  root_span_id: string;
527
592
  };
528
- } & StartSpanArgs);
593
+ } | {
594
+ parentId?: string;
595
+ }));
529
596
  get id(): string;
530
597
  get span_id(): string;
531
598
  get root_span_id(): string;
532
599
  log(event: ExperimentLogPartialArgs): void;
600
+ logFeedback(event: Omit<LogFeedbackFullArgs, "id">): void;
533
601
  traced<R>(callback: (span: Span) => R, args?: StartSpanArgs & SetCurrentArg): R;
534
- startSpan(args?: StartSpanArgs): Span;
602
+ startSpan(args?: Omit<StartSpanArgs, "parent_id">): Span;
535
603
  end(args?: EndSpanArgs): number;
536
604
  close(args?: EndSpanArgs): number;
537
605
  }
package/dist/oai.d.ts CHANGED
@@ -4,14 +4,19 @@ interface BetaLike {
4
4
  stream: any;
5
5
  };
6
6
  };
7
+ embeddings: any;
7
8
  }
8
9
  interface ChatLike {
9
10
  completions: any;
10
11
  }
11
12
  interface OpenAILike {
12
13
  chat: ChatLike;
14
+ embeddings: any;
13
15
  beta?: BetaLike;
14
16
  }
17
+ declare global {
18
+ var __inherited_braintrust_wrap_openai: ((openai: any) => any) | undefined;
19
+ }
15
20
  /**
16
21
  * Wrap an `OpenAI` object (created with `new OpenAI(...)`) to add tracing. If Braintrust is
17
22
  * not configured, this is a no-op