「Web開発 × AI」 もう難しくない！？シンプルに始めるAI開発入門

## はじめに
こんにちは、皆さん！最近、AIについての話題をよくシェアしていますが、正直なところ、AIの話を聞いているとまるで別の世界に迷い込んだような気分になることがありますよね。AI、人工知能、シンギュラリティ（特異点）、エージェント、MCPといった言葉はどれも深い意味を持っていて、つい深く掘り下げているとあっという間に一日が過ぎてしまいます。普段フロントエンドやバックエンドの開発に携わっている多くのエンジニアにとって、これらの概念は少し遠い存在に感じるかもしれません。でも、就職市場がますます厳しくなっているという話やその他の不安を耳にすると、「AIの基本くらいは学んでおかないと置いていかれるかも」と考える人も少なくないはずです。そこで、今日は皆さんに新しくリリースされた「Agentica」というライブラリを紹介したいと思います。

## Agenticaとは？
Agenticaは、TypeScriptのクラスやSwaggerをLLM（大規模言語モデル）のFunction Callingに変換するライブラリです。具体的には、マルチエージェントのオーケストレーションやエージェント型AIの開発をサポートします。ちょっと難しそうに聞こえるかもしれませんが、ポイントをシンプルにまとめると次の通りです：

- **TypeScriptがわかればAIが作れる** → フロントエンド開発者でもAI開発が可能に！
- **Swaggerが作れればAIが作れる** → バックエンド開発者でもAI開発が可能に！

「本当にこの2つだけでAIが作れるの？」と思うかもしれません。AIというと、機械学習や回帰分析といった複雑な用語が並び、全部覚えてマスターしないといけないようなイメージがありますよね。でも、ちょっと考えてみてください。ReactやjQueryが登場する前のフロントエンド開発はどうだったでしょう？SpringやNestJS、Djangoといったフレームワークがない時代の開発はどうだったでしょう？その頃の開発は、今では想像もつかないほど大変だったはずです。

**「AI開発が難しいのは、それを助けるライブラリやフレームワークがまだ十分に揃っていないから。」**

私の結論は、AIも同じだということです。AIのエコシステムはまだ発展途上で、意外にも理論的な進歩に比べて実践的な開発が遅れています。だからこそ、Agenticaのような新しいライブラリが次々と登場しているのです。個人的にAgenticaはとても魅力的だと思っていて、詳しく説明する前に、まずはその使い方を紹介したいと思います。

## AgenticaでTypeScriptクラスを使ったFunction Calling
「Function Calling」という言葉を難しく考える必要はありません。Function Callingとは、LLMが会話の中で関数を呼び出せる仕組みのことです。簡単に言うと、ただおしゃべりするだけのチャットボットではなく、必要に応じてアクションを実行できる——例えば、食事の注文や送金など——ユーザーのために適切なタイミングで適切な行動を取れるということです。

> Function Callingは、OpenAIモデルがあなたのコードや外部サービスと連携するための強力で柔軟な方法を提供します。このガイドでは、モデルをあなたのカスタムコードに接続してデータを取得したり、アクションを実行したりする方法を説明します。*

では、Function Callingの使い方を簡単なコード例で見てみましょう。

### 例: Gmailコードを使ったAIエージェントの作成

```typescript
import { Agentica } from "@agentica/core";
import typia from "typia";
import dotenv from "dotenv";
import { OpenAI } from "openai";

import { GmailService } from "@wrtnlabs/connector-gmail";

dotenv.config();

export const agent = new Agentica({
  model: "chatgpt",
  vendor: {
    api: new OpenAI({ apiKey: process.env.OPENAI_API_KEY! }), // OpenAIキーを挿入
    model: "gpt-4o-mini", // モデルを設定
  },
  controllers: [
    {
      name: "Gmail Connector", // LLMが関数を選ぶためのわかりやすい名前
      protocol: "class",
      application: typia.llm.application<GmailService, "chatgpt">(), // クラスを提供
      execute: new GmailService({ ... }), // クラスのインスタンスを渡す
    },
  ],
});

const main = async () => {
  console.log(await agent.conversate("何ができるの？")); // 会話が可能に！
};

main();
```

