langsmith 0.1.38 → 0.1.39

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
@@ -933,6 +933,43 @@ class Client {
933
933
  }
934
934
  }
935
935
  }
936
+ async getRunStats({ id, trace, parentRun, runType, projectNames, projectIds, referenceExampleIds, startTime, endTime, error, query, filter, traceFilter, treeFilter, isRoot, dataSourceType, }) {
937
+ let projectIds_ = projectIds || [];
938
+ if (projectNames) {
939
+ projectIds_ = [
940
+ ...(projectIds || []),
941
+ ...(await Promise.all(projectNames.map((name) => this.readProject({ projectName: name }).then((project) => project.id)))),
942
+ ];
943
+ }
944
+ const payload = {
945
+ id,
946
+ trace,
947
+ parent_run: parentRun,
948
+ run_type: runType,
949
+ session: projectIds_,
950
+ reference_example: referenceExampleIds,
951
+ start_time: startTime,
952
+ end_time: endTime,
953
+ error,
954
+ query,
955
+ filter,
956
+ trace_filter: traceFilter,
957
+ tree_filter: treeFilter,
958
+ is_root: isRoot,
959
+ data_source_type: dataSourceType,
960
+ };
961
+ // Remove undefined values from the payload
962
+ const filteredPayload = Object.fromEntries(Object.entries(payload).filter(([_, value]) => value !== undefined));
963
+ const response = await this.caller.call(fetch, `${this.apiUrl}/runs/stats`, {
964
+ method: "POST",
965
+ headers: this.headers,
966
+ body: JSON.stringify(filteredPayload),
967
+ signal: AbortSignal.timeout(this.timeout_ms),
968
+ ...this.fetchOptions,
969
+ });
970
+ const result = await response.json();
971
+ return result;
972
+ }
936
973
  async shareRun(runId, { shareId } = {}) {
937
974
  const data = {
938
975
  run_id: runId,
package/dist/client.d.ts CHANGED
@@ -300,6 +300,24 @@ export declare class Client {
300
300
  * });
301
301
  */
302
302
  listRuns(props: ListRunsParams): AsyncIterable<Run>;
303
+ getRunStats({ id, trace, parentRun, runType, projectNames, projectIds, referenceExampleIds, startTime, endTime, error, query, filter, traceFilter, treeFilter, isRoot, dataSourceType, }: {
304
+ id?: string[];
305
+ trace?: string;
306
+ parentRun?: string;
307
+ runType?: string;
308
+ projectNames?: string[];
309
+ projectIds?: string[];
310
+ referenceExampleIds?: string[];
311
+ startTime?: string;
312
+ endTime?: string;
313
+ error?: boolean;
314
+ query?: string;
315
+ filter?: string;
316
+ traceFilter?: string;
317
+ treeFilter?: string;
318
+ isRoot?: boolean;
319
+ dataSourceType?: string;
320
+ }): Promise<any>;
303
321
  shareRun(runId: string, { shareId }?: {
304
322
  shareId?: string;
305
323
  }): Promise<string>;
package/dist/client.js CHANGED
@@ -906,6 +906,43 @@ export class Client {
906
906
  }
907
907
  }
908
908
  }
