Ai_Assistant/_Backup/server/check_setup.py

678 lines
28 KiB
Python
Raw Normal View History

2026-05-24 13:31:30 +02:00
#!/usr/bin/env python3
"""
System Test Script for VRM Avatar Chat System
Tests each component in sequence with user-friendly feedback and troubleshooting tips.
"""
import os
import sys
import time
import json
import yaml
import uuid
import requests
from pathlib import Path
from dotenv import load_dotenv
import sounddevice as sd
import numpy as np
# Color codes for terminal output
class Colors:
HEADER = '\033[95m'
OKBLUE = '\033[94m'
OKCYAN = '\033[96m'
OKGREEN = '\033[92m'
WARNING = '\033[93m'
FAIL = '\033[91m'
ENDC = '\033[0m'
BOLD = '\033[1m'
UNDERLINE = '\033[4m'
def print_header(text):
print(f"\n{Colors.HEADER}{Colors.BOLD}{'='*60}{Colors.ENDC}")
print(f"{Colors.HEADER}{Colors.BOLD}{text}{Colors.ENDC}")
print(f"{Colors.HEADER}{Colors.BOLD}{'='*60}{Colors.ENDC}\n")
def print_success(text):
print(f"{Colors.OKGREEN}{text}{Colors.ENDC}")
def print_error(text):
print(f"{Colors.FAIL}{text}{Colors.ENDC}")
def print_warning(text):
print(f"{Colors.WARNING}{text}{Colors.ENDC}")
def print_info(text):
print(f"{Colors.OKCYAN} {text}{Colors.ENDC}")
def wait_for_user(prompt="Press ENTER to continue..."):
input(f"\n{Colors.BOLD}{prompt}{Colors.ENDC}")
# Base URL for VRM server
BASE_URL = "http://localhost:8001"
# ============================================================================
# TEST 0: Configuration and API Keys
# ============================================================================
def test_config_and_keys():
print_header("TEST 0: Configuration and API Keys")
issues = []
# Check .env file
print_info("Checking .env file...")
load_dotenv()
if not os.path.exists('.env'):
print_warning(".env file not found in current directory")
issues.append(".env file missing")
else:
print_success(".env file found")
# Check OpenAI API Key
print_info("Checking OpenAI API Key...")
openai_key = os.getenv('OPENAI_API_KEY')
if not openai_key:
print_error("OPENAI_API_KEY not set in environment")
issues.append("OPENAI_API_KEY not set")
elif openai_key.startswith('sk-'):
print_success(f"OpenAI API Key found (starts with: {openai_key[:10]}...)")
else:
print_warning("OpenAI API Key found but doesn't start with 'sk-' (might be invalid)")
issues.append("OPENAI_API_KEY format looks incorrect")
# Check Groq API Key
print_info("Checking Groq API Key...")
groq_key = os.getenv('GROQ_API_KEY')
if not groq_key:
print_error("GROQ_API_KEY not set in environment")
issues.append("GROQ_API_KEY not set")
else:
print_success(f"Groq API Key found (starts with: {groq_key[:10]}...)")
# Check character_config.yaml
print_info("Checking character_config.yaml...")
config_path = 'character_config.yaml'
if not os.path.exists(config_path):
print_error(f"{config_path} not found")
issues.append("character_config.yaml missing")
else:
print_success(f"{config_path} found")
try:
with open(config_path, 'r') as f:
config = yaml.safe_load(f)
# Check required fields
required_fields = ['history_file', 'presets']
for field in required_fields:
if field in config:
print_success(f" - {field}: present")
else:
print_error(f" - {field}: missing")
issues.append(f"character_config.yaml missing '{field}'")
# Check if model is set
model = config.get('model', 'not set')
print_info(f" - Model: {model}")
except Exception as e:
print_error(f"Error reading config: {e}")
issues.append(f"character_config.yaml parse error: {e}")
# Summary
print("\n" + ""*60)
if issues:
print_error("Configuration Issues Found:")
for issue in issues:
print(f"{issue}")
print("\n" + Colors.WARNING + "Troubleshooting Tips:" + Colors.ENDC)
if "OPENAI_API_KEY not set" in str(issues):
print(" 1. Create a .env file in your project root")
print(" 2. Add: OPENAI_API_KEY=sk-your-key-here")
print(" 3. Get your key from: https://platform.openai.com/api-keys")
if "GROQ_API_KEY not set" in str(issues):
print(" 1. Add to .env file: GROQ_API_KEY=your-groq-key-here")
print(" 2. Get your key from: https://console.groq.com/keys")
if "character_config.yaml" in str(issues):
print(" 1. Ensure character_config.yaml exists in project root")
print(" 2. Check the file has correct YAML syntax")
return False
else:
print_success("All configuration checks passed!")
return True
# ============================================================================
# TEST 1: LLM Connection
# ============================================================================
def test_llm():
print_header("TEST 1: LLM (OpenAI) Connection")
print_info("Testing connection to OpenAI API...")
try:
from openai import OpenAI
api_key = os.getenv('OPENAI_API_KEY')
if not api_key:
print_error("OPENAI_API_KEY not found in environment")
print_warning("Troubleshooting:")
print(" 1. Make sure .env file contains OPENAI_API_KEY=sk-...")
print(" 2. Restart your terminal/IDE after adding the key")
return False
client = OpenAI(api_key=api_key)
print_info("Sending test message to OpenAI...")
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "user", "content": "Say 'Hello! LLM test successful.' and nothing else."}
],
max_tokens=50
)
response_text = response.choices[0].message.content
print_success(f"LLM Response: {response_text}")
print_success("OpenAI API is working correctly!")
return True
except ImportError:
print_error("OpenAI library not installed")
print_warning("Install with: pip install openai")
return False
except Exception as e:
print_error(f"LLM test failed: {e}")
print_warning("\nTroubleshooting:")
print(" 1. Check your API key is valid at https://platform.openai.com/api-keys")
print(" 2. Ensure you have credits/billing set up on your OpenAI account")
print(" 3. Check your internet connection")
print(f" 4. Error details: {str(e)}")
return False
# ============================================================================
# TEST 2: Audio Recording
# ============================================================================
def test_audio_recording():
print_header("TEST 2: Audio Recording (Microphone)")
print_info("Checking available audio devices...")
try:
devices = sd.query_devices()
print_info("Available audio devices:")
for i, device in enumerate(devices):
if device['max_input_channels'] > 0:
default = " (DEFAULT)" if i == sd.default.device[0] else ""
print(f" [{i}] {device['name']}{default}")
default_input = sd.default.device[0]
print_success(f"\nDefault input device: {devices[default_input]['name']}")
except Exception as e:
print_error(f"Error querying audio devices: {e}")
print_warning("Troubleshooting:")
print(" 1. Make sure a microphone is plugged in")
print(" 2. Check system audio settings")
print(" 3. Install required library: pip install sounddevice")
return False
print_info("\nTesting microphone recording...")
print_warning("When prompted, speak into your microphone for 3 seconds")
wait_for_user("Press ENTER when ready to record...")
try:
from process.asr_func.asr_auto_record import record_on_speech
test_audio_path = Path("audio") / "test_recording.wav"
test_audio_path.parent.mkdir(parents=True, exist_ok=True)
print_info("Recording... (speak now!)")
record_on_speech(
output_file=str(test_audio_path),
samplerate=44100,
channels=1,
silence_threshold=0.02,
silence_duration=2,
device=None
)
if test_audio_path.exists() and test_audio_path.stat().st_size > 1000:
print_success(f"Audio recorded successfully! File: {test_audio_path}")
print_info(f"File size: {test_audio_path.stat().st_size} bytes")
# Test transcription
print_info("\nTesting transcription with Groq...")
try:
from process.asr_func.asr_transcribe_groq import transcribe_audio_groq
transcription = transcribe_audio_groq(aud_path=str(test_audio_path))
print_success(f"Transcription: '{transcription}'")
if transcription and len(transcription.strip()) > 0:
print_success("Audio recording and transcription working!")
return True
else:
print_warning("Transcription returned empty text")
print_info("This might be normal if you didn't speak during recording")
return True
except Exception as e:
print_error(f"Transcription failed: {e}")
print_warning("\nTroubleshooting:")
print(" 1. Check GROQ_API_KEY is set in .env file")
print(" 2. Verify Groq API key at https://console.groq.com/keys")
print(" 3. Check internet connection")
return False
else:
print_error("Recording file not created or is too small")
return False
except ImportError as e:
print_error(f"Missing required module: {e}")
print_warning("Install required libraries:")
print(" pip install sounddevice soundfile")
return False
except Exception as e:
print_error(f"Recording test failed: {e}")
print_warning("\nTroubleshooting:")
print(" 1. Check microphone is plugged in and working")
print(" 2. Grant microphone permissions to Python/terminal")
print(" 3. Try a different microphone or audio device")
print(" 4. Check audio device settings in your OS")
return False
# ============================================================================
# TEST 3: TTS (SoVITS) Audio Generation
# ============================================================================
def test_tts_generation():
print_header("TEST 3: TTS Audio Generation (GPT-SoVITS)")
print_info("Testing connection to GPT-SoVITS server...")
try:
from process.tts_func.sovits_ping import sovits_gen
test_text = "Hello! This is a test of the text to speech system."
output_path = Path("audio") / f"test_tts_{uuid.uuid4().hex}.wav"
output_path.parent.mkdir(parents=True, exist_ok=True)
print_info(f"Generating speech for: '{test_text}'")
print_warning("This requires GPT-SoVITS server to be running...")
sovits_gen(test_text, output_wav_pth=str(output_path))
if output_path.exists() and output_path.stat().st_size > 1000:
print_success(f"TTS audio generated! File: {output_path}")
print_info(f"File size: {output_path.stat().st_size} bytes")
# Try to get duration
try:
from process.tts_func.sovits_ping import get_wav_duration
duration = get_wav_duration(str(output_path))
print_info(f"Audio duration: {duration:.2f} seconds")
except:
pass
print_success("\n✓ TTS generation is working!")
print_info("You can manually check the audio file to verify quality")
response = input(f"\n{Colors.BOLD}Can you hear the audio when you play it? (y/n): {Colors.ENDC}").lower()
if response == 'y':
print_success("Great! TTS system is fully functional")
return True
else:
print_warning("Audio file was generated but might have issues")
print_info("Check the audio file manually: " + str(output_path))
return True
else:
print_error("TTS file not created or is too small")
return False
except ImportError as e:
print_error(f"Missing required module: {e}")
return False
except ConnectionError as e:
print_error(f"Cannot connect to GPT-SoVITS server: {e}")
print_warning("\nTroubleshooting:")
print(" 1. Make sure GPT-SoVITS server is running")
print(" 2. Check the server is accessible (usually http://localhost:9880)")
print(" 3. Verify server configuration in your code")
print(" 4. Check server logs for errors")
return False
except Exception as e:
print_error(f"TTS test failed: {e}")
print_warning("\nTroubleshooting:")
print(" 1. Ensure GPT-SoVITS server is running and accessible")
print(" 2. Check server URL/port configuration")
print(" 3. Verify server has required voice models loaded")
print(" 4. Check server logs for detailed error messages")
return False
# ============================================================================
# TEST 4: VRM Server and Audio Playback
# ============================================================================
def test_vrm_server():
print_header("TEST 4: VRM Server Connection")
print_info(f"Checking VRM server at {BASE_URL}...")
try:
response = requests.get(f"{BASE_URL}/", timeout=5)
print_success("VRM server is running!")
return True
except requests.exceptions.ConnectionError:
print_error(f"Cannot connect to VRM server at {BASE_URL}")
print_warning("\nTroubleshooting:")
print(" 1. Make sure the VRM server (Node.js/Three.js app) is running")
print(" 2. Check it's running on port 8001")
print(" 3. Verify no firewall is blocking the connection")
print(" 4. Start the server with: npm start (or your start command)")
return False
except Exception as e:
print_error(f"Error connecting to VRM server: {e}")
return False
def test_vrm_audio_playback():
print_header("TEST 5: VRM Audio Playback")
print_info("Testing vrm_talk function with audio playback...")
# First, generate a test audio file
try:
from process.tts_func.sovits_ping import sovits_gen, get_wav_duration
test_text = "Testing audio playback through the VRM system."
client_audio = Path("client/audio") / f"test_playback_{uuid.uuid4().hex}.wav"
client_audio.parent.mkdir(parents=True, exist_ok=True)
public_audio = Path("audio") / client_audio.name
public_audio.parent.mkdir(parents=True, exist_ok=True)
print_info("Generating test audio...")
sovits_gen(test_text, output_wav_pth=str(client_audio))
# Copy to public directory
import shutil
shutil.copy2(client_audio, public_audio)
duration = get_wav_duration(str(public_audio))
print_success(f"Test audio generated: {public_audio}")
# Send to VRM
print_info("Sending audio to VRM server...")
url = f"{BASE_URL}/talk"
payload = {
"audio_path": str(public_audio),
"expression": "relaxed",
"audio_text": test_text,
"audio_duraction": int(duration)
}
response = requests.post(url, json=payload, timeout=10)
if response.status_code == 200:
print_success(f"VRM talk request successful! Status: {response.status_code}")
print_info("Response: " + str(response.json()))
print_warning("\n" + ""*60)
print_warning("IMPORTANT: Check the VRM client in your browser!")
print_warning(""*60)
print_info("\nYou should see/hear:")
print(" 1. The avatar's mouth moving")
print(" 2. Audio playing from your speakers")
while True:
response = input(f"\n{Colors.BOLD}Did you see the mouth move AND hear audio? (y/n): {Colors.ENDC}").lower()
if response == 'y':
print_success("Perfect! VRM audio playback is working correctly!")
return True
else:
print_warning("\nDiagnosing the issue...")
mouth = input(f"{Colors.BOLD}Did you see the mouth move? (y/n): {Colors.ENDC}").lower()
audio = input(f"{Colors.BOLD}Did you hear audio? (y/n): {Colors.ENDC}").lower()
if audio == 'y' and mouth == 'n':
print_warning("\n🔧 Issue: Audio plays but mouth doesn't move")
print_info("Solution:")
print(" 1. Open client/config.js")
print(" 2. Find 'mouth_threshold' variable")
print(" 3. Try lowering it (e.g., from 0.01 to 0.005)")
print(" 4. Refresh the browser and test again")
elif audio == 'n' and mouth == 'n':
print_warning("\n🔧 Issue: No audio and no animation")
print_info("Solution:")
print(" 1. Refresh the browser page")
print(" 2. Click inside the browser window to activate it")
print(" 3. Try again")
print(" 4. Check browser console (F12) for errors")
print(" 5. Ensure audio files are in the correct directory")
elif audio == 'n' and mouth == 'y':
print_warning("\n🔧 Issue: Mouth moves but no audio")
print_info("Solution:")
print(" 1. Check browser audio isn't muted")
print(" 2. Check system volume")
print(" 3. Verify audio file path is correct")
print(" 4. Check browser console (F12) for audio errors")
# Ask if they want to retry or continue
print("\n" + ""*60)
retry = input(f"{Colors.BOLD}Would you like to:\n [r] Retry the test after applying changes\n [c] Continue to next test anyway\n [q] Mark as failed and continue\nChoice (r/c/q): {Colors.ENDC}").lower()
if retry == 'r':
print_info("\nRetrying test...\n")
# Re-send the audio to VRM
time.sleep(1)
requests.post(url, json=payload, timeout=10)
continue # Loop back to ask if it worked
elif retry == 'c':
print_warning("Continuing despite issues...")
return True # Mark as passed but with warning
else:
print_warning("Marking test as failed")
return False
else:
print_error(f"VRM talk request failed! Status: {response.status_code}")
print_info("Response: " + str(response.text))
return False
except Exception as e:
print_error(f"VRM audio playback test failed: {e}")
print_warning("\nTroubleshooting:")
print(" 1. Ensure VRM server is running")
print(" 2. Check browser is open with the VRM client")
print(" 3. Verify audio files are in correct directories")
print(" 4. Check server logs for errors")
return False
# ============================================================================
# TEST 6: VRM Animations
# ============================================================================
def test_vrm_animations():
print_header("TEST 6: VRM Animations")
animations = [
("idle", "animations/mixamo/Idle.fbx", "Idle (looking around)"),
("thinking", "animations/mixamo/Thinking.fbx", "Thinking (looking away)"),
("talking", "animations/mixamo/Talking.fbx", "Talking (nodding)"),
]
print_info("Testing VRM animations...")
print_warning("Watch the VRM client in your browser during these tests\n")
all_passed = True
for state_name, anim_path, description in animations:
while True:
try:
print_info(f"Testing: {description}")
# Set animation
url = f"{BASE_URL}/animate"
payload = {
"animate_type": "start_mixamo",
"animation_url": anim_path,
"play_once": False,
"crop_start": 0.0,
"crop_end": 0.0,
"lock_position": False,
"track_position": True,
}
response = requests.post(url, json=payload, timeout=5)
# Set state
state_url = f"{BASE_URL}/set_state"
state_payload = {"state": state_name}
state_response = requests.post(state_url, json=state_payload, timeout=5)
if response.status_code == 200 and state_response.status_code == 200:
print_success(f" Animation command sent successfully")
time.sleep(2) # Let user observe
saw_it = input(f" {Colors.BOLD}Did you see the {description} animation? (y/n): {Colors.ENDC}").lower()
if saw_it == 'y':
print_success(f"{state_name} animation working!\n")
break # Move to next animation
else:
print_warning(f" ! {state_name} animation may not be working")
print_info("\nTroubleshooting:")
print(f" 1. Check that {anim_path} exists")
print(" 2. Refresh the browser and ensure VRM client is loaded")
print(" 3. Check browser console (F12) for errors")
print(" 4. Verify VRM server logs")
retry = input(f"\n{Colors.BOLD}Would you like to:\n [r] Retry this animation\n [c] Continue to next animation\n [q] Mark as failed and continue\nChoice (r/c/q): {Colors.ENDC}").lower()
if retry == 'r':
print_info("Retrying animation...\n")
time.sleep(1)
continue # Retry this animation
elif retry == 'c':
print_warning(f"Continuing despite {state_name} animation issues...\n")
all_passed = False
break # Move to next animation
else:
print_warning(f"Marking {state_name} animation as failed\n")
all_passed = False
break # Move to next animation
else:
print_error(f" Animation request failed: {response.status_code}")
print_warning(" Check VRM server logs for details\n")
retry = input(f"{Colors.BOLD}Would you like to:\n [r] Retry this animation\n [c] Continue to next animation\nChoice (r/c): {Colors.ENDC}").lower()
if retry == 'r':
print_info("Retrying...\n")
continue
else:
all_passed = False
break
except Exception as e:
print_error(f" Animation test failed: {e}")
retry = input(f"{Colors.BOLD}Would you like to:\n [r] Retry this animation\n [c] Continue to next animation\nChoice (r/c): {Colors.ENDC}").lower()
if retry == 'r':
print_info("Retrying...\n")
continue
else:
all_passed = False
break
if all_passed:
print_success("\n✓ All animations are working!")
return True
else:
print_warning("\nSome animations may not be working correctly")
print_info("Troubleshooting:")
print(" 1. Check that animation files exist in animations/mixamo/")
print(" 2. Verify file paths are correct")
print(" 3. Check VRM server console for errors")
print(" 4. Ensure browser client has loaded properly")
return False
# ============================================================================
# Main Test Runner
# ============================================================================
def main():
print(f"\n{Colors.HEADER}{Colors.BOLD}")
print("╔═══════════════════════════════════════════════════════════╗")
print("║ VRM AVATAR CHAT SYSTEM - COMPREHENSIVE TEST SUITE ║")
print("╚═══════════════════════════════════════════════════════════╝")
print(f"{Colors.ENDC}")
print_info("This script will test all components of your VRM chat system")
print_info("Each test will provide feedback and troubleshooting tips if needed\n")
wait_for_user()
results = {}
# Run tests in sequence
results['config'] = test_config_and_keys()
if results['config']:
results['llm'] = test_llm()
else:
print_warning("\nSkipping LLM test due to configuration issues")
results['llm'] = False
results['recording'] = test_audio_recording()
results['tts'] = test_tts_generation()
results['vrm_server'] = test_vrm_server()
if results['vrm_server']:
results['vrm_playback'] = test_vrm_audio_playback()
results['vrm_animations'] = test_vrm_animations()
else:
print_warning("\nSkipping VRM tests due to server connection issues")
results['vrm_playback'] = False
results['vrm_animations'] = False
# Final Summary
print_header("TEST SUMMARY")
passed = sum(1 for v in results.values() if v)
total = len(results)
for test_name, result in results.items():
status = f"{Colors.OKGREEN}PASS{Colors.ENDC}" if result else f"{Colors.FAIL}FAIL{Colors.ENDC}"
print(f" {test_name.upper():.<50} {status}")
print(f"\n{Colors.BOLD}Overall: {passed}/{total} tests passed{Colors.ENDC}")
if passed == total:
print(f"\n{Colors.OKGREEN}{Colors.BOLD}🎉 All systems operational! Your VRM chat system is ready to use!{Colors.ENDC}")
else:
print(f"\n{Colors.WARNING}⚠ Some tests failed. Please review the troubleshooting tips above.{Colors.ENDC}")
print_info("\nCommon next steps:")
print(" 1. Fix configuration issues (API keys, config files)")
print(" 2. Ensure all servers are running (GPT-SoVITS, VRM server)")
print(" 3. Check hardware (microphone, speakers)")
print(" 4. Verify network connectivity")
print(" 5. Review server logs for detailed errors")
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
print(f"\n\n{Colors.WARNING}Test interrupted by user{Colors.ENDC}")
sys.exit(0)
except Exception as e:
print(f"\n{Colors.FAIL}Unexpected error: {e}{Colors.ENDC}")
import traceback
traceback.print_exc()
sys.exit(1)