生成AIにLINE Botを作ってもらう GPT4o編 その2

# はじめに

[前回](https://qiita.com/bathtimefish/items/56113209a1ad3586dea3)の続きです。GPT4o先生にてきとーに書いてもらったDenoのコードを実行したらエラーになりました。

# コードを見直してみる

```main.ts
for await (const req of server) {
  if (req.method === "POST" && req.url === "/webhook") {
    const body = await req.json();
    await Promise.all(body.events.map(handleEvent))
      .then((result) => {
        req.respond({ status: 200, body: JSON.stringify(result) });
      })
      .catch((err) => {
        console.error(err);
        req.respond({ status: 500, body: "Internal Server Error" });
      });
  } else {
    req.respond({ status: 404, body: "Not Found" });
  }
}
```

エラーになってるのはこの部分。一見しておかしいです。`server`の中に`req`がある前提の時点で[http server](https://deno.land/std@0.224.0/http/server.ts)の仕様じゃない。ハルシネーションにしろ、ちょっと4oでこんなコードはおかしすぎね？と思いました。

で、このコードの前に、Denoのコードで生成してって注文し忘れてnode.jsで生成されたコードを見直して原因が判りました。

```app.ts
// src/app.ts
import express from 'express';
import { ClientConfig, Client, middleware, MiddlewareConfig, WebhookEvent } from '@line/bot-sdk';

const app = express();

// LINEのチャネルアクセストークンとチャネルシークレットを設定
const config: ClientConfig & MiddlewareConfig = {
  channelAccessToken: process.env.LINE_CHANNEL_ACCESS_TOKEN || '',
  channelSecret: process.env.LINE_CHANNEL_SECRET || '',
};

const client = new Client(config);

// ミドルウェアをセットアップ
app.use(middleware(config));

// Webhookエンドポイント
app.post('/webhook', (req, res) => {
  Promise.all(req.body.events.map(handleEvent))
    .then((result) => res.json(result))
    .catch((err) => {
      console.error(err);
      res.status(500).end();
    });
});

// イベントハンドラ
function handleEvent(event: WebhookEvent) {
  if (event.type !== 'message' || event.message.type !== 'text') {
    return Promise.resolve(null);
  }

  const replyText = `You said: ${event.message.text}`;
  return client.replyMessage(event.replyToken, {
    type: 'text',
    text: replyText,
  });
}

// サーバーを起動
const port = process.env.PORT || 3000;
app.listen(port, () => {
  console.log(`Server running on ${port}`);
});
```

この部分ですね。[express](https://github.com/expressjs/express)のお作法です。

```app.ts
// Webhookエンドポイント
app.post('/webhook', (req, res) => {
  Promise.all(req.body.events.map(handleEvent))
    .then((result) => res.json(result))
    .catch((err) => {
      console.error(err);
      res.status(500).end();
    });
});
```

なるほどこのexpressのコードをDenoで書き直してって言ったからexpressのお作法に引っ張られてしまった感じですね。これは4o先生のせいだけにするにはちょっと酷かなと思います。

# 直してみる

さて、これをどうプロンプトで修正しようかと考えて、以下のように指示してみました。

```prompt.txt
上記のコードを実行したらエラーになりました。コードを検査したところ、このコードはexpressとdeno http serverのお作法がごっちゃになっていておかしなコードになっているようです。

上記のコードを参酌すること無く、改めて次の条件で LINE Botサーバーのコードを書いてください。

# 条件
1. LINE Messaging API SDK for nodejs を利用する
2. Denoで動作するTypeScriptで記述する
3. その他LINE Botとして確実に作動するよう配慮したコードとする
4. コード以外に作動するために必要な設定等があれば解説文を書く
5. `https://deno.land/std/http/server.ts` の典型的なサンプルコードを参考にする

```

次段にChatGPT4oが出力した応答をレイアウトし直して掲載します。

## 応答

申し訳ありません。条件に合ったLINE Botサーバーのコードを改めて作成しました。以下のコードは、Denoで動作し、`https://deno.land/std/http/server.ts`の典型的なサンプルを基にして作成されています。

### LINE Botサーバーのコード

```main.ts
import { serve } from "https://deno.land/std@0.203.0/http/server.ts";
import { createClient } from "https://esm.sh/@line/bot-sdk@latest";

// LINEのチャネルアクセストークンとチャネルシークレットを設定
const config = {
  channelAccessToken: Deno.env.get("LINE_CHANNEL_ACCESS_TOKEN") || "",
  channelSecret: Deno.env.get("LINE_CHANNEL_SECRET") || "",
};

const client = createClient(config);

async function handleRequest(req: Request): Promise<Response> {
  if (req.method === "POST" && new URL(req.url).pathname === "/webhook") {
    try {
      const body = await req.json();
      await Promise.all(body.events.map(handleEvent));
      return new Response("OK", { status: 200 });
    } catch (err) {
      console.error(err);
      return new Response("Internal Server Error", { status: 500 });
    }
  } else {
    return new Response("Not Found", { status: 404 });
  }
}

// イベントハンドラ
async function handleEvent(event: any) {
  if (event.type !== "message" || event.message.type !== "text") {
    return Promise.resolve(null);
  }

  const replyText = `You said: ${event.message.text}`;
  return client.replyMessage(event.replyToken, {
    type: "text",
    text: replyText,
  });
}

const port = Number(Deno.env.get("PORT")) || 3000;
console.log(`Server running on http://localhost:${port}`);
await serve(handleRequest, { port });
```

### 必要な設定と実行手順
(以下略)

# 実行してみる

```shell
deno run -A main.ts
```

エラーになりました。

```shell
error: Uncaught SyntaxError: The requested module 'https://esm.sh/@line/bot-sdk@latest' does not provide an export named 'createClient'
import { createClient } from "https://esm.sh/@line/bot-sdk@latest";
         ^
    at <anonymous> (file:///home/ubuntu/llm-linebots/GPT4o-2/main.ts:2:10)
```

# おわりに

LINE Bot SDK for nodejs に`createClient`というクラスは存在しません。[esm.shにSDKは収録されているよう](https://esm.sh/@line/bot-sdk@9.3.1)なのでimportは成功していますが呼び出すクラスが間違っています。

よく見ると前回の記事からbot-sdkとexpressが混濁されているし、全体的に観て4oはLINE Bot SDKには詳しくないようです。この感じだとLINE Bot SDKについてだいぶ教えないと正しいコードにはならなさそうですね。つまり自分で書いたほう早いと。。

ここからどう進めたものか。次回までに考えたいと思います。