909
+ async getRunStats({ id, trace, parentRun, runType, projectNames, projectIds, referenceExampleIds, startTime, endTime, error, query, filter, traceFilter, treeFilter, isRoot, dataSourceType, }) {
910
+ let projectIds_ = projectIds || [];
911
+ if (projectNames) {
912
+ projectIds_ = [
913
+ ...(projectIds || []),
914
+ ...(await Promise.all(projectNames.map((name) => this.readProject({ projectName: name }).then((project) => project.id)))),
915
+ ];
916
+ }
917
+ const payload = {
918
+ id,
919
+ trace,
920
+ parent_run: parentRun,
921
+ run_type: runType,
922
+ session: projectIds_,
923
+ reference_example: referenceExampleIds,
924
+ start_time: startTime,
925
+ end_time: endTime,
926
+ error,
927
+ query,
928
+ filter,
929
+ trace_filter: traceFilter,
930
+ tree_filter: treeFilter,
931
+ is_root: isRoot,
932
+ data_source_type: dataSourceType,
933
+ };
934
+ // Remove undefined values from the payload
935
+ const filteredPayload = Object.fromEntries(Object.entries(payload).filter(([_, value]) => value !== undefined));
936
+ const response = await this.caller.call(fetch, `${this.apiUrl}/runs/stats`, {
937
+ method: "POST",
938
+ headers: this.headers,
939
+ body: JSON.stringify(filteredPayload),
940
+ signal: AbortSignal.timeout(this.timeout_ms),
941
+ ...this.fetchOptions,
942
+ });
943
+ const result = await response.json();
944
+ return result;
945
+ }
909
946
  async shareRun(runId, { shareId } = {}) {
910
947
  const data = {
911
948
  run_id: runId,
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.1.38";
9
+ exports.__version__ = "0.1.39";
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  export { Client } from "./client.js";
2
2
  export type { Dataset, Example, TracerSession, Run, Feedback, RetrieverOutput, } from "./schemas.js";
3
3
  export { RunTree, type RunTreeConfig } from "./run_trees.js";
4
- export declare const __version__ = "0.1.38";
4
+ export declare const __version__ = "0.1.39";
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
1
  export { Client } from "./client.js";
2
2
  export { RunTree } from "./run_trees.js";
3
3
  // Update using yarn bump-version
4
- export const __version__ = "0.1.38";
4
+ export const __version__ = "0.1.39";
@@ -55,12 +55,20 @@ async function getLangchainCallbacks(currentRunTree) {
55
55
  Object.assign(callbacks, { _parentRunId: runTree.id });
56
56
  }
57
57
  if (langChainTracer != null) {
58
- Object.assign(langChainTracer, {
59
- runMap,
60
- client: runTree.client,
61
- projectName: runTree.project_name || langChainTracer.projectName,
62
- exampleId: runTree.reference_example_id || langChainTracer.exampleId,
63
- });
58
+ if ("updateFromRunTree" in langChainTracer &&
59
+ typeof langChainTracer === "function") {
60
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
61
+ // @ts-ignore @langchain/core can use a different version of LangSmith
62
+ langChainTracer.updateFromRunTree(runTree);
63
+ }
64
+ else {
65
+ Object.assign(langChainTracer, {
66
+ runMap,
67
+ client: runTree.client,
68
+ projectName: runTree.project_name || langChainTracer.projectName,
69
+ exampleId: runTree.reference_example_id || langChainTracer.exampleId,
70
+ });
71
+ }
64
72
  }
65
73
  return callbacks;
66
74
  }
package/dist/langchain.js CHANGED
@@ -52,12 +52,20 @@ export async function getLangchainCallbacks(currentRunTree) {
52
52
  Object.assign(callbacks, { _parentRunId: runTree.id });
53
53
  }
54
54
  if (langChainTracer != null) {
55
- Object.assign(langChainTracer, {
56
- runMap,
57
- client: runTree.client,
58
- projectName: runTree.project_name || langChainTracer.projectName,
59
- exampleId: runTree.reference_example_id || langChainTracer.exampleId,
60
- });
55
+ if ("updateFromRunTree" in langChainTracer &&
56
+ typeof langChainTracer === "function") {
57
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
58
+ // @ts-ignore @langchain/core can use a different version of LangSmith
59
+ langChainTracer.updateFromRunTree(runTree);
60
+ }
61
+ else {
62
+ Object.assign(langChainTracer, {
63
+ runMap,
64
+ client: runTree.client,
65
+ projectName: runTree.project_name || langChainTracer.projectName,
66
+ exampleId: runTree.reference_example_id || langChainTracer.exampleId,
67
+ });
68
+ }
61
69
  }
62
70
  return callbacks;
63
71
  }
