langchain 0.0.177 → 0.0.179

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.
Files changed (73) hide show
  1. package/chains/combine_documents/reduce.cjs +1 -0
  2. package/chains/combine_documents/reduce.d.ts +1 -0
  3. package/chains/combine_documents/reduce.js +1 -0
  4. package/chat_models/iflytek_xinghuo/web.cjs +1 -0
  5. package/chat_models/iflytek_xinghuo/web.d.ts +1 -0
  6. package/chat_models/iflytek_xinghuo/web.js +1 -0
  7. package/chat_models/iflytek_xinghuo.cjs +1 -0
  8. package/chat_models/iflytek_xinghuo.d.ts +1 -0
  9. package/chat_models/iflytek_xinghuo.js +1 -0
  10. package/dist/cache/base.d.ts +1 -1
  11. package/dist/callbacks/index.d.ts +1 -1
  12. package/dist/chains/combine_documents/reduce.cjs +67 -0
  13. package/dist/chains/combine_documents/reduce.d.ts +28 -0
  14. package/dist/chains/combine_documents/reduce.js +62 -0
  15. package/dist/chat_models/cloudflare_workersai.cjs +70 -24
  16. package/dist/chat_models/cloudflare_workersai.d.ts +6 -2
  17. package/dist/chat_models/cloudflare_workersai.js +71 -25
  18. package/dist/chat_models/iflytek_xinghuo/common.cjs +335 -0
  19. package/dist/chat_models/iflytek_xinghuo/common.d.ts +165 -0
  20. package/dist/chat_models/iflytek_xinghuo/common.js +331 -0
  21. package/dist/chat_models/iflytek_xinghuo/index.cjs +35 -0
  22. package/dist/chat_models/iflytek_xinghuo/index.d.ts +5 -0
  23. package/dist/chat_models/iflytek_xinghuo/index.js +28 -0
  24. package/dist/chat_models/iflytek_xinghuo/web.cjs +30 -0
  25. package/dist/chat_models/iflytek_xinghuo/web.d.ts +5 -0
  26. package/dist/chat_models/iflytek_xinghuo/web.js +26 -0
  27. package/dist/graphs/neo4j_graph.cjs +36 -5
  28. package/dist/graphs/neo4j_graph.js +14 -3
  29. package/dist/llms/cloudflare_workersai.cjs +59 -13
  30. package/dist/llms/cloudflare_workersai.d.ts +9 -3
  31. package/dist/llms/cloudflare_workersai.js +59 -13
  32. package/dist/load/import_constants.cjs +2 -0
  33. package/dist/load/import_constants.js +2 -0
  34. package/dist/load/import_map.cjs +4 -2
  35. package/dist/load/import_map.d.ts +2 -0
  36. package/dist/load/import_map.js +2 -0
  37. package/dist/output_parsers/json.cjs +77 -0
  38. package/dist/output_parsers/json.d.ts +1 -0
  39. package/dist/output_parsers/json.js +73 -0
  40. package/dist/output_parsers/openai_functions.cjs +37 -2
  41. package/dist/output_parsers/openai_functions.d.ts +10 -5
  42. package/dist/output_parsers/openai_functions.js +38 -3
  43. package/dist/prompts/chat.cjs +8 -0
  44. package/dist/prompts/chat.d.ts +5 -0
  45. package/dist/prompts/chat.js +8 -0
  46. package/dist/schema/index.cjs +33 -1
  47. package/dist/schema/index.d.ts +3 -1
  48. package/dist/schema/index.js +31 -0
  49. package/dist/schema/output_parser.cjs +63 -3
  50. package/dist/schema/output_parser.d.ts +16 -1
  51. package/dist/schema/output_parser.js +59 -0
  52. package/dist/schema/prompt_template.cjs +33 -0
  53. package/dist/schema/prompt_template.d.ts +12 -0
  54. package/dist/schema/prompt_template.js +29 -0
  55. package/dist/storage/convex.d.ts +21 -0
  56. package/dist/stores/message/convex.d.ts +21 -0
  57. package/dist/util/event-source-parse.cjs +20 -1
  58. package/dist/util/event-source-parse.d.ts +2 -0
  59. package/dist/util/event-source-parse.js +18 -0
  60. package/dist/util/fast-json-patch/index.cjs +1 -0
  61. package/dist/util/fast-json-patch/index.d.ts +1 -0
  62. package/dist/util/fast-json-patch/index.js +1 -0
  63. package/dist/util/fast-json-patch/src/duplex.cjs +237 -0
  64. package/dist/util/fast-json-patch/src/duplex.d.ts +23 -0
  65. package/dist/util/fast-json-patch/src/duplex.js +230 -0
  66. package/dist/util/iflytek_websocket_stream.cjs +81 -0
  67. package/dist/util/iflytek_websocket_stream.d.ts +27 -0
  68. package/dist/util/iflytek_websocket_stream.js +77 -0
  69. package/dist/vectorstores/convex.d.ts +21 -0
  70. package/package.json +38 -1
  71. package/schema/prompt_template.cjs +1 -0
  72. package/schema/prompt_template.d.ts +1 -0
  73. package/schema/prompt_template.js +1 -0
