MastraとNext.jsで製造業の工場トラブル事例検索チャットボットを作ってみた

MastraとNext.jsで製造業の工場トラブル事例検索チャットボットを作ってみた

Clock Icon2025.03.22

はじめに

MastraはAIアプリケーションを構築するためのTypeScriptのフレームワークです。ELv2ライセンスで、マネージドサービスとして他社に提供することはNGですが、業務アプリの構築は可能です。なぜELv2なのかドキュメントもありますので詳細はこちらをご参照ください。

https://mastra.ai/docs/faq#elastic-license-20-elv2

The primary limitation is that you cannot provide Mastra as a hosted or managed service that offers users access to the substantial functionality of the software.

(訳) 主な制限は、ソフトウェアの重要な機能にユーザーがアクセスできるホスト型または管理型のサービスとして Mastra を提供できないことです。

またAIを活用したTypeScriptツールキットは、Vercel社がAI SDKを公開しています。

https://sdk.vercel.ai/docs/introduction

こちらに AI SDKとMastraの関係が書いており
https://mastra.ai/docs/frameworks/02-ai-sdk

Mastra acts as a layer on top of AI SDK to help teams productionize their proof-of-concepts quickly and easily.

とあるように、MastraはAI SDK 上位レイヤーとして機能するという位置付けでもあります。

今回はMastraを試しつつ、製造業の保全業務周りで使えそうな、テキストや画像で過去のトラブル記録を検索するというアプリを作成します。

今回は最初なのでMastraのAgentとWorkflow機能を試しつつ、MastraのPlaygroundで便利な機能を適宜紹介します。なので今回紹介する機能はMastraのほんの一部となります。

概要

構成図

今回はローカルの動作に限定します。
architecture.drawio

デモ

アプリは以下のような形で動作します。容量の都合上冒頭のみです..。一瞬止まりますが、これはtool use(function calling)が走っているためです。

CleanShot 2025-03-22 at 05.31.03

別の画像の例も貼ります。前のデモは写真にまんま事例の文字列が入っていたため...
CleanShot 2025-03-22 at 08.16.30

全体的な出力の画像は以下の通りです。
CleanShot 2025-03-22 at 05.32.48@2x

CleanShot 2025-03-22 at 08.19.13@2x

補足は以下の通りです。

  • 本当はMastraのPlayGroundのチャットUIで済ませる予定でしたが、マルチモーダルの対応ができていないため今回はUIをNext.jsで自作しています。
    • チャットUIはQuick Start用にコード量は抑えています。リッチなものを求めている場合、mckaywrigley/chatbot-uiがおすすめです。
    • チャットはストリーミングにし、@ai-sdk/react に寄せるようにExperimentalな機能を利用してます(注意)

ソースコード

リポジトリ、サンプルコード、データセットは以下のリポジトリです。必要なコードやデータは全て格納しています。
https://github.com/shuntaka9576/nextjs-mastra-manufacturing

利用するもの

サービス名 用途
Bedrock 埋め込みモデル(cohere.embed-multilingual-v3)と生成AIモデル(anthropic.claude-3-5-sonnet-20241022-v2:0)を利用します
Cohere 事例書き込みと検索文字列のベクトル化
TypeScript ソースコード
Pinecone local[1] ベクトルデータベース
Grafana関連 TempoとGrafanaですが、イメージにはprometheusやlokiも含まれています

基本 @ai-sdk/amazon-bedrock は使っていますが、Cohereで埋め込みベクトルを生成する箇所は、@aws-sdk/client-bedrock-runtimeを利用しています。

https://github.com/vercel/ai/issues/5055

@mastra/pinecone はローカルpineconeに未対応のため未採用

検索に関して

今回は埋め込みモデルにテキストと画像の両方に対応しているcohere.embed-multilingual-v3を利用します。モデルの詳細はこちらをご参照ください。事例をベクトル化してpineconeに格納します。その後テキスト、画像のクエリをベクトル化し、コサイン類似度で類似事例をセマンティック検索します。全文検索は単語の一致で検索するのに対し、セマンテック検索は言葉の意味や文脈を理解して関連する概念も含めて検索するので、曖昧な検索を行うケースが多い場合に便利です。

