feat: P3c LLM集成层增强 (模型目录 + 用量统计 + getModelInfo)

This commit is contained in:
yuzhiran-dev
2026-05-18 12:10:17 +08:00
parent ed003d0ef0
commit 0ed017b212
2 changed files with 32 additions and 1 deletions
@@ -11,15 +11,32 @@ export interface ChatOptions {
max_tokens?: number;
}
export interface ModelInfo {
id: string;
provider: string;
capabilities: string[];
contextWindow: number;
}
interface AIProvider {
name: string;
chat(messages: ChatMessage[], options?: ChatOptions): Promise<string>;
}
const MODEL_CATALOG: Record<string, ModelInfo> = {
'general': { id: 'general', provider: 'OpenAI 兼容', capabilities: ['chat', 'code'], contextWindow: 8192 },
'openai': { id: 'openai', provider: 'OpenAI 兼容', capabilities: ['chat', 'code'], contextWindow: 8192 },
'gpt-3.5': { id: 'gpt-3.5', provider: 'OpenAI', capabilities: ['chat', 'code'], contextWindow: 16384 },
'gpt-4': { id: 'gpt-4', provider: 'OpenAI', capabilities: ['chat', 'code', 'vision'], contextWindow: 32768 },
'opencode-go': { id: 'opencode-go', provider: 'OpenCode Go', capabilities: ['chat', 'code'], contextWindow: 32768 },
'deepseek-v4-flash': { id: 'deepseek-v4-flash', provider: 'OpenCode Go', capabilities: ['chat', 'code'], contextWindow: 32768 },
}
@Injectable()
export class AIGatewayService {
private readonly logger = new Logger(AIGatewayService.name);
private providers: Map<string, AIProvider> = new Map();
private usageStats: Record<string, { total: number; success: number; failed: number }> = {};
constructor() {
this.registerProviders();
@@ -73,15 +90,20 @@ export class AIGatewayService {
const providerKey = modelMap[model.toLowerCase()] || (model.includes('/') ? 'openai' : model);
const provider = this.providers.get(providerKey);
if (!this.usageStats[providerKey]) this.usageStats[providerKey] = { total: 0, success: 0, failed: 0 };
this.usageStats[providerKey].total++;
if (provider) {
try {
const reply = await provider.chat(messages, options);
if (typeof reply !== 'string' || reply.length === 0) {
throw new Error(`AI 返回内容为空: ${JSON.stringify(reply)}`);
}
this.usageStats[providerKey].success++;
return reply;
} catch (err: any) {
this.logger.error(`${provider.name} 调用失败: ${err.message}`);
this.usageStats[providerKey].failed++;
return this.fallback(messages);
}
}
@@ -114,6 +136,15 @@ export class AIGatewayService {
return `我是宇之然 AI 助手。关于"${lastMsg.slice(0, 50)}..."的问题,我已收到。当前 AI 沙箱处于模拟模式,请配置 API Key 以获取真实回复。已配置的 API:${names}`;
}
getModelInfo(model: string): ModelInfo {
const key = model.toLowerCase();
return MODEL_CATALOG[key] || { id: model, provider: '未知', capabilities: ['chat'], contextWindow: 4096 };
}
getUsageStats() {
return { ...this.usageStats };
}
getRegisteredProviders(): string[] {
return Array.from(this.providers.keys());
}
File diff suppressed because one or more lines are too long