@nocobase/plugin-ai 2.2.0-alpha.2 → 2.2.0-alpha.4

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 (53) hide show
  1. package/dist/ai/docs/nocobase/api/cli/env/auth.md +53 -5
  2. package/dist/ai/docs/nocobase/ops-management/version-control/index.md +1 -0
  3. package/dist/client/559.9f97ebcdb0bd6231.js +10 -0
  4. package/dist/client/{604.de96f3ec4d471afd.js → 604.89c674f35b52b4ef.js} +1 -1
  5. package/dist/client/index.js +3 -3
  6. package/dist/client/llm-providers/mistral/ModelSettings.d.ts +10 -0
  7. package/dist/client/llm-providers/mistral/index.d.ts +10 -0
  8. package/dist/client/llm-services/utils.d.ts +5 -0
  9. package/dist/externalVersion.js +16 -16
  10. package/dist/locale/en-US.json +1 -0
  11. package/dist/locale/zh-CN.json +1 -0
  12. package/dist/node_modules/@langchain/mistralai/LICENSE +21 -0
  13. package/dist/node_modules/@langchain/mistralai/dist/_virtual/rolldown_runtime.cjs +25 -0
  14. package/dist/node_modules/@langchain/mistralai/dist/chat_models.cjs +859 -0
  15. package/dist/node_modules/@langchain/mistralai/dist/chat_models.d.cts +541 -0
  16. package/dist/node_modules/@langchain/mistralai/dist/chat_models.d.ts +541 -0
  17. package/dist/node_modules/@langchain/mistralai/dist/chat_models.js +857 -0
  18. package/dist/node_modules/@langchain/mistralai/dist/embeddings.cjs +140 -0
  19. package/dist/node_modules/@langchain/mistralai/dist/embeddings.d.cts +116 -0
  20. package/dist/node_modules/@langchain/mistralai/dist/embeddings.d.ts +116 -0
  21. package/dist/node_modules/@langchain/mistralai/dist/embeddings.js +139 -0
  22. package/dist/node_modules/@langchain/mistralai/dist/index.cjs +21 -0
  23. package/dist/node_modules/@langchain/mistralai/dist/index.d.cts +4 -0
  24. package/dist/node_modules/@langchain/mistralai/dist/index.d.ts +4 -0
  25. package/dist/node_modules/@langchain/mistralai/dist/index.js +5 -0
  26. package/dist/node_modules/@langchain/mistralai/dist/llms.cjs +275 -0
  27. package/dist/node_modules/@langchain/mistralai/dist/llms.d.cts +147 -0
  28. package/dist/node_modules/@langchain/mistralai/dist/llms.d.ts +147 -0
  29. package/dist/node_modules/@langchain/mistralai/dist/llms.js +274 -0
  30. package/dist/node_modules/@langchain/mistralai/dist/utils.cjs +61 -0
  31. package/dist/node_modules/@langchain/mistralai/dist/utils.js +59 -0
  32. package/dist/node_modules/@langchain/mistralai/package.json +1 -0
  33. package/dist/node_modules/@langchain/xai/dist/index.cjs +2 -2
  34. package/dist/node_modules/@langchain/xai/package.json +1 -1
  35. package/dist/node_modules/fs-extra/package.json +1 -1
  36. package/dist/node_modules/jsonrepair/package.json +1 -1
  37. package/dist/node_modules/just-bash/package.json +1 -1
  38. package/dist/node_modules/nodejs-snowflake/package.json +1 -1
  39. package/dist/node_modules/openai/package.json +1 -1
  40. package/dist/node_modules/zod/package.json +1 -1
  41. package/dist/server/ai-employees/ai-employee.js +7 -5
  42. package/dist/server/ai-employees/middleware/conversation.d.ts +2 -0
  43. package/dist/server/ai-employees/middleware/conversation.js +2 -1
  44. package/dist/server/ai-employees/utils.d.ts +3 -1
  45. package/dist/server/ai-employees/utils.js +2 -0
  46. package/dist/server/llm-providers/mistral.d.ts +62 -0
  47. package/dist/server/llm-providers/mistral.js +265 -0
  48. package/dist/server/llm-providers/provider.d.ts +6 -2
  49. package/dist/server/llm-providers/provider.js +27 -14
  50. package/dist/server/plugin.js +2 -0
  51. package/dist/server/workflow/nodes/employee/index.js +91 -45
  52. package/package.json +3 -2
  53. package/dist/client/559.a0f2f1cc2be3c039.js +0 -10
