@llumiverse/drivers 0.16.0 → 0.18.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.
Files changed (108) hide show
  1. package/README.md +1 -1
  2. package/lib/cjs/bedrock/converse.js +65 -15
  3. package/lib/cjs/bedrock/converse.js.map +1 -1
  4. package/lib/cjs/bedrock/index.js +191 -51
  5. package/lib/cjs/bedrock/index.js.map +1 -1
  6. package/lib/cjs/bedrock/nova-image-payload.js.map +1 -1
  7. package/lib/cjs/bedrock/s3.js +47 -0
  8. package/lib/cjs/bedrock/s3.js.map +1 -1
  9. package/lib/cjs/groq/index.js +4 -4
  10. package/lib/cjs/groq/index.js.map +1 -1
  11. package/lib/cjs/mistral/index.js +4 -4
  12. package/lib/cjs/mistral/index.js.map +1 -1
  13. package/lib/cjs/openai/azure.js +1 -1
  14. package/lib/cjs/openai/azure.js.map +1 -1
  15. package/lib/cjs/openai/index.js +218 -83
  16. package/lib/cjs/openai/index.js.map +1 -1
  17. package/lib/cjs/replicate.js +4 -17
  18. package/lib/cjs/replicate.js.map +1 -1
  19. package/lib/cjs/togetherai/index.js +2 -2
  20. package/lib/cjs/vertexai/embeddings/embeddings-image.js +2 -1
  21. package/lib/cjs/vertexai/embeddings/embeddings-image.js.map +1 -1
  22. package/lib/cjs/vertexai/embeddings/embeddings-text.js +2 -1
  23. package/lib/cjs/vertexai/embeddings/embeddings-text.js.map +1 -1
  24. package/lib/cjs/vertexai/index.js +117 -52
  25. package/lib/cjs/vertexai/index.js.map +1 -1
  26. package/lib/cjs/vertexai/models/claude.js +51 -17
  27. package/lib/cjs/vertexai/models/claude.js.map +1 -1
  28. package/lib/cjs/vertexai/models/gemini.js +42 -20
  29. package/lib/cjs/vertexai/models/gemini.js.map +1 -1
  30. package/lib/cjs/vertexai/models/imagen.js.map +1 -1
  31. package/lib/cjs/watsonx/index.js +12 -6
  32. package/lib/cjs/watsonx/index.js.map +1 -1
  33. package/lib/esm/bedrock/converse.js +63 -14
  34. package/lib/esm/bedrock/converse.js.map +1 -1
  35. package/lib/esm/bedrock/index.js +193 -50
  36. package/lib/esm/bedrock/index.js.map +1 -1
  37. package/lib/esm/bedrock/nova-image-payload.js.map +1 -1
  38. package/lib/esm/bedrock/s3.js +46 -0
  39. package/lib/esm/bedrock/s3.js.map +1 -1
  40. package/lib/esm/groq/index.js +4 -4
  41. package/lib/esm/groq/index.js.map +1 -1
  42. package/lib/esm/mistral/index.js +4 -4
  43. package/lib/esm/mistral/index.js.map +1 -1
  44. package/lib/esm/openai/azure.js +1 -1
  45. package/lib/esm/openai/azure.js.map +1 -1
  46. package/lib/esm/openai/index.js +219 -85
  47. package/lib/esm/openai/index.js.map +1 -1
  48. package/lib/esm/replicate.js +3 -16
  49. package/lib/esm/replicate.js.map +1 -1
  50. package/lib/esm/togetherai/index.js +2 -2
  51. package/lib/esm/vertexai/embeddings/embeddings-image.js +2 -1
  52. package/lib/esm/vertexai/embeddings/embeddings-image.js.map +1 -1
  53. package/lib/esm/vertexai/embeddings/embeddings-text.js +2 -1
  54. package/lib/esm/vertexai/embeddings/embeddings-text.js.map +1 -1
  55. package/lib/esm/vertexai/index.js +120 -55
  56. package/lib/esm/vertexai/index.js.map +1 -1
  57. package/lib/esm/vertexai/models/claude.js +52 -18
  58. package/lib/esm/vertexai/models/claude.js.map +1 -1
  59. package/lib/esm/vertexai/models/gemini.js +42 -20
  60. package/lib/esm/vertexai/models/gemini.js.map +1 -1
  61. package/lib/esm/vertexai/models/imagen.js.map +1 -1
  62. package/lib/esm/watsonx/index.js +12 -6
  63. package/lib/esm/watsonx/index.js.map +1 -1
  64. package/lib/types/bedrock/converse.d.ts +3 -2
  65. package/lib/types/bedrock/converse.d.ts.map +1 -1
  66. package/lib/types/bedrock/index.d.ts +5 -16
  67. package/lib/types/bedrock/index.d.ts.map +1 -1
  68. package/lib/types/bedrock/nova-image-payload.d.ts.map +1 -1
  69. package/lib/types/bedrock/s3.d.ts +6 -0
  70. package/lib/types/bedrock/s3.d.ts.map +1 -1
  71. package/lib/types/openai/index.d.ts +8 -5
  72. package/lib/types/openai/index.d.ts.map +1 -1
  73. package/lib/types/togetherai/interfaces.d.ts +3 -3
  74. package/lib/types/togetherai/interfaces.d.ts.map +1 -1
  75. package/lib/types/vertexai/embeddings/embeddings-image.d.ts.map +1 -1
  76. package/lib/types/vertexai/embeddings/embeddings-text.d.ts.map +1 -1
  77. package/lib/types/vertexai/index.d.ts +11 -6
  78. package/lib/types/vertexai/index.d.ts.map +1 -1
  79. package/lib/types/vertexai/models/claude.d.ts.map +1 -1
  80. package/lib/types/vertexai/models/gemini.d.ts.map +1 -1
  81. package/lib/types/vertexai/models/imagen.d.ts.map +1 -1
  82. package/lib/types/vertexai/models.d.ts +1 -1
  83. package/lib/types/vertexai/models.d.ts.map +1 -1
  84. package/lib/types/watsonx/index.d.ts.map +1 -1
  85. package/lib/types/watsonx/interfaces.d.ts +4 -0
  86. package/lib/types/watsonx/interfaces.d.ts.map +1 -1
  87. package/package.json +19 -21
  88. package/src/bedrock/converse.ts +69 -20
  89. package/src/bedrock/index.ts +231 -62
  90. package/src/bedrock/nova-image-payload.ts +1 -2
  91. package/src/bedrock/s3.ts +48 -0
  92. package/src/groq/index.ts +4 -4
  93. package/src/mistral/index.ts +4 -4
  94. package/src/openai/azure.ts +2 -2
  95. package/src/openai/index.ts +269 -93
  96. package/src/openai/openai.ts +1 -1
  97. package/src/replicate.ts +4 -16
  98. package/src/togetherai/index.ts +2 -2
  99. package/src/togetherai/interfaces.ts +3 -3
  100. package/src/vertexai/embeddings/embeddings-image.ts +5 -3
  101. package/src/vertexai/embeddings/embeddings-text.ts +5 -3
  102. package/src/vertexai/index.ts +168 -67
  103. package/src/vertexai/models/claude.ts +71 -32
  104. package/src/vertexai/models/gemini.ts +47 -23
  105. package/src/vertexai/models/imagen.ts +4 -3
  106. package/src/vertexai/models.ts +1 -1
  107. package/src/watsonx/index.ts +12 -6
  108. package/src/watsonx/interfaces.ts +4 -0
