/** * RVW稿件审查模块 - 工具函数 * @module rvw/services/utils */ import { MethodologyReview, MethodologyStatus } from '../types/index.js'; /** * 从LLM响应中解析JSON * 支持多种格式:纯JSON、```json代码块、混合文本 */ export function parseJSONFromLLMResponse(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个智能体'); } }