Files
AIclinicalresearch/backend/src/modules/rvw/services/utils.ts
HaHafeng 4088275290 fix(pkb): fix create KB and upload issues - remove simulated upload, fix department mapping, add upload modal
Fixed issues:
- Remove simulateUpload function from DashboardPage Step 3
- Map department to description field when creating KB
- Add upload modal in WorkspacePage knowledge assets tab
- Fix DocumentUpload import path (../../stores to ../stores)

Known issue: Dify API validation error during document upload (file uploaded but DB record failed, needs investigation)

Testing: KB creation works, upload dialog opens correctly
2026-01-13 13:17:20 +08:00

123 lines
3.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.
/**
* RVW稿件审查模块 - 工具函数
* @module rvw/services/utils
*/
import { MethodologyReview, MethodologyStatus } from '../types/index.js';
/**
* 从LLM响应中解析JSON
* 支持多种格式纯JSON、```json代码块、混合文本
*/
export function parseJSONFromLLMResponse<T>(content: string): T {
try {
// 1. 尝试直接解析
return JSON.parse(content) as T;
} catch {
// 2. 尝试提取```json代码块
const jsonMatch = content.match(/```json\s*\n?([\s\S]*?)\n?```/);
if (jsonMatch) {
try {
return JSON.parse(jsonMatch[1].trim()) as T;
} catch {
// 继续尝试其他方法
}
}
// 3. 尝试提取{}或[]包裹的内容
const objectMatch = content.match(/(\{[\s\S]*\})/);
if (objectMatch) {
try {
return JSON.parse(objectMatch[1]) as T;
} catch {
// 继续尝试其他方法
}
}
const arrayMatch = content.match(/(\[[\s\S]*\])/);
if (arrayMatch) {
try {
return JSON.parse(arrayMatch[1]) as T;
} catch {
// 失败
}
}
// 4. 所有尝试都失败
throw new Error('无法从LLM响应中解析JSON');
}
}
/**
* 根据方法学评估结果判断状态
* @param review 方法学评估结果
* @returns pass | warn | fail
*/
export function getMethodologyStatus(review: MethodologyReview | null | undefined): MethodologyStatus | undefined {
if (!review) return undefined;
const score = review.overall_score;
if (score >= 80) return 'pass';
if (score >= 60) return 'warn';
return 'fail';
}
/**
* 根据选择的智能体计算综合分数
* @param editorialScore 稿约规范性分数
* @param methodologyScore 方法学分数
* @param agents 选择的智能体
* @returns 综合分数
*/
export function calculateOverallScore(
editorialScore: number | null | undefined,
methodologyScore: number | null | undefined,
agents: string[]
): number | null {
const hasEditorial = agents.includes('editorial') && editorialScore != null;
const hasMethodology = agents.includes('methodology') && methodologyScore != null;
if (hasEditorial && hasMethodology) {
// 两个都选稿约40% + 方法学60%
return editorialScore! * 0.4 + methodologyScore! * 0.6;
} else if (hasEditorial) {
// 只选规范性
return editorialScore!;
} else if (hasMethodology) {
// 只选方法学
return methodologyScore!;
}
return null;
}
/**
* 验证智能体选择
* @param agents 选择的智能体列表
* @throws 如果选择无效
*/
export function validateAgentSelection(agents: string[]): void {
if (!agents || agents.length === 0) {
throw new Error('请至少选择一个智能体');
}
const validAgents = ['editorial', 'methodology'];
for (const agent of agents) {
if (!validAgents.includes(agent)) {
throw new Error(`无效的智能体类型: ${agent}`);
}
}
if (agents.length > 2) {
throw new Error('最多只能选择2个智能体');
}
}