@@ -278,6 +278,26 @@ class RunTree {
278
278
  execution_order: child_execution_order,
279
279
  child_execution_order: child_execution_order,
280
280
  });
281
+ const LC_CHILD = Symbol.for("lc:child_config");
282
+ const presentConfig = config.extra?.[LC_CHILD] ??
283
+ this.extra[LC_CHILD];
284
+ // tracing for LangChain is defined by the _parentRunId and runMap of the tracer
285
+ if (isRunnableConfigLike(presentConfig)) {
286
+ const newConfig = { ...presentConfig };
287
+ const callbacks = isCallbackManagerLike(newConfig.callbacks)
288
+ ? newConfig.callbacks.copy?.()
289
+ : undefined;
290
+ if (callbacks) {
291
+ // update the parent run id
292
+ Object.assign(callbacks, { _parentRunId: child.id });
293
+ // only populate if we're in a newer LC.JS version
294
+ callbacks.handlers
295
+ ?.find(isLangChainTracerLike)
296
+ ?.updateFromRunTree?.(child);
297
+ newConfig.callbacks = callbacks;
298
+ }
299
+ child.extra[LC_CHILD] = newConfig;
300
+ }
281
301
  // propagate child_execution_order upwards
282
302
  const visited = new Set();
283
303
  let current = this;
@@ -463,12 +483,19 @@ function isRunTree(x) {
463
483
  typeof x.postRun === "function");
464
484
  }
465
485
  exports.isRunTree = isRunTree;
486
+ function isLangChainTracerLike(x) {
487
+ return (typeof x === "object" &&
488
+ x != null &&
489
+ typeof x.name === "string" &&
490
+ x.name === "langchain_tracer");
491
+ }
466
492
  function containsLangChainTracerLike(x) {
467
- return (Array.isArray(x) &&
468
- x.some((callback) => {
469
- return (typeof callback.name === "string" &&
470
- callback.name === "langchain_tracer");
471
- }));
493
+ return (Array.isArray(x) && x.some((callback) => isLangChainTracerLike(callback)));
494
+ }
495
+ function isCallbackManagerLike(x) {
496
+ return (typeof x === "object" &&
497
+ x != null &&
498
+ Array.isArray(x.handlers));
472
499
  }
473
500
  function isRunnableConfigLike(x) {
474
501
  // Check that it's an object with a callbacks arg
package/dist/run_trees.js CHANGED
@@ -251,6 +251,26 @@ export class RunTree {
251
251
  execution_order: child_execution_order,
252
252
  child_execution_order: child_execution_order,
253
253
  });
254
+ const LC_CHILD = Symbol.for("lc:child_config");
255
+ const presentConfig = config.extra?.[LC_CHILD] ??
256
+ this.extra[LC_CHILD];
257
+ // tracing for LangChain is defined by the _parentRunId and runMap of the tracer
258
+ if (isRunnableConfigLike(presentConfig)) {
259
+ const newConfig = { ...presentConfig };
260
+ const callbacks = isCallbackManagerLike(newConfig.callbacks)
261
+ ? newConfig.callbacks.copy?.()
262
+ : undefined;
263
+ if (callbacks) {
264
+ // update the parent run id
265
+ Object.assign(callbacks, { _parentRunId: child.id });
266
+ // only populate if we're in a newer LC.JS version
267
+ callbacks.handlers
268
+ ?.find(isLangChainTracerLike)
269
+ ?.updateFromRunTree?.(child);
270
+ newConfig.callbacks = callbacks;
271
+ }
272
+ child.extra[LC_CHILD] = newConfig;
273
+ }
254
274
  // propagate child_execution_order upwards
255
275
  const visited = new Set();
256
276
  let current = this;
@@ -434,12 +454,19 @@ export function isRunTree(x) {
434
454
  typeof x.createChild === "function" &&
435
455
  typeof x.postRun === "function");
436
456
  }