@@ -1,18 +1,24 @@
1
- import { Bedrock, CreateModelCustomizationJobCommand, FoundationModelSummary, GetModelCustomizationJobCommand, GetModelCustomizationJobCommandOutput, ModelCustomizationJobStatus, StopModelCustomizationJobCommand } from "@aws-sdk/client-bedrock";
2
- import { BedrockRuntime, ConverseRequest, ConverseResponse, ConverseStreamOutput, InferenceConfiguration } from "@aws-sdk/client-bedrock-runtime";
1
+ import {
2
+ Bedrock, CreateModelCustomizationJobCommand, FoundationModelSummary, GetModelCustomizationJobCommand,
3
+ GetModelCustomizationJobCommandOutput, ModelCustomizationJobStatus, ModelModality, StopModelCustomizationJobCommand
4
+ } from "@aws-sdk/client-bedrock";
5
+ import { BedrockRuntime, ConverseRequest, ConverseResponse, ConverseStreamOutput, InferenceConfiguration, Tool } from "@aws-sdk/client-bedrock-runtime";
3
6
  import { S3Client } from "@aws-sdk/client-s3";
4
- import { AbstractDriver, AIModel, Completion, CompletionChunkObject, DataSource, DriverOptions, EmbeddingsOptions, EmbeddingsResult, ExecutionOptions, ExecutionTokenUsage, ImageGeneration, Modalities, PromptOptions, PromptSegment, TextFallbackOptions, TrainingJob, TrainingJobStatus, TrainingOptions } from "@llumiverse/core";
7
+ import { AwsCredentialIdentity, Provider } from "@aws-sdk/types";
8
+ import {
9
+ AbstractDriver, AIModel, Completion, CompletionChunkObject, DataSource, DriverOptions, EmbeddingsOptions, EmbeddingsResult,
10
+ ExecutionOptions, ExecutionTokenUsage, ImageGeneration, Modalities, PromptOptions, PromptSegment,
11
+ TextFallbackOptions, ToolDefinition, ToolUse, TrainingJob, TrainingJobStatus, TrainingOptions,
12
+ BedrockClaudeOptions, BedrockPalmyraOptions, getMaxTokensLimit, NovaCanvasOptions,
13
+ modelModalitiesToArray, getModelCapabilities
14
+ } from "@llumiverse/core";
5
15
  import { transformAsyncIterator } from "@llumiverse/core/async";
