diff --git a/src/modules/admin-ai-chat/admin-ai-chat.service.ts b/src/modules/admin-ai-chat/admin-ai-chat.service.ts index 663d35f..1e90ddf 100644 --- a/src/modules/admin-ai-chat/admin-ai-chat.service.ts +++ b/src/modules/admin-ai-chat/admin-ai-chat.service.ts @@ -2,6 +2,10 @@ import { DeepSeekProvider } from '../ai/providers/deepseek.provider'; import type { AiChatDto } from './dto/ai-chat.dto'; +const HERMES_API_URL = 'http://10.2.0.7:8642/v1/chat/completions'; +const HERMES_API_KEY = 'zhixi-hermes-key-2026'; +const SYSTEM_PROMPT = '你是知习管理后台的 AI 任务助理,帮助管理员处理日常任务、解答问题。请用简洁专业的中文回复。'; + @Injectable() export class AdminAiChatService { private readonly logger = new Logger(AdminAiChatService.name); @@ -14,11 +18,48 @@ export class AdminAiChatService { const messages = hasSystemPrompt ? dto.messages - : [ - { role: 'system' as const, content: '你是知习管理后台的 AI 任务助理,帮助管理员处理日常任务、解答问题。请用简洁专业的中文回复。' }, - ...dto.messages, - ]; + : [{ role: 'system' as const, content: SYSTEM_PROMPT }, ...dto.messages]; + // Try Hermes Agent first, fall back to DeepSeek + try { + return await this.callHermes(messages); + } catch (err: any) { + this.logger.warn('Hermes unavailable, falling back to DeepSeek: ' + err.message); + return await this.callDeepSeek(messages); + } + } + + private async callHermes(messages: Array<{ role: string; content: string }>) { + const start = Date.now(); + const resp = await fetch(HERMES_API_URL, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: 'Bearer ' + HERMES_API_KEY, + }, + body: JSON.stringify({ + model: 'hermes-agent', + messages, + temperature: 0.7, + max_tokens: 4096, + }), + signal: AbortSignal.timeout(120_000), + }); + + if (!resp.ok) { + throw new Error('Hermes returned ' + resp.status); + } + + const data = await resp.json(); + const content = data.choices?.[0]?.message?.content || ''; + const usage = data.usage || {}; + + this.logger.log('Hermes chat: ' + (Date.now() - start) + 'ms, tokens: ' + + (usage.prompt_tokens || 0) + '/' + (usage.completion_tokens || 0)); + return { content, usage: { model: 'hermes-agent', inputTokens: usage.prompt_tokens, outputTokens: usage.completion_tokens } }; + } + + private async callDeepSeek(messages: Array<{ role: string; content: string }>) { const start = Date.now(); const result = await this.deepseek.generate({ model: 'deepseek-chat', @@ -26,20 +67,15 @@ export class AdminAiChatService { temperature: 0.7, maxTokens: 4096, }); - - this.logger.log(`AI chat completed in ${Date.now() - start}ms, tokens: ${result.usage?.inputTokens ?? 0}/${result.usage?.outputTokens ?? 0}`); - - return { - content: result.rawText, - usage: result.usage, - }; + this.logger.log('DeepSeek chat: ' + (Date.now() - start) + 'ms'); + return { content: result.rawText, usage: result.usage }; } getDashboardConfig() { return { url: 'http://10.2.0.7:9119', - token: 'v8dAkvcsHaHe_yok5kjO0QErKtogQcq3IKaJT8PNczQ', - description: 'Hermes Agent Dashboard — 4核4G 上的 AI Agent,可执行服务器管理、文件操作等高级任务', + apiUrl: 'http://10.2.0.7:8642/v1', + description: 'Hermes Agent Dashboard — 4核4G 上的 AI Agent', }; } } \ No newline at end of file