@langchain/openai 0.1.3 → 0.2.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.
@@ -47,7 +47,7 @@ function messageToOpenAIRole(message) {
47
47
  }
48
48
  }
49
49
  exports.messageToOpenAIRole = messageToOpenAIRole;
50
- function openAIResponseToChatMessage(message) {
50
+ function openAIResponseToChatMessage(message, messageId) {
51
51
  const rawToolCalls = message.tool_calls;
52
52
  switch (message.role) {
53
53
  case "assistant": {
@@ -70,6 +70,7 @@ function openAIResponseToChatMessage(message) {
70
70
  function_call: message.function_call,
71
71
  tool_calls: rawToolCalls,
72
72
  },
73
+ id: messageId,
73
74
  });
74
75
  }
75
76
  default:
@@ -78,7 +79,7 @@ function openAIResponseToChatMessage(message) {
78
79
  }
79
80
  function _convertDeltaToMessageChunk(
80
81
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
81
- delta, defaultRole) {
82
+ delta, messageId, defaultRole) {
82
83
  const role = delta.role ?? defaultRole;
83
84
  const content = delta.content ?? "";
84
85
  let additional_kwargs;
@@ -114,6 +115,7 @@ delta, defaultRole) {
114
115
  content,
115
116
  tool_call_chunks: toolCallChunks,
116
117
  additional_kwargs,
118
+ id: messageId,
117
119
  });
118
120
  }
