こんにちは、juttaです。
今回は、少し前から手をつけていたアプリの開発が順調に進み、
無事クローズドベータまで進んだので、そのアプリの開発記録を書いてみようと思います。
どんなアプリか?
アプリとしては、極めてシンプルな作りです。
一問一答型の占いアプリで、ユーザーの入力事項も原則として「占ってほしい質問」を入力→生成AIが答えるだけ。
とはいえ、私は現職としてはほぼマークアップ寄り。
業務ではWordPress周り(PHP/CSS/JSを必要なぶんだけ)を触ってきた程度で、
いわゆる「アプリ開発」はほぼ未経験です。
さすがにレガシー自認がつらくなってきたので、
モダンな開発に一回ちゃんと触れてみるか、というのが今回の動機でした。
では要件定義をしてみよう
……と言いたいところなんですが、要件定義をした記憶がありません。なんてこった。
アプリを開発したいんだよねー、という話をただひたすらClaudeとくっちゃべっていた記憶しかありません。
私「ねーねー、占いのアプリ作りたい。質問入れてポチ、AIが答える、みたいなやつ」
Claude「いいね。関連したライブラリがいるなら、このへんが候補かなー?言語はPythonかJS寄り、どっちがいい?」
私「覚えたいのと手持ちスキル的に、とりあえずjs寄りかな〜」
Claude「なるほど、js方面だね!じゃあ配信はどうしようか?フロントは?インフラは?答えるLLMのモデルどうしよっか?」
……本当にこんな感じでOpus4.5ちゃんとだらだら話してただけなのに、
気づいたら技術スタックと“次にやること”が決まっていました。怖い。
とりあえず、そんな感じで決まった仕様をなんかよくわからん名前のmdファイルにして、
雑につくったプロジェクトディレクトリの docs/ に放り込みました。
そしてその日のうちにClaudeちゃんが、かんたんなDocker関連のファイルを作ってくれて、
言われるままにAIのAPIキーを取得し、
完全に骨格だけとはいえ「質問入力したらなんかLLMが返事をしてくれるかんたんなぺーじ」ができてしまいました。こわい。
※まだこの時は本当に最低限のHTMLのみで、UIもデザインもへったくれもありません。
とはいえ「ここから始まるぞ!」というワクワクはありましたね。
見事なHello World!感でした。
そしていよいよコーディングエージェント召喚
この日までAIエージェントを使ったことがない私でしたが、ついにVibeコーディングデビューです。
まずは挙動のお作法マニュアルとして CLAUDE.md を書きました。
書いたことはだいたいこれだけ:
- 作業前に関連ファイル(特に
docs/)を読む - その日の終わりに
docs/log_yymmdd.mdを残す - commit は私がやる(AIは明示指示のときだけ)
- 作業ブランチを固定する
(後日Codexくんも参入したので、役割分担は AGENTS.md に追記しました)
そんな感じで指示をうって、数回のやりとりから「それじゃあよろしく」といったら、
コーヒー淹れてる間になんか占い演算コードができていた。
なにこれ怖っ!っていうか早っ!!!
そして立ち塞がるハルシネーション問題
一問一答の占いアプリ、出力がそれっぽいほど“嘘”が混ざると困ります。
そして生成AIは、混ざります。いい感じに。
というわけで、RAGを作りました✨
はじめての人間作業 〜手始めにRAGを作ります〜
まず、占いにあたっての必要な演算ルールや外部のライブラリは読み込んであります。
となれば、他のハルシネーション対策としては、やっぱり「適当言うことを許さない根拠情報の詰め込み」ですよね!
そんな感じで流れるように「よし、RAG作ろう」となりましたので、
ついに人間様の手作業の出番です!
とはいえ、ボリュームはそんなに多くはないです。
すでにAIがすべてやってくれる怠惰になれた人間にも余裕な程度でした。
中身としては、複数シートのCSVにカテゴリ×要素×キーワードを埋めていく方式で、最終的に 合計3,500ワード くらい。
所要時間は半日くらいでした。『これでRAG名乗っていいの?』ってくらい、あっさりですね。
このCSVを「振り分け辞書用のJSONにして」ってAIに投げたら、まずそれが出てきて、
その後かるーく雑談してたら、今度は17世紀の占星術文献(パブリックドメイン)のテキストもいい感じにRAG化してくれました。
ちなみにこの書籍、日本語訳の物理本も持ってるんですが、だいたい1,400ページくらいあります。
……簡単ですね、RAGつくるのって。AIすごーい!✨
そんなわけで、デザイン以外だいたいできあがりました
……いや、「デザイン以外」って何なんだよ、って話なんですが……現時点の仕様はこんな感じです。
- 入力:質問テキストのみ
- 時刻:JST基準の送信時刻を採用
- 位置:GPS取得(失敗時は手入力にフォールバック)、GPS情報が嫌な方向けに都道府県プルダウンも用意
- 占い内部エンジン:NASAの天体情報を根拠にした天文暦ライブラリをAPIで取得し、
JST時間+位置情報からより具体的なホロスコープ情報を計算。以下詳細挙動- 評価ロジック:入力(天文計算結果+位置+時刻)を features に正規化 → ルール群(Strategy)でスコアリング → 最終判断を reducer で集約(関数合成で差し替え可能)
- 欠損・例外系:外部API/計算の欠損を前提に、境界で null を吸収して fallback 値を注入(fail-open)。落とす例外と握り潰す欠損を分類し、warning を診断ログへ吐く
- 関係整合性:エンティティ間の双方向関係(Mutual Reception)は片方向参照を禁止し、A↔B の invariant を検証。成立フラグを状態として派生させ、スコアリング側のトグル条件に接続
- 回答生成:上記の features/スコア(=判定用の feature vector)をコンテキストとしてLLMに渡し、質問テキストに対する最終回答を生成(参照した根拠と天文情報も同梱)
- ハルシネ対策:カテゴリ辞書CSV → JSON化 → 文献テキストをRAG化して参照
- 保存:結果のテキストコピーとDPFエクスポートのみ。こちらでの保存はしない。
- 運用:CLAUDE.md / AGENTS.mdでエージェント運用、日次ログをdocsに出す。
ほぼ毎回Claude Code ↔︎ Codex はお互いの作業のコードレビューをし、問題点があったら翌日その指摘箇所を再検討し修正。その後メインのタスク開始。 - ローカルのDocker起動しながら挙動確認と修正指示。
なんか、内部構造でいきなり難しい話になってすみません。
実際つくった構造をAIに説明してもらったのをそのまま書いたらこうなってしまいました、えへへ。
ここまでカレンダーで5日くらい。手を動かした正味は3日くらいです。AIでのアプリ開発ってすごい!
というわけで、次回は「はじめてのAI開発 〜Figmaと和解できないエンジニアの悲劇〜」です。お楽しみに!