NVIDIA PersonaPlex を Google Colab で試す!リアルタイム全二重音声AI入門( 📒Google Colab ノートブック付)
📒 本記事のコードはすべてGoogle Colabで実行できます。記事末尾のリンクからお試しください!
⚠️ この記事を読む前に この記事は2026年1月時点の情報をもとにしています。PersonaPlexは最近公開されたばかりのモデルのため、今後APIや使用方法が変更される可能性があります。また、 A100 GPU(有料) が必要です。
NVIDIA公式の遅延がほぼゼロの音声AI「PersonaPlex」をGoogleColabでとりあえず動かしてみた!
— Maki@Sunwood AI Labs. (@hAru_mAki_ch) January 22, 2026
33GBのVRAMが必要な模様、、、結構重い、、、 https://t.co/2H39D3CreO pic.twitter.com/PVKiaM91TD
ざっくり言うと
PersonaPlex は、NVIDIAが開発した「聞きながら話す」ができるリアルタイム音声AIモデル
テキストで「役割」を、音声で「声質」を指定できるので、カスタマーサポートAIからカジュアルな会話相手まで自在に変身
Google Colab の オフラインモード を使えば、音声ファイルを入力して AI の応答音声を生成できる
そもそも、PersonaPlex ってなに?
従来の音声AIは「聞く」「考える」「話す」を 順番に 処理していました。人間が話し終わるのを待ってから返答を考え始めるので、どうしても会話が不自然になります。「あー」「うん」といった相槌もできませんし、話の途中で割り込むこともできません。
PersonaPlex は、 聞きながら同時に話す ことができる「全二重(Full Duplex)」モデルです。人間同士の会話と同じように、相手の話を聞きながら「うんうん」と相槌を打ったり、適切なタイミングで話し始めたりできます。
たとえ話で説明すると...
従来のAIは トランシーバー のような会話でした。一方が話し終わってボタンを離すまで、もう一方は何も言えません。
PersonaPlex は 電話 のような会話です。お互いが同時に話すことも、相槌を打つことも、話を遮ることもできます。
PersonaPlex のすごいところ
🛠️ セットアップ
Step 1: Google Drive のマウント
from google.colab import drive
drive.mount('/content/drive')
print("✅ Google Drive マウント完了")
Step 2: GPU の確認
⚠️ 重要: PersonaPlex は約30GB以上のVRAMが必要です。Colab の A100 GPU(有料プラン)を使用してください。
# GPU情報の確認
!nvidia-smi
import torch
if torch.cuda.is_available():
gpu_name = torch.cuda.get_device_name(0)
gpu_memory = torch.cuda.get_device_properties(0).total_memory / 1024**3
print(f"✅ GPU: {gpu_name}")
print(f"✅ VRAM: {gpu_memory:.1f} GB")
if gpu_memory < 30:
print("⚠️ 警告: VRAMが不足している可能性があります。A100 GPUを推奨します。")
else:
print("❌ GPUが利用できません。ランタイム → ランタイムのタイプを変更 → GPU を選択してください。")
Step 3: uv のセットアップ
# uvのインストール(高速パッケージマネージャー)
print("⚡ uvをインストール中...")
!pip install uv -q
# Colab環境の制約ファイル問題を回避
import os
os.makedirs("/backend-container/containers", exist_ok=True)
!touch /backend-container/containers/requirements.constraints
!touch /backend-container/containers/build.constraints
!uv --version
print("✅ uvセットアップ完了")
Step 4: 環境変数とユーティリティの設定
import os
import time
from datetime import datetime
from contextlib import contextmanager
import json
# 保存ディレクトリの設定
SAVE_DIR = '/content/drive/MyDrive/Prj/PersonaPlex/experiments'
os.makedirs(SAVE_DIR, exist_ok=True)
# 実験ログ
experiment_log = []
@contextmanager
def timer(task_name: str, log_to_file: bool = True):
"""処理時間を計測"""
start = time.time()
print(f"⏱️ {task_name} 開始...")
yield
elapsed = time.time() - start
print(f"✅ {task_name} 完了: {elapsed:.2f}秒")
if log_to_file:
experiment_log.append({
"timestamp": datetime.now().isoformat(),
"task": task_name,
"elapsed_seconds": round(elapsed, 2)
})
def log_experiment(experiment_name: str, result_info: dict = None):
"""実験結果をログに記録"""
entry = {"timestamp": datetime.now().isoformat(), "experiment": experiment_name}
if result_info:
entry.update(result_info)
experiment_log.append(entry)
print(f"📝 実験ログ記録: {experiment_name}")
def generate_timestamp():
return datetime.now().strftime("%Y%m%d_%H%M%S")
def save_experiment_log(project_name: str):
"""実験ログをJSONファイルとして保存"""
log_path = os.path.join(SAVE_DIR, f"{project_name}_log_{generate_timestamp()}.json")
with open(log_path, 'w', encoding='utf-8') as f:
json.dump(experiment_log, f, ensure_ascii=False, indent=2)
print(f"📊 実験ログ保存: {log_path}")
print("✅ 環境設定完了")
print(f"📁 保存先: {SAVE_DIR}")
Step 5: HuggingFace 認証の設定
⚠️ 重要: PersonaPlex のモデルを使用するには、HuggingFace でライセンスに同意する必要があります。
ライセンスに同意(NVIDIA Open Model License)
HuggingFace のアクセストークンを取得
from google.colab import userdata
# Colab のシークレットから HF_TOKEN を取得
# 事前に「シークレット」タブで HF_TOKEN を設定してください
try:
HF_TOKEN = userdata.get('HF_TOKEN')
os.environ['HF_TOKEN'] = HF_TOKEN
print("✅ HuggingFace トークン設定完了")
except Exception as e:
print("⚠️ HF_TOKEN が設定されていません。")
print("手順: サイドバー → 🔑 シークレット → HF_TOKEN を追加")
HF_TOKEN = input("または、ここにトークンを入力: ")
os.environ['HF_TOKEN'] = HF_TOKEN
Step 6: リポジトリのクローン
with timer("リポジトリのクローン"):
!git clone https://github.com/NVIDIA/personaplex.git
%cd personaplex
print("\n📁 ファイル構成:")
!ls -la
Step 7: 依存関係のインストール
with timer("依存関係のインストール"):
# moshi パッケージのインストール
!uv pip install ./moshi/. --system -q
# 追加の依存関係(必要に応じて)
!uv pip install soundfile librosa --system -q
print("✅ パッケージインストール完了")
📖 PersonaPlex の仕組みを覗いてみよう
アーキテクチャ概要
PersonaPlex は以下のコンポーネントで構成されています。
┌─────────────────────────────────────────────────────────┐
│ PersonaPlex │
├─────────────────────────────────────────────────────────┤
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Mimi 音声 │ │ Transformer │ │ Mimi 音声 │ │
│ │ エンコーダ │ → │ (Temporal + │ → │ デコーダ │ │
│ │ │ │ Depth) │ │ │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
├─────────────────────────────────────────────────────────┤
│ 入力: ユーザー音声 (24kHz) │
│ 出力: AI応答音声 (24kHz) + テキスト │
└─────────────────────────────────────────────────────────┘
つまり、音声を一度「トークン」という単位に変換し、言語モデルで処理してから、また音声に戻すという流れです。
ペルソナ制御の仕組み
PersonaPlex では 2種類のプロンプト でAIの振る舞いを制御します。
利用可能なボイス
🧪 実験1:アシスタントモードで音声応答を生成
実行内容 テスト用の音声ファイルを入力し、PersonaPlex に応答音声を生成させます。
テストファイルの確認
# assets/test ディレクトリの内容を確認
print("📁 テストファイル一覧:")
!ls -la assets/test/
# 入力音声ファイルの情報
print("\n🎤 入力音声ファイル情報:")
!file assets/test/input_assistant.wav
オフラインモードで実行
import subprocess
with timer("PersonaPlex オフライン推論(アシスタントモード)"):
# 出力ファイルパス
output_wav = os.path.join(SAVE_DIR, f"output_assistant_{generate_timestamp()}.wav")
output_json = os.path.join(SAVE_DIR, f"output_assistant_{generate_timestamp()}.json")
# コマンド実行
cmd = [
"python", "-m", "moshi.offline",
"--voice-prompt", "NATF2.pt",
"--input-wav", "assets/test/input_assistant.wav",
"--seed", "42424242",
"--output-wav", output_wav,
"--output-text", output_json
]
result = subprocess.run(cmd, capture_output=True, text=True, env=os.environ)
if result.returncode == 0:
print(f"✅ 出力音声: {output_wav}")
print(f"✅ 出力テキスト: {output_json}")
else:
print(f"❌ エラー発生:")
print(result.stderr)
log_experiment(
experiment_name="assistant_mode_inference",
result_info={
"voice_prompt": "NATF2.pt",
"input_file": "input_assistant.wav",
"output_wav": output_wav
}
)
結果の確認と再生
from IPython.display import Audio, display
import json
# 出力音声を再生
if os.path.exists(output_wav):
print("🔊 生成された応答音声:")
display(Audio(output_wav))
# 出力テキストを確認
if os.path.exists(output_json):
print("\n📝 生成されたテキスト:")
with open(output_json, 'r') as f:
text_output = json.load(f)
print(json.dumps(text_output, indent=2, ensure_ascii=False))
🧪 実験2:カスタマーサービスモードで試す
実行内容 テキストプロンプトでカスタマーサービス担当者の役割を指定し、より専門的な応答を生成します。
プロンプトの作成
# カスタマーサービス用のプロンプトを作成
service_prompt = """You work for TechSupport Pro which is a software support company and your name is Alex Chen.
Information: Verify customer name and product version.
Available support tiers: Basic (free), Premium ($29/month), Enterprise (custom pricing).
Common issues: password reset, license activation, software updates.
Support hours: 24/7 for Premium and Enterprise, 9 AM - 6 PM for Basic."""
# プロンプトを一時ファイルに保存
prompt_file = "/content/service_prompt.txt"
with open(prompt_file, 'w') as f:
f.write(service_prompt)
print("📝 カスタマーサービスプロンプト:")
print(service_prompt)
カスタマーサービスモードで実行
with timer("PersonaPlex オフライン推論(カスタマーサービスモード)"):
output_wav_service = os.path.join(SAVE_DIR, f"output_service_{generate_timestamp()}.wav")
output_json_service = os.path.join(SAVE_DIR, f"output_service_{generate_timestamp()}.json")
# プロンプトファイルを読み込み
with open(prompt_file, 'r') as f:
text_prompt = f.read()
cmd = [
"python", "-m", "moshi.offline",
"--voice-prompt", "NATM1.pt", # 男性の声を使用
"--text-prompt", text_prompt,
"--input-wav", "assets/test/input_service.wav",
"--seed", "42424242",
"--output-wav", output_wav_service,
"--output-text", output_json_service
]
result = subprocess.run(cmd, capture_output=True, text=True, env=os.environ)
if result.returncode == 0:
print(f"✅ 出力音声: {output_wav_service}")
else:
print(f"❌ エラー発生:")
print(result.stderr)
log_experiment(
experiment_name="service_mode_inference",
result_info={
"voice_prompt": "NATM1.pt",
"text_prompt": "customer_service",
"output_wav": output_wav_service
}
)
結果の確認
if os.path.exists(output_wav_service):
print("🔊 カスタマーサービスモードの応答音声:")
display(Audio(output_wav_service))
🧪 実験3:カジュアル会話モードを試す
実行内容 自由な会話を楽しむためのプロンプトを使用します。
# カジュアル会話用のプロンプト
casual_prompt = "You enjoy having a good conversation. Have a casual discussion about favorite movies and TV shows."
with timer("PersonaPlex オフライン推論(カジュアル会話モード)"):
output_wav_casual = os.path.join(SAVE_DIR, f"output_casual_{generate_timestamp()}.wav")
output_json_casual = os.path.join(SAVE_DIR, f"output_casual_{generate_timestamp()}.json")
cmd = [
"python", "-m", "moshi.offline",
"--voice-prompt", "NATF3.pt", # 別の女性の声
"--text-prompt", casual_prompt,
"--input-wav", "assets/test/input_assistant.wav", # テスト用入力を流用
"--seed", "12345678",
"--output-wav", output_wav_casual,
"--output-text", output_json_casual
]
result = subprocess.run(cmd, capture_output=True, text=True, env=os.environ)
if result.returncode == 0:
print(f"✅ 出力音声: {output_wav_casual}")
else:
print(f"❌ エラー発生:")
print(result.stderr)
log_experiment(
experiment_name="casual_mode_inference",
result_info={
"voice_prompt": "NATF3.pt",
"text_prompt": casual_prompt
}
)
if os.path.exists(output_wav_casual):
print("\n🔊 カジュアル会話モードの応答音声:")
display(Audio(output_wav_casual))
🎤 実験4:自分の音声で試す(オプション)
実行内容 自分で録音した音声ファイルをアップロードして、PersonaPlex と会話してみましょう。
音声ファイルのアップロード
from google.colab import files
print("📤 音声ファイルをアップロードしてください(.wav形式、24kHz推奨)")
uploaded = files.upload()
if uploaded:
uploaded_filename = list(uploaded.keys())[0]
print(f"✅ アップロード完了: {uploaded_filename}")
else:
uploaded_filename = None
print("⚠️ ファイルがアップロードされませんでした")
アップロードした音声で推論
if uploaded_filename:
with timer("PersonaPlex オフライン推論(カスタム入力)"):
output_wav_custom = os.path.join(SAVE_DIR, f"output_custom_{generate_timestamp()}.wav")
cmd = [
"python", "-m", "moshi.offline",
"--voice-prompt", "NATF2.pt",
"--input-wav", uploaded_filename,
"--seed", "99999999",
"--output-wav", output_wav_custom,
"--output-text", output_wav_custom.replace('.wav', '.json')
]
result = subprocess.run(cmd, capture_output=True, text=True, env=os.environ)
if result.returncode == 0:
print(f"✅ 出力音声: {output_wav_custom}")
print("\n🔊 生成された応答音声:")
display(Audio(output_wav_custom))
else:
print(f"❌ エラー発生:")
print(result.stderr)
log_experiment(
experiment_name="custom_input_inference",
result_info={"input_file": uploaded_filename}
)
何がわかったの?
PersonaPlex を使った実験から、以下のことがわかりました。
テキストプロンプト で役割や知識を指定すると、AIの応答内容が変化する
ボイスプロンプト で声質を選択できるので、用途に合わせた音声を生成できる
オフラインモード を使えば、サーバーを立てなくても音声応答を生成できる
💡 ポイント PersonaPlex は「全二重」が売りですが、オフラインモードでは入力音声と同じ長さの出力が生成されます。リアルタイムの対話体験を得るには、サーバーモードとWebUIを使う必要があります。
じゃあ、どうすればいいの?〜次のステップ〜
ローカル環境でサーバーモードを試す
Google Colab のオフラインモードでは、PersonaPlex の「リアルタイム対話」機能は体験できません。本格的に試すには、以下の環境が必要です。
GPU: NVIDIA GPU(VRAM 16GB以上推奨)
環境: ローカルPCまたはクラウドGPUインスタンス
ブラウザ: WebUIにアクセスするためのモダンブラウザ
# ローカル環境での実行例
SSL_DIR=$(mktemp -d)
python -m moshi.server --ssl "$SSL_DIR"
# ブラウザで https://localhost:8998 にアクセス
Docker を使う
より簡単に環境を構築したい場合は、Docker を使用できます。
# .env ファイルに HF_TOKEN を設定
echo "HF_TOKEN=your_token_here" > .env
# Docker Compose で起動
docker-compose up
まだわかっていないこと
日本語対応: 現時点では英語のみ対応。日本語音声の入出力は未確認
ファインチューニング: 独自の声やペルソナを追加する方法は公開されていない
量子化: メモリ削減のための量子化バージョンは未提供
まとめ
NVIDIA PersonaPlex は、「聞きながら話す」ができる次世代の音声AIモデルです。テキストプロンプトで役割を、ボイスプロンプトで声質を指定できるので、カスタマーサポートから雑談相手まで、さまざまな用途に活用できます。
Google Colab のオフラインモードでは、リアルタイム対話こそ体験できませんが、音声入力から応答音声を生成する基本的なワークフローを試すことができました。
📊 実験サマリーの表示と保存
def print_experiment_summary():
print("\n" + "=" * 60)
print("📊 実験サマリー")
print("=" * 60)
total_time = sum(e.get('elapsed_seconds', 0) for e in experiment_log)
print(f"\n📈 総実験数: {len(experiment_log)}")
print(f"⏱️ 総実行時間: {total_time:.2f}秒")
print("\n📝 実験一覧:")
for i, entry in enumerate(experiment_log, 1):
exp_name = entry.get('experiment', entry.get('task', 'N/A'))
elapsed = entry.get('elapsed_seconds', '-')
print(f" {i}. {exp_name}: {elapsed}秒")
print("=" * 60)
print_experiment_summary()
save_experiment_log("personaplex")
print("\n🎉 すべての実験が完了しました!")
もっと詳しく知りたい人へ
参考にした資料
PersonaPlex GitHub リポジトリ - NVIDIA, 2026
PersonaPlex HuggingFace モデルカード - NVIDIA, 2026
PersonaPlex プロジェクトページ - NVIDIA Research, 2026
PersonaPlex 論文プレプリント - ICASSP 2026 採択
関連技術
Moshi (Kyutai) - PersonaPlex のベースとなった全二重音声モデル
Helium LLM - PersonaPlex の言語モデルバックボーン
📒 Google Colab ノートブック
本記事のコードはすべてGoogle Colabで実行できます。
https://colab.research.google.com/drive/1oGtinc0RVFU7nbYUKQLWpWyKxo5JkSdP?usp=sharing
使い方
上のボタンをクリックしてノートブックを開く
ランタイム → ランタイムのタイプを変更 → A100 GPU を選択
HuggingFace でライセンスに同意し、トークンをシークレットに設定
記事の各コードブロックを順番に実行するだけ!
💡 ヒント A100 GPU を使用するには Colab Pro+ が必要です。T4 GPU では VRAM 不足でエラーになる可能性があります。
参考リンク
この記事は2026年1月23日時点の情報です。


コメント