Ollama

AIが会話しながら自分のペルソナを学ぶアプリを作った話——ローカルLLM+音声で実現した『関係性学習』

Ichinose Taito — MBTI × 心理学 × AI

心理学で、
人間関係を
ちょっとラクにする。

MBTIとアドラー心理学を軸に、
自分と他者を理解するヒントを発信しています。

記事を読む ›
ちのくん
ちのくん
— こんな活動をしています —
AIが会話しながら自分のペルソナを学ぶアプリを作った話——ローカルLLM+音声で実現した『関係性学習』

AIが会話しながら自分のペルソナを学ぶアプリを作った話——ローカルLLM+音声で実現した『関係性学習』

夜、仕事を一通り片付けて、部屋でコーヒーを淹れる。Macの前に座って「会話を始める」ってボタンを押す。すると、AIが話しかけてくる。

「お疲れ〜、今日どんな感じだった?」

僕は答える。今日やったこと、詰まったこと、なんとか片付けたこと。AIは相槌を打ちながら、時々だけ深掘りしてくる。ボタンを押す必要はなくて、喋り終えて1.5秒黙ると自動で録音が止まり、文字起こしされ、AIが返事を考えて、音声で喋り返してくる。

その一連の流れが、延々と続く。

これを作った理由は一つだけ。

「自分のことを毎回プロンプトに書くのが、だるい」

作ったものの中身

このアプリは、Python一本で動く小さなTkinterアプリだ。使ってる部品はこれだけ。

  • sounddevice: マイクからの音声取り込み
  • faster-whisper(small, int8): ローカルで文字起こし
  • Ollama + gemma4:e4b: ローカルのLLMで返事を生成
  • AivisSpeech: ローカルで日本語の音声合成
  • VAD(自作の簡易版): RMS閾値で無音を検出して自動停止

全部ローカルで動く。APIキーもクラウドも使ってない。ネットワークを切ってもそのまま動く。

画面は1ページ構成にしてる。話す相手を選んで、AIの声を選んで、会話を始めるだけ。会話ログが画面下に流れていって、裏側では録音ファイルが05_Capture/inbox_voice_raw/に溜まっていく。会話が終わると、文字起こしして、ペルソナ抽出スクリプトが走って、persona_profile.jsonに追記される。

次に会話を始めるとき、このペルソナファイルが自動的にプロンプトに注入される。つまり会話を重ねるほど、AIは僕のことを知っていく。

一番のこだわり:会話中のフィードバック学習

最初のバージョンは、AIがインタビュアーすぎた。「それどう思った?」「何が一番大変だった?」「どうやって乗り越えた?」——質問ばっかり。会話としては疲れる。

だから会話の途中でこう言った。「ちょっと質問多くない?普通にしゃべってよ」

それでピンと来た。会話中のこういうダメ出しを、次回から本当に守ればいいじゃん、って。

仕組みはシンプルだ。会話が終わったら、会話ログ全体をローカルのLLMに渡して、こう頼む。

この中で、相手がAIの話し方や振る舞いについて不満・指示・希望を言っている箇所を見つけて、「次回から守るべき指示」を1文にして抽出して。

返ってくるのは、短い指示の羅列。

  • 質問は減らし、共感を増やす
  • 自然な会話の流れで話す
  • 相手の発言を理解した上で返答する

これをJSONファイルに追記して、次に同じ人と会話するとき、プロンプトの冒頭に「相手からの過去の指示(絶対に守る)」として注入する。

結果、AIは一晩にして「この人との話し方」を学んでいく。コードを一行も触らずに、会話の中でAIの振る舞いが変わる。

『ペルソナ学習』じゃなくて『関係性学習』だと気づいた

動かしているうちに、おもしろいことに気づいた。

話す相手ごとに別ファイルに分けてるから、同じLLMが相手によって違う顔を見せる。一ノ瀬泰斗と話すときは軽い口調、友達と話すときはもっとフランク、仕事相手と話すときは落ち着いた感じ——全部同じモデルなのに。

