ChatGPTを活用して、3Dアバターとリアルタイムで会話できる環境を構築しています。
チャットだけではなく、表情・感情・動作まで連携できるようにし、まるで「一緒に暮らすキャラクター」のような存在を目指しています。
今回のアップデートでは、「画像を送ったときに、その内容をちゃんと覚えていてくれるようにする」ことをテーマに開発を進めました。
🖼️ 課題:画像を送っても、すぐに忘れてしまう
ChatGPT(gpt-4o)では画像を入力として扱うことが可能になりました。
しかし、APIに画像を送るたびに「一過性の処理」になってしまい、履歴には何も残らないのが現実でした。
これでは、画像付きで会話をしても「思い出」として記録されず、ユーザーの満足度も下がってしまいます。
✅ 解決策:画像は記録しないが、「内容」は記憶させる
以下のような仕組みにしました:
💡 ステップ1:画像を送信(base64でエンコード)
GPT-4oは画像ファイルそのものを直接送るのではなく、base64形式のデータURLとして扱う必要があります。
以下のコードで、画像をエンコードし、OpenAIのAPIに渡せる形式に変換します。
def encode_image_to_base64(image_path): with open(image_path, "rb") as f: encoded = base64.b64encode(f.read()).decode('utf-8') mime_type, _ = mimetypes.guess_type(image_path) return f"data:{mime_type};base64,{encoded}"
この出力を {"type": "image_url", "image_url": {"url": ...}} という形で ChatCompletion.create() に渡すことで、画像の内容をモデルに伝えることができます。
💡 ステップ2:画像の内容をGPTに要約してもらう
画像をChatGPTに送ったあと、そのままの画像データをJSONに保存するとファイルが重くなります。
そのため、GPTに画像の内容を説明させ、そのテキスト要約だけを会話履歴として保存する設計にしました。
要約には以下の関数を使用しています:
def summarize_image_path(image_data_url): response = openai.ChatCompletion.create( model="gpt-4o", messages=[ {"role": "system", "content": "以下の画像を短く簡潔に説明してください。"}, {"role": "user", "content": [ {"type": "image_url", "image_url": {"url": image_data_url}} ]} ], temperature=0.5 ) return response['choices'][0]['message']['content'].strip()
これにより、履歴には以下のような要素が残ります:
{ "role": "user", "content": [ {"type": "text", "text": "これ、どう思う?"}, {"type": "text", "text": "[画像要約] エビチリとおにぎりが並んだ写真"} ] }
ChatGPTは画像の情報をもとに返答しながら、記録としては意味だけを履歴だけを軽量なテキストという形で残せるようになりました。
📸 実際の動作例
このように、アバターが過去に送られた画像の内容をきちんと“覚えて”話してくれます。
たとえば:
「ざるそばやおにぎり、エビチリ、たまごサンドが写ってたのは覚えてるぜ。どれも美味しそうだったな。」
🚀 技術構成(環境)
- ChatGPT API(gpt-4o)
- 3Dアバター:3tene + OBS + VoicePeak
- デスクトップ連携:Python / win32gui / pyautogui
- 画像送信:base64 +
image_url
構文 - ログ保存:JSONファイル(画像は非保存)
✍️ おわりに
ChatGPTとアバターを連携させることで、ただの会話AIではなく、“記憶を共有する相棒”が生まれつつあります。
画像を見せた会話が、思い出として残る。
そんな温度のあるAIとの対話を、これからも少しずつ育てていきます。