457
+ function isLangChainTracerLike(x) {
458
+ return (typeof x === "object" &&
459
+ x != null &&
460
+ typeof x.name === "string" &&
461
+ x.name === "langchain_tracer");
462
+ }
437
463
  function containsLangChainTracerLike(x) {
438
- return (Array.isArray(x) &&
439
- x.some((callback) => {
440
- return (typeof callback.name === "string" &&
441
- callback.name === "langchain_tracer");
442
- }));
464
+ return (Array.isArray(x) && x.some((callback) => isLangChainTracerLike(callback)));
465
+ }
466
+ function isCallbackManagerLike(x) {
467
+ return (typeof x === "object" &&
468
+ x != null &&
469
+ Array.isArray(x.handlers));
443
470
  }
444
471
  export function isRunnableConfigLike(x) {
445
472
  // Check that it's an object with a callbacks arg
@@ -9,28 +9,18 @@ class MockAsyncLocalStorage {
9
9
  return callback();
10
10
  }
11
11
  }
12
+ const TRACING_ALS_KEY = Symbol.for("ls:tracing_async_local_storage");
13
+ const mockAsyncLocalStorage = new MockAsyncLocalStorage();
12
14
  class AsyncLocalStorageProvider {
13
- constructor() {
14
- Object.defineProperty(this, "asyncLocalStorage", {
15
- enumerable: true,
16
- configurable: true,
17
- writable: true,
18
- value: new MockAsyncLocalStorage()
19
- });
20
- Object.defineProperty(this, "hasBeenInitialized", {
21
- enumerable: true,
22
- configurable: true,
23
- writable: true,
24
- value: false
25
- });
26
- }
27
15
  getInstance() {
28
- return this.asyncLocalStorage;
16
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
17
+ return globalThis[TRACING_ALS_KEY] ?? mockAsyncLocalStorage;
29
18
  }
30
19
  initializeGlobalInstance(instance) {
31
- if (!this.hasBeenInitialized) {
32
- this.hasBeenInitialized = true;
33
- this.asyncLocalStorage = instance;
20
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
21
+ if (globalThis[TRACING_ALS_KEY] === undefined) {
22
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
23
+ globalThis[TRACING_ALS_KEY] = instance;
34
24
  }
35
25
  }
36
26
  }
@@ -5,8 +5,6 @@ interface AsyncLocalStorageInterface {
5
5
  run: (context: RunTree | undefined, fn: () => void) => void;
6
6
  }
7
7
  declare class AsyncLocalStorageProvider {
8
- private asyncLocalStorage;
9
- private hasBeenInitialized;
10
8
  getInstance(): AsyncLocalStorageInterface;
11
9
  initializeGlobalInstance(instance: AsyncLocalStorageInterface): void;
12
10
  }
@@ -6,28 +6,18 @@ class MockAsyncLocalStorage {
6
6
  return callback();
7
7
  }
8
8
  }
