Files
AIclinicalresearch/backend/scripts/test-unifuncs-deepsearch.ts
HaHafeng 61cdc97eeb feat(platform): Fix pg-boss queue conflict and add safety standards
Summary:
- Fix pg-boss queue conflict (duplicate key violation on queue_pkey)
- Add global error listener to prevent process crash
- Reduce connection pool from 10 to 4
- Add graceful shutdown handling (SIGTERM/SIGINT)
- Fix researchWorker recursive call bug in catch block
- Make screeningWorker idempotent using upsert

Security Standards (v1.1):
- Prohibit recursive retry in Worker catch blocks
- Prohibit payload bloat (only store fileKey/ID in job.data)
- Require Worker idempotency (upsert + unique constraint)
- Recommend task-specific expireInSeconds settings
- Document graceful shutdown pattern

New Features:
- PKB signed URL endpoint for document preview/download
- pg_bigm installation guide for Docker
- Dockerfile.postgres-with-extensions for pgvector + pg_bigm

Documentation:
- Update Postgres-Only async task processing guide (v1.1)
- Add troubleshooting SQL queries
- Update safety checklist

Tested: Local verification passed
2026-01-23 22:07:26 +08:00

129 lines
4.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
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.
/**
* unifuncs DeepSearch API 快速验证脚本
*
* 运行方式:
* cd backend
* npx tsx scripts/test-unifuncs-deepsearch.ts
*/
import OpenAI from 'openai';
// ========== 配置 ==========
const UNIFUNCS_API_KEY = 'sk-2fNwqUH73elGq0aDKJEM4ReqP7Ry0iqHo4OXyidDe2WpQ9XQ';
const UNIFUNCS_BASE_URL = 'https://api.unifuncs.com/deepsearch/v1';
// ========== 测试用例 ==========
const TEST_QUERIES = [
// 简单测试
'糖尿病 SGLT2抑制剂 心血管 RCT',
// 复杂临床问题
// '乳腺癌免疫治疗最新系统综述近3年的研究进展',
];
// ========== 主函数 ==========
async function testDeepSearch() {
console.log('🚀 unifuncs DeepSearch API 验证测试\n');
console.log('=' .repeat(60));
const client = new OpenAI({
baseURL: UNIFUNCS_BASE_URL,
apiKey: UNIFUNCS_API_KEY,
});
for (const query of TEST_QUERIES) {
console.log(`\n📝 测试查询: "${query}"\n`);
console.log('-'.repeat(60));
try {
const startTime = Date.now();
// 方式1: 流式响应(推荐用于验证)
const stream = await client.chat.completions.create({
model: 's2',
messages: [{ role: 'user', content: query }],
stream: true,
// @ts-ignore - unifuncs 扩展参数
introduction: '你是一名专业的临床研究文献检索专家,请在 PubMed 中检索相关文献。输出每篇文献的 PMID、标题、作者、期刊、发表年份、研究类型。',
max_depth: 10, // 验证时用较小的深度,加快速度
domain_scope: ['https://pubmed.ncbi.nlm.nih.gov/'],
domain_blacklist: ['wanfang.com', 'cnki.net'],
reference_style: 'link',
} as any);
let thinking = false;
let thinkingContent = '';
let responseContent = '';
console.log('📡 流式响应中...\n');
for await (const chunk of stream) {
const delta = chunk.choices[0]?.delta;
// 处理思考过程 (reasoning_content)
if ((delta as any)?.reasoning_content) {
if (!thinking) {
console.log('💭 [思考过程]');
thinking = true;
}
const content = (delta as any).reasoning_content;
thinkingContent += content;
process.stdout.write(content);
}
// 处理正式回答 (content)
else if (delta?.content) {
if (thinking) {
console.log('\n\n📄 [检索结果]');
thinking = false;
}
responseContent += delta.content;
process.stdout.write(delta.content);
}
}
const endTime = Date.now();
const duration = ((endTime - startTime) / 1000).toFixed(2);
console.log('\n\n' + '='.repeat(60));
console.log(`✅ 测试完成!耗时: ${duration}`);
console.log(`📊 思考过程长度: ${thinkingContent.length} 字符`);
console.log(`📊 回答内容长度: ${responseContent.length} 字符`);
// 尝试提取 PMID
const pmidMatches = responseContent.match(/PMID[:\s]*(\d+)/gi) || [];
const pubmedLinks = responseContent.match(/pubmed\.ncbi\.nlm\.nih\.gov\/(\d+)/gi) || [];
const totalPmids = new Set([
...pmidMatches.map(m => m.replace(/PMID[:\s]*/i, '')),
...pubmedLinks.map(m => m.replace(/pubmed\.ncbi\.nlm\.nih\.gov\//i, '')),
]);
console.log(`📚 检索到的文献数量: ${totalPmids.size}`);
if (totalPmids.size > 0) {
console.log(`📚 PMID 列表: ${[...totalPmids].slice(0, 10).join(', ')}${totalPmids.size > 10 ? '...' : ''}`);
}
} catch (error: any) {
console.error('\n❌ 测试失败:', error.message);
if (error.response) {
console.error('响应状态:', error.response.status);
console.error('响应数据:', error.response.data);
}
}
}
console.log('\n' + '='.repeat(60));
console.log('🏁 所有测试完成!');
}
// ========== 运行 ==========
testDeepSearch().catch(console.error);