@langchain/openai 0.3.4 → 0.3.6-rc.0

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.
@@ -10,5 +10,7 @@ export declare class AzureOpenAIEmbeddings extends OpenAIEmbeddings {
10
10
  deploymentName?: string;
11
11
  openAIApiVersion?: string;
12
12
  }, configuration?: ClientOptions & LegacyOpenAIInput);
13
- protected embeddingWithRetry(request: OpenAIClient.EmbeddingCreateParams): Promise<OpenAIClient.Embeddings.CreateEmbeddingResponse>;
13
+ protected embeddingWithRetry(request: OpenAIClient.EmbeddingCreateParams): Promise<OpenAIClient.Embeddings.CreateEmbeddingResponse & {
14
+ _request_id?: string | null | undefined;
15
+ }>;
14
16
  }
@@ -74,6 +74,7 @@ function openAIResponseToChatMessage(message, rawResponse, includeRawResponse) {
74
74
  let response_metadata;
75
75
  if (rawResponse.system_fingerprint) {
76
76
  response_metadata = {
77
+ usage: { ...rawResponse.usage },
77
78
  system_fingerprint: rawResponse.system_fingerprint,
78
79
  };
79
80
  }
@@ -112,8 +113,9 @@ delta, rawResponse, defaultRole, includeRawResponse) {
112
113
  if (includeRawResponse) {
113
114
  additional_kwargs.__raw_response = rawResponse;
114
115
  }
116
+ const response_metadata = { usage: { ...rawResponse.usage } };
115
117
  if (role === "user") {
116
- return new messages_1.HumanMessageChunk({ content });
118
+ return new messages_1.HumanMessageChunk({ content, response_metadata });
117
119
  }
118
120
  else if (role === "assistant") {
119
121
  const toolCallChunks = [];
@@ -133,16 +135,18 @@ delta, rawResponse, defaultRole, includeRawResponse) {
133
135
  tool_call_chunks: toolCallChunks,
134
136
  additional_kwargs,
135
137
  id: rawResponse.id,
138
+ response_metadata,
136
139
  });
137
140
  }
138
141
  else if (role === "system") {
139
- return new messages_1.SystemMessageChunk({ content });
142
+ return new messages_1.SystemMessageChunk({ content, response_metadata });
140
143
  }
141
144
  else if (role === "function") {
142
145
  return new messages_1.FunctionMessageChunk({
143
146
  content,
144
147
  additional_kwargs,
145
148
  name: delta.name,
149
+ response_metadata,
146
150
  });
147
151
  }
148
152
  else if (role === "tool") {
@@ -150,10 +154,11 @@ delta, rawResponse, defaultRole, includeRawResponse) {
150
154
  content,
151
155
  additional_kwargs,
152
156
  tool_call_id: delta.tool_call_id,
157
+ response_metadata,
153
158
  });
154
159
  }
155
160
  else {
156
- return new messages_1.ChatMessageChunk({ content, role });
161
+ return new messages_1.ChatMessageChunk({ content, role, response_metadata });
157
162
  }
158
163
  }
159
164
  // Used in LangSmith, export is important here
@@ -1152,13 +1157,38 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
1152
1157
  await runManager?.handleLLMNewToken(generationChunk.text ?? "", newTokenIndices, undefined, undefined, undefined, { chunk: generationChunk });
1153
1158
  }
