langsmith 0.1.20 → 0.1.22

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.
Files changed (41) hide show
  1. package/README.md +1 -1
  2. package/dist/client.cjs +71 -31
  3. package/dist/client.d.ts +7 -3
  4. package/dist/client.js +48 -8
  5. package/dist/evaluation/_random_name.cjs +730 -0
  6. package/dist/evaluation/_random_name.d.ts +5 -0
  7. package/dist/evaluation/_random_name.js +726 -0
  8. package/dist/evaluation/_runner.cjs +709 -0
  9. package/dist/evaluation/_runner.d.ts +158 -0
  10. package/dist/evaluation/_runner.js +705 -0
  11. package/dist/evaluation/evaluator.cjs +86 -0
  12. package/dist/evaluation/evaluator.d.ts +31 -27
  13. package/dist/evaluation/evaluator.js +83 -1
  14. package/dist/evaluation/index.cjs +3 -1
  15. package/dist/evaluation/index.d.ts +1 -0
  16. package/dist/evaluation/index.js +1 -0
  17. package/dist/index.cjs +1 -1
  18. package/dist/index.d.ts +1 -1
  19. package/dist/index.js +1 -1
  20. package/dist/run_trees.cjs +4 -4
  21. package/dist/run_trees.d.ts +2 -1
  22. package/dist/run_trees.js +4 -4
  23. package/dist/schemas.d.ts +22 -1
  24. package/dist/traceable.cjs +237 -62
  25. package/dist/traceable.d.ts +7 -3
  26. package/dist/traceable.js +235 -61
  27. package/dist/utils/_git.cjs +72 -0
  28. package/dist/utils/_git.d.ts +14 -0
  29. package/dist/utils/_git.js +67 -0
  30. package/dist/utils/_uuid.cjs +33 -0
  31. package/dist/utils/_uuid.d.ts +1 -0
  32. package/dist/utils/_uuid.js +6 -0
  33. package/dist/utils/async_caller.cjs +17 -9
  34. package/dist/utils/async_caller.js +17 -9
  35. package/dist/utils/atee.cjs +24 -0
  36. package/dist/utils/atee.d.ts +1 -0
  37. package/dist/utils/atee.js +20 -0
  38. package/dist/wrappers/openai.cjs +53 -74
  39. package/dist/wrappers/openai.d.ts +10 -11
  40. package/dist/wrappers/openai.js +53 -74
  41. package/package.json +4 -4
@@ -1,18 +1,35 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isTraceableFunction = exports.getCurrentRunTree = exports.traceable = void 0;
3
+ exports.wrapFunctionAndEnsureTraceable = exports.isTraceableFunction = exports.getCurrentRunTree = exports.traceable = void 0;
4
4
  const async_hooks_1 = require("async_hooks");
5
5
  const run_trees_js_1 = require("./run_trees.cjs");
6
6
  const env_js_1 = require("./utils/env.cjs");
7
+ function isPromiseMethod(x) {
8
+ if (x === "then" || x === "catch" || x === "finally") {
9
+ return true;
10
+ }
11
+ return false;
12
+ }
7
13
  const asyncLocalStorage = new async_hooks_1.AsyncLocalStorage();
8
14
  const isAsyncIterable = (x) => x != null &&
9
15
  typeof x === "object" &&
10
16
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
11
17
  typeof x[Symbol.asyncIterator] === "function";
