Skip to content

Commit 300a72d

Browse files
author
Kamil Sobol
authored
Infer executable tool input type from input schema (#2070)
* Infer executable tool input type from input schema * Infer executable tool input type from input schema * tests * npm install * that is better * fix that
1 parent 27202b4 commit 300a72d

File tree

17 files changed

+375
-92
lines changed

17 files changed

+375
-92
lines changed

.changeset/eleven-mails-scream.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@aws-amplify/ai-constructs': minor
3+
'@aws-amplify/backend-ai': minor
4+
---
5+
6+
Infer executable tool input type from input schema

package-lock.json

Lines changed: 43 additions & 23 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/ai-constructs/API.md

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
import * as bedrock from '@aws-sdk/client-bedrock-runtime';
1010
import { Construct } from 'constructs';
1111
import { FunctionResources } from '@aws-amplify/plugin-types';
12+
import * as jsonSchemaToTypeScript from 'json-schema-to-ts';
1213
import { ResourceProvider } from '@aws-amplify/plugin-types';
13-
import * as smithy from '@smithy/types';
1414

1515
declare namespace __export__conversation {
1616
export {
@@ -25,10 +25,12 @@ declare namespace __export__conversation__runtime {
2525
ConversationMessage,
2626
ConversationMessageContentBlock,
2727
ConversationTurnEvent,
28+
createExecutableTool,
2829
ExecutableTool,
30+
FromJSONSchema,
31+
JSONSchema,
2932
handleConversationTurnEvent,
3033
ToolDefinition,
31-
ToolExecutionInput,
3234
ToolInputSchema,
3335
ToolResultContentBlock
3436
}
@@ -111,28 +113,36 @@ type ConversationTurnEvent = {
111113
};
112114
};
113115

116+
// @public
117+
const createExecutableTool: <TJSONSchema extends JSONSchema = JSONSchema, TToolInput = FromJSONSchema<TJSONSchema>>(name: string, description: string, inputSchema: ToolInputSchema<TJSONSchema>, handler: (input: TToolInput) => Promise<bedrock.ToolResultContentBlock>) => ExecutableTool<TJSONSchema, TToolInput>;
118+
114119
// @public (undocumented)
115-
type ExecutableTool = ToolDefinition & {
116-
execute: (input: ToolExecutionInput | undefined) => Promise<ToolResultContentBlock>;
120+
type ExecutableTool<TJSONSchema extends JSONSchema = JSONSchema, TToolInput = FromJSONSchema<TJSONSchema>> = ToolDefinition<TJSONSchema> & {
121+
execute: (input: TToolInput) => Promise<ToolResultContentBlock>;
117122
};
118123

124+
// @public (undocumented)
125+
type FromJSONSchema<TJSONSchema extends JSONSchema> = jsonSchemaToTypeScript.FromSchema<TJSONSchema>;
126+
119127
// @public
120128
const handleConversationTurnEvent: (event: ConversationTurnEvent, props?: {
121-
tools?: Array<ExecutableTool>;
129+
tools?: Array<ExecutableTool<JSONSchema, any>>;
122130
}) => Promise<void>;
123131

124132
// @public (undocumented)
125-
type ToolDefinition = {
133+
type JSONSchema = jsonSchemaToTypeScript.JSONSchema;
134+
135+
// @public (undocumented)
136+
type ToolDefinition<TJSONSchema extends JSONSchema = JSONSchema> = {
126137
name: string;
127138
description: string;
128-
inputSchema: ToolInputSchema;
139+
inputSchema: ToolInputSchema<TJSONSchema>;
129140
};
130141

131142
// @public (undocumented)
132-
type ToolExecutionInput = smithy.DocumentType;
133-
134-
// @public (undocumented)
135-
type ToolInputSchema = bedrock.ToolInputSchema;
143+
type ToolInputSchema<TJSONSchema extends JSONSchema> = {
144+
json: TJSONSchema;
145+
};
136146

137147
// @public (undocumented)
138148
type ToolResultContentBlock = bedrock.ToolResultContentBlock;

packages/ai-constructs/package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,11 @@
2828
"dependencies": {
2929
"@aws-amplify/plugin-types": "^1.0.1",
3030
"@aws-sdk/client-bedrock-runtime": "^3.622.0",
31-
"@smithy/types": "^3.3.0"
31+
"@smithy/types": "^3.3.0",
32+
"json-schema-to-ts": "^3.1.1"
33+
},
34+
"devDependencies": {
35+
"typescript": "^5.0.0"
3236
},
3337
"peerDependencies": {
3438
"aws-cdk-lib": "^2.152.0",

packages/ai-constructs/src/conversation/runtime/bedrock_converse_adapter.test.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
ConverseCommandOutput,
1515
Message,
1616
ToolConfiguration,
17+
ToolInputSchema,
1718
ToolResultContentBlock,
1819
} from '@aws-sdk/client-bedrock-runtime';
1920
import { ConversationTurnEventToolsProvider } from './event-tools-provider';
@@ -252,14 +253,14 @@ void describe('Bedrock converse adapter', () => {
252253
toolSpec: {
253254
name: eventTool.name,
254255
description: eventTool.description,
255-
inputSchema: eventTool.inputSchema,
256+
inputSchema: eventTool.inputSchema as ToolInputSchema,
256257
},
257258
},
258259
{
259260
toolSpec: {
260261
name: additionalTool.name,
261262
description: additionalTool.description,
262-
inputSchema: additionalTool.inputSchema,
263+
inputSchema: additionalTool.inputSchema as ToolInputSchema,
263264
},
264265
},
265266
],
@@ -689,14 +690,14 @@ void describe('Bedrock converse adapter', () => {
689690
toolSpec: {
690691
name: additionalTool.name,
691692
description: additionalTool.description,
692-
inputSchema: additionalTool.inputSchema,
693+
inputSchema: additionalTool.inputSchema as ToolInputSchema,
693694
},
694695
},
695696
{
696697
toolSpec: {
697698
name: clientTool.name,
698699
description: clientTool.description,
699-
inputSchema: clientTool.inputSchema,
700+
inputSchema: clientTool.inputSchema as ToolInputSchema,
700701
},
701702
},
702703
],

packages/ai-constructs/src/conversation/runtime/bedrock_converse_adapter.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
Message,
88
Tool,
99
ToolConfiguration,
10+
ToolInputSchema,
1011
} from '@aws-sdk/client-bedrock-runtime';
1112
import {
1213
ConversationTurnEvent,
@@ -171,7 +172,9 @@ export class BedrockConverseAdapter {
171172
toolSpec: {
172173
name: t.name,
173174
description: t.description,
174-
inputSchema: t.inputSchema,
175+
// We have to cast to bedrock type as we're using different types to describe JSON schema in our API.
176+
// These types are runtime compatible.
177+
inputSchema: t.inputSchema as ToolInputSchema,
175178
},
176179
};
177180
}),

packages/ai-constructs/src/conversation/runtime/conversation_turn_executor.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { ConversationTurnResponseSender } from './conversation_turn_response_sender.js';
2-
import { ConversationTurnEvent, ExecutableTool } from './types.js';
2+
import { ConversationTurnEvent, ExecutableTool, JSONSchema } from './types.js';
33
import { BedrockConverseAdapter } from './bedrock_converse_adapter.js';
44

55
/**
@@ -54,7 +54,10 @@ export class ConversationTurnExecutor {
5454
*/
5555
export const handleConversationTurnEvent = async (
5656
event: ConversationTurnEvent,
57-
props?: { tools?: Array<ExecutableTool> }
57+
// This is by design, so that tools with different input types can be added
58+
// to single arrays. Downstream code doesn't use these types.
59+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
60+
props?: { tools?: Array<ExecutableTool<JSONSchema, any>> }
5861
): Promise<void> => {
5962
await new ConversationTurnExecutor(event, props?.tools ?? []).execute();
6063
};

packages/ai-constructs/src/conversation/runtime/event-tools-provider/event_tools_provider.test.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,17 @@ void describe('events tool provider', () => {
3636
description: 'toolDescription1',
3737
inputSchema: {
3838
json: {
39-
tool1: 'value1',
39+
type: 'object',
40+
properties: {
41+
tool1Property: { type: 'string' },
42+
},
4043
},
4144
},
4245
graphqlRequestInputDescriptor: {
4346
queryName: 'queryName1',
4447
selectionSet: 'selection1',
4548
propertyTypes: {
46-
property1: 'type1',
49+
tool1Property: 'type1',
4750
},
4851
},
4952
};
@@ -52,14 +55,17 @@ void describe('events tool provider', () => {
5255
description: 'toolDescription2',
5356
inputSchema: {
5457
json: {
55-
tool1: 'value2',
58+
type: 'object',
59+
properties: {
60+
tool2Property: { type: 'string' },
61+
},
5662
},
5763
},
5864
graphqlRequestInputDescriptor: {
5965
queryName: 'queryName2',
6066
selectionSet: 'selection2',
6167
propertyTypes: {
62-
property1: 'type2',
68+
tool2Property: 'type2',
6369
},
6470
},
6571
};

0 commit comments

Comments
 (0)