1154
1159
  if (usage) {
1160
+ const inputTokenDetails = {
1161
+ ...(usage.prompt_tokens_details?.audio_tokens !== null && {
1162
+ audio: usage.prompt_tokens_details?.audio_tokens,
1163
+ }),
1164
+ ...(usage.prompt_tokens_details?.cached_tokens !== null && {
1165
+ cache_read: usage.prompt_tokens_details?.cached_tokens,
1166
+ }),
1167
+ };
1168
+ const outputTokenDetails = {
1169
+ ...(usage.completion_tokens_details?.audio_tokens !== null && {
1170
+ audio: usage.completion_tokens_details?.audio_tokens,
1171
+ }),
1172
+ ...(usage.completion_tokens_details?.reasoning_tokens !== null && {
1173
+ reasoning: usage.completion_tokens_details?.reasoning_tokens,
1174
+ }),
1175
+ };
1155
1176
  const generationChunk = new outputs_1.ChatGenerationChunk({
1156
1177
  message: new messages_1.AIMessageChunk({
1157
1178
  content: "",
1179
+ response_metadata: {
1180
+ usage: { ...usage },
1181
+ },
1158
1182
  usage_metadata: {
1159
1183
  input_tokens: usage.prompt_tokens,
1160
1184
  output_tokens: usage.completion_tokens,
1161
1185
  total_tokens: usage.total_tokens,
1186
+ ...(Object.keys(inputTokenDetails).length > 0 && {
1187
+ input_token_details: inputTokenDetails,
1188
+ }),
1189
+ ...(Object.keys(outputTokenDetails).length > 0 && {
1190
+ output_token_details: outputTokenDetails,
1191
+ }),
1162
1192
  },
1163
1193
  }),
1164
1194
  text: "",
@@ -1178,7 +1208,7 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
1178
1208
  }
1179
1209
  /** @ignore */
1180
1210
  async _generate(messages, options, runManager) {
1181
- const tokenUsage = {};
1211
+ const usageMetadata = {};
1182
1212
  const params = this.invocationParams(options);
1183
1213
  const messagesMapped = _convertMessagesToOpenAIParams(messages);
1184
1214
  if (params.stream) {
@@ -1205,10 +1235,19 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
1205
1235
  // fallback to estimation.
1206
1236
  const promptTokenUsage = await this.getEstimatedTokenCountFromPrompt(messages, functions, function_call);
1207
1237
  const completionTokenUsage = await this.getNumTokensFromGenerations(generations);
1208
- tokenUsage.promptTokens = promptTokenUsage;
1209
- tokenUsage.completionTokens = completionTokenUsage;
1210
- tokenUsage.totalTokens = promptTokenUsage + completionTokenUsage;
1211
- return { generations, llmOutput: { estimatedTokenUsage: tokenUsage } };
1238
+ usageMetadata.input_tokens = promptTokenUsage;
1239
+ usageMetadata.output_tokens = completionTokenUsage;
1240
+ usageMetadata.total_tokens = promptTokenUsage + completionTokenUsage;
1241
+ return {
1242
+ generations,
1243
+ llmOutput: {
1244
+ estimatedTokenUsage: {
1245
+ promptTokens: usageMetadata.input_tokens,
1246
+ completionTokens: usageMetadata.output_tokens,
1247
+ totalTokens: usageMetadata.total_tokens,
1248
+ },
1249
+ },
1250
+ };
1212
1251
  }
1213
1252
  else {
1214
1253
  let data;
@@ -1233,16 +1272,40 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
1233
1272
  ...options?.options,
1234
1273
  });
1235
1274
  }
1236
- const { completion_tokens: completionTokens, prompt_tokens: promptTokens, total_tokens: totalTokens, } = data?.usage ?? {};
1275
+ const { completion_tokens: completionTokens, prompt_tokens: promptTokens, total_tokens: totalTokens, prompt_tokens_details: promptTokensDetails, completion_tokens_details: completionTokensDetails, } = data?.usage ?? {};
1237
1276
  if (completionTokens) {
1238
- tokenUsage.completionTokens =
1239
- (tokenUsage.completionTokens ?? 0) + completionTokens;
1277
+ usageMetadata.output_tokens =
1278
+ (usageMetadata.output_tokens ?? 0) + completionTokens;
1240
1279
  }
1241
1280
  if (promptTokens) {
1242
- tokenUsage.promptTokens = (tokenUsage.promptTokens ?? 0) + promptTokens;
1281
+ usageMetadata.input_tokens =
1282
+ (usageMetadata.input_tokens ?? 0) + promptTokens;
1243
1283
  }
1244
1284
  if (totalTokens) {
1245
- tokenUsage.totalTokens = (tokenUsage.totalTokens ?? 0) + totalTokens;
1285
+ usageMetadata.total_tokens =
1286
+ (usageMetadata.total_tokens ?? 0) + totalTokens;
1287
+ }
1288
+ if (promptTokensDetails?.audio_tokens !== null ||
1289
+ promptTokensDetails?.cached_tokens !== null) {
1290
+ usageMetadata.input_token_details = {
1291
+ ...(promptTokensDetails?.audio_tokens !== null && {
1292
+ audio: promptTokensDetails?.audio_tokens,
1293
+ }),
1294
+ ...(promptTokensDetails?.cached_tokens !== null && {
1295
+ cache_read: promptTokensDetails?.cached_tokens,
1296
+ }),
1297
+ };
1298
+ }
1299
+ if (completionTokensDetails?.audio_tokens !== null ||
1300
+ completionTokensDetails?.reasoning_tokens !== null) {
1301
+ usageMetadata.output_token_details = {
1302
+ ...(completionTokensDetails?.audio_tokens !== null && {
1303
+ audio: completionTokensDetails?.audio_tokens,
1304
+ }),
1305
+ ...(completionTokensDetails?.reasoning_tokens !== null && {
1306
+ reasoning: completionTokensDetails?.reasoning_tokens,
1307
+ }),
1308
+ };
1246
1309
  }
1247
1310
  const generations = [];
1248
1311
  for (const part of data?.choices ?? []) {
@@ -1256,17 +1319,19 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
1256
1319
  ...(part.logprobs ? { logprobs: part.logprobs } : {}),
1257
1320
  };
1258
1321
  if ((0, messages_1.isAIMessage)(generation.message)) {
1259
- generation.message.usage_metadata = {
1260
- input_tokens: tokenUsage.promptTokens ?? 0,
1261
- output_tokens: tokenUsage.completionTokens ?? 0,
1262
- total_tokens: tokenUsage.totalTokens ?? 0,
1263
- };
1322
+ generation.message.usage_metadata = usageMetadata;
1264
1323
  }
1265
1324
  generations.push(generation);
1266
1325
  }
