langsmith 0.2.16-rc.13 → 0.2.16-rc.15

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/client.cjs CHANGED
@@ -1784,6 +1784,40 @@ class Client {
1784
1784
  await (0, error_js_1.raiseForStatus)(response, "update dataset");
1785
1785
  return (await response.json());
1786
1786
  }
1787
+ /**
1788
+ * Updates a tag on a dataset.
1789
+ *
1790
+ * If the tag is already assigned to a different version of this dataset,
1791
+ * the tag will be moved to the new version. The as_of parameter is used to
1792
+ * determine which version of the dataset to apply the new tags to.
1793
+ *
1794
+ * It must be an exact version of the dataset to succeed. You can
1795
+ * use the "readDatasetVersion" method to find the exact version
1796
+ * to apply the tags to.
1797
+ * @param params.datasetId The ID of the dataset to update. Must be provided if "datasetName" is not provided.
1798
+ * @param params.datasetName The name of the dataset to update. Must be provided if "datasetId" is not provided.
1799
+ * @param params.asOf The timestamp of the dataset to apply the new tags to.
1800
+ * @param params.tag The new tag to apply to the dataset.
1801
+ */
1802
+ async updateDatasetTag(props) {
1803
+ const { datasetId, datasetName, asOf, tag } = props;
1804
+ if (!datasetId && !datasetName) {
1805
+ throw new Error("Must provide either datasetName or datasetId");
1806
+ }
1807
+ const _datasetId = datasetId ?? (await this.readDataset({ datasetName })).id;
1808
+ (0, _uuid_js_1.assertUuid)(_datasetId);
1809
+ const response = await this.caller.call((0, fetch_js_1._getFetchImplementation)(), `${this.apiUrl}/datasets/${_datasetId}/tags`, {
1810
+ method: "PUT",
1811
+ headers: { ...this.headers, "Content-Type": "application/json" },
1812
+ body: JSON.stringify({
1813
+ as_of: typeof asOf === "string" ? asOf : asOf.toISOString(),
1814
+ tag,
1815
+ }),
1816
+ signal: AbortSignal.timeout(this.timeout_ms),
1817
+ ...this.fetchOptions,
1818
+ });
1819
+ await (0, error_js_1.raiseForStatus)(response, "update dataset tags");
1820
+ }
1787
1821
  async deleteDataset({ datasetId, datasetName, }) {
1788
1822
  let path = "/datasets";
1789
1823
  let datasetId_ = datasetId;
@@ -2099,6 +2133,47 @@ class Client {
2099
2133
  const result = await response.json();
2100
2134
  return result;
2101
2135
  }
2136
+ /**
2137
+ * Get dataset version by closest date or exact tag.
2138
+ *
2139
+ * Use this to resolve the nearest version to a given timestamp or for a given tag.
2140
+ *
2141
+ * @param options The options for getting the dataset version
2142
+ * @param options.datasetId The ID of the dataset
2143
+ * @param options.datasetName The name of the dataset
2144
+ * @param options.asOf The timestamp of the dataset to retrieve
2145
+ * @param options.tag The tag of the dataset to retrieve
2146
+ * @returns The dataset version
2147
+ */
2148
+ async readDatasetVersion({ datasetId, datasetName, asOf, tag, }) {
2149
+ let resolvedDatasetId;
2150
+ if (!datasetId) {
2151
+ const dataset = await this.readDataset({ datasetName });
2152
+ resolvedDatasetId = dataset.id;
2153
+ }
2154
+ else {
2155
+ resolvedDatasetId = datasetId;
2156
+ }
2157
+ (0, _uuid_js_1.assertUuid)(resolvedDatasetId);
2158
+ if ((asOf && tag) || (!asOf && !tag)) {
2159
+ throw new Error("Exactly one of asOf and tag must be specified.");
2160
+ }
2161
+ const params = new URLSearchParams();
2162
+ if (asOf !== undefined) {
2163
+ params.append("as_of", typeof asOf === "string" ? asOf : asOf.toISOString());
2164
+ }
2165
+ if (tag !== undefined) {
2166
+ params.append("tag", tag);
2167
+ }
2168
+ const response = await this.caller.call((0, fetch_js_1._getFetchImplementation)(), `${this.apiUrl}/datasets/${resolvedDatasetId}/version?${params.toString()}`, {
2169
+ method: "GET",
2170
+ headers: { ...this.headers },
2171
+ signal: AbortSignal.timeout(this.timeout_ms),
2172
+ ...this.fetchOptions,
2173
+ });
2174
+ await (0, error_js_1.raiseForStatus)(response, "read dataset version");
2175
+ return await response.json();
2176
+ }
2102
2177
  async listDatasetSplits({ datasetId, datasetName, asOf, }) {
2103
2178
  let datasetId_;
2104
2179
  if (datasetId === undefined && datasetName === undefined) {
package/dist/client.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { AsyncCallerParams } from "./utils/async_caller.js";
2
- import { ComparativeExperiment, DataType, Dataset, DatasetDiffInfo, DatasetShareSchema, Example, ExampleUpdate, ExampleUpdateWithId, Feedback, FeedbackConfig, FeedbackIngestToken, KVMap, LangChainBaseMessage, LangSmithSettings, LikePromptResponse, Prompt, PromptCommit, PromptSortField, Run, RunCreate, RunUpdate, ScoreType, ExampleSearch, TimeDelta, TracerSession, TracerSessionResult, ValueType, AnnotationQueue, RunWithAnnotationQueueInfo, Attachments, ExampleUploadWithAttachments, UploadExamplesResponse, ExampleUpdateWithAttachments, UpdateExamplesResponse } from "./schemas.js";
2
+ import { ComparativeExperiment, DataType, Dataset, DatasetDiffInfo, DatasetShareSchema, Example, ExampleUpdate, ExampleUpdateWithId, Feedback, FeedbackConfig, FeedbackIngestToken, KVMap, LangChainBaseMessage, LangSmithSettings, LikePromptResponse, Prompt, PromptCommit, PromptSortField, Run, RunCreate, RunUpdate, ScoreType, ExampleSearch, TimeDelta, TracerSession, TracerSessionResult, ValueType, AnnotationQueue, RunWithAnnotationQueueInfo, Attachments, ExampleUploadWithAttachments, UploadExamplesResponse, ExampleUpdateWithAttachments, UpdateExamplesResponse, DatasetVersion } from "./schemas.js";
3
3
  import { EvaluationResult, EvaluationResults, RunEvaluator } from "./evaluation/evaluator.js";
4
4
  export interface ClientConfig {
5
5
  apiUrl?: string;
@@ -487,6 +487,27 @@ export declare class Client implements LangSmithTracingClientInterface {
487
487
  name?: string;
488
488
  description?: string;
489
489
  }): Promise<Dataset>;
490
+ /**
491
+ * Updates a tag on a dataset.
492
+ *
493
+ * If the tag is already assigned to a different version of this dataset,
494
+ * the tag will be moved to the new version. The as_of parameter is used to
495
+ * determine which version of the dataset to apply the new tags to.
496
+ *
497
+ * It must be an exact version of the dataset to succeed. You can
498
+ * use the "readDatasetVersion" method to find the exact version
499
+ * to apply the tags to.
500
+ * @param params.datasetId The ID of the dataset to update. Must be provided if "datasetName" is not provided.
501
+ * @param params.datasetName The name of the dataset to update. Must be provided if "datasetId" is not provided.
502
+ * @param params.asOf The timestamp of the dataset to apply the new tags to.
503
+ * @param params.tag The new tag to apply to the dataset.
504
+ */
505
+ updateDatasetTag(props: {
506
+ datasetId?: string;
507
+ datasetName?: string;
508
+ asOf: string | Date;
509
+ tag: string;
510
+ }): Promise<void>;
490
511
  deleteDataset({ datasetId, datasetName, }: {
491
512
  datasetId?: string;
492
513
  datasetName?: string;
@@ -559,6 +580,24 @@ export declare class Client implements LangSmithTracingClientInterface {
559
580
  deleteExample(exampleId: string): Promise<void>;
560
581
  updateExample(exampleId: string, update: ExampleUpdate): Promise<object>;
561
582
  updateExamples(update: ExampleUpdateWithId[]): Promise<object>;
583
+ /**
584
+ * Get dataset version by closest date or exact tag.
585
+ *
586
+ * Use this to resolve the nearest version to a given timestamp or for a given tag.
587
+ *
588
+ * @param options The options for getting the dataset version
589
+ * @param options.datasetId The ID of the dataset
590
+ * @param options.datasetName The name of the dataset
591
+ * @param options.asOf The timestamp of the dataset to retrieve
592
+ * @param options.tag The tag of the dataset to retrieve
593
+ * @returns The dataset version
594
+ */
595
+ readDatasetVersion({ datasetId, datasetName, asOf, tag, }: {
596
+ datasetId?: string;
597
+ datasetName?: string;
598
+ asOf?: string | Date;
599
+ tag?: string;
600
+ }): Promise<DatasetVersion>;
562
601
  listDatasetSplits({ datasetId, datasetName, asOf, }: {
563
602
  datasetId?: string;
564
603
  datasetName?: string;
package/dist/client.js CHANGED
@@ -1756,6 +1756,40 @@ export class Client {
1756
1756
  await raiseForStatus(response, "update dataset");
1757
1757
  return (await response.json());
1758
1758
  }
1759
+ /**
1760
+ * Updates a tag on a dataset.
1761
+ *
1762
+ * If the tag is already assigned to a different version of this dataset,
1763
+ * the tag will be moved to the new version. The as_of parameter is used to
1764
+ * determine which version of the dataset to apply the new tags to.
1765
+ *
1766
+ * It must be an exact version of the dataset to succeed. You can
1767
+ * use the "readDatasetVersion" method to find the exact version
1768
+ * to apply the tags to.
1769
+ * @param params.datasetId The ID of the dataset to update. Must be provided if "datasetName" is not provided.
1770
+ * @param params.datasetName The name of the dataset to update. Must be provided if "datasetId" is not provided.
1771
+ * @param params.asOf The timestamp of the dataset to apply the new tags to.
1772
+ * @param params.tag The new tag to apply to the dataset.
1773
+ */
1774
+ async updateDatasetTag(props) {
1775
+ const { datasetId, datasetName, asOf, tag } = props;
1776
+ if (!datasetId && !datasetName) {
1777
+ throw new Error("Must provide either datasetName or datasetId");
1778
+ }
1779
+ const _datasetId = datasetId ?? (await this.readDataset({ datasetName })).id;
1780
+ assertUuid(_datasetId);
1781
+ const response = await this.caller.call(_getFetchImplementation(), `${this.apiUrl}/datasets/${_datasetId}/tags`, {
1782
+ method: "PUT",
1783
+ headers: { ...this.headers, "Content-Type": "application/json" },
1784
+ body: JSON.stringify({
1785
+ as_of: typeof asOf === "string" ? asOf : asOf.toISOString(),
1786
+ tag,
1787
+ }),
1788
+ signal: AbortSignal.timeout(this.timeout_ms),
1789
+ ...this.fetchOptions,
1790
+ });
1791
+ await raiseForStatus(response, "update dataset tags");
1792
+ }
1759
1793
  async deleteDataset({ datasetId, datasetName, }) {
1760
1794
  let path = "/datasets";
1761
1795
  let datasetId_ = datasetId;
@@ -2071,6 +2105,47 @@ export class Client {
2071
2105
  const result = await response.json();
2072
2106
  return result;
2073
2107
  }
2108
+ /**
2109
+ * Get dataset version by closest date or exact tag.
2110
+ *
2111
+ * Use this to resolve the nearest version to a given timestamp or for a given tag.
2112
+ *
2113
+ * @param options The options for getting the dataset version
2114
+ * @param options.datasetId The ID of the dataset
2115
+ * @param options.datasetName The name of the dataset
2116
+ * @param options.asOf The timestamp of the dataset to retrieve
2117
+ * @param options.tag The tag of the dataset to retrieve
2118
+ * @returns The dataset version
2119
+ */
2120
+ async readDatasetVersion({ datasetId, datasetName, asOf, tag, }) {
2121
+ let resolvedDatasetId;
2122
+ if (!datasetId) {
2123
+ const dataset = await this.readDataset({ datasetName });
2124
+ resolvedDatasetId = dataset.id;
2125
+ }
2126
+ else {
2127
+ resolvedDatasetId = datasetId;
2128
+ }
2129
+ assertUuid(resolvedDatasetId);
2130
+ if ((asOf && tag) || (!asOf && !tag)) {
2131
+ throw new Error("Exactly one of asOf and tag must be specified.");
2132
+ }
2133
+ const params = new URLSearchParams();
2134
+ if (asOf !== undefined) {
2135
+ params.append("as_of", typeof asOf === "string" ? asOf : asOf.toISOString());
2136
+ }
2137
+ if (tag !== undefined) {
2138
+ params.append("tag", tag);
2139
+ }
2140
+ const response = await this.caller.call(_getFetchImplementation(), `${this.apiUrl}/datasets/${resolvedDatasetId}/version?${params.toString()}`, {
2141
+ method: "GET",
2142
+ headers: { ...this.headers },
2143
+ signal: AbortSignal.timeout(this.timeout_ms),
2144
+ ...this.fetchOptions,
2145
+ });
2146
+ await raiseForStatus(response, "read dataset version");
2147
+ return await response.json();
2148
+ }
2074
2149
  async listDatasetSplits({ datasetId, datasetName, asOf, }) {
2075
2150
  let datasetId_;
2076
2151
  if (datasetId === undefined && datasetName === undefined) {
package/dist/index.cjs CHANGED
@@ -8,4 +8,4 @@ Object.defineProperty(exports, "RunTree", { enumerable: true, get: function () {
8
8
  var fetch_js_1 = require("./singletons/fetch.cjs");
9
9
  Object.defineProperty(exports, "overrideFetchImplementation", { enumerable: true, get: function () { return fetch_js_1.overrideFetchImplementation; } });
10
10
  // Update using yarn bump-version
11
- exports.__version__ = "0.2.16-rc.13";
11
+ exports.__version__ = "0.2.16-rc.15";
package/dist/index.d.ts CHANGED
@@ -2,4 +2,4 @@ export { Client, type ClientConfig, type LangSmithTracingClientInterface, } from
2
2
  export type { Dataset, Example, TracerSession, Run, Feedback, RetrieverOutput, } from "./schemas.js";
3
3
  export { RunTree, type RunTreeConfig } from "./run_trees.js";
4
4
  export { overrideFetchImplementation } from "./singletons/fetch.js";
5
- export declare const __version__ = "0.2.16-rc.13";
5
+ export declare const __version__ = "0.2.16-rc.15";
package/dist/index.js CHANGED
@@ -2,4 +2,4 @@ export { Client, } from "./client.js";
2
2
  export { RunTree } from "./run_trees.js";
3
3
  export { overrideFetchImplementation } from "./singletons/fetch.js";
4
4
  // Update using yarn bump-version
5
- export const __version__ = "0.2.16-rc.13";
5
+ export const __version__ = "0.2.16-rc.15";
@@ -60,30 +60,30 @@ declare global {
60
60
  }
61
61
  declare const test: (<I extends Record<string, any> = Record<string, any>, O extends Record<string, any> = Record<string, any>>(name: string, lsParams: LangSmithJestlikeWrapperParams<I, O>, testFn: (data: {
62
62
  inputs: I;
63
- referenceOutputs: O;
63
+ referenceOutputs?: O | undefined;
64
64
  } & Record<string, any>) => unknown, timeout?: number | undefined) => void) & {
65
65
  only: (<I extends Record<string, any> = Record<string, any>, O extends Record<string, any> = Record<string, any>>(name: string, lsParams: LangSmithJestlikeWrapperParams<I, O>, testFn: (data: {
66
66
  inputs: I;
67
- referenceOutputs: O;
67
+ referenceOutputs?: O | undefined;
68
68
  } & Record<string, any>) => unknown, timeout?: number | undefined) => void) & {
69
69
  each: <I_1 extends import("../schemas.js").KVMap, O_1 extends import("../schemas.js").KVMap>(table: ({
70
70
  inputs: I_1;
71
71
  referenceOutputs: O_1;
72
72
  } & Record<string, any>)[], config?: import("../utils/jestlike/types.js").LangSmithJestlikeWrapperConfig | undefined) => (name: string, fn: (params: {
73
73
  inputs: I_1;
74
- referenceOutputs: O_1;
74
+ referenceOutputs?: O_1 | undefined;
75
75
  } & Record<string, any>) => unknown, timeout?: number | undefined) => void;
76
76
  };
77
77
  skip: (<I extends Record<string, any> = Record<string, any>, O extends Record<string, any> = Record<string, any>>(name: string, lsParams: LangSmithJestlikeWrapperParams<I, O>, testFn: (data: {
78
78
  inputs: I;
79
- referenceOutputs: O;
79
+ referenceOutputs?: O | undefined;
80
80
  } & Record<string, any>) => unknown, timeout?: number | undefined) => void) & {
81
81
  each: <I_1 extends import("../schemas.js").KVMap, O_1 extends import("../schemas.js").KVMap>(table: ({
82
82
  inputs: I_1;
83
83
  referenceOutputs: O_1;
84
84
  } & Record<string, any>)[], config?: import("../utils/jestlike/types.js").LangSmithJestlikeWrapperConfig | undefined) => (name: string, fn: (params: {
85
85
  inputs: I_1;
86
- referenceOutputs: O_1;
86
+ referenceOutputs?: O_1 | undefined;
87
87
  } & Record<string, any>) => unknown, timeout?: number | undefined) => void;
88
88
  };
89
89
  each: <I_1 extends import("../schemas.js").KVMap, O_1 extends import("../schemas.js").KVMap>(table: ({
@@ -91,34 +91,34 @@ declare const test: (<I extends Record<string, any> = Record<string, any>, O ext
91
91
  referenceOutputs: O_1;
92
92
  } & Record<string, any>)[], config?: import("../utils/jestlike/types.js").LangSmithJestlikeWrapperConfig | undefined) => (name: string, fn: (params: {
93
93
  inputs: I_1;
94
- referenceOutputs: O_1;
94
+ referenceOutputs?: O_1 | undefined;
95
95
  } & Record<string, any>) => unknown, timeout?: number | undefined) => void;
96
96
  }, it: (<I extends Record<string, any> = Record<string, any>, O extends Record<string, any> = Record<string, any>>(name: string, lsParams: LangSmithJestlikeWrapperParams<I, O>, testFn: (data: {
97
97
  inputs: I;
98
- referenceOutputs: O;
98
+ referenceOutputs?: O | undefined;
99
99
  } & Record<string, any>) => unknown, timeout?: number | undefined) => void) & {
100
100
  only: (<I extends Record<string, any> = Record<string, any>, O extends Record<string, any> = Record<string, any>>(name: string, lsParams: LangSmithJestlikeWrapperParams<I, O>, testFn: (data: {
101
101
  inputs: I;
102
- referenceOutputs: O;
102
+ referenceOutputs?: O | undefined;
103
103
  } & Record<string, any>) => unknown, timeout?: number | undefined) => void) & {
104
104
  each: <I extends import("../schemas.js").KVMap, O extends import("../schemas.js").KVMap>(table: ({
105
105
  inputs: I;
106
106
  referenceOutputs: O;
107
107
  } & Record<string, any>)[], config?: import("../utils/jestlike/types.js").LangSmithJestlikeWrapperConfig | undefined) => (name: string, fn: (params: {
108
108
  inputs: I;
109
- referenceOutputs: O;
109
+ referenceOutputs?: O | undefined;
110
110
  } & Record<string, any>) => unknown, timeout?: number | undefined) => void;
111
111
  };
112
112
  skip: (<I extends Record<string, any> = Record<string, any>, O extends Record<string, any> = Record<string, any>>(name: string, lsParams: LangSmithJestlikeWrapperParams<I, O>, testFn: (data: {
113
113
  inputs: I;
114
- referenceOutputs: O;
114
+ referenceOutputs?: O | undefined;
115
115
  } & Record<string, any>) => unknown, timeout?: number | undefined) => void) & {
116
116
  each: <I extends import("../schemas.js").KVMap, O extends import("../schemas.js").KVMap>(table: ({
117
117
  inputs: I;
118
118
  referenceOutputs: O;
119
119
  } & Record<string, any>)[], config?: import("../utils/jestlike/types.js").LangSmithJestlikeWrapperConfig | undefined) => (name: string, fn: (params: {
120
120
  inputs: I;
121
- referenceOutputs: O;
121
+ referenceOutputs?: O | undefined;
122
122
  } & Record<string, any>) => unknown, timeout?: number | undefined) => void;
123
123
  };
124
124
  each: <I extends import("../schemas.js").KVMap, O extends import("../schemas.js").KVMap>(table: ({
@@ -126,7 +126,7 @@ declare const test: (<I extends Record<string, any> = Record<string, any>, O ext
126
126
  referenceOutputs: O;
127
127
  } & Record<string, any>)[], config?: import("../utils/jestlike/types.js").LangSmithJestlikeWrapperConfig | undefined) => (name: string, fn: (params: {
128
128
  inputs: I;
129
- referenceOutputs: O;
129
+ referenceOutputs?: O | undefined;
130
130
  } & Record<string, any>) => unknown, timeout?: number | undefined) => void;
131
131
  }, describe: import("../utils/jestlike/types.js").LangSmithJestDescribeWrapper & {
132
132
  only: import("../utils/jestlike/types.js").LangSmithJestDescribeWrapper;
package/dist/schemas.d.ts CHANGED
@@ -268,6 +268,10 @@ export interface DatasetShareSchema {
268
268
  share_token: string;
269
269
  url: string;
270
270
  }
271
+ export interface DatasetVersion {
272
+ tags?: string[];
273
+ as_of: string;
274
+ }
271
275
  export interface FeedbackSourceBase {
272
276
  type: string;
273
277
  metadata?: KVMap;
@@ -34,11 +34,13 @@ const uuid_1 = require("uuid");
34
34
  const os = __importStar(require("node:os"));
35
35
  const path = __importStar(require("node:path"));
36
36
  const fs = __importStar(require("node:fs/promises"));
37
+ const child_process_1 = require("child_process");
37
38
  const traceable_js_1 = require("../../traceable.cjs");
38
39
  const _random_name_js_1 = require("../../evaluation/_random_name.cjs");
39
40
  const matchers_js_1 = require("./matchers.cjs");
40
41
  const globals_js_1 = require("./globals.cjs");
41
42
  const chain_js_1 = require("./vendor/chain.cjs");
43
+ const DEFAULT_TEST_TIMEOUT = 30_000;
42
44
  const UUID5_NAMESPACE = "6ba7b810-9dad-11d1-80b4-00c04fd430c8";
43
45
  // From https://stackoverflow.com/a/29497680
44
46
  exports.STRIP_ANSI_REGEX =
@@ -221,6 +223,7 @@ function generateWrapperFromJestlikeMethods(methods, testRunnerName) {
221
223
  return function (datasetName, fn, experimentConfig) {
222
224
  const client = experimentConfig?.client ?? globals_js_1.DEFAULT_TEST_CLIENT;
223
225
  return method(datasetName, () => {
226
+ const startTime = new Date();
224
227
  const suiteUuid = (0, uuid_1.v4)();
225
228
  const context = {
226
229
  suiteUuid,
@@ -246,6 +249,62 @@ function generateWrapperFromJestlikeMethods(methods, testRunnerName) {
246
249
  ...globals_js_1.syncExamplePromises.values(),
247
250
  ...globals_js_1.evaluatorLogFeedbackPromises.values(),
248
251
  ]);
252
+ if (!(0, globals_js_1.trackingEnabled)(context)) {
253
+ return;
254
+ }
255
+ const examples = [...globals_js_1.syncExamplePromises.values()];
256
+ if (examples.length === 0) {
257
+ return;
258
+ }
259
+ const endTime = new Date();
260
+ let branch;
261
+ let commit;
262
+ try {
263
+ branch = (0, child_process_1.execSync)("git rev-parse --abbrev-ref HEAD")
264
+ .toString()
265
+ .trim();
266
+ commit = (0, child_process_1.execSync)("git rev-parse HEAD").toString().trim();
267
+ }
268
+ catch {
269
+ return;
270
+ }
271
+ if (branch === undefined || commit === undefined) {
272
+ return;
273
+ }
274
+ try {
275
+ let finalModifiedAt = examples.reduce((latestModifiedAt, example) => {
276
+ if (new Date(latestModifiedAt).getTime() >
277
+ new Date(example.modified_at).getTime()) {
278
+ return latestModifiedAt;
279
+ }
280
+ else {
281
+ return example.modified_at;
282
+ }
283
+ }, examples[0].modified_at);
284
+ if (new Date(finalModifiedAt).getTime() < startTime.getTime()) {
285
+ finalModifiedAt = endTime.toISOString();
286
+ }
287
+ const datasetInfo = datasetSetupInfo.get(suiteUuid);
288
+ const { as_of } = await client.readDatasetVersion({
289
+ datasetId: datasetInfo.dataset.id,
290
+ asOf: finalModifiedAt,
291
+ });
292
+ await Promise.all([
293
+ client.updateDatasetTag({
294
+ datasetId: datasetInfo.dataset.id,
295
+ asOf: as_of,
296
+ tag: `git:branch:${branch}`,
297
+ }),
298
+ client.updateDatasetTag({
299
+ datasetId: datasetInfo.dataset.id,
300
+ asOf: as_of,
301
+ tag: `git:commit:${commit}`,
302
+ }),
303
+ ]);
304
+ }
305
+ catch (e) {
306
+ console.warn(`[LANGSMITH]: Failed to tag dataset: ${e.message}`);
307
+ }
249
308
  });
250
309
  /**
251
310
  * We cannot rely on setting AsyncLocalStorage in beforeAll or beforeEach,
@@ -458,7 +517,7 @@ function generateWrapperFromJestlikeMethods(methods, testRunnerName) {
458
517
  experimentUrl,
459
518
  }));
460
519
  }
461
- }, timeout);
520
+ }, timeout ?? DEFAULT_TEST_TIMEOUT);
462
521
  }
463
522
  };
464
523
  }
@@ -12,30 +12,30 @@ export declare function logOutputs(output: Record<string, unknown>): void;
12
12
  export declare function generateWrapperFromJestlikeMethods(methods: Record<string, any>, testRunnerName: string): {
13
13
  test: (<I extends Record<string, any> = Record<string, any>, O extends Record<string, any> = Record<string, any>>(name: string, lsParams: LangSmithJestlikeWrapperParams<I, O>, testFn: (data: {
14
14
  inputs: I;
15
- referenceOutputs: O;
15
+ referenceOutputs?: O;
16
16
  } & Record<string, any>) => unknown | Promise<unknown>, timeout?: number) => void) & {
17
17
  only: (<I extends Record<string, any> = Record<string, any>, O extends Record<string, any> = Record<string, any>>(name: string, lsParams: LangSmithJestlikeWrapperParams<I, O>, testFn: (data: {
18
18
  inputs: I;
19
- referenceOutputs: O;
19
+ referenceOutputs?: O;
20
20
  } & Record<string, any>) => unknown | Promise<unknown>, timeout?: number) => void) & {
21
21
  each: <I_1 extends KVMap, O_1 extends KVMap>(table: ({
22
22
  inputs: I_1;
23
23
  referenceOutputs: O_1;
24
24
  } & Record<string, any>)[], config?: LangSmithJestlikeWrapperConfig) => (name: string, fn: (params: {
25
25
  inputs: I_1;
26
- referenceOutputs: O_1;
26
+ referenceOutputs?: O_1 | undefined;
27
27
  } & Record<string, any>) => unknown | Promise<unknown>, timeout?: number) => void;
28
28
  };
29
29
  skip: (<I extends Record<string, any> = Record<string, any>, O extends Record<string, any> = Record<string, any>>(name: string, lsParams: LangSmithJestlikeWrapperParams<I, O>, testFn: (data: {
30
30
  inputs: I;
31
- referenceOutputs: O;
31
+ referenceOutputs?: O;
32
32
  } & Record<string, any>) => unknown | Promise<unknown>, timeout?: number) => void) & {
33
33
  each: <I_1 extends KVMap, O_1 extends KVMap>(table: ({
34
34
  inputs: I_1;
35
35
  referenceOutputs: O_1;
36
36
  } & Record<string, any>)[], config?: LangSmithJestlikeWrapperConfig) => (name: string, fn: (params: {
37
37
  inputs: I_1;
38
- referenceOutputs: O_1;
38
+ referenceOutputs?: O_1 | undefined;
39
39
  } & Record<string, any>) => unknown | Promise<unknown>, timeout?: number) => void;
40
40
  };
41
41
  each: <I_1 extends KVMap, O_1 extends KVMap>(table: ({
@@ -43,35 +43,35 @@ export declare function generateWrapperFromJestlikeMethods(methods: Record<strin
43
43
  referenceOutputs: O_1;
44
44
  } & Record<string, any>)[], config?: LangSmithJestlikeWrapperConfig) => (name: string, fn: (params: {
45
45
  inputs: I_1;
46
- referenceOutputs: O_1;
46
+ referenceOutputs?: O_1 | undefined;
47
47
  } & Record<string, any>) => unknown | Promise<unknown>, timeout?: number) => void;
48
48
  };
49
49
  it: (<I extends Record<string, any> = Record<string, any>, O extends Record<string, any> = Record<string, any>>(name: string, lsParams: LangSmithJestlikeWrapperParams<I, O>, testFn: (data: {
50
50
  inputs: I;
51
- referenceOutputs: O;
51
+ referenceOutputs?: O;
52
52
  } & Record<string, any>) => unknown | Promise<unknown>, timeout?: number) => void) & {
53
53
  only: (<I extends Record<string, any> = Record<string, any>, O extends Record<string, any> = Record<string, any>>(name: string, lsParams: LangSmithJestlikeWrapperParams<I, O>, testFn: (data: {
54
54
  inputs: I;
55
- referenceOutputs: O;
55
+ referenceOutputs?: O;
56
56
  } & Record<string, any>) => unknown | Promise<unknown>, timeout?: number) => void) & {
57
57
  each: <I_1 extends KVMap, O_1 extends KVMap>(table: ({
58
58
  inputs: I_1;
59
59
  referenceOutputs: O_1;
60
60
  } & Record<string, any>)[], config?: LangSmithJestlikeWrapperConfig) => (name: string, fn: (params: {
61
61
  inputs: I_1;
62
- referenceOutputs: O_1;
62
+ referenceOutputs?: O_1 | undefined;
63
63
  } & Record<string, any>) => unknown | Promise<unknown>, timeout?: number) => void;
64
64
  };
65
65
  skip: (<I extends Record<string, any> = Record<string, any>, O extends Record<string, any> = Record<string, any>>(name: string, lsParams: LangSmithJestlikeWrapperParams<I, O>, testFn: (data: {
66
66
  inputs: I;
67
- referenceOutputs: O;
67
+ referenceOutputs?: O;
68
68
  } & Record<string, any>) => unknown | Promise<unknown>, timeout?: number) => void) & {
69
69
  each: <I_1 extends KVMap, O_1 extends KVMap>(table: ({
70
70
  inputs: I_1;
71
71
  referenceOutputs: O_1;
72
72
  } & Record<string, any>)[], config?: LangSmithJestlikeWrapperConfig) => (name: string, fn: (params: {
73
73
  inputs: I_1;
74
- referenceOutputs: O_1;
74
+ referenceOutputs?: O_1 | undefined;
75
75
  } & Record<string, any>) => unknown | Promise<unknown>, timeout?: number) => void;
76
76
  };
77
77
  each: <I_1 extends KVMap, O_1 extends KVMap>(table: ({
@@ -79,7 +79,7 @@ export declare function generateWrapperFromJestlikeMethods(methods: Record<strin
79
79
  referenceOutputs: O_1;
80
80
  } & Record<string, any>)[], config?: LangSmithJestlikeWrapperConfig) => (name: string, fn: (params: {
81
81
  inputs: I_1;
82
- referenceOutputs: O_1;
82
+ referenceOutputs?: O_1 | undefined;
83
83
  } & Record<string, any>) => unknown | Promise<unknown>, timeout?: number) => void;
84
84
  };
85
85
  describe: LangSmithJestDescribeWrapper & {
@@ -5,11 +5,13 @@ import { v4, v5 } from "uuid";
5
5
  import * as os from "node:os";
6
6
  import * as path from "node:path";
7
7
  import * as fs from "node:fs/promises";
8
+ import { execSync } from "child_process";
8
9
  import { getCurrentRunTree, traceable } from "../../traceable.js";
9
10
  import { randomName } from "../../evaluation/_random_name.js";
10
11
  import { toBeRelativeCloseTo, toBeAbsoluteCloseTo, toBeSemanticCloseTo, } from "./matchers.js";
11
12
  import { evaluatorLogFeedbackPromises, testWrapperAsyncLocalStorageInstance, _logTestFeedback, syncExamplePromises, trackingEnabled, DEFAULT_TEST_CLIENT, } from "./globals.js";
12
13
  import { wrapExpect } from "./vendor/chain.js";
14
+ const DEFAULT_TEST_TIMEOUT = 30_000;
13
15
  const UUID5_NAMESPACE = "6ba7b810-9dad-11d1-80b4-00c04fd430c8";
14
16
  // From https://stackoverflow.com/a/29497680
15
17
  export const STRIP_ANSI_REGEX =
@@ -190,6 +192,7 @@ export function generateWrapperFromJestlikeMethods(methods, testRunnerName) {
190
192
  return function (datasetName, fn, experimentConfig) {
191
193
  const client = experimentConfig?.client ?? DEFAULT_TEST_CLIENT;
192
194
  return method(datasetName, () => {
195
+ const startTime = new Date();
193
196
  const suiteUuid = v4();
194
197
  const context = {
195
198
  suiteUuid,
@@ -215,6 +218,62 @@ export function generateWrapperFromJestlikeMethods(methods, testRunnerName) {
215
218
  ...syncExamplePromises.values(),
216
219
  ...evaluatorLogFeedbackPromises.values(),
217
220
  ]);
221
+ if (!trackingEnabled(context)) {
222
+ return;
223
+ }
224
+ const examples = [...syncExamplePromises.values()];
225
+ if (examples.length === 0) {
226
+ return;
227
+ }
228
+ const endTime = new Date();
229
+ let branch;
230
+ let commit;
231
+ try {
232
+ branch = execSync("git rev-parse --abbrev-ref HEAD")
233
+ .toString()
234
+ .trim();
235
+ commit = execSync("git rev-parse HEAD").toString().trim();
236
+ }
237
+ catch {
238
+ return;
239
+ }
240
+ if (branch === undefined || commit === undefined) {
241
+ return;
242
+ }
243
+ try {
244
+ let finalModifiedAt = examples.reduce((latestModifiedAt, example) => {
245
+ if (new Date(latestModifiedAt).getTime() >
246
+ new Date(example.modified_at).getTime()) {
247
+ return latestModifiedAt;
248
+ }
249
+ else {
250
+ return example.modified_at;
251
+ }
252
+ }, examples[0].modified_at);
253
+ if (new Date(finalModifiedAt).getTime() < startTime.getTime()) {
254
+ finalModifiedAt = endTime.toISOString();
255
+ }
256
+ const datasetInfo = datasetSetupInfo.get(suiteUuid);
257
+ const { as_of } = await client.readDatasetVersion({
258
+ datasetId: datasetInfo.dataset.id,
259
+ asOf: finalModifiedAt,
260
+ });
261
+ await Promise.all([
262
+ client.updateDatasetTag({
263
+ datasetId: datasetInfo.dataset.id,
264
+ asOf: as_of,
265
+ tag: `git:branch:${branch}`,
266
+ }),
267
+ client.updateDatasetTag({
268
+ datasetId: datasetInfo.dataset.id,
269
+ asOf: as_of,
270
+ tag: `git:commit:${commit}`,
271
+ }),
272
+ ]);
273
+ }
274
+ catch (e) {
275
+ console.warn(`[LANGSMITH]: Failed to tag dataset: ${e.message}`);
276
+ }
218
277
  });
219
278
  /**
220
279
  * We cannot rely on setting AsyncLocalStorage in beforeAll or beforeEach,
@@ -427,7 +486,7 @@ export function generateWrapperFromJestlikeMethods(methods, testRunnerName) {
427
486
  experimentUrl,
428
487
  }));
429
488
  }
430
- }, timeout);
489
+ }, timeout ?? DEFAULT_TEST_TIMEOUT);
431
490
  }
432
491
  };
433
492
  }
@@ -66,11 +66,10 @@ async function evaluatedBy(outputs, evaluator) {
66
66
  `See this page for more information: https://docs.smith.langchain.com/evaluation/how_to_guides/vitest_jest`,
67
67
  ].join("\n"));
68
68
  }
69
- const runTree = (0, traceable_js_1.getCurrentRunTree)();
70
69
  const wrappedEvaluator = wrapEvaluator(evaluator);
71
70
  const evalRunId = (0, uuid_1.v4)();
72
71
  const evalResult = await wrappedEvaluator({
73
- inputs: runTree.inputs,
72
+ inputs: context.currentExample?.inputs ?? {},
74
73
  referenceOutputs: context?.currentExample?.outputs ?? {},
75
74
  outputs,
76
75
  }, { runId: evalRunId });
@@ -62,11 +62,10 @@ export async function evaluatedBy(outputs, evaluator) {
62
62
  `See this page for more information: https://docs.smith.langchain.com/evaluation/how_to_guides/vitest_jest`,
63
63
  ].join("\n"));
64
64
  }
65
- const runTree = getCurrentRunTree();
66
65
  const wrappedEvaluator = wrapEvaluator(evaluator);
67
66
  const evalRunId = v4();
68
67
  const evalResult = await wrappedEvaluator({
69
- inputs: runTree.inputs,
68
+ inputs: context.currentExample?.inputs ?? {},
70
69
  referenceOutputs: context?.currentExample?.outputs ?? {},
71
70
  outputs,
72
71
  }, { runId: evalRunId });
@@ -58,30 +58,30 @@ declare module "vitest" {
58
58
  }
59
59
  declare const test: (<I extends Record<string, any> = Record<string, any>, O extends Record<string, any> = Record<string, any>>(name: string, lsParams: LangSmithJestlikeWrapperParams<I, O>, testFn: (data: {
60
60
  inputs: I;
61
- referenceOutputs: O;
61
+ referenceOutputs?: O | undefined;
62
62
  } & Record<string, any>) => unknown, timeout?: number | undefined) => void) & {
63
63
  only: (<I extends Record<string, any> = Record<string, any>, O extends Record<string, any> = Record<string, any>>(name: string, lsParams: LangSmithJestlikeWrapperParams<I, O>, testFn: (data: {
64
64
  inputs: I;
65
- referenceOutputs: O;
65
+ referenceOutputs?: O | undefined;
66
66
  } & Record<string, any>) => unknown, timeout?: number | undefined) => void) & {
67
67
  each: <I_1 extends import("../schemas.js").KVMap, O_1 extends import("../schemas.js").KVMap>(table: ({
68
68
  inputs: I_1;
69
69
  referenceOutputs: O_1;
70
70
  } & Record<string, any>)[], config?: import("../utils/jestlike/types.js").LangSmithJestlikeWrapperConfig | undefined) => (name: string, fn: (params: {
71
71
  inputs: I_1;
72
- referenceOutputs: O_1;
72
+ referenceOutputs?: O_1 | undefined;
73
73
  } & Record<string, any>) => unknown, timeout?: number | undefined) => void;
74
74
  };
75
75
  skip: (<I extends Record<string, any> = Record<string, any>, O extends Record<string, any> = Record<string, any>>(name: string, lsParams: LangSmithJestlikeWrapperParams<I, O>, testFn: (data: {
76
76
  inputs: I;
77
- referenceOutputs: O;
77
+ referenceOutputs?: O | undefined;
78
78
  } & Record<string, any>) => unknown, timeout?: number | undefined) => void) & {
79
79
  each: <I_1 extends import("../schemas.js").KVMap, O_1 extends import("../schemas.js").KVMap>(table: ({
80
80
  inputs: I_1;
81
81
  referenceOutputs: O_1;
82
82
  } & Record<string, any>)[], config?: import("../utils/jestlike/types.js").LangSmithJestlikeWrapperConfig | undefined) => (name: string, fn: (params: {
83
83
  inputs: I_1;
84
- referenceOutputs: O_1;
84
+ referenceOutputs?: O_1 | undefined;
85
85
  } & Record<string, any>) => unknown, timeout?: number | undefined) => void;
86
86
  };
87
87
  each: <I_1 extends import("../schemas.js").KVMap, O_1 extends import("../schemas.js").KVMap>(table: ({
@@ -89,34 +89,34 @@ declare const test: (<I extends Record<string, any> = Record<string, any>, O ext
89
89
  referenceOutputs: O_1;
90
90
  } & Record<string, any>)[], config?: import("../utils/jestlike/types.js").LangSmithJestlikeWrapperConfig | undefined) => (name: string, fn: (params: {
91
91
  inputs: I_1;
92
- referenceOutputs: O_1;
92
+ referenceOutputs?: O_1 | undefined;
93
93
  } & Record<string, any>) => unknown, timeout?: number | undefined) => void;
94
94
  }, it: (<I extends Record<string, any> = Record<string, any>, O extends Record<string, any> = Record<string, any>>(name: string, lsParams: LangSmithJestlikeWrapperParams<I, O>, testFn: (data: {
95
95
  inputs: I;
96
- referenceOutputs: O;
96
+ referenceOutputs?: O | undefined;
97
97
  } & Record<string, any>) => unknown, timeout?: number | undefined) => void) & {
98
98
  only: (<I extends Record<string, any> = Record<string, any>, O extends Record<string, any> = Record<string, any>>(name: string, lsParams: LangSmithJestlikeWrapperParams<I, O>, testFn: (data: {
99
99
  inputs: I;
100
- referenceOutputs: O;
100
+ referenceOutputs?: O | undefined;
101
101
  } & Record<string, any>) => unknown, timeout?: number | undefined) => void) & {
102
102
  each: <I extends import("../schemas.js").KVMap, O extends import("../schemas.js").KVMap>(table: ({
103
103
  inputs: I;
104
104
  referenceOutputs: O;
105
105
  } & Record<string, any>)[], config?: import("../utils/jestlike/types.js").LangSmithJestlikeWrapperConfig | undefined) => (name: string, fn: (params: {
106
106
  inputs: I;
107
- referenceOutputs: O;
107
+ referenceOutputs?: O | undefined;
108
108
  } & Record<string, any>) => unknown, timeout?: number | undefined) => void;
109
109
  };
110
110
  skip: (<I extends Record<string, any> = Record<string, any>, O extends Record<string, any> = Record<string, any>>(name: string, lsParams: LangSmithJestlikeWrapperParams<I, O>, testFn: (data: {
111
111
  inputs: I;
112
- referenceOutputs: O;
112
+ referenceOutputs?: O | undefined;
113
113
  } & Record<string, any>) => unknown, timeout?: number | undefined) => void) & {
114
114
  each: <I extends import("../schemas.js").KVMap, O extends import("../schemas.js").KVMap>(table: ({
115
115
  inputs: I;
116
116
  referenceOutputs: O;
117
117
  } & Record<string, any>)[], config?: import("../utils/jestlike/types.js").LangSmithJestlikeWrapperConfig | undefined) => (name: string, fn: (params: {
118
118
  inputs: I;
119
- referenceOutputs: O;
119
+ referenceOutputs?: O | undefined;
120
120
  } & Record<string, any>) => unknown, timeout?: number | undefined) => void;
121
121
  };
122
122
  each: <I extends import("../schemas.js").KVMap, O extends import("../schemas.js").KVMap>(table: ({
@@ -124,7 +124,7 @@ declare const test: (<I extends Record<string, any> = Record<string, any>, O ext
124
124
  referenceOutputs: O;
125
125
  } & Record<string, any>)[], config?: import("../utils/jestlike/types.js").LangSmithJestlikeWrapperConfig | undefined) => (name: string, fn: (params: {
126
126
  inputs: I;
127
- referenceOutputs: O;
127
+ referenceOutputs?: O | undefined;
128
128
  } & Record<string, any>) => unknown, timeout?: number | undefined) => void;
129
129
  }, describe: import("../utils/jestlike/types.js").LangSmithJestDescribeWrapper & {
130
130
  only: import("../utils/jestlike/types.js").LangSmithJestDescribeWrapper;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "langsmith",
3
- "version": "0.2.16-rc.13",
3
+ "version": "0.2.16-rc.15",
4
4
  "description": "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform.",
5
5
  "packageManager": "yarn@1.22.19",
6
6
  "files": [
@@ -94,7 +94,6 @@
94
94
  "test:integration": "cross-env NODE_OPTIONS=--experimental-vm-modules jest --testPathPattern=\\.int\\.test.ts --testTimeout 100000",
95
95
  "test:single": "NODE_OPTIONS=--experimental-vm-modules yarn run jest --config jest.config.cjs --testTimeout 100000",
96
96
  "watch:single": "NODE_OPTIONS=--experimental-vm-modules yarn run jest --watch --config jest.config.cjs --testTimeout 100000",
97
- "eval:vitest": "vitest run --config ls.vitest.config.ts",
98
97
  "lint": "NODE_OPTIONS=--max-old-space-size=4096 eslint --cache --ext .ts,.js src/",
99
98
  "lint:fix": "yarn lint --fix",
100
99
  "format": "prettier --write 'src/**/*.{ts,tsx}'",