跳至主要內容

在 React + Vite 項目中整合 Mastra

在本指南中,你會使用 Mastra 建立一個可呼叫 Tool 的 AI Agent,然後從 Mastra 的獨立伺服器直接呼叫該 Agent,將它連接至 React。

你會使用 AI SDK UIAI Elements 建立美觀且具互動性的聊天體驗。

開始之前
開始之前 的直接連結

  • 你需要取得受支援 model provider 的 API 金鑰。如果沒有偏好,可使用 OpenAI
  • 安裝 Node.js v22.13.0 或更新版本

建立新的 React + Vite 應用程式(可選)
建立新的 React + Vite 應用程式(可選) 的直接連結

如果你已有使用 Tailwind 的 React + Vite 應用程式,可跳至下一步。

建立項目框架
建立項目框架 的直接連結

執行以下命令以建立新的 React + Vite 應用程式

npm create vite@latest mastra-react -- --template react-ts

這會建立名為 mastra-react 的項目,但你可以換成任何想用的名稱。

前往你的項目目錄:

cd mastra-react

Tailwind
Tailwind 的直接連結

接着安裝 Tailwind:

npm install tailwindcss @tailwindcss/vite

設定 Vite plugins:

vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import path from 'path'
import tailwindcss from '@tailwindcss/vite'

export default defineConfig({
plugins: [react(), tailwindcss()],
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
},
},
})

以下列內容取代 src/index.css 的所有內容:

src/index.css
@import 'tailwindcss';

將以下 compilerOptions 加入 tsconfig.json

tsconfig.json
{
// ...
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"],
},
},
}

編輯 tsconfig.app.json 以解析路徑:

tsconfig.app.json
{
"compilerOptions": {
// ...
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"],
},
// ...
},
}

初始化 Mastra
初始化 Mastra 的直接連結

執行 mastra init。系統提示時,選擇 Provider(例如 OpenAI)並輸入你的金鑰:

npx mastra@latest init

這會建立一個 src/mastra 資料夾,當中包含天氣 Agent 範例及以下檔案:

  • index.ts - Mastra 設定,包括記憶功能
  • tools/weather-tool.ts - 擷取指定地點天氣資料的 Tool
  • agents/weather-agent.ts- 天氣 Agent,包含使用該 Tool 的 prompt

在接下來的步驟中,你會從聊天 UI 呼叫 weather-agent.ts

安裝 AI SDK UI 和 AI Elements
安裝 AI SDK UI 和 AI Elements 的直接連結

安裝 AI SDK UI 及 Mastra adapter:

npm install @mastra/ai-sdk@latest @ai-sdk/react ai

接着初始化 AI Elements。系統提示時,選擇預設選項:

npx ai-elements@latest

這會將整個 AI Elements UI 元件庫下載至 @/components/ai-elements 資料夾。

建立聊天路由
建立聊天路由 的直接連結

開啟 src/mastra/index.ts,並在設定中加入 ⁠chatRoute()。這會建立一個 API 路由,供 React 前端呼叫並取得與 AI SDK 相容的聊天回應;下一步會配合 ⁠useChat() 使用。

src/mastra/index.ts
import { Mastra } from '@mastra/core/mastra'
// Existing imports...
import { chatRoute } from '@mastra/ai-sdk'

export const mastra = new Mastra({
// Existing config...
server: {
apiRoutes: [
chatRoute({
path: '/chat/:agentId',
}),
],
},
})

加入聊天 UI
加入聊天 UI 的直接連結

取代 src/App.tsx 檔案,以建立聊天介面:

src/App.tsx
import * as React from 'react'
import { DefaultChatTransport, type ToolUIPart } from 'ai'
import { useChat } from '@ai-sdk/react'

import {
PromptInput,
PromptInputBody,
PromptInputTextarea,
} from '@/components/ai-elements/prompt-input'

import {
Conversation,
ConversationContent,
ConversationScrollButton,
} from '@/components/ai-elements/conversation'

import { Message, MessageContent, MessageResponse } from '@/components/ai-elements/message'

import { Tool, ToolHeader, ToolContent, ToolInput, ToolOutput } from '@/components/ai-elements/tool'

export default function App() {
const [input, setInput] = React.useState<string>('')

const { messages, sendMessage, status } = useChat({
transport: new DefaultChatTransport({
api: 'http://localhost:4111/chat/weather-agent',
}),
})

const handleSubmit = async () => {
if (!input.trim()) return

sendMessage({ text: input })
setInput('')
}

return (
<div className="relative mx-auto size-full h-screen max-w-4xl p-6">
<div className="flex h-full flex-col">
<Conversation className="h-full">
<ConversationContent>
{messages.map(message => (
<div key={message.id}>
{message.parts?.map((part, i) => {
if (part.type === 'text') {
return (
<Message key={`${message.id}-${i}`} from={message.role}>
<MessageContent>
<MessageResponse>{part.text}</MessageResponse>
</MessageContent>
</Message>
)
}

if (part.type?.startsWith('tool-')) {
return (
<Tool key={`${message.id}-${i}`}>
<ToolHeader
type={(part as ToolUIPart).type}
state={(part as ToolUIPart).state || 'output-available'}
className="cursor-pointer"
/>
<ToolContent>
<ToolInput input={(part as ToolUIPart).input || {}} />
<ToolOutput
output={(part as ToolUIPart).output}
errorText={(part as ToolUIPart).errorText}
/>
</ToolContent>
</Tool>
)
}

return null
})}
</div>
))}
<ConversationScrollButton />
</ConversationContent>
</Conversation>
<PromptInput onSubmit={handleSubmit} className="mt-20">
<PromptInputBody>
<PromptInputTextarea
onChange={e => setInput(e.target.value)}
className="md:leading-10"
value={input}
placeholder="Ask about the weather..."
disabled={status !== 'ready'}
/>
</PromptInputBody>
</PromptInput>
</div>
</div>
)
}

此元件會將 useChat() 連接至 chat/weather-agent endpoint,把 prompt 傳送至該處,並以串流方式逐段傳回回應。

它會使用 <MessageResponse> 元件顯示回應文字,並以 <Tool> 元件顯示所有 Tool 呼叫。

測試你的 Agent
測試你的 Agent 的直接連結

要使用聊天介面測試 Agent,請同時執行 Mastra 伺服器和 Vite 開發伺服器。

  1. 啟動 Mastra 開發伺服器:

    npx mastra dev
  2. 在另一個終端機視窗中啟動 Vite 開發伺服器:

    npm run dev
  3. http://localhost:5173 開啟應用程式

  4. 嘗試詢問天氣。如果 API 金鑰設定正確,你便會收到回應

後續步驟
後續步驟 的直接連結

恭喜你使用 React 建立了 Mastra Agent!🎉

接下來,你可以使用自己的 Tool 和邏輯擴充項目:

準備好後,可進一步了解 Mastra 如何與 AI SDK UI 和 React 整合,以及如何在任何地方部署 Agent: