langsmith 0.2.4-dev.0 → 0.2.5

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
@@ -259,17 +259,11 @@ class Client {
259
259
  writable: true,
260
260
  value: void 0
261
261
  });
262
- Object.defineProperty(this, "autoBatchInitialDelayMs", {
263
- enumerable: true,
264
- configurable: true,
265
- writable: true,
266
- value: 250
267
- });
268
262
  Object.defineProperty(this, "autoBatchAggregationDelayMs", {
269
263
  enumerable: true,
270
264
  configurable: true,
271
265
  writable: true,
272
- value: 50
266
+ value: 250
273
267
  });
274
268
  Object.defineProperty(this, "batchSizeBytesLimit", {
275
269
  enumerable: true,
@@ -576,7 +570,6 @@ class Client {
576
570
  }
577
571
  }
578
572
  async processRunOperation(item) {
579
- const oldTimeout = this.autoBatchTimeout;
580
573
  clearTimeout(this.autoBatchTimeout);
581
574
  this.autoBatchTimeout = undefined;
582
575
  if (item.action === "create") {
@@ -591,9 +584,7 @@ class Client {
591
584
  this.autoBatchTimeout = setTimeout(() => {
592
585
  this.autoBatchTimeout = undefined;
593
586
  this.drainAutoBatchQueue(sizeLimitBytes);
594
- }, oldTimeout
595
- ? this.autoBatchAggregationDelayMs
596
- : this.autoBatchInitialDelayMs);
587
+ }, this.autoBatchAggregationDelayMs);
597
588
  }
598
589
  return itemPromise;
599
590
  }
