bedrock-wrapper 2.6.2 → 2.7.1

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.
@@ -144,10 +144,18 @@ async function convertToConverseFormat(messages) {
144
144
  }
145
145
 
146
146
  // Only add messages with actual content (Converse API doesn't allow empty content)
147
- if (content.length > 0) {
147
+ // Filter out content items with empty text
148
+ const validContent = content.filter(item => {
149
+ if (item.text !== undefined) {
150
+ return item.text !== null && item.text !== '';
151
+ }
152
+ return true; // Keep non-text items (like images)
153
+ });
154
+
155
+ if (validContent.length > 0) {
148
156
  converseMessages.push({
149
157
  role: msg.role,
150
- content: content
158
+ content: validContent
151
159
  });
152
160
  }
153
161
  }
@@ -288,59 +296,8 @@ function buildInvokePrompt(message_cleaned, awsModel) {
288
296
  }
289
297
  }
290
298
 
291
- // Apply parameter restrictions for models that have them
292
- function applyParameterRestrictions(params, awsModel) {
293
- if (!awsModel.parameter_restrictions) {
294
- return params;
295
- }
296
-
297
- const restrictions = awsModel.parameter_restrictions;
298
-
299
- // Handle mutually exclusive parameters
300
- if (restrictions.mutually_exclusive) {
301
- for (const exclusiveGroup of restrictions.mutually_exclusive) {
302
- // Check for both top_p and topP variants
303
- const presentParams = exclusiveGroup.filter(param => {
304
- if (param === 'top_p') {
305
- return (params['top_p'] !== undefined && params['top_p'] !== null) ||
306
- (params['topP'] !== undefined && params['topP'] !== null);
307
- }
308
- return params[param] !== undefined && params[param] !== null;
309
- });
310
-
311
- if (presentParams.length > 1) {
312
- // Keep the first parameter and remove others
313
- // For temperature/top_p, prioritize temperature as it's more commonly used
314
- const priorityOrder = ['temperature', 'top_p'];
315
- const sortedParams = presentParams.sort((a, b) => {
316
- const aIndex = priorityOrder.indexOf(a);
317
- const bIndex = priorityOrder.indexOf(b);
318
- if (aIndex !== -1 && bIndex !== -1) return aIndex - bIndex;
319
- if (aIndex !== -1) return -1;
320
- if (bIndex !== -1) return 1;
321
- return 0;
322
- });
323
-
324
- // Keep the first (highest priority) parameter, remove others
325
- for (let i = 1; i < sortedParams.length; i++) {
326
- const paramToRemove = sortedParams[i];
327
- if (paramToRemove === 'top_p') {
328
- // Remove both variants
329
- delete params['top_p'];
330
- delete params['topP'];
331
- } else {
332
- delete params[paramToRemove];
333
- }
334
- }
335
- }
336
- }
337
- }
338
-
339
- return params;
340
- }
341
-
342
299
  // Build request object for Invoke API (model-specific)
