langchain 0.1.19 → 0.1.20

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.
@@ -367,7 +367,7 @@ class AgentExecutor extends base_js_1.BaseChain {
367
367
  return this.maxIterations === undefined || iterations < this.maxIterations;
368
368
  }
369
369
  /** @ignore */
370
- async _call(inputs, runManager) {
370
+ async _call(inputs, runManager, config) {
371
371
  const toolsByName = Object.fromEntries(this.tools.map((t) => [t.name.toLowerCase(), t]));
372
372
  const steps = [];
373
373
  let iterations = 0;
@@ -444,7 +444,7 @@ class AgentExecutor extends base_js_1.BaseChain {
444
444
  let observation;
445
445
  try {
446
446
  observation = tool
447
- ? await tool.call(action.toolInput, runManager?.getChild())
447
+ ? await tool.invoke(action.toolInput, (0, runnables_1.patchConfig)(config, { callbacks: runManager?.getChild() }))
448
448
  : `${action.tool} is not a valid tool, try another one.`;
449
449
  }
450
450
  catch (e) {
@@ -140,7 +140,7 @@ export declare class AgentExecutor extends BaseChain<ChainValues, AgentExecutorO
140
140
  */
141
141
  private shouldContinue;
142
142
  /** @ignore */
143
- _call(inputs: ChainValues, runManager?: CallbackManagerForChainRun): Promise<AgentExecutorOutput>;
143
+ _call(inputs: ChainValues, runManager?: CallbackManagerForChainRun, config?: RunnableConfig): Promise<AgentExecutorOutput>;
144
144
  _takeNextStep(nameToolMap: Record<string, ToolInterface>, inputs: ChainValues, intermediateSteps: AgentStep[], runManager?: CallbackManagerForChainRun): Promise<AgentFinish | AgentStep[]>;
145
145
  _return(output: AgentFinish, intermediateSteps: AgentStep[], runManager?: CallbackManagerForChainRun): Promise<AgentExecutorOutput>;
146
146
  _getToolReturn(nextStepOutput: AgentStep): Promise<AgentFinish | null>;
@@ -1,5 +1,5 @@
1
1
  import { ToolInputParsingException, Tool, } from "@langchain/core/tools";
2
- import { Runnable } from "@langchain/core/runnables";
2
+ import { Runnable, patchConfig, } from "@langchain/core/runnables";
3
3
  import { CallbackManager, } from "@langchain/core/callbacks/manager";
4
4
  import { OutputParserException } from "@langchain/core/output_parsers";
5
5
  import { Serializable } from "@langchain/core/load/serializable";
@@ -362,7 +362,7 @@ export class AgentExecutor extends BaseChain {
362
362
  return this.maxIterations === undefined || iterations < this.maxIterations;
363
363
  }
364
364
  /** @ignore */
365
- async _call(inputs, runManager) {
365
+ async _call(inputs, runManager, config) {
366
366
  const toolsByName = Object.fromEntries(this.tools.map((t) => [t.name.toLowerCase(), t]));
367
367
  const steps = [];
368
368
  let iterations = 0;
@@ -439,7 +439,7 @@ export class AgentExecutor extends BaseChain {
439
439
  let observation;
440
440
  try {
441
441
  observation = tool
442
- ? await tool.call(action.toolInput, runManager?.getChild())
442
+ ? await tool.invoke(action.toolInput, patchConfig(config, { callbacks: runManager?.getChild() }))
443
443
  : `${action.tool} is not a valid tool, try another one.`;
444
444
  }
445
445
  catch (e) {
@@ -55,14 +55,14 @@ class BaseChain extends base_1.BaseLangChain {
55
55
  try {
56
56
  outputValues = await (fullValues.signal
57
57
  ? Promise.race([
58
- this._call(fullValues, runManager),
58
+ this._call(fullValues, runManager, config),
59
59
  new Promise((_, reject) => {
60
60
  fullValues.signal?.addEventListener("abort", () => {
61
61
  reject(new Error("AbortError"));
62
62
  });
63
63
  }),
64
64
  ])
65
- : this._call(fullValues, runManager));
65
+ : this._call(fullValues, runManager, config));
66
66
  }
67
67
  catch (e) {
68
68
  await runManager?.handleChainError(e);
@@ -37,7 +37,7 @@ export declare abstract class BaseChain<RunInput extends ChainValues = ChainValu
37
37
  /**
38
38
  * Run the core logic of this chain and return the output
39
39
  */
40
- abstract _call(values: RunInput, runManager?: CallbackManagerForChainRun): Promise<RunOutput>;
40
+ abstract _call(values: RunInput, runManager?: CallbackManagerForChainRun, config?: RunnableConfig): Promise<RunOutput>;
41
41
  /**
42
42
  * Return the string type key uniquely identifying this class of chain.
43
43
  */
@@ -52,14 +52,14 @@ export class BaseChain extends BaseLangChain {
52
52
  try {
53
53
  outputValues = await (fullValues.signal
54
54
  ? Promise.race([
55
- this._call(fullValues, runManager),
55
+ this._call(fullValues, runManager, config),
56
56
  new Promise((_, reject) => {
57
57
  fullValues.signal?.addEventListener("abort", () => {
58
58
  reject(new Error("AbortError"));
59
59
  });
60
60
  }),
61
61
  ])
62
- : this._call(fullValues, runManager));
62
+ : this._call(fullValues, runManager, config));
63
63
  }
64
64
  catch (e) {
65
65
  await runManager?.handleChainError(e);
@@ -43,7 +43,11 @@ class AzureBlobStorageContainerLoader extends base_js_1.BaseDocumentLoader {
43
43
  * @returns An array of loaded documents.
44
44
  */
45
45
  async load() {
46
- const blobServiceClient = storage_blob_1.BlobServiceClient.fromConnectionString(this.connectionString);
46
+ const blobServiceClient = storage_blob_1.BlobServiceClient.fromConnectionString(this.connectionString, {
47
+ userAgentOptions: {
48
+ userAgentPrefix: "langchainjs-blob-storage-container",
49
+ },
50
+ });
47
51
  const containerClient = blobServiceClient.getContainerClient(this.container);
48
52
  let docs = [];
49
53
  for await (const blob of containerClient.listBlobsFlat()) {
@@ -40,7 +40,11 @@ export class AzureBlobStorageContainerLoader extends BaseDocumentLoader {
40
40
  * @returns An array of loaded documents.
41
41
  */
42
42
  async load() {
43
- const blobServiceClient = BlobServiceClient.fromConnectionString(this.connectionString);
43
+ const blobServiceClient = BlobServiceClient.fromConnectionString(this.connectionString, {
44
+ userAgentOptions: {
45
+ userAgentPrefix: "langchainjs-blob-storage-container",
46
+ },
47
+ });
44
48
  const containerClient = blobServiceClient.getContainerClient(this.container);
45
49
  let docs = [];
46
50
  for await (const blob of containerClient.listBlobsFlat()) {
@@ -89,7 +89,11 @@ class AzureBlobStorageFileLoader extends base_js_1.BaseDocumentLoader {
89
89
  const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "azureblobfileloader-"));
90
90
  const filePath = path.join(tempDir, this.blobName);
91
91
  try {
92
- const blobServiceClient = storage_blob_1.BlobServiceClient.fromConnectionString(this.connectionString);
92
+ const blobServiceClient = storage_blob_1.BlobServiceClient.fromConnectionString(this.connectionString, {
93
+ userAgentOptions: {
94
+ userAgentPrefix: "langchainjs-blob-storage-file",
95
+ },
96
+ });
93
97
  const containerClient = blobServiceClient.getContainerClient(this.container);
94
98
  const blobClient = containerClient.getBlobClient(this.blobName);
95
99
  fs.mkdirSync(path.dirname(filePath), { recursive: true });
@@ -63,7 +63,11 @@ export class AzureBlobStorageFileLoader extends BaseDocumentLoader {
63
63
  const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "azureblobfileloader-"));
64
64
  const filePath = path.join(tempDir, this.blobName);
65
65
  try {
66
- const blobServiceClient = BlobServiceClient.fromConnectionString(this.connectionString);
66
+ const blobServiceClient = BlobServiceClient.fromConnectionString(this.connectionString, {
67
+ userAgentOptions: {
68
+ userAgentPrefix: "langchainjs-blob-storage-file",
69
+ },
70
+ });
67
71
  const containerClient = blobServiceClient.getContainerClient(this.container);
68
72
  const blobClient = containerClient.getBlobClient(this.blobName);
69
73
  fs.mkdirSync(path.dirname(filePath), { recursive: true });
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.LabeledCriteria = exports.Criteria = exports.isCustomEvaluator = exports.isOffTheShelfEvaluator = void 0;
3
+ exports.EmbeddingDistance = exports.LabeledCriteria = exports.Criteria = exports.isCustomEvaluator = exports.isOffTheShelfEvaluator = void 0;
4
4
  function isOffTheShelfEvaluator(evaluator) {
5
5
  return typeof evaluator === "string" || "evaluatorType" in evaluator;
6
6
  }
@@ -36,6 +36,7 @@ function Criteria(criteria, config) {
36
36
  evaluatorType: "criteria",
37
37
  criteria,
38
38
  feedbackKey: config?.feedbackKey ?? criteria,
39
+ llm: config?.llm,
39
40
  formatEvaluatorInputs,
40
41
  };
41
42
  }
@@ -51,7 +52,23 @@ function LabeledCriteria(criteria, config) {
51
52
  evaluatorType: "labeled_criteria",
52
53
  criteria,
53
54
  feedbackKey: config?.feedbackKey ?? criteria,
55
+ llm: config?.llm,
54
56
  formatEvaluatorInputs,
55
57
  };
56
58
  }
57
59
  exports.LabeledCriteria = LabeledCriteria;
60
+ function EmbeddingDistance(distanceMetric, config) {
61
+ const formatEvaluatorInputs = config?.formatEvaluatorInputs ??
62
+ ((payload) => ({
63
+ prediction: getSingleStringifiedValue(payload.rawPrediction),
64
+ reference: getSingleStringifiedValue(payload.rawReferenceOutput),
65
+ }));
66
+ return {
67
+ evaluatorType: "embedding_distance",
68
+ embedding: config?.embedding,
69
+ distanceMetric,
70
+ feedbackKey: config?.feedbackKey ?? "embedding_distance",
71
+ formatEvaluatorInputs,
72
+ };
73
+ }
74
+ exports.EmbeddingDistance = EmbeddingDistance;
@@ -2,7 +2,7 @@ import { BaseLanguageModel } from "@langchain/core/language_models/base";
2
2
  import { RunnableConfig } from "@langchain/core/runnables";
3
3
  import { Example, Run } from "langsmith";
4
4
  import { EvaluationResult, RunEvaluator } from "langsmith/evaluation";
5
- import { Criteria as CriteriaType } from "../evaluation/index.js";
5
+ import { Criteria as CriteriaType, type EmbeddingDistanceEvalChainInput } from "../evaluation/index.js";
6
6
  import { LoadEvaluatorOptions } from "../evaluation/loader.js";
7
7
  import { EvaluatorType } from "../evaluation/types.js";
8
8
  export type EvaluatorInputs = {
@@ -35,6 +35,7 @@ export type RunEvaluatorLike = ((props: DynamicRunEvaluatorParams, options?: {
35
35
  }) => EvaluationResult);
36
36
  export declare function isOffTheShelfEvaluator<T extends keyof EvaluatorType, U extends RunEvaluator | RunEvaluatorLike = RunEvaluator | RunEvaluatorLike>(evaluator: T | EvalConfig | U): evaluator is T | EvalConfig;
37
37
  export declare function isCustomEvaluator<T extends keyof EvaluatorType, U extends RunEvaluator | RunEvaluatorLike = RunEvaluator | RunEvaluatorLike>(evaluator: T | EvalConfig | U): evaluator is U;
38
+ export type RunEvalType<T extends keyof EvaluatorType = "criteria" | "labeled_criteria" | "embedding_distance", U extends RunEvaluator | RunEvaluatorLike = RunEvaluator | RunEvaluatorLike> = T | EvalConfig | U;
38
39
  /**
39
40
  * Configuration class for running evaluations on datasets.
40
41
  *
@@ -44,22 +45,13 @@ export declare function isCustomEvaluator<T extends keyof EvaluatorType, U exten
44
45
  * @typeparam T - The type of evaluators.
45
46
  * @typeparam U - The type of custom evaluators.
46
47
  */
47
- export type RunEvalConfig<T extends keyof EvaluatorType = keyof EvaluatorType, U extends RunEvaluator | RunEvaluatorLike = RunEvaluator | RunEvaluatorLike> = {
48
+ export type RunEvalConfig<T extends keyof EvaluatorType = "criteria" | "labeled_criteria" | "embedding_distance", U extends RunEvaluator | RunEvaluatorLike = RunEvaluator | RunEvaluatorLike> = {
48
49
  /**
49
- * Custom evaluators to apply to a dataset run.
50
- * Each evaluator is provided with a run trace containing the model
51
- * outputs, as well as an "example" object representing a record
52
- * in the dataset.
53
- *
54
- * @deprecated Use `evaluators` instead.
55
- */
56
- customEvaluators?: U[];
57
- /**
58
- * LangChain evaluators to apply to a dataset run.
50
+ * Evaluators to apply to a dataset run.
59
51
  * You can optionally specify these by name, or by
60
52
  * configuring them with an EvalConfig object.
61
53
  */
62
- evaluators?: (T | EvalConfig | U)[];
54
+ evaluators?: RunEvalType<T, U>[];
63
55
  /**
64
56
  * Convert the evaluation data into formats that can be used by the evaluator.
65
57
  * This should most commonly be a string.
@@ -85,9 +77,14 @@ export type RunEvalConfig<T extends keyof EvaluatorType = keyof EvaluatorType, U
85
77
  */
86
78
  formatEvaluatorInputs?: EvaluatorInputFormatter;
87
79
  /**
88
- * The language model specification for evaluators that require one.
80
+ * Custom evaluators to apply to a dataset run.
81
+ * Each evaluator is provided with a run trace containing the model
82
+ * outputs, as well as an "example" object representing a record
83
+ * in the dataset.
84
+ *
85
+ * @deprecated Use `evaluators` instead.
89
86
  */
90
- evalLlm?: string;
87
+ customEvaluators?: U[];
91
88
  };
92
89
  export interface EvalConfig extends LoadEvaluatorOptions {
93
90
  /**
@@ -151,7 +148,7 @@ export interface EvalConfig extends LoadEvaluatorOptions {
151
148
  * }]
152
149
  * };
153
150
  */
154
- export type CriteriaEvalChainConfig = EvalConfig & {
151
+ export type Criteria = EvalConfig & {
155
152
  evaluatorType: "criteria";
156
153
  /**
157
154
  * The "criteria" to insert into the prompt template
@@ -161,16 +158,12 @@ export type CriteriaEvalChainConfig = EvalConfig & {
161
158
  */
162
159
  criteria?: CriteriaType | Record<string, string>;
163
160
  /**
164
- * The feedback (or metric) name to use for the logged
165
- * evaluation results. If none provided, we default to
166
- * the evaluationName.
167
- */
168
- feedbackKey?: string;
169
- /**
170
- * The language model to use as the evaluator.
161
+ * The language model to use as the evaluator, defaults to GPT-4
171
162
  */
172
163
  llm?: BaseLanguageModel;
173
164
  };
165
+ export type CriteriaEvalChainConfig = Criteria;
166
+ export declare function Criteria(criteria: CriteriaType, config?: Pick<Partial<LabeledCriteria>, "formatEvaluatorInputs" | "llm" | "feedbackKey">): EvalConfig;
174
167
  /**
175
168
  * Configuration to load a "LabeledCriteriaEvalChain" evaluator,
176
169
  * which prompts an LLM to determine whether the model's
@@ -208,39 +201,17 @@ export type LabeledCriteria = EvalConfig & {
208
201
  */
209
202
  criteria?: CriteriaType | Record<string, string>;
210
203
  /**
211
- * The feedback (or metric) name to use for the logged
212
- * evaluation results. If none provided, we default to
213
- * the evaluationName.
214
- */
215
- feedbackKey?: string;
216
- /**
217
- * The language model to use as the evaluator.
204
+ * The language model to use as the evaluator, defaults to GPT-4
218
205
  */
219
206
  llm?: BaseLanguageModel;
220
207
  };
221
- export declare function Criteria(criteria: CriteriaType, config?: {
222
- formatEvaluatorInputs?: EvaluatorInputFormatter;
223
- feedbackKey?: string;
224
- }): {
225
- evaluatorType: "criteria";
226
- criteria: CriteriaType;
227
- feedbackKey: string;
228
- formatEvaluatorInputs: EvaluatorInputFormatter | ((payload: {
229
- rawInput: any;
230
- rawPrediction: any;
231
- rawReferenceOutput?: any;
232
- run: Run;
233
- }) => {
234
- prediction: string;
235
- input: string;
236
- });
237
- };
238
- export declare function LabeledCriteria(criteria: CriteriaType, config?: {
239
- formatEvaluatorInputs?: EvaluatorInputFormatter;
240
- feedbackKey?: string;
241
- }): {
242
- evaluatorType: "labeled_criteria";
243
- criteria: CriteriaType;
244
- feedbackKey: string;
245
- formatEvaluatorInputs: EvaluatorInputFormatter;
208
+ export declare function LabeledCriteria(criteria: CriteriaType, config?: Pick<Partial<LabeledCriteria>, "formatEvaluatorInputs" | "llm" | "feedbackKey">): LabeledCriteria;
209
+ /**
210
+ * Configuration to load a "EmbeddingDistanceEvalChain" evaluator,
211
+ * which embeds distances to score semantic difference between
212
+ * a prediction and reference.
213
+ */
214
+ export type EmbeddingDistance = EvalConfig & EmbeddingDistanceEvalChainInput & {
215
+ evaluatorType: "embedding_distance";
246
216
  };
217
+ export declare function EmbeddingDistance(distanceMetric: EmbeddingDistanceEvalChainInput["distanceMetric"], config?: Pick<Partial<LabeledCriteria>, "formatEvaluatorInputs" | "embedding" | "feedbackKey">): EmbeddingDistance;
@@ -31,6 +31,7 @@ export function Criteria(criteria, config) {
31
31
  evaluatorType: "criteria",
32
32
  criteria,
33
33
  feedbackKey: config?.feedbackKey ?? criteria,
34
+ llm: config?.llm,
34
35
  formatEvaluatorInputs,
35
36
  };
36
37
  }
@@ -45,6 +46,21 @@ export function LabeledCriteria(criteria, config) {
45
46
  evaluatorType: "labeled_criteria",
46
47
  criteria,
47
48
  feedbackKey: config?.feedbackKey ?? criteria,
49
+ llm: config?.llm,
50
+ formatEvaluatorInputs,
51
+ };
52
+ }
53
+ export function EmbeddingDistance(distanceMetric, config) {
54
+ const formatEvaluatorInputs = config?.formatEvaluatorInputs ??
55
+ ((payload) => ({
56
+ prediction: getSingleStringifiedValue(payload.rawPrediction),
57
+ reference: getSingleStringifiedValue(payload.rawReferenceOutput),
58
+ }));
59
+ return {
60
+ evaluatorType: "embedding_distance",
61
+ embedding: config?.embedding,
62
+ distanceMetric,
63
+ feedbackKey: config?.feedbackKey ?? "embedding_distance",
48
64
  formatEvaluatorInputs,
49
65
  };
50
66
  }
@@ -115,6 +115,61 @@ class DynamicRunEvaluator {
115
115
  function isLLMStringEvaluator(evaluator) {
116
116
  return evaluator && typeof evaluator.evaluateStrings === "function";
117
117
  }
118
+ /**
119
+ * Internal implementation of RunTree, which uses the
120
+ * provided callback manager instead of the internal LangSmith client.
121
+ *
122
+ * The goal of this class is to ensure seamless interop when intergrated
123
+ * with other Runnables.
124
+ */
125
+ class CallbackManagerRunTree extends langsmith_1.RunTree {
126
+ constructor(config, callbackManager) {
127
+ super(config);
128
+ Object.defineProperty(this, "callbackManager", {
129
+ enumerable: true,
130
+ configurable: true,
131
+ writable: true,
132
+ value: void 0
133
+ });
134
+ Object.defineProperty(this, "activeCallbackManager", {
135
+ enumerable: true,
136
+ configurable: true,
137
+ writable: true,
138
+ value: undefined
139
+ });
140
+ this.callbackManager = callbackManager;
141
+ }
142
+ async createChild(config) {
143
+ const child = new CallbackManagerRunTree({
144
+ ...config,
145
+ parent_run: this,
146
+ project_name: this.project_name,
147
+ client: this.client,
148
+ }, this.activeCallbackManager?.getChild() ?? this.callbackManager);
149
+ this.child_runs.push(child);
150
+ return child;
151
+ }
152
+ async postRun() {
153
+ // how it is translated in comparison to basic RunTree?
154
+ this.activeCallbackManager = await this.callbackManager.handleChainStart(typeof this.serialized !== "object" &&
155
+ this.serialized != null &&
156
+ "lc" in this.serialized
157
+ ? this.serialized
158
+ : {
159
+ id: ["langchain", "smith", "CallbackManagerRunTree"],
160
+ lc: 1,
161
+ type: "not_implemented",
162
+ }, this.inputs, this.id, this.run_type, undefined, undefined, this.name);
163
+ }
164
+ async patchRun() {
165
+ if (this.error) {
166
+ await this.activeCallbackManager?.handleChainError(this.error, this.id, this.parent_run?.id, undefined, undefined);
167
+ }
168
+ else {
169
+ await this.activeCallbackManager?.handleChainEnd(this.outputs ?? {}, this.id, this.parent_run?.id, undefined, undefined);
170
+ }
171
+ }
172
+ }
118
173
  class RunnableTraceable extends runnables_1.Runnable {
119
174
  constructor(fields) {
120
175
  super(fields);
@@ -147,12 +202,14 @@ class RunnableTraceable extends runnables_1.Runnable {
147
202
  const partialConfig = "langsmith:traceable" in this.func
148
203
  ? this.func["langsmith:traceable"]
149
204
  : { name: "<lambda>" };
150
- const runTree = new langsmith_1.RunTree({
205
+ if (!callbackManager)
206
+ throw new Error("CallbackManager not found");
207
+ const runTree = new CallbackManagerRunTree({
151
208
  ...partialConfig,
152
209
  parent_run: callbackManager?._parentRunId
153
210
  ? new langsmith_1.RunTree({ name: "<parent>", id: callbackManager?._parentRunId })
154
211
  : undefined,
155
- });
212
+ }, callbackManager);
156
213
  if (typeof input === "object" &&
157
214
  input != null &&
158
215
  Object.keys(input).length === 1) {
@@ -217,14 +274,14 @@ class PreparedRunEvaluator {
217
274
  const evalConfig = typeof config === "string" ? {} : config;
218
275
  const evaluator = await (0, loader_js_1.loadEvaluator)(evaluatorType, evalConfig);
219
276
  const feedbackKey = evalConfig?.feedbackKey ?? evaluator?.evaluationName;
220
- if (!feedbackKey) {
221
- throw new Error(`Evaluator of type ${evaluatorType} must have an evaluationName` +
222
- ` or feedbackKey. Please manually provide a feedbackKey in the EvalConfig.`);
223
- }
224
277
  if (!isLLMStringEvaluator(evaluator)) {
225
278
  throw new Error(`Evaluator of type ${evaluatorType} not yet supported. ` +
226
279
  "Please use a string evaluator, or implement your " +
227
- "evaluation logic as a customEvaluator.");
280
+ "evaluation logic as a custom evaluator.");
281
+ }
282
+ if (!feedbackKey) {
283
+ throw new Error(`Evaluator of type ${evaluatorType} must have an evaluationName` +
284
+ ` or feedbackKey. Please manually provide a feedbackKey in the EvalConfig.`);
228
285
  }
229
286
  return new PreparedRunEvaluator(evaluator, feedbackKey, evalConfig?.formatEvaluatorInputs);
230
287
  }
@@ -261,7 +318,7 @@ class PreparedRunEvaluator {
261
318
  }
262
319
  throw new Error("Evaluator not yet supported. " +
263
320
  "Please use a string evaluator, or implement your " +
264
- "evaluation logic as a customEvaluator.");
321
+ "evaluation logic as a custom evaluator.");
265
322
  }
266
323
  }
267
324
  class LoadedEvalConfig {
@@ -302,6 +359,10 @@ const createWrappedModel = async (modelOrFactory) => {
302
359
  return () => modelOrFactory;
303
360
  }
304
361
  if (typeof modelOrFactory === "function") {
362
+ if (isLangsmithTraceableFunction(modelOrFactory)) {
363
+ const wrappedModel = new RunnableTraceable({ func: modelOrFactory });
364
+ return () => wrappedModel;
365
+ }
305
366
  try {
306
367
  // If it works with no arguments, assume it's a factory
307
368
  let res = modelOrFactory();
@@ -313,11 +374,7 @@ const createWrappedModel = async (modelOrFactory) => {
313
374
  }
314
375
  catch (err) {
315
376
  // Otherwise, it's a custom UDF, and we'll wrap
316
- // in a lambda or a traceable function
317
- if (isLangsmithTraceableFunction(modelOrFactory)) {
318
- const wrappedModel = new RunnableTraceable({ func: modelOrFactory });
319
- return () => wrappedModel;
320
- }
377
+ // the function in a lambda
321
378
  const wrappedModel = new runnables_1.RunnableLambda({ func: modelOrFactory });
322
379
  return () => wrappedModel;
323
380
  }
@@ -389,10 +446,65 @@ const getExamplesInputs = (examples, chainOrFactory, dataType) => {
389
446
  }
390
447
  return examples.map(({ inputs }) => inputs);
391
448
  };
449
+ /**
450
+ * Evaluates a given model or chain against a specified LangSmith dataset.
451
+ *
452
+ * This function fetches example records from the specified dataset,
453
+ * runs the model or chain against each example, and returns the evaluation
454
+ * results.
455
+ *
456
+ * @param chainOrFactory - A model or factory/constructor function to be evaluated. It can be a
457
+ * Runnable instance, a factory function that returns a Runnable, or a user-defined
458
+ * function or factory.
459
+ *
460
+ * @param datasetName - The name of the dataset against which the evaluation will be
461
+ * performed. This dataset should already be defined and contain the relevant data
462
+ * for evaluation.
463
+ *
464
+ * @param options - (Optional) Additional parameters for the evaluation process:
465
+ * - `evaluators` (RunEvalType[]): Evaluators to apply to a dataset run.
466
+ * - `formatEvaluatorInputs` (EvaluatorInputFormatter): Convert the evaluation data into formats that can be used by the evaluator.
467
+ * - `projectName` (string): Name of the project for logging and tracking.
468
+ * - `projectMetadata` (Record<string, unknown>): Additional metadata for the project.
469
+ * - `client` (Client): Client instance for LangSmith service interaction.
470
+ * - `maxConcurrency` (number): Maximum concurrency level for dataset processing.
471
+ *
472
+ * @returns A promise that resolves to an `EvalResults` object. This object includes
473
+ * detailed results of the evaluation, such as execution time, run IDs, and feedback
474
+ * for each entry in the dataset.
475
+ *
476
+ * @example
477
+ * ```typescript
478
+ * // Example usage for evaluating a model on a dataset
479
+ * async function evaluateModel() {
480
+ * const chain = /* ...create your model or chain...*\//
481
+ * const datasetName = 'example-dataset';
482
+ * const client = new Client(/* ...config... *\//);
483
+ *
484
+ * const results = await runOnDataset(chain, datasetName, {
485
+ * evaluators: [/* ...evaluators... *\//],
486
+ * client,
487
+ * });
488
+ *
489
+ * console.log('Evaluation Results:', results);
490
+ * }
491
+ *
492
+ * evaluateModel();
493
+ * ```
494
+ * In this example, `runOnDataset` is used to evaluate a language model (or a chain of models) against
495
+ * a dataset named 'example-dataset'. The evaluation process is configured using `RunOnDatasetParams["evaluators"]`, which can
496
+ * include both standard and custom evaluators. The `Client` instance is used to interact with LangChain services.
497
+ * The function returns the evaluation results, which can be logged or further processed as needed.
498
+ */
392
499
  async function runOnDataset(chainOrFactory, datasetName, options) {
393
- const { evaluationConfig, projectName, projectMetadata, client, maxConcurrency, } = Array.isArray(options)
394
- ? { evaluationConfig: { evaluators: options } }
395
- : options ?? {};
500
+ const { projectName, projectMetadata, client, maxConcurrency, } = options ?? {};
501
+ const evaluationConfig = options?.evaluationConfig ??
502
+ (options?.evaluators != null
503
+ ? {
504
+ evaluators: options.evaluators,
505
+ formatEvaluatorInputs: options.formatEvaluatorInputs,
506
+ }
507
+ : undefined);
396
508
  const wrappedModel = await createWrappedModel(chainOrFactory);
397
509
  const testClient = client ?? new langsmith_1.Client();
398
510
  const testProjectName = projectName ?? (0, name_generation_js_1.randomName)();
@@ -4,13 +4,28 @@ import type { TraceableFunction } from "langsmith/traceable";
4
4
  import { type RunEvalConfig } from "./config.js";
5
5
  export type ChainOrFactory = Runnable | (() => Runnable) | AnyTraceableFunction | ((obj: any) => any) | ((obj: any) => Promise<any>) | (() => (obj: unknown) => unknown) | (() => (obj: unknown) => Promise<unknown>);
6
6
  type AnyTraceableFunction = TraceableFunction<(...any: any[]) => any>;
7
- export type RunOnDatasetParams = {
8
- evaluationConfig?: RunEvalConfig;
9
- projectMetadata?: Record<string, unknown>;
7
+ export interface RunOnDatasetParams extends Omit<RunEvalConfig, "customEvaluators"> {
8
+ /**
9
+ * Name of the project for logging and tracking.
10
+ */
10
11
  projectName?: string;
12
+ /**
13
+ * Additional metadata for the project.
14
+ */
15
+ projectMetadata?: Record<string, unknown>;
16
+ /**
17
+ * Client instance for LangSmith service interaction.
18
+ */
11
19
  client?: Client;
20
+ /**
21
+ * Maximum concurrency level for dataset processing.
22
+ */
12
23
  maxConcurrency?: number;
13
- };
24
+ /**
25
+ * @deprecated Pass keys directly to the RunOnDatasetParams instead
26
+ */
27
+ evaluationConfig?: RunEvalConfig;
28
+ }
14
29
  export type EvalResults = {
15
30
  projectName: string;
16
31
  results: {
@@ -37,11 +52,11 @@ export type EvalResults = {
37
52
  * for evaluation.
38
53
  *
39
54
  * @param options - (Optional) Additional parameters for the evaluation process:
40
- * - `evaluationConfig` (RunEvalConfig): Configuration for the evaluation, including
41
- * standard and custom evaluators.
55
+ * - `evaluators` (RunEvalType[]): Evaluators to apply to a dataset run.
56
+ * - `formatEvaluatorInputs` (EvaluatorInputFormatter): Convert the evaluation data into formats that can be used by the evaluator.
42
57
  * - `projectName` (string): Name of the project for logging and tracking.
43
58
  * - `projectMetadata` (Record<string, unknown>): Additional metadata for the project.
44
- * - `client` (Client): Client instance for LangChain service interaction.
59
+ * - `client` (Client): Client instance for LangSmith service interaction.
45
60
  * - `maxConcurrency` (number): Maximum concurrency level for dataset processing.
46
61
  *
47
62
  * @returns A promise that resolves to an `EvalResults` object. This object includes
@@ -56,13 +71,8 @@ export type EvalResults = {
56
71
  * const datasetName = 'example-dataset';
57
72
  * const client = new Client(/* ...config... *\//);
58
73
  *
59
- * const evaluationConfig = {
60
- * evaluators: [/* ...evaluators... *\//],
61
- * customEvaluators: [/* ...custom evaluators... *\//],
62
- * };
63
- *
64
74
  * const results = await runOnDataset(chain, datasetName, {
65
- * evaluationConfig,
75
+ * evaluators: [/* ...evaluators... *\//],
66
76
  * client,
67
77
  * });
68
78
  *
@@ -72,10 +82,9 @@ export type EvalResults = {
72
82
  * evaluateModel();
73
83
  * ```
74
84
  * In this example, `runOnDataset` is used to evaluate a language model (or a chain of models) against
75
- * a dataset named 'example-dataset'. The evaluation process is configured using `RunEvalConfig`, which can
85
+ * a dataset named 'example-dataset'. The evaluation process is configured using `RunOnDatasetParams["evaluators"]`, which can
76
86
  * include both standard and custom evaluators. The `Client` instance is used to interact with LangChain services.
77
87
  * The function returns the evaluation results, which can be logged or further processed as needed.
78
88
  */
79
- export declare function runOnDataset(chainOrFactory: ChainOrFactory, datasetName: string, { evaluationConfig, projectName, projectMetadata, client, maxConcurrency, }: RunOnDatasetParams): Promise<EvalResults>;
80
- export declare function runOnDataset(chainOrFactory: ChainOrFactory, datasetName: string, evaluators: RunEvalConfig["evaluators"]): Promise<EvalResults>;
89
+ export declare function runOnDataset(chainOrFactory: ChainOrFactory, datasetName: string, options?: RunOnDatasetParams): Promise<EvalResults>;
81
90
  export {};
@@ -112,6 +112,61 @@ class DynamicRunEvaluator {
112
112
  function isLLMStringEvaluator(evaluator) {
113
113
  return evaluator && typeof evaluator.evaluateStrings === "function";
114
114
  }
115
+ /**
116
+ * Internal implementation of RunTree, which uses the
117
+ * provided callback manager instead of the internal LangSmith client.
118
+ *
119
+ * The goal of this class is to ensure seamless interop when intergrated
120
+ * with other Runnables.
121
+ */
122
+ class CallbackManagerRunTree extends RunTree {
123
+ constructor(config, callbackManager) {
124
+ super(config);
125
+ Object.defineProperty(this, "callbackManager", {
126
+ enumerable: true,
127
+ configurable: true,
128
+ writable: true,
129
+ value: void 0
130
+ });
131
+ Object.defineProperty(this, "activeCallbackManager", {
132
+ enumerable: true,
133
+ configurable: true,
134
+ writable: true,
135
+ value: undefined
136
+ });
137
+ this.callbackManager = callbackManager;
138
+ }
139
+ async createChild(config) {
140
+ const child = new CallbackManagerRunTree({
141
+ ...config,
142
+ parent_run: this,
143
+ project_name: this.project_name,
144
+ client: this.client,
145
+ }, this.activeCallbackManager?.getChild() ?? this.callbackManager);
146
+ this.child_runs.push(child);
147
+ return child;
148
+ }
149
+ async postRun() {
150
+ // how it is translated in comparison to basic RunTree?
151
+ this.activeCallbackManager = await this.callbackManager.handleChainStart(typeof this.serialized !== "object" &&
152
+ this.serialized != null &&
153
+ "lc" in this.serialized
154
+ ? this.serialized
155
+ : {
156
+ id: ["langchain", "smith", "CallbackManagerRunTree"],
157
+ lc: 1,
158
+ type: "not_implemented",
159
+ }, this.inputs, this.id, this.run_type, undefined, undefined, this.name);
160
+ }
161
+ async patchRun() {
162
+ if (this.error) {
163
+ await this.activeCallbackManager?.handleChainError(this.error, this.id, this.parent_run?.id, undefined, undefined);
164
+ }
165
+ else {
166
+ await this.activeCallbackManager?.handleChainEnd(this.outputs ?? {}, this.id, this.parent_run?.id, undefined, undefined);
167
+ }
168
+ }
169
+ }
115
170
  class RunnableTraceable extends Runnable {
116
171
  constructor(fields) {
117
172
  super(fields);
@@ -144,12 +199,14 @@ class RunnableTraceable extends Runnable {
144
199
  const partialConfig = "langsmith:traceable" in this.func
145
200
  ? this.func["langsmith:traceable"]
146
201
  : { name: "<lambda>" };
147
- const runTree = new RunTree({
202
+ if (!callbackManager)
203
+ throw new Error("CallbackManager not found");
204
+ const runTree = new CallbackManagerRunTree({
148
205
  ...partialConfig,
149
206
  parent_run: callbackManager?._parentRunId
150
207
  ? new RunTree({ name: "<parent>", id: callbackManager?._parentRunId })
151
208
  : undefined,
152
- });
209
+ }, callbackManager);
153
210
  if (typeof input === "object" &&
154
211
  input != null &&
155
212
  Object.keys(input).length === 1) {
@@ -214,14 +271,14 @@ class PreparedRunEvaluator {
214
271
  const evalConfig = typeof config === "string" ? {} : config;
215
272
  const evaluator = await loadEvaluator(evaluatorType, evalConfig);
216
273
  const feedbackKey = evalConfig?.feedbackKey ?? evaluator?.evaluationName;
217
- if (!feedbackKey) {
218
- throw new Error(`Evaluator of type ${evaluatorType} must have an evaluationName` +
219
- ` or feedbackKey. Please manually provide a feedbackKey in the EvalConfig.`);
220
- }
221
274
  if (!isLLMStringEvaluator(evaluator)) {
222
275
  throw new Error(`Evaluator of type ${evaluatorType} not yet supported. ` +
223
276
  "Please use a string evaluator, or implement your " +
224
- "evaluation logic as a customEvaluator.");
277
+ "evaluation logic as a custom evaluator.");
278
+ }
279
+ if (!feedbackKey) {
280
+ throw new Error(`Evaluator of type ${evaluatorType} must have an evaluationName` +
281
+ ` or feedbackKey. Please manually provide a feedbackKey in the EvalConfig.`);
225
282
  }
226
283
  return new PreparedRunEvaluator(evaluator, feedbackKey, evalConfig?.formatEvaluatorInputs);
227
284
  }
@@ -258,7 +315,7 @@ class PreparedRunEvaluator {
258
315
  }
259
316
  throw new Error("Evaluator not yet supported. " +
260
317
  "Please use a string evaluator, or implement your " +
261
- "evaluation logic as a customEvaluator.");
318
+ "evaluation logic as a custom evaluator.");
262
319
  }
263
320
  }
264
321
  class LoadedEvalConfig {
@@ -299,6 +356,10 @@ const createWrappedModel = async (modelOrFactory) => {
299
356
  return () => modelOrFactory;
300
357
  }
301
358
  if (typeof modelOrFactory === "function") {
359
+ if (isLangsmithTraceableFunction(modelOrFactory)) {
360
+ const wrappedModel = new RunnableTraceable({ func: modelOrFactory });
361
+ return () => wrappedModel;
362
+ }
302
363
  try {
303
364
  // If it works with no arguments, assume it's a factory
304
365
  let res = modelOrFactory();
@@ -310,11 +371,7 @@ const createWrappedModel = async (modelOrFactory) => {
310
371
  }
311
372
  catch (err) {
312
373
  // Otherwise, it's a custom UDF, and we'll wrap
313
- // in a lambda or a traceable function
314
- if (isLangsmithTraceableFunction(modelOrFactory)) {
315
- const wrappedModel = new RunnableTraceable({ func: modelOrFactory });
316
- return () => wrappedModel;
317
- }
374
+ // the function in a lambda
318
375
  const wrappedModel = new RunnableLambda({ func: modelOrFactory });
319
376
  return () => wrappedModel;
320
377
  }
@@ -386,10 +443,65 @@ const getExamplesInputs = (examples, chainOrFactory, dataType) => {
386
443
  }
387
444
  return examples.map(({ inputs }) => inputs);
388
445
  };
446
+ /**
447
+ * Evaluates a given model or chain against a specified LangSmith dataset.
448
+ *
449
+ * This function fetches example records from the specified dataset,
450
+ * runs the model or chain against each example, and returns the evaluation
451
+ * results.
452
+ *
453
+ * @param chainOrFactory - A model or factory/constructor function to be evaluated. It can be a
454
+ * Runnable instance, a factory function that returns a Runnable, or a user-defined
455
+ * function or factory.
456
+ *
457
+ * @param datasetName - The name of the dataset against which the evaluation will be
458
+ * performed. This dataset should already be defined and contain the relevant data
459
+ * for evaluation.
460
+ *
461
+ * @param options - (Optional) Additional parameters for the evaluation process:
462
+ * - `evaluators` (RunEvalType[]): Evaluators to apply to a dataset run.
463
+ * - `formatEvaluatorInputs` (EvaluatorInputFormatter): Convert the evaluation data into formats that can be used by the evaluator.
464
+ * - `projectName` (string): Name of the project for logging and tracking.
465
+ * - `projectMetadata` (Record<string, unknown>): Additional metadata for the project.
466
+ * - `client` (Client): Client instance for LangSmith service interaction.
467
+ * - `maxConcurrency` (number): Maximum concurrency level for dataset processing.
468
+ *
469
+ * @returns A promise that resolves to an `EvalResults` object. This object includes
470
+ * detailed results of the evaluation, such as execution time, run IDs, and feedback
471
+ * for each entry in the dataset.
472
+ *
473
+ * @example
474
+ * ```typescript
475
+ * // Example usage for evaluating a model on a dataset
476
+ * async function evaluateModel() {
477
+ * const chain = /* ...create your model or chain...*\//
478
+ * const datasetName = 'example-dataset';
479
+ * const client = new Client(/* ...config... *\//);
480
+ *
481
+ * const results = await runOnDataset(chain, datasetName, {
482
+ * evaluators: [/* ...evaluators... *\//],
483
+ * client,
484
+ * });
485
+ *
486
+ * console.log('Evaluation Results:', results);
487
+ * }
488
+ *
489
+ * evaluateModel();
490
+ * ```
491
+ * In this example, `runOnDataset` is used to evaluate a language model (or a chain of models) against
492
+ * a dataset named 'example-dataset'. The evaluation process is configured using `RunOnDatasetParams["evaluators"]`, which can
493
+ * include both standard and custom evaluators. The `Client` instance is used to interact with LangChain services.
494
+ * The function returns the evaluation results, which can be logged or further processed as needed.
495
+ */
389
496
  export async function runOnDataset(chainOrFactory, datasetName, options) {
390
- const { evaluationConfig, projectName, projectMetadata, client, maxConcurrency, } = Array.isArray(options)
391
- ? { evaluationConfig: { evaluators: options } }
392
- : options ?? {};
497
+ const { projectName, projectMetadata, client, maxConcurrency, } = options ?? {};
498
+ const evaluationConfig = options?.evaluationConfig ??
499
+ (options?.evaluators != null
500
+ ? {
501
+ evaluators: options.evaluators,
502
+ formatEvaluatorInputs: options.formatEvaluatorInputs,
503
+ }
504
+ : undefined);
393
505
  const wrappedModel = await createWrappedModel(chainOrFactory);
394
506
  const testClient = client ?? new Client();
395
507
  const testProjectName = projectName ?? randomName();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "langchain",
3
- "version": "0.1.19",
3
+ "version": "0.1.20",
4
4
  "description": "Typescript bindings for langchain",
5
5
  "type": "module",
6
6
  "engines": {
@@ -1223,7 +1223,7 @@
1223
1223
  "@gomomento/sdk": "^1.51.1",
1224
1224
  "@gomomento/sdk-core": "^1.51.1",
1225
1225
  "@google-ai/generativelanguage": "^0.2.1",
1226
- "@google-cloud/storage": "^6.10.1",
1226
+ "@google-cloud/storage": "^7.7.0",
1227
1227
  "@jest/globals": "^29.5.0",
1228
1228
  "@langchain/scripts": "~0.0",
1229
1229
  "@notionhq/client": "^2.2.10",
@@ -1310,7 +1310,7 @@
1310
1310
  "@gomomento/sdk-core": "^1.51.1",
1311
1311
  "@gomomento/sdk-web": "^1.51.1",
1312
1312
  "@google-ai/generativelanguage": "^0.2.1",
1313
- "@google-cloud/storage": "^6.10.1",
1313
+ "@google-cloud/storage": "^6.10.1 || ^7.7.0",
1314
1314
  "@notionhq/client": "^2.2.10",
1315
1315
  "@pinecone-database/pinecone": "*",
1316
1316
  "@supabase/supabase-js": "^2.10.0",