# 生成AIはどこまで自然な会話ができるか試してみた

> アニメ『PSYCHO-PASS』のキャラクター「キャンディ」を基に、生成AI技術でキャラクターAIを実現するための検証と実験の記録をまとめています。GraphRAGを活用し、ユーザーとの自然な会話や思い出の記憶を実現する方法について考察しています。

- 公開日: 2024-12-24
- 更新日: 2024-12-24
- 著者: やました
- タグ: 生成AI, AIエージェント, 新しい技術で検証
- URL: https://tech.anycloud.co.jp/articles/candy-ai-verification

---

Anycloudのやましたです！

突然ですが、[サイコパス](https://psycho-pass.com/)というアニメに出てくるこのキャラクター知ってますか？

<figure><img src="./image-001.webp" alt="" width="200" height="275"></figure>

参照先：[https://neoapo.com/characters/22055](https://neoapo.com/characters/22055)

名前はキャンディ。

主人公の自宅にいて、家事やスケジュール管理など色々やってくれるAI。ホログラムで姿を映し出して、同居人みたいに自然に会話してくれる。

最近は生成AI周りの技術が発展しています。なので、キャンディみたいなAIキャラクター、完全再現は無理でも、簡単なバージョンなら作れるんじゃと思い、少し検証してみることにします。

今回はまず自然な会話、キャラクターの特性を踏まえた発言や対話相手の情報も覚えて会話してくれるのが実現可能か検証してみます。

調べた限りでは適切そうなのはGraphRAGという技術だったので、GraphRAGを使って会話できないかやってみます。

せめて「あ、この子、私のこと覚えててくれるんだ」って感じる会話くらいはできるのではとは思ってます。

## まずはGraphRAGの簡単な説明

RAG（Retrieval-Augmented Generation）とは、AIが回答を生成する際に、外部の知識やデータを参照できるようにする技術です。AIが知らないような知識を質問内容に合わせて参照し、AIに与え、それらを参考にしながら回答できるようになります。

しかし従来のRAGでは、情報は単純なテキストの集まりとして保存されていました。そのため、文書同士の関連性や文脈を十分に理解するのが難しく、質問に対して適切な知識を参照できない課題がありました。

そこで登場したのがGraphRAGです。この技術では、情報をより立体的に整理します。

従来のデータベースのように「誰が」「いつ」「何をした」という単純な表形式ではなく、情報同士の「つながり」も一緒に保存。「この人はあの人の友達で」「この出来事はあの場所で起きて」といった関係性を表現してデータとして保存します。

これにより、AIはより文脈を理解しながら情報を引き出せるようになります。キャラクターAIの場合、「誰とどんな会話をして、どんな思い出を共有しているか」といった複雑な関係性も、より自然に扱えるようになるんです。

下記により具体的な仕組みも込みでわかりやすく説明されているので一読をおすすめします。

<div class="link-card-wrap"><a class="link-card" href="https://qiita.com/ksonoda/items/98a6607f31d0bbb237ef" target="_blank" rel="noopener noreferrer"><span class="link-card-body"><span class="link-card-title">GraphRAGをわかりやすく解説 - Qiita</span><span class="link-card-description">本記事は日本オラクルが運営する下記Meetupで発表予定の内容になります。発表までに今後、内容は予告なく変更される可能性があることをあらかじめご了承ください。 ※セミナー実施済の動画は下記です。 そもそもRAGとは 以前の記事：【ChatGPT】とベクトルデータベ...</span><span class="link-card-meta"><img class="link-card-favicon" src="./linkcard-01-favicon.ico" alt=""><span class="link-card-domain">qiita.com</span></span></span><img class="link-card-image" src="./linkcard-01-image.webp" alt=""></a></div>

## まずはGraphRAGを触ってみよう

色々調べた中でMicrosoftが出しているGraphRAGというpythonのパッケージを使うのが手軽にできそうだったのでそちらを使ってみます。

グラフデータ作成から実際にクエリを投げる状態まで一気に生成できるようです。

<div class="link-card-wrap"><a class="link-card" href="https://github.com/microsoft/graphrag" target="_blank" rel="noopener noreferrer"><span class="link-card-body"><span class="link-card-title">GitHub - microsoft/graphrag: A modular graph-based Retrieval-Augmented Generation (RAG) system</span><span class="link-card-description">A modular graph-based Retrieval-Augmented Generation (RAG) system - microsoft/graphrag</span><span class="link-card-meta"><img class="link-card-favicon" src="./linkcard-02-favicon.svg" alt=""><span class="link-card-domain">github.com</span></span></span><img class="link-card-image" src="./linkcard-02-image.webp" alt=""></a></div>

<div class="link-card-wrap"><a class="link-card" href="https://www.microsoft.com/en-us/research/blog/graphrag-auto-tuning-provides-rapid-adaptation-to-new-domains/" target="_blank" rel="noopener noreferrer"><span class="link-card-body"><span class="link-card-title">GraphRAG Auto-Tuning Provides Rapid Adaptation To New Domains</span><span class="link-card-description">GraphRAG uses LLM-generated knowledge graphs to substantially improve complex Q&amp;A over retrieval-augmented generation (RAG). Discover automatic tuning of GraphRAG for new datasets, making it more accurate and relevant.</span><span class="link-card-meta"><img class="link-card-favicon" src="./linkcard-03-favicon.ico" alt=""><span class="link-card-domain">www.microsoft.com</span></span></span><img class="link-card-image" src="./linkcard-03-image.webp" alt=""></a></div>

それでは[Getting Started](https://microsoft.github.io/graphrag/get_started/)に沿って順番にコマンド叩いていきます。

まずは `pip install graphrag` で`graphrag`をインストール。

次に `mkdir -p ./ragtest/input` でディレクトリを作成。

今回はGetting Startedにあるデータはデータ量が多そうだったので、[不思議の国のアリスのwiki](https://ja.wikipedia.org/wiki/%E4%B8%8D%E6%80%9D%E8%AD%B0%E3%81%AE%E5%9B%BD%E3%81%AE%E3%82%A2%E3%83%AA%E3%82%B9)を入れてみることにします。

上記のデータを `./ragtest/input` 配下に置きます。

そして`graphrag init --root ./ragtest` を実行してデータ作成完了！

以下のようになりました。

<figure><img src="./image-002.webp" alt="" width="2840" height="1644"></figure>

グラフのビジュアライズは下記を参考にやってみました。

<div class="link-card-wrap"><a class="link-card" href="https://github.com/microsoft/graphrag/discussions/884" target="_blank" rel="noopener noreferrer"><span class="link-card-body"><span class="link-card-title">GraphRAG Visualizer: The Easiest Way to Visualize GraphRAG Artifacts! · microsoft/graphrag · Discussion #884</span><span class="link-card-description">👉 GraphRAG Visualizer 👉 GraphRAG Visualizer Demo Overview GraphRAG Visualizer is an application designed to visualize Microsoft GraphRAG artifacts. By uploading parquet files generated from the Gra...</span><span class="link-card-meta"><img class="link-card-favicon" src="./linkcard-04-favicon.svg" alt=""><span class="link-card-domain">github.com</span></span></span><img class="link-card-image" src="./linkcard-04-image.webp" alt=""></a></div>

それでは早速質問していきます！

整えたデータベースに対して、GraphRAGの`query`コマンドを使います。例としては以下のように実行します。

```shell
graphrag query \\
--root ./ragtest \\
--method local \\
--query "物語の中でアリスが経験したことを教えて"
```

すると、下記のような回答が返ってきました。

```shell
### アリスが物語の中で経験したこと

『不思議の国のアリス』の主人公アリスは、物語の中で数々の奇妙で幻想的な体験をします。これらの出来事は、彼女がウサギの穴に落ちるところから始まり、さまざまなキャラクターとの出会いや不思議な出来事を通じて展開されます。

---

#### **冒険の始まりと身体の変化**
アリスの冒険は、白ウサギを追いかけてウサギの穴に飛び込むところから始まります。彼女はそこで、身体の大きさが変わる不思議な体験をします。例えば、不思議なケーキを食べて巨大化し、部屋に収まりきらなくなったり、涙の池を作るほど泣いてしまう場面があります。その後、白ウサギが落とした扇子の効果で再び小さくなり、池に飛び込むことになります [Data: Relationships (62, 66); Sources (9)]。

---

#### **奇妙なキャラクターとの出会い**
アリスは冒険の中で多くのユニークなキャラクターと出会います。例えば、キノコの上に座るイモムシとの会話では、彼のぞんざいな態度に戸惑いながらも、自分のアイデンティティについて考えさせられます。また、チェシャ猫からは謎めいた助言を受け、帽子屋の狂ったお茶会ではナンセンスな会話を体験します。さらに、グリフォンやモックタートルと踊ったり詩を暗唱したりする場面もあり、これらのキャラクターたちとの交流が物語のユーモアと深みを加えています [Data: Relationships (65, 105, 106, 96, 97)]。

---

#### **試練と成長**
物語の終盤では、アリスは裁判に巻き込まれます。ここでは、トランプの王や女王が登場し、アリスはその理不尽な裁判のやり方に反発します。最終的に、彼女は「あなたたちはただのトランプだ！」と叫び、トランプたちが舞い上がる中で目を覚まします。この経験を通じて、アリスは自分の意見を主張する力を学び、成長を遂げます [Data: Sources (13)]。

---

#### **テーマと象徴的な体験**
アリスの冒険は、単なる奇妙な出来事の連続ではなく、成長やアイデンティティの探求といった深いテーマを象徴しています。例えば、身体の大きさが変わる体験は、子供から大人への成長や自己認識の変化を表していると解釈されることがあります。また、物語全体を通じて繰り返されるナンセンスな要素は、現実世界の理不尽さや社会のルールへの批判を反映しているとも言われます [Data: Reports (60); Relationships (156)]。

---

アリスの物語は、彼女が経験する不思議な出来事やキャラクターとの出会いを通じて、読者に想像力と自己発見の旅を提供します。これらの体験は、物語の魅力を高めると同時に、普遍的なテーマを探求する機会を与えています。
```

テキストの要点をしっかりと拾いつつ、グラフ上で紐づけられたキャラクターの関係も参照していそうです。

## 架空キャラクター「もふりん」と会話してみる

次にもふりんという架空のキャラクターをつくって、それに関連するデータを作成し、もふりんとして回答してくれるものを作ってみます。「サイコパスのキャンディ」っぽくできるか実験。

まずは架空設定を用意

-   名前：もふりん
-   出身：もふもふの里
-   性格：ふわふわした雰囲気で話す
-   過去の会話ログ：UserBと初めて話した際の内容など

このような「もふりん」のプロフィールや適当な人たちとのやり取りのログをcsv形式でまとめ、再び `graphrag init --root ./ragtest` を実行してグラフデータを作りました。

<figure><img src="./image-003.webp" alt="" width="2832" height="1642"></figure>

そして、「私はuserBです。初めて話したときのこと覚えてる？」と質問してみます。

```shell
graphrag query \\
--root ./ragtest \\
--method local \\
--query "私はuserBです。初めて話したときのこと覚えてる？"

(...)

SUCCESS: Local Search Response:
### もふりんとの初対面の記憶

はい、もふりんはUserBさんとの初めての会話を覚えています！その時のやり取りは、もふりんにとっても印象的だったようです。

最初の会話では、UserBさんが「はじめまして、もふりん！ふわふわで見てるだけで癒やされる〜」と話しかけてくれました [Data: Sources (e0004)]. この言葉に対して、もふりんはとても嬉しく感じ、「もっとふわふわをアピールしよう」と心の中で決意したようです [Data: Sources (e0005)]. UserBさんの優しい言葉が、もふりんの「ふわふわパワー」をさらに引き出すきっかけになったのですね。

その後、UserBさんは「もふりんって、いつ生まれたの？ どこから来たの？」と質問しました [Data: Sources (e0006)]. これに対して、もふりんは「森の奥にある ‘もふもふの里’ 出身なんだもふ。いつもゆったり暮らしてるもふよ」と答え、自分の出身地である「もふもふの里」について教えてくれました [Data: Sources (e0007)]. このやり取りを通じて、もふりんの背景や性格が少しずつ明らかになりました。

### もふりんの感想とその後

もふりんはこの会話の後、「やっぱり ‘もふもふの里’ は落ち着くもふ…いまはちょっとホームシックかももふ…」と独り言をつぶやいており、故郷への思いを再確認していたようです [Data: Sources (e0008)]. UserBさんとの会話が、もふりんにとって自分のルーツを振り返るきっかけになったのかもしれません。

このように、UserBさんとの初めての会話は、もふりんにとっても特別な思い出として残っています。もふりんの「ふわふわパワー」を引き出してくれたことに感謝していることでしょう！
```

データとして初めて話したときのデータを入れていたのですが、それをしっかり参照して回答してくれました。

ただ、第三者的な話し方になっているので、もふりんが話している風に回答してもらえるようにプロンプトを変えて、再度同じ質問をしてみます。

```shell
graphrag query \\
--root ./ragtest \\
--method local \\
--query "私はuserBです。初めて話したときのこと覚えてる？"

(...)

SUCCESS: Local Search Response:
もふりん: ゆらゆら～♪ もちろん覚えてるもふよ！UserBさんが初めて話しかけてくれたとき、「ふわふわで見てるだけで癒やされる〜」って言ってくれたんだもふ。それがすごく嬉しくて、もっとふわふわ感をアピールしようって思ったんだもふよ～。

それから、UserBさんが「もふりんって、いつ生まれたの？どこから来たの？」って聞いてくれたとき、もふりんは「森の奥にある ‘もふもふの里’ 出身なんだもふ」って答えたんだもふ。あのとき、もふもふの里のことを思い出して、ちょっとホームシックになっちゃったけど、UserBさんとお話しできてすごく楽しかったもふ～♪

またお話しできて嬉しいもふ！他にも何か聞きたいことがあったら、何でも聞いてほしいもふよ～！
```

「ふわふわ」「もふもふ」といった語尾や口調を、キャラクターの設定に沿って出せるようになりました！

ただ余計な情報まで入れちゃってるので、まだ自然な会話とまではいかないですね…。ここはもう少しプロンプトの改善余地がありそうです。

## ここまでの所感と課題

ここまで検証してみて思ったことをまとめます。

1.  **リアルタイム性とデータ蓄積方法の工夫**
    -   現状は、ナレッジグラフを再生成してからクエリを投げるフローのため、リアルタイムでデータが更新・蓄積されるわけではない。
    -   しかし、実際に「キャンディ」的な存在を目指すなら、ユーザーとの対話履歴や新しい情報を常に取り込み、随時アップデートしていく仕組みが求められる。
    -   MicrosoftのGraphRAGで最近リリースされた [Incremental Ingest 機能](https://www.microsoft.com/en-us/research/blog/moving-to-graphrag-1-0-streamlining-ergonomics-for-developers-and-users/?msockid=00c7e3abb4ad6fc13ff8f6eeb5d76efb)を使えば、毎回ゼロからグラフを作り直さなくてもよくなる可能性が高い。
    -   さらに、通常のRAGやリレーショナルデータベース、あるいは直前の会話履歴をキャッシュして活用するなど、既存の手法を組み合わせる余地もある。
2.  **どのデータをどのようにグラフ化するか**
    -   キャラクター的なやり取りを重視する場合、単にテキストを収集するだけでなく、「いつ・誰が・どのような思い出を共有したか」のように、対話の背景情報を立体的に管理する必要がある。
    -   具体的には「このキャラクターがどう感じたか」「相手が何を言ったか」など、発言や感情を分割して格納し、必要に応じて参照できるようにしておくと、より人間的な応答が期待できる。
    -   「思い出」をどう定義し、何を忘れて何を保持するのかのルールを設計することで、キャラクターの性格や世界観に一貫性を持たせることも重要となりそう。
3.  **より立体的なキャラクターを作るためのアプローチ**
    -   単に問い合わせ→回答の流れではなく、キャラクターが「そのときどう考えたのか」と「実際に何を話したのか」を記録し、過去の自分自身の“思考過程”すら再参照できるようにすれば、一貫した行動・人格を再現しやすいのでは？
    -   こうした「見えない独り言（思考）」と「実際の発言」を分離して保存する技法は、ゲームAIなどでも使われるので、活用していけると良いかも。
    -   一連の会話の中で、「前回ユーザーの発言に対して自分はこう感じていた」といった情報を保持できれば、継続性のあるキャラクターとして行動できるようになる。
4.  **家事代行やマルチエージェントとの連携**
    -   「キャンディ」が本編で担っている家事やスケジュール管理などを完全再現するには、現状のLLMベースの対話モデルだけでは不十分。
    -   ただし、インターネット接続や既存のAPI連携機能を活用することで、「情報検索・提供」レベルのサポートなら十分に実現可能（既にChatGPTでは実装されていますよね）。
    -   まだ使ったことはないですが、オープンソースで提供されているマルチエージェントフレームワーク（例: OpenAIの**swarm**など）を活用すると、各タスクを専門化したエージェントを組み合わせてより複雑なタスクを実行できる可能性がありそうです。
        
        <div class="link-card-wrap"><a class="link-card" href="https://github.com/openai/swarm" target="_blank" rel="noopener noreferrer"><span class="link-card-body"><span class="link-card-title">GitHub - openai/swarm: Educational framework exploring ergonomic, lightweight multi-agent orchestration. Managed by OpenAI Solution team.</span><span class="link-card-description">Educational framework exploring ergonomic, lightweight multi-agent orchestration. Managed by OpenAI Solution team. - openai/swarm</span><span class="link-card-meta"><img class="link-card-favicon" src="./linkcard-05-favicon.svg" alt=""><span class="link-card-domain">github.com</span></span></span><img class="link-card-image" src="./linkcard-05-image.webp" alt=""></a></div>
        

## 最後のまとめ

今回の検証を通じて、単発のクエリであれば「キャンディ」のようにキャラクターがユーザーの情報を参照しつつ返答することはある程度実現可能だとわかりました。

しかし、リアルタイムで対話履歴を取り込み、キャラクターが自律的に思考・発言を更新し続けるとなると、さらなる仕組みづくりが必要になります。

1.  Incremental Ingest などで逐次グラフを更新していく方法
2.  既存のRAGやリレーショナルDBの利用・会話キャッシュの工夫
3.  エージェントフレームワークによる外部API・複数エージェントとの連携
4.  「思い出」や「考え」をグラフ上にどこまで格納・参照するかという設計

こうしたポイントを総合的に検討することで、より「人間くさい」キャラクターAIが作れるようになる気がします。

特に、個人情報や過去会話をどう扱うかはプライバシーの問題とも絡むため、セキュリティ面・データ管理の設計も合わせて考える必要もありますが（まずは自分のためのものを作ってみるのが良さそうです）。

色々出ている技術を組み合わせるとまだまだ実現できそうなことが多くありそうなので、ぜひこの記事を読んでいただいた方の中でも「こういう技術を組みわせるとXXができる」など実際にやってみたりアイデアあればぜひ共有していきたいです！

今後も新しい技術を触っていきながら色々検証してみます。
