はじめに
前回の記事から約1年が経過しました。
コールセンターやサポートセンターは、生成AIアバターに置き換えられる未来が近づいています。その時代に即座にシステム提供できる技術力を今から身につけておきたいと考え、本記事を執筆しました。
目的
HeyGenでインタラクティブアバターの実装は実現できましたが、より専門的な知識ベースが必要です。HeyGenのデフォルト知識ベースでは対応できない業務固有の情報に対応するため、自前のRAG(Retrieval-Augmented Generation)システムを統合します。
技術スタックの選定
採用したフレームワーク
今回、TypeScriptとNext.jsを新たに学習しました。
参考リポジトリ:
Next.jsの利点
Next.jsはReactベースのフレームワークで、以下の特徴があります:
- 直感的なフォルダ構成: ディレクトリ構造がそのままルーティングに対応
- 高い再利用性: コンポーネントベースの開発
- 優れたフロントエンド開発体験: 画面設計に特化した機能
以前習得したDjangoと比較すると、機械学習や豊富なPythonライブラリを必要としない場合、Next.jsの方が効率的です。
DjangoとNext.jsの使い分け
| 用途 | 推奨フレームワーク |
|---|---|
| 機械学習中心のシステム | Django |
| LangChainを多用するシステム | Django or Next.js + Python API |
| フロントエンド重視のWebアプリ | Next.js |
実装手順
1. リポジトリのセットアップ
HeyGen公式のGitHubリポジトリを使用します。
参考記事:
@denwayaさん、有益な記事をありがとうございます!
記事では「realtime-alpha-demo」ブランチが紹介されていますが、本記事では1年後にリリースされたmainブランチを採用しました。mainブランチでは、フロントエンドとバックエンドが統合され、Next.jsのみで完結する構成になっています。
2. プロジェクトのインストール
依存関係をインストールします:
npm install
実行後、プロジェクトルートにnode_modulesフォルダが生成されます。
3. 開発サーバーの起動
以下のコマンドでサーバーを起動:
npm run dev
ブラウザで http://localhost:3000 にアクセスすると、以下の画面が表示されます。
「Start Voice Chat」ボタンをクリックすると、インタラクティブアバターが起動し、双方向の音声対話が可能になります。
4. 現在の課題(2025年12月31日時点)
2025年12月10日頃までは正常に動作していましたが、現在は400エラーが発生しています。HeyGenの有償APIプランに加入しないと接続できない仕様に変更された可能性があります。
RAGシステムの統合
使用するベクトルデータベース
Pineconeを採用します。クラウドベースで管理が容易なため、プロトタイピングに最適です。
必要なライブラリのインストール
# Pinecone SDK
npm install @pinecone-database/pinecone
# HeyGen Streaming Avatar SDK
npm install @heygen/streaming-avatar
環境変数の設定
.envファイルに以下を記述:
HEYGEN_API_KEY=sk_V2_************************
NEXT_PUBLIC_BASE_API_URL=https://api.heygen.com
PINECONE_API_KEY=pcsk_***********************
PINECONE_INDEX_NAME=heygen-knowledge
Pineconeへの知識注入
インデックスの次元数設定
Pineconeのダッシュボードで次元数を1536に設定します。OpenAIのtext-embedding-3-smallモデルと一致させる必要があります。
知識ベースの作成スクリプト
以下のTypeScriptコードでPineconeにデータを投入します:
import { Pinecone } from '@pinecone-database/pinecone';
import OpenAI from 'openai';
import * as dotenv from 'dotenv';
dotenv.config({ path: '.env.local' });
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
const pinecone = new Pinecone({
apiKey: process.env.PINECONE_API_KEY || '',
});
// 知識ベースのデータ
const knowledgeBase = [
{
id: 'heygen-overview',
text: 'HeyGenはAIを使ったアバター動画生成プラットフォームです。リアルタイムで対話可能なストリーミングアバターSDKを提供しており、ユーザーはテキストや音声入力に応じてアバターが話す動画を生成できます。',
keywords: ['HeyGen', 'アバター', '動画生成', 'AI', 'ストリーミング'],
},
{
id: 'streaming-avatar',
text: 'Streaming Avatar SDKは、Next.jsなどのWebアプリケーションでインタラクティブなアバターを実装するためのツールです。音声認識(STT)、テキスト読み上げ(TTS)、OpenAIとの統合が可能です。',
keywords: ['Streaming Avatar', 'SDK', 'Next.js', 'STT', 'TTS', 'OpenAI'],
},
{
id: 'rag-implementation',
text: 'HeyGenのデモでRAGを実装するには、Knowledge Base機能を使うか、独自のRAGパイプラインを構築する方法があります。PineconeなどのベクトルDBとOpenAI Embeddingsを組み合わせると、高度な意味検索が可能になります。',
keywords: ['RAG', 'Knowledge Base', 'Pinecone', 'ベクトルDB', 'OpenAI Embeddings'],
},
{
id: 'openai-integration',
text: 'HeyGenのmainブランチには直接的なOpenAI統合は含まれていませんが、ドキュメントに従ってWhisper APIを使ったSTT統合が可能です。TTSはHeyGenの内蔵機能で対応でき、OpenAI TTSは通常不要です。',
keywords: ['OpenAI', 'Whisper', 'STT', 'TTS', 'main', 'ブランチ'],
},
];
interface KnowledgeMetadata extends Record<string, string | number | boolean | string[]> {
text: string;
}
async function seedPinecone() {
try {
console.log('🚀 Pinecone シード処理を開始...');
const indexName = process.env.PINECONE_INDEX_NAME;
if (!indexName) {
throw new Error('PINECONE_INDEX_NAME が設定されていません');
}
const index = pinecone.index<KnowledgeMetadata>(indexName);
for (const doc of knowledgeBase) {
console.log(`📄 処理中: ${doc.id}`);
// OpenAI Embeddings でベクトル化
const embeddingResponse = await openai.embeddings.create({
model: 'text-embedding-3-small',
input: doc.text,
});
const vector = embeddingResponse.data[0].embedding;
console.log(` ✅ ベクトル化完了 (次元: ${vector.length})`);
const metadata: KnowledgeMetadata = {
text: doc.text,
};
await index.upsert([
{
id: doc.id,
values: vector,
metadata,
},
]);
console.log(` ✅ ${doc.id} を登録完了`);
}
const stats = await index.describeIndexStats();
console.log('\n📊 Pinecone インデックス統計:');
console.log(` - 総レコード数: ${stats.totalRecordCount}`);
console.log(` - 次元数: ${stats.dimension}`);
console.log('\n🎉 すべてのドキュメントを Pinecone に登録しました!');
} catch (error) {
console.error('❌ エラーが発生しました:', error);
process.exit(1);
}
}
seedPinecone();
実行結果
スクリプト実行後、Pineconeダッシュボードで4レコードが登録されたことを確認できます。
アプリケーションコードの修正
components/InteractiveAvatar.tsx
デフォルト設定を日本語対応に変更し、操作性を向上させました:
const DEFAULT_CONFIG: StartAvatarRequest = {
quality: AvatarQuality.Low,
avatarName: "Thaddeus_ProfessionalLook_public",
language: "ja",
voice: {
voiceId: "1bd001e7e50f421d891986aad5158bc8",
},
};
その他の主要な変更点:
- エラーハンドリングの強化
- デバッグログの追加
- トークン取得処理の改善
app/api/get-access-token/route.ts
Pinecone統合とトークンキャッシング機能を追加:
import { NextRequest, NextResponse } from 'next/server';
import { Pinecone } from '@pinecone-database/pinecone';
const pinecone = new Pinecone({
apiKey: process.env.PINECONE_API_KEY || '',
});
interface KnowledgeMetadata {
text: string;
[key: string]: string | number | boolean | string[];
}
let cachedToken: string | null = null;
let tokenExpiry: number = 0;
export async function POST(req: NextRequest) {
try {
console.log('🔑 Access Token API called');
// キャッシュされたトークンの確認
const now = Date.now();
if (cachedToken && tokenExpiry > now) {
console.log('✅ Using cached token');
return NextResponse.json({ token: cachedToken }, { status: 200 });
}
const apiKey = process.env.HEYGEN_API_KEY;
if (!apiKey) {
return NextResponse.json(
{ error: 'HEYGEN_API_KEY is not configured' },
{ status: 500 }
);
}
// HeyGen API呼び出し
const res = await fetch('https://api.heygen.com/v1/streaming.create_token', {
method: 'POST',
headers: {
'X-Api-Key': apiKey,
'Content-Type': 'application/json',
},
});
if (!res.ok) {
const errorText = await res.text();
console.error('❌ HeyGen API error:', errorText);
return NextResponse.json(
{ error: 'Failed to create access token' },
{ status: 500 }
);
}
const data = await res.json();
const finalToken = data.data?.token || data.token;
if (!finalToken) {
return NextResponse.json(
{ error: 'Token not found in response' },
{ status: 500 }
);
}
// トークンをキャッシュ(5分間)
cachedToken = finalToken;
tokenExpiry = Date.now() + 5 * 60 * 1000;
// Pinecone接続確認
try {
const indexName = process.env.PINECONE_INDEX_NAME || 'heygen-knowledge';
const index = pinecone.index<KnowledgeMetadata>(indexName);
const stats = await index.describeIndexStats();
console.log('📊 Pinecone stats:', stats);
} catch (e) {
console.warn('⚠️ Pinecone query failed:', e);
}
return NextResponse.json({ token: finalToken }, { status: 200 });
} catch (error) {
console.error('❌ Error:', error);
return NextResponse.json(
{ error: 'Internal server error' },
{ status: 500 }
);
}
}
今後の拡張予定:
現在はPineconeの統計情報のみ取得していますが、今後はユーザークエリに基づいた検索ロジックを実装します。
実行時のエラー
実際に実行したところ、401 Unauthorizedエラーが発生しました。HeyGenサポートに確認した結果、API利用には別途有償プランが必要とのことです。
コスト試算:
- HeyGen API: $99/月
- Streaming Avatar API: $99/月
- 合計: 約$200/月(約3万円)
デバッグ環境の構築
VSCodeでのNext.jsデバッグ設定
効率的なバグ修正のため、ブレークポイントを使用したデバッグ環境を構築しました。
.vscode/launch.json を以下のように設定:
{
"version": "0.2.0",
"configurations": [
{
"name": "Next.js: フルスタックデバッグ",
"type": "node",
"request": "launch",
"cwd": "${workspaceFolder}",
"runtimeExecutable": "npm",
"runtimeArgs": ["run", "dev"],
"console": "integratedTerminal",
"serverReadyAction": {
"pattern": "- Local:.+(https?://[^\\s]+)",
"uriFormat": "%s",
"action": "debugWithChrome"
},
"skipFiles": ["<node_internals>/**", "**/node_modules/**"]
},
{
"name": "Next.js: サーバーサイドデバッグ",
"type": "node",
"request": "attach",
"port": 9229,
"skipFiles": ["<node_internals>/**"]
},
{
"name": "Next.js: クライアントサイドデバッグ",
"type": "chrome",
"request": "launch",
"url": "http://localhost:3000",
"webRoot": "${workspaceFolder}",
"sourceMapPathOverrides": {
"webpack://_N_E/*": "${webRoot}/*"
}
}
]
}
この設定により、VSCode上でブレークポイントを設定し、変数の状態を確認できるようになりました。
まとめ
実装の成果
- HeyGen Streaming AvatarにPineconeベースのRAGを統合する基盤を構築
- Next.js + TypeScriptでの開発環境とデバッグ環境を整備
- 知識ベースの拡張可能な設計を実現
コスト面の考察
有償APIを使用すれば、完全にカスタマイズ可能なインタラクティブアバターを実現できますが、月額約3万円のコストがネックです。知識ベースが不要であれば、HeyGenの標準機能だけでも十分に活用できます。
今後の展望
この実装をノーコードツール(Difyなど)だけで実現するのは困難です。少なくとも今後5年間は、プログラミングスキルを持つエンジニアの需要は継続すると考えられます。
関連リンク:
主な改善点
- 構成の整理: 論理的な流れに沿って章立てを再構成
- 技術的正確性: 用語の統一とコードの説明を追加
- 視覚的改善: 表やコードブロックで可読性を向上
- プロフェッショナルなトーン: 技術記事として適切な文体に修正
- 具体的な情報: コスト試算や今後の展望を明確化


