Files
AIclinicalresearch/backend/src/services/agentService.ts
AI Clinical Dev Team 239c7ea85e feat: Day 21-22 - knowledge base frontend completed, fix CORS and file upload issues
- Complete knowledge base list and detail pages
- Complete document upload component
- Fix CORS config (add PUT/DELETE method support)
- Fix file upload issues (disabled state and beforeUpload return value)
- Add detailed debug logs (cleaned up)
- Create Day 21-22 completion summary document
2025-10-11 15:40:12 +08:00

216 lines
5.5 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.
import fs from 'fs';
import path from 'path';
import yaml from 'js-yaml';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// 智能体配置接口
export interface AgentConfig {
id: string;
name: string;
nameEn: string;
description: string;
category: string;
icon: string;
enabled: boolean;
systemPromptFile: string;
userPromptTemplateFile: string;
models: {
[modelName: string]: {
temperature: number;
maxTokens: number;
topP?: number;
};
};
ragEnabled: boolean;
requiresProject: boolean;
outputFormat: 'text' | 'structured' | 'document';
tags: string[];
}
// 配置文件根结构
interface AgentsConfigFile {
agents: AgentConfig[];
}
class AgentService {
private agents: Map<string, AgentConfig> = new Map();
private prompts: Map<string, string> = new Map();
private configPath: string;
private promptsPath: string;
constructor() {
// 配置文件路径
this.configPath = path.resolve(__dirname, '../../config/agents.yaml');
this.promptsPath = path.resolve(__dirname, '../../prompts');
// 初始化加载配置
this.loadAgents();
}
// 加载智能体配置
private loadAgents() {
try {
const fileContents = fs.readFileSync(this.configPath, 'utf8');
const config = yaml.load(fileContents) as AgentsConfigFile;
if (!config || !config.agents) {
throw new Error('Invalid agents configuration file');
}
// 存储到Map中
config.agents.forEach((agent) => {
this.agents.set(agent.id, agent);
});
console.log(`✅ Loaded ${this.agents.size} agent configurations`);
} catch (error) {
console.error('❌ Failed to load agent configurations:', error);
throw error;
}
}
// 加载Prompt模板
private loadPrompt(filename: string): string {
const cacheKey = filename;
// 检查缓存
if (this.prompts.has(cacheKey)) {
return this.prompts.get(cacheKey)!;
}
try {
const promptPath = path.join(this.promptsPath, filename);
const content = fs.readFileSync(promptPath, 'utf8');
// 缓存到内存
this.prompts.set(cacheKey, content);
return content;
} catch (error) {
console.error(`❌ Failed to load prompt file: ${filename}`, error);
throw new Error(`Prompt file not found: ${filename}`);
}
}
// 获取所有智能体列表
getAllAgents(): AgentConfig[] {
return Array.from(this.agents.values());
}
// 获取启用的智能体列表
getEnabledAgents(): AgentConfig[] {
return Array.from(this.agents.values()).filter((agent) => agent.enabled);
}
// 根据ID获取智能体配置
getAgentById(agentId: string): AgentConfig | null {
return this.agents.get(agentId) || null;
}
// 根据分类获取智能体列表
getAgentsByCategory(category: string): AgentConfig[] {
return Array.from(this.agents.values()).filter(
(agent) => agent.category === category
);
}
// 获取智能体的系统Prompt
getSystemPrompt(agentId: string): string {
const agent = this.getAgentById(agentId);
if (!agent) {
throw new Error(`Agent not found: ${agentId}`);
}
return this.loadPrompt(agent.systemPromptFile);
}
// 获取智能体的用户Prompt模板
getUserPromptTemplate(agentId: string): string {
const agent = this.getAgentById(agentId);
if (!agent) {
throw new Error(`Agent not found: ${agentId}`);
}
return this.loadPrompt(agent.userPromptTemplateFile);
}
// 渲染用户Prompt替换模板变量
renderUserPrompt(
agentId: string,
variables: {
projectBackground?: string;
userInput: string;
knowledgeBaseContext?: string;
}
): string {
const template = this.getUserPromptTemplate(agentId);
let rendered = template;
// 替换变量
rendered = rendered.replace(/\{\{projectBackground\}\}/g, variables.projectBackground || '未提供项目背景');
rendered = rendered.replace(/\{\{userInput\}\}/g, variables.userInput);
// 处理条件块(知识库上下文)
if (variables.knowledgeBaseContext) {
rendered = rendered.replace(
/\{\{#if knowledgeBaseContext\}\}([\s\S]*?)\{\{\/if\}\}/g,
'$1'
);
rendered = rendered.replace(/\{\{knowledgeBaseContext\}\}/g, variables.knowledgeBaseContext);
} else {
// 移除条件块
rendered = rendered.replace(
/\{\{#if knowledgeBaseContext\}\}[\s\S]*?\{\{\/if\}\}/g,
''
);
}
return rendered.trim();
}
// 检查智能体是否存在
agentExists(agentId: string): boolean {
return this.agents.has(agentId);
}
// 检查智能体是否启用
isAgentEnabled(agentId: string): boolean {
const agent = this.getAgentById(agentId);
return agent ? agent.enabled : false;
}
// 获取智能体的模型配置
getModelConfig(agentId: string, modelName: string) {
const agent = this.getAgentById(agentId);
if (!agent) {
throw new Error(`Agent not found: ${agentId}`);
}
const modelConfig = agent.models[modelName];
if (!modelConfig) {
throw new Error(`Model ${modelName} not configured for agent ${agentId}`);
}
return modelConfig;
}
// 重新加载配置(热更新)
reloadConfig() {
this.agents.clear();
this.prompts.clear();
this.loadAgents();
console.log('✅ Agent configurations reloaded');
}
}
// 导出单例
export const agentService = new AgentService();