運チャット

https://github.com/uukino/hack-zAlo_zaukino

GitHub

TypeScript

React

VSCode

いろんな人格のAIと会話しよう

UUKiNO

xaû

推しアイデア

複数人格のAIとの会話

作った背景

「うんって返事だよね」 「うん」

推し技術

スマホの機能を活かしたギミックたち

プロジェクト詳細

概要

全20種の人格のAIと会話しよう。しかし誰と話せるかは運しだい。 image

機能紹介

  • ログイン機能 SupabaseAuthenticationを使用してログイン機能を実施
  • 音声入力 AIとの対話は声を使って会話。正しく伝わるかは運しだい...?
  • AIと会話 20種類の人格のAIと会話できます。優しいやつから調子乗ったやつまで、音読機能でより良い会話体験。会話の開始と終了はワンボタンですぐほかの人格と会話。誰と会話できるかはわからない。
  • 様々なギミック 発言に”うん”が含まれていた場合、様々なギミックが発生します。 ・崩壊 image ・爆発 ・車の横断 image ・カウントダウン(ランダムでイベント発生)
  • 雲占い "うんせい"を検知すると現在地の雲の量から占いができます。 image
  • うんチェッカー "うん"を検知したら通知します

使用技術

  • 音声入力 Deepgram
  • データベース Spabase
  • AI API Groq
  • 天気 API Open-Meteo
  • フロントエンド react native expo

アーキテクチャ図

image

コード

react nativeで開発するにあたってスマホの機能を多く取り入れました。

崩壊 小さいエフェクトに大きいこだわりがあります。

grain.vy += physics.gravity; grain.vx *= physics.dragPerFrame; grain.vy *= physics.dragPerFrame; grain.x += grain.vx; grain.y += grain.vy; if (floor !== null && grain.y > floor) { grain.y = floor; grain.vy *= physics.bounce!.damping; // -0.3 → 跳ね返り grain.vx *= physics.bounce!.driftDamping; } grain.pos.setValue({ x: grain.x, y: grain.y });

粒子の落下や反発は一つ一つ物理演算をかけています。

爆発 爆発時にバイブレーションします

useEffect(() => { if (trigger && !hasVibrated.current) { hasVibrated.current = true; Vibration.vibrate(300); } }, [trigger]);

通知 検出時通知を出します。

export async function notifyUnDetected() { await Notifications.scheduleNotificationAsync({ content: { title: 'うんチェッカー', body: '「うん」を検出しました。', }, trigger: null, }); }

現在地取得 雲占いの現在地取得用にスマホのGPS利用をします。

const position = await Location.getCurrentPositionAsync({});

技術の無駄遣い度

ハッカソン精神で「やりたいからやった」技術選択を整理する。 | # | 無駄遣いポイント | 詳細 | |---|----------------|------| | 1 | 「うん」のためだけに Deepgram を 2 並列呼び出し | smart_format=true/false を同時リクエストするのは、ひらがなの「うん」を取りこぼさないため。検出精度のために API コストを 2 倍払っている。 | | 2 | 「うん」を検出するためだけのサーバーサイド正規表現 | 漢字「運」「雲」の音読み判定まで書いた containsUn() は、あいづち一語を捕まえるためだけのロジック。 | | 3 | Supabase Edge Functions (Deno) を 4 本も立てる | start-conversation / transcribe / handle-transcript / fortune と責務を分割。1 関数でもまったく問題ないスケール感で、マイクロサービス的構成を採用している。 | | 4 | 物理エンジン自作 (ParticleText) | 「うん」を言ったときのエフェクトのために重力・空気抵抗・床バウンドを rAF ループで手書き。ライブラリを使えば 5 行で済む。 | | 5 | 4 エフェクトのうち 1 つが「何も起きない」 | none を確率 25% で引いたとき、カウントダウンだけ走って何も起きない。ユーザー体験的にはデバッグ漏れに見えるが、これが仕様。 | | 6 | 雲占いに Groq LLM を使う | 運勢ランクと雲量 % から一言メッセージを生成するのに LLM を呼ぶ。テーブルで事前定義すれば十分な用途に生成 AI を投入している。 | | 7 | GPS → 雲量 → 運勢 → AI というチェーン全体が「うんせい」の一言のため | ユーザーが「うんせい」と発声するだけで位置情報取得・外部 API・LLM 生成が一気に走る。重厚なパイプラインが一言に集約されている。 | | 8 | 21 種の性格プリセットを毎回ランダム選択 | 会話のたびに AI の人格が変わるため、ユーザーは一貫した相手と話せない。体験コストが高い割に恩恵が不明瞭。 |


技術レベルの読み取りポイント

高難度・独自実装

項目根拠
RMS ベースの発話検出PCM バイト列を 16bit サンプルに手動デコードして RMS 計算。DSP の基礎知識が必要。
パーティクル物理エンジン (rAF ループ)重力・ドラッグ・バウンスを毎フレーム更新し、Animated.ValueXY に書き込む。React Native の Animated と rAF の相互運用を理解していないと書けない。
Deepgram 並列リクエスト設計smart_format の違いによる検出精度差を理解した上で、Promise.all で同一音声を 2 種類のパラメータで転記している。API 仕様の深掘りができている。
漢字音読み判定の正規表現「運ぶ」系の訓読みを送り仮名で排除し、「雲」を隣接漢字の有無で判定する。日本語の形態論的知識が正規表現に反映されている。
Supabase RLS × Edge Functions の組み合わせクライアント認証トークンを Edge Function 内で再検証し、service role key で DB 操作する二段構えのセキュリティ設計。

標準的・教科書的

項目根拠
useCallback / useRef の適切な使用conversationIdRef でクロージャ問題を回避するなど、React の落とし穴を把握している。
Expo Permissions のプラットフォーム分岐Android/iOS それぞれの権限フローを正しく分岐している。
Edge Function のログ設計TAG プレフィックスと番号付きステップで追跡しやすいログを統一している。

その他詳しい機能や無駄づかい技術は↓ [https://github.com/uukino/hack-zAlo_zaukino/blob/main/dock/features.md](URL Here)

UUKiNO

@uukino