1267
1326
  return {
1268
1327
  generations,
1269
- llmOutput: { tokenUsage },
1328
+ llmOutput: {
1329
+ tokenUsage: {
1330
+ promptTokens: usageMetadata.input_tokens,
1331
+ completionTokens: usageMetadata.output_tokens,
1332
+ totalTokens: usageMetadata.total_tokens,
1333
+ },
1334
+ },
1270
1335
  };
1271
1336
  }
1272
1337
  }
@@ -70,6 +70,7 @@ function openAIResponseToChatMessage(message, rawResponse, includeRawResponse) {
70
70
  let response_metadata;
71
71
  if (rawResponse.system_fingerprint) {
72
72
  response_metadata = {
73
+ usage: { ...rawResponse.usage },
73
74
  system_fingerprint: rawResponse.system_fingerprint,
74
75
  };
75
76
  }
@@ -108,8 +109,9 @@ delta, rawResponse, defaultRole, includeRawResponse) {
108
109
  if (includeRawResponse) {
109
110
  additional_kwargs.__raw_response = rawResponse;
110
111
  }
112
+ const response_metadata = { usage: { ...rawResponse.usage } };
111
113
  if (role === "user") {
112
- return new HumanMessageChunk({ content });
114
+ return new HumanMessageChunk({ content, response_metadata });
113
115
  }
114
116
  else if (role === "assistant") {
115
117
  const toolCallChunks = [];
@@ -129,16 +131,18 @@ delta, rawResponse, defaultRole, includeRawResponse) {
129
131
  tool_call_chunks: toolCallChunks,
130
132
  additional_kwargs,
131
133
  id: rawResponse.id,
134
+ response_metadata,
132
135
  });
133
136
  }
134
137
  else if (role === "system") {
135
- return new SystemMessageChunk({ content });
138
+ return new SystemMessageChunk({ content, response_metadata });
136
139
  }
137
140
  else if (role === "function") {
138
141
  return new FunctionMessageChunk({
139
142
  content,
140
143
  additional_kwargs,
141
144
  name: delta.name,
145
+ response_metadata,
142
146
  });
143
147
  }
144
148
  else if (role === "tool") {
@@ -146,10 +150,11 @@ delta, rawResponse, defaultRole, includeRawResponse) {
146
150
  content,
147
151
  additional_kwargs,
148
152
  tool_call_id: delta.tool_call_id,
153
+ response_metadata,
149
154
  });
150
155
  }
151
156
  else {
152
- return new ChatMessageChunk({ content, role });
157
+ return new ChatMessageChunk({ content, role, response_metadata });
153
158
  }
154
159
  }
155
160
  // Used in LangSmith, export is important here
@@ -1147,13 +1152,38 @@ export class ChatOpenAI extends BaseChatModel {
1147
1152
  await runManager?.handleLLMNewToken(generationChunk.text ?? "", newTokenIndices, undefined, undefined, undefined, { chunk: generationChunk });
1148
1153
  }