ソース構成解説

階層は2つまで表示しています。

$ eza -T --git-ignore -L 2
.
├── bin
│   └── init-vector-store.ts # pinecorneにデータを突っ込むスクリプト
├── biome.json
├── compose.yml # pinecorne, tmpo, grafanaが起動するdokcerファイル
├── data
│   ├── dataset.csv # トラブル事例のデータセット(LLMで生成)
│   └── trobules # トラブル事例の画像群(geminiで生成)
├── docs
│   ├── app.gif
│   └── architecture.drawio.png # アーキテクチャ図
├── next.config.ts
├── package-lock.json
├── package.json
├── postcss.config.mjs
├── public
│   ├── file.svg
│   ├── globe.svg
│   ├── next.svg
│   ├── vercel.svg
│   └── window.svg
├── README.md
├── src
│   ├── app      # Next.jsのソースコード
│   ├── lib      # 共通のライブラリ
│   └── mastra   # Mastra関連コード
├── test
│   ├── globalSetup.ts
│   └── testSetup.ts
├── tsconfig.json
└── vitest.config.ts

準備

Next.jsとMastraのセットアップ

前述のリポジトリを利用することを推奨しますが、初期化方法を知りたい方向けに書きます。

基本的に好みで大丈夫です。自分的にはNext.jsもMastraのsrcディレクトリを作るのが良いと思います。これはMastraのCLIがデフォルトでsrc/mastraに一連のコードがあることを期待するためです。(もちろんCLIオプションで設定可能ですが、個人的な好みで推奨しています。)

Next.jsセットアップ
$ npx create-next-app@latest
✔ What is your project named? … nextjs-mastra-sample
✔ Would you like to use TypeScript? … No / Yes # Yes
✔ Would you like to use ESLint? … No / Yes # No
✔ Would you like to use Tailwind CSS? … No / Yes # Yes
✔ Would you like your code inside a `src/` directory? … No / Yes # YES
✔ Would you like to use App Router? (recommended) … No / Yes # Yes
✔ Would you like to use Turbopack for `next dev`? … No / Yes # Yes
✔ Would you like to customize the import alias (`@/*` by default)? … No / Yes # Yes
Creating a new Next.js app in /Users/shuntaka/repos/github.com/shuntaka9576/nextjs-mastra-sample.

Using npm.

Initializing project with template: app-tw

Installing dependencies:
- react
- react-dom
- next

Installing devDependencies:
- typescript
- @types/node
- @types/react
- @types/react-dom
- @tailwindcss/postcss
- tailwindcss

added 48 packages, and audited 49 packages in 13s

10 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
Initialized a git repository.

Success! Created nextjs-mastra-sample at /Users/shuntaka/repos/github.com/shuntaka9576/nextjs-mastra-sample
cd nextjs-mastra-sample

Mastraはsrc配下に定義しました。これはMastraのCLIがデフォルトでsrc/mastraを指定するためです。--dirオプションで変更可能なので、適宜指定してください。

Mastrasセットアップ
❯ npx mastra@latest init
│
◇  You do not have the @mastra/core package installed. Would you like to install it?
│  Yes
⠼ Installing Mastra core dependencies

removed 1 package, and audited 436 packages in 3s

48 packages are looking for funding
  run `npm fund` for details

✔ @mastra/core installed successfully
┌  Mastra Init
│
◇  Where should we create the Mastra files? (default: src/)
│  /src
│
◇  Choose components to install:
│  Agents
│
◇  Add tools?
│  Yes
│
◇  Select default provider:
│  OpenAI
│
◇  Enter your openai API key?
│  Skip for now
│
◇  Add example
│  Yes
│
◇  Make your AI IDE into a Mastra expert? (installs Mastra docs MCP server)
│  Cursor
│
│
│  Note: you will need to go into Cursor Settings -> MCP Settings and manually enable the installed Mastra MCP server.
│
│
◇
│
◇   ─────────────────────────────────────────────────────────╮
│                                                            │
│                                                            │
│        Mastra initialized successfully!                    │
│                                                            │
│        Add your OPENAI_API_KEY as an environment variable  │
│        in your .env.development file                       │
│                                                            │
│                                                            │
├────────────────────────────────────────────────────────────╯

