@bedrockio/ai 0.9.1 → 0.9.3

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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## 0.9.3
2
+
3
+ - Further fixes for empty input.
4
+
5
+ ## 0.9.2
6
+
7
+ - Strip empty input out of resulting messages.
8
+
1
9
  ## 0.9.1
2
10
 
3
11
  - Pass interpolated instructions back in result.
@@ -107,6 +107,12 @@ class BaseClient {
107
107
  getTemplateSource(name) {
108
108
  return this.renderer.getTemplateSource(name);
109
109
  }
110
+ getFilteredMessages(options) {
111
+ const { messages = [] } = options;
112
+ return messages.filter((message) => {
113
+ return message.content.trim();
114
+ });
115
+ }
110
116
  // Protected
111
117
  runPrompt(options) {
112
118
  void options;
@@ -214,19 +220,30 @@ class BaseClient {
214
220
  if (Array.isArray(input) && !input.length) {
215
221
  input = '';
216
222
  }
223
+ let result = [];
217
224
  if (Array.isArray(input)) {
218
- return input;
225
+ result = input;
219
226
  }
220
227
  else {
221
228
  const { messages = [] } = options;
222
- return [
229
+ result = [
223
230
  ...messages,
224
231
  {
225
232
  role: 'user',
226
- content: input || '',
233
+ content: input,
227
234
  },
228
235
  ];
229
236
  }
237
+ if (result.length === 1 && !result[0].content) {
238
+ // If a single user input is passed and is nullish, coerce it to a
239
+ // single space. Combined with getFilteredMessages below this allows
240
+ // a chatbot the ability to "speak first" by prompting it with empty
241
+ // content. The empty message will be filtered out of the final result
242
+ // appearing as if the chatbot went first. Note empty string will also
243
+ // fail here hence the single space.
244
+ result[0].content = ' ';
245
+ }
246
+ return result;
230
247
  }
231
248
  normalizeSchema(options) {
232
249
  let { schema } = options;
@@ -57,10 +57,9 @@ class AnthropicClient extends BaseClient_js_1.default {
57
57
  return toolBlock?.input || null;
58
58
  }
59
59
  normalizeResponse(response, options) {
60
- const { messages } = options;
61
60
  return {
62
61
  messages: [
63
- ...messages,
62
+ ...this.getFilteredMessages(options),
64
63
  ...response.content
65
64
  .filter((item) => {
66
65
  return item.type === 'text';
@@ -113,7 +112,7 @@ class AnthropicClient extends BaseClient_js_1.default {
113
112
  return {
114
113
  type: 'stop',
115
114
  messages: [
116
- ...options.messages,
115
+ ...this.getFilteredMessages(options),
117
116
  {
118
117
  role: 'assistant',
119
118
  content: options.buffer,
@@ -91,10 +91,9 @@ class OpenAiClient extends BaseClient_js_1.default {
91
91
  return JSON.parse(last.text);
92
92
  }
93
93
  normalizeResponse(response, options) {
94
- const { messages } = options;
95
94
  return {
96
95
  messages: [
97
- ...messages,
96
+ ...this.getFilteredMessages(options),
98
97
  {
99
98
  role: 'assistant',
100
99
  content: response.output_text,
@@ -152,7 +151,7 @@ class OpenAiClient extends BaseClient_js_1.default {
152
151
  id: event.response.id,
153
152
  instructions: options.instructions,
154
153
  messages: [
155
- ...options.messages,
154
+ ...this.getFilteredMessages(options),
156
155
  {
157
156
  role: 'assistant',
158
157
  content: output?.content[0].text,
@@ -105,6 +105,12 @@ export default class BaseClient {
105
105
  getTemplateSource(name) {
106
106
  return this.renderer.getTemplateSource(name);
107
107
  }
108
+ getFilteredMessages(options) {
109
+ const { messages = [] } = options;
110
+ return messages.filter((message) => {
111
+ return message.content.trim();
112
+ });
113
+ }
108
114
  // Protected
109
115
  runPrompt(options) {
110
116
  void options;
@@ -212,19 +218,30 @@ export default class BaseClient {
212
218
  if (Array.isArray(input) && !input.length) {
213
219
  input = '';
214
220
  }
221
+ let result = [];
215
222
  if (Array.isArray(input)) {
216
- return input;
223
+ result = input;
217
224
  }
218
225
  else {
219
226
  const { messages = [] } = options;
220
- return [
227
+ result = [
221
228
  ...messages,
222
229
  {
223
230
  role: 'user',
224
- content: input || '',
231
+ content: input,
225
232
  },
226
233
  ];
227
234
  }
235
+ if (result.length === 1 && !result[0].content) {
236
+ // If a single user input is passed and is nullish, coerce it to a
237
+ // single space. Combined with getFilteredMessages below this allows
238
+ // a chatbot the ability to "speak first" by prompting it with empty
239
+ // content. The empty message will be filtered out of the final result
240
+ // appearing as if the chatbot went first. Note empty string will also
241
+ // fail here hence the single space.
242
+ result[0].content = ' ';
243
+ }
244
+ return result;
228
245
  }
229
246
  normalizeSchema(options) {
230
247
  let { schema } = options;
@@ -51,10 +51,9 @@ export class AnthropicClient extends BaseClient {
51
51
  return toolBlock?.input || null;
52
52
  }
53
53
  normalizeResponse(response, options) {
54
- const { messages } = options;
55
54
  return {
56
55
  messages: [
57
- ...messages,
56
+ ...this.getFilteredMessages(options),
58
57
  ...response.content
59
58
  .filter((item) => {
60
59
  return item.type === 'text';
@@ -107,7 +106,7 @@ export class AnthropicClient extends BaseClient {
107
106
  return {
108
107
  type: 'stop',
109
108
  messages: [
110
- ...options.messages,
109
+ ...this.getFilteredMessages(options),
111
110
  {
112
111
  role: 'assistant',
113
112
  content: options.buffer,
@@ -85,10 +85,9 @@ export class OpenAiClient extends BaseClient {
85
85
  return JSON.parse(last.text);
86
86
  }
87
87
  normalizeResponse(response, options) {
88
- const { messages } = options;
89
88
  return {
90
89
  messages: [
91
- ...messages,
90
+ ...this.getFilteredMessages(options),
92
91
  {
93
92
  role: 'assistant',
94
93
  content: response.output_text,
@@ -146,7 +145,7 @@ export class OpenAiClient extends BaseClient {
146
145
  id: event.response.id,
147
146
  instructions: options.instructions,
148
147
  messages: [
149
- ...options.messages,
148
+ ...this.getFilteredMessages(options),
150
149
  {
151
150
  role: 'assistant',
152
151
  content: output?.content[0].text,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bedrockio/ai",
3
- "version": "0.9.1",
3
+ "version": "0.9.3",
4
4
  "description": "Bedrock wrapper for common AI chatbots.",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -22,6 +22,7 @@ export default class BaseClient {
22
22
  * @param {string} name
23
23
  */
24
24
  getTemplateSource(name: string): any;
25
+ getFilteredMessages(options: any): any;
25
26
  runPrompt(options: any): void;
26
27
  runStream(options: any): void;
27
28
  getTextResponse(response: any): void;
@@ -1 +1 @@
1
- {"version":3,"file":"BaseClient.d.ts","sourceRoot":"","sources":["../src/BaseClient.js"],"names":[],"mappings":"AAKA;IACE,0BASC;IARC,aAIC;IACD,2BAEE;IAKJ;;;;;OAKG;IACH,gBAFW,aAAa,gBAiCvB;IAED;;;;;OAKG;IACH,gBAHW,aAAa,GAAG,aAAa,gCAsDvC;IAED;;;;OAIG;IACH,wBAFW,MAAM,OAIhB;IAID,8BAGC;IAED,8BAGC;IAED,qCAGC;IAED;;OAEG;IACH,0CAGC;IAED;;OAEG;IACH,oDAIC;IAED;;OAEG;IACH,oDAIC;IAID;;OAEG;IACH,oCAOC;IAED;;;MAeC;IAED,4CAiDC;IAED,uCAoBC;IAED;;;MA4BC;IAED,uDAWC;IAED,kDAMC;CACF;;;;;WAIa,MAAM;kBACN,MAAM;;;;cACN,aAAa,EAAE;;;;YACf,MAAM;;;;YACN,OAAO;;;;;;;;aAEP,MAAM,GAAG,MAAM;;;;;;;;;;;sBAOf,MAAM;;;UAKN,QAAQ,GAAG,MAAM,GAAG,WAAW;aAC/B,MAAM;;iCA1Va,sBAAsB"}
1
+ {"version":3,"file":"BaseClient.d.ts","sourceRoot":"","sources":["../src/BaseClient.js"],"names":[],"mappings":"AAKA;IACE,0BASC;IARC,aAIC;IACD,2BAEE;IAKJ;;;;;OAKG;IACH,gBAFW,aAAa,gBAiCvB;IAED;;;;;OAKG;IACH,gBAHW,aAAa,GAAG,aAAa,gCAsDvC;IAED;;;;OAIG;IACH,wBAFW,MAAM,OAIhB;IAED,uCAKC;IAID,8BAGC;IAED,8BAGC;IAED,qCAGC;IAED;;OAEG;IACH,0CAGC;IAED;;OAEG;IACH,oDAIC;IAED;;OAEG;IACH,oDAIC;IAID;;OAEG;IACH,oCAOC;IAED;;;MAeC;IAED,4CAiDC;IAED,uCAkCC;IAED;;;MA4BC;IAED,uDAWC;IAED,kDAMC;CACF;;;;;WAIa,MAAM;kBACN,MAAM;;;;cACN,aAAa,EAAE;;;;YACf,MAAM;;;;YACN,OAAO;;;;;;;;aAEP,MAAM,GAAG,MAAM;;;;;;;;;;;sBAOf,MAAM;;;UAKN,QAAQ,GAAG,MAAM,GAAG,WAAW;aAC/B,MAAM;;iCA/Wa,sBAAsB"}
@@ -1 +1 @@
1
- {"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../src/anthropic.js"],"names":[],"mappings":"AAMA;IACE,6BAA2C;IAIzC,kBAAoC;IAGtC;;;OAGG;IACH,4BAGC;IAED;;wGA2BC;IAED;;wGAKC;IAED,oCAKC;IASD;;;;;;MAkBC;IAED;;;MAKC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MAsCC;IAID;;;;;;;;;;MA0CC;IAED,oCAKC;IAUD;;;;MAOC;IAID;;;;MAOC;IAED;;;;MAQC;CACF;uBApOsB,iBAAiB;sBAFlB,mBAAmB"}
1
+ {"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../src/anthropic.js"],"names":[],"mappings":"AAMA;IACE,6BAA2C;IAIzC,kBAAoC;IAGtC;;;OAGG;IACH,4BAGC;IAED;;wGA2BC;IAED;;wGAKC;IAED,oCAKC;IASD;;;;;;MAiBC;IAED;;;MAKC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MAsCC;IAID;;;;;;;;;;MA0CC;IAED,oCAKC;IAUD;;;;MAOC;IAID;;;;MAOC;IAED;;;;MAQC;CACF;uBAnOsB,iBAAiB;sBAFlB,mBAAmB"}
@@ -1 +1 @@
1
- {"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../src/openai.js"],"names":[],"mappings":"AAIA;IACE,6BAAoC;IAIlC,eAAiC;IAGnC;;;;OAIG;IACH,kBAHW,cAAc,qBAgCxB;IAED;;yFAiCC;IAED;;yFAKC;IAED,oCAEC;IAwBD;;;;;;;MAeC;IAED;;;MAKC;IAID;;;;;;;;;;MAmBC;CA2CF;6BAQA,GAAC,GAAK,KAAK,GACL,SAAS,GACT,WAAW,GACX,aAAa,GACb,YAAY,GACZ,WAAW,GACX,QAAQ,GACR,OAAO,GACP,OAAO,GACP,MAAM,GACN,QAAQ;uBA5NQ,iBAAiB;mBAFrB,QAAQ"}
1
+ {"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../src/openai.js"],"names":[],"mappings":"AAIA;IACE,6BAAoC;IAIlC,eAAiC;IAGnC;;;;OAIG;IACH,kBAHW,cAAc,qBAgCxB;IAED;;yFAiCC;IAED;;yFAKC;IAED,oCAEC;IAwBD;;;;;;;MAcC;IAED;;;MAKC;IAID;;;;;;;;;;MAmBC;CA2CF;6BAQA,GAAC,GAAK,KAAK,GACL,SAAS,GACT,WAAW,GACX,aAAa,GACb,YAAY,GACZ,WAAW,GACX,QAAQ,GACR,OAAO,GACP,OAAO,GACP,MAAM,GACN,QAAQ;uBA3NQ,iBAAiB;mBAFrB,QAAQ"}