@langchain/core 0.3.32 → 0.3.34

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.
@@ -58,12 +58,12 @@ declare abstract class BaseCallbackHandlerMethodsClass {
58
58
  /**
59
59
  * Called if an LLM/ChatModel run encounters an error
60
60
  */
61
- handleLLMError?(err: Error, runId: string, parentRunId?: string, tags?: string[]): // eslint-disable-next-line @typescript-eslint/no-explicit-any
61
+ handleLLMError?(err: Error, runId: string, parentRunId?: string, tags?: string[], extraParams?: Record<string, unknown>): // eslint-disable-next-line @typescript-eslint/no-explicit-any
62
62
  Promise<any> | any;
63
63
  /**
64
64
  * Called at the end of an LLM/ChatModel run, with the output and the run ID.
65
65
  */
66
- handleLLMEnd?(output: LLMResult, runId: string, parentRunId?: string, tags?: string[]): // eslint-disable-next-line @typescript-eslint/no-explicit-any
66
+ handleLLMEnd?(output: LLMResult, runId: string, parentRunId?: string, tags?: string[], extraParams?: Record<string, unknown>): // eslint-disable-next-line @typescript-eslint/no-explicit-any
67
67
  Promise<any> | any;
68
68
  /**
69
69
  * Called at the start of a Chat Model run, with the prompt(s)
@@ -228,11 +228,11 @@ export declare abstract class BaseCallbackHandler extends BaseCallbackHandlerMet
228
228
  /**
229
229
  * Called if an LLM/ChatModel run encounters an error
230
230
  */
231
- handleLLMError?(err: any, runId: string, parentRunId?: string | undefined, tags?: string[] | undefined): any;
231
+ handleLLMError?(err: any, runId: string, parentRunId?: string | undefined, tags?: string[] | undefined, extraParams?: Record<string, unknown> | undefined): any;
232
232
  /**
233
233
  * Called at the end of an LLM/ChatModel run, with the output and the run ID.
234
234
  */
235
- handleLLMEnd?(output: LLMResult, runId: string, parentRunId?: string | undefined, tags?: string[] | undefined): any;
235
+ handleLLMEnd?(output: LLMResult, runId: string, parentRunId?: string | undefined, tags?: string[] | undefined, extraParams?: Record<string, unknown> | undefined): any;
236
236
  /**
237
237
  * Called at the start of a Chat Model run, with the prompt(s)
238
238
  * and the run ID.
@@ -199,11 +199,11 @@ class CallbackManagerForLLMRun extends BaseRunManager {
199
199
  }
200
200
  }, handler.awaitHandlers)));
201
201
  }
202
- async handleLLMError(err) {
202
+ async handleLLMError(err, _runId, _parentRunId, _tags, extraParams) {
203
203
  await Promise.all(this.handlers.map((handler) => (0, promises_js_1.consumeCallback)(async () => {
204
204
  if (!handler.ignoreLLM) {
205
205
  try {
206
- await handler.handleLLMError?.(err, this.runId, this._parentRunId, this.tags);
206
+ await handler.handleLLMError?.(err, this.runId, this._parentRunId, this.tags, extraParams);
207
207
  }
208
208
  catch (err) {
209
209
  const logFunction = handler.raiseError
@@ -217,11 +217,11 @@ class CallbackManagerForLLMRun extends BaseRunManager {
217
217
  }
218
218
  }, handler.awaitHandlers)));
219
219
  }
220
- async handleLLMEnd(output) {
220
+ async handleLLMEnd(output, _runId, _parentRunId, _tags, extraParams) {
221
221
  await Promise.all(this.handlers.map((handler) => (0, promises_js_1.consumeCallback)(async () => {
222
222
  if (!handler.ignoreLLM) {
223
223
  try {
224
- await handler.handleLLMEnd?.(output, this.runId, this._parentRunId, this.tags);
224
+ await handler.handleLLMEnd?.(output, this.runId, this._parentRunId, this.tags, extraParams);
225
225
  }
226
226
  catch (err) {
227
227
  const logFunction = handler.raiseError
@@ -77,8 +77,8 @@ export declare class CallbackManagerForRetrieverRun extends BaseRunManager imple
77
77
  }
78
78
  export declare class CallbackManagerForLLMRun extends BaseRunManager implements BaseCallbackManagerMethods {
79
79
  handleLLMNewToken(token: string, idx?: NewTokenIndices, _runId?: string, _parentRunId?: string, _tags?: string[], fields?: HandleLLMNewTokenCallbackFields): Promise<void>;
80
- handleLLMError(err: Error | unknown): Promise<void>;
81
- handleLLMEnd(output: LLMResult): Promise<void>;
80
+ handleLLMError(err: Error | unknown, _runId?: string, _parentRunId?: string, _tags?: string[], extraParams?: Record<string, unknown>): Promise<void>;
81
+ handleLLMEnd(output: LLMResult, _runId?: string, _parentRunId?: string, _tags?: string[], extraParams?: Record<string, unknown>): Promise<void>;
82
82
  }
83
83
  export declare class CallbackManagerForChainRun extends BaseRunManager implements BaseCallbackManagerMethods {
84
84
  getChild(tag?: string): CallbackManager;
@@ -192,11 +192,11 @@ export class CallbackManagerForLLMRun extends BaseRunManager {
192
192
  }
193
193
  }, handler.awaitHandlers)));
194
194
  }
195
- async handleLLMError(err) {
195
+ async handleLLMError(err, _runId, _parentRunId, _tags, extraParams) {
196
196
  await Promise.all(this.handlers.map((handler) => consumeCallback(async () => {
197
197
  if (!handler.ignoreLLM) {
198
198
  try {
199
- await handler.handleLLMError?.(err, this.runId, this._parentRunId, this.tags);
199
+ await handler.handleLLMError?.(err, this.runId, this._parentRunId, this.tags, extraParams);
200
200
  }
201
201
  catch (err) {
202
202
  const logFunction = handler.raiseError
@@ -210,11 +210,11 @@ export class CallbackManagerForLLMRun extends BaseRunManager {
210
210
  }
211
211
  }, handler.awaitHandlers)));
212
212
  }
213
- async handleLLMEnd(output) {
213
+ async handleLLMEnd(output, _runId, _parentRunId, _tags, extraParams) {
214
214
  await Promise.all(this.handlers.map((handler) => consumeCallback(async () => {
215
215
  if (!handler.ignoreLLM) {
216
216
  try {
217
- await handler.handleLLMEnd?.(output, this.runId, this._parentRunId, this.tags);
217
+ await handler.handleLLMEnd?.(output, this.runId, this._parentRunId, this.tags, extraParams);
218
218
  }
219
219
  catch (err) {
220
220
  const logFunction = handler.raiseError
@@ -148,20 +148,27 @@ class BaseChatModel extends base_js_1.BaseLanguageModel {
148
148
  };
149
149
  }
150
150
  /** @ignore */
151
- async _generateUncached(messages, parsedOptions, handledOptions) {
151
+ async _generateUncached(messages, parsedOptions, handledOptions, startedRunManagers) {
152
152
  const baseMessages = messages.map((messageList) => messageList.map(index_js_1.coerceMessageLikeToMessage));
153
- const inheritableMetadata = {
154
- ...handledOptions.metadata,
155
- ...this.getLsParams(parsedOptions),
156
- };
157
- // create callback manager and start run
158
- const callbackManager_ = await manager_js_1.CallbackManager.configure(handledOptions.callbacks, this.callbacks, handledOptions.tags, this.tags, inheritableMetadata, this.metadata, { verbose: this.verbose });
159
- const extra = {
160
- options: parsedOptions,
161
- invocation_params: this?.invocationParams(parsedOptions),
162
- batch_size: 1,
163
- };
164
- const runManagers = await callbackManager_?.handleChatModelStart(this.toJSON(), baseMessages, handledOptions.runId, undefined, extra, undefined, undefined, handledOptions.runName);
153
+ let runManagers;
154
+ if (startedRunManagers !== undefined &&
155
+ startedRunManagers.length === baseMessages.length) {
156
+ runManagers = startedRunManagers;
157
+ }
158
+ else {
159
+ const inheritableMetadata = {
160
+ ...handledOptions.metadata,
161
+ ...this.getLsParams(parsedOptions),
162
+ };
163
+ // create callback manager and start run
164
+ const callbackManager_ = await manager_js_1.CallbackManager.configure(handledOptions.callbacks, this.callbacks, handledOptions.tags, this.tags, inheritableMetadata, this.metadata, { verbose: this.verbose });
165
+ const extra = {
166
+ options: parsedOptions,
167
+ invocation_params: this?.invocationParams(parsedOptions),
168
+ batch_size: 1,
169
+ };
170
+ runManagers = await callbackManager_?.handleChatModelStart(this.toJSON(), baseMessages, handledOptions.runId, undefined, extra, undefined, undefined, handledOptions.runName);
171
+ }
165
172
  const generations = [];
166
173
  const llmOutputs = [];
167
174
  // Even if stream is not explicitly called, check if model is implicitly
@@ -169,6 +176,7 @@ class BaseChatModel extends base_js_1.BaseLanguageModel {
169
176
  // Bail out if _streamResponseChunks not overridden
170
177
  const hasStreamingHandler = !!runManagers?.[0].handlers.find(base_js_3.callbackHandlerPrefersStreaming);
171
178
  if (hasStreamingHandler &&
179
+ !this.disableStreaming &&
172
180
  baseMessages.length === 1 &&
173
181
  this._streamResponseChunks !==
174
182
  BaseChatModel.prototype._streamResponseChunks) {
@@ -279,7 +287,6 @@ class BaseChatModel extends base_js_1.BaseLanguageModel {
279
287
  options: parsedOptions,
280
288
  invocation_params: this?.invocationParams(parsedOptions),
281
289
  batch_size: 1,
282
- cached: true,
283
290
  };
284
291
  const runManagers = await callbackManager_?.handleChatModelStart(this.toJSON(), baseMessages, handledOptions.runId, undefined, extra, undefined, undefined, handledOptions.runName);
285
292
  // generate results
@@ -304,23 +311,45 @@ class BaseChatModel extends base_js_1.BaseLanguageModel {
304
311
  await Promise.all(cachedResults.map(async ({ result: promiseResult, runManager }, i) => {
305
312
  if (promiseResult.status === "fulfilled") {
306
313
  const result = promiseResult.value;
307
- generations[i] = result;
314
+ generations[i] = result.map((result) => {
315
+ if ("message" in result &&
316
+ (0, index_js_1.isBaseMessage)(result.message) &&
317
+ (0, index_js_1.isAIMessage)(result.message)) {
318
+ // eslint-disable-next-line no-param-reassign
319
+ result.message.usage_metadata = {
320
+ input_tokens: 0,
321
+ output_tokens: 0,
322
+ total_tokens: 0,
323
+ };
324
+ }
325
+ // eslint-disable-next-line no-param-reassign
326
+ result.generationInfo = {
327
+ ...result.generationInfo,
328
+ tokenUsage: {},
329
+ };
330
+ return result;
331
+ });
308
332
  if (result.length) {
309
333
  await runManager?.handleLLMNewToken(result[0].text);
310
334
  }
311
335
  return runManager?.handleLLMEnd({
312
336
  generations: [result],
337
+ }, undefined, undefined, undefined, {
338
+ cached: true,
313
339
  });
314
340
  }
315
341
  else {
316
342
  // status === "rejected"
317
- await runManager?.handleLLMError(promiseResult.reason);
343
+ await runManager?.handleLLMError(promiseResult.reason, undefined, undefined, undefined, {
344
+ cached: true,
345
+ });
318
346
  return Promise.reject(promiseResult.reason);
319
347
  }
320
348
  }));
321
349
  const output = {
322
350
  generations,
323
351
  missingPromptIndices,
352
+ startedRunManagers: runManagers,
324
353
  };
325
354
  // This defines RUN_KEY as a non-enumerable property on the output object
326
355
  // so that it is not serialized when the output is stringified, and so that
@@ -357,7 +386,7 @@ class BaseChatModel extends base_js_1.BaseLanguageModel {
357
386
  }
358
387
  const { cache } = this;
359
388
  const llmStringKey = this._getSerializedCacheKeyParametersForCall(callOptions);
360
- const { generations, missingPromptIndices } = await this._generateCached({
389
+ const { generations, missingPromptIndices, startedRunManagers } = await this._generateCached({
361
390
  messages: baseMessages,
362
391
  cache,
363
392
  llmStringKey,
@@ -366,7 +395,9 @@ class BaseChatModel extends base_js_1.BaseLanguageModel {
366
395
  });
367
396
  let llmOutput = {};
368
397
  if (missingPromptIndices.length > 0) {
369
- const results = await this._generateUncached(missingPromptIndices.map((i) => baseMessages[i]), callOptions, runnableConfig);
398
+ const results = await this._generateUncached(missingPromptIndices.map((i) => baseMessages[i]), callOptions, runnableConfig, startedRunManagers !== undefined
399
+ ? missingPromptIndices.map((i) => startedRunManagers?.[i])
400
+ : undefined);
370
401
  await Promise.all(results.generations.map(async (generation, index) => {
371
402
  const promptIndex = missingPromptIndices[index];
372
403
  generations[promptIndex] = generation;
@@ -104,7 +104,7 @@ export declare abstract class BaseChatModel<CallOptions extends BaseChatModelCal
104
104
  _streamIterator(input: BaseLanguageModelInput, options?: CallOptions): AsyncGenerator<OutputMessageType>;
105
105
  getLsParams(options: this["ParsedCallOptions"]): LangSmithParams;
106
106
  /** @ignore */
107
- _generateUncached(messages: BaseMessageLike[][], parsedOptions: this["ParsedCallOptions"], handledOptions: RunnableConfig): Promise<LLMResult>;
107
+ _generateUncached(messages: BaseMessageLike[][], parsedOptions: this["ParsedCallOptions"], handledOptions: RunnableConfig, startedRunManagers?: CallbackManagerForLLMRun[]): Promise<LLMResult>;
108
108
  _generateCached({ messages, cache, llmStringKey, parsedOptions, handledOptions, }: {
109
109
  messages: BaseMessageLike[][];
110
110
  cache: BaseCache<Generation[]>;
@@ -113,6 +113,7 @@ export declare abstract class BaseChatModel<CallOptions extends BaseChatModelCal
113
113
  handledOptions: RunnableConfig;
114
114
  }): Promise<LLMResult & {
115
115
  missingPromptIndices: number[];
116
+ startedRunManagers?: CallbackManagerForLLMRun[];
116
117
  }>;
117
118
  /**
118
119
  * Generates chat based on the input messages.
@@ -1,5 +1,5 @@
1
1
  import { zodToJsonSchema } from "zod-to-json-schema";
2
- import { AIMessage, HumanMessage, coerceMessageLikeToMessage, isAIMessageChunk, } from "../messages/index.js";
2
+ import { AIMessage, HumanMessage, coerceMessageLikeToMessage, isAIMessageChunk, isBaseMessage, isAIMessage, } from "../messages/index.js";
3
3
  import { RUN_KEY, } from "../outputs.js";
4
4
  import { BaseLanguageModel, } from "./base.js";
5
5
  import { CallbackManager, } from "../callbacks/manager.js";
@@ -144,20 +144,27 @@ export class BaseChatModel extends BaseLanguageModel {
144
144
  };
145
145
  }
146
146
  /** @ignore */
147
- async _generateUncached(messages, parsedOptions, handledOptions) {
147
+ async _generateUncached(messages, parsedOptions, handledOptions, startedRunManagers) {
148
148
  const baseMessages = messages.map((messageList) => messageList.map(coerceMessageLikeToMessage));
149
- const inheritableMetadata = {
150
- ...handledOptions.metadata,
151
- ...this.getLsParams(parsedOptions),
152
- };
153
- // create callback manager and start run
154
- const callbackManager_ = await CallbackManager.configure(handledOptions.callbacks, this.callbacks, handledOptions.tags, this.tags, inheritableMetadata, this.metadata, { verbose: this.verbose });
155
- const extra = {
156
- options: parsedOptions,
157
- invocation_params: this?.invocationParams(parsedOptions),
158
- batch_size: 1,
159
- };
160
- const runManagers = await callbackManager_?.handleChatModelStart(this.toJSON(), baseMessages, handledOptions.runId, undefined, extra, undefined, undefined, handledOptions.runName);
149
+ let runManagers;
150
+ if (startedRunManagers !== undefined &&
151
+ startedRunManagers.length === baseMessages.length) {
152
+ runManagers = startedRunManagers;
153
+ }
154
+ else {
155
+ const inheritableMetadata = {
156
+ ...handledOptions.metadata,
157
+ ...this.getLsParams(parsedOptions),
158
+ };
159
+ // create callback manager and start run
160
+ const callbackManager_ = await CallbackManager.configure(handledOptions.callbacks, this.callbacks, handledOptions.tags, this.tags, inheritableMetadata, this.metadata, { verbose: this.verbose });
161
+ const extra = {
162
+ options: parsedOptions,
163
+ invocation_params: this?.invocationParams(parsedOptions),
164
+ batch_size: 1,
165
+ };
166
+ runManagers = await callbackManager_?.handleChatModelStart(this.toJSON(), baseMessages, handledOptions.runId, undefined, extra, undefined, undefined, handledOptions.runName);
167
+ }
161
168
  const generations = [];
162
169
  const llmOutputs = [];
163
170
  // Even if stream is not explicitly called, check if model is implicitly
@@ -165,6 +172,7 @@ export class BaseChatModel extends BaseLanguageModel {
165
172
  // Bail out if _streamResponseChunks not overridden
166
173
  const hasStreamingHandler = !!runManagers?.[0].handlers.find(callbackHandlerPrefersStreaming);
167
174
  if (hasStreamingHandler &&
175
+ !this.disableStreaming &&
168
176
  baseMessages.length === 1 &&
169
177
  this._streamResponseChunks !==
170
178
  BaseChatModel.prototype._streamResponseChunks) {
@@ -275,7 +283,6 @@ export class BaseChatModel extends BaseLanguageModel {
275
283
  options: parsedOptions,
276
284
  invocation_params: this?.invocationParams(parsedOptions),
277
285
  batch_size: 1,
278
- cached: true,
279
286
  };
280
287
  const runManagers = await callbackManager_?.handleChatModelStart(this.toJSON(), baseMessages, handledOptions.runId, undefined, extra, undefined, undefined, handledOptions.runName);
281
288
  // generate results
@@ -300,23 +307,45 @@ export class BaseChatModel extends BaseLanguageModel {
300
307
  await Promise.all(cachedResults.map(async ({ result: promiseResult, runManager }, i) => {
301
308
  if (promiseResult.status === "fulfilled") {
302
309
  const result = promiseResult.value;
303
- generations[i] = result;
310
+ generations[i] = result.map((result) => {
311
+ if ("message" in result &&
312
+ isBaseMessage(result.message) &&
313
+ isAIMessage(result.message)) {
314
+ // eslint-disable-next-line no-param-reassign
315
+ result.message.usage_metadata = {
316
+ input_tokens: 0,
317
+ output_tokens: 0,
318
+ total_tokens: 0,
319
+ };
320
+ }
321
+ // eslint-disable-next-line no-param-reassign
322
+ result.generationInfo = {
323
+ ...result.generationInfo,
324
+ tokenUsage: {},
325
+ };
326
+ return result;
327
+ });
304
328
  if (result.length) {
305
329
  await runManager?.handleLLMNewToken(result[0].text);
306
330
  }
307
331
  return runManager?.handleLLMEnd({
308
332
  generations: [result],
333
+ }, undefined, undefined, undefined, {
334
+ cached: true,
309
335
  });
310
336
  }
311
337
  else {
312
338
  // status === "rejected"
313
- await runManager?.handleLLMError(promiseResult.reason);
339
+ await runManager?.handleLLMError(promiseResult.reason, undefined, undefined, undefined, {
340
+ cached: true,
341
+ });
314
342
  return Promise.reject(promiseResult.reason);
315
343
  }
316
344
  }));
317
345
  const output = {
318
346
  generations,
319
347
  missingPromptIndices,
348
+ startedRunManagers: runManagers,
320
349
  };
321
350
  // This defines RUN_KEY as a non-enumerable property on the output object
322
351
  // so that it is not serialized when the output is stringified, and so that
@@ -353,7 +382,7 @@ export class BaseChatModel extends BaseLanguageModel {
353
382
  }
354
383
  const { cache } = this;
355
384
  const llmStringKey = this._getSerializedCacheKeyParametersForCall(callOptions);
356
- const { generations, missingPromptIndices } = await this._generateCached({
385
+ const { generations, missingPromptIndices, startedRunManagers } = await this._generateCached({
357
386
  messages: baseMessages,
358
387
  cache,
359
388
  llmStringKey,
@@ -362,7 +391,9 @@ export class BaseChatModel extends BaseLanguageModel {
362
391
  });
363
392
  let llmOutput = {};
364
393
  if (missingPromptIndices.length > 0) {
365
- const results = await this._generateUncached(missingPromptIndices.map((i) => baseMessages[i]), callOptions, runnableConfig);
394
+ const results = await this._generateUncached(missingPromptIndices.map((i) => baseMessages[i]), callOptions, runnableConfig, startedRunManagers !== undefined
395
+ ? missingPromptIndices.map((i) => startedRunManagers?.[i])
396
+ : undefined);
366
397
  await Promise.all(results.generations.map(async (generation, index) => {
367
398
  const promptIndex = missingPromptIndices[index];
368
399
  generations[promptIndex] = generation;
@@ -126,14 +126,21 @@ class BaseLLM extends base_js_1.BaseLanguageModel {
126
126
  return llmResults;
127
127
  }
128
128
  /** @ignore */
129
- async _generateUncached(prompts, parsedOptions, handledOptions) {
130
- const callbackManager_ = await manager_js_1.CallbackManager.configure(handledOptions.callbacks, this.callbacks, handledOptions.tags, this.tags, handledOptions.metadata, this.metadata, { verbose: this.verbose });
131
- const extra = {
132
- options: parsedOptions,
133
- invocation_params: this?.invocationParams(parsedOptions),
134
- batch_size: prompts.length,
135
- };
136
- const runManagers = await callbackManager_?.handleLLMStart(this.toJSON(), prompts, handledOptions.runId, undefined, extra, undefined, undefined, handledOptions?.runName);
129
+ async _generateUncached(prompts, parsedOptions, handledOptions, startedRunManagers) {
130
+ let runManagers;
131
+ if (startedRunManagers !== undefined &&
132
+ startedRunManagers.length === prompts.length) {
133
+ runManagers = startedRunManagers;
134
+ }
135
+ else {
136
+ const callbackManager_ = await manager_js_1.CallbackManager.configure(handledOptions.callbacks, this.callbacks, handledOptions.tags, this.tags, handledOptions.metadata, this.metadata, { verbose: this.verbose });
137
+ const extra = {
138
+ options: parsedOptions,
139
+ invocation_params: this?.invocationParams(parsedOptions),
140
+ batch_size: prompts.length,
141
+ };
142
+ runManagers = await callbackManager_?.handleLLMStart(this.toJSON(), prompts, handledOptions.runId, undefined, extra, undefined, undefined, handledOptions?.runName);
143
+ }
137
144
  // Even if stream is not explicitly called, check if model is implicitly
138
145
  // called from streamEvents() or streamLog() to get all streamed events.
139
146
  // Bail out if _streamResponseChunks not overridden
@@ -191,7 +198,6 @@ class BaseLLM extends base_js_1.BaseLanguageModel {
191
198
  options: parsedOptions,
192
199
  invocation_params: this?.invocationParams(parsedOptions),
193
200
  batch_size: prompts.length,
194
- cached: true,
195
201
  };
196
202
  const runManagers = await callbackManager_?.handleLLMStart(this.toJSON(), prompts, runId, undefined, extra, undefined, undefined, handledOptions?.runName);
197
203
  // generate results
@@ -214,23 +220,35 @@ class BaseLLM extends base_js_1.BaseLanguageModel {
214
220
  await Promise.all(cachedResults.map(async ({ result: promiseResult, runManager }, i) => {
215
221
  if (promiseResult.status === "fulfilled") {
216
222
  const result = promiseResult.value;
217
- generations[i] = result;
223
+ generations[i] = result.map((result) => {
224
+ // eslint-disable-next-line no-param-reassign
225
+ result.generationInfo = {
226
+ ...result.generationInfo,
227
+ tokenUsage: {},
228
+ };
229
+ return result;
230
+ });
218
231
  if (result.length) {
219
232
  await runManager?.handleLLMNewToken(result[0].text);
220
233
  }
221
234
  return runManager?.handleLLMEnd({
222
235
  generations: [result],
236
+ }, undefined, undefined, undefined, {
237
+ cached: true,
223
238
  });
224
239
  }
225
240
  else {
226
241
  // status === "rejected"
227
- await runManager?.handleLLMError(promiseResult.reason);
242
+ await runManager?.handleLLMError(promiseResult.reason, undefined, undefined, undefined, {
243
+ cached: true,
244
+ });
228
245
  return Promise.reject(promiseResult.reason);
229
246
  }
230
247
  }));
231
248
  const output = {
232
249
  generations,
233
250
  missingPromptIndices,
251
+ startedRunManagers: runManagers,
234
252
  };
235
253
  // This defines RUN_KEY as a non-enumerable property on the output object
236
254
  // so that it is not serialized when the output is stringified, and so that
@@ -264,7 +282,7 @@ class BaseLLM extends base_js_1.BaseLanguageModel {
264
282
  }
265
283
  const { cache } = this;
266
284
  const llmStringKey = this._getSerializedCacheKeyParametersForCall(callOptions);
267
- const { generations, missingPromptIndices } = await this._generateCached({
285
+ const { generations, missingPromptIndices, startedRunManagers } = await this._generateCached({
268
286
  prompts,
269
287
  cache,
270
288
  llmStringKey,
@@ -274,7 +292,9 @@ class BaseLLM extends base_js_1.BaseLanguageModel {
274
292
  });
275
293
  let llmOutput = {};
276
294
  if (missingPromptIndices.length > 0) {
277
- const results = await this._generateUncached(missingPromptIndices.map((i) => prompts[i]), callOptions, runnableConfig);
295
+ const results = await this._generateUncached(missingPromptIndices.map((i) => prompts[i]), callOptions, runnableConfig, startedRunManagers !== undefined
296
+ ? missingPromptIndices.map((i) => startedRunManagers?.[i])
297
+ : undefined);
278
298
  await Promise.all(results.generations.map(async (generation, index) => {
279
299
  const promptIndex = missingPromptIndices[index];
280
300
  generations[promptIndex] = generation;
@@ -55,7 +55,7 @@ export declare abstract class BaseLLM<CallOptions extends BaseLLMCallOptions = B
55
55
  invocationParams(_options?: this["ParsedCallOptions"]): any;
56
56
  _flattenLLMResult(llmResult: LLMResult): LLMResult[];
57
57
  /** @ignore */
58
- _generateUncached(prompts: string[], parsedOptions: this["ParsedCallOptions"], handledOptions: BaseCallbackConfig): Promise<LLMResult>;
58
+ _generateUncached(prompts: string[], parsedOptions: this["ParsedCallOptions"], handledOptions: BaseCallbackConfig, startedRunManagers?: CallbackManagerForLLMRun[]): Promise<LLMResult>;
59
59
  _generateCached({ prompts, cache, llmStringKey, parsedOptions, handledOptions, runId, }: {
60
60
  prompts: string[];
61
61
  cache: BaseCache<Generation[]>;
@@ -65,6 +65,7 @@ export declare abstract class BaseLLM<CallOptions extends BaseLLMCallOptions = B
65
65
  runId?: string;
66
66
  }): Promise<LLMResult & {
67
67
  missingPromptIndices: number[];
68
+ startedRunManagers?: CallbackManagerForLLMRun[];
68
69
  }>;
69
70
  /**
70
71
  * Run the LLM on the given prompts and input, handling caching.
@@ -123,14 +123,21 @@ export class BaseLLM extends BaseLanguageModel {
123
123
  return llmResults;
124
124
  }
125
125
  /** @ignore */
126
- async _generateUncached(prompts, parsedOptions, handledOptions) {
127
- const callbackManager_ = await CallbackManager.configure(handledOptions.callbacks, this.callbacks, handledOptions.tags, this.tags, handledOptions.metadata, this.metadata, { verbose: this.verbose });
128
- const extra = {
129
- options: parsedOptions,
130
- invocation_params: this?.invocationParams(parsedOptions),
131
- batch_size: prompts.length,
132
- };
133
- const runManagers = await callbackManager_?.handleLLMStart(this.toJSON(), prompts, handledOptions.runId, undefined, extra, undefined, undefined, handledOptions?.runName);
126
+ async _generateUncached(prompts, parsedOptions, handledOptions, startedRunManagers) {
127
+ let runManagers;
128
+ if (startedRunManagers !== undefined &&
129
+ startedRunManagers.length === prompts.length) {
130
+ runManagers = startedRunManagers;
131
+ }
132
+ else {
133
+ const callbackManager_ = await CallbackManager.configure(handledOptions.callbacks, this.callbacks, handledOptions.tags, this.tags, handledOptions.metadata, this.metadata, { verbose: this.verbose });
134
+ const extra = {
135
+ options: parsedOptions,
136
+ invocation_params: this?.invocationParams(parsedOptions),
137
+ batch_size: prompts.length,
138
+ };
139
+ runManagers = await callbackManager_?.handleLLMStart(this.toJSON(), prompts, handledOptions.runId, undefined, extra, undefined, undefined, handledOptions?.runName);
140
+ }
134
141
  // Even if stream is not explicitly called, check if model is implicitly
135
142
  // called from streamEvents() or streamLog() to get all streamed events.
136
143
  // Bail out if _streamResponseChunks not overridden
@@ -188,7 +195,6 @@ export class BaseLLM extends BaseLanguageModel {
188
195
  options: parsedOptions,
189
196
  invocation_params: this?.invocationParams(parsedOptions),
190
197
  batch_size: prompts.length,
191
- cached: true,
192
198
  };
193
199
  const runManagers = await callbackManager_?.handleLLMStart(this.toJSON(), prompts, runId, undefined, extra, undefined, undefined, handledOptions?.runName);
194
200
  // generate results
@@ -211,23 +217,35 @@ export class BaseLLM extends BaseLanguageModel {
211
217
  await Promise.all(cachedResults.map(async ({ result: promiseResult, runManager }, i) => {
212
218
  if (promiseResult.status === "fulfilled") {
213
219
  const result = promiseResult.value;
214
- generations[i] = result;
220
+ generations[i] = result.map((result) => {
221
+ // eslint-disable-next-line no-param-reassign
222
+ result.generationInfo = {
223
+ ...result.generationInfo,
224
+ tokenUsage: {},
225
+ };
226
+ return result;
227
+ });
215
228
  if (result.length) {
216
229
  await runManager?.handleLLMNewToken(result[0].text);
217
230
  }
218
231
  return runManager?.handleLLMEnd({
219
232
  generations: [result],
233
+ }, undefined, undefined, undefined, {
234
+ cached: true,
220
235
  });
221
236
  }
222
237
  else {
223
238
  // status === "rejected"
224
- await runManager?.handleLLMError(promiseResult.reason);
239
+ await runManager?.handleLLMError(promiseResult.reason, undefined, undefined, undefined, {
240
+ cached: true,
241
+ });
225
242
  return Promise.reject(promiseResult.reason);
226
243
  }
227
244
  }));
228
245
  const output = {
229
246
  generations,
230
247
  missingPromptIndices,
248
+ startedRunManagers: runManagers,
231
249
  };
232
250
  // This defines RUN_KEY as a non-enumerable property on the output object
233
251
  // so that it is not serialized when the output is stringified, and so that
@@ -261,7 +279,7 @@ export class BaseLLM extends BaseLanguageModel {
261
279
  }
262
280
  const { cache } = this;
263
281
  const llmStringKey = this._getSerializedCacheKeyParametersForCall(callOptions);
264
- const { generations, missingPromptIndices } = await this._generateCached({
282
+ const { generations, missingPromptIndices, startedRunManagers } = await this._generateCached({
265
283
  prompts,
266
284
  cache,
267
285
  llmStringKey,
@@ -271,7 +289,9 @@ export class BaseLLM extends BaseLanguageModel {
271
289
  });
272
290
  let llmOutput = {};
273
291
  if (missingPromptIndices.length > 0) {
274
- const results = await this._generateUncached(missingPromptIndices.map((i) => prompts[i]), callOptions, runnableConfig);
292
+ const results = await this._generateUncached(missingPromptIndices.map((i) => prompts[i]), callOptions, runnableConfig, startedRunManagers !== undefined
293
+ ? missingPromptIndices.map((i) => startedRunManagers?.[i])
294
+ : undefined);
275
295
  await Promise.all(results.generations.map(async (generation, index) => {
276
296
  const promptIndex = missingPromptIndices[index];
277
297
  generations[promptIndex] = generation;
@@ -503,13 +503,20 @@ function _coerceMessagePromptTemplateLike(messagePromptTemplateLike, extra) {
503
503
  if (Array.isArray(messagePromptTemplateLike) &&
504
504
  messagePromptTemplateLike[0] === "placeholder") {
505
505
  const messageContent = messagePromptTemplateLike[1];
506
- if (typeof messageContent !== "string" ||
507
- messageContent[0] !== "{" ||
508
- messageContent[messageContent.length - 1] !== "}") {
509
- throw new Error(`Invalid placeholder template: "${messagePromptTemplateLike[1]}". Expected a variable name surrounded by curly braces.`);
506
+ if (extra?.templateFormat === "mustache" &&
507
+ typeof messageContent === "string" &&
508
+ messageContent.slice(0, 2) === "{{" &&
509
+ messageContent.slice(-2) === "}}") {
510
+ const variableName = messageContent.slice(2, -2);
511
+ return new MessagesPlaceholder({ variableName, optional: true });
510
512
  }
511
- const variableName = messageContent.slice(1, -1);
512
- return new MessagesPlaceholder({ variableName, optional: true });
513
+ else if (typeof messageContent === "string" &&
514
+ messageContent[0] === "{" &&
515
+ messageContent[messageContent.length - 1] === "}") {
516
+ const variableName = messageContent.slice(1, -1);
517
+ return new MessagesPlaceholder({ variableName, optional: true });
518
+ }
519
+ throw new Error(`Invalid placeholder template for format ${extra?.templateFormat ?? `"f-string"`}: "${messagePromptTemplateLike[1]}". Expected a variable name surrounded by ${extra?.templateFormat === "mustache" ? "double" : "single"} curly braces.`);
513
520
  }
514
521
  const message = (0, index_js_1.coerceMessageLikeToMessage)(messagePromptTemplateLike);
515
522
  let templateData;
@@ -492,13 +492,20 @@ function _coerceMessagePromptTemplateLike(messagePromptTemplateLike, extra) {
492
492
  if (Array.isArray(messagePromptTemplateLike) &&
493
493
  messagePromptTemplateLike[0] === "placeholder") {
494
494
  const messageContent = messagePromptTemplateLike[1];
495
- if (typeof messageContent !== "string" ||
496
- messageContent[0] !== "{" ||
497
- messageContent[messageContent.length - 1] !== "}") {
498
- throw new Error(`Invalid placeholder template: "${messagePromptTemplateLike[1]}". Expected a variable name surrounded by curly braces.`);
495
+ if (extra?.templateFormat === "mustache" &&
496
+ typeof messageContent === "string" &&
497
+ messageContent.slice(0, 2) === "{{" &&
498
+ messageContent.slice(-2) === "}}") {
499
+ const variableName = messageContent.slice(2, -2);
500
+ return new MessagesPlaceholder({ variableName, optional: true });
499
501
  }
500
- const variableName = messageContent.slice(1, -1);
501
- return new MessagesPlaceholder({ variableName, optional: true });
502
+ else if (typeof messageContent === "string" &&
503
+ messageContent[0] === "{" &&
504
+ messageContent[messageContent.length - 1] === "}") {
505
+ const variableName = messageContent.slice(1, -1);
506
+ return new MessagesPlaceholder({ variableName, optional: true });
507
+ }
508
+ throw new Error(`Invalid placeholder template for format ${extra?.templateFormat ?? `"f-string"`}: "${messagePromptTemplateLike[1]}". Expected a variable name surrounded by ${extra?.templateFormat === "mustache" ? "double" : "single"} curly braces.`);
502
509
  }
503
510
  const message = coerceMessageLikeToMessage(messagePromptTemplateLike);
504
511
  let templateData;
@@ -178,7 +178,7 @@ class BaseTracer extends base_js_1.BaseCallbackHandler {
178
178
  await this.onLLMStart?.(run);
179
179
  return run;
180
180
  }
181
- async handleLLMEnd(output, runId) {
181
+ async handleLLMEnd(output, runId, _parentRunId, _tags, extraParams) {
182
182
  const run = this.runMap.get(runId);
183
183
  if (!run || run?.run_type !== "llm") {
184
184
  throw new Error("No LLM run to end.");
@@ -189,11 +189,12 @@ class BaseTracer extends base_js_1.BaseCallbackHandler {
189
189
  name: "end",
190
190
  time: new Date(run.end_time).toISOString(),
191
191
  });
192
+ run.extra = { ...run.extra, ...extraParams };
192
193
  await this.onLLMEnd?.(run);
193
194
  await this._endTrace(run);
194
195
  return run;
195
196
  }
196
- async handleLLMError(error, runId) {
197
+ async handleLLMError(error, runId, _parentRunId, _tags, extraParams) {
197
198
  const run = this.runMap.get(runId);
198
199
  if (!run || run?.run_type !== "llm") {
199
200
  throw new Error("No LLM run to end.");
@@ -204,6 +205,7 @@ class BaseTracer extends base_js_1.BaseCallbackHandler {
204
205
  name: "error",
205
206
  time: new Date(run.end_time).toISOString(),
206
207
  });
208
+ run.extra = { ...run.extra, ...extraParams };
207
209
  await this.onLLMError?.(run);
208
210
  await this._endTrace(run);
209
211
  return run;
@@ -124,8 +124,8 @@ export declare abstract class BaseTracer extends BaseCallbackHandler {
124
124
  attachments?: import("langsmith/schemas").Attachments | undefined;
125
125
  };
126
126
  handleChatModelStart(llm: Serialized, messages: BaseMessage[][], runId: string, parentRunId?: string, extraParams?: KVMap, tags?: string[], metadata?: KVMap, name?: string): Promise<Run>;
127
- handleLLMEnd(output: LLMResult, runId: string): Promise<Run>;
128
- handleLLMError(error: unknown, runId: string): Promise<Run>;
127
+ handleLLMEnd(output: LLMResult, runId: string, _parentRunId?: string, _tags?: string[], extraParams?: Record<string, unknown>): Promise<Run>;
128
+ handleLLMError(error: unknown, runId: string, _parentRunId?: string, _tags?: string[], extraParams?: Record<string, unknown>): Promise<Run>;
129
129
  /**
130
130
  * Create and add a run to the run map for chain start events.
131
131
  * This must sometimes be done synchronously to avoid race conditions
@@ -174,7 +174,7 @@ export class BaseTracer extends BaseCallbackHandler {
174
174
  await this.onLLMStart?.(run);
175
175
  return run;
176
176
  }
177
- async handleLLMEnd(output, runId) {
177
+ async handleLLMEnd(output, runId, _parentRunId, _tags, extraParams) {
178
178
  const run = this.runMap.get(runId);
179
179
  if (!run || run?.run_type !== "llm") {
180
180
  throw new Error("No LLM run to end.");
@@ -185,11 +185,12 @@ export class BaseTracer extends BaseCallbackHandler {
185
185
  name: "end",
186
186
  time: new Date(run.end_time).toISOString(),
187
187
  });
188
+ run.extra = { ...run.extra, ...extraParams };
188
189
  await this.onLLMEnd?.(run);
189
190
  await this._endTrace(run);
190
191
  return run;
191
192
  }
192
- async handleLLMError(error, runId) {
193
+ async handleLLMError(error, runId, _parentRunId, _tags, extraParams) {
193
194
  const run = this.runMap.get(runId);
194
195
  if (!run || run?.run_type !== "llm") {
195
196
  throw new Error("No LLM run to end.");
@@ -200,6 +201,7 @@ export class BaseTracer extends BaseCallbackHandler {
200
201
  name: "error",
201
202
  time: new Date(run.end_time).toISOString(),
202
203
  });
204
+ run.extra = { ...run.extra, ...extraParams };
203
205
  await this.onLLMError?.(run);
204
206
  await this._endTrace(run);
205
207
  return run;
@@ -72,6 +72,7 @@ class LangChainTracer extends base_js_1.BaseTracer {
72
72
  trace_id: run.trace_id,
73
73
  dotted_order: run.dotted_order,
74
74
  parent_run_id: run.parent_run_id,
75
+ extra: run.extra,
75
76
  };
76
77
  await this.client.updateRun(run.id, runUpdate);
77
78
  }
@@ -69,6 +69,7 @@ export class LangChainTracer extends BaseTracer {
69
69
  trace_id: run.trace_id,
70
70
  dotted_order: run.dotted_order,
71
71
  parent_run_id: run.parent_run_id,
72
+ extra: run.extra,
72
73
  };
73
74
  await this.client.updateRun(run.id, runUpdate);
74
75
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langchain/core",
3
- "version": "0.3.32",
3
+ "version": "0.3.34",
4
4
  "description": "Core LangChain.js abstractions and schemas",
5
5
  "type": "module",
6
6
  "engines": {