langsmith 0.2.14-rc.6 → 0.2.15-beta.0
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 +30 -4
- package/dist/client.d.ts +11 -1
- package/dist/client.js +30 -4
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/run_trees.d.ts +1 -1
- package/dist/singletons/traceable.cjs +1 -1
- package/dist/singletons/traceable.js +1 -1
- package/package.json +1 -14
- package/dist/jest/globals.cjs +0 -10
- package/dist/jest/globals.d.ts +0 -18
- package/dist/jest/globals.js +0 -6
- package/dist/jest/index.cjs +0 -254
- package/dist/jest/index.d.ts +0 -55
- package/dist/jest/index.js +0 -245
- package/dist/jest/matchers.cjs +0 -101
- package/dist/jest/matchers.d.ts +0 -25
- package/dist/jest/matchers.js +0 -95
- package/dist/jest/vendor/chain.cjs +0 -93
- package/dist/jest/vendor/chain.d.ts +0 -1
- package/dist/jest/vendor/chain.js +0 -89
- package/dist/jest/vendor/gradedBy.cjs +0 -40
- package/dist/jest/vendor/gradedBy.d.ts +0 -7
- package/dist/jest/vendor/gradedBy.js +0 -36
- package/jest.cjs +0 -1
- package/jest.d.cts +0 -1
- package/jest.d.ts +0 -1
- package/jest.js +0 -1
package/dist/client.cjs
CHANGED
|
@@ -308,6 +308,12 @@ class Client {
|
|
|
308
308
|
writable: true,
|
|
309
309
|
value: void 0
|
|
310
310
|
});
|
|
311
|
+
Object.defineProperty(this, "manualFlushMode", {
|
|
312
|
+
enumerable: true,
|
|
313
|
+
configurable: true,
|
|
314
|
+
writable: true,
|
|
315
|
+
value: false
|
|
316
|
+
});
|
|
311
317
|
const defaultConfig = Client.getDefaultClientConfig();
|
|
312
318
|
this.tracingSampleRate = getTracingSamplingRate();
|
|
313
319
|
this.apiUrl = trimQuotes(config.apiUrl ?? defaultConfig.apiUrl) ?? "";
|
|
@@ -341,6 +347,7 @@ class Client {
|
|
|
341
347
|
config.blockOnRootRunFinalization ?? this.blockOnRootRunFinalization;
|
|
342
348
|
this.batchSizeBytesLimit = config.batchSizeBytesLimit;
|
|
343
349
|
this.fetchOptions = config.fetchOptions || {};
|
|
350
|
+
this.manualFlushMode = config.manualFlushMode ?? this.manualFlushMode;
|
|
344
351
|
}
|
|
345
352
|
static getDefaultClientConfig() {
|
|
346
353
|
const apiKey = (0, env_js_1.getLangSmithEnvironmentVariable)("API_KEY");
|
|
@@ -538,14 +545,17 @@ class Client {
|
|
|
538
545
|
return (serverInfo.instance_flags?.dataset_examples_multipart_enabled ?? false);
|
|
539
546
|
}
|
|
540
547
|
drainAutoBatchQueue(batchSizeLimit) {
|
|
548
|
+
const promises = [];
|
|
541
549
|
while (this.autoBatchQueue.items.length > 0) {
|
|
542
550
|
const [batch, done] = this.autoBatchQueue.pop(batchSizeLimit);
|
|
543
551
|
if (!batch.length) {
|
|
544
552
|
done();
|
|
545
553
|
break;
|
|
546
554
|
}
|
|
547
|
-
|
|
555
|
+
const batchPromise = this._processBatch(batch, done).catch(console.error);
|
|
556
|
+
promises.push(batchPromise);
|
|
548
557
|
}
|
|
558
|
+
return Promise.all(promises);
|
|
549
559
|
}
|
|
550
560
|
async _processBatch(batch, done) {
|
|
551
561
|
if (!batch.length) {
|
|
@@ -580,14 +590,18 @@ class Client {
|
|
|
580
590
|
item.item = mergeRuntimeEnvIntoRunCreate(item.item);
|
|
581
591
|
}
|
|
582
592
|
const itemPromise = this.autoBatchQueue.push(item);
|
|
593
|
+
if (this.manualFlushMode) {
|
|
594
|
+
// Rely on manual flushing in serverless environments
|
|
595
|
+
return itemPromise;
|
|
596
|
+
}
|
|
583
597
|
const sizeLimitBytes = await this._getBatchSizeLimitBytes();
|
|
584
598
|
if (this.autoBatchQueue.sizeBytes > sizeLimitBytes) {
|
|
585
|
-
this.drainAutoBatchQueue(sizeLimitBytes);
|
|
599
|
+
void this.drainAutoBatchQueue(sizeLimitBytes);
|
|
586
600
|
}
|
|
587
601
|
if (this.autoBatchQueue.items.length > 0) {
|
|
588
602
|
this.autoBatchTimeout = setTimeout(() => {
|
|
589
603
|
this.autoBatchTimeout = undefined;
|
|
590
|
-
this.drainAutoBatchQueue(sizeLimitBytes);
|
|
604
|
+
void this.drainAutoBatchQueue(sizeLimitBytes);
|
|
591
605
|
}, this.autoBatchAggregationDelayMs);
|
|
592
606
|
}
|
|
593
607
|
return itemPromise;
|
|
@@ -629,6 +643,13 @@ class Client {
|
|
|
629
643
|
}
|
|
630
644
|
return await this.settings;
|
|
631
645
|
}
|
|
646
|
+
/**
|
|
647
|
+
* Flushes current queued traces.
|
|
648
|
+
*/
|
|
649
|
+
async flush() {
|
|
650
|
+
const sizeLimitBytes = await this._getBatchSizeLimitBytes();
|
|
651
|
+
await this.drainAutoBatchQueue(sizeLimitBytes);
|
|
652
|
+
}
|
|
632
653
|
async createRun(run) {
|
|
633
654
|
if (!this._filterForSampling([run]).length) {
|
|
634
655
|
return;
|
|
@@ -921,7 +942,8 @@ class Client {
|
|
|
921
942
|
data.dotted_order !== undefined) {
|
|
922
943
|
if (run.end_time !== undefined &&
|
|
923
944
|
data.parent_run_id === undefined &&
|
|
924
|
-
this.blockOnRootRunFinalization
|
|
945
|
+
this.blockOnRootRunFinalization &&
|
|
946
|
+
!this.manualFlushMode) {
|
|
925
947
|
// Trigger batches as soon as a root trace ends and wait to ensure trace finishes
|
|
926
948
|
// in serverless environments.
|
|
927
949
|
await this.processRunOperation({ action: "update", item: data }).catch(console.error);
|
|
@@ -3052,6 +3074,10 @@ class Client {
|
|
|
3052
3074
|
* @returns A promise that resolves once all currently pending traces have sent.
|
|
3053
3075
|
*/
|
|
3054
3076
|
awaitPendingTraceBatches() {
|
|
3077
|
+
if (this.manualFlushMode) {
|
|
3078
|
+
console.warn("[WARNING]: When tracing in manual flush mode, you must call `await client.flush()` manually to submit trace batches.");
|
|
3079
|
+
return Promise.resolve();
|
|
3080
|
+
}
|
|
3055
3081
|
return Promise.all([
|
|
3056
3082
|
...this.autoBatchQueue.items.map(({ itemPromise }) => itemPromise),
|
|
3057
3083
|
this.batchIngestCaller.queue.onIdle(),
|
package/dist/client.d.ts
CHANGED
|
@@ -15,6 +15,11 @@ export interface ClientConfig {
|
|
|
15
15
|
blockOnRootRunFinalization?: boolean;
|
|
16
16
|
traceBatchConcurrency?: number;
|
|
17
17
|
fetchOptions?: RequestInit;
|
|
18
|
+
/**
|
|
19
|
+
* Whether to require manual .flush() calls before sending traces.
|
|
20
|
+
* Useful if encountering network rate limits at trace high volumes.
|
|
21
|
+
*/
|
|
22
|
+
manualFlushMode?: boolean;
|
|
18
23
|
}
|
|
19
24
|
/**
|
|
20
25
|
* Represents the parameters for listing runs (spans) from the Langsmith server.
|
|
@@ -207,6 +212,7 @@ export declare class Client implements LangSmithTracingClientInterface {
|
|
|
207
212
|
private traceBatchConcurrency;
|
|
208
213
|
private _serverInfo;
|
|
209
214
|
private _getServerInfoPromise?;
|
|
215
|
+
private manualFlushMode;
|
|
210
216
|
constructor(config?: ClientConfig);
|
|
211
217
|
static getDefaultClientConfig(): {
|
|
212
218
|
apiUrl: string;
|
|
@@ -233,6 +239,10 @@ export declare class Client implements LangSmithTracingClientInterface {
|
|
|
233
239
|
protected _getServerInfo(): Promise<any>;
|
|
234
240
|
protected _ensureServerInfo(): Promise<Record<string, any>>;
|
|
235
241
|
protected _getSettings(): Promise<LangSmithSettings>;
|
|
242
|
+
/**
|
|
243
|
+
* Flushes current queued traces.
|
|
244
|
+
*/
|
|
245
|
+
flush(): Promise<void>;
|
|
236
246
|
createRun(run: CreateRunParams): Promise<void>;
|
|
237
247
|
/**
|
|
238
248
|
* Batch ingest/upsert multiple runs in the Langsmith system.
|
|
@@ -804,7 +814,7 @@ export declare class Client implements LangSmithTracingClientInterface {
|
|
|
804
814
|
*
|
|
805
815
|
* @returns A promise that resolves once all currently pending traces have sent.
|
|
806
816
|
*/
|
|
807
|
-
awaitPendingTraceBatches(): Promise<[...void[], void]>;
|
|
817
|
+
awaitPendingTraceBatches(): Promise<void> | Promise<[...void[], void]>;
|
|
808
818
|
}
|
|
809
819
|
export interface LangSmithTracingClientInterface {
|
|
810
820
|
createRun: (run: CreateRunParams) => Promise<void>;
|
package/dist/client.js
CHANGED
|
@@ -280,6 +280,12 @@ export class Client {
|
|
|
280
280
|
writable: true,
|
|
281
281
|
value: void 0
|
|
282
282
|
});
|
|
283
|
+
Object.defineProperty(this, "manualFlushMode", {
|
|
284
|
+
enumerable: true,
|
|
285
|
+
configurable: true,
|
|
286
|
+
writable: true,
|
|
287
|
+
value: false
|
|
288
|
+
});
|
|
283
289
|
const defaultConfig = Client.getDefaultClientConfig();
|
|
284
290
|
this.tracingSampleRate = getTracingSamplingRate();
|
|
285
291
|
this.apiUrl = trimQuotes(config.apiUrl ?? defaultConfig.apiUrl) ?? "";
|
|
@@ -313,6 +319,7 @@ export class Client {
|
|
|
313
319
|
config.blockOnRootRunFinalization ?? this.blockOnRootRunFinalization;
|
|
314
320
|
this.batchSizeBytesLimit = config.batchSizeBytesLimit;
|
|
315
321
|
this.fetchOptions = config.fetchOptions || {};
|
|
322
|
+
this.manualFlushMode = config.manualFlushMode ?? this.manualFlushMode;
|
|
316
323
|
}
|
|
317
324
|
static getDefaultClientConfig() {
|
|
318
325
|
const apiKey = getLangSmithEnvironmentVariable("API_KEY");
|
|
@@ -510,14 +517,17 @@ export class Client {
|
|
|
510
517
|
return (serverInfo.instance_flags?.dataset_examples_multipart_enabled ?? false);
|
|
511
518
|
}
|
|
512
519
|
drainAutoBatchQueue(batchSizeLimit) {
|
|
520
|
+
const promises = [];
|
|
513
521
|
while (this.autoBatchQueue.items.length > 0) {
|
|
514
522
|
const [batch, done] = this.autoBatchQueue.pop(batchSizeLimit);
|
|
515
523
|
if (!batch.length) {
|
|
516
524
|
done();
|
|
517
525
|
break;
|
|
518
526
|
}
|
|
519
|
-
|
|
527
|
+
const batchPromise = this._processBatch(batch, done).catch(console.error);
|
|
528
|
+
promises.push(batchPromise);
|
|
520
529
|
}
|
|
530
|
+
return Promise.all(promises);
|
|
521
531
|
}
|
|
522
532
|
async _processBatch(batch, done) {
|
|
523
533
|
if (!batch.length) {
|
|
@@ -552,14 +562,18 @@ export class Client {
|
|
|
552
562
|
item.item = mergeRuntimeEnvIntoRunCreate(item.item);
|
|
553
563
|
}
|
|
554
564
|
const itemPromise = this.autoBatchQueue.push(item);
|
|
565
|
+
if (this.manualFlushMode) {
|
|
566
|
+
// Rely on manual flushing in serverless environments
|
|
567
|
+
return itemPromise;
|
|
568
|
+
}
|
|
555
569
|
const sizeLimitBytes = await this._getBatchSizeLimitBytes();
|
|
556
570
|
if (this.autoBatchQueue.sizeBytes > sizeLimitBytes) {
|
|
557
|
-
this.drainAutoBatchQueue(sizeLimitBytes);
|
|
571
|
+
void this.drainAutoBatchQueue(sizeLimitBytes);
|
|
558
572
|
}
|
|
559
573
|
if (this.autoBatchQueue.items.length > 0) {
|
|
560
574
|
this.autoBatchTimeout = setTimeout(() => {
|
|
561
575
|
this.autoBatchTimeout = undefined;
|
|
562
|
-
this.drainAutoBatchQueue(sizeLimitBytes);
|
|
576
|
+
void this.drainAutoBatchQueue(sizeLimitBytes);
|
|
563
577
|
}, this.autoBatchAggregationDelayMs);
|
|
564
578
|
}
|
|
565
579
|
return itemPromise;
|
|
@@ -601,6 +615,13 @@ export class Client {
|
|
|
601
615
|
}
|
|
602
616
|
return await this.settings;
|
|
603
617
|
}
|
|
618
|
+
/**
|
|
619
|
+
* Flushes current queued traces.
|
|
620
|
+
*/
|
|
621
|
+
async flush() {
|
|
622
|
+
const sizeLimitBytes = await this._getBatchSizeLimitBytes();
|
|
623
|
+
await this.drainAutoBatchQueue(sizeLimitBytes);
|
|
624
|
+
}
|
|
604
625
|
async createRun(run) {
|
|
605
626
|
if (!this._filterForSampling([run]).length) {
|
|
606
627
|
return;
|
|
@@ -893,7 +914,8 @@ export class Client {
|
|
|
893
914
|
data.dotted_order !== undefined) {
|
|
894
915
|
if (run.end_time !== undefined &&
|
|
895
916
|
data.parent_run_id === undefined &&
|
|
896
|
-
this.blockOnRootRunFinalization
|
|
917
|
+
this.blockOnRootRunFinalization &&
|
|
918
|
+
!this.manualFlushMode) {
|
|
897
919
|
// Trigger batches as soon as a root trace ends and wait to ensure trace finishes
|
|
898
920
|
// in serverless environments.
|
|
899
921
|
await this.processRunOperation({ action: "update", item: data }).catch(console.error);
|
|
@@ -3024,6 +3046,10 @@ export class Client {
|
|
|
3024
3046
|
* @returns A promise that resolves once all currently pending traces have sent.
|
|
3025
3047
|
*/
|
|
3026
3048
|
awaitPendingTraceBatches() {
|
|
3049
|
+
if (this.manualFlushMode) {
|
|
3050
|
+
console.warn("[WARNING]: When tracing in manual flush mode, you must call `await client.flush()` manually to submit trace batches.");
|
|
3051
|
+
return Promise.resolve();
|
|
3052
|
+
}
|
|
3027
3053
|
return Promise.all([
|
|
3028
3054
|
...this.autoBatchQueue.items.map(({ itemPromise }) => itemPromise),
|
|
3029
3055
|
this.batchIngestCaller.queue.onIdle(),
|
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.
|
|
11
|
+
exports.__version__ = "0.2.15-beta.0";
|
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.
|
|
5
|
+
export declare const __version__ = "0.2.15-beta.0";
|
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.
|
|
5
|
+
export const __version__ = "0.2.15-beta.0";
|
package/dist/run_trees.d.ts
CHANGED
|
@@ -80,7 +80,7 @@ export declare class RunTree implements BaseRun {
|
|
|
80
80
|
attachments?: Attachments;
|
|
81
81
|
constructor(originalConfig: RunTreeConfig | RunTree);
|
|
82
82
|
private static getDefaultConfig;
|
|
83
|
-
static getSharedClient
|
|
83
|
+
private static getSharedClient;
|
|
84
84
|
createChild(config: RunTreeConfig): RunTree;
|
|
85
85
|
end(outputs?: KVMap, error?: string, endTime?: number, metadata?: KVMap): Promise<void>;
|
|
86
86
|
private _convertToCreate;
|
|
@@ -38,7 +38,7 @@ const getCurrentRunTree = () => {
|
|
|
38
38
|
throw new Error([
|
|
39
39
|
"Could not get the current run tree.",
|
|
40
40
|
"",
|
|
41
|
-
"Please make sure you are calling this method within a traceable function
|
|
41
|
+
"Please make sure you are calling this method within a traceable function or the tracing is enabled.",
|
|
42
42
|
].join("\n"));
|
|
43
43
|
}
|
|
44
44
|
return runTree;
|
|
@@ -35,7 +35,7 @@ export const getCurrentRunTree = () => {
|
|
|
35
35
|
throw new Error([
|
|
36
36
|
"Could not get the current run tree.",
|
|
37
37
|
"",
|
|
38
|
-
"Please make sure you are calling this method within a traceable function
|
|
38
|
+
"Please make sure you are calling this method within a traceable function or the tracing is enabled.",
|
|
39
39
|
].join("\n"));
|
|
40
40
|
}
|
|
41
41
|
return runTree;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "langsmith",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.15-beta.0",
|
|
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": [
|
|
@@ -33,10 +33,6 @@
|
|
|
33
33
|
"langchain.js",
|
|
34
34
|
"langchain.d.ts",
|
|
35
35
|
"langchain.d.cts",
|
|
36
|
-
"jest.cjs",
|
|
37
|
-
"jest.js",
|
|
38
|
-
"jest.d.ts",
|
|
39
|
-
"jest.d.cts",
|
|
40
36
|
"vercel.cjs",
|
|
41
37
|
"vercel.js",
|
|
42
38
|
"vercel.d.ts",
|
|
@@ -232,15 +228,6 @@
|
|
|
232
228
|
"import": "./langchain.js",
|
|
233
229
|
"require": "./langchain.cjs"
|
|
234
230
|
},
|
|
235
|
-
"./jest": {
|
|
236
|
-
"types": {
|
|
237
|
-
"import": "./jest.d.ts",
|
|
238
|
-
"require": "./jest.d.cts",
|
|
239
|
-
"default": "./jest.d.ts"
|
|
240
|
-
},
|
|
241
|
-
"import": "./jest.js",
|
|
242
|
-
"require": "./jest.cjs"
|
|
243
|
-
},
|
|
244
231
|
"./vercel": {
|
|
245
232
|
"types": {
|
|
246
233
|
"import": "./vercel.d.ts",
|
package/dist/jest/globals.cjs
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.trackingEnabled = exports.jestAsyncLocalStorageInstance = void 0;
|
|
4
|
-
const node_async_hooks_1 = require("node:async_hooks");
|
|
5
|
-
const env_js_1 = require("../utils/env.cjs");
|
|
6
|
-
exports.jestAsyncLocalStorageInstance = new node_async_hooks_1.AsyncLocalStorage();
|
|
7
|
-
function trackingEnabled() {
|
|
8
|
-
return (0, env_js_1.getEnvironmentVariable)("LANGSMITH_TEST_TRACKING") === "true";
|
|
9
|
-
}
|
|
10
|
-
exports.trackingEnabled = trackingEnabled;
|
package/dist/jest/globals.d.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/// <reference types="node" resolution-mode="require"/>
|
|
2
|
-
import { AsyncLocalStorage } from "node:async_hooks";
|
|
3
|
-
import { Dataset, TracerSession, Example } from "../schemas.js";
|
|
4
|
-
import { Client } from "../client.js";
|
|
5
|
-
export declare const jestAsyncLocalStorageInstance: AsyncLocalStorage<{
|
|
6
|
-
dataset?: Dataset | undefined;
|
|
7
|
-
examples?: (Example & {
|
|
8
|
-
inputHash: string;
|
|
9
|
-
outputHash: string;
|
|
10
|
-
})[] | undefined;
|
|
11
|
-
createdAt: string;
|
|
12
|
-
project?: TracerSession | undefined;
|
|
13
|
-
currentExample?: Partial<Example> | undefined;
|
|
14
|
-
client: Client;
|
|
15
|
-
suiteUuid: string;
|
|
16
|
-
suiteName: string;
|
|
17
|
-
}>;
|
|
18
|
-
export declare function trackingEnabled(): boolean;
|
package/dist/jest/globals.js
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { AsyncLocalStorage } from "node:async_hooks";
|
|
2
|
-
import { getEnvironmentVariable } from "../utils/env.js";
|
|
3
|
-
export const jestAsyncLocalStorageInstance = new AsyncLocalStorage();
|
|
4
|
-
export function trackingEnabled() {
|
|
5
|
-
return getEnvironmentVariable("LANGSMITH_TEST_TRACKING") === "true";
|
|
6
|
-
}
|
package/dist/jest/index.cjs
DELETED
|
@@ -1,254 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/* eslint-disable import/no-extraneous-dependencies */
|
|
3
|
-
/* eslint-disable @typescript-eslint/no-namespace */
|
|
4
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
5
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
6
|
-
};
|
|
7
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.expect = exports.describe = exports.it = exports.test = void 0;
|
|
9
|
-
const globals_1 = require("@jest/globals");
|
|
10
|
-
const crypto_1 = __importDefault(require("crypto"));
|
|
11
|
-
const uuid_1 = require("uuid");
|
|
12
|
-
const traceable_js_1 = require("../traceable.cjs");
|
|
13
|
-
const run_trees_js_1 = require("../run_trees.cjs");
|
|
14
|
-
const _random_name_js_1 = require("../evaluation/_random_name.cjs");
|
|
15
|
-
const matchers_js_1 = require("./matchers.cjs");
|
|
16
|
-
const globals_js_1 = require("./globals.cjs");
|
|
17
|
-
const chain_js_1 = require("./vendor/chain.cjs");
|
|
18
|
-
globals_1.expect.extend({
|
|
19
|
-
toBeRelativeCloseTo: matchers_js_1.toBeRelativeCloseTo,
|
|
20
|
-
toBeAbsoluteCloseTo: matchers_js_1.toBeAbsoluteCloseTo,
|
|
21
|
-
toBeSemanticCloseTo: matchers_js_1.toBeSemanticCloseTo,
|
|
22
|
-
});
|
|
23
|
-
const objectHash = (obj, depth = 0) => {
|
|
24
|
-
// Prevent infinite recursion
|
|
25
|
-
if (depth > 50) {
|
|
26
|
-
return "[Max Depth Exceeded]";
|
|
27
|
-
}
|
|
28
|
-
if (Array.isArray(obj)) {
|
|
29
|
-
return obj.map((item) => objectHash(item, depth + 1));
|
|
30
|
-
}
|
|
31
|
-
if (obj && typeof obj === "object") {
|
|
32
|
-
return Object.keys(obj)
|
|
33
|
-
.sort()
|
|
34
|
-
.reduce((result, key) => {
|
|
35
|
-
result[key] = objectHash(obj[key], depth + 1);
|
|
36
|
-
return result;
|
|
37
|
-
}, {});
|
|
38
|
-
}
|
|
39
|
-
return crypto_1.default.createHash("sha256").update(JSON.stringify(obj)).digest("hex");
|
|
40
|
-
};
|
|
41
|
-
async function _createProject(client, datasetId) {
|
|
42
|
-
// Create the project, updating the experimentName until we find a unique one.
|
|
43
|
-
let project;
|
|
44
|
-
let experimentName = (0, _random_name_js_1.randomName)();
|
|
45
|
-
for (let i = 0; i < 10; i++) {
|
|
46
|
-
try {
|
|
47
|
-
project = await client.createProject({
|
|
48
|
-
projectName: experimentName,
|
|
49
|
-
referenceDatasetId: datasetId,
|
|
50
|
-
// description: this._description,
|
|
51
|
-
});
|
|
52
|
-
return project;
|
|
53
|
-
}
|
|
54
|
-
catch (e) {
|
|
55
|
-
// Naming collision
|
|
56
|
-
if (e?.name === "LangSmithConflictError") {
|
|
57
|
-
const ent = (0, uuid_1.v4)().slice(0, 6);
|
|
58
|
-
experimentName = `${experimentName}-${ent}`;
|
|
59
|
-
}
|
|
60
|
-
else {
|
|
61
|
-
throw e;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
throw new Error("Could not generate a unique experiment name within 10 attempts." +
|
|
66
|
-
" Please try again.");
|
|
67
|
-
}
|
|
68
|
-
const setupPromises = new Map();
|
|
69
|
-
async function runDatasetSetup(testClient, datasetName) {
|
|
70
|
-
let storageValue;
|
|
71
|
-
if (!(0, globals_js_1.trackingEnabled)()) {
|
|
72
|
-
storageValue = {
|
|
73
|
-
createdAt: new Date().toISOString(),
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
else {
|
|
77
|
-
let dataset;
|
|
78
|
-
try {
|
|
79
|
-
dataset = await testClient.readDataset({
|
|
80
|
-
datasetName,
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
catch (e) {
|
|
84
|
-
if (e.message.includes("not found")) {
|
|
85
|
-
dataset = await testClient.createDataset(datasetName, {
|
|
86
|
-
description: `Dataset for unit tests created on ${new Date().toISOString()}`,
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
else {
|
|
90
|
-
throw e;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
const examplesList = testClient.listExamples({
|
|
94
|
-
datasetName,
|
|
95
|
-
});
|
|
96
|
-
const examples = [];
|
|
97
|
-
for await (const example of examplesList) {
|
|
98
|
-
const inputHash = objectHash(example.inputs);
|
|
99
|
-
const outputHash = objectHash(example.outputs ?? {});
|
|
100
|
-
examples.push({ ...example, inputHash, outputHash });
|
|
101
|
-
}
|
|
102
|
-
const project = await _createProject(testClient, dataset.id);
|
|
103
|
-
storageValue = {
|
|
104
|
-
dataset,
|
|
105
|
-
examples,
|
|
106
|
-
project,
|
|
107
|
-
client: testClient,
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
return storageValue;
|
|
111
|
-
}
|
|
112
|
-
function wrapDescribeMethod(method) {
|
|
113
|
-
return function (datasetName, fn, config) {
|
|
114
|
-
return method(datasetName, () => {
|
|
115
|
-
const suiteUuid = (0, uuid_1.v4)();
|
|
116
|
-
/**
|
|
117
|
-
* We cannot rely on setting AsyncLocalStorage in beforeAll or beforeEach,
|
|
118
|
-
* due to https://github.com/jestjs/jest/issues/13653 and needing to use
|
|
119
|
-
* the janky .enterWith.
|
|
120
|
-
*
|
|
121
|
-
* We also cannot do async setup in describe due to Jest restrictions.
|
|
122
|
-
* However, .run works and since the below function does not contain synchronously,
|
|
123
|
-
* it works.
|
|
124
|
-
*/
|
|
125
|
-
void globals_js_1.jestAsyncLocalStorageInstance.run({
|
|
126
|
-
suiteUuid,
|
|
127
|
-
suiteName: datasetName,
|
|
128
|
-
client: config?.client ?? run_trees_js_1.RunTree.getSharedClient(),
|
|
129
|
-
createdAt: new Date().toISOString(),
|
|
130
|
-
}, fn);
|
|
131
|
-
});
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
const lsDescribe = Object.assign(wrapDescribeMethod(globals_1.describe), {
|
|
135
|
-
only: wrapDescribeMethod(globals_1.describe.only),
|
|
136
|
-
skip: wrapDescribeMethod(globals_1.describe.skip),
|
|
137
|
-
});
|
|
138
|
-
exports.describe = lsDescribe;
|
|
139
|
-
function wrapTestMethod(method) {
|
|
140
|
-
return function (params, config) {
|
|
141
|
-
// Due to https://github.com/jestjs/jest/issues/13653,
|
|
142
|
-
// we must access the local store value here before
|
|
143
|
-
// entering an async context
|
|
144
|
-
const context = globals_js_1.jestAsyncLocalStorageInstance.getStore();
|
|
145
|
-
// This typing is wrong, but necessary to avoid lint errors
|
|
146
|
-
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
147
|
-
return async function (...args) {
|
|
148
|
-
return method(args[0], async () => {
|
|
149
|
-
if (context === undefined) {
|
|
150
|
-
throw new Error(`Could not retrieve test context.\nPlease make sure you have tracing enabled and you are wrapping all of your test cases in an "ls.describe()" function.`);
|
|
151
|
-
}
|
|
152
|
-
// Because of https://github.com/jestjs/jest/issues/13653, we have to do asynchronous setup
|
|
153
|
-
// within the test itself
|
|
154
|
-
if (!setupPromises.get(context.suiteUuid)) {
|
|
155
|
-
setupPromises.set(context.suiteUuid, runDatasetSetup(context.client, context.suiteName));
|
|
156
|
-
}
|
|
157
|
-
const { examples, dataset, createdAt, project, client } = await setupPromises.get(context.suiteUuid);
|
|
158
|
-
const testInput = typeof params === "string" ? {} : params.inputs;
|
|
159
|
-
const testOutput = typeof params === "string" ? {} : params.outputs;
|
|
160
|
-
const inputHash = objectHash(testInput);
|
|
161
|
-
const outputHash = objectHash(testOutput ?? {});
|
|
162
|
-
if ((0, globals_js_1.trackingEnabled)()) {
|
|
163
|
-
const missingFields = [];
|
|
164
|
-
if (examples === undefined) {
|
|
165
|
-
missingFields.push("examples");
|
|
166
|
-
}
|
|
167
|
-
if (dataset === undefined) {
|
|
168
|
-
missingFields.push("dataset");
|
|
169
|
-
}
|
|
170
|
-
if (project === undefined) {
|
|
171
|
-
missingFields.push("project");
|
|
172
|
-
}
|
|
173
|
-
if (client === undefined) {
|
|
174
|
-
missingFields.push("client");
|
|
175
|
-
}
|
|
176
|
-
if (missingFields.length > 0) {
|
|
177
|
-
throw new Error(`Failed to initialize test tracking: Could not identify ${missingFields
|
|
178
|
-
.map((field) => `"${field}"`)
|
|
179
|
-
.join(", ")} while syncing to LangSmith. Please contact us for help.`);
|
|
180
|
-
}
|
|
181
|
-
const testClient = config?.client ?? client;
|
|
182
|
-
let example = (examples ?? []).find((example) => {
|
|
183
|
-
return (example.inputHash === inputHash &&
|
|
184
|
-
example.outputHash === outputHash);
|
|
185
|
-
});
|
|
186
|
-
if (example === undefined) {
|
|
187
|
-
const newExample = await testClient.createExample(testInput, testOutput, {
|
|
188
|
-
datasetId: dataset?.id,
|
|
189
|
-
createdAt: new Date(createdAt ?? new Date()),
|
|
190
|
-
});
|
|
191
|
-
example = { ...newExample, inputHash, outputHash };
|
|
192
|
-
}
|
|
193
|
-
// .enterWith is OK here
|
|
194
|
-
globals_js_1.jestAsyncLocalStorageInstance.enterWith({
|
|
195
|
-
...context,
|
|
196
|
-
currentExample: example,
|
|
197
|
-
client: testClient,
|
|
198
|
-
});
|
|
199
|
-
const traceableOptions = {
|
|
200
|
-
reference_example_id: example.id,
|
|
201
|
-
project_name: project.name,
|
|
202
|
-
metadata: {
|
|
203
|
-
...config?.metadata,
|
|
204
|
-
example_version: example.modified_at
|
|
205
|
-
? new Date(example.modified_at).toISOString()
|
|
206
|
-
: new Date(example.created_at).toISOString(),
|
|
207
|
-
},
|
|
208
|
-
client: testClient,
|
|
209
|
-
tracingEnabled: true,
|
|
210
|
-
name: "Unit test",
|
|
211
|
-
};
|
|
212
|
-
// Pass inputs into traceable so tracing works correctly but
|
|
213
|
-
// provide both to the user-defined test function
|
|
214
|
-
const tracedFunction = (0, traceable_js_1.traceable)(async (_) => {
|
|
215
|
-
return args[1]({
|
|
216
|
-
inputs: testInput,
|
|
217
|
-
outputs: testOutput,
|
|
218
|
-
});
|
|
219
|
-
}, { ...traceableOptions, ...config });
|
|
220
|
-
await tracedFunction(testInput);
|
|
221
|
-
await testClient.awaitPendingTraceBatches();
|
|
222
|
-
}
|
|
223
|
-
else {
|
|
224
|
-
// .enterWith is OK here
|
|
225
|
-
globals_js_1.jestAsyncLocalStorageInstance.enterWith({
|
|
226
|
-
...context,
|
|
227
|
-
currentExample: { inputs: testInput, outputs: testOutput },
|
|
228
|
-
});
|
|
229
|
-
await args[1]({
|
|
230
|
-
inputs: testInput,
|
|
231
|
-
outputs: testOutput,
|
|
232
|
-
});
|
|
233
|
-
}
|
|
234
|
-
}, ...args.slice(2));
|
|
235
|
-
};
|
|
236
|
-
};
|
|
237
|
-
}
|
|
238
|
-
function eachMethod(table) {
|
|
239
|
-
return function (name, fn, timeout) {
|
|
240
|
-
for (let i = 0; i < table.length; i += 1) {
|
|
241
|
-
const example = table[i];
|
|
242
|
-
wrapTestMethod(globals_1.test)(example)(`${name} ${i}`, fn, timeout);
|
|
243
|
-
}
|
|
244
|
-
};
|
|
245
|
-
}
|
|
246
|
-
const lsTest = Object.assign(wrapTestMethod(globals_1.test), {
|
|
247
|
-
only: wrapTestMethod(globals_1.test.only),
|
|
248
|
-
skip: wrapTestMethod(globals_1.test.skip),
|
|
249
|
-
each: eachMethod,
|
|
250
|
-
});
|
|
251
|
-
exports.test = lsTest;
|
|
252
|
-
exports.it = lsTest;
|
|
253
|
-
const wrappedExpect = (0, chain_js_1.wrapExpect)(globals_1.expect);
|
|
254
|
-
exports.expect = wrappedExpect;
|
package/dist/jest/index.d.ts
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { RunTreeConfig } from "../run_trees.js";
|
|
2
|
-
import { KVMap } from "../schemas.js";
|
|
3
|
-
import type { SimpleEvaluator } from "./vendor/gradedBy.js";
|
|
4
|
-
declare global {
|
|
5
|
-
namespace jest {
|
|
6
|
-
interface AsymmetricMatchers {
|
|
7
|
-
toBeRelativeCloseTo(expected: string, options?: any): void;
|
|
8
|
-
toBeAbsoluteCloseTo(expected: string, options?: any): void;
|
|
9
|
-
toBeSemanticCloseTo(expected: string, options?: any): Promise<void>;
|
|
10
|
-
}
|
|
11
|
-
interface Matchers<R> {
|
|
12
|
-
toBeRelativeCloseTo(expected: string, options?: any): R;
|
|
13
|
-
toBeAbsoluteCloseTo(expected: string, options?: any): R;
|
|
14
|
-
toBeSemanticCloseTo(expected: string, options?: any): Promise<R>;
|
|
15
|
-
gradedBy(evaluator: SimpleEvaluator): jest.Matchers<Promise<R>> & {
|
|
16
|
-
not: jest.Matchers<Promise<R>>;
|
|
17
|
-
resolves: jest.Matchers<Promise<R>>;
|
|
18
|
-
rejects: jest.Matchers<Promise<R>>;
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
export type LangSmithJestDescribeWrapper = (name: string, fn: () => void | Promise<void>, config?: Partial<RunTreeConfig>) => void;
|
|
24
|
-
declare const lsDescribe: LangSmithJestDescribeWrapper & {
|
|
25
|
-
only: LangSmithJestDescribeWrapper;
|
|
26
|
-
skip: LangSmithJestDescribeWrapper;
|
|
27
|
-
};
|
|
28
|
-
export type LangSmithJestTestWrapper<I, O> = (name: string, fn: (params: {
|
|
29
|
-
inputs: I;
|
|
30
|
-
outputs: O;
|
|
31
|
-
}) => unknown | Promise<unknown>, timeout?: number) => void;
|
|
32
|
-
declare function eachMethod<I extends KVMap, O extends KVMap>(table: {
|
|
33
|
-
inputs: I;
|
|
34
|
-
outputs: O;
|
|
35
|
-
}[]): (name: string, fn: (params: {
|
|
36
|
-
inputs: I;
|
|
37
|
-
outputs: O;
|
|
38
|
-
}) => unknown | Promise<unknown>, timeout?: number) => void;
|
|
39
|
-
declare const lsTest: (<I extends Record<string, any> = Record<string, any>, O extends Record<string, any> = Record<string, any>>(params: {
|
|
40
|
-
inputs: I;
|
|
41
|
-
outputs: O;
|
|
42
|
-
} | string, config?: Partial<RunTreeConfig>) => LangSmithJestTestWrapper<I, O>) & {
|
|
43
|
-
only: <I extends Record<string, any> = Record<string, any>, O extends Record<string, any> = Record<string, any>>(params: {
|
|
44
|
-
inputs: I;
|
|
45
|
-
outputs: O;
|
|
46
|
-
} | string, config?: Partial<RunTreeConfig>) => LangSmithJestTestWrapper<I, O>;
|
|
47
|
-
skip: <I extends Record<string, any> = Record<string, any>, O extends Record<string, any> = Record<string, any>>(params: {
|
|
48
|
-
inputs: I;
|
|
49
|
-
outputs: O;
|
|
50
|
-
} | string, config?: Partial<RunTreeConfig>) => LangSmithJestTestWrapper<I, O>;
|
|
51
|
-
each: typeof eachMethod;
|
|
52
|
-
};
|
|
53
|
-
declare const wrappedExpect: any;
|
|
54
|
-
export { lsTest as test, lsTest as it, lsDescribe as describe, wrappedExpect as expect, };
|
|
55
|
-
export { type SimpleEvaluator };
|