@@ -824,7 +815,7 @@ class Client {
824
815
  ]) {
825
816
  for (const originalPayload of payloads) {
826
817
  // collect fields to be sent as separate parts
827
- const { inputs, outputs, events, ...payload } = originalPayload;
818
+ const { inputs, outputs, events, attachments, ...payload } = originalPayload;
828
819
  const fields = { inputs, outputs, events };
829
820
  // encode the main run payload
830
821
  const stringifiedPayload = (0, index_js_2.stringify)(payload);
@@ -853,10 +844,16 @@ class Client {
853
844
  if (attachments) {
854
845
  delete allAttachments[payload.id];
855
846
  for (const [name, [contentType, content]] of Object.entries(attachments)) {
847
+ // Validate that the attachment name doesn't contain a '.'
848
+ if (name.includes(".")) {
849
+ console.warn(`Skipping attachment '${name}' for run ${payload.id}: Invalid attachment name. ` +
850
+ `Attachment names must not contain periods ('.'). Please rename the attachment and try again.`);
851
+ continue;
852
+ }
856
853
  accumulatedParts.push({
857
854
  name: `attachment.${payload.id}.${name}`,
858
855
  payload: new Blob([content], {
859
- type: `${contentType}; length=${content.length}`,
856
+ type: `${contentType}; length=${content.byteLength}`,
860
857
  }),
861
858
  });
862
859
  }
@@ -874,6 +871,7 @@ class Client {
874
871
  for (const part of parts) {
875
872
  formData.append(part.name, part.payload);
876
873
  }
874
+ // Log the form data
877
875
  await this.batchIngestCaller.call((0, fetch_js_1._getFetchImplementation)(), `${this.apiUrl}/runs/multipart`, {
878
876
  method: "POST",
879
877
  headers: {
package/dist/client.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { AsyncCallerParams } from "./utils/async_caller.js";
2
- import { ComparativeExperiment, DataType, Dataset, DatasetDiffInfo, DatasetShareSchema, Example, ExampleUpdate, ExampleUpdateWithId, Feedback, FeedbackConfig, FeedbackIngestToken, KVMap, LangChainBaseMessage, LangSmithSettings, LikePromptResponse, Prompt, PromptCommit, PromptSortField, Run, RunCreate, RunUpdate, ScoreType, ExampleSearch, TimeDelta, TracerSession, TracerSessionResult, ValueType, AnnotationQueue, RunWithAnnotationQueueInfo } from "./schemas.js";
2
+ import { ComparativeExperiment, DataType, Dataset, DatasetDiffInfo, DatasetShareSchema, Example, ExampleUpdate, ExampleUpdateWithId, Feedback, FeedbackConfig, FeedbackIngestToken, KVMap, LangChainBaseMessage, LangSmithSettings, LikePromptResponse, Prompt, PromptCommit, PromptSortField, Run, RunCreate, RunUpdate, ScoreType, ExampleSearch, TimeDelta, TracerSession, TracerSessionResult, ValueType, AnnotationQueue, RunWithAnnotationQueueInfo, Attachments } from "./schemas.js";
3
3
  import { EvaluationResult, EvaluationResults, RunEvaluator } from "./evaluation/evaluator.js";
4
4
  export interface ClientConfig {
5
5
  apiUrl?: string;
@@ -135,7 +135,7 @@ interface CreateRunParams {
135
135
  revision_id?: string;
136
136
  trace_id?: string;
137
137
  dotted_order?: string;
138
- attachments?: Record<string, [string, Uint8Array]>;
138
+ attachments?: Attachments;
139
139
  }
140
140
  interface ProjectOptions {
141
141
  projectName?: string;
@@ -199,7 +199,6 @@ export declare class Client {
199
199
  private autoBatchTracing;
200
200
  private autoBatchQueue;
201
201
  private autoBatchTimeout;
202
- private autoBatchInitialDelayMs;
203
202
  private autoBatchAggregationDelayMs;
204
203
  private batchSizeBytesLimit?;
205
204
  private fetchOptions;
package/dist/client.js CHANGED
@@ -231,17 +231,11 @@ export class Client {
231
231
  writable: true,
232
232
  value: void 0
233
233
  });
234
- Object.defineProperty(this, "autoBatchInitialDelayMs", {
235
- enumerable: true,
236
- configurable: true,
237
- writable: true,
238
- value: 250
239
- });
240
234
  Object.defineProperty(this, "autoBatchAggregationDelayMs", {
241
235
  enumerable: true,
242
236
  configurable: true,
243
237
  writable: true,
244
- value: 50
238
+ value: 250
245
239
  });
246
240
  Object.defineProperty(this, "batchSizeBytesLimit", {
247
241
  enumerable: true,
@@ -548,7 +542,6 @@ export class Client {
548
542
  }
549
543
  }
550
544
  async processRunOperation(item) {
551
- const oldTimeout = this.autoBatchTimeout;
552
545
  clearTimeout(this.autoBatchTimeout);
553
546
  this.autoBatchTimeout = undefined;
554
547
  if (item.action === "create") {
@@ -563,9 +556,7 @@ export class Client {
563
556
  this.autoBatchTimeout = setTimeout(() => {
564
557
  this.autoBatchTimeout = undefined;
565
558
  this.drainAutoBatchQueue(sizeLimitBytes);
566
- }, oldTimeout
567
- ? this.autoBatchAggregationDelayMs
568
- : this.autoBatchInitialDelayMs);
559
+ }, this.autoBatchAggregationDelayMs);
569
560
  }
570
561
  return itemPromise;
571
562
  }
@@ -796,7 +787,7 @@ export class Client {
796
787
  ]) {
797
788
  for (const originalPayload of payloads) {
798
789
  // collect fields to be sent as separate parts
799
- const { inputs, outputs, events, ...payload } = originalPayload;
790
+ const { inputs, outputs, events, attachments, ...payload } = originalPayload;
800
791
  const fields = { inputs, outputs, events };
801
792
  // encode the main run payload
802
793
  const stringifiedPayload = stringifyForTracing(payload);
@@ -825,10 +816,16 @@ export class Client {
825
816
  if (attachments) {
826
817
  delete allAttachments[payload.id];
827
818
  for (const [name, [contentType, content]] of Object.entries(attachments)) {
819
+ // Validate that the attachment name doesn't contain a '.'
820
+ if (name.includes(".")) {
821
+ console.warn(`Skipping attachment '${name}' for run ${payload.id}: Invalid attachment name. ` +
822
+ `Attachment names must not contain periods ('.'). Please rename the attachment and try again.`);
823
+ continue;
824
+ }
828
825
  accumulatedParts.push({
829
826
  name: `attachment.${payload.id}.${name}`,
830
827
  payload: new Blob([content], {
831
- type: `${contentType}; length=${content.length}`,
828
+ type: `${contentType}; length=${content.byteLength}`,
832
829
  }),
833
830
  });
834
831
  }
@@ -846,6 +843,7 @@ export class Client {
846
843
  for (const part of parts) {
847
844
  formData.append(part.name, part.payload);
848
845
  }
846
+ // Log the form data
849
847
  await this.batchIngestCaller.call(_getFetchImplementation(), `${this.apiUrl}/runs/multipart`, {
850
848
  method: "POST",
851
849
  headers: {
@@ -1,14 +1,14 @@
1
1
  import { Client } from "../index.js";
2
2
  import { Example, KVMap, Run, TracerSession } from "../schemas.js";
3
3
  import { EvaluationResult, EvaluationResults, RunEvaluator } from "./evaluator.js";
4
- type TargetT<TInput = any, TOutput = KVMap> = ((input: TInput, config?: KVMap) => Promise<TOutput>) | ((input: TInput, config?: KVMap) => TOutput) | {
4
+ export type TargetT<TInput = any, TOutput = KVMap> = ((input: TInput, config?: KVMap) => Promise<TOutput>) | ((input: TInput, config?: KVMap) => TOutput) | {
5
5
  invoke: (input: TInput, config?: KVMap) => TOutput;
6
6
  } | {
7
7
  invoke: (input: TInput, config?: KVMap) => Promise<TOutput>;
8
8
  };
9
- type DataT = string | AsyncIterable<Example> | Example[];
10
- type SummaryEvaluatorT = ((runs: Array<Run>, examples: Array<Example>) => Promise<EvaluationResult | EvaluationResults>) | ((runs: Array<Run>, examples: Array<Example>) => EvaluationResult | EvaluationResults);
11
- type EvaluatorT = RunEvaluator | ((run: Run, example?: Example) => EvaluationResult | EvaluationResults) | ((run: Run, example?: Example) => Promise<EvaluationResult | EvaluationResults>);
9
+ export type DataT = string | AsyncIterable<Example> | Example[];
10
+ export type SummaryEvaluatorT = ((runs: Array<Run>, examples: Array<Example>) => Promise<EvaluationResult | EvaluationResults>) | ((runs: Array<Run>, examples: Array<Example>) => EvaluationResult | EvaluationResults);
11
+ export type EvaluatorT = RunEvaluator | ((run: Run, example?: Example) => EvaluationResult | EvaluationResults) | ((run: Run, example?: Example) => Promise<EvaluationResult | EvaluationResults>);
12
12
  interface _ForwardResults {
13
13
  run: Run;
14
14
  example: Example;
@@ -77,7 +77,7 @@ export declare function evaluate(
77
77
  * The target system or function to evaluate.
78
78
  */
79
79
  target: TargetT, options: EvaluateOptions): Promise<ExperimentResults>;
80
- interface ExperimentResultRow {
80
+ export interface ExperimentResultRow {
81
81
  run: Run;
82
82
  example: Example;
83
83
  evaluationResults: EvaluationResults;
@@ -1,4 +1,4 @@
1
1
  export { RunEvaluator, EvaluationResult } from "./evaluator.js";
2
2
  export { StringEvaluator, GradingFunctionParams, GradingFunctionResult, } from "./string_evaluator.js";
3
- export { evaluate, type EvaluateOptions } from "./_runner.js";
3
+ export { evaluate, type EvaluateOptions, type TargetT, type DataT, type SummaryEvaluatorT, type EvaluatorT, type ExperimentResultRow, } from "./_runner.js";
4
4
  export { evaluateComparative } from "./evaluate_comparative.js";
@@ -1,3 +1,3 @@
1
1
  export { StringEvaluator, } from "./string_evaluator.js";
2
- export { evaluate } from "./_runner.js";
2
+ export { evaluate, } from "./_runner.js";
3
3
  export { evaluateComparative } from "./evaluate_comparative.js";
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.4-dev.0";
11
+ exports.__version__ = "0.2.4";
package/dist/index.d.ts CHANGED
@@ -2,4 +2,4 @@ export { Client, type ClientConfig } 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
4
  export { overrideFetchImplementation } from "./singletons/fetch.js";
5
- export declare const __version__ = "0.2.4-dev.0";
5
+ export declare const __version__ = "0.2.4";
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.4-dev.0";
5
+ export const __version__ = "0.2.4";
@@ -221,6 +221,16 @@ class RunTree {
221
221
  writable: true,
222
222
  value: void 0
223
223
  });
224
+ /**
225
+ * Attachments associated with the run.
226
+ * Each entry is a tuple of [mime_type, bytes]
227
+ */
228
+ Object.defineProperty(this, "attachments", {
229
+ enumerable: true,
230
+ configurable: true,
231
+ writable: true,
232
+ value: void 0
233
+ });
224
234
  // If you pass in a run tree directly, return a shallow clone
225
235
  if (isRunTree(originalConfig)) {
226
236
  Object.assign(this, { ...originalConfig });
@@ -377,6 +387,7 @@ class RunTree {
377
387
  trace_id: run.trace_id,
378
388
  dotted_order: run.dotted_order,
379
389
  tags: run.tags,
390
+ attachments: run.attachments,
380
391
  };
381
392
  return persistedRun;
382
393
  }
@@ -410,6 +421,7 @@ class RunTree {
410
421
  dotted_order: this.dotted_order,
411
422
  trace_id: this.trace_id,
412
423
  tags: this.tags,
424
+ attachments: this.attachments,
413
425
  };
414
426
  await this.client.updateRun(this.id, runUpdate);
415
427
  }
@@ -1,4 +1,4 @@
1
- import { BaseRun, KVMap, RunCreate } from "./schemas.js";
1
+ import { Attachments, BaseRun, KVMap, RunCreate } from "./schemas.js";
2
2
  import { Client } from "./client.js";
3
3
  export declare function convertToDottedOrderFormat(epoch: number, runId: string, executionOrder?: number): string;
4
4
  export interface RunTreeConfig {
@@ -26,6 +26,7 @@ export interface RunTreeConfig {
26
26
  child_execution_order?: number;
27
27
  trace_id?: string;
28
28
  dotted_order?: string;
29
+ attachments?: Attachments;
29
30
  }
30
31
  export interface RunnableConfigLike {
31
32
  /**
@@ -72,6 +73,11 @@ export declare class RunTree implements BaseRun {
72
73
  tracingEnabled?: boolean;
73
74
  execution_order: number;
74
75
  child_execution_order: number;
76
+ /**
77
+ * Attachments associated with the run.
78
+ * Each entry is a tuple of [mime_type, bytes]
79
+ */
80
+ attachments?: Attachments;
75
81
  constructor(originalConfig: RunTreeConfig | RunTree);
76
82
  private static getDefaultConfig;
77
83
  private static getSharedClient;
package/dist/run_trees.js CHANGED
@@ -194,6 +194,16 @@ export class RunTree {
194
194
  writable: true,
195
195
  value: void 0
196
196
  });
197
+ /**
198
+ * Attachments associated with the run.
199
+ * Each entry is a tuple of [mime_type, bytes]
200
+ */
201
+ Object.defineProperty(this, "attachments", {
202
+ enumerable: true,
203
+ configurable: true,
204
+ writable: true,
205
+ value: void 0
206
+ });
197
207
  // If you pass in a run tree directly, return a shallow clone
198
208
  if (isRunTree(originalConfig)) {
199
209
  Object.assign(this, { ...originalConfig });
@@ -350,6 +360,7 @@ export class RunTree {
350
360
  trace_id: run.trace_id,
351
361
  dotted_order: run.dotted_order,
352
362
  tags: run.tags,
363
+ attachments: run.attachments,
353
364
  };
354
365
  return persistedRun;
355
366
  }
@@ -383,6 +394,7 @@ export class RunTree {
383
394
  dotted_order: this.dotted_order,
384
395
  trace_id: this.trace_id,
385
396
  tags: this.tags,
397
+ attachments: this.attachments,
386
398
  };
387
399
  await this.client.updateRun(this.id, runUpdate);
388
400
  }
package/dist/schemas.d.ts CHANGED
@@ -32,6 +32,8 @@ export interface BaseExample {
32
32
  metadata?: KVMap;
33
33
  source_run_id?: string;
34
34
  }
35
+ export type AttachmentData = Uint8Array | ArrayBuffer;
36
+ export type Attachments = Record<string, [string, AttachmentData]>;
35
37
  /**
36
38
  * A run can represent either a trace (root run)
37
39
  * or a child run (~span).
@@ -84,7 +86,7 @@ export interface BaseRun {
84
86
  * Attachments associated with the run.
85
87
  * Each entry is a tuple of [mime_type, bytes]
86
88
  */
87
- attachments?: Record<string, [string, Uint8Array]>;
89
+ attachments?: Attachments;
88
90
  }
89
91
  type S3URL = {
90
92
  ROOT: {
@@ -164,6 +166,11 @@ export interface RunUpdate {
164
166
  * - 20230915T223155647Z1b64098b-4ab7-43f6-afee-992304f198d8.20230914T223155650Zc8d9f4c5-6c5a-4b2d-9b1c-3d9d7a7c5c7c
165
167
  */
166
168
  dotted_order?: string;
169
+ /**
170
+ * Attachments associated with the run.
171
+ * Each entry is a tuple of [mime_type, bytes]
172
+ */
173
+ attachments?: Attachments;
167
174
  }
168
175
  export interface ExampleCreate extends BaseExample {
169
176
  id?: string;
@@ -8,7 +8,7 @@ const traceable_js_1 = require("./singletons/traceable.cjs");
8
8
  const constants_js_1 = require("./singletons/constants.cjs");
9
9
  const asserts_js_1 = require("./utils/asserts.cjs");
10
10
  traceable_js_1.AsyncLocalStorageProviderSingleton.initializeGlobalInstance(new node_async_hooks_1.AsyncLocalStorage());
11
- const handleRunInputs = (rawInputs, processInputs) => {
11
+ const runInputsToMap = (rawInputs) => {
12
12
  const firstInput = rawInputs[0];
13
13
  let inputs;
14
14
  if (firstInput == null) {
@@ -23,6 +23,9 @@ const handleRunInputs = (rawInputs, processInputs) => {
23
23
  else {
24
24
  inputs = { input: firstInput };
25
25
  }
26
+ return inputs;
27
+ };
28
+ const handleRunInputs = (inputs, processInputs) => {
26
29
  try {
27
30
  return processInputs(inputs);
28
31
  }
@@ -47,11 +50,26 @@ const handleRunOutputs = (rawOutputs, processOutputs) => {
47
50
  return outputs;
48
51
  }
49
52
  };
50
- const getTracingRunTree = (runTree, inputs, getInvocationParams, processInputs) => {
53
+ const handleRunAttachments = (rawInputs, extractAttachments) => {
54
+ if (!extractAttachments) {
55
+ return [undefined, rawInputs];
56
+ }
57
+ try {
58
+ const [attachments, remainingArgs] = extractAttachments(...rawInputs);
59
+ return [attachments, remainingArgs];
60
+ }
61
+ catch (e) {
62
+ console.error("Error occurred during extractAttachments:", e);
63
+ return [undefined, rawInputs];
64
+ }
65
+ };
66
+ const getTracingRunTree = (runTree, inputs, getInvocationParams, processInputs, extractAttachments) => {
51
67
  if (!(0, env_js_1.isTracingEnabled)(runTree.tracingEnabled)) {
52
68
  return undefined;
53
69
  }
54
- runTree.inputs = handleRunInputs(inputs, processInputs);
70
+ const [attached, args] = handleRunAttachments(inputs, extractAttachments);
71
+ runTree.attachments = attached;
72
+ runTree.inputs = handleRunInputs(args, processInputs);
55
73
  const invocationParams = getInvocationParams?.(...inputs);
56
74
  if (invocationParams != null) {
57
75
  runTree.extra ??= {};
@@ -213,9 +231,10 @@ const convertSerializableArg = (arg) => {
213
231
  */
214
232
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
215
233
  function traceable(wrappedFunc, config) {
216
- const { aggregator, argsConfigPath, __finalTracedIteratorKey, processInputs, processOutputs, ...runTreeConfig } = config ?? {};
234
+ const { aggregator, argsConfigPath, __finalTracedIteratorKey, processInputs, processOutputs, extractAttachments, ...runTreeConfig } = config ?? {};
217
235
  const processInputsFn = processInputs ?? ((x) => x);
218
236
  const processOutputsFn = processOutputs ?? ((x) => x);
237
+ const extractAttachmentsFn = extractAttachments ?? ((...x) => [undefined, runInputsToMap(x)]);
219
238
  const traceableFunc = (...args) => {
220
239
  let ensuredConfig;
221
240
  try {
@@ -273,7 +292,7 @@ function traceable(wrappedFunc, config) {
273
292
  // used for handoff between LangChain.JS and traceable functions
274
293
  if ((0, run_trees_js_1.isRunnableConfigLike)(firstArg)) {
275
294
  return [
276
- getTracingRunTree(run_trees_js_1.RunTree.fromRunnableConfig(firstArg, ensuredConfig), restArgs, config?.getInvocationParams, processInputsFn),
295
+ getTracingRunTree(run_trees_js_1.RunTree.fromRunnableConfig(firstArg, ensuredConfig), restArgs, config?.getInvocationParams, processInputsFn, extractAttachmentsFn),
277
296
  restArgs,
278
297
  ];
279
298
  }
@@ -289,7 +308,7 @@ function traceable(wrappedFunc, config) {
289
308
  if (firstArg === traceable_js_1.ROOT || (0, run_trees_js_1.isRunTree)(firstArg)) {
290
309
  const currentRunTree = getTracingRunTree(firstArg === traceable_js_1.ROOT
291
310
  ? new run_trees_js_1.RunTree(ensuredConfig)
292
- : firstArg.createChild(ensuredConfig), restArgs, config?.getInvocationParams, processInputsFn);
311
+ : firstArg.createChild(ensuredConfig), restArgs, config?.getInvocationParams, processInputsFn, extractAttachmentsFn);
293
312
  return [currentRunTree, [currentRunTree, ...restArgs]];
294
313
  }
295
314
  // Node.JS uses AsyncLocalStorage (ALS) and AsyncResource
@@ -297,11 +316,11 @@ function traceable(wrappedFunc, config) {
297
316
  const prevRunFromStore = asyncLocalStorage.getStore();
298
317
  if ((0, run_trees_js_1.isRunTree)(prevRunFromStore)) {
299
318
  return [
300
- getTracingRunTree(prevRunFromStore.createChild(ensuredConfig), processedArgs, config?.getInvocationParams, processInputsFn),
319
+ getTracingRunTree(prevRunFromStore.createChild(ensuredConfig), processedArgs, config?.getInvocationParams, processInputsFn, extractAttachmentsFn),
301
320
  processedArgs,
302
321
  ];
303
322
  }
304
- const currentRunTree = getTracingRunTree(new run_trees_js_1.RunTree(ensuredConfig), processedArgs, config?.getInvocationParams, processInputsFn);
323
+ const currentRunTree = getTracingRunTree(new run_trees_js_1.RunTree(ensuredConfig), processedArgs, config?.getInvocationParams, processInputsFn, extractAttachmentsFn);
305
324
  // If a context var is set by LangChain outside of a traceable,
306
325
  // it will be an object with a single property and we should copy
307
326
  // context vars over into the new run tree.
@@ -1,5 +1,5 @@
1
1
  import { RunTreeConfig } from "./run_trees.js";
2
- import { InvocationParamsSchema, KVMap } from "./schemas.js";
2
+ import { Attachments, InvocationParamsSchema, KVMap } from "./schemas.js";
3
3
  import { TraceableFunction } from "./singletons/types.js";
4
4
  /**
5
5
  * Higher-order function that takes function as input and returns a
@@ -19,6 +19,12 @@ export declare function traceable<Func extends (...args: any[]) => any>(wrappedF
19
19
  aggregator?: (args: any[]) => any;
20
20
  argsConfigPath?: [number] | [number, string];
21
21
  __finalTracedIteratorKey?: string;
22
+ /**
23
+ * Extract attachments from args and return remaining args.
24
+ * @param args Arguments of the traced function
25
+ * @returns Tuple of [Attachments, remaining args]
26
+ */
27
+ extractAttachments?: (...args: Parameters<Func>) => [Attachments | undefined, KVMap];
22
28
  /**
23
29
  * Extract invocation parameters from the arguments of the traced function.
24
30
  * This is useful for LangSmith to properly track common metadata like
package/dist/traceable.js CHANGED
@@ -5,7 +5,7 @@ import { ROOT, AsyncLocalStorageProviderSingleton, } from "./singletons/traceabl
5
5
  import { _LC_CONTEXT_VARIABLES_KEY } from "./singletons/constants.js";
6
6
  import { isKVMap, isReadableStream, isAsyncIterable, isIteratorLike, isThenable, isGenerator, isPromiseMethod, } from "./utils/asserts.js";
7
7
  AsyncLocalStorageProviderSingleton.initializeGlobalInstance(new AsyncLocalStorage());
8
- const handleRunInputs = (rawInputs, processInputs) => {
8
+ const runInputsToMap = (rawInputs) => {
9
9
  const firstInput = rawInputs[0];
10
10
  let inputs;
11
11
  if (firstInput == null) {
@@ -20,6 +20,9 @@ const handleRunInputs = (rawInputs, processInputs) => {
20
20
  else {
21
21
  inputs = { input: firstInput };
22
22
  }
23
+ return inputs;
24
+ };
25
+ const handleRunInputs = (inputs, processInputs) => {
23
26
  try {
24
27
  return processInputs(inputs);
25
28
  }
@@ -44,11 +47,26 @@ const handleRunOutputs = (rawOutputs, processOutputs) => {
44
47
  return outputs;
45
48
  }
46
49
  };
47
- const getTracingRunTree = (runTree, inputs, getInvocationParams, processInputs) => {
50
+ const handleRunAttachments = (rawInputs, extractAttachments) => {
51
+ if (!extractAttachments) {
52
+ return [undefined, rawInputs];
53
+ }
54
+ try {
55
+ const [attachments, remainingArgs] = extractAttachments(...rawInputs);
56
+ return [attachments, remainingArgs];
57
+ }
58
+ catch (e) {
59
+ console.error("Error occurred during extractAttachments:", e);
60
+ return [undefined, rawInputs];
61
+ }
62
+ };
63
+ const getTracingRunTree = (runTree, inputs, getInvocationParams, processInputs, extractAttachments) => {
48
64
  if (!isTracingEnabled(runTree.tracingEnabled)) {
49
65
  return undefined;
50
66
  }
51
- runTree.inputs = handleRunInputs(inputs, processInputs);
67
+ const [attached, args] = handleRunAttachments(inputs, extractAttachments);
68
+ runTree.attachments = attached;
69
+ runTree.inputs = handleRunInputs(args, processInputs);
52
70
  const invocationParams = getInvocationParams?.(...inputs);
53
71
  if (invocationParams != null) {
54
72
  runTree.extra ??= {};
@@ -210,9 +228,10 @@ const convertSerializableArg = (arg) => {
210
228
  */
211
229
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
212
230
  export function traceable(wrappedFunc, config) {
213
- const { aggregator, argsConfigPath, __finalTracedIteratorKey, processInputs, processOutputs, ...runTreeConfig } = config ?? {};
231
+ const { aggregator, argsConfigPath, __finalTracedIteratorKey, processInputs, processOutputs, extractAttachments, ...runTreeConfig } = config ?? {};
214
232
  const processInputsFn = processInputs ?? ((x) => x);
215
233
  const processOutputsFn = processOutputs ?? ((x) => x);
234
+ const extractAttachmentsFn = extractAttachments ?? ((...x) => [undefined, runInputsToMap(x)]);
216
235
  const traceableFunc = (...args) => {
217
236
  let ensuredConfig;
218
237
  try {
@@ -270,7 +289,7 @@ export function traceable(wrappedFunc, config) {
270
289
  // used for handoff between LangChain.JS and traceable functions
271
290
  if (isRunnableConfigLike(firstArg)) {
272
291
  return [
273
- getTracingRunTree(RunTree.fromRunnableConfig(firstArg, ensuredConfig), restArgs, config?.getInvocationParams, processInputsFn),
292
+ getTracingRunTree(RunTree.fromRunnableConfig(firstArg, ensuredConfig), restArgs, config?.getInvocationParams, processInputsFn, extractAttachmentsFn),
274
293
  restArgs,
275
294
  ];
276
295
  }
@@ -286,7 +305,7 @@ export function traceable(wrappedFunc, config) {
286
305
  if (firstArg === ROOT || isRunTree(firstArg)) {
287
306
  const currentRunTree = getTracingRunTree(firstArg === ROOT
288
307
  ? new RunTree(ensuredConfig)
289
- : firstArg.createChild(ensuredConfig), restArgs, config?.getInvocationParams, processInputsFn);
308
+ : firstArg.createChild(ensuredConfig), restArgs, config?.getInvocationParams, processInputsFn, extractAttachmentsFn);
290
309
  return [currentRunTree, [currentRunTree, ...restArgs]];
291
310
  }
292
311
  // Node.JS uses AsyncLocalStorage (ALS) and AsyncResource
@@ -294,11 +313,11 @@ export function traceable(wrappedFunc, config) {
294
313
  const prevRunFromStore = asyncLocalStorage.getStore();
295
314
  if (isRunTree(prevRunFromStore)) {
296
315
  return [
297
- getTracingRunTree(prevRunFromStore.createChild(ensuredConfig), processedArgs, config?.getInvocationParams, processInputsFn),
316
+ getTracingRunTree(prevRunFromStore.createChild(ensuredConfig), processedArgs, config?.getInvocationParams, processInputsFn, extractAttachmentsFn),
298
317
  processedArgs,
299
318
  ];
300
319
  }
301
- const currentRunTree = getTracingRunTree(new RunTree(ensuredConfig), processedArgs, config?.getInvocationParams, processInputsFn);
320
+ const currentRunTree = getTracingRunTree(new RunTree(ensuredConfig), processedArgs, config?.getInvocationParams, processInputsFn, extractAttachmentsFn);
302
321
  // If a context var is set by LangChain outside of a traceable,
303
322
  // it will be an object with a single property and we should copy
304
323
  // context vars over into the new run tree.
package/dist/vercel.cjs CHANGED
@@ -5,6 +5,7 @@ const index_js_1 = require("./index.cjs");
5
5
  const uuid_1 = require("uuid");
6
6
  const traceable_js_1 = require("./singletons/traceable.cjs");
7
7
  const env_js_1 = require("./utils/env.cjs");
8
+ const env_js_2 = require("./env.cjs");
8
9
  // Attempt to convert CoreMessage to a LangChain-compatible format
9
10
  // which allows us to render messages more nicely in LangSmith
10
11
  function convertCoreToSmith(message) {
@@ -223,6 +224,7 @@ class AISDKExporter {
223
224
  this.client = args?.client ?? new index_js_1.Client();
224
225
  this.debug =
225
226
  args?.debug ?? (0, env_js_1.getEnvironmentVariable)("OTEL_LOG_LEVEL") === "DEBUG";
227
+ this.logDebug("creating exporter", { tracingEnabled: (0, env_js_2.isTracingEnabled)() });
226
228
  }
227
229
  static getSettings(settings) {
228
230
  const { runId, runName, ...rest } = settings ?? {};
@@ -232,7 +234,7 @@ class AISDKExporter {
232
234
  if (runName != null)
233
235
  metadata[RUN_NAME_METADATA_KEY.input] = runName;
234
236
  // attempt to obtain the run tree if used within a traceable function
235
- let defaultEnabled = true;
237
+ let defaultEnabled = settings?.isEnabled ?? (0, env_js_2.isTracingEnabled)();
236
238
  try {
237
239
  const runTree = (0, traceable_js_1.getCurrentRunTree)();
238
240
  const headers = runTree.toHeaders();
package/dist/vercel.js CHANGED
@@ -2,6 +2,7 @@ import { Client, RunTree } from "./index.js";
2
2
  import { v5 as uuid5, v4 as uuid4 } from "uuid";
3
3
  import { getCurrentRunTree } from "./singletons/traceable.js";
4
4
  import { getLangSmithEnvironmentVariable, getEnvironmentVariable, } from "./utils/env.js";
5
+ import { isTracingEnabled } from "./env.js";
5
6
  // Attempt to convert CoreMessage to a LangChain-compatible format
6
7
  // which allows us to render messages more nicely in LangSmith
7
8
  function convertCoreToSmith(message) {
@@ -220,6 +221,7 @@ export class AISDKExporter {
220
221
  this.client = args?.client ?? new Client();
221
222
  this.debug =
222
223
  args?.debug ?? getEnvironmentVariable("OTEL_LOG_LEVEL") === "DEBUG";
224
+ this.logDebug("creating exporter", { tracingEnabled: isTracingEnabled() });
223
225
  }
224
226
  static getSettings(settings) {
225
227
  const { runId, runName, ...rest } = settings ?? {};
@@ -229,7 +231,7 @@ export class AISDKExporter {
229
231
  if (runName != null)
230
232
  metadata[RUN_NAME_METADATA_KEY.input] = runName;
231
233
  // attempt to obtain the run tree if used within a traceable function
232
- let defaultEnabled = true;
234
+ let defaultEnabled = settings?.isEnabled ?? isTracingEnabled();
233
235
  try {
234
236
  const runTree = getCurrentRunTree();
235
237
  const headers = runTree.toHeaders();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "langsmith",
3
- "version": "0.2.4-dev.0",
3
+ "version": "0.2.5",
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": [