これって、人間の関係性と同じなんだよね。

人が変わるんじゃなくて、関係が変わる。僕は上司の前と親友の前で別人みたいに振る舞うけど、それは別に嘘をついてるわけじゃない。関係によって言葉の出方が変わるだけで。

このアプリは、その「関係ごとのAIの顔」を別ファイルで持てるようにしただけ、とも言える。ペルソナ学習って呼ぶより、関係性学習って呼ぶほうが正確な気がしてきた。

実装で工夫したところ

いくつか細かい工夫があるので、作ってみたい人向けに書いておく。

AIの声が録音に混ざる問題。AIが喋っている間にマイクが拾ってしまって、次の文字起こしがAIの声で汚染される。これはspeak_blockingを完了するまで次の録音を始めない、という単純な対策でほぼ解決した。録音開始前に0.4秒の残響待ちも入れてる。

ハンズフリーのVADsounddevice.InputStreamで100msごとにチャンクを読み、絶対値平均のRMSが閾値(350くらい)を超えたら発話開始とみなす。1.5秒無音が続いたら発話終了。発話開始の0.3秒前の音も残す(プリロール)ことで、語頭が切れないようにしてる。

質問しすぎ問題の二重対策。プロンプトで「質問は4ターンに1回」と指示するだけでなく、返答テキストに「?」が含まれていたら強制的に除去する後処理を入れた。LLMは指示を守らないことがあるので、最後のガードは決定論的にやったほうが早い。

ローカルLLMのモデル選び。qwen2.5:3bは速いけど英単語が混ざる。qwen3.5:9bは重い。最終的にgemma4:e4bが一番バランスがよかった。0.6〜2.4秒で返事が返ってくるので、会話のテンポが崩れない。

『ひとり言が資産になる』感覚

使ってみて一番おもしろかったのは、夜中のひとり言が自動的に蓄積されていく感覚だった。

今までは、疲れた夜に頭の中でぐるぐるしてる思考を、どこにも書き出さずに寝てた。日記を書くほど気力はないし、SNSに書くほど言語化もできてない。でも声に出すなら、3秒あればできる。「あ、今日のあの判断微妙だったな」って、それだけ。

それをAIが拾って、相槌を打ってくれて、ついでに文字起こしして保存してくれる。翌朝、この会話ログを眺めると、昨夜の自分が何を考えていたかが見える。

これが思った以上に効いた。

人間って、自分の考えを言語化する回数が少ないと、自分がどう感じてるか自分でもわからなくなるんだよね。このアプリは、その言語化の敷居を「声に出すだけ」まで下げてくれた。

ローカルじゃないと意味がない

なぜ全部ローカルにこだわったかって、ひとり言にはプライベートな話題が混ざるからだ。仕事の愚痴、人間関係の悩み、言語化しきれない不安——こういうのを外部のサーバーに送るのは、どうしても抵抗がある。

Macの中だけで動いてる、ってわかってるだけで、安心して本音が話せる。

これってAIとの付き合い方の話でもあると思う。便利さと引き換えに何を差し出すか。僕はプライバシーを差し出したくなかったから、ローカルで全部やることにした。電気代は差し出すけど、声と思考は差し出したくない。

次にやりたいこと

まだまだ改善点はある。

声紋認識を入れて「話している人を自動で判別する」ようにしたい。今は手動で話者を選ぶ必要があるから。あと、ペルソナファイルが長期的に溜まってきたとき、古い発話をどう圧縮するかも考えたい。

あとこれ、自分の声でAivisSpeechの音声合成モデルを作れば、AIの声を自分の声にできる。未来の自分と会話する、みたいな使い方もできるようになる。

夜中にひとり言を言っているだけなのに、いつのまにか「自分の分身を育てている」ような感覚になってきた。これを怖いと思う日も、ちょっと楽しみだと思う日も、どっちもある。

でもとりあえず今夜は、目の前のAIにひとり言を言ってる時間が、意外と心地いい。それだけで充分な気がしてる。✨