6
16
  import { formatNovaPrompt, NovaMessagesPrompt } from "@llumiverse/core/formatters";
7
- import { AwsCredentialIdentity, Provider } from "@smithy/types";
8
- import mnemonist from "mnemonist";
9
- import { BedrockClaudeOptions, NovaCanvasOptions } from "../../../core/src/options/bedrock.js";
10
- import { converseConcatMessages, converseRemoveJSONprefill, converseSystemToMessages, fortmatConversePrompt } from "./converse.js";
17
+ import { LRUCache } from "mnemonist";
18
+ import { converseConcatMessages, converseJSONprefill, converseSystemToMessages, formatConversePrompt } from "./converse.js";
11
19
  import { formatNovaImageGenerationPayload, NovaImageGenerationTaskType } from "./nova-image-payload.js";
12
20
  import { forceUploadFile } from "./s3.js";
13
21
 
14
- const { LRUCache } = mnemonist;
15
-
16
22
  const supportStreamingCache = new LRUCache<string, boolean>(4096);
17
23
 
18
24
  enum BedrockModelType {
@@ -44,8 +50,8 @@ export interface BedrockDriverOptions extends DriverOptions {
44
50
  */
45
51
  region: string;
46
52
  /**
47
- * Tthe bucket name to be used for training.
48
- * It will be created oif nto already exixts
53
+ * The bucket name to be used for training.
54
+ * It will be created if does not already exist.
49
55
  */
50
56
  training_bucket?: string;
51
57
 
@@ -105,10 +111,10 @@ export class BedrockDriver extends AbstractDriver<BedrockDriverOptions, BedrockP
105
111
  if (opts.model.includes("canvas")) {
106
112
  return await formatNovaPrompt(segments, opts.result_schema);
107
113
  }
108
- return await fortmatConversePrompt(segments, opts.result_schema);
114
+ return await formatConversePrompt(segments, opts.result_schema);
109
115
  }
110
116
 
111
- static getExtractedExecuton(result: ConverseResponse, _prompt?: BedrockPrompt): CompletionChunkObject {
117
+ static getExtractedExecution(result: ConverseResponse, _prompt?: BedrockPrompt): CompletionChunkObject {
112
118
  return {
113
119
  result: result.output?.message?.content?.map(c => c.text).join("\n") ?? "",
114
120
  token_usage: {
@@ -145,18 +151,45 @@ export class BedrockDriver extends AbstractDriver<BedrockDriverOptions, BedrockP
145
151
  };
146
152
 
147
153
  async requestTextCompletion(prompt: ConverseRequest, options: ExecutionOptions): Promise<Completion> {
154
+ let conversation = updateConversation(options.conversation as ConverseRequest, prompt);
148
155
 
149
- const payload = this.preparePayload(prompt, options);
156
+ const payload = this.preparePayload(conversation, options);
150
157
  const executor = this.getExecutor();
151
158
 
152
159
  const res = await executor.converse({
153
160
  ...payload,
154
161
  });
155
162
 
163
+ conversation = updateConversation(conversation, {
164
+ messages: [res.output?.message ?? { content: [{ text: "" }], role: "assistant" }],
165
+ modelId: prompt.modelId,
166
+ });
167
+
168
+ let tool_use: ToolUse[] | undefined = undefined;
169
+ //Get tool requests
170
+ if (res.stopReason == "tool_use") {
171
+ tool_use = res.output?.message?.content?.reduce((tools: ToolUse[], c) => {
172
+ if (c.toolUse) {
173
+ tools.push({
174
+ tool_name: c.toolUse.name ?? "",
175
+ tool_input: c.toolUse.input as any,
176
+ id: c.toolUse.toolUseId ?? "",
177
+ } satisfies ToolUse);
178
+ }
179
+ return tools;
180
+ }, []);
181
+ //If no tools were used, set to undefined
182
+ if (tool_use && tool_use.length == 0) {
183
+ tool_use = undefined;
184
+ }
185
+ }
186
+
156
187
  const completion = {
157
- ...BedrockDriver.getExtractedExecuton(res, prompt),
188
+ ...BedrockDriver.getExtractedExecution(res, prompt),
158
189
  original_response: options.include_original_response ? res : undefined,
159
- } satisfies Completion;
190
+ conversation: conversation,
191
+ tool_use: tool_use,
192
+ };
160
193
 
161
194
  return completion;
162
195
  }
@@ -167,13 +200,13 @@ export class BedrockDriver extends AbstractDriver<BedrockDriverOptions, BedrockP
167
200
  if (arnMatch) {
168
201
  return arnMatch[1];
169
202
  }
170
-
203
+
171
204
  // Match common AWS regions directly in string
172
205
  const regionMatch = modelString.match(/(?:us|eu|ap|sa|ca|me|af)[-](east|west|central|south|north|southeast|southwest|northeast|northwest)[-][1-9]/);
173
206
  if (regionMatch) {
174
207
  return regionMatch[0];
175
208
  }
176
-
209
+
177
210
  return defaultRegion;
178
211
  }
179
212
 
@@ -267,11 +300,17 @@ export class BedrockDriver extends AbstractDriver<BedrockDriverOptions, BedrockP
267
300
  let additionalField = {};
268
301
 
269
302
  if (options.model.includes("amazon")) {
303
+ if (options.result_schema) {
304
+ prompt.messages = converseJSONprefill(prompt.messages);
305
+ }
270
306
  //Titan models also exists but does not support any additional options
271
307
  if (options.model.includes("nova")) {
272
308
  additionalField = { inferenceConfig: { topK: model_options?.top_k } };
273
309
  }
274
310
  } else if (options.model.includes("claude")) {
311
+ if (options.result_schema) {
312
+ prompt.messages = converseJSONprefill(prompt.messages);
313
+ }
275
314
  if (options.model.includes("claude-3-7")) {
276
315
  const thinking_options = options.model_options as BedrockClaudeOptions;
277
316
  const thinking = thinking_options?.thinking_mode ?? false;
@@ -279,13 +318,13 @@ export class BedrockDriver extends AbstractDriver<BedrockDriverOptions, BedrockP
279
318
  model_options.max_tokens = thinking ? 128000 : 8192;
280
319
  }
281
320
  additionalField = {
282
- top_k: model_options?.top_k,
321
+ ...additionalField,
283
322
  reasoning_config: {
284
323
  type: thinking ? "enabled" : "disabled",
285
324
  budget_tokens: thinking_options?.thinking_budget_tokens,
286
325
  }
287
326
  };
288
- if(thinking && (thinking_options?.thinking_budget_tokens ?? 0) > 64000){
327
+ if (thinking && (thinking_options?.thinking_budget_tokens ?? 0) > 64000) {
289
328
  additionalField = {
290
329
  ...additionalField,
291
330
  anthorpic_beta: ["output-128k-2025-02-19"]
@@ -294,22 +333,11 @@ export class BedrockDriver extends AbstractDriver<BedrockDriverOptions, BedrockP
294
333
  }
295
334
  //Needs max_tokens to be set
296
335
  if (!model_options?.max_tokens) {
297
- if (options.model.includes("claude-3-5")) {
298
- model_options.max_tokens = 8192;
299
-
300
- //Bug with AWS Converse Sonnet 3.5, does not effect Haiku.
301
- //See https://github.com/boto/boto3/issues/4279
302
- if (options.model.includes("claude-3-5-sonnet")) {
303
- model_options.max_tokens = 4096;
304
- }
305
- } else {
306
- model_options.max_tokens = 4096;
307
- }
336
+ model_options.max_tokens = getMaxTokensLimit(options.model, model_options);
308
337
  }
309
- additionalField = { top_k: model_options?.top_k };
338
+ additionalField = { ...additionalField, top_k: model_options?.top_k };
310
339
  } else if (options.model.includes("meta")) {
311
- //If last message is "```json", remove it. Model requires the final message to be a user message
312
- prompt.messages = converseRemoveJSONprefill(prompt.messages);
340
+ //LLaMA models support no additional options
313
341
  } else if (options.model.includes("mistral")) {
314
342
  //7B instruct and 8x7B instruct
315
343
  if (options.model.includes("7b")) {
@@ -320,14 +348,14 @@ export class BedrockDriver extends AbstractDriver<BedrockDriverOptions, BedrockP
320
348
  prompt.system = undefined;
321
349
  prompt.messages = converseConcatMessages(prompt.messages);
322
350
  }
351
+ if (options.result_schema) {
352
+ prompt.messages = converseJSONprefill(prompt.messages);
353
+ }
323
354
  } else {
324
355
  //Other models such as Mistral Small,Large and Large 2
325
356
  //Support no additional fields.
326
- prompt.messages = converseRemoveJSONprefill(prompt.messages);
327
357
  }
328
358
  } else if (options.model.includes("ai21")) {
329
- //If last message is "```json", remove it. Model requires the final message to be a user message
330
- prompt.messages = converseRemoveJSONprefill(prompt.messages);
331
359
  //Jamba models support no additional options
332
360
  //Jurassic 2 models do.
333
361
  if (options.model.includes("j2")) {
@@ -344,8 +372,6 @@ export class BedrockDriver extends AbstractDriver<BedrockDriverOptions, BedrockP
344
372
  }
345
373
  } else if (options.model.includes("cohere.command")) {
346
374
  // If last message is "```json", remove it.
347
- // Model requires the final message to be a user message or does not support assistant messages
348
- prompt.messages = converseRemoveJSONprefill(prompt.messages);
349
375
  //Command R and R plus
350
376
  if (options.model.includes("cohere.command-r")) {
351
377
  additionalField = {
@@ -363,6 +389,16 @@ export class BedrockDriver extends AbstractDriver<BedrockDriverOptions, BedrockP
363
389
  prompt.messages = converseConcatMessages(prompt.messages);
364
390
  }
365
391
  }
392
+ } else if (options.model.includes("palmyra")) {
393
+ const palmyraOptions = options.model_options as BedrockPalmyraOptions;
394
+ additionalField = {
395
+ seed: palmyraOptions?.seed,
396
+ presence_penalty: palmyraOptions?.presence_penalty,
397
+ frequency_penalty: palmyraOptions?.frequency_penalty,
398
+ min_tokens: palmyraOptions?.min_tokens,
399
+ }
400
+ } else if (options.model.includes("deepseek")) {
401
+ //DeepSeek models support no additional options
366
402
  }
367
403
 
368
404
  //If last message is "```json", add corresponding ``` as a stop sequence.
@@ -378,7 +414,9 @@ export class BedrockDriver extends AbstractDriver<BedrockDriverOptions, BedrockP
378
414
  }
379
415
  }
380
416
 
381
- return {
417
+ const tool_defs = getToolDefinitions(options.tools);
418
+
419
+ const request: ConverseRequest = {
382
420
  messages: prompt.messages,
383
421
  system: prompt.system,
384
422
  modelId: options.model,
@@ -390,8 +428,17 @@ export class BedrockDriver extends AbstractDriver<BedrockDriverOptions, BedrockP
390
428
  } satisfies InferenceConfiguration,
391
429
  additionalModelRequestFields: {
392
430
  ...additionalField,
393
- },
394
- } satisfies ConverseRequest;
431
+ }
432
+ };
433
+
434
+ //Only add tools if they are defined
435
+ if (tool_defs) {
436
+ request.toolConfig = {
437
+ tools: tool_defs,
438
+ }
439
+ }
440
+
441
+ return request;
395
442
  }