ミドルウェアの準備

今回は ghcr.io/pinecone-io/pinecone-local:latest docker.io/grafana/otel-lgtm:0.8.1 のイメージを利用します。ソースは以下の通りです。

https://github.com/shuntaka9576/nextjs-mastra-manufacturing/blob/49f4adb3e13e8e88d812422c051a8947fedea05e/compose.yml#L1-L22

以下のコマンドで立ち上げてください。

docker compose up -d

次にpineconeにトラブル事例を投入します。

npx tsx ./bin/init-vector-store.ts

投入されるデータは以下のような形です。使わない列もあります。
https://github.com/shuntaka9576/nextjs-mastra-manufacturing/blob/49f4adb3e13e8e88d812422c051a8947fedea05e/data/dataset.csv#L1-L46

ベクトル化は、タイトルと説明と解決策で行います。
https://github.com/shuntaka9576/nextjs-mastra-manufacturing/blob/49f4adb3e13e8e88d812422c051a8947fedea05e/bin/init-vector-store.ts#L67

これにより画像やテキストで全文検索とは異なる意味的に類似性に基づいた検索が可能になります。

MastraのAgent実装

はじめに

冒頭でも紹介したこちらの実装を解説します。

CleanShot 2025-03-22 at 05.31.03

処理はシンプルです。

  1. ユーザーが画像かテキストで問い合わせる
  2. 生成AIがテキストを解析、画像が含まれる場合LLM側でマルチモーダルで解釈し、文字列にし、tool use(function calling)し、pinecorneから類似事例を検索(※ なぜ画像をテキストにするかは後述)
  3. 2の出力のフォーマットを整えて出力

実装して気づきましたが、ストリーミングで実装するとツール呼び出し前でもレスポンスが返却される点です。これはユーザーの体感時間を下げることに繋がるため体験として良いと思いました。

Next.js 実装

フロントの実装は以下の通りで、特筆することは @ai-sdk/react を利用して非常に簡単にストリーミングを実装していることです

https://github.com/shuntaka9576/nextjs-mastra-manufacturing/blob/49f4adb3e13e8e88d812422c051a8947fedea05e/src/app/chat/agent/page.tsx#L1-L112

ただ画像送信に関しては、experimental機能を活用してます。まだ安定していないと思いますので利用の際は注意してください。また、画像だけでも送信できるようにallowEmptySubmitを許可しています。
https://github.com/shuntaka9576/nextjs-mastra-manufacturing/blob/49f4adb3e13e8e88d812422c051a8947fedea05e/src/app/chat/agent/page.tsx#L68-L69

APIルートで事例検索を呼び出しています。
https://github.com/shuntaka9576/nextjs-mastra-manufacturing/blob/49f4adb3e13e8e88d812422c051a8947fedea05e/src/app/chat/agent/page.tsx#L9

APIルートの実装は、最新のメッセージを取り出してmastra呼び出しをしています。なので過去履歴を読み取ってくれる実装になっていません。。これは今後対応したいです。
https://github.com/shuntaka9576/nextjs-mastra-manufacturing/blob/49f4adb3e13e8e88d812422c051a8947fedea05e/src/app/api/chat/agent/route.ts#L1-L48

ストリーミングで返す処理もとても簡単です!
https://github.com/shuntaka9576/nextjs-mastra-manufacturing/blob/49f4adb3e13e8e88d812422c051a8947fedea05e/src/app/api/chat/agent/route.ts#L39-L40

ではmastraの実装を見てみます。

Mastra 実装

まずMastraのエージェント実装について解説します。

こちらがNext.jsのAPI RouteでimportしたMastra実装です。
https://github.com/shuntaka9576/nextjs-mastra-manufacturing/blob/49f4adb3e13e8e88d812422c051a8947fedea05e/src/mastra/agents/factoryTroubleResarchAgent.ts#L1-L50

こちらでツールを指定しています。これは画像ないし、テキストを元にpinecorneから類似事例を引っ張ってくるツールです。
https://github.com/shuntaka9576/nextjs-mastra-manufacturing/blob/49f4adb3e13e8e88d812422c051a8947fedea05e/src/mastra/agents/factoryTroubleResarchAgent.ts#L44