9
+ const TRACING_ALS_KEY = Symbol.for("ls:tracing_async_local_storage");
10
+ const mockAsyncLocalStorage = new MockAsyncLocalStorage();
9
11
  class AsyncLocalStorageProvider {
10
- constructor() {
11
- Object.defineProperty(this, "asyncLocalStorage", {
12
- enumerable: true,
13
- configurable: true,
14
- writable: true,
15
- value: new MockAsyncLocalStorage()
16
- });
17
- Object.defineProperty(this, "hasBeenInitialized", {
18
- enumerable: true,
19
- configurable: true,
20
- writable: true,
21
- value: false
22
- });
23
- }
24
12
  getInstance() {
25
- return this.asyncLocalStorage;
13
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
14
+ return globalThis[TRACING_ALS_KEY] ?? mockAsyncLocalStorage;
26
15
  }
27
16
  initializeGlobalInstance(instance) {
28
- if (!this.hasBeenInitialized) {
29
- this.hasBeenInitialized = true;
30
- this.asyncLocalStorage = instance;
17
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
18
+ if (globalThis[TRACING_ALS_KEY] === undefined) {
19
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
20
+ globalThis[TRACING_ALS_KEY] = instance;
31
21
  }
32
22
  }
33
23
  }
@@ -13,7 +13,7 @@ type WrapArgReturnPair<Pair> = Pair extends [
13
13
  (config: RunnableConfigLike, ...args: Args): SmartPromise<Return>;
14
14
  } : never;
15
15
  type UnionToIntersection<U> = (U extends any ? (x: U) => void : never) extends (x: infer I) => void ? I : never;
16
- export type TraceableFunction<Func extends (...args: any[]) => any> = Func extends {
16
+ export type TraceableFunction<Func extends (...args: any[]) => any> = (Func extends {
17
17
  (...args: infer A1): infer R1;
18
18
  (...args: infer A2): infer R2;
19
19
  (...args: infer A3): infer R3;
@@ -33,6 +33,8 @@ export type TraceableFunction<Func extends (...args: any[]) => any> = Func exten
33
33
  (...args: infer A2): infer R2;
34
34
  } ? UnionToIntersection<WrapArgReturnPair<[A1, R1] | [A2, R2]>> : Func extends {
35
35
  (...args: infer A1): infer R1;
36
- } ? UnionToIntersection<WrapArgReturnPair<[A1, R1]>> : never;
36
+ } ? UnionToIntersection<WrapArgReturnPair<[A1, R1]>> : never) & {
37
+ [K in keyof Func]: Func[K];
38
+ };
37
39
  export type RunTreeLike = RunTree;
38
40
  export {};
@@ -294,11 +294,10 @@ function traceable(wrappedFunc, config) {
294
294
  }
295
295
  return chunks;
296
296
  }
297
- async function* wrapAsyncGeneratorForTracing(iterable, snapshot) {
297
+ async function* wrapAsyncIteratorForTracing(iterator, snapshot) {
298
298
  let finished = false;
299
299
  const chunks = [];
300
300
  try {
301
- const iterator = iterable[Symbol.asyncIterator]();
302
301
  while (true) {
303
302
  const { value, done } = await (snapshot
304
303
  ? snapshot(() => iterator.next())
@@ -322,6 +321,12 @@ function traceable(wrappedFunc, config) {
322
321
  await handleEnd();
323
322
  }
324
323
  }
324
+ function wrapAsyncGeneratorForTracing(iterable, snapshot) {
325
+ const iterator = iterable[Symbol.asyncIterator]();
326
+ const wrappedIterator = wrapAsyncIteratorForTracing(iterator, snapshot);
327
+ iterable[Symbol.asyncIterator] = () => wrappedIterator;
328
+ return iterable;
329
+ }
325
330
  async function handleEnd() {
326
331
  const onEnd = config?.on_end;
327
332
  if (onEnd) {
package/dist/traceable.js CHANGED
@@ -291,11 +291,10 @@ export function traceable(wrappedFunc, config) {
291
291
  }
292
292
  return chunks;
293
293
  }
294
- async function* wrapAsyncGeneratorForTracing(iterable, snapshot) {
294
+ async function* wrapAsyncIteratorForTracing(iterator, snapshot) {
295
295
  let finished = false;
296
296
  const chunks = [];
297
297
  try {
298
- const iterator = iterable[Symbol.asyncIterator]();
299
298
  while (true) {
300
299
  const { value, done } = await (snapshot
301
300
  ? snapshot(() => iterator.next())
@@ -319,6 +318,12 @@ export function traceable(wrappedFunc, config) {
319
318
  await handleEnd();
320
319
  }
321
320
  }
321
+ function wrapAsyncGeneratorForTracing(iterable, snapshot) {
322
+ const iterator = iterable[Symbol.asyncIterator]();
323
+ const wrappedIterator = wrapAsyncIteratorForTracing(iterator, snapshot);
324
+ iterable[Symbol.asyncIterator] = () => wrappedIterator;
325
+ return iterable;
326
+ }
322
327
  async function handleEnd() {
323
328
  const onEnd = config?.on_end;
324
329
  if (onEnd) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "langsmith",
3
- "version": "0.1.38",
3
+ "version": "0.1.39",
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": [