/** * CloseAI集成测试脚本 * * 测试通过CloseAI代理访问GPT-5和Claude-4.5模型 * * 运行方式: * ```bash * cd backend * npx tsx src/scripts/test-closeai.ts * ``` * * 环境变量要求: * - CLOSEAI_API_KEY: CloseAI API密钥 * - CLOSEAI_OPENAI_BASE_URL: OpenAI端点 * - CLOSEAI_CLAUDE_BASE_URL: Claude端点 * * 参考文档:docs/02-通用能力层/01-LLM大模型网关/03-CloseAI集成指南.md */ import { LLMFactory } from '../common/llm/adapters/LLMFactory.js'; import { config } from '../config/env.js'; /** * 测试配置验证 */ function validateConfig() { console.log('🔍 验证环境配置...\n'); const checks = [ { name: 'CLOSEAI_API_KEY', value: config.closeaiApiKey, required: true, }, { name: 'CLOSEAI_OPENAI_BASE_URL', value: config.closeaiOpenaiBaseUrl, required: true, }, { name: 'CLOSEAI_CLAUDE_BASE_URL', value: config.closeaiClaudeBaseUrl, required: true, }, ]; let allValid = true; for (const check of checks) { const status = check.value ? '✅' : '❌'; console.log(`${status} ${check.name}: ${check.value ? '已配置' : '未配置'}`); if (check.required && !check.value) { allValid = false; } } console.log(''); if (!allValid) { throw new Error('环境配置不完整,请检查 .env 文件'); } console.log('✅ 环境配置验证通过\n'); } /** * 测试GPT-5-Pro */ async function testGPT5() { console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'); console.log('1️⃣ 测试 GPT-5-Pro'); console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n'); try { const gpt5 = LLMFactory.getAdapter('gpt-5'); console.log('📤 发送测试请求...'); console.log('提示词: "你好,请用一句话介绍你自己。"\n'); const startTime = Date.now(); const response = await gpt5.chat([ { role: 'user', content: '你好,请用一句话介绍你自己。', }, ]); const duration = Date.now() - startTime; console.log('📥 收到响应:\n'); console.log(`模型: ${response.model}`); console.log(`内容: ${response.content}`); console.log(`耗时: ${duration}ms`); if (response.usage) { console.log(`Token使用: ${response.usage.totalTokens} (输入: ${response.usage.promptTokens}, 输出: ${response.usage.completionTokens})`); } console.log('\n✅ GPT-5测试通过\n'); return true; } catch (error) { console.error('\n❌ GPT-5测试失败:', error); return false; } } /** * 测试Claude-4.5-Sonnet */ async function testClaude() { console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'); console.log('2️⃣ 测试 Claude-4.5-Sonnet'); console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n'); try { const claude = LLMFactory.getAdapter('claude-4.5'); console.log('📤 发送测试请求...'); console.log('提示词: "你好,请用一句话介绍你自己。"\n'); const startTime = Date.now(); const response = await claude.chat([ { role: 'user', content: '你好,请用一句话介绍你自己。', }, ]); const duration = Date.now() - startTime; console.log('📥 收到响应:\n'); console.log(`模型: ${response.model}`); console.log(`内容: ${response.content}`); console.log(`耗时: ${duration}ms`); if (response.usage) { console.log(`Token使用: ${response.usage.totalTokens} (输入: ${response.usage.promptTokens}, 输出: ${response.usage.completionTokens})`); } console.log('\n✅ Claude测试通过\n'); return true; } catch (error) { console.error('\n❌ Claude测试失败:', error); return false; } } /** * 测试文献筛选场景(实际应用) */ async function testLiteratureScreening() { console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'); console.log('3️⃣ 测试文献筛选场景(双模型对比)'); console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n'); const testLiterature = { title: 'Deep learning in medical imaging: A systematic review', abstract: 'Background: Deep learning has shown remarkable performance in various medical imaging tasks. Methods: We systematically reviewed 150 studies on deep learning applications in radiology, pathology, and ophthalmology. Results: Deep learning models achieved high accuracy (>90%) in most tasks. Conclusion: Deep learning is a promising tool for medical image analysis.', }; const picoPrompt = ` 请根据以下PICO标准,判断这篇文献是否应该纳入系统评价: **PICO标准:** - Population: 成年患者 - Intervention: 深度学习模型 - Comparison: 传统机器学习方法 - Outcome: 诊断准确率 **文献信息:** 标题:${testLiterature.title} 摘要:${testLiterature.abstract} 请输出JSON格式: { "decision": "include/exclude/uncertain", "reason": "判断理由", "confidence": 0.0-1.0 } `; try { console.log('📤 使用DeepSeek和GPT-5进行双模型对比筛选...\n'); // 并行调用两个模型 const [deepseekAdapter, gpt5Adapter] = [ LLMFactory.getAdapter('deepseek-v3'), LLMFactory.getAdapter('gpt-5'), ]; const startTime = Date.now(); const [deepseekResponse, gpt5Response] = await Promise.all([ deepseekAdapter.chat([{ role: 'user', content: picoPrompt }]), gpt5Adapter.chat([{ role: 'user', content: picoPrompt }]), ]); const duration = Date.now() - startTime; console.log('📥 DeepSeek响应:'); console.log(deepseekResponse.content); console.log(''); console.log('📥 GPT-5响应:'); console.log(gpt5Response.content); console.log(''); console.log(`⏱️ 总耗时: ${duration}ms(并行)`); console.log(`💰 总Token: ${(deepseekResponse.usage?.totalTokens || 0) + (gpt5Response.usage?.totalTokens || 0)}`); // 尝试解析JSON结果(简单验证) try { const deepseekDecision = JSON.parse(deepseekResponse.content); const gpt5Decision = JSON.parse(gpt5Response.content); console.log('\n✅ 双模型筛选结果:'); console.log(`DeepSeek决策: ${deepseekDecision.decision} (置信度: ${deepseekDecision.confidence})`); console.log(`GPT-5决策: ${gpt5Decision.decision} (置信度: ${gpt5Decision.confidence})`); if (deepseekDecision.decision === gpt5Decision.decision) { console.log('✅ 两个模型一致,共识度高'); } else { console.log('⚠️ 两个模型不一致,建议人工复核或启用第三方仲裁(Claude)'); } } catch (parseError) { console.log('⚠️ JSON解析失败(测试环境,实际应用需要优化提示词)'); } console.log('\n✅ 文献筛选场景测试通过\n'); return true; } catch (error) { console.error('\n❌ 文献筛选场景测试失败:', error); return false; } } /** * 测试流式调用(可选) */ async function testStreamMode() { console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'); console.log('4️⃣ 测试流式调用(GPT-5)'); console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n'); try { const gpt5 = LLMFactory.getAdapter('gpt-5'); console.log('📤 发送流式请求...'); console.log('提示词: "请写一首关于人工智能的短诗(4行)"\n'); console.log('📥 流式响应:\n'); const startTime = Date.now(); let fullContent = ''; let chunkCount = 0; for await (const chunk of gpt5.chatStream([ { role: 'user', content: '请写一首关于人工智能的短诗(4行)', }, ])) { if (chunk.content) { process.stdout.write(chunk.content); fullContent += chunk.content; chunkCount++; } if (chunk.done) { const duration = Date.now() - startTime; console.log('\n'); console.log(`\n⏱️ 耗时: ${duration}ms`); console.log(`📦 Chunk数: ${chunkCount}`); console.log(`📝 总字符数: ${fullContent.length}`); if (chunk.usage) { console.log(`💰 Token使用: ${chunk.usage.totalTokens}`); } } } console.log('\n✅ 流式调用测试通过\n'); return true; } catch (error) { console.error('\n❌ 流式调用测试失败:', error); return false; } } /** * 主测试函数 */ async function main() { console.log('╔═══════════════════════════════════════════════════╗'); console.log('║ 🧪 CloseAI集成测试 ║'); console.log('║ 测试GPT-5和Claude-4.5通过CloseAI代理访问 ║'); console.log('╚═══════════════════════════════════════════════════╝\n'); try { // 验证配置 validateConfig(); // 测试结果 const results = { gpt5: false, claude: false, literatureScreening: false, stream: false, }; // 1. 测试GPT-5 results.gpt5 = await testGPT5(); // 2. 测试Claude-4.5 results.claude = await testClaude(); // 3. 测试文献筛选场景 results.literatureScreening = await testLiteratureScreening(); // 4. 测试流式调用(可选) results.stream = await testStreamMode(); // 总结 console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'); console.log('📊 测试总结'); console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n'); const allPassed = Object.values(results).every((r) => r === true); console.log(`GPT-5测试: ${results.gpt5 ? '✅ 通过' : '❌ 失败'}`); console.log(`Claude测试: ${results.claude ? '✅ 通过' : '❌ 失败'}`); console.log(`文献筛选场景: ${results.literatureScreening ? '✅ 通过' : '❌ 失败'}`); console.log(`流式调用测试: ${results.stream ? '✅ 通过' : '❌ 失败'}`); console.log('\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n'); if (allPassed) { console.log('🎉 所有测试通过!CloseAI集成成功!'); console.log('\n✅ 可以在ASL模块中使用GPT-5和Claude-4.5进行双模型对比筛选'); console.log('✅ 支持三模型共识仲裁(DeepSeek + GPT-5 + Claude)'); console.log('✅ 支持流式调用,适用于实时响应场景\n'); process.exit(0); } else { console.error('⚠️ 部分测试失败,请检查配置和网络连接\n'); process.exit(1); } } catch (error) { console.error('❌ 测试执行失败:', error); process.exit(1); } } // 运行测试 main();