diff --git a/.lingma/rules/project_rule.md b/.lingma/rules/project_rule.md index 35a81c3..e18624f 100644 --- a/.lingma/rules/project_rule.md +++ b/.lingma/rules/project_rule.md @@ -6,3 +6,4 @@ 1. 语言:TypeScript 2. nodejs 使用版本v22 3. 执行node, npm 相关命令时先执行`nvm use v22`切换到v22版本 +4. dev环境运行命令是`npm run dev` \ No newline at end of file diff --git a/backend/src/ai/ai-adapter.manager.ts b/backend/src/ai/ai-adapter.manager.ts new file mode 100644 index 0000000..1d418db --- /dev/null +++ b/backend/src/ai/ai-adapter.manager.ts @@ -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 = 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; + } +} \ No newline at end of file diff --git a/backend/src/ai/ai-config.entity.ts b/backend/src/ai/ai-config.entity.ts index d32da92..259767e 100644 --- a/backend/src/ai/ai-config.entity.ts +++ b/backend/src/ai/ai-config.entity.ts @@ -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; diff --git a/backend/src/ai/ai-config.module.ts b/backend/src/ai/ai-config.module.ts new file mode 100644 index 0000000..3151734 --- /dev/null +++ b/backend/src/ai/ai-config.module.ts @@ -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 {} \ No newline at end of file diff --git a/backend/src/ai/ai.adapter.ts b/backend/src/ai/ai.adapter.ts new file mode 100644 index 0000000..dbe58ec --- /dev/null +++ b/backend/src/ai/ai.adapter.ts @@ -0,0 +1,34 @@ +import { AiConfig } from "./ai-config.entity"; + +export interface AiServiceAdapter { + generateText(model: string, prompt: string, config?: Record): Promise; + chat(model: string, messages: Array<{role: string, content: string}>, config?: Record): Promise; +} + +export class DeepSeekAdapter implements AiServiceAdapter { + constructor(private readonly config: AiConfig) {} + + async generateText(model: string, prompt: string): Promise { + // 实现DeepSeek的文本生成逻辑 + return `Generated text by ${model}: ${prompt}`; + } + + async chat(model: string, messages: Array<{role: string, content: string}>): Promise { + // 实现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 { + // 实现通义千问的文本生成逻辑 + return `Tongyi generated text: ${prompt}`; + } + + async chat(model: string, messages: Array<{role: string, content: string}>): Promise { + // 实现通义千问的对话交互逻辑 + return `Tongyi chat response: ${JSON.stringify(messages)}`; + } +} \ No newline at end of file diff --git a/backend/src/ai/ai.controller.ts b/backend/src/ai/ai.controller.ts index 4e86547..d02a464 100644 --- a/backend/src/ai/ai.controller.ts +++ b/backend/src/ai/ai.controller.ts @@ -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 }; + } } \ No newline at end of file diff --git a/backend/src/ai/ai.module.ts b/backend/src/ai/ai.module.ts index c96ec76..8ec4c1a 100644 --- a/backend/src/ai/ai.module.ts +++ b/backend/src/ai/ai.module.ts @@ -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 {} \ No newline at end of file diff --git a/backend/src/ai/ai.service.ts b/backend/src/ai/ai.service.ts index 77c68d7..67fb398 100644 --- a/backend/src/ai/ai.service.ts +++ b/backend/src/ai/ai.service.ts @@ -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, ) { this.defaultModel = this.configService.get('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); diff --git a/backend/src/ai/deepseek.adapter.ts b/backend/src/ai/deepseek.adapter.ts new file mode 100644 index 0000000..530d99e --- /dev/null +++ b/backend/src/ai/deepseek.adapter.ts @@ -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): Promise { + // 这里添加调用DeepSeek API的具体实现 + return `Response from DeepSeek: ${prompt}`; + } + + async chat(model: string, messages: Array<{role: string, content: string}>, config?: Record): Promise { + // 这里添加调用DeepSeek API的具体实现 + return `Chat response from DeepSeek: ${messages[messages.length - 1].content}`; + } +} \ No newline at end of file diff --git a/backend/src/ai/tongyi.adapter.ts b/backend/src/ai/tongyi.adapter.ts new file mode 100644 index 0000000..f4a482a --- /dev/null +++ b/backend/src/ai/tongyi.adapter.ts @@ -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): Promise { + // 这里添加调用Tongyi API的具体实现 + return `Response from Tongyi: ${prompt}`; + } + + async chat(model: string, messages: Array<{role: string, content: string}>, config?: Record): Promise { + // 这里添加调用Tongyi API的具体实现 + return `Chat response from Tongyi: ${messages[messages.length - 1].content}`; + } +} \ No newline at end of file diff --git a/backend/tsconfig.json b/backend/tsconfig.json index 2bbb58b..dd6dab3 100644 --- a/backend/tsconfig.json +++ b/backend/tsconfig.json @@ -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/**/*"] diff --git a/docs/project/status.md b/docs/project/status.md index f40e37d..a8e4598 100644 --- a/docs/project/status.md +++ b/docs/project/status.md @@ -1,7 +1,7 @@ # 项目状态报告 ## 日期 -2023-10-05 +2025-06-09 ## 已完成功能 1. 基础架构搭建