ツールの詳細は以下の通りです。画像かテキストまたその両方のベクトルを取得し事例検索をかけます。テキストと画像が両方指定された場合は、ベクトルの平均をとっています。
https://github.com/shuntaka9576/nextjs-mastra-manufacturing/blob/49f4adb3e13e8e88d812422c051a8947fedea05e/src/mastra/tools/similarSearch.ts#L1-L56

ただ画像に関しては、function callingで指定させないようにしています。これは、おそらくトークン量の都合で呼び出しに失敗する(適当な文字列指定してくる)もしくは呼び出しに30秒以上時間がかかるケースが多く安定しなかったためです。画像を使ったコサイン類似度による検索は次項のWorkflow機能で試します。
https://github.com/shuntaka9576/nextjs-mastra-manufacturing/blob/49f4adb3e13e8e88d812422c051a8947fedea05e/src/mastra/agents/factoryTroubleResarchAgent.ts#L20-L22

Mastra Playground

Mastraには、playgroundがついています。これが検証しながら実装を調整できるので非常の便利です。

トップ画面

実装したAgent機能はMastraのplaygroundで処理を確認することができます。以下のコマンドでlocalhost:4111でサーバーが立ち上がります。余談ですが、内部的にはHonoを採用しているそうです。

npx mastra dev

トップ画面
CleanShot 2025-03-22 at 06.08.43@2x

Tool

前項でAgentを作成する過程で、テキストないし画像で、Pineconeから類似事例を検索するツールを紹介しました。ツールとして作成しているのでPlaygroundからテストができます。

簡単にテキスト電動回転パーツに普段と違う響きが聞こえるで試してみます。
CleanShot 2025-03-22 at 07.10.32@2x

ベアリング摩耗による異音という事例が引っかかりました。セマンティック検索は単なる文字列の一致ではなく、このように意味的に類似性が高いものを検索できるため、用語の名寄せをしなくてもある程度柔軟に検索が可能です。

JSON詳細

expectedInquiryという項目がありますが、こちらは想定するクエリです。意味的類似性の検証のためのデータセットを作るため入れています。前述の通りベクトルには含めていないため、影響は一切ありません。

{
  "results": [
    {
      "id": "trouble-2023-01-07T14:15:00.000Z-assembly-motor",
      "title": "ベアリング摩耗による異音",
      "description": "ベアリング摩耗の兆候あり。3号機モーター部から断続的な金属音を検知。回転数を下げて様子見。部品交換の準備を開始。",
      "date": "2023-01-07T14:15:00.000Z",
      "line": "assembly",
      "machine": "motor",
      "type": "hardware",
      "solution": "ベアリングの交換と定期点検スケジュールの見直し",
      "expectedInquiry": "電動回転パーツに普段と違う響きが聞こえる",
      "similarity": 0.6632226
    },
    {
      "id": "trouble-2023-01-05T09:30:00.000Z-assembly-motor",
      "title": "軸受け部の金属異音と振動",
      "description": "駆動系の振動が通常より大きく、軸受け部分から金属的な異音を確認。緊急対応として減速運転で対処。明日保全部に連絡予定。",
      "date": "2023-01-05T09:30:00.000Z",
      "line": "assembly",
      "machine": "motor",
      "type": "hardware",
      "solution": "軸受けの交換と潤滑油の補充を実施",
      "expectedInquiry": "電動回転パーツに普段と違う響きが聞こえる",
      "similarity": 0.65542156
    },
    {
      "id": "trouble-2023-03-08T08:45:00.000Z-painting-controller",
      "title": "送風機ローター不均衡による振動音",
      "description": "塗装ブース換気装置から不規則な振動音が発生。点検の結果、送風機ローターにコーティング剤の付着による不均衡を確認。この状態での継続運転はベアリング破損リスクあり。",
      "date": "2023-03-08T08:45:00.000Z",
      "line": "painting",
      "machine": "controller",
      "type": "hardware",
      "solution": "ローターの洗浄と動的バランス調整、および定期清掃頻度の見直し",
      "expectedInquiry": "電動回転パーツに普段と違う響きが聞こえる",
      "similarity": 0.62663317
    },
    {
      "id": "trouble-2023-01-10T14:00:00.000Z-assembly-conveyor",
      "title": "冷却ファン固定ボルト緩みによる異常音",
      "description": "午後2時頃、A棟コンベア駆動モーターから異常音発生。点検したところ冷却ファンの固定ボルトが緩んでいたため増し締め実施。現在は正常運転中。",
      "date": "2023-01-10T14:00:00.000Z",
      "line": "assembly",
      "machine": "conveyor",
      "type": "hardware",
      "solution": "固定ボルトの増し締めと緩み止め剤の塗布",
      "expectedInquiry": "電動回転パーツに普段と違う響きが聞こえる",
      "similarity": 0.6034444
    }
  ]
}

