langsmith 0.0.66 → 0.0.68
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 +248 -26
- package/dist/client.d.ts +28 -3
- package/dist/client.js +248 -26
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/schemas.d.ts +32 -15
- package/package.json +2 -1
package/dist/client.cjs
CHANGED
|
@@ -29,6 +29,40 @@ const async_caller_js_1 = require("./utils/async_caller.cjs");
|
|
|
29
29
|
const messages_js_1 = require("./utils/messages.cjs");
|
|
30
30
|
const env_js_1 = require("./utils/env.cjs");
|
|
31
31
|
const index_js_1 = require("./index.cjs");
|
|
32
|
+
async function mergeRuntimeEnvIntoRunCreates(runs) {
|
|
33
|
+
const runtimeEnv = await (0, env_js_1.getRuntimeEnvironment)();
|
|
34
|
+
const envVars = (0, env_js_1.getLangChainEnvVarsMetadata)();
|
|
35
|
+
return runs.map((run) => {
|
|
36
|
+
const extra = run.extra ?? {};
|
|
37
|
+
const metadata = extra.metadata;
|
|
38
|
+
run.extra = {
|
|
39
|
+
...extra,
|
|
40
|
+
runtime: {
|
|
41
|
+
...runtimeEnv,
|
|
42
|
+
...extra?.runtime,
|
|
43
|
+
},
|
|
44
|
+
metadata: {
|
|
45
|
+
...envVars,
|
|
46
|
+
...(envVars.revision_id || run.revision_id
|
|
47
|
+
? { revision_id: run.revision_id ?? envVars.revision_id }
|
|
48
|
+
: {}),
|
|
49
|
+
...metadata,
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
return run;
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
const getTracingSamplingRate = () => {
|
|
56
|
+
const samplingRateStr = (0, env_js_1.getEnvironmentVariable)("LANGCHAIN_TRACING_SAMPLING_RATE");
|
|
57
|
+
if (samplingRateStr === undefined) {
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
const samplingRate = parseFloat(samplingRateStr);
|
|
61
|
+
if (samplingRate < 0 || samplingRate > 1) {
|
|
62
|
+
throw new Error(`LANGCHAIN_TRACING_SAMPLING_RATE must be between 0 and 1 if set. Got: ${samplingRate}`);
|
|
63
|
+
}
|
|
64
|
+
return samplingRate;
|
|
65
|
+
};
|
|
32
66
|
// utility functions
|
|
33
67
|
const isLocalhost = (url) => {
|
|
34
68
|
const strippedUrl = url.replace("http://", "").replace("https://", "");
|
|
@@ -114,7 +148,56 @@ class Client {
|
|
|
114
148
|
writable: true,
|
|
115
149
|
value: void 0
|
|
116
150
|
});
|
|
151
|
+
Object.defineProperty(this, "tracingSampleRate", {
|
|
152
|
+
enumerable: true,
|
|
153
|
+
configurable: true,
|
|
154
|
+
writable: true,
|
|
155
|
+
value: void 0
|
|
156
|
+
});
|
|
157
|
+
Object.defineProperty(this, "sampledPostUuids", {
|
|
158
|
+
enumerable: true,
|
|
159
|
+
configurable: true,
|
|
160
|
+
writable: true,
|
|
161
|
+
value: new Set()
|
|
162
|
+
});
|
|
163
|
+
Object.defineProperty(this, "autoBatchTracing", {
|
|
164
|
+
enumerable: true,
|
|
165
|
+
configurable: true,
|
|
166
|
+
writable: true,
|
|
167
|
+
value: false
|
|
168
|
+
});
|
|
169
|
+
Object.defineProperty(this, "pendingAutoBatchedRuns", {
|
|
170
|
+
enumerable: true,
|
|
171
|
+
configurable: true,
|
|
172
|
+
writable: true,
|
|
173
|
+
value: []
|
|
174
|
+
});
|
|
175
|
+
Object.defineProperty(this, "pendingAutoBatchedRunLimit", {
|
|
176
|
+
enumerable: true,
|
|
177
|
+
configurable: true,
|
|
178
|
+
writable: true,
|
|
179
|
+
value: 100
|
|
180
|
+
});
|
|
181
|
+
Object.defineProperty(this, "autoBatchTimeout", {
|
|
182
|
+
enumerable: true,
|
|
183
|
+
configurable: true,
|
|
184
|
+
writable: true,
|
|
185
|
+
value: void 0
|
|
186
|
+
});
|
|
187
|
+
Object.defineProperty(this, "autoBatchInitialDelayMs", {
|
|
188
|
+
enumerable: true,
|
|
189
|
+
configurable: true,
|
|
190
|
+
writable: true,
|
|
191
|
+
value: 250
|
|
192
|
+
});
|
|
193
|
+
Object.defineProperty(this, "autoBatchAggregationDelayMs", {
|
|
194
|
+
enumerable: true,
|
|
195
|
+
configurable: true,
|
|
196
|
+
writable: true,
|
|
197
|
+
value: 50
|
|
198
|
+
});
|
|
117
199
|
const defaultConfig = Client.getDefaultClientConfig();
|
|
200
|
+
this.tracingSampleRate = getTracingSamplingRate();
|
|
118
201
|
this.apiUrl = trimQuotes(config.apiUrl ?? defaultConfig.apiUrl) ?? "";
|
|
119
202
|
this.apiKey = trimQuotes(config.apiKey ?? defaultConfig.apiKey);
|
|
120
203
|
this.webUrl = trimQuotes(config.webUrl ?? defaultConfig.webUrl);
|
|
@@ -123,6 +206,9 @@ class Client {
|
|
|
123
206
|
this.caller = new async_caller_js_1.AsyncCaller(config.callerOptions ?? {});
|
|
124
207
|
this.hideInputs = config.hideInputs ?? defaultConfig.hideInputs;
|
|
125
208
|
this.hideOutputs = config.hideOutputs ?? defaultConfig.hideOutputs;
|
|
209
|
+
this.autoBatchTracing = config.autoBatchTracing ?? this.autoBatchTracing;
|
|
210
|
+
this.pendingAutoBatchedRunLimit =
|
|
211
|
+
config.pendingAutoBatchedRunLimit ?? this.pendingAutoBatchedRunLimit;
|
|
126
212
|
}
|
|
127
213
|
static getDefaultClientConfig() {
|
|
128
214
|
const apiKey = (0, env_js_1.getEnvironmentVariable)("LANGCHAIN_API_KEY");
|
|
@@ -187,6 +273,16 @@ class Client {
|
|
|
187
273
|
}
|
|
188
274
|
return outputs;
|
|
189
275
|
}
|
|
276
|
+
prepareRunCreateOrUpdateInputs(run) {
|
|
277
|
+
const runParams = { ...run };
|
|
278
|
+
if (runParams.inputs !== undefined) {
|
|
279
|
+
runParams.inputs = this.processInputs(runParams.inputs);
|
|
280
|
+
}
|
|
281
|
+
if (runParams.outputs !== undefined) {
|
|
282
|
+
runParams.outputs = this.processOutputs(runParams.outputs);
|
|
283
|
+
}
|
|
284
|
+
return runParams;
|
|
285
|
+
}
|
|
190
286
|
async _getResponse(path, queryParams) {
|
|
191
287
|
const paramsString = queryParams?.toString() ?? "";
|
|
192
288
|
const url = `${this.apiUrl}${path}?${paramsString}`;
|
|
@@ -257,45 +353,157 @@ class Client {
|
|
|
257
353
|
bodyParams.cursor = cursors.next;
|
|
258
354
|
}
|
|
259
355
|
}
|
|
356
|
+
_filterForSampling(runs, patch = false) {
|
|
357
|
+
if (this.tracingSampleRate === undefined) {
|
|
358
|
+
return runs;
|
|
359
|
+
}
|
|
360
|
+
if (patch) {
|
|
361
|
+
const sampled = [];
|
|
362
|
+
for (const run of runs) {
|
|
363
|
+
if (this.sampledPostUuids.has(run.id)) {
|
|
364
|
+
sampled.push(run);
|
|
365
|
+
this.sampledPostUuids.delete(run.id);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
return sampled;
|
|
369
|
+
}
|
|
370
|
+
else {
|
|
371
|
+
const sampled = [];
|
|
372
|
+
for (const run of runs) {
|
|
373
|
+
if (Math.random() < this.tracingSampleRate) {
|
|
374
|
+
sampled.push(run);
|
|
375
|
+
this.sampledPostUuids.add(run.id);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
return sampled;
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
async triggerAutoBatchSend(runs) {
|
|
382
|
+
let batch = runs;
|
|
383
|
+
if (batch === undefined) {
|
|
384
|
+
batch = this.pendingAutoBatchedRuns.slice(0, this.pendingAutoBatchedRunLimit);
|
|
385
|
+
this.pendingAutoBatchedRuns = this.pendingAutoBatchedRuns.slice(this.pendingAutoBatchedRunLimit);
|
|
386
|
+
}
|
|
387
|
+
await this.batchIngestRuns({
|
|
388
|
+
runCreates: batch
|
|
389
|
+
.filter((item) => item.action === "create")
|
|
390
|
+
.map((item) => item.item),
|
|
391
|
+
runUpdates: batch
|
|
392
|
+
.filter((item) => item.action === "update")
|
|
393
|
+
.map((item) => item.item),
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
appendRunCreateToAutoBatchQueue(item) {
|
|
397
|
+
const oldTimeout = this.autoBatchTimeout;
|
|
398
|
+
clearTimeout(this.autoBatchTimeout);
|
|
399
|
+
this.autoBatchTimeout = undefined;
|
|
400
|
+
this.pendingAutoBatchedRuns.push(item);
|
|
401
|
+
while (this.pendingAutoBatchedRuns.length >= this.pendingAutoBatchedRunLimit) {
|
|
402
|
+
const batch = this.pendingAutoBatchedRuns.slice(0, this.pendingAutoBatchedRunLimit);
|
|
403
|
+
this.pendingAutoBatchedRuns = this.pendingAutoBatchedRuns.slice(this.pendingAutoBatchedRunLimit);
|
|
404
|
+
void this.triggerAutoBatchSend(batch);
|
|
405
|
+
}
|
|
406
|
+
if (this.pendingAutoBatchedRuns.length > 0) {
|
|
407
|
+
if (!oldTimeout) {
|
|
408
|
+
this.autoBatchTimeout = setTimeout(() => {
|
|
409
|
+
this.autoBatchTimeout = undefined;
|
|
410
|
+
void this.triggerAutoBatchSend();
|
|
411
|
+
}, this.autoBatchInitialDelayMs);
|
|
412
|
+
}
|
|
413
|
+
else {
|
|
414
|
+
this.autoBatchTimeout = setTimeout(() => {
|
|
415
|
+
this.autoBatchTimeout = undefined;
|
|
416
|
+
void this.triggerAutoBatchSend();
|
|
417
|
+
}, this.autoBatchAggregationDelayMs);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
}
|
|
260
421
|
async createRun(run) {
|
|
422
|
+
if (!this._filterForSampling([run]).length) {
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
261
425
|
const headers = { ...this.headers, "Content-Type": "application/json" };
|
|
262
|
-
const extra = run.extra ?? {};
|
|
263
|
-
const metadata = extra.metadata;
|
|
264
|
-
const runtimeEnv = await (0, env_js_1.getRuntimeEnvironment)();
|
|
265
|
-
const envVars = (0, env_js_1.getLangChainEnvVarsMetadata)();
|
|
266
426
|
const session_name = run.project_name;
|
|
267
427
|
delete run.project_name;
|
|
268
|
-
const runCreate = {
|
|
428
|
+
const runCreate = this.prepareRunCreateOrUpdateInputs({
|
|
269
429
|
session_name,
|
|
270
430
|
...run,
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
: {}),
|
|
282
|
-
...metadata,
|
|
283
|
-
},
|
|
284
|
-
},
|
|
285
|
-
};
|
|
286
|
-
runCreate.inputs = this.processInputs(runCreate.inputs);
|
|
287
|
-
if (runCreate.outputs) {
|
|
288
|
-
runCreate.outputs = this.processOutputs(runCreate.outputs);
|
|
431
|
+
start_time: run.start_time ?? Date.now(),
|
|
432
|
+
});
|
|
433
|
+
if (this.autoBatchTracing &&
|
|
434
|
+
runCreate.trace_id !== undefined &&
|
|
435
|
+
runCreate.dotted_order !== undefined) {
|
|
436
|
+
this.appendRunCreateToAutoBatchQueue({
|
|
437
|
+
action: "create",
|
|
438
|
+
item: runCreate,
|
|
439
|
+
});
|
|
440
|
+
return;
|
|
289
441
|
}
|
|
290
|
-
|
|
442
|
+
const mergedRunCreateParams = await mergeRuntimeEnvIntoRunCreates([
|
|
443
|
+
runCreate,
|
|
444
|
+
]);
|
|
291
445
|
const response = await this.caller.call(fetch, `${this.apiUrl}/runs`, {
|
|
292
446
|
method: "POST",
|
|
293
447
|
headers,
|
|
294
|
-
body: JSON.stringify(
|
|
448
|
+
body: JSON.stringify(mergedRunCreateParams[0]),
|
|
295
449
|
signal: AbortSignal.timeout(this.timeout_ms),
|
|
296
450
|
});
|
|
297
451
|
await raiseForStatus(response, "create run");
|
|
298
452
|
}
|
|
453
|
+
/**
|
|
454
|
+
* Batch ingest/upsert multiple runs in the Langsmith system.
|
|
455
|
+
* @param runs
|
|
456
|
+
*/
|
|
457
|
+
async batchIngestRuns({ runCreates, runUpdates, }) {
|
|
458
|
+
if (runCreates === undefined && runUpdates === undefined) {
|
|
459
|
+
return;
|
|
460
|
+
}
|
|
461
|
+
let preparedCreateParams = runCreates?.map((create) => this.prepareRunCreateOrUpdateInputs(create)) ?? [];
|
|
462
|
+
let preparedUpdateParams = runUpdates?.map((update) => this.prepareRunCreateOrUpdateInputs(update)) ?? [];
|
|
463
|
+
if (preparedCreateParams.length > 0 && preparedUpdateParams.length > 0) {
|
|
464
|
+
const createById = preparedCreateParams.reduce((params, run) => {
|
|
465
|
+
if (!run.id) {
|
|
466
|
+
return params;
|
|
467
|
+
}
|
|
468
|
+
params[run.id] = run;
|
|
469
|
+
return params;
|
|
470
|
+
}, {});
|
|
471
|
+
const standaloneUpdates = [];
|
|
472
|
+
for (const updateParam of preparedUpdateParams) {
|
|
473
|
+
if (updateParam.id !== undefined && createById[updateParam.id]) {
|
|
474
|
+
createById[updateParam.id] = {
|
|
475
|
+
...createById[updateParam.id],
|
|
476
|
+
...updateParam,
|
|
477
|
+
};
|
|
478
|
+
}
|
|
479
|
+
else {
|
|
480
|
+
standaloneUpdates.push(updateParam);
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
preparedCreateParams = Object.values(createById);
|
|
484
|
+
preparedUpdateParams = standaloneUpdates;
|
|
485
|
+
}
|
|
486
|
+
const body = {
|
|
487
|
+
post: this._filterForSampling(preparedCreateParams),
|
|
488
|
+
patch: this._filterForSampling(preparedUpdateParams, true),
|
|
489
|
+
};
|
|
490
|
+
if (!body.post.length && !body.patch.length) {
|
|
491
|
+
return;
|
|
492
|
+
}
|
|
493
|
+
preparedCreateParams = await mergeRuntimeEnvIntoRunCreates(preparedCreateParams);
|
|
494
|
+
const headers = {
|
|
495
|
+
...this.headers,
|
|
496
|
+
"Content-Type": "application/json",
|
|
497
|
+
Accept: "application/json",
|
|
498
|
+
};
|
|
499
|
+
const response = await this.caller.call(fetch, `${this.apiUrl}/runs/batch`, {
|
|
500
|
+
method: "POST",
|
|
501
|
+
headers,
|
|
502
|
+
body: JSON.stringify(body),
|
|
503
|
+
signal: AbortSignal.timeout(this.timeout_ms),
|
|
504
|
+
});
|
|
505
|
+
await raiseForStatus(response, "batch create run");
|
|
506
|
+
}
|
|
299
507
|
async updateRun(runId, run) {
|
|
300
508
|
assertUuid(runId);
|
|
301
509
|
if (run.inputs) {
|
|
@@ -304,6 +512,17 @@ class Client {
|
|
|
304
512
|
if (run.outputs) {
|
|
305
513
|
run.outputs = this.processOutputs(run.outputs);
|
|
306
514
|
}
|
|
515
|
+
// TODO: Untangle types
|
|
516
|
+
const data = { ...run, id: runId };
|
|
517
|
+
if (!this._filterForSampling([data], true).length) {
|
|
518
|
+
return;
|
|
519
|
+
}
|
|
520
|
+
if (this.autoBatchTracing &&
|
|
521
|
+
data.trace_id !== undefined &&
|
|
522
|
+
data.dotted_order !== undefined) {
|
|
523
|
+
this.appendRunCreateToAutoBatchQueue({ action: "update", item: data });
|
|
524
|
+
return;
|
|
525
|
+
}
|
|
307
526
|
const headers = { ...this.headers, "Content-Type": "application/json" };
|
|
308
527
|
const response = await this.caller.call(fetch, `${this.apiUrl}/runs/${runId}`, {
|
|
309
528
|
method: "PATCH",
|
|
@@ -572,7 +791,7 @@ class Client {
|
|
|
572
791
|
}
|
|
573
792
|
return result;
|
|
574
793
|
}
|
|
575
|
-
async readProject({ projectId, projectName, }) {
|
|
794
|
+
async readProject({ projectId, projectName, includeStats, }) {
|
|
576
795
|
let path = "/sessions";
|
|
577
796
|
const params = new URLSearchParams();
|
|
578
797
|
if (projectId !== undefined && projectName !== undefined) {
|
|
@@ -588,6 +807,9 @@ class Client {
|
|
|
588
807
|
else {
|
|
589
808
|
throw new Error("Must provide projectName or projectId");
|
|
590
809
|
}
|
|
810
|
+
if (includeStats !== undefined) {
|
|
811
|
+
params.append("include_stats", includeStats.toString());
|
|
812
|
+
}
|
|
591
813
|
const response = await this._get(path, params);
|
|
592
814
|
let result;
|
|
593
815
|
if (Array.isArray(response)) {
|
package/dist/client.d.ts
CHANGED
|
@@ -9,6 +9,8 @@ interface ClientConfig {
|
|
|
9
9
|
webUrl?: string;
|
|
10
10
|
hideInputs?: boolean;
|
|
11
11
|
hideOutputs?: boolean;
|
|
12
|
+
autoBatchTracing?: boolean;
|
|
13
|
+
pendingAutoBatchedRunLimit?: number;
|
|
12
14
|
}
|
|
13
15
|
interface ListRunsParams {
|
|
14
16
|
projectId?: string;
|
|
@@ -49,8 +51,10 @@ interface CreateRunParams {
|
|
|
49
51
|
parent_run_id?: string;
|
|
50
52
|
project_name?: string;
|
|
51
53
|
revision_id?: string;
|
|
54
|
+
trace_id?: string;
|
|
55
|
+
dotted_order?: string;
|
|
52
56
|
}
|
|
53
|
-
interface
|
|
57
|
+
interface ProjectOptions {
|
|
54
58
|
projectName?: string;
|
|
55
59
|
projectId?: string;
|
|
56
60
|
}
|
|
@@ -70,6 +74,14 @@ export declare class Client {
|
|
|
70
74
|
private _tenantId;
|
|
71
75
|
private hideInputs?;
|
|
72
76
|
private hideOutputs?;
|
|
77
|
+
private tracingSampleRate?;
|
|
78
|
+
private sampledPostUuids;
|
|
79
|
+
private autoBatchTracing;
|
|
80
|
+
private pendingAutoBatchedRuns;
|
|
81
|
+
private pendingAutoBatchedRunLimit;
|
|
82
|
+
private autoBatchTimeout;
|
|
83
|
+
private autoBatchInitialDelayMs;
|
|
84
|
+
private autoBatchAggregationDelayMs;
|
|
73
85
|
constructor(config?: ClientConfig);
|
|
74
86
|
static getDefaultClientConfig(): {
|
|
75
87
|
apiUrl: string;
|
|
@@ -83,11 +95,23 @@ export declare class Client {
|
|
|
83
95
|
private get headers();
|
|
84
96
|
private processInputs;
|
|
85
97
|
private processOutputs;
|
|
98
|
+
private prepareRunCreateOrUpdateInputs;
|
|
86
99
|
private _getResponse;
|
|
87
100
|
private _get;
|
|
88
101
|
private _getPaginated;
|
|
89
102
|
private _getCursorPaginatedList;
|
|
103
|
+
private _filterForSampling;
|
|
104
|
+
private triggerAutoBatchSend;
|
|
105
|
+
private appendRunCreateToAutoBatchQueue;
|
|
90
106
|
createRun(run: CreateRunParams): Promise<void>;
|
|
107
|
+
/**
|
|
108
|
+
* Batch ingest/upsert multiple runs in the Langsmith system.
|
|
109
|
+
* @param runs
|
|
110
|
+
*/
|
|
111
|
+
batchIngestRuns({ runCreates, runUpdates, }: {
|
|
112
|
+
runCreates?: RunCreate[];
|
|
113
|
+
runUpdates?: RunUpdate[];
|
|
114
|
+
}): Promise<void>;
|
|
91
115
|
updateRun(runId: string, run: RunUpdate): Promise<void>;
|
|
92
116
|
readRun(runId: string, { loadChildRuns }?: {
|
|
93
117
|
loadChildRuns: boolean;
|
|
@@ -95,7 +119,7 @@ export declare class Client {
|
|
|
95
119
|
getRunUrl({ runId, run, projectOpts, }: {
|
|
96
120
|
runId?: string;
|
|
97
121
|
run?: Run;
|
|
98
|
-
projectOpts?:
|
|
122
|
+
projectOpts?: ProjectOptions;
|
|
99
123
|
}): Promise<string>;
|
|
100
124
|
private _loadChildRuns;
|
|
101
125
|
listRuns({ projectId, projectName, parentRunId, referenceExampleId, startTime, executionOrder, runType, error, id, query, filter, limit, }: ListRunsParams): AsyncIterable<Run>;
|
|
@@ -126,9 +150,10 @@ export declare class Client {
|
|
|
126
150
|
projectExtra?: Record<string, any> | null;
|
|
127
151
|
endTime?: string | null;
|
|
128
152
|
}): Promise<TracerSession>;
|
|
129
|
-
readProject({ projectId, projectName, }: {
|
|
153
|
+
readProject({ projectId, projectName, includeStats, }: {
|
|
130
154
|
projectId?: string;
|
|
131
155
|
projectName?: string;
|
|
156
|
+
includeStats?: boolean;
|
|
132
157
|
}): Promise<TracerSessionResult>;
|
|
133
158
|
private _getTenantId;
|
|
134
159
|
listProjects({ projectIds, name, nameContains, referenceDatasetId, referenceDatasetName, referenceFree, }?: {
|
package/dist/client.js
CHANGED
|
@@ -3,6 +3,40 @@ import { AsyncCaller } from "./utils/async_caller.js";
|
|
|
3
3
|
import { convertLangChainMessageToExample, isLangChainMessage, } from "./utils/messages.js";
|
|
4
4
|
import { getEnvironmentVariable, getLangChainEnvVarsMetadata, getRuntimeEnvironment, } from "./utils/env.js";
|
|
5
5
|
import { __version__ } from "./index.js";
|
|
6
|
+
async function mergeRuntimeEnvIntoRunCreates(runs) {
|
|
7
|
+
const runtimeEnv = await getRuntimeEnvironment();
|
|
8
|
+
const envVars = getLangChainEnvVarsMetadata();
|
|
9
|
+
return runs.map((run) => {
|
|
10
|
+
const extra = run.extra ?? {};
|
|
11
|
+
const metadata = extra.metadata;
|
|
12
|
+
run.extra = {
|
|
13
|
+
...extra,
|
|
14
|
+
runtime: {
|
|
15
|
+
...runtimeEnv,
|
|
16
|
+
...extra?.runtime,
|
|
17
|
+
},
|
|
18
|
+
metadata: {
|
|
19
|
+
...envVars,
|
|
20
|
+
...(envVars.revision_id || run.revision_id
|
|
21
|
+
? { revision_id: run.revision_id ?? envVars.revision_id }
|
|
22
|
+
: {}),
|
|
23
|
+
...metadata,
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
return run;
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
const getTracingSamplingRate = () => {
|
|
30
|
+
const samplingRateStr = getEnvironmentVariable("LANGCHAIN_TRACING_SAMPLING_RATE");
|
|
31
|
+
if (samplingRateStr === undefined) {
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
const samplingRate = parseFloat(samplingRateStr);
|
|
35
|
+
if (samplingRate < 0 || samplingRate > 1) {
|
|
36
|
+
throw new Error(`LANGCHAIN_TRACING_SAMPLING_RATE must be between 0 and 1 if set. Got: ${samplingRate}`);
|
|
37
|
+
}
|
|
38
|
+
return samplingRate;
|
|
39
|
+
};
|
|
6
40
|
// utility functions
|
|
7
41
|
const isLocalhost = (url) => {
|
|
8
42
|
const strippedUrl = url.replace("http://", "").replace("https://", "");
|
|
@@ -88,7 +122,56 @@ export class Client {
|
|
|
88
122
|
writable: true,
|
|
89
123
|
value: void 0
|
|
90
124
|
});
|
|
125
|
+
Object.defineProperty(this, "tracingSampleRate", {
|
|
126
|
+
enumerable: true,
|
|
127
|
+
configurable: true,
|
|
128
|
+
writable: true,
|
|
129
|
+
value: void 0
|
|
130
|
+
});
|
|
131
|
+
Object.defineProperty(this, "sampledPostUuids", {
|
|
132
|
+
enumerable: true,
|
|
133
|
+
configurable: true,
|
|
134
|
+
writable: true,
|
|
135
|
+
value: new Set()
|
|
136
|
+
});
|
|
137
|
+
Object.defineProperty(this, "autoBatchTracing", {
|
|
138
|
+
enumerable: true,
|
|
139
|
+
configurable: true,
|
|
140
|
+
writable: true,
|
|
141
|
+
value: false
|
|
142
|
+
});
|
|
143
|
+
Object.defineProperty(this, "pendingAutoBatchedRuns", {
|
|
144
|
+
enumerable: true,
|
|
145
|
+
configurable: true,
|
|
146
|
+
writable: true,
|
|
147
|
+
value: []
|
|
148
|
+
});
|
|
149
|
+
Object.defineProperty(this, "pendingAutoBatchedRunLimit", {
|
|
150
|
+
enumerable: true,
|
|
151
|
+
configurable: true,
|
|
152
|
+
writable: true,
|
|
153
|
+
value: 100
|
|
154
|
+
});
|
|
155
|
+
Object.defineProperty(this, "autoBatchTimeout", {
|
|
156
|
+
enumerable: true,
|
|
157
|
+
configurable: true,
|
|
158
|
+
writable: true,
|
|
159
|
+
value: void 0
|
|
160
|
+
});
|
|
161
|
+
Object.defineProperty(this, "autoBatchInitialDelayMs", {
|
|
162
|
+
enumerable: true,
|
|
163
|
+
configurable: true,
|
|
164
|
+
writable: true,
|
|
165
|
+
value: 250
|
|
166
|
+
});
|
|
167
|
+
Object.defineProperty(this, "autoBatchAggregationDelayMs", {
|
|
168
|
+
enumerable: true,
|
|
169
|
+
configurable: true,
|
|
170
|
+
writable: true,
|
|
171
|
+
value: 50
|
|
172
|
+
});
|
|
91
173
|
const defaultConfig = Client.getDefaultClientConfig();
|
|
174
|
+
this.tracingSampleRate = getTracingSamplingRate();
|
|
92
175
|
this.apiUrl = trimQuotes(config.apiUrl ?? defaultConfig.apiUrl) ?? "";
|
|
93
176
|
this.apiKey = trimQuotes(config.apiKey ?? defaultConfig.apiKey);
|
|
94
177
|
this.webUrl = trimQuotes(config.webUrl ?? defaultConfig.webUrl);
|
|
@@ -97,6 +180,9 @@ export class Client {
|
|
|
97
180
|
this.caller = new AsyncCaller(config.callerOptions ?? {});
|
|
98
181
|
this.hideInputs = config.hideInputs ?? defaultConfig.hideInputs;
|
|
99
182
|
this.hideOutputs = config.hideOutputs ?? defaultConfig.hideOutputs;
|
|
183
|
+
this.autoBatchTracing = config.autoBatchTracing ?? this.autoBatchTracing;
|
|
184
|
+
this.pendingAutoBatchedRunLimit =
|
|
185
|
+
config.pendingAutoBatchedRunLimit ?? this.pendingAutoBatchedRunLimit;
|
|
100
186
|
}
|
|
101
187
|
static getDefaultClientConfig() {
|
|
102
188
|
const apiKey = getEnvironmentVariable("LANGCHAIN_API_KEY");
|
|
@@ -161,6 +247,16 @@ export class Client {
|
|
|
161
247
|
}
|
|
162
248
|
return outputs;
|
|
163
249
|
}
|
|
250
|
+
prepareRunCreateOrUpdateInputs(run) {
|
|
251
|
+
const runParams = { ...run };
|
|
252
|
+
if (runParams.inputs !== undefined) {
|
|
253
|
+
runParams.inputs = this.processInputs(runParams.inputs);
|
|
254
|
+
}
|
|
255
|
+
if (runParams.outputs !== undefined) {
|
|
256
|
+
runParams.outputs = this.processOutputs(runParams.outputs);
|
|
257
|
+
}
|
|
258
|
+
return runParams;
|
|
259
|
+
}
|
|
164
260
|
async _getResponse(path, queryParams) {
|
|
165
261
|
const paramsString = queryParams?.toString() ?? "";
|
|
166
262
|
const url = `${this.apiUrl}${path}?${paramsString}`;
|
|
@@ -231,45 +327,157 @@ export class Client {
|
|
|
231
327
|
bodyParams.cursor = cursors.next;
|
|
232
328
|
}
|
|
233
329
|
}
|
|
330
|
+
_filterForSampling(runs, patch = false) {
|
|
331
|
+
if (this.tracingSampleRate === undefined) {
|
|
332
|
+
return runs;
|
|
333
|
+
}
|
|
334
|
+
if (patch) {
|
|
335
|
+
const sampled = [];
|
|
336
|
+
for (const run of runs) {
|
|
337
|
+
if (this.sampledPostUuids.has(run.id)) {
|
|
338
|
+
sampled.push(run);
|
|
339
|
+
this.sampledPostUuids.delete(run.id);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
return sampled;
|
|
343
|
+
}
|
|
344
|
+
else {
|
|
345
|
+
const sampled = [];
|
|
346
|
+
for (const run of runs) {
|
|
347
|
+
if (Math.random() < this.tracingSampleRate) {
|
|
348
|
+
sampled.push(run);
|
|
349
|
+
this.sampledPostUuids.add(run.id);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
return sampled;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
async triggerAutoBatchSend(runs) {
|
|
356
|
+
let batch = runs;
|
|
357
|
+
if (batch === undefined) {
|
|
358
|
+
batch = this.pendingAutoBatchedRuns.slice(0, this.pendingAutoBatchedRunLimit);
|
|
359
|
+
this.pendingAutoBatchedRuns = this.pendingAutoBatchedRuns.slice(this.pendingAutoBatchedRunLimit);
|
|
360
|
+
}
|
|
361
|
+
await this.batchIngestRuns({
|
|
362
|
+
runCreates: batch
|
|
363
|
+
.filter((item) => item.action === "create")
|
|
364
|
+
.map((item) => item.item),
|
|
365
|
+
runUpdates: batch
|
|
366
|
+
.filter((item) => item.action === "update")
|
|
367
|
+
.map((item) => item.item),
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
appendRunCreateToAutoBatchQueue(item) {
|
|
371
|
+
const oldTimeout = this.autoBatchTimeout;
|
|
372
|
+
clearTimeout(this.autoBatchTimeout);
|
|
373
|
+
this.autoBatchTimeout = undefined;
|
|
374
|
+
this.pendingAutoBatchedRuns.push(item);
|
|
375
|
+
while (this.pendingAutoBatchedRuns.length >= this.pendingAutoBatchedRunLimit) {
|
|
376
|
+
const batch = this.pendingAutoBatchedRuns.slice(0, this.pendingAutoBatchedRunLimit);
|
|
377
|
+
this.pendingAutoBatchedRuns = this.pendingAutoBatchedRuns.slice(this.pendingAutoBatchedRunLimit);
|
|
378
|
+
void this.triggerAutoBatchSend(batch);
|
|
379
|
+
}
|
|
380
|
+
if (this.pendingAutoBatchedRuns.length > 0) {
|
|
381
|
+
if (!oldTimeout) {
|
|
382
|
+
this.autoBatchTimeout = setTimeout(() => {
|
|
383
|
+
this.autoBatchTimeout = undefined;
|
|
384
|
+
void this.triggerAutoBatchSend();
|
|
385
|
+
}, this.autoBatchInitialDelayMs);
|
|
386
|
+
}
|
|
387
|
+
else {
|
|
388
|
+
this.autoBatchTimeout = setTimeout(() => {
|
|
389
|
+
this.autoBatchTimeout = undefined;
|
|
390
|
+
void this.triggerAutoBatchSend();
|
|
391
|
+
}, this.autoBatchAggregationDelayMs);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
}
|
|
234
395
|
async createRun(run) {
|
|
396
|
+
if (!this._filterForSampling([run]).length) {
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
235
399
|
const headers = { ...this.headers, "Content-Type": "application/json" };
|
|
236
|
-
const extra = run.extra ?? {};
|
|
237
|
-
const metadata = extra.metadata;
|
|
238
|
-
const runtimeEnv = await getRuntimeEnvironment();
|
|
239
|
-
const envVars = getLangChainEnvVarsMetadata();
|
|
240
400
|
const session_name = run.project_name;
|
|
241
401
|
delete run.project_name;
|
|
242
|
-
const runCreate = {
|
|
402
|
+
const runCreate = this.prepareRunCreateOrUpdateInputs({
|
|
243
403
|
session_name,
|
|
244
404
|
...run,
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
: {}),
|
|
256
|
-
...metadata,
|
|
257
|
-
},
|
|
258
|
-
},
|
|
259
|
-
};
|
|
260
|
-
runCreate.inputs = this.processInputs(runCreate.inputs);
|
|
261
|
-
if (runCreate.outputs) {
|
|
262
|
-
runCreate.outputs = this.processOutputs(runCreate.outputs);
|
|
405
|
+
start_time: run.start_time ?? Date.now(),
|
|
406
|
+
});
|
|
407
|
+
if (this.autoBatchTracing &&
|
|
408
|
+
runCreate.trace_id !== undefined &&
|
|
409
|
+
runCreate.dotted_order !== undefined) {
|
|
410
|
+
this.appendRunCreateToAutoBatchQueue({
|
|
411
|
+
action: "create",
|
|
412
|
+
item: runCreate,
|
|
413
|
+
});
|
|
414
|
+
return;
|
|
263
415
|
}
|
|
264
|
-
|
|
416
|
+
const mergedRunCreateParams = await mergeRuntimeEnvIntoRunCreates([
|
|
417
|
+
runCreate,
|
|
418
|
+
]);
|
|
265
419
|
const response = await this.caller.call(fetch, `${this.apiUrl}/runs`, {
|
|
266
420
|
method: "POST",
|
|
267
421
|
headers,
|
|
268
|
-
body: JSON.stringify(
|
|
422
|
+
body: JSON.stringify(mergedRunCreateParams[0]),
|
|
269
423
|
signal: AbortSignal.timeout(this.timeout_ms),
|
|
270
424
|
});
|
|
271
425
|
await raiseForStatus(response, "create run");
|
|
272
426
|
}
|
|
427
|
+
/**
|
|
428
|
+
* Batch ingest/upsert multiple runs in the Langsmith system.
|
|
429
|
+
* @param runs
|
|
430
|
+
*/
|
|
431
|
+
async batchIngestRuns({ runCreates, runUpdates, }) {
|
|
432
|
+
if (runCreates === undefined && runUpdates === undefined) {
|
|
433
|
+
return;
|
|
434
|
+
}
|
|
435
|
+
let preparedCreateParams = runCreates?.map((create) => this.prepareRunCreateOrUpdateInputs(create)) ?? [];
|
|
436
|
+
let preparedUpdateParams = runUpdates?.map((update) => this.prepareRunCreateOrUpdateInputs(update)) ?? [];
|
|
437
|
+
if (preparedCreateParams.length > 0 && preparedUpdateParams.length > 0) {
|
|
438
|
+
const createById = preparedCreateParams.reduce((params, run) => {
|
|
439
|
+
if (!run.id) {
|
|
440
|
+
return params;
|
|
441
|
+
}
|
|
442
|
+
params[run.id] = run;
|
|
443
|
+
return params;
|
|
444
|
+
}, {});
|
|
445
|
+
const standaloneUpdates = [];
|
|
446
|
+
for (const updateParam of preparedUpdateParams) {
|
|
447
|
+
if (updateParam.id !== undefined && createById[updateParam.id]) {
|
|
448
|
+
createById[updateParam.id] = {
|
|
449
|
+
...createById[updateParam.id],
|
|
450
|
+
...updateParam,
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
else {
|
|
454
|
+
standaloneUpdates.push(updateParam);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
preparedCreateParams = Object.values(createById);
|
|
458
|
+
preparedUpdateParams = standaloneUpdates;
|
|
459
|
+
}
|
|
460
|
+
const body = {
|
|
461
|
+
post: this._filterForSampling(preparedCreateParams),
|
|
462
|
+
patch: this._filterForSampling(preparedUpdateParams, true),
|
|
463
|
+
};
|
|
464
|
+
if (!body.post.length && !body.patch.length) {
|
|
465
|
+
return;
|
|
466
|
+
}
|
|
467
|
+
preparedCreateParams = await mergeRuntimeEnvIntoRunCreates(preparedCreateParams);
|
|
468
|
+
const headers = {
|
|
469
|
+
...this.headers,
|
|
470
|
+
"Content-Type": "application/json",
|
|
471
|
+
Accept: "application/json",
|
|
472
|
+
};
|
|
473
|
+
const response = await this.caller.call(fetch, `${this.apiUrl}/runs/batch`, {
|
|
474
|
+
method: "POST",
|
|
475
|
+
headers,
|
|
476
|
+
body: JSON.stringify(body),
|
|
477
|
+
signal: AbortSignal.timeout(this.timeout_ms),
|
|
478
|
+
});
|
|
479
|
+
await raiseForStatus(response, "batch create run");
|
|
480
|
+
}
|
|
273
481
|
async updateRun(runId, run) {
|
|
274
482
|
assertUuid(runId);
|
|
275
483
|
if (run.inputs) {
|
|
@@ -278,6 +486,17 @@ export class Client {
|
|
|
278
486
|
if (run.outputs) {
|
|
279
487
|
run.outputs = this.processOutputs(run.outputs);
|
|
280
488
|
}
|
|
489
|
+
// TODO: Untangle types
|
|
490
|
+
const data = { ...run, id: runId };
|
|
491
|
+
if (!this._filterForSampling([data], true).length) {
|
|
492
|
+
return;
|
|
493
|
+
}
|
|
494
|
+
if (this.autoBatchTracing &&
|
|
495
|
+
data.trace_id !== undefined &&
|
|
496
|
+
data.dotted_order !== undefined) {
|
|
497
|
+
this.appendRunCreateToAutoBatchQueue({ action: "update", item: data });
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
281
500
|
const headers = { ...this.headers, "Content-Type": "application/json" };
|
|
282
501
|
const response = await this.caller.call(fetch, `${this.apiUrl}/runs/${runId}`, {
|
|
283
502
|
method: "PATCH",
|
|
@@ -546,7 +765,7 @@ export class Client {
|
|
|
546
765
|
}
|
|
547
766
|
return result;
|
|
548
767
|
}
|
|
549
|
-
async readProject({ projectId, projectName, }) {
|
|
768
|
+
async readProject({ projectId, projectName, includeStats, }) {
|
|
550
769
|
let path = "/sessions";
|
|
551
770
|
const params = new URLSearchParams();
|
|
552
771
|
if (projectId !== undefined && projectName !== undefined) {
|
|
@@ -562,6 +781,9 @@ export class Client {
|
|
|
562
781
|
else {
|
|
563
782
|
throw new Error("Must provide projectName or projectId");
|
|
564
783
|
}
|
|
784
|
+
if (includeStats !== undefined) {
|
|
785
|
+
params.append("include_stats", includeStats.toString());
|
|
786
|
+
}
|
|
565
787
|
const response = await this._get(path, params);
|
|
566
788
|
let result;
|
|
567
789
|
if (Array.isArray(response)) {
|
package/dist/index.cjs
CHANGED
|
@@ -6,4 +6,4 @@ Object.defineProperty(exports, "Client", { enumerable: true, get: function () {
|
|
|
6
6
|
var run_trees_js_1 = require("./run_trees.cjs");
|
|
7
7
|
Object.defineProperty(exports, "RunTree", { enumerable: true, get: function () { return run_trees_js_1.RunTree; } });
|
|
8
8
|
// Update using yarn bump-version
|
|
9
|
-
exports.__version__ = "0.0.
|
|
9
|
+
exports.__version__ = "0.0.68";
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
package/dist/schemas.d.ts
CHANGED
|
@@ -61,6 +61,21 @@ export interface BaseRun {
|
|
|
61
61
|
parent_run_id?: string;
|
|
62
62
|
/** Tags for further categorizing or annotating the run. */
|
|
63
63
|
tags?: string[];
|
|
64
|
+
/** Unique ID assigned to every run within this nested trace. **/
|
|
65
|
+
trace_id?: string;
|
|
66
|
+
/**
|
|
67
|
+
* The dotted order for the run.
|
|
68
|
+
*
|
|
69
|
+
* This is a string composed of {time}{run-uuid}.* so that a trace can be
|
|
70
|
+
* sorted in the order it was executed.
|
|
71
|
+
*
|
|
72
|
+
* Example:
|
|
73
|
+
* - Parent: 20230914T223155647Z1b64098b-4ab7-43f6-afee-992304f198d8
|
|
74
|
+
* - Children:
|
|
75
|
+
* - 20230914T223155647Z1b64098b-4ab7-43f6-afee-992304f198d8.20230914T223155649Z809ed3a2-0172-4f4d-8a02-a64e9b7a0f8a
|
|
76
|
+
* - 20230915T223155647Z1b64098b-4ab7-43f6-afee-992304f198d8.20230914T223155650Zc8d9f4c5-6c5a-4b2d-9b1c-3d9d7a7c5c7c
|
|
77
|
+
*/
|
|
78
|
+
dotted_order?: string;
|
|
64
79
|
}
|
|
65
80
|
/**
|
|
66
81
|
* Describes properties of a run when loaded from the database.
|
|
@@ -93,27 +108,14 @@ export interface Run extends BaseRun {
|
|
|
93
108
|
first_token_time?: number;
|
|
94
109
|
/** IDs of parent runs, if multiple exist. */
|
|
95
110
|
parent_run_ids?: string[];
|
|
96
|
-
/**Unique ID assigned to every run within this nested trace.**/
|
|
97
|
-
trace_id?: string;
|
|
98
|
-
/**
|
|
99
|
-
* The dotted order for the run.
|
|
100
|
-
*
|
|
101
|
-
* This is a string composed of {time}{run-uuid}.* so that a trace can be
|
|
102
|
-
* sorted in the order it was executed.
|
|
103
|
-
*
|
|
104
|
-
* Example:
|
|
105
|
-
* - Parent: 20230914T223155647Z1b64098b-4ab7-43f6-afee-992304f198d8
|
|
106
|
-
* - Children:
|
|
107
|
-
* - 20230914T223155647Z1b64098b-4ab7-43f6-afee-992304f198d8.20230914T223155649Z809ed3a2-0172-4f4d-8a02-a64e9b7a0f8a
|
|
108
|
-
* - 20230915T223155647Z1b64098b-4ab7-43f6-afee-992304f198d8.20230914T223155650Zc8d9f4c5-6c5a-4b2d-9b1c-3d9d7a7c5c7c
|
|
109
|
-
*/
|
|
110
|
-
dotted_order?: string;
|
|
111
111
|
}
|
|
112
112
|
export interface RunCreate extends BaseRun {
|
|
113
|
+
revision_id?: string;
|
|
113
114
|
child_runs?: this[];
|
|
114
115
|
session_name?: string;
|
|
115
116
|
}
|
|
116
117
|
export interface RunUpdate {
|
|
118
|
+
id?: string;
|
|
117
119
|
end_time?: number;
|
|
118
120
|
extra?: KVMap;
|
|
119
121
|
error?: string;
|
|
@@ -123,6 +125,21 @@ export interface RunUpdate {
|
|
|
123
125
|
reference_example_id?: string;
|
|
124
126
|
events?: KVMap[];
|
|
125
127
|
session_id?: string;
|
|
128
|
+
/** Unique ID assigned to every run within this nested trace. **/
|
|
129
|
+
trace_id?: string;
|
|
130
|
+
/**
|
|
131
|
+
* The dotted order for the run.
|
|
132
|
+
*
|
|
133
|
+
* This is a string composed of {time}{run-uuid}.* so that a trace can be
|
|
134
|
+
* sorted in the order it was executed.
|
|
135
|
+
*
|
|
136
|
+
* Example:
|
|
137
|
+
* - Parent: 20230914T223155647Z1b64098b-4ab7-43f6-afee-992304f198d8
|
|
138
|
+
* - Children:
|
|
139
|
+
* - 20230914T223155647Z1b64098b-4ab7-43f6-afee-992304f198d8.20230914T223155649Z809ed3a2-0172-4f4d-8a02-a64e9b7a0f8a
|
|
140
|
+
* - 20230915T223155647Z1b64098b-4ab7-43f6-afee-992304f198d8.20230914T223155650Zc8d9f4c5-6c5a-4b2d-9b1c-3d9d7a7c5c7c
|
|
141
|
+
*/
|
|
142
|
+
dotted_order?: string;
|
|
126
143
|
}
|
|
127
144
|
export interface ExampleCreate extends BaseExample {
|
|
128
145
|
id?: string;
|
package/package.json
CHANGED