どうですか？思ったよりコードが短いですよね。

このコードを見ると、以下のことが行われています：

- **Model**: プロバイダーを決めます。ここでは`chatgpt`を使用。
- **Vendor**: LLMを提供するサービスを選びます。ここではOpenAIを使用。
- **Controller**: コントローラーを定義します。クラスを含めることで（コメントにある通り）、その関数に自由にアクセスできます。

### コントローラーの補足説明
```typescript
export const agent = new Agentica({
  model: "chatgpt",
  vendor: {
    api: new OpenAI({ apiKey: process.env.OPENAI_API_KEY! }), // OpenAIキーを挿入
    model: "gpt-4o-mini", // モデルを設定
  },
  controllers: [],
});
```

Agenticaでは、コントローラーはLLMが呼び出せる関数の集合を表します。クラスを提供すると、LLMはTypeScriptコンパイラが解釈したクラス情報を読み取り、その公開メンバー関数を理解します。さらに、実際の呼び出しはインスタンスが行うため、インスタンスも提供する必要があります。

```bash
npm install @wrtnlabs/connector-gmail
```

```typescript
export const agent = new Agentica({
  model: "chatgpt",
  vendor: {
    api: new OpenAI({ apiKey: process.env.OPENAI_API_KEY! }), // OpenAIキーを挿入
    model: "gpt-4o-mini", // モデルを設定
  },
  controllers: [
    {
      name: "Gmail Connector", // LLMが関数を選ぶためのわかりやすい名前
      protocol: "class",
      application: typia.llm.application<GmailService, "chatgpt">(), // クラスを提供
      execute: new GmailService({ ... }), // クラスのインスタンスを渡す
    },
  ],
});
```

このようにして`GmailService`を定義して使えます。`GmailService`には、次のような公開メソッドが定義されています：

- メール送信
- メールの下書き作成
- メール一覧や詳細の取得

これで、会話を通じてこれらの関数を呼び出せるようになります。

```typescript
(async function () {
    await agent.conversate("知人にメールを転送してもらえますか？");
    await agent.conversate("その人のメールアドレスはABC@gmail.comです。"); // 会話が続く！
})();
```

必要に応じて、`fs`モジュールをクラスとして再定義すれば、コンピュータのファイルを直接管理するエージェントも作れます。同様に、フロントエンド開発者はブラウザの関数をクラスとして定義して操作できます。既存のコントローラーもたくさん用意されているので、ぜひ見てみる価値があります。

## AgenticaでSwaggerを使ったFunction Calling
```bash
npm install @samchon/openapi
```

```typescript
import { Agentica } from "@agentica/core";
import { HttpLlm, OpenApi } from "@samchon/openapi";
import dotenv from "dotenv";
import OpenAI from "openai";

dotenv.config();

const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });

export const SwaggerAgent = async () =>
  new Agentica({
    model: "chatgpt",
    vendor: {
      api: openai,
      model: "gpt-4o-mini",
    },
    controllers: [
      {
        name: "PetStore", // コネクターの名前（わかりやすい名前なら何でもOK）
        protocol: "http", // HTTPベースのコネクターを示す
        application: HttpLlm.application({
          // Swagger JSONドキュメントをAgentica用のOpenAPIモデルに変換
          document: OpenApi.convert(
            await fetch("https://petstore.swagger.io/v2/swagger.json").then(
              (r) => r.json()
            )
          ),
          model: "chatgpt",
        }),
        connection: {
          // APIリクエストが送信される実際のAPIホスト
          host: "https://petstore.swagger.io/v2",
        },
      },
    ],
  });
```

次はSwaggerです。バックエンド開発者は、自分が作ったSwaggerドキュメントだけでエージェントを作成できます。Swaggerを`fetch`で読み込むか、ファイルとして読み込むかして、JSONとして取得したら、以下のように`application`フィールドに代入するだけです：