次は以下の画像で試しています。
04_trobule

cat ./data/trobules/04_trobule.jpeg| base64 | pbcopy

CleanShot 2025-03-22 at 07.05.24@2x

冷却液循環系統からの液剤漏出が一番近似しているので、上手くいってそうということがわかります。

JSON詳細
{
  "results": [
    {
      "id": "trouble-2023-02-10T13:25:00.000Z-machining-controller",
      "title": "冷却液循環系統からの液剤漏出",
      "description": "加工ラインで床面に青色の痕跡を発見。機械本体下部から冷却液が少量ずつ滴下していることを確認。ホースの接続部に微細なひび割れが発生し、圧力がかかった際に液体が噴出する状態になっていた。作業を一時中断し、該当箇所の清掃を実施。",
      "date": "2023-02-10T13:25:00.000Z",
      "line": "machining",
      "machine": "controller",
      "type": "maintenance",
      "solution": "劣化したホース全体の交換と接続部の固定具強化による恒久対策を実施。漏出防止用の受け皿を設置。",
      "expectedInquiry": "なんらかの液体が流出している",
      "similarity": 0.4914673
    },
    {
      "id": "trouble-2023-02-15T11:20:00.000Z-machining-robot",
      "title": "関節部の摩擦による金属摩耗音",
      "description": "第二工場自動加工セクションのアーム関節から周期的な摩擦音が発生。精密部品の加工精度に影響が出始めているため、作業速度を70%に制限して対応中。",
      "date": "2023-02-15T11:20:00.000Z",
      "line": "machining",
      "machine": "robot",
      "type": "hardware",
      "solution": "関節部の分解清掃とグリス再充填及びシール部品の交換",
      "expectedInquiry": "電動回転パーツに普段と違う響きが聞こえる",
      "similarity": 0.48170584
    },
    {
      "id": "trouble-2023-09-05T09:40:00.000Z-painting-motor",
      "title": "塗装ミキサーの回転子バランス不良による機械的動揺",
      "description": "塗装材料ミキサーから異常な機械的動揺が発生。分析の結果、回転子のバランスウェイトが一部脱落し、高速回転時に遠心力による不均衡状態が生じていることが判明。",
      "date": "2023-09-05T09:40:00.000Z",
      "line": "painting",
      "machine": "motor",
      "type": "hardware",
      "solution": "回転子の再バランシング作業を実施し、バランスウェイトの固定方法を改良。また、始動前点検手順に動的バランス確認項目を追加。",
      "expectedInquiry": "マシンが激しく揺れているように感じる",
      "similarity": 0.44172436
    },
    {
      "id": "trouble-2023-05-12T08:45:00.000Z-machining-robot",
      "title": "アーム関節部故障による加工中断",
      "description": "精密切削工程中に自動操作機の可動接合部が固着。作業ラインが自動防護機能により稼働中止。技術班による緊急診断の結果、軸受け摩耗を確認。代替ユニットへの交換作業で3時間の工程遅延が発生。",
      "date": "2023-05-12T08:45:00.000Z",
      "line": "machining",
      "machine": "robot",
      "type": "hardware",
      "solution": "接合部の完全交換と予防点検プログラムの強化",
      "expectedInquiry": "製造フローがストップしてしまった",
      "similarity": 0.4380265
    }
  ]
}

Agent - Chat