1149
1154
  if (usage) {
1155
+ const inputTokenDetails = {
1156
+ ...(usage.prompt_tokens_details?.audio_tokens !== null && {
1157
+ audio: usage.prompt_tokens_details?.audio_tokens,
1158
+ }),
1159
+ ...(usage.prompt_tokens_details?.cached_tokens !== null && {
1160
+ cache_read: usage.prompt_tokens_details?.cached_tokens,
1161
+ }),
1162
+ };
1163
+ const outputTokenDetails = {
1164
+ ...(usage.completion_tokens_details?.audio_tokens !== null && {
1165
+ audio: usage.completion_tokens_details?.audio_tokens,
1166
+ }),
1167
+ ...(usage.completion_tokens_details?.reasoning_tokens !== null && {
1168
+ reasoning: usage.completion_tokens_details?.reasoning_tokens,
1169
+ }),
1170
+ };
1150
1171
  const generationChunk = new ChatGenerationChunk({
1151
1172
  message: new AIMessageChunk({
1152
1173
  content: "",
1174
+ response_metadata: {
1175
+ usage: { ...usage },
1176
+ },
1153
1177
  usage_metadata: {
1154
1178
  input_tokens: usage.prompt_tokens,
1155
1179
  output_tokens: usage.completion_tokens,
1156
1180
  total_tokens: usage.total_tokens,
1181
+ ...(Object.keys(inputTokenDetails).length > 0 && {
1182
+ input_token_details: inputTokenDetails,
1183
+ }),
1184
+ ...(Object.keys(outputTokenDetails).length > 0 && {
1185
+ output_token_details: outputTokenDetails,
1186
+ }),
1157
1187
  },
1158
1188
  }),
1159
1189
  text: "",
@@ -1173,7 +1203,7 @@ export class ChatOpenAI extends BaseChatModel {
1173
1203
  }
1174
1204
  /** @ignore */
1175
1205
  async _generate(messages, options, runManager) {
1176
- const tokenUsage = {};
1206
+ const usageMetadata = {};
1177
1207
  const params = this.invocationParams(options);
1178
1208
  const messagesMapped = _convertMessagesToOpenAIParams(messages);
1179
1209
  if (params.stream) {
@@ -1200,10 +1230,19 @@ export class ChatOpenAI extends BaseChatModel {
1200
1230
  // fallback to estimation.
1201
1231
  const promptTokenUsage = await this.getEstimatedTokenCountFromPrompt(messages, functions, function_call);
1202
1232
  const completionTokenUsage = await this.getNumTokensFromGenerations(generations);
1203
- tokenUsage.promptTokens = promptTokenUsage;
1204
- tokenUsage.completionTokens = completionTokenUsage;
1205
- tokenUsage.totalTokens = promptTokenUsage + completionTokenUsage;
1206
- return { generations, llmOutput: { estimatedTokenUsage: tokenUsage } };
1233
+ usageMetadata.input_tokens = promptTokenUsage;
1234
+ usageMetadata.output_tokens = completionTokenUsage;
1235
+ usageMetadata.total_tokens = promptTokenUsage + completionTokenUsage;
1236
+ return {
1237
+ generations,
1238
+ llmOutput: {
1239
+ estimatedTokenUsage: {
1240
+ promptTokens: usageMetadata.input_tokens,
1241
+ completionTokens: usageMetadata.output_tokens,
1242
+ totalTokens: usageMetadata.total_tokens,
1243
+ },
1244
+ },
1245
+ };
1207
1246
  }
1208
1247
  else {
1209
1248
  let data;
@@ -1228,16 +1267,40 @@ export class ChatOpenAI extends BaseChatModel {
1228
1267
  ...options?.options,
1229
1268
  });
1230
1269
  }
1231
- const { completion_tokens: completionTokens, prompt_tokens: promptTokens, total_tokens: totalTokens, } = data?.usage ?? {};
1270
+ const { completion_tokens: completionTokens, prompt_tokens: promptTokens, total_tokens: totalTokens, prompt_tokens_details: promptTokensDetails, completion_tokens_details: completionTokensDetails, } = data?.usage ?? {};
1232
1271
  if (completionTokens) {
1233
- tokenUsage.completionTokens =
1234
- (tokenUsage.completionTokens ?? 0) + completionTokens;
1272
+ usageMetadata.output_tokens =
1273
+ (usageMetadata.output_tokens ?? 0) + completionTokens;
1235
1274
  }
1236
1275
  if (promptTokens) {
1237
- tokenUsage.promptTokens = (tokenUsage.promptTokens ?? 0) + promptTokens;
1276
+ usageMetadata.input_tokens =
1277
+ (usageMetadata.input_tokens ?? 0) + promptTokens;
1238
1278
  }
1239
1279
  if (totalTokens) {
1240
- tokenUsage.totalTokens = (tokenUsage.totalTokens ?? 0) + totalTokens;
1280
+ usageMetadata.total_tokens =
1281
+ (usageMetadata.total_tokens ?? 0) + totalTokens;
1282
+ }
1283
+ if (promptTokensDetails?.audio_tokens !== null ||
1284
+ promptTokensDetails?.cached_tokens !== null) {
1285
+ usageMetadata.input_token_details = {
1286
+ ...(promptTokensDetails?.audio_tokens !== null && {
1287
+ audio: promptTokensDetails?.audio_tokens,
1288
+ }),
1289
+ ...(promptTokensDetails?.cached_tokens !== null && {
1290
+ cache_read: promptTokensDetails?.cached_tokens,
1291
+ }),
1292
+ };
1293
+ }
1294
+ if (completionTokensDetails?.audio_tokens !== null ||
1295
+ completionTokensDetails?.reasoning_tokens !== null) {
1296
+ usageMetadata.output_token_details = {
1297
+ ...(completionTokensDetails?.audio_tokens !== null && {
1298
+ audio: completionTokensDetails?.audio_tokens,
1299
+ }),
1300
+ ...(completionTokensDetails?.reasoning_tokens !== null && {
1301
+ reasoning: completionTokensDetails?.reasoning_tokens,
1302
+ }),
1303
+ };
1241
1304
  }
1242
1305
  const generations = [];
1243
1306
  for (const part of data?.choices ?? []) {
@@ -1251,17 +1314,19 @@ export class ChatOpenAI extends BaseChatModel {
1251
1314
  ...(part.logprobs ? { logprobs: part.logprobs } : {}),
1252
1315
  };
1253
1316
  if (isAIMessage(generation.message)) {
1254
- generation.message.usage_metadata = {
1255
- input_tokens: tokenUsage.promptTokens ?? 0,
1256
- output_tokens: tokenUsage.completionTokens ?? 0,
1257
- total_tokens: tokenUsage.totalTokens ?? 0,
1258
- };
1317
+ generation.message.usage_metadata = usageMetadata;
1259
1318
  }
1260
1319
  generations.push(generation);
1261
1320
  }
1262
1321
  return {
1263
1322
  generations,
1264
- llmOutput: { tokenUsage },
1323
+ llmOutput: {
1324
+ tokenUsage: {
1325
+ promptTokens: usageMetadata.input_tokens,
1326
+ completionTokens: usageMetadata.output_tokens,
1327
+ totalTokens: usageMetadata.total_tokens,
1328
+ },
1329
+ },
1265
1330
  };
1266
1331
  }
1267
1332
  }
@@ -102,5 +102,10 @@ export declare class OpenAIEmbeddings extends Embeddings implements OpenAIEmbedd
102
102
  * @param request Request to send to the OpenAI API.
103
103
  * @returns Promise that resolves to the response from the API.
104
104
  */
105
- protected embeddingWithRetry(request: OpenAIClient.EmbeddingCreateParams): Promise<OpenAIClient.Embeddings.CreateEmbeddingResponse>;
105
+ protected embeddingWithRetry(request: OpenAIClient.EmbeddingCreateParams): Promise<OpenAIClient.Embeddings.CreateEmbeddingResponse & {
106
+ _request_id?: string | null | undefined; /**
107
+ * The number of dimensions the resulting output embeddings should have.
108
+ * Only supported in `text-embedding-3` and later models.
109
+ */
110
+ }>;
106
111
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langchain/openai",
3
- "version": "0.3.4",
3
+ "version": "0.3.6-rc.0",
4
4
  "description": "OpenAI integrations for LangChain.js",
5
5
  "type": "module",
6
6
  "engines": {
@@ -36,7 +36,7 @@
36
36
  "license": "MIT",
37
37
  "dependencies": {
38
38
  "js-tiktoken": "^1.0.12",
39
- "openai": "^4.57.3",
39
+ "openai": "^4.67.2",
40
40
  "zod": "^3.22.4",
41
41
  "zod-to-json-schema": "^3.22.3"
42
42
  },