396
443
 
397
444
 
@@ -400,7 +447,7 @@ export class BedrockDriver extends AbstractDriver<BedrockDriverOptions, BedrockP
400
447
  throw new Error(`Image generation requires image output_modality`);
401
448
  }
402
449
  if (options.model_options?._option_id !== "bedrock-nova-canvas") {
403
- this.logger.warn("Invalid model options", {options: options.model_options });
450
+ this.logger.warn("Invalid model options", { options: options.model_options });
404
451
  }
405
452
  const model_options = options.model_options as NovaCanvasOptions;
406
453
 
@@ -522,7 +569,7 @@ export class BedrockDriver extends AbstractDriver<BedrockDriverOptions, BedrockP
522
569
 
523
570
  async _listModels(foundationFilter?: (m: FoundationModelSummary) => boolean): Promise<AIModel[]> {
524
571
  const service = this.getService();
525
- const [foundationals, customs, inferenceProfiles] = await Promise.all([
572
+ const [foundationModelsList, customModelsList, inferenceProfilesList] = await Promise.all([
526
573
  service.listFoundationModels({}).catch(() => {
527
574
  this.logger.warn("[Bedrock] Can't list foundation models. Check if the user has the right permissions.");
528
575
  return undefined
@@ -537,21 +584,65 @@ export class BedrockDriver extends AbstractDriver<BedrockDriverOptions, BedrockP
537
584
  }),
538
585
  ]);
539
586
 
540
- if (!foundationals?.modelSummaries) {
587
+ if (!foundationModelsList?.modelSummaries) {
541
588
  throw new Error("Foundation models not found");
542
589
  }
543
590
 
544
- let fmodels = foundationals.modelSummaries || [];
591
+ let foundationModels = foundationModelsList.modelSummaries || [];
545
592
  if (foundationFilter) {
546
- fmodels = fmodels.filter(foundationFilter);
593
+ foundationModels = foundationModels.filter(foundationFilter);
547
594
  }
548
595
 
549
- const aimodels: AIModel[] = fmodels.map((m) => {
596
+ const supportedPublishers = ["amazon", "anthropic", "cohere", "ai21", "mistral", "meta", "deepseek", "writer"];
597
+ const unsupportedModelsByPublisher = {
598
+ amazon: ["titan-image-generator", "nova-reel", "nova-sonic", "rerank"],
599
+ anthropic: [],
600
+ cohere: ["rerank"],
601
+ ai21: [],
602
+ mistral: [],
603
+ meta: [],
604
+ deepseek: [],
605
+ writer: [],
606
+ };
607
+
608
+ // Helper function to check if model should be filtered out
609
+ const shouldIncludeModel = (modelId?: string, providerName?: string): boolean => {
610
+ if (!modelId || !providerName) return false;
611
+
612
+ const normalizedProvider = providerName.toLowerCase();
613
+
614
+ // Check if provider is supported
615
+ const isProviderSupported = supportedPublishers.some(provider =>
616
+ normalizedProvider.includes(provider)
617
+ );
618
+
619
+ if (!isProviderSupported) return false;
620
+
621
+ // Check if model is in the unsupported list for its provider
622
+ for (const provider of supportedPublishers) {
623
+ if (normalizedProvider.includes(provider)) {
624
+ const unsupportedModels = unsupportedModelsByPublisher[provider as keyof typeof unsupportedModelsByPublisher] || [];
625
+ return !unsupportedModels.some(unsupported =>
626
+ modelId.toLowerCase().includes(unsupported)
627
+ );
628
+ }
629
+ }
630
+
631
+ return true;
632
+ };
633
+
634
+ foundationModels = foundationModels.filter(m =>
635
+ shouldIncludeModel(m.modelId, m.providerName)
636
+ );
637
+
638
+ const aiModels: AIModel[] = foundationModels.map((m) => {
550
639
 
551
640
  if (!m.modelId) {
552
641
  throw new Error("modelId not found");
553
642
  }
554
643
 
644
+ const modelCapability = getModelCapabilities(m.modelArn ?? m.modelId, this.provider);
645
+
555
646
  const model: AIModel = {
556
647
  id: m.modelArn ?? m.modelId,
557
648
  name: `${m.providerName} ${m.modelName}`,
@@ -559,52 +650,78 @@ export class BedrockDriver extends AbstractDriver<BedrockDriverOptions, BedrockP
559
650
  //description: ``,
560
651
  owner: m.providerName,
561
652
  can_stream: m.responseStreamingSupported ?? false,
562
- is_multimodal: m.inputModalities?.includes("IMAGE") ?? false,
563
- tags: m.outputModalities ?? [],
653
+ input_modalities: m.inputModalities ? formatAmazonModalities(m.inputModalities) : modelModalitiesToArray(modelCapability.input),
654
+ output_modalities: m.outputModalities ? formatAmazonModalities(m.outputModalities) : modelModalitiesToArray(modelCapability.input),
655
+ tool_support: modelCapability.tool_support,
564
656
  };
565
657
 
566
658
  return model;
567
659
  });
568
660
 
569
661
  //add custom models
570
- if (customs?.modelSummaries) {
571
- customs.modelSummaries.forEach((m) => {
662
+ if (customModelsList?.modelSummaries) {
663
+ customModelsList.modelSummaries.forEach((m) => {
572
664
 
573
665
  if (!m.modelArn) {
574
666
  throw new Error("Model ID not found");
575
667
  }
576
668
 
669
+ const modelCapability = getModelCapabilities(m.modelArn, this.provider);
670
+
577
671
  const model: AIModel = {
578
672
  id: m.modelArn,
579
673
  name: m.modelName ?? m.modelArn,
580
674
  provider: this.provider,
581
675
  description: `Custom model from ${m.baseModelName}`,
582
676
  is_custom: true,
677
+ input_modalities: modelModalitiesToArray(modelCapability.input),
678
+ output_modalities: modelModalitiesToArray(modelCapability.output),
679
+ tool_support: modelCapability.tool_support,
583
680
  };
584
681
 
585
- aimodels.push(model);
682
+ aiModels.push(model);
586
683
  this.validateConnection;
587
684
  });
588
685
  }
589
686
 
590
687
  //add inference profiles
591
- if (inferenceProfiles?.inferenceProfileSummaries) {
592
- inferenceProfiles.inferenceProfileSummaries.forEach((p) => {
688
+ if (inferenceProfilesList?.inferenceProfileSummaries) {
689
+ inferenceProfilesList.inferenceProfileSummaries.forEach((p) => {
593
690
  if (!p.inferenceProfileArn) {
594
691
  throw new Error("Profile ARN not found");
595
692
  }
596
693
 
597
- const model: AIModel = {
598
- id: p.inferenceProfileArn ?? p.inferenceProfileId,
599
- name: p.inferenceProfileName ?? p.inferenceProfileArn,
600
- provider: this.provider,
601
- };
694
+ // Apply the same filtering logic to inference profiles based on their name
695
+ const profileId = p.inferenceProfileId || "";
696
+ const profileName = p.inferenceProfileName || "";
697
+
698
+ // Extract provider name from profile name or ID
699
+ let providerName = "";
700
+ for (const provider of supportedPublishers) {
701
+ if (profileName.toLowerCase().includes(provider) || profileId.toLowerCase().includes(provider)) {
702
+ providerName = provider;
703
+ break;
704
+ }
705
+ }
706
+
707
+ const modelCapability = getModelCapabilities(p.inferenceProfileArn ?? p.inferenceProfileId, this.provider);
708
+
709
+ if (providerName && shouldIncludeModel(profileId, providerName)) {
710
+ const model: AIModel = {
711
+ id: p.inferenceProfileArn ?? p.inferenceProfileId,
712
+ name: p.inferenceProfileName ?? p.inferenceProfileArn,
713
+ provider: this.provider,
714
+ input_modalities: modelModalitiesToArray(modelCapability.input),
715
+ output_modalities: modelModalitiesToArray(modelCapability.output),
716
+ tool_support: modelCapability.tool_support,
717
+ };
602
718
 
603
- aimodels.push(model);
719
+ aiModels.push(model);
720
+ }
604
721
  });
605
722
  }
606
723
 
607
- return aimodels;
724
+ return aiModels;
608
725
  }
609
726
 
610
727
  async generateEmbeddings({ text, image, model }: EmbeddingsOptions): Promise<EmbeddingsResult> {
@@ -666,4 +783,56 @@ function jobInfo(job: GetModelCustomizationJobCommandOutput, jobId: string): Tra
666
783
  status,
667
784
  details
668
785
  }
786
+ }
787
+
788
+ function getToolDefinitions(tools?: ToolDefinition[]): Tool[] | undefined {
789
+ return tools ? tools.map(getToolDefinition) : undefined;
790
+ }
791
+
792
+ function getToolDefinition(tool: ToolDefinition): Tool.ToolSpecMember {
793
+ return {
794
+ toolSpec: {
795
+ name: tool.name,
796
+ description: tool.description,
797
+ inputSchema: {
798
+ json: tool.input_schema as any,
799
+ }
800
+ }
801
+ }
802
+ }
803
+
804
+ /**
805
+ * Update the conversation messages
806
+ * @param prompt
807
+ * @param response
808
+ * @returns
809
+ */
810
+ function updateConversation(conversation: ConverseRequest, prompt: ConverseRequest): ConverseRequest {
811
+ return {
812
+ ...conversation,
813
+ ...prompt,
814
+ messages: [...(conversation?.messages || []), ...(prompt.messages || [])],
815
+ system: prompt.system || conversation?.system,
816
+ };
817
+ }
818
+
819
+ function formatAmazonModalities(modalities: ModelModality[]): string[] {
820
+ const standardizedModalities: string[] = [];
821
+ for (const modality of modalities) {
822
+ if (modality === ModelModality.TEXT) {
823
+ standardizedModalities.push("text");
824
+ } else if (modality === ModelModality.IMAGE) {
825
+ standardizedModalities.push("image");
826
+ } else if (modality === ModelModality.EMBEDDING) {
827
+ standardizedModalities.push("embedding");
828
+ } else if (modality == "SPEECH") {
829
+ standardizedModalities.push("audio");
830
+ } else if (modality == "VIDEO") {
831
+ standardizedModalities.push("video");
832
+ } else {
833
+ // Handle other modalities as needed
834
+ standardizedModalities.push((modality as string).toString().toLowerCase());
835
+ }
836
+ }
837
+ return standardizedModalities;
669
838
  }
@@ -1,6 +1,5 @@
1
- import { ExecutionOptions } from "@llumiverse/core";
1
+ import { ExecutionOptions, NovaCanvasOptions } from "@llumiverse/core";
2
2
  import { NovaMessage, NovaMessagesPrompt } from "@llumiverse/core/formatters";
3
- import { NovaCanvasOptions } from "../../../core/src/options/bedrock.js";
4
3
 
5
4
  function getFirstImageFromPrompt(prompt: NovaMessage[]) {
6
5
 
package/src/bedrock/s3.ts CHANGED
@@ -59,3 +59,51 @@ export async function forceUploadFile(s3: S3Client, source: ReadableStream, buck
59
59
  await tryCreateBucket(s3, bucketName);
60
60
  return uploadFile(s3, source, bucketName, file, onProgress);
61
61
  }
62
+
63
+
64
+ /**
65
+ * Parse an S3 HTTPS URL into an S3 URI format
66
+ * s3Url - The S3 HTTPS URL (e.g., https://bucket.s3.region.amazonaws.com/key)
67
+ * returns The S3 URI (e.g., s3://bucket/key)
68
+ */
69
+ export function parseS3UrlToUri(s3Url: URL) {
70
+ try {
71
+ const url = new URL(s3Url);
72
+
73
+ // Extract the hostname which contains the bucket and S3 endpoint
74
+ const hostname = url.hostname;
75
+
76
+ // Parse the hostname to extract the bucket name
77
+ let bucketName;
78
+ if (hostname.endsWith('.amazonaws.com')) {
79
+ if (hostname.includes('.s3.')) {
80
+ // Format: bucket-name.s3.region.amazonaws.com
81
+ bucketName = hostname.split('.s3.')[0];
82
+ } else if (hostname.startsWith('s3.')) {
83
+ // Format: s3.region.amazonaws.com/bucket-name
84
+ // In this case, the bucket is actually in the first segment of the pathname
85
+ bucketName = url.pathname.split('/')[1];
86
+ // Adjust the pathname to remove the bucket name
87
+ const pathParts = url.pathname.split('/').slice(2);
88
+ url.pathname = '/' + pathParts.join('/');
89
+ } else {
90
+ throw new Error('Unable to determine bucket name from URL');
91
+ }
92
+ } else {
93
+ throw new Error('Unable to determine bucket name from URL');
94
+ }
95
+
96
+ // The key is the pathname without the leading slash
97
+ // If we had the bucket name in the path, it's already been removed above
98
+ let key = url.pathname;
99
+ if (key.startsWith('/')) {
100
+ key = key.substring(1);
101
+ }
102
+
103
+ // Construct the S3 URI
104
+ return `s3://${bucketName}/${key}`;
105
+ } catch (error) {
106
+ console.error('Error parsing S3 URL:', error);
107
+ throw error;
108
+ }
109
+ }
package/src/groq/index.ts CHANGED
@@ -28,7 +28,7 @@ export class GroqDriver extends AbstractDriver<GroqDriverOptions, OpenAITextMess
28
28
 
29
29
  // protected canStream(options: ExecutionOptions): Promise<boolean> {
30
30
  // if (options.result_schema) {
31
- // // not yet streamign json responses
31
+ // // not yet streaming json responses
32
32
  // return Promise.resolve(false);
33
33
  // } else {
34
34
  // return Promise.resolve(true);
@@ -59,7 +59,7 @@ export class GroqDriver extends AbstractDriver<GroqDriverOptions, OpenAITextMess
59
59
  }
60
60
 
61
61
  async requestTextCompletion(messages: OpenAITextMessage[], options: ExecutionOptions): Promise<Completion<any>> {
62
- if (options.model_options?._option_id !== "text-fallback") {
62
+ if (options.model_options?._option_id !== "text-fallback" && options.model_options?._option_id !== "groq-deepseek-thinking") {
63
63
  this.logger.warn("Invalid model options", {options: options.model_options });
64
64
  }
65
65
  options.model_options = options.model_options as TextFallbackOptions;
@@ -130,7 +130,7 @@ export class GroqDriver extends AbstractDriver<GroqDriverOptions, OpenAITextMess
130
130
  throw new Error("No models found");
131
131
  }
132
132
 
133
- const aimodels = models.data?.map(m => {
133
+ const aiModels = models.data?.map(m => {
134
134
  if (!m.id) {
135
135
  throw new Error("Model id is missing");
136
136
  }
@@ -143,7 +143,7 @@ export class GroqDriver extends AbstractDriver<GroqDriverOptions, OpenAITextMess
143
143
  }
144
144
  });
145
145
 
146
- return aimodels;
146
+ return aiModels;
147
147
  }
148
148
 
149
149
  validateConnection(): Promise<boolean> {
@@ -45,7 +45,7 @@ export class MistralAIDriver extends AbstractDriver<MistralAIDriverOptions, Open
45
45
  // return _options.result_schema ? responseFormatJson : responseFormatText;
46
46
 
47
47
  //TODO remove this when Mistral properly supports the parameters - it makes an error for now
48
- // some models like mixtral mistrall tiny or medium are throwing an error when using the response_format parameter
48
+ // some models like mixtral mistral tiny or medium are throwing an error when using the response_format parameter
49
49
  return undefined
50
50
  }
51
51
 
@@ -130,7 +130,7 @@ export class MistralAIDriver extends AbstractDriver<MistralAIDriverOptions, Open
130
130
  async listModels(): Promise<AIModel<string>[]> {
131
131
  const models: ListModelsResponse = await this.client.get('v1/models');
132
132
 
133
- const aimodels = models.data.map(m => {
133
+ const aiModels = models.data.map(m => {
134
134
  return {
135
135
  id: m.id,
136
136
  name: m.id,
@@ -140,7 +140,7 @@ export class MistralAIDriver extends AbstractDriver<MistralAIDriverOptions, Open
140
140
  }
141
141
  });
142
142
 
143
- return aimodels;
143
+ return aiModels;
144
144
  }
145
145
 
146
146
  validateConnection(): Promise<boolean> {
@@ -158,7 +158,7 @@ export class MistralAIDriver extends AbstractDriver<MistralAIDriverOptions, Open
158
158
  return {
159
159
  values: r.data[0].embedding,
160
160
  model,
161
- token_count: r.usage.total_tokens
161
+ token_count: r.usage.total_tokens || r.usage.prompt_tokens + r.usage.completion_tokens,
162
162
  }
163
163
  }
164
164
 
@@ -8,7 +8,7 @@ export interface AzureOpenAIDriverOptions extends DriverOptions {
8
8
  /**
9
9
  * The credentials to use to access Azure OpenAI
10
10
  */
11
- azureADTokenProvider?: any; //type with azure credntials
11
+ azureADTokenProvider?: any; //type with azure credentials
12
12
 
13
13
  apiKey?: string;
14
14
 
@@ -37,7 +37,7 @@ export class AzureOpenAIDriver extends BaseOpenAIDriver {
37
37
  apiKey: opts.apiKey,
38
38
  azureADTokenProvider: opts.azureADTokenProvider,
39
39
  endpoint: opts.endpoint,
40
- apiVersion: opts.apiVersion ?? "2024-05-01-preview",
40
+ apiVersion: opts.apiVersion ?? "2024-10-21",
41
41
  deployment: opts.deployment
42
42
  });
43
43
  this.provider = "azure_openai";