119
121
  else if (role === "system") {
@@ -150,9 +152,11 @@ function convertMessagesToOpenAIParams(messages) {
150
152
  }
151
153
  if (message.additional_kwargs.function_call != null) {
152
154
  completionParam.function_call = message.additional_kwargs.function_call;
155
+ completionParam.content = null;
153
156
  }
154
157
  if ((0, messages_1.isAIMessage)(message) && !!message.tool_calls?.length) {
155
158
  completionParam.tool_calls = message.tool_calls.map(openai_tools_1.convertLangChainToolCallToOpenAI);
159
+ completionParam.content = null;
156
160
  }
157
161
  else {
158
162
  if (message.additional_kwargs.tool_calls != null) {
@@ -168,14 +172,13 @@ function convertMessagesToOpenAIParams(messages) {
168
172
  /**
169
173
  * Wrapper around OpenAI large language models that use the Chat endpoint.
170
174
  *
171
- * To use you should have the `openai` package installed, with the
172
- * `OPENAI_API_KEY` environment variable set.
175
+ * To use you should have the `OPENAI_API_KEY` environment variable set.
173
176
  *
174
- * To use with Azure you should have the `openai` package installed, with the
177
+ * To use with Azure you should have the:
175
178
  * `AZURE_OPENAI_API_KEY`,
176
179
  * `AZURE_OPENAI_API_INSTANCE_NAME`,
177
180
  * `AZURE_OPENAI_API_DEPLOYMENT_NAME`
178
- * and `AZURE_OPENAI_API_VERSION` environment variable set.
181
+ * and `AZURE_OPENAI_API_VERSION` environment variables set.
179
182
  * `AZURE_OPENAI_BASE_PATH` is optional and will override `AZURE_OPENAI_API_INSTANCE_NAME` if you need to use a custom endpoint.
180
183
  *
181
184
  * @remarks
@@ -329,6 +332,12 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
329
332
  writable: true,
330
333
  value: false
331
334
  });
335
+ Object.defineProperty(this, "streamUsage", {
336
+ enumerable: true,
337
+ configurable: true,
338
+ writable: true,
339
+ value: true
340
+ });
332
341
  Object.defineProperty(this, "maxTokens", {
333
342
  enumerable: true,
334
343
  configurable: true,
@@ -457,6 +466,7 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
457
466
  this.stopSequences = this?.stop;
458
467
  this.user = fields?.user;
459
468
  this.streaming = fields?.streaming ?? false;
469
+ this.streamUsage = fields?.streamUsage ?? this.streamUsage;
460
470
  if (this.azureOpenAIApiKey || this.azureADTokenProvider) {
461
471
  if (!this.azureOpenAIApiInstanceName && !this.azureOpenAIBasePath) {
462
472
  throw new Error("Azure OpenAI API instance name not found");
@@ -507,6 +517,13 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
507
517
  return (tools !== undefined &&
508
518
  tools.every((tool) => Array.isArray(tool.lc_namespace)));
509
519
  }
520
+ let streamOptionsConfig = {};
521
+ if (options?.stream_options !== undefined) {
522
+ streamOptionsConfig = { stream_options: options.stream_options };
523
+ }
524
+ else if (this.streamUsage && this.streaming) {
525
+ streamOptionsConfig = { stream_options: { include_usage: true } };
526
+ }
510
527
  const params = {
511
528
  model: this.model,
512
529
  temperature: this.temperature,
@@ -520,6 +537,7 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
520
537
  logit_bias: this.logitBias,
521
538
  stop: options?.stop ?? this.stopSequences,
522
539
  user: this.user,
540
+ // if include_usage is set or streamUsage then stream must be set to true.
523
541
  stream: this.streaming,
524
542
  functions: options?.functions,
525
543
  function_call: options?.function_call,
@@ -529,9 +547,7 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
529
547
  tool_choice: options?.tool_choice,
530
548
  response_format: options?.response_format,
531
549
  seed: options?.seed,
532
- ...(options?.stream_options !== undefined
533
- ? { stream_options: options.stream_options }
534
- : {}),
550
+ ...streamOptionsConfig,
535
551
  parallel_tool_calls: options?.parallel_tool_calls,
536
552
  ...this.modelKwargs,
537
553
  };
@@ -567,7 +583,7 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
567
583
  if (!delta) {
568
584
  continue;
569
585
  }
570
- const chunk = _convertDeltaToMessageChunk(delta, defaultRole);
586
+ const chunk = _convertDeltaToMessageChunk(delta, data.id, defaultRole);
571
587
  defaultRole = delta.role ?? defaultRole;
572
588
  const newTokenIndices = {
573
589
  prompt: options.promptIndex ?? 0,
@@ -678,7 +694,7 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
678
694
  const text = part.message?.content ?? "";
679
695
  const generation = {
680
696
  text,
681
- message: openAIResponseToChatMessage(part.message ?? { role: "assistant" }),
697
+ message: openAIResponseToChatMessage(part.message ?? { role: "assistant" }, data.id),
682
698
  };
683
699
  generation.generationInfo = {
684
700
  ...(part.finish_reason ? { finish_reason: part.finish_reason } : {}),
@@ -29,6 +29,7 @@ export interface ChatOpenAICallOptions extends OpenAICallOptions, BaseFunctionCa
29
29
  seed?: number;
30
30
  /**
31
31
  * Additional options to pass to streamed completions.
32
+ * If provided takes precedence over "streamUsage" set at initialization time.
32
33
  */
33
34
  stream_options?: {
34
35
  /**
@@ -47,14 +48,13 @@ export interface ChatOpenAICallOptions extends OpenAICallOptions, BaseFunctionCa
47
48
  /**
48
49
  * Wrapper around OpenAI large language models that use the Chat endpoint.
49
50
  *
50
- * To use you should have the `openai` package installed, with the
51
- * `OPENAI_API_KEY` environment variable set.
51
+ * To use you should have the `OPENAI_API_KEY` environment variable set.
52
52
  *
53
- * To use with Azure you should have the `openai` package installed, with the
53
+ * To use with Azure you should have the:
54
54
  * `AZURE_OPENAI_API_KEY`,
55
55
  * `AZURE_OPENAI_API_INSTANCE_NAME`,
56
56
  * `AZURE_OPENAI_API_DEPLOYMENT_NAME`
57
- * and `AZURE_OPENAI_API_VERSION` environment variable set.
57
+ * and `AZURE_OPENAI_API_VERSION` environment variables set.
58
58
  * `AZURE_OPENAI_BASE_PATH` is optional and will override `AZURE_OPENAI_API_INSTANCE_NAME` if you need to use a custom endpoint.
59
59
  *
60
60
  * @remarks
@@ -100,6 +100,7 @@ export declare class ChatOpenAI<CallOptions extends ChatOpenAICallOptions = Chat
100
100
  user?: string;
101
101
  timeout?: number;
102
102
  streaming: boolean;
103
+ streamUsage: boolean;
103
104
  maxTokens?: number;
104
105
  logprobs?: boolean;
105
106
  topLogprobs?: number;
@@ -43,7 +43,7 @@ export function messageToOpenAIRole(message) {
43
43
  throw new Error(`Unknown message type: ${type}`);
44
44
  }
45
45
  }
46
- function openAIResponseToChatMessage(message) {
46
+ function openAIResponseToChatMessage(message, messageId) {
47
47
  const rawToolCalls = message.tool_calls;
48
48
  switch (message.role) {
49
49
  case "assistant": {
@@ -66,6 +66,7 @@ function openAIResponseToChatMessage(message) {
66
66
  function_call: message.function_call,
67
67
  tool_calls: rawToolCalls,
68
68
  },
69
+ id: messageId,
69
70
  });
70
71
  }
71
72
  default:
@@ -74,7 +75,7 @@ function openAIResponseToChatMessage(message) {
74
75
  }
75
76
  function _convertDeltaToMessageChunk(
76
77
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
77
- delta, defaultRole) {
78
+ delta, messageId, defaultRole) {
78
79
  const role = delta.role ?? defaultRole;
79
80
  const content = delta.content ?? "";
80
81
  let additional_kwargs;
@@ -110,6 +111,7 @@ delta, defaultRole) {
110
111
  content,
111
112
  tool_call_chunks: toolCallChunks,
112
113
  additional_kwargs,
114
+ id: messageId,
113
115
  });
114
116
  }
115
117
  else if (role === "system") {
@@ -146,9 +148,11 @@ function convertMessagesToOpenAIParams(messages) {
146
148
  }
147
149
  if (message.additional_kwargs.function_call != null) {
148
150
  completionParam.function_call = message.additional_kwargs.function_call;
151
+ completionParam.content = null;
149
152
  }
150
153
  if (isAIMessage(message) && !!message.tool_calls?.length) {
151
154
  completionParam.tool_calls = message.tool_calls.map(convertLangChainToolCallToOpenAI);
155
+ completionParam.content = null;
152
156
  }
153
157
  else {
154
158
  if (message.additional_kwargs.tool_calls != null) {
@@ -164,14 +168,13 @@ function convertMessagesToOpenAIParams(messages) {
164
168
  /**
165
169
  * Wrapper around OpenAI large language models that use the Chat endpoint.
166
170
  *
167
- * To use you should have the `openai` package installed, with the
168
- * `OPENAI_API_KEY` environment variable set.
171
+ * To use you should have the `OPENAI_API_KEY` environment variable set.
169
172
  *
170
- * To use with Azure you should have the `openai` package installed, with the
173
+ * To use with Azure you should have the:
171
174
  * `AZURE_OPENAI_API_KEY`,
172
175
  * `AZURE_OPENAI_API_INSTANCE_NAME`,
173
176
  * `AZURE_OPENAI_API_DEPLOYMENT_NAME`
174
- * and `AZURE_OPENAI_API_VERSION` environment variable set.
177
+ * and `AZURE_OPENAI_API_VERSION` environment variables set.
175
178
  * `AZURE_OPENAI_BASE_PATH` is optional and will override `AZURE_OPENAI_API_INSTANCE_NAME` if you need to use a custom endpoint.
176
179
  *
177
180
  * @remarks
@@ -325,6 +328,12 @@ export class ChatOpenAI extends BaseChatModel {
325
328
  writable: true,
326
329
  value: false
327
330
  });
331
+ Object.defineProperty(this, "streamUsage", {
332
+ enumerable: true,
333
+ configurable: true,
334
+ writable: true,
335
+ value: true
336
+ });
328
337
  Object.defineProperty(this, "maxTokens", {
329
338
  enumerable: true,
330
339
  configurable: true,
@@ -453,6 +462,7 @@ export class ChatOpenAI extends BaseChatModel {
453
462
  this.stopSequences = this?.stop;
454
463
  this.user = fields?.user;
455
464
  this.streaming = fields?.streaming ?? false;
465
+ this.streamUsage = fields?.streamUsage ?? this.streamUsage;
456
466
  if (this.azureOpenAIApiKey || this.azureADTokenProvider) {
457
467
  if (!this.azureOpenAIApiInstanceName && !this.azureOpenAIBasePath) {
458
468
  throw new Error("Azure OpenAI API instance name not found");
@@ -503,6 +513,13 @@ export class ChatOpenAI extends BaseChatModel {
503
513
  return (tools !== undefined &&
504
514
  tools.every((tool) => Array.isArray(tool.lc_namespace)));
505
515
  }
516
+ let streamOptionsConfig = {};
517
+ if (options?.stream_options !== undefined) {
518
+ streamOptionsConfig = { stream_options: options.stream_options };
519
+ }
520
+ else if (this.streamUsage && this.streaming) {
521
+ streamOptionsConfig = { stream_options: { include_usage: true } };
522
+ }
506
523
  const params = {
507
524
  model: this.model,
508
525
  temperature: this.temperature,
@@ -516,6 +533,7 @@ export class ChatOpenAI extends BaseChatModel {
516
533
  logit_bias: this.logitBias,
517
534
  stop: options?.stop ?? this.stopSequences,
518
535
  user: this.user,
536
+ // if include_usage is set or streamUsage then stream must be set to true.
519
537
  stream: this.streaming,
520
538
  functions: options?.functions,
521
539
  function_call: options?.function_call,
@@ -525,9 +543,7 @@ export class ChatOpenAI extends BaseChatModel {
525
543
  tool_choice: options?.tool_choice,
526
544
  response_format: options?.response_format,
527
545
  seed: options?.seed,
528
- ...(options?.stream_options !== undefined
529
- ? { stream_options: options.stream_options }
530
- : {}),
546
+ ...streamOptionsConfig,
531
547
  parallel_tool_calls: options?.parallel_tool_calls,
532
548
  ...this.modelKwargs,
533
549
  };
@@ -563,7 +579,7 @@ export class ChatOpenAI extends BaseChatModel {
563
579
  if (!delta) {
564
580
  continue;
565
581
  }
566
- const chunk = _convertDeltaToMessageChunk(delta, defaultRole);
582
+ const chunk = _convertDeltaToMessageChunk(delta, data.id, defaultRole);
567
583
  defaultRole = delta.role ?? defaultRole;
568
584
  const newTokenIndices = {
569
585
  prompt: options.promptIndex ?? 0,
@@ -674,7 +690,7 @@ export class ChatOpenAI extends BaseChatModel {
674
690
  const text = part.message?.content ?? "";
675
691
  const generation = {
676
692
  text,
677
- message: openAIResponseToChatMessage(part.message ?? { role: "assistant" }),
693
+ message: openAIResponseToChatMessage(part.message ?? { role: "assistant" }, data.id),
678
694
  };
679
695
  generation.generationInfo = {
680
696
  ...(part.finish_reason ? { finish_reason: part.finish_reason } : {}),
package/dist/types.d.ts CHANGED
@@ -24,6 +24,11 @@ export declare interface OpenAIBaseInput {
24
24
  user?: string;
25
25
  /** Whether to stream the results or not. Enabling disables tokenUsage reporting */
26
26
  streaming: boolean;
27
+ /**
28
+ * Whether or not to include token usage data in streamed chunks.
29
+ * @default true
30
+ */
31
+ streamUsage?: boolean;
27
32
  /**
28
33
  * Model name to use
29
34
  * Alias for `model`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langchain/openai",
3
- "version": "0.1.3",
3
+ "version": "0.2.0",
4
4
  "description": "OpenAI integrations for LangChain.js",
5
5
  "type": "module",
6
6
  "engines": {
@@ -35,7 +35,7 @@
35
35
  "author": "LangChain",
36
36
  "license": "MIT",
37
37
  "dependencies": {
38
- "@langchain/core": ">=0.2.5 <0.3.0",
38
+ "@langchain/core": ">=0.2.8 <0.3.0",
39
39
  "js-tiktoken": "^1.0.12",
40
40
  "openai": "^4.49.1",
41
41
  "zod": "^3.22.4",