feat(ai): 添加 AI 服务适配器管理器和新接口

- 新增 AiAdapterManager 类,用于管理和初始化不同 AI 服务适配器
- 添加 AiServiceAdapter 接口和两个实现类:DeepSeekAdapter 和 TongyiAdapter
- 在 AiConfig 实体中增加 provider 字段,用于标识 AI 服务提供商
- 新增 ai-config 模块,负责 AI 配置的管理和存储
- 在 ai 服务中集成适配器管理器,支持动态获取不同 AI 服务的适配器
- 更新 ai 控制器,添加获取适配器信息的接口
This commit is contained in:
程广 2025-06-10 18:21:24 +08:00
parent ae7c88d213
commit 6473395f86
12 changed files with 169 additions and 18 deletions

View File

@ -6,3 +6,4 @@
1. 语言TypeScript
2. nodejs 使用版本v22
3. 执行node, npm 相关命令时先执行`nvm use v22`切换到v22版本
4. dev环境运行命令是`npm run dev`

View File

@ -0,0 +1,38 @@
import { AiConfig } from './ai-config.entity';
import { AiServiceAdapter } from './ai.adapter';
import { DeepSeekAdapter } from './deepseek.adapter';
import { TongyiAdapter } from './tongyi.adapter';
export class AiAdapterManager {
private adapters: Map<string, AiServiceAdapter> = new Map();
constructor(private readonly aiConfigs: AiConfig[]) {
this.initializeAdapters();
}
private initializeAdapters() {
this.aiConfigs?.forEach(config => {
// 确保config.id是字符串类型
const serviceId = config.id.toString();
switch (config.provider) {
case 'deepseek':
this.adapters.set(serviceId, new DeepSeekAdapter(config));
break;
case 'tongyi':
this.adapters.set(serviceId, new TongyiAdapter(config));
break;
default:
throw new Error(`Unsupported AI provider: ${config.provider}`);
}
});
}
getAdapter(serviceId: string): AiServiceAdapter {
const adapter = this.adapters.get(serviceId);
if (!adapter) {
throw new Error(`AI adapter not found for service ID: ${serviceId}`);
}
return adapter;
}
}

View File

