Claude 4出ましたね。!なにか作りたくなりますよね!Amplify Gen2ですよね!
前にやったことがあるからすんなり行くと思ったら、、
見事ハマりました
Oh no...
備忘録でございます。
ドキュメントどおりに最速で下準備
-
Viteでプロジェクトを作る
npm create vite@latest
│ ◇ Project name: │ amplify-ai-kit-app │ ◇ Select a framework: │ React │ ◇ Select a variant: │ TypeScript + SWC │ ◇ Scaffolding project in /workspaces/workspace/amplify-ai/amplify-ai-kit-app... │ └ Done. Now run: cd amplify-ai-kit-app npm install npm run dev
-
ライブラリーインストール
cd amplify-ai-kit-app npm i
-
Amplify Gen2追加
npm create amplify@latest
✔ Where should we create your project? .
-
サンドボックス起動
npx ampx sandbox
-
バックエンドにAI機能追加
Amazon Nova Liteを使用します。
amplify/data/resource.ts... const schema = a.schema({ Todo: a .model({ content: a.string(), }) .authorization((allow) => [allow.guest()]), + chat: a + .conversation({ + aiModel: a.ai.model("Amazon Nova Lite"), + systemPrompt: "You are a helpful assistant", + }) + .authorization((allow) => allow.owner()),
-
クライアントライブラリーをインストール
npm add aws-amplify @aws-amplify/ui-react @aws-amplify/ui-react-ai
-
src/main.tsx
でクライアントライブラリー読み込みsrc/main.tsximport { Amplify } from 'aws-amplify'; import '@aws-amplify/ui-react/styles.css'; import outputs from '../amplify_outputs.json'; Amplify.configure(outputs);
-
データクライアントを作成
src/client.tsimport { generateClient } from "aws-amplify/api"; import { Schema } from "../amplify/data/resource"; import { createAIHooks } from "@aws-amplify/ui-react-ai"; export const client = generateClient<Schema>({ authMode: "userPool" }); export const { useAIConversation, useAIGeneration } = createAIHooks(client);
-
App.tsx
を修正(全置き換え)src/App.tsximport { Authenticator } from "@aws-amplify/ui-react"; import { AIConversation } from '@aws-amplify/ui-react-ai'; import { useAIConversation } from './client'; export default function App() { const [ { data: { messages }, isLoading, }, handleSendMessage, ] = useAIConversation('chat'); // 'chat' is based on the key for the conversation route in your schema. return ( <Authenticator> <AIConversation messages={messages} isLoading={isLoading} handleSendMessage={handleSendMessage} /> </Authenticator> ); }
-
レイアウトがずれるので
src/index.css
とsrc/App.css
をファイルを残しつつソースを全削除
はいできた。
- 起動する
npm run dev -- --host
ログインしたらチャットができました
未対応モデルを使用する
さて、ここからが本題です。
おさらいですが、使用するAIモデルはamplify/data/resource.ts
で指定する仕組みです。
const schema = a.schema({
chat: a
.conversation({
aiModel: a.ai.model("Amazon Nova Lite"),
systemPrompt: "You are a helpful assistant",
})
.authorization((allow) => allow.owner()),
a.ai.model
の引数ですが、任意の文字列が指定できるわけではなくsupportedModelsLookup
として定義されているものだけが選択できます。
ここにないモデル(例えばJamba 1.5 Largeなど)を使用したい場合は以下のように指定します。
chat: a
.conversation({
+ aiModel: { resourcePath: "ai21.jamba-1-5-large-v1:0" },
- aiModel: a.ai.model("Amazon Nova Lite"),
systemPrompt: "You are a helpful assistant",
})
.authorization((allow) => allow.owner()),
この指定方法で動作しました。
クロスリージョン推論する
なるほど、と。全部理解した。
クロスリージョン推論はどうするのって?そんなときはこうです。
aiModel: { resourcePath: "us.amazon.nova-premier-v1:0" }
と思ったあなた。これでは残念ながら駄目です🥲
裏側でよしなに作られるLambdaに付与されるIAMロールが変な感じになります。
正しくは、foundation-modelはus
がつかないamazon.nova-premier-v1:0でかつ、推論プロファイルへのアクセス権限も必要です。
この部分がよしなにはやってくれないので、自前でやります。
-
追加ライブラリーをインストール
npm install @aws-amplify/backend-ai
-
amplify/data/resource.ts
を修正handlerを追加で指定します。
amplify/data/resource.tsimport { type ClientSchema, a, defineData } from "@aws-amplify/backend"; + import { defineConversationHandlerFunction } from "@aws-amplify/backend-ai/conversation"; + export const model = "anthropic.claude-sonnet-4-20250514-v1:0"; + export const crossRegionModel = `us.${model}`; + export const conversationHandler = defineConversationHandlerFunction({ + entry: "./conversationHandler.ts", + name: "conversationHandler", + models: [{ modelId: crossRegionModel }], + }); const schema = a.schema({ chat: a .conversation({ + aiModel: { resourcePath: crossRegionModel }, systemPrompt: "You are a helpful assistant", + handler: conversationHandler, }) .authorization((allow) => allow.owner()), }); export type Schema = ClientSchema<typeof schema>; export const data = defineData({ schema, authorizationModes: { defaultAuthorizationMode: "identityPool", }, });
-
amplify/data/conversationHandler.ts
を作成ハンドラーを作ります。何をしてるのかはよくわかりません。
amplify/data/conversationHandler.tsimport { handleConversationTurnEvent } from "@aws-amplify/backend-ai/conversation/runtime"; export const handler = handleConversationTurnEvent;
-
amplify/backend.ts
を修正IAMロールを愚直に指定します。(リージョンが変わると変わると思うので注意)
amplify/backend.tsimport { defineBackend } from "@aws-amplify/backend"; import { PolicyStatement } from "aws-cdk-lib/aws-iam"; import { auth } from "./auth/resource"; import { + conversationHandler, + crossRegionModel, data, + model, } from "./data/resource"; /** * @see https://docs.amplify.aws/react/build-a-backend/ to add storage, functions, and more */ const backend = defineBackend({ auth, data, + conversationHandler, }); + backend.conversationHandler.resources.lambda.addToRolePolicy( + new PolicyStatement({ + resources: [ + `arn:aws:bedrock:us-east-1:${backend.stack.account}:inference-profile/${crossRegionModel}`, + `arn:aws:bedrock:us-east-1::foundation-model/${model}`, + `arn:aws:bedrock:us-east-2::foundation-model/${model}`, + `arn:aws:bedrock:us-west-2::foundation-model/${model}`, + ], + actions: ["bedrock:InvokeModelWithResponseStream"], + }) + );
これでClaude 4が使えましたよ!
参考