@@ -0,0 +1,857 @@
1
+ import { _convertToolCallIdToMistralCompatible, _mistralContentChunkToMessageContentComplex } from "./utils.js";
2
+ import { v4 } from "uuid";
3
+ import { Mistral } from "@mistralai/mistralai";
4
+ import { HTTPClient } from "@mistralai/mistralai/lib/http.js";
5
+ import { AIMessage, AIMessageChunk, ChatMessageChunk, FunctionMessageChunk, HumanMessage, HumanMessageChunk, ToolMessageChunk, isAIMessage } from "@langchain/core/messages";
6
+ import { BaseChatModel } from "@langchain/core/language_models/chat_models";
7
+ import { ChatGenerationChunk } from "@langchain/core/outputs";
8
+ import { AsyncCaller } from "@langchain/core/utils/async_caller";
9
+ import { getEnvironmentVariable } from "@langchain/core/utils/env";
10
+ import { JsonOutputParser, StructuredOutputParser } from "@langchain/core/output_parsers";
11
+ import { JsonOutputKeyToolsParser, convertLangChainToolCallToOpenAI, makeInvalidToolCall, parseToolCall } from "@langchain/core/output_parsers/openai_tools";
12
+ import { RunnableBinding, RunnablePassthrough, RunnableSequence } from "@langchain/core/runnables";
13
+ import { toJsonSchema } from "@langchain/core/utils/json_schema";
14
+ import { isLangChainTool } from "@langchain/core/utils/function_calling";
15
+ import { isInteropZodSchema } from "@langchain/core/utils/types";
16
+
17
+ //#region src/chat_models.ts
18
+ function convertMessagesToMistralMessages(messages) {
19
+ const getRole = (role) => {
20
+ switch (role) {
21
+ case "human": return "user";
22
+ case "ai": return "assistant";
23
+ case "system": return "system";
24
+ case "tool": return "tool";
25
+ case "function": return "assistant";
26
+ default: throw new Error(`Unknown message type: ${role}`);
27
+ }
28
+ };
29
+ const getContent = (content, type) => {
30
+ const _generateContentChunk = (complex, role) => {
31
+ if (complex.type === "image_url" && (role === "user" || role === "assistant")) return {
32
+ type: complex.type,
33
+ imageUrl: complex?.image_url
34
+ };
35
+ if (complex.type === "text") return {
36
+ type: complex.type,
37
+ text: complex?.text
38
+ };
39
+ throw new Error(`ChatMistralAI only supports messages of "image_url" for roles "user" and "assistant", and "text" for all others.\n\nReceived: ${JSON.stringify(content, null, 2)}`);
40
+ };
41
+ if (typeof content === "string") return content;
42
+ if (Array.isArray(content)) {
43
+ const mistralRole = getRole(type);
44
+ const newContent = [];
45
+ content.forEach((messageContentComplex) => {
46
+ if (messageContentComplex.type === "text" || messageContentComplex.type === "image_url") newContent.push(_generateContentChunk(messageContentComplex, mistralRole));
47
+ else throw new Error(`Mistral only supports types "text" or "image_url" for complex message types.`);
48
+ });
49
+ return newContent;
50
+ }
51
+ throw new Error(`Message content must be a string or an array.\n\nReceived: ${JSON.stringify(content, null, 2)}`);
52
+ };
53
+ const getTools = (message) => {
54
+ if (isAIMessage(message) && !!message.tool_calls?.length) return message.tool_calls.map((toolCall) => ({
55
+ ...toolCall,
56
+ id: _convertToolCallIdToMistralCompatible(toolCall.id ?? "")
57
+ })).map(convertLangChainToolCallToOpenAI);
58
+ return void 0;
59
+ };
60
+ const toolResponseIds = /* @__PURE__ */ new Set();
61
+ for (const m of messages) if ("tool_call_id" in m && typeof m.tool_call_id === "string") toolResponseIds.add(_convertToolCallIdToMistralCompatible(m.tool_call_id));
62
+ return messages.flatMap((message) => {
63
+ const toolCalls = getTools(message);
64
+ const content = getContent(message.content, message.getType());
65
+ if ("tool_call_id" in message && typeof message.tool_call_id === "string") return [{
66
+ role: getRole(message.getType()),
67
+ content,
68
+ name: message.name,
69
+ toolCallId: _convertToolCallIdToMistralCompatible(message.tool_call_id)
70
+ }];
71
+ else if (isAIMessage(message)) if (toolCalls === void 0) return [{
72
+ role: getRole(message.getType()),
73
+ content
74
+ }];
75
+ else {
76
+ const filteredToolCalls = toolCalls.filter((tc) => toolResponseIds.has(_convertToolCallIdToMistralCompatible(tc.id ?? "")));
77
+ if (filteredToolCalls.length === 0) {
78
+ const isEmptyContent = typeof content === "string" && content.trim() === "" || Array.isArray(content) && content.length === 0;
79
+ if (isEmptyContent) return [];
80
+ return [{
81
+ role: getRole(message.getType()),
82
+ content
83
+ }];
84
+ }
85
+ return [{
86
+ role: getRole(message.getType()),
87
+ toolCalls: filteredToolCalls
88
+ }];
89
+ }
90
+ return [{
91
+ role: getRole(message.getType()),
92
+ content
93
+ }];
94
+ });
95
+ }
96
+ function mistralAIResponseToChatMessage(choice, usage) {
97
+ const { message } = choice;
98
+ if (message === void 0) throw new Error("No message found in response");
99
+ let rawToolCalls = [];
100
+ if ("toolCalls" in message && Array.isArray(message.toolCalls)) rawToolCalls = message.toolCalls;
101
+ const content = _mistralContentChunkToMessageContentComplex(message.content);
102
+ switch (message.role) {
103
+ case "assistant": {
104
+ const toolCalls = [];
105
+ const invalidToolCalls = [];
106
+ for (const rawToolCall of rawToolCalls) try {
107
+ const parsed = parseToolCall(rawToolCall, { returnId: true });
108
+ toolCalls.push({
109
+ ...parsed,
110
+ id: parsed.id ?? v4().replace(/-/g, "")
111
+ });
112
+ } catch (e) {
113
+ invalidToolCalls.push(makeInvalidToolCall(rawToolCall, e.message));
114
+ }
115
+ return new AIMessage({
116
+ content,
117
+ tool_calls: toolCalls,
118
+ invalid_tool_calls: invalidToolCalls,
119
+ additional_kwargs: {},
120
+ usage_metadata: usage ? {
121
+ input_tokens: usage.promptTokens,
122
+ output_tokens: usage.completionTokens,
123
+ total_tokens: usage.totalTokens
124
+ } : void 0
125
+ });
126
+ }
127
+ default: return new HumanMessage({ content });
128
+ }
129
+ }
130
+ function _convertDeltaToMessageChunk(delta, usage) {
131
+ if (!delta.content && !delta.toolCalls) {
132
+ if (usage) return new AIMessageChunk({
133
+ content: "",
134
+ usage_metadata: usage ? {
135
+ input_tokens: usage.promptTokens,
136
+ output_tokens: usage.completionTokens,
137
+ total_tokens: usage.totalTokens
138
+ } : void 0
139
+ });
140
+ return null;
141
+ }
142
+ const rawToolCallChunksWithIndex = delta.toolCalls?.length ? delta.toolCalls?.map((toolCall, index) => ({
143
+ ...toolCall,
144
+ index,
145
+ id: toolCall.id ?? v4().replace(/-/g, ""),
146
+ type: "function"
147
+ })) : void 0;
148
+ let role = "assistant";
149
+ if (delta.role) role = delta.role;
150
+ const content = _mistralContentChunkToMessageContentComplex(delta.content);
151
+ let additional_kwargs;
152
+ const toolCallChunks = [];
153
+ if (rawToolCallChunksWithIndex !== void 0) for (const rawToolCallChunk of rawToolCallChunksWithIndex) {
154
+ const rawArgs = rawToolCallChunk.function?.arguments;
155
+ const args = rawArgs === void 0 || typeof rawArgs === "string" ? rawArgs : JSON.stringify(rawArgs);
156
+ toolCallChunks.push({
157
+ name: rawToolCallChunk.function?.name,
158
+ args,
159
+ id: rawToolCallChunk.id,
160
+ index: rawToolCallChunk.index,
161
+ type: "tool_call_chunk"
162
+ });
163
+ }
164
+ else additional_kwargs = {};
165
+ if (role === "user") return new HumanMessageChunk({ content });
166
+ else if (role === "assistant") return new AIMessageChunk({
167
+ content,
168
+ tool_call_chunks: toolCallChunks,
169
+ additional_kwargs,
170
+ usage_metadata: usage ? {
171
+ input_tokens: usage.promptTokens,
172
+ output_tokens: usage.completionTokens,
173
+ total_tokens: usage.totalTokens
174
+ } : void 0
175
+ });
176
+ else if (role === "tool") return new ToolMessageChunk({
177
+ content,
178
+ additional_kwargs,
179
+ tool_call_id: rawToolCallChunksWithIndex?.[0].id ?? ""
180
+ });
181
+ else if (role === "function") return new FunctionMessageChunk({
182
+ content,
183
+ additional_kwargs
184
+ });
185
+ else return new ChatMessageChunk({
186
+ content,
187
+ role
188
+ });
189
+ }
190
+ function _convertToolToMistralTool(tools) {
191
+ if (!tools || !tools.length) return void 0;
192
+ return tools.map((tool) => {
193
+ if ("function" in tool) return {
194
+ type: tool.type ?? "function",
195
+ function: tool.function
196
+ };
197
+ if (isLangChainTool(tool)) {
198
+ const description = tool.description ?? `Tool: ${tool.name}`;
199
+ return {
200
+ type: "function",
201
+ function: {
202
+ name: tool.name,
203
+ description,
204
+ parameters: isInteropZodSchema(tool.schema) ? toJsonSchema(tool.schema) : tool.schema
205
+ }
206
+ };
207
+ }
208
+ throw new Error(`Unknown tool type passed to ChatMistral: ${JSON.stringify(tool, null, 2)}`);
209
+ });
210
+ }
211
+ /**
212
+ * Mistral AI chat model integration.
213
+ *
214
+ * Setup:
215
+ * Install `@langchain/mistralai` and set an environment variable named `MISTRAL_API_KEY`.
216
+ *
217
+ * ```bash
218
+ * npm install @langchain/mistralai
219
+ * export MISTRAL_API_KEY="your-api-key"
220
+ * ```
221
+ *
222
+ * ## [Constructor args](https://api.js.langchain.com/classes/_langchain_mistralai.ChatMistralAI.html#constructor)
223
+ *
224
+ * ## [Runtime args](https://api.js.langchain.com/interfaces/_langchain_mistralai.ChatMistralAICallOptions.html)
225
+ *
226
+ * Runtime args can be passed as the second argument to any of the base runnable methods `.invoke`. `.stream`, `.batch`, etc.
227
+ * They can also be passed via `.withConfig`, or the second arg in `.bindTools`, like shown in the examples below:
228
+ *
229
+ * ```typescript
230
+ * // When calling `.withConfig`, call options should be passed via the first argument
231
+ * const llmWithArgsBound = llm.bindTools([...]) // tools array
232
+ * .withConfig({
233
+ * stop: ["\n"], // other call options
234
+ * });
235
+ *
236
+ * // You can also bind tools and call options like this
237
+ * const llmWithTools = llm.bindTools([...], {
238
+ * tool_choice: "auto",
239
+ * });
240
+ * ```
241
+ *
242
+ * ## Examples
243
+ *
244
+ * <details open>
245
+ * <summary><strong>Instantiate</strong></summary>
246
+ *
247
+ * ```typescript
248
+ * import { ChatMistralAI } from '@langchain/mistralai';
249
+ *
250
+ * const llm = new ChatMistralAI({
251
+ * model: "mistral-large-2402",
252
+ * temperature: 0,
253
+ * // other params...
254
+ * });
255
+ * ```
256
+ * </details>
257
+ *
258
+ * <br />
259
+ *
260
+ * <details>
261
+ * <summary><strong>Invoking</strong></summary>
262
+ *
263
+ * ```typescript
264
+ * const input = `Translate "I love programming" into French.`;
265
+ *
266
+ * // Models also accept a list of chat messages or a formatted prompt
267
+ * const result = await llm.invoke(input);
268
+ * console.log(result);
269
+ * ```
270
+ *
271
+ * ```txt
272
+ * AIMessage {
273
+ * "content": "The translation of \"I love programming\" into French is \"J'aime la programmation\". Here's the breakdown:\n\n- \"I\" translates to \"Je\"\n- \"love\" translates to \"aime\"\n- \"programming\" translates to \"la programmation\"\n\nSo, \"J'aime la programmation\" means \"I love programming\" in French.",
274
+ * "additional_kwargs": {},
275
+ * "response_metadata": {
276
+ * "tokenUsage": {
277
+ * "completionTokens": 89,
278
+ * "promptTokens": 13,
279
+ * "totalTokens": 102
280
+ * },
281
+ * "finish_reason": "stop"
282
+ * },
283
+ * "tool_calls": [],
284
+ * "invalid_tool_calls": [],
285
+ * "usage_metadata": {
286
+ * "input_tokens": 13,
287
+ * "output_tokens": 89,
288
+ * "total_tokens": 102
289
+ * }
290
+ * }
291
+ * ```
292
+ * </details>
293
+ *
294
+ * <br />
295
+ *
296
+ * <details>
297
+ * <summary><strong>Streaming Chunks</strong></summary>
298
+ *
299
+ * ```typescript
300
+ * for await (const chunk of await llm.stream(input)) {
301
+ * console.log(chunk);
302
+ * }
303
+ * ```
304
+ *
305
+ * ```txt
306
+ * AIMessageChunk {
307
+ * "content": "The",
308
+ * "additional_kwargs": {},
309
+ * "response_metadata": {
310
+ * "prompt": 0,
311
+ * "completion": 0
312
+ * },
313
+ * "tool_calls": [],
314
+ * "tool_call_chunks": [],
315
+ * "invalid_tool_calls": []
316
+ * }
317
+ * AIMessageChunk {
318
+ * "content": " translation",
319
+ * "additional_kwargs": {},
320
+ * "response_metadata": {
321
+ * "prompt": 0,
322
+ * "completion": 0
323
+ * },
324
+ * "tool_calls": [],
325
+ * "tool_call_chunks": [],
326
+ * "invalid_tool_calls": []
327
+ * }
328
+ * AIMessageChunk {
329
+ * "content": " of",
330
+ * "additional_kwargs": {},
331
+ * "response_metadata": {
332
+ * "prompt": 0,
333
+ * "completion": 0
334
+ * },
335
+ * "tool_calls": [],
336
+ * "tool_call_chunks": [],
337
+ * "invalid_tool_calls": []
338
+ * }
339
+ * AIMessageChunk {
340
+ * "content": " \"",
341
+ * "additional_kwargs": {},
342
+ * "response_metadata": {
343
+ * "prompt": 0,
344
+ * "completion": 0
345
+ * },
346
+ * "tool_calls": [],
347
+ * "tool_call_chunks": [],
348
+ * "invalid_tool_calls": []
349
+ * }
350
+ * AIMessageChunk {
351
+ * "content": "I",
352
+ * "additional_kwargs": {},
353
+ * "response_metadata": {
354
+ * "prompt": 0,
355
+ * "completion": 0
356
+ * },
357
+ * "tool_calls": [],
358
+ * "tool_call_chunks": [],
359
+ * "invalid_tool_calls": []
360
+ * }
361
+ * AIMessageChunk {
362
+ * "content": ".",
363
+ * "additional_kwargs": {},
364
+ * "response_metadata": {
365
+ * "prompt": 0,
366
+ * "completion": 0
367
+ * },
368
+ * "tool_calls": [],
369
+ * "tool_call_chunks": [],
370
+ * "invalid_tool_calls": []
371
+ *}
372
+ *AIMessageChunk {
373
+ * "content": "",
374
+ * "additional_kwargs": {},
375
+ * "response_metadata": {
376
+ * "prompt": 0,
377
+ * "completion": 0
378
+ * },
379
+ * "tool_calls": [],
380
+ * "tool_call_chunks": [],
381
+ * "invalid_tool_calls": [],
382
+ * "usage_metadata": {
383
+ * "input_tokens": 13,
384
+ * "output_tokens": 89,
385
+ * "total_tokens": 102
386
+ * }
387
+ *}
388
+ * ```
389
+ * </details>
390
+ *
391
+ * <br />
392
+ *
393
+ * <details>
394
+ * <summary><strong>Aggregate Streamed Chunks</strong></summary>
395
+ *
396
+ * ```typescript
397
+ * import { AIMessageChunk } from '@langchain/core/messages';
398
+ * import { concat } from '@langchain/core/utils/stream';
399
+ *
400
+ * const stream = await llm.stream(input);
401
+ * let full: AIMessageChunk | undefined;
402
+ * for await (const chunk of stream) {
403
+ * full = !full ? chunk : concat(full, chunk);
404
+ * }
405
+ * console.log(full);
406
+ * ```
407
+ *
408
+ * ```txt
409
+ * AIMessageChunk {
410
+ * "content": "The translation of \"I love programming\" into French is \"J'aime la programmation\". Here's the breakdown:\n\n- \"I\" translates to \"Je\"\n- \"love\" translates to \"aime\"\n- \"programming\" translates to \"la programmation\"\n\nSo, \"J'aime la programmation\" means \"I love programming\" in French.",
411
+ * "additional_kwargs": {},
412
+ * "response_metadata": {
413
+ * "prompt": 0,
414
+ * "completion": 0
415
+ * },
416
+ * "tool_calls": [],
417
+ * "tool_call_chunks": [],
418
+ * "invalid_tool_calls": [],
419
+ * "usage_metadata": {
420
+ * "input_tokens": 13,
421
+ * "output_tokens": 89,
422
+ * "total_tokens": 102
423
+ * }
424
+ * }
425
+ * ```
426
+ * </details>
427
+ *
428
+ * <br />
429
+ *
430
+ * <details>
431
+ * <summary><strong>Bind tools</strong></summary>
432
+ *
433
+ * ```typescript
434
+ * import { z } from 'zod';
435
+ *
436
+ * const GetWeather = {
437
+ * name: "GetWeather",
438
+ * description: "Get the current weather in a given location",
439
+ * schema: z.object({
440
+ * location: z.string().describe("The city and state, e.g. San Francisco, CA")
441
+ * }),
442
+ * }
443
+ *
444
+ * const GetPopulation = {
445
+ * name: "GetPopulation",
446
+ * description: "Get the current population in a given location",
447
+ * schema: z.object({
448
+ * location: z.string().describe("The city and state, e.g. San Francisco, CA")
449
+ * }),
450
+ * }
451
+ *
452
+ * const llmWithTools = llm.bindTools([GetWeather, GetPopulation]);
453
+ * const aiMsg = await llmWithTools.invoke(
454
+ * "Which city is hotter today and which is bigger: LA or NY?"
455
+ * );
456
+ * console.log(aiMsg.tool_calls);
457
+ * ```
458
+ *
459
+ * ```txt
460
+ * [
461
+ * {
462
+ * name: 'GetWeather',
463
+ * args: { location: 'Los Angeles, CA' },
464
+ * type: 'tool_call',
465
+ * id: '47i216yko'
466
+ * },
467
+ * {
468
+ * name: 'GetWeather',
469
+ * args: { location: 'New York, NY' },
470
+ * type: 'tool_call',
471
+ * id: 'nb3v8Fpcn'
472
+ * },
473
+ * {
474
+ * name: 'GetPopulation',
475
+ * args: { location: 'Los Angeles, CA' },
476
+ * type: 'tool_call',
477
+ * id: 'EedWzByIB'
478
+ * },
479
+ * {
480
+ * name: 'GetPopulation',
481
+ * args: { location: 'New York, NY' },
482
+ * type: 'tool_call',
483
+ * id: 'jLdLia7zC'
484
+ * }
485
+ * ]
486
+ * ```
487
+ * </details>
488
+ *
489
+ * <br />
490
+ *
491
+ * <details>
492
+ * <summary><strong>Structured Output</strong></summary>
493
+ *
494
+ * ```typescript
495
+ * import { z } from 'zod';
496
+ *
497
+ * const Joke = z.object({
498
+ * setup: z.string().describe("The setup of the joke"),
499
+ * punchline: z.string().describe("The punchline to the joke"),
500
+ * rating: z.number().optional().describe("How funny the joke is, from 1 to 10")
501
+ * }).describe('Joke to tell user.');
502
+ *
503
+ * const structuredLlm = llm.withStructuredOutput(Joke, { name: "Joke" });
504
+ * const jokeResult = await structuredLlm.invoke("Tell me a joke about cats");
505
+ * console.log(jokeResult);
506
+ * ```
507
+ *
508
+ * ```txt
509
+ * {
510
+ * setup: "Why don't cats play poker in the jungle?",
511
+ * punchline: 'Too many cheetahs!',
512
+ * rating: 7
513
+ * }
514
+ * ```
515
+ * </details>
516
+ *
517
+ * <br />
518
+ *
519
+ * <details>
520
+ * <summary><strong>Usage Metadata</strong></summary>
521
+ *
522
+ * ```typescript
523
+ * const aiMsgForMetadata = await llm.invoke(input);
524
+ * console.log(aiMsgForMetadata.usage_metadata);
525
+ * ```
526
+ *
527
+ * ```txt
528
+ * { input_tokens: 13, output_tokens: 89, total_tokens: 102 }
529
+ * ```
530
+ * </details>
531
+ *
532
+ * <br />
533
+ */
534
+ var ChatMistralAI = class extends BaseChatModel {
535
+ static lc_name() {
536
+ return "ChatMistralAI";
537
+ }
538
+ lc_namespace = [
539
+ "langchain",
540
+ "chat_models",
541
+ "mistralai"
542
+ ];
543
+ model = "mistral-small-latest";
544
+ apiKey;
545
+ /**
546
+ * @deprecated use serverURL instead
547
+ */
548
+ endpoint;
549
+ serverURL;
550
+ temperature = .7;
551
+ streaming = false;
552
+ topP = 1;
553
+ maxTokens;
554
+ /**
555
+ * @deprecated use safePrompt instead
556
+ */
557
+ safeMode = false;
558
+ safePrompt = false;
559
+ randomSeed;
560
+ seed;
561
+ maxRetries;
562
+ lc_serializable = true;
563
+ streamUsage = true;
564
+ beforeRequestHooks;
565
+ requestErrorHooks;
566
+ responseHooks;
567
+ httpClient;
568
+ presencePenalty;
569
+ frequencyPenalty;
570
+ numCompletions;
571
+ constructor(fields) {
572
+ super(fields ?? {});
573
+ const apiKey = fields?.apiKey ?? getEnvironmentVariable("MISTRAL_API_KEY");
574
+ if (!apiKey) throw new Error("API key MISTRAL_API_KEY is missing for MistralAI, but it is required.");
575
+ this.apiKey = apiKey;
576
+ this.streaming = fields?.streaming ?? this.streaming;
577
+ this.serverURL = fields?.serverURL ?? this.serverURL;
578
+ this.temperature = fields?.temperature ?? this.temperature;
579
+ this.topP = fields?.topP ?? this.topP;
580
+ this.maxTokens = fields?.maxTokens ?? this.maxTokens;
581
+ this.safePrompt = fields?.safePrompt ?? this.safePrompt;
582
+ this.randomSeed = fields?.seed ?? fields?.randomSeed ?? this.seed;
583
+ this.seed = this.randomSeed;
584
+ this.maxRetries = fields?.maxRetries;
585
+ this.httpClient = fields?.httpClient;
586
+ this.model = fields?.model ?? fields?.modelName ?? this.model;
587
+ this.streamUsage = fields?.streamUsage ?? this.streamUsage;
588
+ this.beforeRequestHooks = fields?.beforeRequestHooks ?? this.beforeRequestHooks;
589
+ this.requestErrorHooks = fields?.requestErrorHooks ?? this.requestErrorHooks;
590
+ this.responseHooks = fields?.responseHooks ?? this.responseHooks;
591
+ this.presencePenalty = fields?.presencePenalty ?? this.presencePenalty;
592
+ this.frequencyPenalty = fields?.frequencyPenalty ?? this.frequencyPenalty;
593
+ this.numCompletions = fields?.numCompletions ?? this.numCompletions;
594
+ this.addAllHooksToHttpClient();
595
+ }
596
+ get lc_secrets() {
597
+ return { apiKey: "MISTRAL_API_KEY" };
598
+ }
599
+ get lc_aliases() {
600
+ return { apiKey: "mistral_api_key" };
601
+ }
602
+ getLsParams(options) {
603
+ const params = this.invocationParams(options);
604
+ return {
605
+ ls_provider: "mistral",
606
+ ls_model_name: this.model,
607
+ ls_model_type: "chat",
608
+ ls_temperature: params.temperature ?? void 0,
609
+ ls_max_tokens: params.maxTokens ?? void 0
610
+ };
611
+ }
612
+ _llmType() {
613
+ return "mistral_ai";
614
+ }
615
+ /**
616
+ * Get the parameters used to invoke the model
617
+ */
618
+ invocationParams(options) {
619
+ const { response_format, tools, tool_choice } = options ?? {};
620
+ const mistralAITools = tools?.length ? _convertToolToMistralTool(tools) : void 0;
621
+ const params = {
622
+ model: this.model,
623
+ tools: mistralAITools,
624
+ temperature: this.temperature,
625
+ maxTokens: this.maxTokens,
626
+ topP: this.topP,
627
+ randomSeed: this.seed,
628
+ safePrompt: this.safePrompt,
629
+ toolChoice: tool_choice,
630
+ responseFormat: response_format,
631
+ presencePenalty: this.presencePenalty,
632
+ frequencyPenalty: this.frequencyPenalty,
633
+ n: this.numCompletions
634
+ };
635
+ return params;
636
+ }
637
+ bindTools(tools, kwargs) {
638
+ const mistralTools = _convertToolToMistralTool(tools);
639
+ return new RunnableBinding({
640
+ bound: this,
641
+ kwargs: {
642
+ ...kwargs ?? {},
643
+ tools: mistralTools
644
+ },
645
+ config: {}
646
+ });
647
+ }
648
+ async completionWithRetry(input, streaming) {
649
+ const caller = new AsyncCaller({ maxRetries: this.maxRetries });
650
+ const client = new Mistral({
651
+ apiKey: this.apiKey,
652
+ serverURL: this.serverURL,
653
+ ...this.httpClient ? { httpClient: this.httpClient } : {}
654
+ });
655
+ return caller.call(async () => {
656
+ try {
657
+ let res;
658
+ if (streaming) res = await client.chat.stream(input);
659
+ else res = await client.chat.complete(input);
660
+ return res;
661
+ } catch (e) {
662
+ if (e.message?.includes("status: 400") || e.message?.toLowerCase().includes("status 400") || e.message?.includes("validation failed")) e.status = 400;
663
+ throw e;
664
+ }
665
+ });
666
+ }
667
+ /** @ignore */
668
+ async _generate(messages, options, runManager) {
669
+ const tokenUsage = {};
670
+ const params = this.invocationParams(options);
671
+ const mistralMessages = convertMessagesToMistralMessages(messages);
672
+ const input = {
673
+ ...params,
674
+ messages: mistralMessages
675
+ };
676
+ const shouldStream = options.signal ?? !!options.timeout;
677
+ if (this.streaming || shouldStream) {
678
+ const stream = this._streamResponseChunks(messages, options, runManager);
679
+ const finalChunks = {};
680
+ for await (const chunk of stream) {
681
+ const index = chunk.generationInfo?.completion ?? 0;
682
+ if (finalChunks[index] === void 0) finalChunks[index] = chunk;
683
+ else finalChunks[index] = finalChunks[index].concat(chunk);
684
+ }
685
+ const generations$1 = Object.entries(finalChunks).sort(([aKey], [bKey]) => parseInt(aKey, 10) - parseInt(bKey, 10)).map(([_, value]) => value);
686
+ return {
687
+ generations: generations$1,
688
+ llmOutput: { estimatedTokenUsage: tokenUsage }
689
+ };
690
+ }
691
+ const response = await this.completionWithRetry(input, false);
692
+ const { completionTokens, promptTokens, totalTokens } = response?.usage ?? {};
693
+ if (completionTokens) tokenUsage.completionTokens = (tokenUsage.completionTokens ?? 0) + completionTokens;
694
+ if (promptTokens) tokenUsage.promptTokens = (tokenUsage.promptTokens ?? 0) + promptTokens;
695
+ if (totalTokens) tokenUsage.totalTokens = (tokenUsage.totalTokens ?? 0) + totalTokens;
696
+ const generations = [];
697
+ for (const part of response?.choices ?? []) {
698
+ if ("delta" in part) throw new Error("Delta not supported in non-streaming mode.");
699
+ if (!("message" in part)) throw new Error("No message found in the choice.");
700
+ let text = part.message?.content ?? "";
701
+ if (Array.isArray(text)) text = text[0].type === "text" ? text[0].text : "";
702
+ const generation = {
703
+ text,
704
+ message: mistralAIResponseToChatMessage(part, response?.usage)
705
+ };
706
+ if (part.finishReason) generation.generationInfo = { finishReason: part.finishReason };
707
+ generations.push(generation);
708
+ }
709
+ return {
710
+ generations,
711
+ llmOutput: { tokenUsage }
712
+ };
713
+ }
714
+ async *_streamResponseChunks(messages, options, runManager) {
715
+ const mistralMessages = convertMessagesToMistralMessages(messages);
716
+ const params = this.invocationParams(options);
717
+ const input = {
718
+ ...params,
719
+ messages: mistralMessages
720
+ };
721
+ const streamIterable = await this.completionWithRetry(input, true);
722
+ for await (const { data } of streamIterable) {
723
+ if (options.signal?.aborted) throw new Error("AbortError");
724
+ const choice = data?.choices[0];
725
+ if (!choice || !("delta" in choice)) continue;
726
+ const { delta } = choice;
727
+ if (!delta) continue;
728
+ const newTokenIndices = {
729
+ prompt: 0,
730
+ completion: choice.index ?? 0
731
+ };
732
+ const shouldStreamUsage = this.streamUsage || options.streamUsage;
733
+ const message = _convertDeltaToMessageChunk(delta, shouldStreamUsage ? data.usage : null);
734
+ if (message === null) continue;
735
+ let text = delta.content ?? "";
736
+ if (Array.isArray(text)) text = text[0].type === "text" ? text[0].text : "";
737
+ const generationChunk = new ChatGenerationChunk({
738
+ message,
739
+ text,
740
+ generationInfo: newTokenIndices
741
+ });
742
+ yield generationChunk;
743
+ runManager?.handleLLMNewToken(generationChunk.text ?? "", newTokenIndices, void 0, void 0, void 0, { chunk: generationChunk });
744
+ }
745
+ }
746
+ addAllHooksToHttpClient() {
747
+ try {
748
+ this.removeAllHooksFromHttpClient();
749
+ const hasHooks = [
750
+ this.beforeRequestHooks,
751
+ this.requestErrorHooks,
752
+ this.responseHooks
753
+ ].some((hook) => hook && hook.length > 0);
754
+ if (hasHooks && !this.httpClient) this.httpClient = new HTTPClient();
755
+ if (this.beforeRequestHooks) for (const hook of this.beforeRequestHooks) this.httpClient?.addHook("beforeRequest", hook);
756
+ if (this.requestErrorHooks) for (const hook of this.requestErrorHooks) this.httpClient?.addHook("requestError", hook);
757
+ if (this.responseHooks) for (const hook of this.responseHooks) this.httpClient?.addHook("response", hook);
758
+ } catch {
759
+ throw new Error("Error in adding all hooks");
760
+ }
761
+ }
762
+ removeAllHooksFromHttpClient() {
763
+ try {
764
+ if (this.beforeRequestHooks) for (const hook of this.beforeRequestHooks) this.httpClient?.removeHook("beforeRequest", hook);
765
+ if (this.requestErrorHooks) for (const hook of this.requestErrorHooks) this.httpClient?.removeHook("requestError", hook);
766
+ if (this.responseHooks) for (const hook of this.responseHooks) this.httpClient?.removeHook("response", hook);
767
+ } catch {
768
+ throw new Error("Error in removing hooks");
769
+ }
770
+ }
771
+ removeHookFromHttpClient(hook) {
772
+ try {
773
+ this.httpClient?.removeHook("beforeRequest", hook);
774
+ this.httpClient?.removeHook("requestError", hook);
775
+ this.httpClient?.removeHook("response", hook);
776
+ } catch {
777
+ throw new Error("Error in removing hook");
778
+ }
779
+ }
780
+ /** @ignore */
781
+ _combineLLMOutput() {
782
+ return [];
783
+ }
784
+ withStructuredOutput(outputSchema, config) {
785
+ const schema = outputSchema;
786
+ const name = config?.name;
787
+ const method = config?.method;
788
+ const includeRaw = config?.includeRaw;
789
+ let llm;
790
+ let outputParser;
791
+ if (method === "jsonMode") {
792
+ let outputSchema$1;
793
+ if (isInteropZodSchema(schema)) {
794
+ outputParser = StructuredOutputParser.fromZodSchema(schema);
795
+ outputSchema$1 = toJsonSchema(schema);
796
+ } else outputParser = new JsonOutputParser();
797
+ llm = this.withConfig({
798
+ response_format: { type: "json_object" },
799
+ ls_structured_output_format: {
800
+ kwargs: { method: "jsonMode" },
801
+ schema: outputSchema$1
802
+ }
803
+ });
804
+ } else {
805
+ let functionName = name ?? "extract";
806
+ if (isInteropZodSchema(schema)) {
807
+ const asJsonSchema = toJsonSchema(schema);
808
+ llm = this.bindTools([{
809
+ type: "function",
810
+ function: {
811
+ name: functionName,
812
+ description: asJsonSchema.description,
813
+ parameters: asJsonSchema
814
+ }
815
+ }]).withConfig({
816
+ tool_choice: "any",
817
+ ls_structured_output_format: {
818
+ kwargs: { method: "functionCalling" },
819
+ schema: asJsonSchema
820
+ }
821
+ });
822
+ outputParser = new JsonOutputKeyToolsParser({
823
+ returnSingle: true,
824
+ keyName: functionName,
825
+ zodSchema: schema
826
+ });
827
+ } else {
828
+ let openAIFunctionDefinition;
829
+ if (typeof schema.name === "string" && typeof schema.parameters === "object" && schema.parameters != null) {
830
+ openAIFunctionDefinition = schema;
831
+ functionName = schema.name;
832
+ } else openAIFunctionDefinition = {
833
+ name: functionName,
834
+ description: schema.description ?? "",
835
+ parameters: schema
836
+ };
837
+ llm = this.bindTools([{
838
+ type: "function",
839
+ function: openAIFunctionDefinition
840
+ }]).withConfig({ tool_choice: "any" });
841
+ outputParser = new JsonOutputKeyToolsParser({
842
+ returnSingle: true,
843
+ keyName: functionName
844
+ });
845
+ }
846
+ }
847
+ if (!includeRaw) return llm.pipe(outputParser);
848
+ const parserAssign = RunnablePassthrough.assign({ parsed: (input, config$1) => outputParser.invoke(input.raw, config$1) });
849
+ const parserNone = RunnablePassthrough.assign({ parsed: () => null });
850
+ const parsedWithFallback = parserAssign.withFallbacks({ fallbacks: [parserNone] });
851
+ return RunnableSequence.from([{ raw: llm }, parsedWithFallback]);
852
+ }
853
+ };
854
+
855
+ //#endregion
856
+ export { ChatMistralAI, convertMessagesToMistralMessages };
857
+ //# sourceMappingURL=chat_models.js.map