[Codex実録] AIエージェントと作るWebサイト - チャット機能の組み込み - AIに同意される違和感
作成中の仮想サイト
<<ここに実際のサイトのURLを入れる予定...>>
はじめに
今回は仮想サイト(静的)にチャット機能を組み込んだときの話になります。
まず初めにサイトをクロールしてもらってRAGのデータを作ってもらいました。このデータも一瞬で作成してくれたのでびっくりです。
その後のチャット機能の組み込みも一瞬で終りました。
しかし、その後のデザイン修正でAIとのやりとりが増え手間がかかりました。
チャット部分は別プロジェクトのコード参照してもらったので速かったってかもしれませんが...「機能」以外の「見た目」って...(個人の好みなので)...やりとり難しかったです。
なんだろうAI使っていて、最近こんなに困った覚えないんだけど...細かな修正にCodexのデスクトップ版で作業したのが間違っていたかもしれません。
本当はKiroとかAIエディタで作業しようと思っていたのですが...月初めはKiroのクレジットのほうが大切なので(笑)
既存サイトへのチャット機能実装
今回は既存のWebサイトにチャット機能を組み込んでみました。Codexデスクトップ版を使用し、驚くほどスムーズに実装が完了しました。「自分で書く」のではなく「AIに組み込ませる」という感覚。この圧倒的なスピード感は毎回驚かされます。
今回は難しいと考えていたので「さらっと」組み込んだのを見て正直びっくりしました。
まだ、自分の中でAIを過小評価してました。
【失敗談】計画なきテストサイト構築とクレジットの霧散
以前、ベースの仮想サイトを「無計画に」作り始めてみたのですが...、これが大きな落とし穴でした。
とりあえずの思いつきで指示を重ねた結果、修正のループに陥り、クレジットが一瞬で溶けてしまったのです。
ツール系の開発では「動けば正解」という側面がありますが、Web制作では「とりあえず」が後の整合性を壊し、際限ない修正コストを生むことを痛感しました。
指示しなかったからと言って、一ファイルに3000行って...(苦笑)
Web制作でクレジットが「一瞬」でなくなる理由
Windowsアプリなどのツール開発では、AIへの曖昧な指示でもロジックが通れば完成に近づきます。しかしWeb制作、特にデザインが絡む作業では、場当たり的な指示がCSSやレイアウトの競合を引き起こします。
AIが「良かれと思って」広範囲のコードを書き換えるたびに、膨大なトークンが消費される——。Web制作におけるクレジット消費の激しさは、この「手戻りと書き換えの多さ」に起因しているのではないか...研究者ってわけじゃないので原因はわからないんですよね。
デザイン面での「主体性」の欠如
特にデザインや配色に関しては、AIからの提案が乏しいと感じました。
こちらが指定した色に対して 「その通りですね」「そうします」 と同意するだけで、「こうした方がより良くなる」「この色は避けるべき」といったフィードバックが返ってきません。
こちらがこだわりを持って調整している時ほど、このような姿勢に違和感を感じてしまいます。
機能実装とデザイン、AIの得意不得意
新機能の追加など、「できる・できない」がはっきりしているタスクについては、AIに任せても大きな齟齬は起きません。
しかし、サイト全体の雰囲気や使い勝手といった、数値化しにくい「感覚的」な部分をAIに委ねるのは、現時点ではまだ工夫が必要なようです。
ロジックは任せられるが、感性は人間がリードしなければならないという境界線が見えてきました。
事前の「定義」がクオリティを左右する
デザイン部分の作業の失敗から得た教訓は、全体の統一感を保つための「事前準備」の重要性です。
プライマリーカラーやセカンダリーカラーといったベースとなる色の指定、あるいは全体のトーンなどは、作業を依頼する前にしっかりと定義しておくべきだと痛感しました。
共通の物差しを先に渡しておくことで、AIの「言われた通り」という性質を逆手に取り、一貫性を保つことができそうですね。
おわりに:割り切りとツールの使い分け
ツールの特性によって、開発体験は大きく変わります。
クレジットの消費量やAIの提案力など、今回感じた違和感が「気のせい」なのかツールの仕様なのか、...正直判断がつきません。
ですが、それぞれのツールやLLMの「性格」を理解し、プロジェクトの性質に合わせて賢く使い分けていくことが、これからのエンジニアに求められるスキルなのかもしれません。
ってかっこよく締めくくりたいんですけど...ものすごく一過性のスキルになりそうだし、またツールやLLMの進化のほうが早いので...その場その場で対応するしかないですね...
ん...同じこといってますね(笑)
以下、セッションログになります。
🧑💻 ユーザー
このサイトの情報を全部クロールしてもらって、AIチャット用の元データっていうんですかね、RAGデータを作りたいんですけどそんなことできますか
🤖 AI
できます。というか、まず一式作っておきました。
追加・生成したもの:
- 生成スクリプト:
scripts/generate-rag-data.mjs
- RAG用JSONL:
docs/rag/knowledge.jsonl
- 元文書JSON:
docs/rag/documents.json
- 生成概要:
docs/rag/manifest.json
-
package.json
に rag スクリプトを追加
実行はPowerShellだとこちらです:
npm.cmd run rag
結果は 122 documents / 122 chunks です。FAQ、商品/体験メニュー、エピソード、安全情報、売却フロー、ページ内テキストなどをAIチャットで拾いやすいJSONLにしています。
検証もしました。
npm.cmd run ragは成功、
npm.cmd run buildも成功しています。ひとつ注意点として、元のソース文言が一部文字化け状態に見えるので、RAGデータもその正本に合わせて同じ文字列を保持しています。サイト表示側の正しい日本語から抽出したい場合は、次はブラウザで実レンダリングDOMをクロールする方式に切り替えるのがよさそうです。
(省略: ファイル変更通知・UIボタン表示)
🧑💻 ユーザー
えっとこれからはこのスクリプトを実行すれば、RAGデータが集まるようになったんですか
🤖 AI
はい、そうです。
これからはこのコマンドを実行すれば、RAG用データが再生成されます。
npm.cmd run rag
出力先はここです。
docs/rag/knowledge.jsonl
docs/rag/documents.json
docs/rag/manifest.json
サイトの文言やFAQ、カタログ情報などを
src/data/index.tsや
src/pages/*で変更したあとに
npm.cmd run ragを実行すると、最新内容でRAGデータが作り直されます。
ただし今の方式は「ローカルのソースコードから集める方式」です。公開中サイトを実際にブラウザで巡回して集める"本当のクロール"ではありません。今のこのサイト構成なら、ソースから取るほうが速くて安定しています。
🧑💻 ユーザー
[画像添付]
以下にReAct版のチャットボットのプロジェクトがあります。
このプロジェクトを参考にWebページの右下にフロートボタンを配置し、クリック時にチャットが起動する機能を追加できますか。
プロジェクト:AIChatWeb2
イメージ
🤖 AI
できます。まず AIChatWeb2 の実装を見て、今のサイト側のReact構成に馴染む形でフロートボタンとチャットパネルを移植します。RAGデータ連携まで含めるかは参照プロジェクト次第ですが、まずUIと起動動作を入れます。
(省略: コマンド実行ログ・参照プロジェクト探索の過程)
参照プロジェクトそのものは見つからないので、画像のUI要件をこちらのサイト用に実装します。チャット本体はまずフロントエンド完結の簡易応答にして、あとからAPI/RAG検索エンドポイントへ差し替えやすい境界で作ります。
🧑💻 ユーザー
"C:\Projects\chat\AIChatWeb2" ここです
🤖 AI
追加できました。右下に丸いフロートボタンを出して、クリックすると画像のようなチャットパネルが開きます。
実装した主なファイル:
FloatingChatWidget.tsx
App.tsx
vite-env.d.ts
挙動はこんな感じです。
- 全ページ右下にチャットボタン表示
- クリックで「AIアシスタント」パネル起動
- メッセージ送信、Enter送信、Shift+Enter改行対応
-
VITE_CHAT_API_URL
が設定されていれば外部チャットAPIへPOST - 未設定なら、このサイト内のFAQ・体験メニュー・安全情報などから簡易検索して回答
確認済みです。
npm.cmd run buildビルド成功しています。ローカル確認用サーバーも起動済みです。
次に本物のRAG/AI回答へつなぐなら、
VITE_CHAT_API_URLにチャットAPIのURLを入れるだけで接続できる形にしてあります。
(省略: ファイル変更通知・UIボタン表示)
🧑💻 ユーザー
C:\Projects\chat\AIChatWeb2 の機能を実装してRAGデータを今回作成したものに変更したいです。
🤖 AI
実装しました。AIChatWeb2 と同じように、チャットUIが
/api/chatにPOSTし、API側で今回作った
docs/rag/knowledge.jsonlを検索して回答する形に変更しています。
入れたもの:
-
api/chat.js
: Vercel本番用のチャットAPI -
server/rag-chat.js
: RAG検索と回答生成 -
vite.config.ts
: ローカル開発でも/api/chat
が動くmiddleware -
FloatingChatWidget.tsx
: API接続に変更 -
vercel.json
:/api/*
をSPA fallbackから除外
今の動きはこうです。
- チャット送信
-
/api/chat
が受信 -
docs/rag/knowledge.jsonl
を読み込み - 関連チャンクを検索
-
OPENAI_API_KEY
があればOpenAIで回答生成 - APIキー未設定なら、検索結果ベースで回答
ローカルの
http://127.0.0.1:5173/も新しい設定で立て直し済みです。API直接テストも成功しています。
検証:
npm.cmd run rag/
npm.cmd run buildどちらも成功しました。
本番でAI回答にする場合は、Vercel環境変数に
OPENAI_API_KEYを設定してください。任意で
OPENAI_MODELも指定できます。未設定なら検索結果ベースの簡易回答になります。
(省略: ファイル変更通知・UIボタン・ウェブプレビュー表示)
🧑💻 ユーザー
すごいいい感じでチャットが実現できていると思います。ローカルで動作確認しているのですが、AIを使って推論とかせずに回答を返してると思うんですけどこれってどういう風に実現してるんですか。スピードも速いしこれだけでもかなり実用的な気がするんですよね
🤖 AI
はい、今ローカルで動いているのは「AI推論なしの軽量RAG検索回答」です。なので速いです。
仕組みはざっくりこうです。
-
npm.cmd run rag
でサイト情報をdocs/rag/knowledge.jsonl
に保存 - チャットから質問を送る
-
/api/chat
がknowledge.jsonl
を読み込む - 質問文をキーワード化する
- 各RAGチャンクの title / content と照合してスコア付け
- 点数が高い上位数件を返す
-
OPENAI_API_KEY
がなければ、その検索結果を整形して回答として表示
実装の中心は
server/rag-chat.jsです。
今やっているのはベクトル検索ではなく、ローカルの文字列検索に近いです。ただし単純な完全一致だけではなく、質問をトークン化して、タイトル一致を強めに評価したり、「安全」「予約」「売却」みたいな語に関連キーワードを足したりしています。
だから例えば「安全性について教えて」と聞くと、内部では「安全」「リスク」「倫理」「副作用」「プロトコル」みたいな語も検索対象に足して、FAQやSafety系のチャンクを拾いやすくしています。
この方式の良いところは:
- 速い
- 安い
- APIキー不要
- 回答がサイト内データに限定される
- 幻覚しにくい
- 小規模サイトならかなり実用的
弱点は:
- 言い換えに弱い
- 複雑な質問の要約や比較は苦手
- 自然な文章生成は限定的
- 「質問の意図」を深く理解しているわけではない
なので今の構成はかなり良い土台です。実用的にするなら、まずこの高速検索回答を基本にして、「必要な時だけAIで整形・要約する」ハイブリッドが一番コスパいいと思います。
🧑💻 ユーザー
この方法って昔から行われたチャットボットのつくりですよね
🤖 AI
はい、かなり昔からあるチャットボット作りに近いです。
今の方式はざっくり言うと、昔ながらの FAQ検索型チャットボット や ルールベース型チャットボット の系譜です。
昔からある構成はこうです。
ユーザーの質問 ↓ キーワード抽出 ↓ FAQ・文書・辞書を検索 ↓ 一番近い回答候補を返す
今回の実装も基本はこれです。ただ、少し現代寄りにしていて、FAQだけではなくサイト全体から作った
knowledge.jsonlを検索対象にしています。なので「FAQボット」よりは「小さなサイト内検索チャット」に近いです。
昔ながらの方式の強みは今でもかなりあります。
- 速い
- 安い
- 壊れにくい
- 回答範囲を制御しやすい
- 事実確認がしやすい
- 小規模サイトでは十分便利
一方で、最近のLLM/RAGチャットはこの上に、
検索結果 ↓ AIが要約・比較・自然文回答
を足している感じです。
なので今のものは「古典的なチャットボット + RAG用データ形式」の中間くらいです。実はこの土台がしっかりしているほど、あとからAIを足したときも安定します。AIだけに丸投げするより、地に足がついてます。
🧑💻 ユーザー
[画像添付]
話はかわりますが、右下のチャットボタンの色がサイトのイメージに合っていない感じがします。
🤖 AI
確かに今の単色ブルーは少し汎用チャット感が強くて、このサイトのシアン/バイオレット/マゼンタの記憶SF感から浮いています。右下ボタンだけ、サイトのアクセントに合わせたグラデーションと薄い発光に寄せます。
ボタンをサイトのアクセントカラーに合わせました。
(省略: ビルド確認コマンド・ファイル変更通知・UIボタン表示)
🧑💻 ユーザー
[画像添付]
背景はこの色にしませんか。グラデーションはうるさい感じがします。
🤖 AI
変更しました。右下チャットボタンをグラデーションではなく、サイト内ボタンと同じシアン系の単色に寄せています。
変更箇所:
FloatingChatWidget.tsx
今の見た目は
bg-cyanlineベースで、ホバー時だけ白寄りに明るくなる控えめな動きです。こっちのほうがサイト全体のUIに馴染むと思います。
(省略: ファイル変更通知・UIボタン表示)
🧑💻 ユーザー
[画像添付]
🤖 AI
はい、この「査定基準を見る」と同じシアン色に合わせています。
現在のチャットボタン背景は
bg-cyanlineで、定義色はこれです。
cyanline: "#58f4ff"
つまり画像のボタンと同じ系統の単色です。もしブラウザ上でまだ青いままなら、ページを一度リロードすると反映されます。
🧑💻 ユーザー
[画像添付]
内部のアイコンは以下にしたいです
🤖 AI
変更しました。
外側のチャットボタンはシアンのまま、内部アイコンを画像のような 青い丸 + 白い吹き出し にしています。
変更箇所:
FloatingChatWidget.tsx
(省略: ファイル変更通知・UIボタン表示)
🧑💻 ユーザー
えっと2重にしたいわけじゃなくて背景をシアンにしてアイコンは白丸のアイコンにしたいです
🤖 AI
修正しました。
今は、
- 背景: シアン単色
- 中身: 白い吹き出しアイコン
- 青い内側丸: なし
になっています。意図を取り違えてました、すみません。
(省略: ファイル変更通知・UIボタン表示)
🧑💻 ユーザー
[画像添付]
このSVGつかえませんか
🤖 AI
使えます。貼ってくれたSVGの形に差し替えました。
変更後は、
- 背景: シアン
- アイコン: 白い丸型チャットSVG
- 中の3点: currentColor で濃色
になっています。
変更箇所:
FloatingChatWidget.tsx
(省略: ファイル変更通知・UIボタン表示)
🧑💻 ユーザー
シアンと白だと少し見にくいです。シアンの明度少しさげませんか
🤖 AI
少し暗めのシアンに落としました。
- 通常: #1bbfd0
- ホバー: #20d6e8
白アイコンとのコントラストが前より出るはずです。
(省略: ファイル変更通知・UIボタン表示)
🧑💻 ユーザー
ヘッダー部分のメニューのフォント色ぐらい下げてみてください
🤖 AI
下げました。
チャットボタンの背景をヘッダーメニュー寄りの落ち着いたシアンにしています。
- 通常: #149aa8
- ホバー: #18b6c6
白アイコンも前より読みやすくなると思います。
(省略: ファイル変更通知・UIボタン表示)
🧑💻 ユーザー
すみません。前の色のほうが良かったです。戻してくれませんか
🤖 AI
戻しました。
- 通常: #1bbfd0
- ホバー: #20d6e8
前の少し明るいシアンに戻っています。
(省略: ファイル変更通知・UIボタン表示)
🧑💻 ユーザー
アイコンをもう少し大きくしてみてくれませんか
🤖 AI
アイコンだけ少し大きくしました。
h-8 w-8から
h-9 w-9に変更しています。ボタン自体のサイズはそのままです。
(省略: ファイル変更通知・UIボタン表示)
🧑💻 ユーザー
いい感じです。
🤖 AI
よかったです。今の状態、サイトのトーンにちゃんと馴染んできましたね。
🧑💻 ユーザー
× 部分も白にしてSVGでいい感じにできませんが、線を太くしたいです
🤖 AI
× をSVGに差し替えて、白い太めの線にしました。
- SVG化
- 線色: 白
- 線幅: 2.8
- 端は丸めて少し柔らかくしています
変更箇所:
FloatingChatWidget.tsx
(省略: ファイル変更通知・UIボタン表示)
🧑💻 ユーザー
いい感じです
🤖 AI
よかったです。今のボタン、だいぶサイトの部品として自然になりました。
🧑💻 ユーザー
チャットの送信ボタンの背景もチャットボタンの背景と合わせたいです。
あと「送信」ではなくSendとかにしたいです。日本語だとSF感が落ちるような感じがしまして...
🤖 AI
変更しました。
- チャット内の送信ボタン背景を右下チャットボタンと同じ #1bbfd0 に統一
- ホバー色も #20d6e8
- ラベルを 送信 から Send に変更
たしかにこのほうがSF寄りのUIトーンに合います。
(省略: ファイル変更通知・UIボタン表示)
🧑💻 ユーザー
Sendのフォントカラーは白に限りなく近いグレーなんてどうですか
🤖 AI
良いと思います。Send の文字色を
text-slate-50にしました。
真っ白より少しだけ柔らかい、ほぼ白のグレーです。
(省略: ファイル変更通知・UIボタン表示)
🧑💻 ユーザー
Sendボタン押した後、 質問分ぐらいチャットを下にスクロールさせませんか、回答が見えないので、少しだけ使い勝手が悪い気がします
🤖 AI
対応しました。
メッセージ送信後、ユーザーの質問や回答待ち表示が追加されたタイミングで、チャット欄が自動で下までスクロールします。
変更箇所:
FloatingChatWidget.tsx
これで Send を押したあと、会話の続きが見えやすくなるはずです。
(省略: ファイル変更通知・UIボタン表示)
🧑💻 ユーザー
チャットボタンを追加して思ったんですけど、ヘッダー部分の各メニューのフォントカラーなんですけど若干暗すぎるような気がするんですよね。もう少し明度あげませんか、どう思いますか
🤖 AI
同感です。少し暗くて、チャットボタンを整えた後だとヘッダーだけ沈んで見える感じがありました。
ヘッダーメニューの通常色を、
text-cyanline/70から
text-cyanline/85に上げました。
ホバー時はこれまで通り
text-cyanlineです。明るくしすぎず、でも視認性は上がるくらいの調整です。
(省略: ファイル変更通知・UIボタン表示)
🧑💻 ユーザー
明るくした分マウスがホバーした時にもっと明るくしないと目立たないです
(省略: AIの使用量上限に達したため一時中断。日をまたいで再開)
🧑💻 ユーザー
明るくした分マウスがホバーした時にもっと明るくしないと目立たないです
🤖 AI
調整しました。
ヘッダーメニューは通常時を明るめのシアンのままにして、ホバー時は
hover:text-white
hover:drop-shadow-[0_0_8px_rgba(88,244,255,0.55)]
にしました。
これで通常時との違いが出て、マウスを乗せた時にちゃんと目立つはずです。
(省略: ファイル変更通知・UIボタン表示)
🧑💻 ユーザー
えっと今回はこれで一旦終わりにしますねえっと推論を使って回答生成する部分はまた今度修正しようと思います
🤖 AI
了解です。今回はここで一区切りにしましょう。
今の状態だと、チャットUI、右下ボタン、ローカルRAG検索回答、/api/chat の土台までは入っています。推論・LLM回答生成部分は次回、OPENAI_API_KEY 前提で回答品質を整えるか、AIChatWeb2寄りのReAct構成に寄せるかを選べます。
おつかれさまでした。かなり良いところまで来ています。
🧑💻 ユーザー
この時点で一旦コミットとプッシュをお願いします
🤖 AI
コミットとプッシュ完了しました。
- コミット:
b80aa09 Add floating RAG chat widget
- プッシュ先:
origin/main
ビルド確認も通っています。
npm.cmd run buildワークツリーもクリーンです。