作成したエージェントごとにチャット画面があります。これはUIと繋げる手間が省けるので非常に便利です。
CleanShot 2025-03-22 at 06.18.23@2x

マルチモーダルには対応していませんが、ストリーミングで挙動を確認できます。
CleanShot 2025-03-22 at 06.20.03

Agent - 評価(Evals)

Evalsは、エージェントの品質を測定できる機能です。AI の出力は非決定論的であり、同じ入力でも変化する可能性があるためです。こちらもplaygroundで確認可能です。

https://mastra.ai/docs/evals/00-overview

evalsの設定をすることで、回答内容の評価も見ることができます。実装はこちらです。
https://github.com/shuntaka9576/nextjs-mastra-manufacturing/blob/49f4adb3e13e8e88d812422c051a8947fedea05e/src/mastra/agents/factoryTroubleResarchAgent.ts#L45-L49

evalsの結果は以下です。mastra playgroundのChatで行った内容は、Liveのタブにに表示されます。
CleanShot 2025-03-22 at 06.24.11@2x

UIをみていて、気づいた方がいると思いますが、CIタブもあります。vitestでテストを書いてその結果もこちらの画面で確認することが可能です。私は公式の手順では上手くいかず、DBを明示的に指定することで閲覧できるようになりました。実装を紹介します。

こちらでストレージ LibSQLStore を明示的に指定します。
https://github.com/shuntaka9576/nextjs-mastra-manufacturing/blob/49f4adb3e13e8e88d812422c051a8947fedea05e/src/mastra/index.ts#L8-L12

あとはvitest実行時に1回実行されるglobalSetupを実装
https://github.com/shuntaka9576/nextjs-mastra-manufacturing/blob/49f4adb3e13e8e88d812422c051a8947fedea05e/test/globalSetup.ts#L1-L5

あとはテスト毎に実行されるtestSetupを実装
https://github.com/shuntaka9576/nextjs-mastra-manufacturing/blob/49f4adb3e13e8e88d812422c051a8947fedea05e/test/testSetup.ts#L1-L6

テストを実装します。
https://github.com/shuntaka9576/nextjs-mastra-manufacturing/blob/49f4adb3e13e8e88d812422c051a8947fedea05e/src/mastra/agents/factoryTroubleResarchAgent.test.ts#L1-L17

テスト実行しました。指定したメトリクスで指定した閾値より低いと当然ですがエラーになります。人間が毎回チャットで確認するのは大変あので便利ですね!

$ npx vitest

 DEV  v3.0.9 /Users/shuntaka/repos/github.com/shuntaka9576/nextjs-mastra-manufacturing

 ❯ src/mastra/agents/factoryTroubleResarchAgent.test.ts (1 test | 1 failed) 17242ms
   × factoryTroubleResarchAgent > should return similar cases 17240ms
     → expected 0.8214285714285714 to be 1 // Object.is equality

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯

 FAIL  src/mastra/agents/factoryTroubleResarchAgent.test.ts > factoryTroubleResarchAgent > should return similar cases
AssertionError: expected 0.8214285714285714 to be 1 // Object.is equality

- Expected
+ Received

- 1
+ 0.8214285714285714

 ❯ src/mastra/agents/factoryTroubleResarchAgent.test.ts:15:26
     13|     );
     14|
     15|     expect(result.score).toBe(1);
       |                          ^
     16|   });
     17| });

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯

 Test Files  1 failed (1)
      Tests  1 failed (1)
   Start at  06:31:06
   Duration  18.94s (transform 63ms, setup 699ms, collect 7ms, tests 17.24s, environment 0ms, prepare 37ms)

 FAIL  Tests failed. Watching for file changes...
       press h to show help, press q to quit

この結果はPlaygroundで確認できます。上記の実行例は上から2番目です、Socreに0.82とあります。1が出なかったので泣きの1回をしましたがダメでした。
CleanShot 2025-03-22 at 06.34.59 2@2x

Observability

https://mastra.ai/docs/observability/tracing

Mastra は、アプリケーションのトレースと監視のための OpenTelemetry Protocol (OTLP) をサポートしています。基本的に上記のドキュメント通りで実装できます。

