全脳シミュレーション クエリレスポンス解析
[!NOTE] 最新の実装状況は 機能実装ステータス (Remaining Functionality) を参照してください。
実装ノート(アーティファクト): トレーニングスクリプトが出力する
artifact_manifest.jsonと推奨CLIフラグについてはdocs/implementation/ARTIFACT_MANIFESTS.mdを参照してください。
概要
全脳シミュレーションでクエリを実行した時のレスポンスの内容とデータフローを精査したドキュメント。
作成日: 2025年12月13日
このドキュメントの目的と使い方
- 目的: クエリレスポンスのデータフローと生成物を把握し、ボトルネックや障害点を特定する。
- 対象読者: API/Backend実装者、QA、運用担当。
- まず読む順: 概要 → データフロー → ログ/出力フォーマット → 障害・遅延分析。
- 関連リンク: 分散脳実行スクリプトは examples/run_zenoh_distributed_brain.py、PFC/Zenoh/Executive詳細は docs/implementation/PFC_ZENOH_EXECUTIVE.md。
1. レスポンスのデータフロー
1.1 クエリ送信フロー
ユーザー入力 (UI)
↓
フロントエンド (distributed_brain.py)
↓
APIエンドポイント (/api/distributed_brain/prompt)
↓
プロンプトファイル書き込み (/tmp/evospikenet_prompt_*.json)
↓
Zenoh Publish (evospikenet/api/prompt)
↓
各ノード (run_zenoh_distributed_brain.py)
1.2 レスポンス返却フロー
各ノード (推論処理)
↓
レスポンス生成
↓
Zenoh Publish (evospikenet/api/result)
↓
APIサーバー (Zenohサブスクライバー)
↓
結果ファイル書き込み (/tmp/evospikenet_query_result_*.json)
↓
フロントエンド (ポーリング)
↓
UI表示 (query-response-area)
2. レスポンスの構造
2.1 基本構造
{
"response": "生成されたテキストレスポンス",
"prompt_id": "UUID形式のプロンプトID",
"timestamp": 1234567890.123
}
2.2 フィールド詳細
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
response |
string | ✅ | 実際の生成テキストまたはシミュレーション結果 |
prompt_id |
string | ✅ | クエリを一意に識別するUUID |
timestamp |
float | ❌ | レスポンス生成時刻(UNIXタイムスタンプ) |
3. レスポンスの種類と内容
3.1 SpikingLM による生成 (lang-main ノード)
条件:
- ノードタイプ: lang-main
- モデル: SpikingEvoTextLM
- トークナイザー: 利用可能
処理:
# トークナイズ
inputs = tokenizer(prompt, return_tensors="pt")
input_ids = inputs["input_ids"]
# 推論実行
generated_ids = model.generate(input_ids, max_new_tokens=20)
# デコード
response_text = tokenizer.decode(generated_ids[0], skip_special_tokens=True)
レスポンス形式:
[HH:MM:SS] SpikingLM Generated: '生成されたテキスト'
例:
{
"response": "[14:30:45] SpikingLM Generated: 'The capital of Japan is Tokyo.'",
"prompt_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
3.2 シミュレートされたレスポンス (その他のノード)
条件: - SpikingLM 利用不可の場合 - 他のノードタイプ (visual, audio, motor など)
レスポンス形式:
[HH:MM:SS] Zenoh Node Processed: 'プロンプト' (Simulated Response)
例:
{
"response": "[14:30:47] Zenoh Node Processed: 'What is AI?' (Simulated Response)",
"prompt_id": "b2c3d4e5-f6a7-8901-bcde-f23456789012"
}
3.3 Visual ノードのレスポンス
処理:
# 視覚処理シミュレーション
time.sleep(1)
response_text = f"Visual processing completed for: '{prompt}'"
例:
{
"response": "Visual processing completed for: 'Analyze this image'",
"prompt_id": "c3d4e5f6-a7b8-9012-cdef-345678901234"
}
3.4 Audio ノードのレスポンス
処理:
# 音声処理シミュレーション
time.sleep(1)
response_text = f"Audio processing completed for: '{prompt}'"
例:
{
"response": "Audio processing completed for: 'Transcribe this audio'",
"prompt_id": "d4e5f6a7-b8c9-0123-def0-456789012345"
}
3.5 エラーレスポンス
条件: - 推論中にエラーが発生
レスポンス形式:
Error during inference: エラーメッセージ
例:
{
"response": "Error during inference: CUDA out of memory",
"prompt_id": "e5f6a7b8-c9d0-1234-ef01-567890123456"
}
4. APIエンドポイント
4.1 プロンプト送信
エンドポイント: POST /api/distributed_brain/prompt
リクエストボディ:
{
"prompt": "テキストプロンプト",
"priority": 1,
"session_id": "セッションID",
"image": "Base64エンコードされた画像データ (オプション)",
"audio": "Base64エンコードされた音声データ (オプション)"
}
レスポンス:
{
"message": "Prompt received and written to file.",
"file": "/tmp/evospikenet_prompt_1234567890_uuid.json",
"prompt_id": "uuid"
}
4.2 結果取得
エンドポイント: GET /api/distributed_brain/result
クエリパラメータ:
- prompt_id (オプション): 特定のプロンプトの結果を取得
レスポンス (結果あり):
{
"response": "生成されたテキスト",
"timestamp": 1234567890.123,
"prompt_id": "uuid"
}
レスポンス (結果なし):
{
"response": null,
"timestamp": null,
"prompt_id": "uuid"
}
5. ファイルシステム操作
5.1 プロンプトファイル
場所: /tmp/evospikenet_prompt_{timestamp}_{prompt_id}.json
内容:
{
"prompt": "テキストプロンプト",
"priority": 1,
"session_id": "session_id",
"timestamp": 1234567890.123,
"prompt_id": "uuid",
"image_path": "/tmp/{prompt_id}_image.png",
"audio_path": "/tmp/{prompt_id}_audio.wav"
}
TTL (Time To Live): - デフォルト: 3600秒 (1時間) - 自動クリーンアップ: バックグラウンドスレッドで実行
5.2 結果ファイル
場所: /tmp/evospikenet_query_result_{prompt_id}.json
内容:
{
"response": "生成されたテキスト",
"prompt_id": "uuid",
"timestamp": 1234567890.123
}
特徴: - 読み込み後に自動削除 - TTL: 3600秒
5.3 メディアファイル
画像:
- 場所: /tmp/{prompt_id}_image.png
- 形式: Base64デコード後のバイナリ
音声:
- 場所: /tmp/{prompt_id}_audio.wav
- 形式: Base64デコード後のバイナリ
6. Zenoh通信
6.1 プロンプト配信
トピック: evospikenet/api/prompt
ペイロード:
{
"prompt": "テキストプロンプト",
"priority": 1,
"session_id": "session_id",
"timestamp": 1234567890.123,
"prompt_id": "uuid",
"image_path": "/tmp/{prompt_id}_image.png",
"audio_path": "/tmp/{prompt_id}_audio.wav"
}
6.2 結果配信
トピック: evospikenet/api/result
ペイロード:
{
"response": "生成されたテキスト",
"prompt_id": "uuid"
}
6.3 タスク完了通知
トピック: task/completion
ペイロード:
{
"node_id": "pfc-0",
"prompt_id": "uuid"
}
7. フロントエンドでのレスポンス処理
7.1 クエリ送信 (execute_query コールバック)
場所: distributed_brain.py
処理フロー:
# ペイロード作成
payload = {
"prompt": query,
"session_id": sim_state.get('session_id'),
"priority": int(priority)
}
# メディアファイル追加
if image_contents:
payload['image'] = content_string
if audio_contents:
payload['audio'] = content_string
# API送信
response = requests.post(f"{api_base_url}/api/distributed_brain/prompt", json=payload)
response_data = response.json()
prompt_id = response_data.get("prompt_id")
# プロンプトIDを保存
return "", prompt_id # 入力をクリアし、IDを保存
7.2 レスポンス表示 (update_visualizations コールバック)
場所: distributed_brain.py
ポーリングロジック:
# 現在のプロンプトIDがある場合
if current_prompt_id:
# 結果取得を試行
result_response = requests.get(
f"{api_base_url}/api/distributed_brain/result",
params={"prompt_id": current_prompt_id}
)
if result_response.status_code == 200:
result_data = result_response.json()
response_text = result_data.get('response')
if response_text: # 有効なレスポンスがある場合
query_response_out = response_text
new_prompt_id = None # プロンプトIDをクリア
表示コンポーネント:
dcc.Textarea(
id='query-response-area',
style={'width': '100%', 'height': 150},
readOnly=True,
placeholder="The simulation's response will appear here..."
)
8. SDK での使用例
8.1 基本的な使用
場所: run_simulation_query.py
```python
from evospikenet.sdk import EvoSpikeNetAPIClient
# Example: use EvoSpikeNetAPIClient as implemented in evospikenet.sdk
クライアント初期化
client = EvoSpikeNetAPIClient()
プロンプト送信
prompt_text = "What is the capital of Japan?" submission_response = client.submit_prompt(prompt=prompt_text)
結果をポーリング
result = client.poll_for_result(timeout=120, interval=5)
結果表示
if result and result.get("response"): print(f"Response: {result['response']}") print(f"Timestamp: {result['timestamp']}")
### 8.2 マルチモーダル使用
**場所:** `run_multimodal_simulation_query.py`
```python
# マルチモーダルプロンプト送信
submission_response = client.submit_prompt(
prompt="Describe this image and audio",
image_path=DUMMY_IMAGE_PATH,
audio_path=DUMMY_AUDIO_PATH,
priority=1
)
# 結果をポーリング
result = client.poll_for_result(timeout=120, interval=5)
9. レスポンスのタイムライン
典型的な実行シーケンス
T+0秒: ユーザーがクエリを入力し "Execute Query" をクリック
T+0.1秒: フロントエンドがAPIにPOSTリクエスト送信
T+0.2秒: APIがプロンプトファイルを作成し、Zenohにパブリッシュ
T+0.3秒: 各ノードがZenohからプロンプトを受信
T+0.4秒: Lang-mainノードが推論スレッドを起動
T+2秒: 推論処理完了
T+2.1秒: Lang-mainノードが結果をZenohにパブリッシュ
T+2.2秒: APIサーバーが結果を受信し、ファイルに書き込み
T+2-7秒: フロントエンドがポーリング (5秒間隔)
T+7秒: フロントエンドが結果を取得し、UIに表示
パフォーマンス要因
| 要因 | 影響時間 | 備考 |
|---|---|---|
| ネットワーク遅延 | 0.1-0.5秒 | APIリクエスト往復 |
| Zenoh通信 | 0.01-0.1秒 | 非常に高速 |
| モデル推論 | 1-10秒 | モデルサイズとGPU性能に依存 |
| ポーリング間隔 | 0-5秒 | デフォルト5秒間隔 |
10. デバッグとトラブルシューティング
10.1 レスポンスが返ってこない
確認ポイント:
-
シミュレーションが実行中か確認
status = client.get_simulation_status() print(json.dumps(status, indent=2)) -
プロンプトファイルの存在確認
ls -la /tmp/evospikenet_prompt_*.json -
結果ファイルの確認
ls -la /tmp/evospikenet_query_result_*.json -
Zenoh接続の確認
- APIログで "✅ Zenoh session established in API" を確認
-
ノードログで Zenoh購読メッセージを確認
-
ノードログの確認
# Docker環境の場合 docker-compose exec frontend cat /tmp/sim_rank_4.log # Lang-main
10.2 レスポンス内容の検証
期待される内容: - ✅ タイムスタンプを含む - ✅ プロンプトIDが一致 - ✅ レスポンステキストが null でない
問題のある例:
{
"response": null,
"timestamp": null,
"prompt_id": "uuid"
}
原因: - ノードが推論を完了していない - Zenoh通信エラー - モデルロードエラー
10.3 一般的なエラーパターン
エラー 1: "CUDA out of memory"
レスポンス:
{
"response": "Error during inference: CUDA out of memory"
}
対処法: - バッチサイズを減らす - モデルのパラメータサイズを縮小 - GPUメモリを増やす
エラー 2: "Could not write result file"
ログ:
WARNING: Could not write result file (expected in remote mode): [Errno 2] No such file or directory
原因: - リモートノードで /tmp ディレクトリへのアクセス権限がない
対処法: - Zenoh通信のみに依存(ファイルは不要) - 警告は無視可能(リモートモードでは正常)
エラー 3: タイムアウト
症状:
Polling timed out. No result received.
対処法:
- timeout値を増やす: poll_for_result(timeout=300)
- モデルの推論時間を確認
- ノードが正常に動作しているか確認
11. レスポンスの拡張性
11.1 現在サポートされている情報
- ✅ テキストレスポンス
- ✅ プロンプトID
- ✅ タイムスタンプ
- ✅ ノードID(タスク完了通知内)
11.2 将来の拡張候補
詳細なメタデータ
{
"response": "生成されたテキスト",
"prompt_id": "uuid",
"timestamp": 1234567890.123,
"metadata": {
"node_id": "lang-main-0",
"model_type": "SpikingEvoTextLM",
"inference_time_ms": 1234,
"tokens_generated": 20,
"energy_consumed": 0.5,
"spike_count": 15000
}
}
スパイクデータの添付
{
"response": "生成されたテキスト",
"prompt_id": "uuid",
"spike_data": {
"total_spikes": 15000,
"spike_rate": 75.5,
"layer_stats": {
"layer_0": 5000,
"layer_1": 6000,
"layer_2": 4000
}
}
}
マルチノード協調結果
{
"response": "統合された最終レスポンス",
"prompt_id": "uuid",
"node_responses": [
{
"node_id": "visual-0",
"response": "Visual: 画像に猫が写っています"
},
{
"node_id": "lang-main-0",
"response": "Lang: これは猫の画像です"
},
{
"node_id": "pfc-0",
"response": "PFC: 統合された最終レスポンス"
}
]
}
12. ベストプラクティス
12.1 効率的なポーリング
# ✅ 推奨: 適切なタイムアウトと間隔
result = client.poll_for_result(timeout=120, interval=5)
# ❌ 非推奨: 短すぎる間隔
result = client.poll_for_result(timeout=120, interval=1) # APIに負荷
12.2 エラーハンドリング
try:
result = client.poll_for_result(timeout=120, interval=5)
if result and result.get("response"):
# 成功
print(f"Response: {result['response']}")
else:
# タイムアウトまたは結果なし
print("No result received within timeout")
# デバッグ情報取得
status = client.get_simulation_status()
print("Simulation status:", status)
except RequestException as e:
# ネットワークエラー
print(f"Network error: {e}")
12.3 プロンプトIDの管理
# ✅ 推奨: プロンプトIDを保存して追跡
submission = client.submit_prompt(prompt="...")
prompt_id = submission.get("prompt_id")
# 後で特定の結果を取得
result = client.get_simulation_result() # 最新結果
12.4 マルチモーダル入力
# ✅ 推奨: すべての入力を検証
if os.path.exists(image_path) and os.path.exists(audio_path):
response = client.submit_prompt(
prompt="Describe this",
image_path=image_path,
audio_path=audio_path
)
else:
print("Error: Media files not found")
13. 関連ファイル
| ファイル | 役割 |
|---|---|
api.py |
APIエンドポイント定義、Zenohサブスクライバー |
sdk.py |
Python SDK、ポーリングロジック |
distributed_brain.py |
UI、クエリ送信、レスポンス表示 |
run_zenoh_distributed_brain.py |
ノード実装、推論処理、結果パブリッシュ |
run_simulation_query.py |
SDK使用例 |
run_multimodal_simulation_query.py |
マルチモーダル使用例 |
14. まとめ
レスポンスの特徴
- 非同期処理: クエリ送信と結果取得は分離
- ポーリングベース: フロントエンドが定期的に結果を確認
- Zenoh通信: 高速で信頼性の高いメッセージング
- ファイルベース: ローカル実行とリモート実行の両方をサポート
- UUID追跡: 各クエリを一意に識別
設計上の利点
- ✅ スケーラビリティ: 複数ノードでの並列処理
- ✅ 柔軟性: ローカル/リモート両対応
- ✅ デバッグ性: ファイルベースで中間状態を確認可能
- ✅ 耐障害性: Zenoh通信の冗長性
改善の余地
- ⚠️ ポーリング効率: WebSocketやServer-Sent Eventsの検討
- ⚠️ メタデータ不足: 推論時間、エネルギー消費などの情報
- ⚠️ エラー詳細: より詳細なエラー情報の提供
参考リンク
- 分散脳システムドキュメント
zenoh_comm.py- SDKクイックスタート