343
- function buildInvokeRequest(prompt, awsModel, max_gen_tokens, temperature, top_p, stop_sequences, stop, system_message) {
300
+ function buildInvokeRequest(prompt, awsModel, max_gen_tokens, temperature, stop_sequences, stop, system_message) {
344
301
  if (awsModel.messages_api) {
345
302
  // Check if this is a Nova model (has schemaVersion in special_request_schema)
346
303
  if (awsModel.special_request_schema?.schemaVersion === "messages-v1") {
@@ -384,15 +341,11 @@ function buildInvokeRequest(prompt, awsModel, max_gen_tokens, temperature, top_p
384
341
  let inferenceConfig = {
385
342
  [awsModel.max_tokens_param_name]: max_gen_tokens,
386
343
  temperature: temperature,
387
- topP: top_p,
388
344
  ...(awsModel.stop_sequences_param_name && stopSequencesValue && {
389
345
  [awsModel.stop_sequences_param_name]: Array.isArray(stopSequencesValue) ? stopSequencesValue : [stopSequencesValue]
390
346
  })
391
347
  };
392
-
393
- // Apply parameter restrictions
394
- inferenceConfig = applyParameterRestrictions(inferenceConfig, awsModel);
395
-
348
+
396
349
  const novaRequest = {
397
350
  ...awsModel.special_request_schema,
398
351
  messages: novaMessages,
@@ -415,16 +368,12 @@ function buildInvokeRequest(prompt, awsModel, max_gen_tokens, temperature, top_p
415
368
  ...(awsModel.system_as_separate_field && system_message && { system: system_message }),
416
369
  [awsModel.max_tokens_param_name]: max_gen_tokens,
417
370
  temperature: temperature,
418
- top_p: top_p,
419
371
  ...(awsModel.stop_sequences_param_name && stopSequencesValue && {
420
372
  [awsModel.stop_sequences_param_name]: Array.isArray(stopSequencesValue) ? stopSequencesValue : [stopSequencesValue]
421
373
  }),
422
374
  ...awsModel.special_request_schema
423
375
  };
424
-
425
- // Apply parameter restrictions
426
- request = applyParameterRestrictions(request, awsModel);
427
-
376
+
428
377
  return request;
429
378
  }
430
379
  } else {
@@ -433,17 +382,16 @@ function buildInvokeRequest(prompt, awsModel, max_gen_tokens, temperature, top_p
433
382
  prompt: typeof prompt === 'string' ? prompt : {
434
383
  messages: prompt.map(msg => ({
435
384
  role: msg.role,
436
- content: Array.isArray(msg.content) ?
437
- msg.content.map(item =>
385
+ content: Array.isArray(msg.content) ?
386
+ msg.content.map(item =>
438
387
  item.type === 'text' ? item.text : item
439
- ).join('\n') :
388
+ ).join('\n') :
440
389
  msg.content
441
390
  }))
442
391
  },
443
392
  // Optional inference parameters:
444
393
  [awsModel.max_tokens_param_name]: max_gen_tokens,
445
394
  temperature: temperature,
446
- top_p: top_p,
447
395
  ...(() => {
448
396
  const stopSequencesValue = stop_sequences || stop;
449
397
  return awsModel.stop_sequences_param_name && stopSequencesValue ? {
@@ -452,10 +400,7 @@ function buildInvokeRequest(prompt, awsModel, max_gen_tokens, temperature, top_p
452
400
  })(),
453
401
  ...awsModel.special_request_schema
454
402
  };
455
-
456
- // Apply parameter restrictions
457
- request = applyParameterRestrictions(request, awsModel);
458
-
403
+
459
404
  return request;
460
405
  }
461
406
  }
@@ -555,10 +500,15 @@ async function* executeInvokeAPI(client, request, awsModelId, shouldStream, awsM
555
500
 
556
501
  export async function* bedrockWrapper(awsCreds, openaiChatCompletionsCreateObject, { logging = false, useConverseAPI = false } = {} ) {
557
502
  const { region, accessKeyId, secretAccessKey } = awsCreds;
558
- let { messages, model, max_tokens, stream, temperature, top_p, include_thinking_data, stop, stop_sequences } = openaiChatCompletionsCreateObject;
503
+ let { messages, model, max_tokens, stream, temperature, include_thinking_data, stop, stop_sequences } = openaiChatCompletionsCreateObject;
559
504
 
560
505
  let {awsModelId, awsModel} = findAwsModelWithId(model);
561
-
506
+
507
+ // Force Converse API for models that only support it
508
+ if (awsModel.converse_api_only) {
509
+ useConverseAPI = true;
510
+ }
511
+
562
512
  // Create a Bedrock Runtime client
563
513
  const client = new BedrockRuntimeClient({
564
514
  region: region,
@@ -585,19 +535,14 @@ export async function* bedrockWrapper(awsCreds, openaiChatCompletionsCreateObjec
585
535
  // Build inference configuration (handle thinking mode for Claude models)
586
536
  let inferenceConfig = {
587
537
  maxTokens: max_gen_tokens,
588
- temperature: temperature,
589
- ...(top_p !== undefined && { topP: top_p })
538
+ temperature: temperature
590
539
  };
591
-
592
- // Apply parameter restrictions for Converse API
593
- inferenceConfig = applyParameterRestrictions(inferenceConfig, awsModel);
594
-
540
+
595
541
  // Handle thinking mode for Claude models
596
542
  let budget_tokens;
597
543
  if (awsModel.special_request_schema?.thinking?.type === "enabled") {
598
544
  // Apply thinking mode constraints for Converse API
599
545
  inferenceConfig.temperature = 1; // temperature must be 1 for thinking
600
- delete inferenceConfig.topP; // top_p must be unset for thinking
601
546
 
602
547
  // Calculate thinking budget configuration
603
548
  budget_tokens = awsModel.special_request_schema?.thinking?.budget_tokens;
@@ -762,8 +707,6 @@ export async function* bedrockWrapper(awsCreds, openaiChatCompletionsCreateObjec
762
707
  if (awsModel.special_request_schema?.thinking?.type === "enabled") {
763
708
  // temperature may only be set to 1 when thinking is enabled
764
709
  temperature = 1;
765
- // top_p must be unset when thinking is enabled
766
- top_p = undefined;
767
710
  // budget_tokens can not be greater than 80% of max_gen_tokens
768
711
  let budget_tokens = awsModel.special_request_schema?.thinking?.budget_tokens;
769
712
  if (budget_tokens > (max_gen_tokens * 0.8)) {
@@ -784,7 +727,7 @@ export async function* bedrockWrapper(awsCreds, openaiChatCompletionsCreateObjec
784
727
  }
785
728
 
786
729
  // Build request for Invoke API (complex, model-specific)
787
- const request = buildInvokeRequest(prompt, awsModel, max_gen_tokens, temperature, top_p, stop_sequences, stop, system_message);
730
+ const request = buildInvokeRequest(prompt, awsModel, max_gen_tokens, temperature, stop_sequences, stop, system_message);
788
731
 
789
732
  if (logging) {
790
733
  console.log("\nFinal request:", JSON.stringify(request, null, 2));
@@ -32,7 +32,6 @@ async function main() {
32
32
  max_tokens: 500,
33
33
  stream: true, // Can be true or false
34
34
  temperature: 0.7,
35
- top_p: 0.9,
36
35
  stop: ["END", "STOP"] // Optional stop sequences
37
36
  };
38
37
 
@@ -80,8 +79,7 @@ async function main() {
80
79
  model: "Claude-3-Haiku",
81
80
  max_tokens: 50,
82
81
  stream: false,
83
- temperature: 0.1,
84
- top_p: 0.9
82
+ temperature: 0.1
85
83
  };
86
84
 
87
85
  // Test with Invoke API
@@ -15,7 +15,6 @@ const AWS_ACCESS_KEY_ID = process.env.AWS_ACCESS_KEY_ID;
15
15
  const AWS_SECRET_ACCESS_KEY = process.env.AWS_SECRET_ACCESS_KEY;
16
16
  const LLM_MAX_GEN_TOKENS = parseInt(process.env.LLM_MAX_GEN_TOKENS);
17
17
  const LLM_TEMPERATURE = parseFloat(process.env.LLM_TEMPERATURE);
18
- const LLM_TOP_P = parseFloat(process.env.LLM_TOP_P);
19
18
 
20
19
  // --------------------------------------------
21
20
  // -- import functions from bedrock-wrapper --
@@ -129,7 +128,6 @@ const openaiChatCompletionsCreateObject = {
129
128
  "max_tokens": LLM_MAX_GEN_TOKENS,
130
129
  "stream": shouldStream,
131
130
  "temperature": LLM_TEMPERATURE,
132
- "top_p": LLM_TOP_P,
133
131
  "include_thinking_data": true,
134
132
  };
135
133
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bedrock-wrapper",
3
- "version": "2.6.2",
3
+ "version": "2.7.1",
4
4
  "description": "🪨 Bedrock Wrapper is an npm package that simplifies the integration of existing OpenAI-compatible API objects with AWS Bedrock's serverless inference LLMs.",
5
5
  "homepage": "https://www.equilllabs.com/projects/bedrock-wrapper",
6
6
  "repository": {
@@ -41,9 +41,9 @@
41
41
  "author": "",
42
42
  "license": "ISC",
43
43
  "dependencies": {
44
- "@aws-sdk/client-bedrock-runtime": "^3.911.0",
44
+ "@aws-sdk/client-bedrock-runtime": "^3.934.0",
45
45
  "dotenv": "^17.2.3",
46
- "sharp": "^0.34.4"
46
+ "sharp": "^0.34.5"
47
47
  },
48
48
  "devDependencies": {
49
49
  "chalk": "^5.6.2"
@@ -16,7 +16,6 @@ const AWS_ACCESS_KEY_ID = process.env.AWS_ACCESS_KEY_ID;
16
16
  const AWS_SECRET_ACCESS_KEY = process.env.AWS_SECRET_ACCESS_KEY;
17
17
  const LLM_MAX_GEN_TOKENS = parseInt(process.env.LLM_MAX_GEN_TOKENS);
18
18
  const LLM_TEMPERATURE = parseFloat(process.env.LLM_TEMPERATURE);
19
- const LLM_TOP_P = parseFloat(process.env.LLM_TOP_P);
20
19
 
21
20
  // --------------------------------------------
22
21
  // -- import functions from bedrock-wrapper --
@@ -60,7 +59,6 @@ async function testModelWithAPI(model, awsCreds, testMessage, isStreaming, useCo
60
59
  max_tokens: LLM_MAX_GEN_TOKENS,
61
60
  stream: isStreaming,
62
61
  temperature: LLM_TEMPERATURE,
63
- top_p: LLM_TOP_P,
64
62
  };
65
63
 
66
64
  let completeResponse = "";
@@ -152,7 +150,6 @@ async function testStopSequences(model, awsCreds) {
152
150
  max_tokens: 100,
153
151
  stream: false,
154
152
  temperature: 0.1,
155
- top_p: 0.9,
156
153
  stop: ["6"] // Stop at "6"
157
154
  };
158
155
 
@@ -208,7 +205,6 @@ async function testSystemPrompt(model, awsCreds) {
208
205
  max_tokens: 100,
209
206
  stream: false,
210
207
  temperature: 0.7,
211
- top_p: 0.9,
212
208
  };
213
209
 
214
210
  try {
@@ -0,0 +1,64 @@
1
+ // Simple test for DeepSeek models
2
+ import dotenv from 'dotenv';
3
+ dotenv.config();
4
+
5
+ import { bedrockWrapper } from "./bedrock-wrapper.js";
6
+
7
+ const AWS_REGION = process.env.AWS_REGION;
8
+ const AWS_ACCESS_KEY_ID = process.env.AWS_ACCESS_KEY_ID;
9
+ const AWS_SECRET_ACCESS_KEY = process.env.AWS_SECRET_ACCESS_KEY;
10
+
11
+ const awsCreds = {
12
+ region: AWS_REGION,
13
+ accessKeyId: AWS_ACCESS_KEY_ID,
14
+ secretAccessKey: AWS_SECRET_ACCESS_KEY,
15
+ };
16
+
17
+ async function testDeepSeekModel(modelName) {
18
+ console.log(`\nTesting ${modelName}...`);
19
+
20
+ const messages = [{ role: "user", content: "What is 2+2? Respond with just the number." }];
21
+ const requestObject = {
22
+ messages,
23
+ model: modelName,
24
+ max_tokens: 100,
25
+ stream: false,
26
+ temperature: 0.1,
27
+ };
28
+
29
+ try {
30
+ const response = await bedrockWrapper(awsCreds, requestObject, { logging: true, useConverseAPI: false });
31
+ let completeResponse = "";
32
+ for await (const data of response) {
33
+ completeResponse += data;
34
+ }
35
+ console.log(`✓ ${modelName} (Invoke API): ${completeResponse.trim()}`);
36
+ } catch (error) {
37
+ console.log(`✗ ${modelName} (Invoke API): ${error.message}`);
38
+ }
39
+
40
+ // Test with Converse API
41
+ try {
42
+ const response = await bedrockWrapper(awsCreds, requestObject, { logging: true, useConverseAPI: true });
43
+ let completeResponse = "";
44
+ for await (const data of response) {
45
+ completeResponse += data;
46
+ }
47
+ console.log(`✓ ${modelName} (Converse API): ${completeResponse.trim()}`);
48
+ } catch (error) {
49
+ console.log(`✗ ${modelName} (Converse API): ${error.message}`);
50
+ }
51
+ }
52
+
53
+ async function main() {
54
+ console.log("Testing DeepSeek Models\n");
55
+ console.log("=".repeat(50));
56
+
57
+ await testDeepSeekModel("DeepSeek-R1");
58
+ await testDeepSeekModel("DeepSeek-V3.1");
59
+
60
+ console.log("\n" + "=".repeat(50));
61
+ console.log("DeepSeek tests completed!");
62
+ }
63
+
64
+ main().catch(console.error);
package/test-models.js CHANGED
@@ -16,7 +16,6 @@ const AWS_ACCESS_KEY_ID = process.env.AWS_ACCESS_KEY_ID;
16
16
  const AWS_SECRET_ACCESS_KEY = process.env.AWS_SECRET_ACCESS_KEY;
17
17
  const LLM_MAX_GEN_TOKENS = parseInt(process.env.LLM_MAX_GEN_TOKENS);
18
18
  const LLM_TEMPERATURE = parseFloat(process.env.LLM_TEMPERATURE);
19
- const LLM_TOP_P = parseFloat(process.env.LLM_TOP_P);
20
19
 
21
20
  // --------------------------------------------
22
21
  // -- import functions from bedrock-wrapper --
@@ -59,7 +58,6 @@ async function testModel(model, awsCreds, testMessage, isStreaming, useConverseA
59
58
  max_tokens: LLM_MAX_GEN_TOKENS,
60
59
  stream: isStreaming,
61
60
  temperature: LLM_TEMPERATURE,
62
- top_p: LLM_TOP_P,
63
61
  include_thinking_data: true,
64
62
  };
65
63
 
@@ -57,7 +57,6 @@ async function testStopSequence(model, awsCreds, testCase, isStreaming, useConve
57
57
  max_tokens: 200,
58
58
  stream: isStreaming,
59
59
  temperature: 0.1,
60
- top_p: 0.9,
61
60
  stop_sequences: testCase.stopSequences
62
61
  };
63
62
 
@@ -1,16 +0,0 @@
1
- [
2
- {
3
- "session_id": "ab845abf-67e2-4cb9-95e2-3942e38326c7",
4
- "transcript_path": "C:\\Users\\Justin.Parker\\.claude\\projects\\C--git-bedrock-wrapper\\ab845abf-67e2-4cb9-95e2-3942e38326c7.jsonl",
5
- "cwd": "C:\\git\\bedrock-wrapper",
6
- "hook_event_name": "Notification",
7
- "message": "Claude is waiting for your input"
8
- },
9
- {
10
- "session_id": "ab845abf-67e2-4cb9-95e2-3942e38326c7",
11
- "transcript_path": "C:\\Users\\Justin.Parker\\.claude\\projects\\C--git-bedrock-wrapper\\ab845abf-67e2-4cb9-95e2-3942e38326c7.jsonl",
12
- "cwd": "C:\\git\\bedrock-wrapper",
13
- "hook_event_name": "Notification",
14
- "message": "Claude is waiting for your input"
15
- }
16
- ]