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
123 lines
3.0 KiB
TypeScript
123 lines
3.0 KiB
TypeScript
/**
|
||
* 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个智能体');
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|