```typescript
{
    ...
    application: HttpLlm.application({
        document: OpenApi.convert(swagger),
    })
    ...
}
```

すると、LLMはSwaggerドキュメントだけでAPIを呼び出せるようになります——Function Callingのためのクラス定義は不要です！

## Agenticaの仕組み
### AIの最大の強みと弱み、そしてその解決策
AIの最大の強みは、常に異なる結果を返すことです。もし常に同じ結果しか返さなかったら、AIは今ほど人気にはならなかったでしょう。しかし、その最大の弱みもまた、常に異なる結果を返すことです。この予測不可能性は、従来のフロントエンドやバックエンド開発ではほとんど理解しがたいものです。テストコードで防ごうとしても、複数回呼び出して確率的に安定性を確認するしか方法がありません。このような開発では、80%の完成度に達するのに20%の努力で済むかもしれませんが、残りの20%を完璧にするには80%の努力が必要です。だからこそ、完全に磨き上げられたAI製品はまだ少ないのです。

Agenticaはこれらの問題に次のように対処します：

- TSC（TypeScriptコンパイラ）を使って、コンパイル時に安定したドキュメントを提供し、AIに関数を教える。
- 同様に、TypeScriptコンパイラを使ってAIのミスを驚くほど正確に修正する。

例えば、次のように指示できます：

「配列`d`の中の`c`の中の`b`の中の`a`の中の要素`e`の型が間違っています。修正してください。」

Agentica内部では、エラーが以下のように修正されます：

```typescript
// Agentica内部では、エラーが以下のように修正されます。
{
    success: false, // 操作が失敗し、
    errors: [{ // 修正方法のヒントがステップごとに提供される。
        path: "$input.a.b.c.d[0].e", 
        expected: "number", 
        value: "abc"
      }], 
    data: { // AIが受け取った値を表す。
      a: {
        b: {
          c: {
            d: [{
                e: "abc"
              }]
          }
        }
      }
    }
}
```

AIが関数を呼び出すたびに、次のように判断できます：

「`a.b.c.d[0].e`の型は`number`であるべきなのに、私は`abc`を渡してしまった！」

AIという遠い存在に思えた分野が、突然コンパイルを取り入れるなんて驚くべきことですよね！

## Agenticaが示すもの
これでAgenticaの簡単な紹介は終わりです。Agenticaに限らず、オープンソースプロジェクトはどんどん増えていて、フロントエンドやバックエンド開発者が何を準備すべきかを示しています。私の見解では、以下の4つのポイントが重要です：

1. オープンソースプロジェクトが増えるにつれ、AI開発は簡単になり、サービス開発のレベルに進化する。
2. AIに説明できないコードは最終的にAIに使えなくなるため、コードの可読性とドキュメントが不可欠。
3. 同様に、自分の仕事を説明するには、コードレベルだけでなくビジネスやドメイン知識にも精通する必要がある。
4. コンパイラと同じように、AI開発を学ぶにはコンピュータサイエンスの基礎がしっかりしていることがますます重要になる。

Agenticaは単なるTypeScript用のライブラリではありません。ウェブ開発者——特に全開発者の半数以上を占めるフロントエンド開発者——のためのツールと見るべきです。AI駆動のサービスへの関心が高まる中、フロントエンド開発者はこのようなライブラリに慣れ、AI時代に備えるべきだと考えます。それは間違いなくキャリアに有利に働くでしょう。

## 結論
この記事を読んで楽しめたなら、Agenticaを使ってプロジェクトを強化してみませんか？既存のフロントエンドにクラスを追加したり、既存のサーバーのSwaggerを生成してチャットボットを作ったりすれば、プロジェクトがさらに魅力的になります。最後まで読んでいただき、ありがとうございました！

---
この記事が参考になったら、ぜひ「いいね」や「ストック」をお願いします！コメントで皆さんのアイデアや活用事例もお待ちしています