念の為該当実装を示します。
https://github.com/shuntaka9576/nextjs-mastra-manufacturing/blob/49f4adb3e13e8e88d812422c051a8947fedea05e/src/mastra/index.ts#L22-L27

本リポジトリで、dokcer-compseをするとlocalhost:3001にGrafanaが閲覧できるようになります。以下が一覧です。
CleanShot 2025-03-22 at 06.47.32@2x

例えばエージェントがツール呼び出しにどの程度時間がかかっていたかは以下のように確認することできます。
CleanShot 2025-03-22 at 06.50.46@2x

MastraのWorkflow実装

はじめに

さてAgent機能を先ほど試しましたが、画像を引数にfunction callingをすると安定しない問題がありました。もちろんURLベースにして関数側でイメージを取得すれば可能になりますが、Workflow機能を呼び出して、この問題を解消します。

Workflowは、LangChainでいうところのLangGraphです。今回は作るのはWorkflowを作るには簡単なものですが、お試しなのでご容赦ください。

実行した結果は以下の通りです。Workflowだとストリーミングではなくなるので画像です。。

CleanShot 2025-03-22 at 07.20.34@2x

Mastra実装

フローはシンプルで以下の通りです。

  1. 画像ないしテキスト受け取り類似事例検索
  2. 生成AIを使ってフォーマット調整

簡単に言えば決定的にできる処理を先にして、その後生成AIを使うという話です。

Mastraの実装は以下の通りです。
https://github.com/shuntaka9576/nextjs-mastra-manufacturing/blob/49f4adb3e13e8e88d812422c051a8947fedea05e/src/mastra/workflow/factoryTroubleResarchWorkflow.ts#L1-L111

Mastra側に登録するのもの忘れないでください。
https://github.com/shuntaka9576/nextjs-mastra-manufacturing/blob/49f4adb3e13e8e88d812422c051a8947fedea05e/src/mastra/index.ts#L16

実装すると、Mastraのplaygroundで確認できます。シンプルすぎ...もっと複雑なワークフローを定義したい人生でした。

CleanShot 2025-03-22 at 07.26.02

もちろんワークフローもテストできます。
CleanShot 2025-03-22 at 07.27.56@2x

Next.js実装

@ai-sdk/react のレスポンス形式に合わせるのが難しかったので、通常の機能でコードを書きました。フロントエンド力は無いので参考程度でお願いします。

https://github.com/shuntaka9576/nextjs-mastra-manufacturing/blob/49f4adb3e13e8e88d812422c051a8947fedea05e/src/app/chat/workflow/page.tsx#L1-L187

同様にAPIルートでMastraのWorkflowを呼び出すことで、実行が可能です。
https://github.com/shuntaka9576/nextjs-mastra-manufacturing/blob/49f4adb3e13e8e88d812422c051a8947fedea05e/src/app/api/chat/workflow/route.ts#L2-L64

最後に

MastraのAgent, Workflow, Playground機能について紹介しました。AgentやWorkflowが簡単に試せるPlaygroundがあるのは便利した。UIと毎回繋ぎこんだり、Workflowは全体像が逐次で確認できないと辛いところがあります。

LangGraphのときはmermaidで出力していましたが、これもワンテンポかかって不便でした。現在は別のソリューションがありそうですが。。

またo11yの機能も充実していそうでした。有名なところでLangsmith, LangfuseはもちろんNew Relicなども対応しています。
https://mastra.ai/docs/reference/observability/providers

Langfuse統合は試してみたいですね!Workflowのo11yは今回出来なかったので時間があるときにまた試してみようと思います。冒頭でも書きましたが、MCPなどまだまだ機能が沢山あるので、ネタは尽きないのと思います。

TypeScript系の生成AI FWはVercel ai-sdkも頑張っていて非常に面白いです!experimentalなところも多い分、今は色々貢献できるタイミングでもあります!AI Agentも型で固めていきたいですね!

ささやかですが、ドキュメント修正をしました。実装でも貢献したいところです!
https://github.com/mastra-ai/mastra/pull/3064

脚注
  1. Dockerイメージとして利用できるメモリ上で動作するPineconeエミュで、目的に合致しているため採用 ↩︎

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.