@ -12,6 +12,10 @@ export class AiConfig {
@Column()
apiKey!: string;
// 新增provider字段用于标识AI服务提供商
@Column({ type: 'enum', enum: ['deepseek', 'tongyi'] })
provider!: 'deepseek' | 'tongyi';
@OneToOne(() => Workspace)
@JoinColumn()
workspace!: Workspace;

View File

@ -0,0 +1,22 @@
import { Module } from '@nestjs/common';
import { AiConfigService } from './ai-config.service';
import { AiConfigController } from './ai-config.controller';
import { WorkspaceModule } from '../workspace/workspace.module';
import { AiConfigRepository } from './ai-config.repository';
import { TypeOrmModule } from '@nestjs/typeorm';
import { AiConfig } from './ai-config.entity';
import { WorkspaceRepository } from '../workspace/workspace.repository';
import { JwtStrategy } from '@src/auth';
@Module({
imports: [WorkspaceModule, TypeOrmModule.forFeature([AiConfig])],
providers: [
AiConfigService,
AiConfigRepository,
WorkspaceRepository,
JwtStrategy
],
controllers: [AiConfigController],
exports: [AiConfigService]
})
export class AiConfigModule {}

View File

@ -0,0 +1,34 @@
import { AiConfig } from "./ai-config.entity";
export interface AiServiceAdapter {
generateText(model: string, prompt: string, config?: Record<string, any>): Promise<string>;
chat(model: string, messages: Array<{role: string, content: string}>, config?: Record<string, any>): Promise<string>;
}
export class DeepSeekAdapter implements AiServiceAdapter {
constructor(private readonly config: AiConfig) {}
async generateText(model: string, prompt: string): Promise<string> {
// 实现DeepSeek的文本生成逻辑
return `Generated text by ${model}: ${prompt}`;
}
async chat(model: string, messages: Array<{role: string, content: string}>): Promise<string> {
// 实现DeepSeek的对话交互逻辑
return `Chat response from ${model}: ${JSON.stringify(messages)}`;
}
}
export class TongyiAdapter implements AiServiceAdapter {
constructor(private readonly config: AiConfig) {}
async generateText(model: string, prompt: string): Promise<string> {
// 实现通义千问的文本生成逻辑
return `Tongyi generated text: ${prompt}`;
}
async chat(model: string, messages: Array<{role: string, content: string}>): Promise<string> {
// 实现通义千问的对话交互逻辑
return `Tongyi chat response: ${JSON.stringify(messages)}`;
}
}

View File

@ -1,4 +1,4 @@
import { Controller, Post, Body, UseGuards } from '@nestjs/common';
import { Controller, Post, Body, UseGuards, Get, Param } from '@nestjs/common';
import { AiService } from './ai.service';
import { JwtAuthGuard } from '../auth/jwt-auth.guard';
@ -11,4 +11,10 @@ export class AiController {
generateCode(@Body() body: { prompt: string; workspaceId: number }) {
return this.aiService.generateCode(body.prompt, body.workspaceId);
}
@Get('adapter/:serviceId')
getAdapterInfo(@Param('serviceId') serviceId: string) {
const adapter = this.aiService.getAdapter(serviceId);
return { provider: adapter.constructor.name };
}
}

View File

@ -1,22 +1,15 @@
import { Module } from '@nestjs/common';
import { AiConfigService } from './ai-config.service';
import { AiConfigController } from './ai-config.controller';
import { WorkspaceModule } from '../workspace/workspace.module';
import { AiConfigRepository } from './ai-config.repository';
import { TypeOrmModule } from '@nestjs/typeorm';
import { AiConfig } from './ai-config.entity';
import { WorkspaceRepository } from '../workspace/workspace.repository'; // 新增导入
import { JwtStrategy } from '@src/auth';
import { AiService } from './ai.service';
import { AiController } from './ai.controller';
import { AiAdapterManager } from './ai-adapter.manager';
@Module({
imports: [WorkspaceModule, TypeOrmModule.forFeature([AiConfig])],
providers: [
AiConfigService,
AiConfigRepository,
WorkspaceRepository, // 添加缺失的依赖
JwtStrategy
],
controllers: [AiConfigController],
exports: [AiConfigService]
imports: [TypeOrmModule.forFeature([AiConfig])],
providers: [AiService, AiAdapterManager],
controllers: [AiController],
exports: [AiService]
})
export class AiModule {}

View File

@ -2,19 +2,38 @@ import { Injectable } from '@nestjs/common';
import { HttpService } from '@nestjs/axios';
import { ConfigService } from '@nestjs/config';
import { AiConfigService } from './ai-config.service';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { AiConfig } from './ai-config.entity';
import { AiAdapterManager } from './ai-adapter.manager';
@Injectable()
export class AiService {
private readonly defaultModel: string;
private adapterManager!: AiAdapterManager;
constructor(
private readonly httpService: HttpService,
private readonly configService: ConfigService,
private readonly aiConfigService: AiConfigService,
@InjectRepository(AiConfig)
private aiConfigRepository: Repository<AiConfig>,
) {
this.defaultModel = this.configService.get<string>('AI_DEFAULT_MODEL', 'gpt-3.5-turbo');
}
async initializeAdapterManager() {
const configs = await this.aiConfigRepository.find();
this.adapterManager = new AiAdapterManager(configs);
}
getAdapter(serviceId: string) {
if (!this.adapterManager) {
throw new Error('AI adapter manager not initialized');
}
return this.adapterManager.getAdapter(serviceId);
}
async generateCode(prompt: string, workspaceId: number) {
// 获取工作区的AI配置
const aiConfig = await this.aiConfigService.getAiConfigByWorkspace(workspaceId);

View File

@ -0,0 +1,16 @@
import { AiServiceAdapter } from './ai.adapter';
export class DeepSeekAdapter implements AiServiceAdapter {
constructor(private readonly config: any) {}
// 实现AiServiceAdapter接口定义的方法
async generateText(model: string, prompt: string, config?: Record<string, any>): Promise<string> {
// 这里添加调用DeepSeek API的具体实现
return `Response from DeepSeek: ${prompt}`;
}
async chat(model: string, messages: Array<{role: string, content: string}>, config?: Record<string, any>): Promise<string> {
// 这里添加调用DeepSeek API的具体实现
return `Chat response from DeepSeek: ${messages[messages.length - 1].content}`;
}
}

View File

@ -0,0 +1,16 @@
import { AiServiceAdapter } from './ai.adapter';
export class TongyiAdapter implements AiServiceAdapter {
constructor(private readonly config: any) {}
// 实现AiServiceAdapter接口定义的方法
async generateText(model: string, prompt: string, config?: Record<string, any>): Promise<string> {
// 这里添加调用Tongyi API的具体实现
return `Response from Tongyi: ${prompt}`;
}
async chat(model: string, messages: Array<{role: string, content: string}>, config?: Record<string, any>): Promise<string> {
// 这里添加调用Tongyi API的具体实现
return `Chat response from Tongyi: ${messages[messages.length - 1].content}`;
}
}

View File

@ -13,7 +13,9 @@
"forceConsistentCasingInFileNames": true,
"baseUrl": ".",
"paths": {
"@src/*": ["./src/*"]
"@src/*": ["./src/*"],
"./deepseek.adapter": ["./src/ai/deepseek.adapter"],
"./tongyi.adapter": ["./src/ai/tongyi.adapter"]
}
},
"include": ["src/**/*"]

View File

@ -1,7 +1,7 @@
# 项目状态报告
## 日期
2023-10-05
2025-06-09
## 已完成功能
1. 基础架构搭建