@@ -0,0 +1 @@
1
+ module.exports = require('../../dist/chains/combine_documents/reduce.cjs');
@@ -0,0 +1 @@
1
+ export * from '../../dist/chains/combine_documents/reduce.js'
@@ -0,0 +1 @@
1
+ export * from '../../dist/chains/combine_documents/reduce.js'
@@ -0,0 +1 @@
1
+ module.exports = require('../../dist/chat_models/iflytek_xinghuo/web.cjs');
@@ -0,0 +1 @@
1
+ export * from '../../dist/chat_models/iflytek_xinghuo/web.js'
@@ -0,0 +1 @@
1
+ export * from '../../dist/chat_models/iflytek_xinghuo/web.js'
@@ -0,0 +1 @@
1
+ module.exports = require('../dist/chat_models/iflytek_xinghuo/index.cjs');
@@ -0,0 +1 @@
1
+ export * from '../dist/chat_models/iflytek_xinghuo/index.js'
@@ -0,0 +1 @@
1
+ export * from '../dist/chat_models/iflytek_xinghuo/index.js'
@@ -12,7 +12,7 @@ import { Generation, StoredGeneration } from "../schema/index.js";
12
12
  export declare const getCacheKey: (...strings: string[]) => string;
13
13
  export declare function deserializeStoredGeneration(storedGeneration: StoredGeneration): {
14
14
  text: string;
15
- message: import("../schema/index.js").HumanMessage | import("../schema/index.js").AIMessage | import("../schema/index.js").SystemMessage | import("../schema/index.js").FunctionMessage | import("../schema/index.js").ChatMessage;
15
+ message: import("../schema/index.js").ChatMessage | import("../schema/index.js").HumanMessage | import("../schema/index.js").AIMessage | import("../schema/index.js").SystemMessage | import("../schema/index.js").FunctionMessage;
16
16
  } | {
17
17
  text: string;
18
18
  message?: undefined;
@@ -5,5 +5,5 @@ export { RunCollectorCallbackHandler } from "./handlers/run_collector.js";
5
5
  export { LangChainTracer } from "./handlers/tracer_langchain.js";
6
6
  export { LangChainTracerV1 } from "./handlers/tracer_langchain_v1.js";
7
7
  export { getTracingCallbackHandler, getTracingV2CallbackHandler, } from "./handlers/initialize.js";
8
- export { CallbackManager, CallbackManagerForRetrieverRun, CallbackManagerForChainRun, CallbackManagerForLLMRun, CallbackManagerForToolRun, type CallbackManagerOptions, type Callbacks, TraceGroup, traceAsGroup, } from "./manager.js";
8
+ export { CallbackManager, CallbackManagerForRetrieverRun, CallbackManagerForChainRun, CallbackManagerForLLMRun, CallbackManagerForToolRun, type CallbackManagerOptions, type Callbacks, type BaseCallbackConfig, TraceGroup, traceAsGroup, } from "./manager.js";
9
9
  export { awaitAllCallbacks, consumeCallback } from "./promises.js";
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.collapseDocs = exports.splitListOfDocs = void 0;
4
+ /**
5
+ * Splits a list of documents into sublists based on a maximum token limit.
6
+ *
7
+ * @param {Document[]} docs - The list of documents to be split.
8
+ * @param {Function} lengthFunc - A function that calculates the number of tokens in a list of documents.
9
+ * @param {number} tokenMax - The maximum number of tokens allowed in a sublist.
10
+ *
11
+ * @returns {Document[][]} - A list of document sublists, each sublist contains documents whose total number of tokens does not exceed the tokenMax.
12
+ *
13
+ * @throws {Error} - Throws an error if a single document has more tokens than the tokenMax.
14
+ */
15
+ function splitListOfDocs(docs, lengthFunc, tokenMax) {
16
+ const newResultDocList = [];
17
+ let subResultDocs = [];
18
+ for (const doc of docs) {
19
+ subResultDocs.push(doc);
20
+ const numTokens = lengthFunc(subResultDocs);
21
+ if (numTokens > tokenMax) {
22
+ if (subResultDocs.length === 1) {
23
+ throw new Error("A single document was longer than the context length, we cannot handle this.");
24
+ }
25
+ newResultDocList.push(subResultDocs.slice(0, -1));
26
+ subResultDocs = subResultDocs.slice(-1);
27
+ }
28
+ }
29
+ newResultDocList.push(subResultDocs);
30
+ return newResultDocList;
31
+ }
32
+ exports.splitListOfDocs = splitListOfDocs;
33
+ /**
34
+ * Collapses a list of documents into a single document.
35
+ *
36
+ * This function takes a list of documents and a function to combine the content of these documents.
37
+ * It combines the content of the documents using the provided function and merges the metadata of all documents.
38
+ * If a metadata key is present in multiple documents, the values are concatenated with a comma separator.
39
+ *
40
+ * @param {Document[]} docs - The list of documents to be collapsed.
41
+ * @param {Function} combineDocumentFunc - A function that combines the content of a list of documents into a single string. This function should return a promise that resolves to the combined string.
42
+ *
43
+ * @returns {Promise<Document>} - A promise that resolves to a single document with combined content and merged metadata.
44
+ *
45
+ * @throws {Error} - Throws an error if the combineDocumentFunc does not return a promise or if the promise does not resolve to a string.
46
+ */
47
+ async function collapseDocs(docs, combineDocumentFunc) {
48
+ const result = await combineDocumentFunc(docs);
49
+ const combinedMetadata = {};
50
+ for (const key in docs[0].metadata) {
51
+ if (key in docs[0].metadata) {
52
+ combinedMetadata[key] = String(docs[0].metadata[key]);
53
+ }
54
+ }
55
+ for (const doc of docs.slice(1)) {
56
+ for (const key in doc.metadata) {
57
+ if (key in combinedMetadata) {
58
+ combinedMetadata[key] += `, ${doc.metadata[key]}`;
59
+ }
60
+ else {
61
+ combinedMetadata[key] = String(doc.metadata[key]);
62
+ }
63
+ }
64
+ }
65
+ return { pageContent: result, metadata: combinedMetadata };
66
+ }
67
+ exports.collapseDocs = collapseDocs;
@@ -0,0 +1,28 @@
1
+ import { Document } from "../../document.js";
2
+ /**
3
+ * Splits a list of documents into sublists based on a maximum token limit.
4
+ *
5
+ * @param {Document[]} docs - The list of documents to be split.
6
+ * @param {Function} lengthFunc - A function that calculates the number of tokens in a list of documents.
7
+ * @param {number} tokenMax - The maximum number of tokens allowed in a sublist.
8
+ *
9
+ * @returns {Document[][]} - A list of document sublists, each sublist contains documents whose total number of tokens does not exceed the tokenMax.
10
+ *
11
+ * @throws {Error} - Throws an error if a single document has more tokens than the tokenMax.
12
+ */
13
+ export declare function splitListOfDocs(docs: Document[], lengthFunc: (...args: any[]) => any, tokenMax: number): Document[][];
14
+ /**
15
+ * Collapses a list of documents into a single document.
16
+ *
17
+ * This function takes a list of documents and a function to combine the content of these documents.
18
+ * It combines the content of the documents using the provided function and merges the metadata of all documents.
19
+ * If a metadata key is present in multiple documents, the values are concatenated with a comma separator.
20
+ *
21
+ * @param {Document[]} docs - The list of documents to be collapsed.
22
+ * @param {Function} combineDocumentFunc - A function that combines the content of a list of documents into a single string. This function should return a promise that resolves to the combined string.
23
+ *
24
+ * @returns {Promise<Document>} - A promise that resolves to a single document with combined content and merged metadata.
25
+ *
26
+ * @throws {Error} - Throws an error if the combineDocumentFunc does not return a promise or if the promise does not resolve to a string.
27
+ */
28
+ export declare function collapseDocs(docs: Document[], combineDocumentFunc: (docs: Document[]) => Promise<string>): Promise<Document>;
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Splits a list of documents into sublists based on a maximum token limit.
3
+ *
4
+ * @param {Document[]} docs - The list of documents to be split.
5
+ * @param {Function} lengthFunc - A function that calculates the number of tokens in a list of documents.
6
+ * @param {number} tokenMax - The maximum number of tokens allowed in a sublist.
7
+ *
8
+ * @returns {Document[][]} - A list of document sublists, each sublist contains documents whose total number of tokens does not exceed the tokenMax.
9
+ *
10
+ * @throws {Error} - Throws an error if a single document has more tokens than the tokenMax.
11
+ */
12
+ export function splitListOfDocs(docs, lengthFunc, tokenMax) {
13
+ const newResultDocList = [];
14
+ let subResultDocs = [];
15
+ for (const doc of docs) {
16
+ subResultDocs.push(doc);
17
+ const numTokens = lengthFunc(subResultDocs);
18
+ if (numTokens > tokenMax) {
19
+ if (subResultDocs.length === 1) {
20
+ throw new Error("A single document was longer than the context length, we cannot handle this.");
21
+ }
22
+ newResultDocList.push(subResultDocs.slice(0, -1));
23
+ subResultDocs = subResultDocs.slice(-1);
24
+ }
25
+ }
26
+ newResultDocList.push(subResultDocs);
27
+ return newResultDocList;
28
+ }
29
+ /**
30
+ * Collapses a list of documents into a single document.
31
+ *
32
+ * This function takes a list of documents and a function to combine the content of these documents.
33
+ * It combines the content of the documents using the provided function and merges the metadata of all documents.
34
+ * If a metadata key is present in multiple documents, the values are concatenated with a comma separator.
35
+ *
36
+ * @param {Document[]} docs - The list of documents to be collapsed.
37
+ * @param {Function} combineDocumentFunc - A function that combines the content of a list of documents into a single string. This function should return a promise that resolves to the combined string.
38
+ *
39
+ * @returns {Promise<Document>} - A promise that resolves to a single document with combined content and merged metadata.
40
+ *
41
+ * @throws {Error} - Throws an error if the combineDocumentFunc does not return a promise or if the promise does not resolve to a string.
42
+ */
43
+ export async function collapseDocs(docs, combineDocumentFunc) {
44
+ const result = await combineDocumentFunc(docs);
45
+ const combinedMetadata = {};
46
+ for (const key in docs[0].metadata) {
47
+ if (key in docs[0].metadata) {
48
+ combinedMetadata[key] = String(docs[0].metadata[key]);
49
+ }
50
+ }
51
+ for (const doc of docs.slice(1)) {
52
+ for (const key in doc.metadata) {
53
+ if (key in combinedMetadata) {
54
+ combinedMetadata[key] += `, ${doc.metadata[key]}`;
55
+ }
56
+ else {
57
+ combinedMetadata[key] = String(doc.metadata[key]);
58
+ }
59
+ }
60
+ }
61
+ return { pageContent: result, metadata: combinedMetadata };
62
+ }
@@ -4,6 +4,7 @@ exports.ChatCloudflareWorkersAI = void 0;
4
4
  const base_js_1 = require("./base.cjs");
5
5
  const index_js_1 = require("../schema/index.cjs");
6
6
  const env_js_1 = require("../util/env.cjs");
7
+ const event_source_parse_js_1 = require("../util/event-source-parse.cjs");
7
8
  /**
8
9
  * A class that enables calls to the Cloudflare Workers AI API to access large language
9
10
  * models in a chat-like fashion. It extends the SimpleChatModel class and
@@ -45,7 +46,14 @@ class ChatCloudflareWorkersAI extends base_js_1.SimpleChatModel {
45
46
  writable: true,
46
47
  value: void 0
47
48
  });
49
+ Object.defineProperty(this, "streaming", {
50
+ enumerable: true,
51
+ configurable: true,
52
+ writable: true,
53
+ value: false
54
+ });
48
55
  this.model = fields?.model ?? this.model;
56
+ this.streaming = fields?.streaming ?? this.streaming;
49
57
  this.cloudflareAccountId =
50
58
  fields?.cloudflareAccountId ??
51
59
  (0, env_js_1.getEnvironmentVariable)("CLOUDFLARE_ACCOUNT_ID");
@@ -88,6 +96,50 @@ class ChatCloudflareWorkersAI extends base_js_1.SimpleChatModel {
88
96
  throw new Error(`No Cloudflare API key found. Please provide it when instantiating the CloudflareWorkersAI class, or set it as "CLOUDFLARE_API_KEY" in your environment variables.`);
89
97
  }
90
98
  }
99
+ async _request(messages, options, stream) {
100
+ this.validateEnvironment();
101
+ const url = `${this.baseUrl}/${this.model}`;
102
+ const headers = {
103
+ Authorization: `Bearer ${this.cloudflareApiToken}`,
104
+ "Content-Type": "application/json",
105
+ };
106
+ const formattedMessages = this._formatMessages(messages);
107
+ const data = { messages: formattedMessages, stream };
108
+ return this.caller.call(async () => {
109
+ const response = await fetch(url, {
110
+ method: "POST",
111
+ headers,
112
+ body: JSON.stringify(data),
113
+ signal: options.signal,
114
+ });
115
+ if (!response.ok) {
116
+ const error = new Error(`Cloudflare LLM call failed with status code ${response.status}`);
117
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
118
+ error.response = response;
119
+ throw error;
120
+ }
121
+ return response;
122
+ });
123
+ }
124
+ async *_streamResponseChunks(messages, options, runManager) {
125
+ const response = await this._request(messages, options, true);
126
+ if (!response.body) {
127
+ throw new Error("Empty response from Cloudflare. Please try again.");
128
+ }
129
+ const stream = (0, event_source_parse_js_1.convertEventStreamToIterableReadableDataStream)(response.body);
130
+ for await (const chunk of stream) {
131
+ if (chunk !== "[DONE]") {
132
+ const parsedChunk = JSON.parse(chunk);
133
+ const generationChunk = new index_js_1.ChatGenerationChunk({
134
+ message: new index_js_1.AIMessageChunk({ content: parsedChunk.response }),
135
+ text: parsedChunk.response,
136
+ });
137
+ yield generationChunk;
138
+ // eslint-disable-next-line no-void
139
+ void runManager?.handleLLMNewToken(generationChunk.text ?? "");
140
+ }
141
+ }
142
+ }
91
143
  _formatMessages(messages) {
92
144
  const formattedMessages = messages.map((message) => {
93
145
  let role;
@@ -115,31 +167,25 @@ class ChatCloudflareWorkersAI extends base_js_1.SimpleChatModel {
115
167
  return formattedMessages;
116
168
  }
117
169
  /** @ignore */
118
- async _call(messages, options) {
119
- this.validateEnvironment();
120
- const url = `${this.baseUrl}/${this.model}`;
121
- const headers = {
122
- Authorization: `Bearer ${this.cloudflareApiToken}`,
123
- "Content-Type": "application/json",
124
- };
125
- const formattedMessages = this._formatMessages(messages);
126
- const data = { messages: formattedMessages };
127
- const responseData = await this.caller.call(async () => {
128
- const response = await fetch(url, {
129
- method: "POST",
130
- headers,
131
- body: JSON.stringify(data),
132
- signal: options.signal,
133
- });
134
- if (!response.ok) {
135
- const error = new Error(`Cloudflare LLM call failed with status code ${response.status}`);
136
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
137
- error.response = response;
138
- throw error;
170
+ async _call(messages, options, runManager) {
171
+ if (!this.streaming) {
172
+ const response = await this._request(messages, options);
173
+ const responseData = await response.json();
174
+ return responseData.result.response;
175
+ }
176
+ else {
177
+ const stream = this._streamResponseChunks(messages, options, runManager);
178
+ let finalResult;
179
+ for await (const chunk of stream) {
180
+ if (finalResult === undefined) {
181
+ finalResult = chunk;
182
+ }
183
+ else {
184
+ finalResult = finalResult.concat(chunk);
185
+ }
139
186
  }
140
- return response.json();
141
- });
142
- return responseData.result.response;
187
+ return finalResult?.message?.content ?? "";
188
+ }
143
189
  }
144
190
  }
145
191
  exports.ChatCloudflareWorkersAI = ChatCloudflareWorkersAI;
@@ -1,7 +1,8 @@
1
1
  import { SimpleChatModel, BaseChatModelParams } from "./base.js";
2
2
  import { BaseLanguageModelCallOptions } from "../base_language/index.js";
3
- import { BaseMessage } from "../schema/index.js";
3
+ import { BaseMessage, ChatGenerationChunk } from "../schema/index.js";
4
4
  import { CloudflareWorkersAIInput } from "../llms/cloudflare_workersai.js";
5
+ import { CallbackManagerForLLMRun } from "../callbacks/manager.js";
5
6
  /**
6
7
  * An interface defining the options for a Cloudflare Workers AI call. It extends
7
8
  * the BaseLanguageModelCallOptions interface.
@@ -20,6 +21,7 @@ export declare class ChatCloudflareWorkersAI extends SimpleChatModel implements
20
21
  cloudflareAccountId?: string;
21
22
  cloudflareApiToken?: string;
22
23
  baseUrl: string;
24
+ streaming: boolean;
23
25
  constructor(fields?: CloudflareWorkersAIInput & BaseChatModelParams);
24
26
  _llmType(): string;
25
27
  /** Get the identifying parameters for this LLM. */
@@ -37,10 +39,12 @@ export declare class ChatCloudflareWorkersAI extends SimpleChatModel implements
37
39
  * Method to validate the environment.
38
40
  */
39
41
  validateEnvironment(): void;
42
+ _request(messages: BaseMessage[], options: this["ParsedCallOptions"], stream?: boolean): Promise<Response>;
43
+ _streamResponseChunks(messages: BaseMessage[], options: this["ParsedCallOptions"], runManager?: CallbackManagerForLLMRun): AsyncGenerator<ChatGenerationChunk>;
40
44
  protected _formatMessages(messages: BaseMessage[]): {
41
45
  role: string;
42
46
  content: string;
43
47
  }[];
44
48
  /** @ignore */
45
- _call(messages: BaseMessage[], options: this["ParsedCallOptions"]): Promise<string>;
49
+ _call(messages: BaseMessage[], options: this["ParsedCallOptions"], runManager?: CallbackManagerForLLMRun): Promise<string>;
46
50
  }
@@ -1,6 +1,7 @@
1
1
  import { SimpleChatModel } from "./base.js";
2
- import { ChatMessage } from "../schema/index.js";
2
+ import { AIMessageChunk, ChatGenerationChunk, ChatMessage, } from "../schema/index.js";
3
3
  import { getEnvironmentVariable } from "../util/env.js";
4
+ import { convertEventStreamToIterableReadableDataStream } from "../util/event-source-parse.js";
4
5
  /**
5
6
  * A class that enables calls to the Cloudflare Workers AI API to access large language
6
7
  * models in a chat-like fashion. It extends the SimpleChatModel class and
@@ -42,7 +43,14 @@ export class ChatCloudflareWorkersAI extends SimpleChatModel {
42
43
  writable: true,
43
44
  value: void 0
44
45
  });
46
+ Object.defineProperty(this, "streaming", {
47
+ enumerable: true,
48
+ configurable: true,
49
+ writable: true,
50
+ value: false
51
+ });
45
52
  this.model = fields?.model ?? this.model;
53
+ this.streaming = fields?.streaming ?? this.streaming;
46
54
  this.cloudflareAccountId =
47
55
  fields?.cloudflareAccountId ??
48
56
  getEnvironmentVariable("CLOUDFLARE_ACCOUNT_ID");
@@ -85,6 +93,50 @@ export class ChatCloudflareWorkersAI extends SimpleChatModel {
85
93
  throw new Error(`No Cloudflare API key found. Please provide it when instantiating the CloudflareWorkersAI class, or set it as "CLOUDFLARE_API_KEY" in your environment variables.`);
86
94
  }
87
95
  }
96
+ async _request(messages, options, stream) {
97
+ this.validateEnvironment();
98
+ const url = `${this.baseUrl}/${this.model}`;
99
+ const headers = {
100
+ Authorization: `Bearer ${this.cloudflareApiToken}`,
101
+ "Content-Type": "application/json",
102
+ };
103
+ const formattedMessages = this._formatMessages(messages);
104
+ const data = { messages: formattedMessages, stream };
105
+ return this.caller.call(async () => {
106
+ const response = await fetch(url, {
107
+ method: "POST",
108
+ headers,
109
+ body: JSON.stringify(data),
110
+ signal: options.signal,
111
+ });
112
+ if (!response.ok) {
113
+ const error = new Error(`Cloudflare LLM call failed with status code ${response.status}`);
114
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
115
+ error.response = response;
116
+ throw error;
117
+ }
118
+ return response;
119
+ });
120
+ }
121
+ async *_streamResponseChunks(messages, options, runManager) {
122
+ const response = await this._request(messages, options, true);
123
+ if (!response.body) {
124
+ throw new Error("Empty response from Cloudflare. Please try again.");
125
+ }
126
+ const stream = convertEventStreamToIterableReadableDataStream(response.body);
127
+ for await (const chunk of stream) {
128
+ if (chunk !== "[DONE]") {
129
+ const parsedChunk = JSON.parse(chunk);
130
+ const generationChunk = new ChatGenerationChunk({
131
+ message: new AIMessageChunk({ content: parsedChunk.response }),
132
+ text: parsedChunk.response,
133
+ });
134
+ yield generationChunk;
135
+ // eslint-disable-next-line no-void
136
+ void runManager?.handleLLMNewToken(generationChunk.text ?? "");
137
+ }
138
+ }
139
+ }
88
140
  _formatMessages(messages) {
89
141
  const formattedMessages = messages.map((message) => {
90
142
  let role;
@@ -112,30 +164,24 @@ export class ChatCloudflareWorkersAI extends SimpleChatModel {
112
164
  return formattedMessages;
113
165
  }
114
166
  /** @ignore */
115
- async _call(messages, options) {
116
- this.validateEnvironment();
117
- const url = `${this.baseUrl}/${this.model}`;
118
- const headers = {
119
- Authorization: `Bearer ${this.cloudflareApiToken}`,
120
- "Content-Type": "application/json",
121
- };
122
- const formattedMessages = this._formatMessages(messages);
123
- const data = { messages: formattedMessages };
124
- const responseData = await this.caller.call(async () => {
125
- const response = await fetch(url, {
126
- method: "POST",
127
- headers,
128
- body: JSON.stringify(data),
129
- signal: options.signal,
130
- });
131
- if (!response.ok) {
132
- const error = new Error(`Cloudflare LLM call failed with status code ${response.status}`);
133
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
134
- error.response = response;
135
- throw error;
167
+ async _call(messages, options, runManager) {
168
+ if (!this.streaming) {
169
+ const response = await this._request(messages, options);
170
+ const responseData = await response.json();
171
+ return responseData.result.response;
172
+ }
173
+ else {
174
+ const stream = this._streamResponseChunks(messages, options, runManager);
175
+ let finalResult;
176
+ for await (const chunk of stream) {
177
+ if (finalResult === undefined) {
178
+ finalResult = chunk;
179
+ }
180
+ else {
181
+ finalResult = finalResult.concat(chunk);
182
+ }
136
183
  }
137
- return response.json();
138
- });
139
- return responseData.result.response;
184
+ return finalResult?.message?.content ?? "";
185
+ }
140
186
  }
141
187
  }