|
|
#!/usr/bin/env python3 |
|
|
""" |
|
|
LLM 投資建議服務測試腳本 |
|
|
|
|
|
用於測試 LLM 服務是否正常工作 |
|
|
""" |
|
|
|
|
|
import os |
|
|
import sys |
|
|
import json |
|
|
from unittest.mock import Mock, patch |
|
|
|
|
|
# 添加專案根目錄到 Python 路徑 |
|
|
sys.path.append(os.path.dirname(os.path.abspath(__file__))) |
|
|
|
|
|
from llm_service import LLMInvestmentAdvisor, get_llm_advisor |
|
|
from prompts.investment_advice import get_comprehensive_analysis_prompt |
|
|
|
|
|
|
|
|
def test_llm_service_initialization(): |
|
|
"""測試 LLM 服務初始化""" |
|
|
print("🔍 測試 LLM 服務初始化...") |
|
|
|
|
|
try: |
|
|
# 測試沒有 API 金鑰的情況 |
|
|
try: |
|
|
advisor = LLMInvestmentAdvisor(api_key=None) |
|
|
print("❌ 應該拋出錯誤但沒有拋出") |
|
|
return False |
|
|
except ValueError as e: |
|
|
print(f"✅ 正確拋出錯誤:{e}") |
|
|
|
|
|
# 測試有假 API 金鑰的情況 |
|
|
fake_api_key = "sk-fake-key-for-testing" |
|
|
try: |
|
|
advisor = LLMInvestmentAdvisor(api_key=fake_api_key) |
|
|
print("✅ 成功初始化 LLM 服務") |
|
|
return True |
|
|
except Exception as e: |
|
|
print(f"❌ 初始化失敗:{e}") |
|
|
return False |
|
|
|
|
|
except Exception as e: |
|
|
print(f"❌ 測試失敗:{e}") |
|
|
return False |
|
|
|
|
|
|
|
|
def test_prompt_generation(): |
|
|
"""測試 Prompt 生成""" |
|
|
print("\n🔍 測試 Prompt 生成...") |
|
|
|
|
|
try: |
|
|
# 模擬策略資料 |
|
|
mock_strategy_data = { |
|
|
'id': 123, |
|
|
'name': '測試策略', |
|
|
'role': '最大化夏普比率', |
|
|
'annual_ret': 0.15, |
|
|
'vol': 0.20, |
|
|
'annual_sr': 1.8, |
|
|
'mdd': -0.12, |
|
|
'alpha': 0.08, |
|
|
'beta': 0.95, |
|
|
'var10': 0.05, |
|
|
'r2': 0.85, |
|
|
'gamma': 2.5, |
|
|
'assets': ['AAPL', 'GOOGL', 'MSFT'], |
|
|
'tw': True |
|
|
} |
|
|
|
|
|
prompt = get_comprehensive_analysis_prompt(mock_strategy_data) |
|
|
|
|
|
if len(prompt) > 100 and '策略名稱:測試策略' in prompt: |
|
|
print("✅ Prompt 生成成功") |
|
|
print(f"📝 Prompt 長度:{len(prompt)} 字符") |
|
|
return True |
|
|
else: |
|
|
print("❌ Prompt 生成格式錯誤") |
|
|
return False |
|
|
|
|
|
except Exception as e: |
|
|
print(f"❌ Prompt 生成失敗:{e}") |
|
|
return False |
|
|
|
|
|
|
|
|
def test_fallback_advice(): |
|
|
"""測試 Fallback 建議""" |
|
|
print("\n🔍 測試 Fallback 建議...") |
|
|
|
|
|
try: |
|
|
advisor = LLMInvestmentAdvisor(api_key="fake-key") |
|
|
|
|
|
# 模擬會失敗的策略資料 |
|
|
strategy_data = { |
|
|
'annual_ret': 0.25, |
|
|
'vol': 0.15, |
|
|
'annual_sr': 2.1 |
|
|
} |
|
|
|
|
|
fallback_advice = advisor._get_fallback_advice(strategy_data) |
|
|
|
|
|
if len(fallback_advice) > 100 and '年化報酬率:25.00%' in fallback_advice: |
|
|
print("✅ Fallback 建議生成成功") |
|
|
return True |
|
|
else: |
|
|
print("❌ Fallback 建議格式錯誤") |
|
|
return False |
|
|
|
|
|
except Exception as e: |
|
|
print(f"❌ Fallback 測試失敗:{e}") |
|
|
return False |
|
|
|
|
|
|
|
|
def test_api_format(): |
|
|
"""測試 API 回應格式""" |
|
|
print("\n🔍 測試 API 回應格式...") |
|
|
|
|
|
try: |
|
|
# 模擬成功的 API 回應 |
|
|
mock_response = { |
|
|
'success': True, |
|
|
'advice': '這是一個測試建議。年化報酬率表現良好,建議持續監控市場變化。', |
|
|
'strategy_id': 123 |
|
|
} |
|
|
|
|
|
if all(key in mock_response for key in ['success', 'advice', 'strategy_id']): |
|
|
print("✅ API 回應格式正確") |
|
|
return True |
|
|
else: |
|
|
print("❌ API 回應格式錯誤") |
|
|
return False |
|
|
|
|
|
except Exception as e: |
|
|
print(f"❌ API 格式測試失敗:{e}") |
|
|
return False |
|
|
|
|
|
|
|
|
def test_error_format(): |
|
|
"""測試錯誤回應格式""" |
|
|
print("\n🔍 測試錯誤回應格式...") |
|
|
|
|
|
try: |
|
|
# 模擬錯誤回應 |
|
|
mock_error_response = { |
|
|
'success': False, |
|
|
'error': 'API 金鑰無效', |
|
|
'details': '請檢查 OpenAI API 金鑰設定' |
|
|
} |
|
|
|
|
|
if all(key in mock_error_response for key in ['success', 'error']): |
|
|
print("✅ 錯誤回應格式正確") |
|
|
return True |
|
|
else: |
|
|
print("❌ 錯誤回應格式錯誤") |
|
|
return False |
|
|
|
|
|
except Exception as e: |
|
|
print(f"❌ 錯誤格式測試失敗:{e}") |
|
|
return False |
|
|
|
|
|
|
|
|
def main(): |
|
|
"""主測試函數""" |
|
|
print("🚀 開始測試 LLM 投資建議服務\n") |
|
|
|
|
|
tests = [ |
|
|
("LLM 服務初始化", test_llm_service_initialization), |
|
|
("Prompt 生成", test_prompt_generation), |
|
|
("Fallback 建議", test_fallback_advice), |
|
|
("API 回應格式", test_api_format), |
|
|
("錯誤回應格式", test_error_format), |
|
|
] |
|
|
|
|
|
passed = 0 |
|
|
total = len(tests) |
|
|
|
|
|
for test_name, test_func in tests: |
|
|
if test_func(): |
|
|
passed += 1 |
|
|
print() |
|
|
|
|
|
print("📊 測試結果摘要") |
|
|
print(f"✅ 通過:{passed}/{total}") |
|
|
print(f"❌ 失敗:{total - passed}/{total}") |
|
|
|
|
|
if passed == total: |
|
|
print("🎉 所有測試通過!LLM 服務準備就緒。") |
|
|
return 0 |
|
|
else: |
|
|
print("⚠️ 部分測試失敗,請檢查配置。") |
|
|
return 1 |
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
exit(main())
|
|
|
|