12
- const getTracingRunTree = (runTree) => {
13
- const tracingEnabled = (0, env_js_1.getEnvironmentVariable)("LANGSMITH_TRACING_V2") === "true" ||
14
- (0, env_js_1.getEnvironmentVariable)("LANGCHAIN_TRACING_V2") === "true";
15
- if (!tracingEnabled) {
18
+ const tracingIsEnabled = (tracingEnabled) => {
19
+ if (tracingEnabled !== undefined) {
20
+ return tracingEnabled;
21
+ }
22
+ const envVars = [
23
+ "LANGSMITH_TRACING_V2",
24
+ "LANGCHAIN_TRACING_V2",
25
+ "LANGSMITH_TRACING",
26
+ "LANGCHAIN_TRACING",
27
+ ];
28
+ return Boolean(envVars.find((envVar) => (0, env_js_1.getEnvironmentVariable)(envVar) === "true"));
29
+ };
30
+ const getTracingRunTree = (runTree, tracingEnabled) => {
31
+ const tracingEnabled_ = tracingIsEnabled(tracingEnabled);
32
+ if (!tracingEnabled_) {
16
33
  return undefined;
17
34
  }
18
35
  return runTree;
@@ -33,14 +50,55 @@ const getTracingRunTree = (runTree) => {
33
50
  */
34
51
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
35
52
  function traceable(wrappedFunc, config) {
36
- const { aggregator, ...runTreeConfig } = config ?? {};
37
- const traceableFunc = async (...args) => {
53
+ const { aggregator, argsConfigPath, tracingEnabled, ...runTreeConfig } = config ?? {};
54
+ const traceableFunc = (...args) => {
38
55
  let currentRunTree;
39
56
  let rawInputs;
40
- const ensuredConfig = {
41
- name: wrappedFunc.name || "<lambda>",
42
- ...runTreeConfig,
43
- };
57
+ let ensuredConfig;
58
+ try {
59
+ let runtimeConfig;
60
+ if (argsConfigPath) {
61
+ const [index, path] = argsConfigPath;
62
+ if (index === args.length - 1 && !path) {
63
+ runtimeConfig = args.pop();
64
+ }
65
+ else if (index <= args.length &&
66
+ typeof args[index] === "object" &&
67
+ args[index] !== null) {
68
+ if (path) {
69
+ const { [path]: extracted, ...rest } = args[index];
70
+ runtimeConfig = extracted;
71
+ args[index] = rest;
72
+ }
73
+ else {
74
+ runtimeConfig = args[index];
75
+ args.splice(index, 1);
76
+ }
77
+ }
78
+ }
79
+ ensuredConfig = {
80
+ name: wrappedFunc.name || "<lambda>",
81
+ ...runTreeConfig,
82
+ ...runtimeConfig,
83
+ tags: [
84
+ ...new Set([
85
+ ...(runTreeConfig?.tags ?? []),
86
+ ...(runtimeConfig?.tags ?? []),
87
+ ]),
88
+ ],
89
+ metadata: {
90
+ ...runTreeConfig?.metadata,
91
+ ...runtimeConfig?.metadata,
92
+ },
93
+ };
94
+ }
95
+ catch (err) {
96
+ console.warn(`Failed to extract runtime config from args for ${runTreeConfig?.name ?? wrappedFunc.name}`, err);
97
+ ensuredConfig = {
98
+ name: wrappedFunc.name || "<lambda>",
99
+ ...runTreeConfig,
100
+ };
101
+ }
44
102
  const previousRunTree = asyncLocalStorage.getStore();
45
103
  if ((0, run_trees_js_1.isRunTree)(args[0])) {
46
104
  currentRunTree = args[0];
@@ -51,14 +109,14 @@ function traceable(wrappedFunc, config) {
51
109
  rawInputs = args.slice(1);
52
110
  }
53
111
  else if (previousRunTree !== undefined) {
54
- currentRunTree = await previousRunTree.createChild(ensuredConfig);
112
+ currentRunTree = previousRunTree.createChild(ensuredConfig);
55
113
  rawInputs = args;
56
114
  }
57
115
  else {
58
116
  currentRunTree = new run_trees_js_1.RunTree(ensuredConfig);
59
117
  rawInputs = args;
60
118
  }
61
- currentRunTree = getTracingRunTree(currentRunTree);
119
+ currentRunTree = getTracingRunTree(currentRunTree, tracingEnabled);
62
120
  let inputs;
63
121
  const firstInput = rawInputs[0];
64
122
  if (firstInput == null) {
@@ -76,74 +134,181 @@ function traceable(wrappedFunc, config) {
76
134
  if (currentRunTree) {
77
135
  currentRunTree.inputs = inputs;
78
136
  }
79
- const initialOutputs = currentRunTree?.outputs;
80
- const initialError = currentRunTree?.error;
81
- await currentRunTree?.postRun();
82
- return new Promise((resolve, reject) => {
83
- void asyncLocalStorage.run(currentRunTree, async () => {
84
- try {
85
- const rawOutput = await wrappedFunc(...rawInputs);
137
+ return asyncLocalStorage.run(currentRunTree, () => {
138
+ const postRunPromise = currentRunTree?.postRun();
139
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
140
+ let returnValue;
141
+ try {
142
+ returnValue = wrappedFunc(...rawInputs);
143
+ }
144
+ catch (err) {
145
+ returnValue = Promise.reject(err);
146
+ }
147
+ if (isAsyncIterable(returnValue)) {
148
+ // eslint-disable-next-line no-inner-declarations
149
+ async function* wrapOutputForTracing() {
150
+ let finished = false;
151
+ const chunks = [];
152
+ try {
153
+ for await (const chunk of returnValue) {
154
+ chunks.push(chunk);
155
+ yield chunk;
156
+ }
157
+ finished = true;
158
+ }
159
+ catch (e) {
160
+ await currentRunTree?.end(undefined, String(e));
161
+ throw e;
162
+ }
163
+ finally {
164
+ if (!finished) {
165
+ await currentRunTree?.end(undefined, "Cancelled");
166
+ }
167
+ let finalOutputs;
168
+ if (aggregator !== undefined) {
169
+ try {
170
+ finalOutputs = await aggregator(chunks);
171
+ }
172
+ catch (e) {
173
+ console.error(`[ERROR]: LangSmith aggregation failed: `, e);
174
+ finalOutputs = chunks;
175
+ }
176
+ }
177
+ else {
178
+ finalOutputs = chunks;
179
+ }
180
+ if (typeof finalOutputs === "object" &&
181
+ !Array.isArray(finalOutputs)) {
182
+ await currentRunTree?.end(finalOutputs);
183
+ }
184
+ else {
185
+ await currentRunTree?.end({ outputs: finalOutputs });
186
+ }
187
+ const onEnd = config?.on_end;
188
+ if (onEnd) {
189
+ if (!currentRunTree) {
190
+ console.warn("Can not call 'on_end' if currentRunTree is undefined");
191
+ }
192
+ else {
193
+ onEnd(currentRunTree);
194
+ }
195
+ }
196
+ await postRunPromise;
197
+ await currentRunTree?.patchRun();
198
+ }
199
+ }
200
+ return wrapOutputForTracing();
201
+ }
202
+ const tracedPromise = new Promise((resolve, reject) => {
203
+ Promise.resolve(returnValue)
204
+ .then(
205
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
206
+ async (rawOutput) => {
86
207
  if (isAsyncIterable(rawOutput)) {
87
208
  // eslint-disable-next-line no-inner-declarations
88
209
  async function* wrapOutputForTracing() {
210
+ let finished = false;
89
211
  const chunks = [];
90
- // TypeScript thinks this is unsafe
91
- for await (const chunk of rawOutput) {
92
- chunks.push(chunk);
93
- yield chunk;
212
+ try {
213
+ // TypeScript thinks this is unsafe
214
+ for await (const chunk of rawOutput) {
215
+ chunks.push(chunk);
216
+ yield chunk;
217
+ }
218
+ finished = true;
219
+ }
220
+ catch (e) {
221
+ await currentRunTree?.end(undefined, String(e));
222
+ throw e;
94
223
  }
95
- let finalOutputs;
96
- if (aggregator !== undefined) {
97
- try {
98
- finalOutputs = await aggregator(chunks);
224
+ finally {
225
+ if (!finished) {
226
+ await currentRunTree?.end(undefined, "Cancelled");
99
227
  }
100
- catch (e) {
101
- console.error(`[ERROR]: LangSmith aggregation failed: `, e);
228
+ let finalOutputs;
229
+ if (aggregator !== undefined) {
230
+ try {
231
+ finalOutputs = await aggregator(chunks);
232
+ }
233
+ catch (e) {
234
+ console.error(`[ERROR]: LangSmith aggregation failed: `, e);
235
+ finalOutputs = chunks;
236
+ }
237
+ }
238
+ else {
102
239
  finalOutputs = chunks;
103
240
  }
241
+ if (typeof finalOutputs === "object" &&
242
+ !Array.isArray(finalOutputs)) {
243
+ await currentRunTree?.end(finalOutputs);
244
+ }
245
+ else {
246
+ await currentRunTree?.end({ outputs: finalOutputs });
247
+ }
248
+ const onEnd = config?.on_end;
249
+ if (onEnd) {
250
+ if (!currentRunTree) {
251
+ console.warn("Can not call 'on_end' if currentRunTree is undefined");
252
+ }
253
+ else {
254
+ onEnd(currentRunTree);
255
+ }
256
+ }
257
+ await postRunPromise;
258
+ await currentRunTree?.patchRun();
104
259
  }
105
- else {
106
- finalOutputs = chunks;
107
- }
108
- if (typeof finalOutputs === "object" &&
109
- !Array.isArray(finalOutputs)) {
110
- await currentRunTree?.end(finalOutputs);
111
- }
112
- else {
113
- await currentRunTree?.end({ outputs: finalOutputs });
114
- }
115
- await currentRunTree?.patchRun();
116
260
  }
117
261
  return resolve(wrapOutputForTracing());
118
262
  }
119
263
  else {
120
- const outputs = isKVMap(rawOutput)
121
- ? rawOutput
122
- : { outputs: rawOutput };
123
- if (initialOutputs === currentRunTree?.outputs) {
124
- await currentRunTree?.end(outputs);
125
- }
126
- else {
127
- if (currentRunTree !== undefined) {
128
- currentRunTree.end_time = Date.now();
264
+ try {
265
+ await currentRunTree?.end(isKVMap(rawOutput) ? rawOutput : { outputs: rawOutput });
266
+ const onEnd = config?.on_end;
267
+ if (onEnd) {
268
+ if (!currentRunTree) {
269
+ console.warn("Can not call 'on_end' if currentRunTree is undefined");
270
+ }
271
+ else {
272
+ onEnd(currentRunTree);
273
+ }
129
274
  }
275
+ await postRunPromise;
276
+ await currentRunTree?.patchRun();
277
+ }
278
+ finally {
279
+ // eslint-disable-next-line no-unsafe-finally
280
+ return rawOutput;
130
281
  }
131
- await currentRunTree?.patchRun();
132
- return resolve(rawOutput);
133
- }
134
- }
135
- catch (error) {
136
- if (initialError === currentRunTree?.error) {
137
- await currentRunTree?.end(initialOutputs, String(error));
138
282
  }
139
- else {
140
- if (currentRunTree !== undefined) {
141
- currentRunTree.end_time = Date.now();
283
+ },
284
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
285
+ async (error) => {
286
+ await currentRunTree?.end(undefined, String(error));
287
+ const onEnd = config?.on_end;
288
+ if (onEnd) {
289
+ if (!currentRunTree) {
290
+ console.warn("Can not call 'on_end' if currentRunTree is undefined");
291
+ }
292
+ else {
293
+ onEnd(currentRunTree);
142
294
  }
143
295
  }
296
+ await postRunPromise;
144
297
  await currentRunTree?.patchRun();
145
- reject(error);
146
- }
298
+ throw error;
299
+ })
300
+ .then(resolve, reject);
301
+ });
302
+ if (typeof returnValue !== "object" || returnValue === null) {
303
+ return tracedPromise;
304
+ }
305
+ return new Proxy(returnValue, {
306
+ get(target, prop, receiver) {
307
+ if (isPromiseMethod(prop)) {
308
+ return tracedPromise[prop].bind(tracedPromise);
309
+ }
310
+ return Reflect.get(target, prop, receiver);
311
+ },
147
312
  });
148
313
  });
149
314
  };
@@ -184,3 +349,13 @@ function isKVMap(x) {
184
349
  // eslint-disable-next-line no-instanceof/no-instanceof
185
350
  !(x instanceof Date));
186
351
  }
352
+ function wrapFunctionAndEnsureTraceable(target, options, name = "target") {
353
+ if (typeof target === "function") {
354
+ return traceable(target, {
355
+ ...options,
356
+ name,
357
+ });
358
+ }
359
+ throw new Error("Target must be runnable function");
360
+ }
361
+ exports.wrapFunctionAndEnsureTraceable = wrapFunctionAndEnsureTraceable;
@@ -1,12 +1,13 @@
1
1
  import { RunTree, RunTreeConfig, RunnableConfigLike } from "./run_trees.js";
2
2
  export type RunTreeLike = RunTree;
3
+ type SmartPromise<T> = T extends AsyncGenerator ? T : T extends Promise<unknown> ? T : Promise<T>;
3
4
  type WrapArgReturnPair<Pair> = Pair extends [
4
5
  infer Args extends any[],
5
6
  infer Return
6
7
  ] ? {
7
- (...args: Args): Promise<Return>;
8
- (...args: [runTree: RunTreeLike, ...rest: Args]): Promise<Return>;
9
- (...args: [config: RunnableConfigLike, ...rest: Args]): Promise<Return>;
8
+ (...args: Args): SmartPromise<Return>;
9
+ (...args: [runTree: RunTreeLike, ...rest: Args]): SmartPromise<Return>;
10
+ (...args: [config: RunnableConfigLike, ...rest: Args]): SmartPromise<Return>;
10
11
  } : never;
11
12
  type UnionToIntersection<U> = (U extends any ? (x: U) => void : never) extends (x: infer I) => void ? I : never;
12
13
  export type TraceableFunction<Func extends (...args: any[]) => any> = Func extends {
@@ -46,6 +47,8 @@ export type TraceableFunction<Func extends (...args: any[]) => any> = Func exten
46
47
  */
47
48
  export declare function traceable<Func extends (...args: any[]) => any>(wrappedFunc: Func, config?: Partial<RunTreeConfig> & {
48
49
  aggregator?: (args: any[]) => any;
50
+ argsConfigPath?: [number] | [number, string];
51
+ tracingEnabled?: boolean;
49
52
  }): TraceableFunction<Func>;
50
53
  /**
51
54
  * Return the current run tree from within a traceable-wrapped function.
@@ -55,4 +58,5 @@ export declare function traceable<Func extends (...args: any[]) => any>(wrappedF
55
58
  */
56
59
  export declare function getCurrentRunTree(): RunTree;
57
60
  export declare function isTraceableFunction(x: unknown): x is TraceableFunction<any>;
61
+ export declare function wrapFunctionAndEnsureTraceable<Func extends (...args: any[]) => any>(target: Func, options: Partial<RunTreeConfig>, name?: string): TraceableFunction<Func>;
58
62
  export {};