Files
AIclinicalresearch/backend/check-api-config.js
HaHafeng beb7f7f559 feat(asl): Implement full-text screening core LLM service and validation system (Day 1-3)
Core Components:
- PDFStorageService with Dify/OSS adapters
- LLM12FieldsService with Nougat-first + dual-model + 3-layer JSON parsing
- PromptBuilder for dynamic prompt assembly
- MedicalLogicValidator with 5 rules + fault tolerance
- EvidenceChainValidator for citation integrity
- ConflictDetectionService for dual-model comparison

Prompt Engineering:
- System Prompt (6601 chars, Section-Aware strategy)
- User Prompt template (PICOS context injection)
- JSON Schema (12 fields constraints)
- Cochrane standards (not loaded in MVP)

Key Innovations:
- 3-layer JSON parsing (JSON.parse + json-repair + code block extraction)
- Promise.allSettled for dual-model fault tolerance
- safeGetFieldValue for robust field extraction
- Mixed CN/EN token calculation

Integration Tests:
- integration-test.ts (full test)
- quick-test.ts (quick test)
- cached-result-test.ts (fault tolerance test)

Documentation Updates:
- Development record (Day 2-3 summary)
- Quality assurance strategy (full-text screening)
- Development plan (progress update)
- Module status (v1.1 update)
- Technical debt (10 new items)

Test Results:
- JSON parsing success rate: 100%
- Medical logic validation: 5/5 passed
- Dual-model parallel processing: OK
- Cost per PDF: CNY 0.10

Files: 238 changed, 14383 insertions(+), 32 deletions(-)
Docs: docs/03-涓氬姟妯″潡/ASL-AI鏅鸿兘鏂囩尞/05-寮€鍙戣褰?2025-11-22_Day2-Day3_LLM鏈嶅姟涓庨獙璇佺郴缁熷紑鍙?md
2025-11-22 22:21:12 +08:00

199 lines
4.8 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* API配置检查脚本
* 检查DeepSeek和Qwen API配置是否正确
*/
import dotenv from 'dotenv';
import axios from 'axios';
// 加载环境变量
dotenv.config();
const colors = {
reset: '\x1b[0m',
green: '\x1b[32m',
red: '\x1b[31m',
yellow: '\x1b[33m',
cyan: '\x1b[36m',
};
function log(message, color = 'reset') {
console.log(`${colors[color]}${message}${colors.reset}`);
}
async function checkDeepSeekAPI() {
log('\n=== 检查 DeepSeek API 配置 ===', 'cyan');
const apiKey = process.env.DEEPSEEK_API_KEY;
if (!apiKey) {
log('❌ 未配置 DEEPSEEK_API_KEY', 'red');
log('请在 .env 文件中添加: DEEPSEEK_API_KEY=sk-xxx', 'yellow');
return false;
}
log(`✅ API Key 已配置: ${apiKey.substring(0, 10)}...`, 'green');
// 测试API连接
try {
log('正在测试 DeepSeek API 连接...', 'cyan');
const response = await axios.post(
'https://api.deepseek.com/v1/chat/completions',
{
model: 'deepseek-chat',
messages: [
{ role: 'user', content: '你好' }
],
max_tokens: 10,
},
{
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${apiKey}`,
},
timeout: 10000,
}
);
log('✅ DeepSeek API 连接成功!', 'green');
log(` 模型: ${response.data.model}`, 'green');
log(` 响应: ${response.data.choices[0].message.content}`, 'green');
return true;
} catch (error) {
log('❌ DeepSeek API 连接失败', 'red');
if (error.response) {
log(` 错误: ${error.response.status} - ${error.response.data?.error?.message || error.response.statusText}`, 'red');
} else if (error.code === 'ECONNABORTED') {
log(' 错误: 请求超时,请检查网络连接', 'red');
} else {
log(` 错误: ${error.message}`, 'red');
}
return false;
}
}
async function checkQwenAPI() {
log('\n=== 检查 Qwen API 配置 ===', 'cyan');
const apiKey = process.env.QWEN_API_KEY;
if (!apiKey) {
log('❌ 未配置 QWEN_API_KEY', 'red');
log('请在 .env 文件中添加: QWEN_API_KEY=sk-xxx', 'yellow');
return false;
}
log(`✅ API Key 已配置: ${apiKey.substring(0, 10)}...`, 'green');
// 测试API连接
try {
log('正在测试 Qwen API 连接...', 'cyan');
const response = await axios.post(
'https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions',
{
model: 'qwen-plus',
messages: [
{ role: 'user', content: '你好' }
],
max_tokens: 10,
},
{
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${apiKey}`,
},
timeout: 10000,
}
);
log('✅ Qwen API 连接成功!', 'green');
log(` 模型: ${response.data.model}`, 'green');
log(` 响应: ${response.data.choices[0].message.content}`, 'green');
return true;
} catch (error) {
log('❌ Qwen API 连接失败', 'red');
if (error.response) {
log(` 错误: ${error.response.status} - ${error.response.data?.message || error.response.statusText}`, 'red');
} else if (error.code === 'ECONNABORTED') {
log(' 错误: 请求超时,请检查网络连接', 'red');
} else {
log(` 错误: ${error.message}`, 'red');
}
return false;
}
}
async function main() {
log('\n╔════════════════════════════════════════════════╗', 'cyan');
log('║ API 配置检查工具 ║', 'cyan');
log('╚════════════════════════════════════════════════╝', 'cyan');
const deepseekOK = await checkDeepSeekAPI();
const qwenOK = await checkQwenAPI();
log('\n=== 检查结果汇总 ===', 'cyan');
log(`DeepSeek API: ${deepseekOK ? '✅ 正常' : '❌ 异常'}`, deepseekOK ? 'green' : 'red');
log(`Qwen API: ${qwenOK ? '✅ 正常' : '❌ 异常'}`, qwenOK ? 'green' : 'red');
if (!deepseekOK && !qwenOK) {
log('\n⚠ 所有API都无法使用请检查配置', 'yellow');
log('\n修复建议:', 'cyan');
log('1. 检查 backend/.env 文件是否存在', 'yellow');
log('2. 确认API Key已正确配置', 'yellow');
log('3. 检查网络连接是否正常', 'yellow');
log('4. 确认API Key有足够的额度', 'yellow');
} else if (!deepseekOK || !qwenOK) {
log('\n⚠ 部分API无法使用', 'yellow');
log('建议使用可用的API进行测试', 'yellow');
} else {
log('\n✅ 所有API配置正常', 'green');
}
log('\n');
}
main().catch(error => {
console.error('脚本执行失败:', error);
process.exit(1);
});