/** * Tool C Day 3 测试脚本 * * 测试内容: * 1. 10个Few-shot示例场景测试 * 2. AI自我修正机制测试(重试) * 3. 端到端测试 * * 前提: * - 需要先创建一个Session(使用Day 2的upload接口) * - 需要Python服务运行(端口8000) * - 需要后端服务运行(端口3000) * * 执行方式:node test-tool-c-day3.mjs */ import axios from 'axios'; import FormData from 'form-data'; import * as XLSX from 'xlsx'; const BASE_URL = 'http://localhost:3000'; const API_PREFIX = '/api/v1/dc/tool-c'; let testSessionId = null; // ==================== 辅助函数 ==================== function printSection(title) { console.log('\n' + '='.repeat(70)); console.log(` ${title}`); console.log('='.repeat(70) + '\n'); } function printSuccess(message) { console.log('✅ ' + message); } function printError(message) { console.log('❌ ' + message); } function printInfo(message) { console.log('ℹ️ ' + message); } // ==================== 准备测试Session ==================== async function createTestSession() { printSection('准备:创建测试Session'); try { // 创建测试Excel数据 const testData = [ { patient_id: 'P001', name: '张三', age: 25, gender: '男', diagnosis: '感冒', sbp: 120, dbp: 80, weight: 70, height: 175, BMI: '', creatinine: '>100', check_date: '2024-01-01' }, { patient_id: 'P002', name: '李四', age: 65, gender: '女', diagnosis: '高血压', sbp: 150, dbp: 95, weight: 65, height: 160, BMI: '', creatinine: '<0.1', check_date: '2024-01-05' }, { patient_id: 'P003', name: '王五', age: 45, gender: '男', diagnosis: '糖尿病', sbp: 135, dbp: 85, weight: 80, height: 170, BMI: '', creatinine: '85', check_date: '2024-01-03' }, { patient_id: 'P004', name: '赵六', age: 70, gender: '女', diagnosis: '冠心病', sbp: 160, dbp: 100, weight: 60, height: 155, BMI: '', creatinine: '120', check_date: '2024-01-10' }, { patient_id: 'P005', name: '钱七', age: 35, gender: '男', diagnosis: '胃炎', sbp: 110, dbp: 70, weight: 75, height: 180, BMI: '', creatinine: '-', check_date: '2024-01-08' }, { patient_id: 'P003', name: '王五', age: 45, gender: '男', diagnosis: '糖尿病', sbp: 138, dbp: 88, weight: 82, height: 170, BMI: '', creatinine: '88', check_date: '2024-01-12' }, // 重复ID,日期更新 ]; // 生成Excel const ws = XLSX.utils.json_to_sheet(testData); const wb = XLSX.utils.book_new(); XLSX.utils.book_append_sheet(wb, ws, 'Sheet1'); const excelBuffer = XLSX.write(wb, { type: 'buffer', bookType: 'xlsx' }); // 上传创建Session const form = new FormData(); form.append('file', excelBuffer, { filename: 'test-medical-data-day3.xlsx', contentType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', }); const response = await axios.post( `${BASE_URL}${API_PREFIX}/sessions/upload`, form, { headers: form.getHeaders(), timeout: 10000 } ); if (response.data.success) { testSessionId = response.data.data.sessionId; printSuccess(`Session创建成功: ${testSessionId}`); printInfo(`数据: ${testData.length}行 x ${Object.keys(testData[0]).length}列`); return true; } else { printError('Session创建失败'); return false; } } catch (error) { printError('Session创建异常: ' + error.message); return false; } } // ==================== AI测试函数 ==================== async function testAIGenerate(testName, userMessage, shouldSucceed = true) { printSection(`测试: ${testName}`); try { printInfo(`用户需求: ${userMessage}`); const response = await axios.post( `${BASE_URL}${API_PREFIX}/ai/generate`, { sessionId: testSessionId, message: userMessage }, { timeout: 30000 } // AI调用可能需要较长时间 ); if (response.data.success) { printSuccess('AI生成代码成功'); console.log('\n生成的代码:'); console.log('```python'); console.log(response.data.data.code); console.log('```\n'); console.log('解释:', response.data.data.explanation); console.log('MessageID:', response.data.data.messageId); return { success: true, data: response.data.data }; } else { if (shouldSucceed) { printError('AI生成失败: ' + response.data.error); } else { printInfo('预期失败: ' + response.data.error); } return { success: false, error: response.data.error }; } } catch (error) { printError('AI生成异常: ' + (error.response?.data?.error || error.message)); return { success: false, error: error.message }; } } async function testAIProcess(testName, userMessage) { printSection(`测试(一步到位): ${testName}`); try { printInfo(`用户需求: ${userMessage}`); const response = await axios.post( `${BASE_URL}${API_PREFIX}/ai/process`, { sessionId: testSessionId, message: userMessage, maxRetries: 3 }, { timeout: 60000 } // 带重试可能需要更长时间 ); if (response.data.success) { printSuccess(`执行成功${response.data.data.retryCount > 0 ? `(重试${response.data.data.retryCount}次)` : ''}`); console.log('\n生成的代码:'); console.log('```python'); console.log(response.data.data.code); console.log('```\n'); console.log('解释:', response.data.data.explanation); if (response.data.data.executeResult.success) { printSuccess('代码执行成功'); console.log('数据预览(前5行):'); console.log(JSON.stringify(response.data.data.executeResult.newDataPreview?.slice(0, 5), null, 2)); } return { success: true, data: response.data.data }; } else { printError('处理失败: ' + response.data.error); return { success: false, error: response.data.error }; } } catch (error) { printError('处理异常: ' + (error.response?.data?.error || error.message)); return { success: false, error: error.message }; } } // ==================== 主测试函数 ==================== async function runAllTests() { console.log('\n' + '🚀'.repeat(35)); console.log(' Tool C Day 3 测试 - AI代码生成'); console.log('🚀'.repeat(35)); const results = {}; try { // 0. 准备测试Session const sessionCreated = await createTestSession(); if (!sessionCreated) { printError('测试Session创建失败,无法继续'); return; } await new Promise(resolve => setTimeout(resolve, 2000)); // ==================== 10个Few-shot示例测试 ==================== // 测试1: 统一缺失值标记 let result = await testAIProcess( '示例1: 统一缺失值标记', '把所有代表缺失的符号(-、不详、NA、N/A)统一替换为标准空值' ); results['示例1-缺失值'] = result.success; await new Promise(resolve => setTimeout(resolve, 3000)); // 测试2: 数值列清洗 result = await testAIProcess( '示例2: 数值列清洗', '把creatinine列里的非数字符号去掉,<0.1按0.05处理,转为数值类型' ); results['示例2-数值清洗'] = result.success; await new Promise(resolve => setTimeout(resolve, 3000)); // 测试3: 分类变量编码 result = await testAIProcess( '示例3: 分类变量编码', '把gender列转为数字,男=1,女=0' ); results['示例3-编码'] = result.success; await new Promise(resolve => setTimeout(resolve, 3000)); // 测试4: 连续变量分箱 result = await testAIProcess( '示例4: 连续变量分箱', '把age列按18岁、60岁分为未成年、成年、老年三组' ); results['示例4-分箱'] = result.success; await new Promise(resolve => setTimeout(resolve, 3000)); // 测试5: BMI计算 result = await testAIProcess( '示例5: BMI计算', '根据weight和height计算BMI,并标记BMI≥28为肥胖' ); results['示例5-BMI'] = result.success; await new Promise(resolve => setTimeout(resolve, 3000)); // 测试6: 条件筛选 result = await testAIProcess( '示例6: 条件筛选', '筛选出年龄≥60岁、且sbp≥140的患者' ); results['示例6-筛选'] = result.success; await new Promise(resolve => setTimeout(resolve, 3000)); // 测试7: 智能去重 result = await testAIProcess( '示例7: 智能去重', '按patient_id去重,保留check_date最新的记录' ); results['示例7-去重'] = result.success; await new Promise(resolve => setTimeout(resolve, 3000)); // 测试8: 中位数填补(简化版,跳过多重插补) result = await testAIProcess( '示例8: 缺失值填补', '用age列的中位数填补age列的缺失值' ); results['示例8-填补'] = result.success; await new Promise(resolve => setTimeout(resolve, 3000)); // 测试9: 统计汇总 result = await testAIProcess( '示例9: 统计汇总', '按diagnosis分组,统计每个诊断的平均年龄和患者数量' ); results['示例9-统计'] = result.success; await new Promise(resolve => setTimeout(resolve, 3000)); // 测试10: 复杂计算 result = await testAIProcess( '示例10: 复杂计算', '根据sbp判断血压分类:正常(<140)、高血压I级(140-159)、高血压II级(≥160)' ); results['示例10-分类'] = result.success; // ==================== 对话历史测试 ==================== printSection('测试: 获取对话历史'); try { const historyResponse = await axios.get( `${BASE_URL}${API_PREFIX}/ai/history/${testSessionId}?limit=5` ); if (historyResponse.data.success) { printSuccess(`获取历史成功: ${historyResponse.data.data.count}条`); results['对话历史'] = true; } else { printError('获取历史失败'); results['对话历史'] = false; } } catch (error) { printError('获取历史异常: ' + error.message); results['对话历史'] = false; } } catch (error) { printError('测试过程中发生异常: ' + error.message); console.error(error); } // 汇总结果 printSection('测试结果汇总'); let passed = 0; let total = 0; for (const [testName, result] of Object.entries(results)) { total++; if (result) { passed++; console.log(`${testName.padEnd(20)}: ✅ 通过`); } else { console.log(`${testName.padEnd(20)}: ❌ 失败`); } } console.log('\n' + '-'.repeat(70)); console.log(`总计: ${passed}/${total} 通过 (${((passed/total)*100).toFixed(1)}%)`); console.log('-'.repeat(70)); if (passed === total) { console.log('\n🎉 所有测试通过!Day 3 AI功能完成!\n'); } else if (passed >= total * 0.7) { console.log(`\n⚠️ 有 ${total - passed} 个测试失败,但通过率≥70%,基本可用\n`); } else { console.log(`\n❌ 通过率过低,需要调试\n`); } } // 执行测试 runAllTests() .then(() => { console.log('测试完成'); process.exit(0); }) .catch((error) => { console.error('测试失败:', error); process.exit(1); });