iconsulting/packages/services/knowledge-service/src/adapters/inbound/knowledge.controller.ts

266 lines
5.8 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 {
Controller,
Get,
Post,
Put,
Delete,
Body,
Param,
Query,
HttpCode,
HttpStatus,
UploadedFile,
UseInterceptors,
BadRequestException,
} from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import { KnowledgeService } from '../../application/services/knowledge.service';
import { RAGService } from '../../application/services/rag.service';
import { TextExtractionService } from '../../application/services/text-extraction.service';
import { KnowledgeSource } from '../../domain/entities/knowledge-article.entity';
import {
CreateArticleDto,
UpdateArticleDto,
SearchArticlesDto,
RetrieveKnowledgeDto,
ImportArticlesDto,
FeedbackDto,
ExtractedTextResponse,
} from '../../application/dtos/knowledge.dto';
@Controller('knowledge')
export class KnowledgeController {
constructor(
private knowledgeService: KnowledgeService,
private ragService: RAGService,
private textExtractionService: TextExtractionService,
) {}
/**
* 创建文章
*/
@Post('articles')
@HttpCode(HttpStatus.CREATED)
async createArticle(@Body() dto: CreateArticleDto) {
const article = await this.knowledgeService.createArticle({
...dto,
source: KnowledgeSource.MANUAL,
});
return {
success: true,
data: article,
};
}
/**
* 上传文件并提取文本(两步流程的第一步)
* 返回提取的文本内容,管理员预览编辑后通过 createArticle 保存
*/
@Post('articles/upload')
@UseInterceptors(
FileInterceptor('file', {
limits: { fileSize: 200 * 1024 * 1024 },
}),
)
async uploadAndExtract(
@UploadedFile() file: Express.Multer.File,
): Promise<{ success: boolean; data: ExtractedTextResponse }> {
if (!file) {
throw new BadRequestException('未上传文件');
}
const extracted = await this.textExtractionService.extractText(file);
return {
success: true,
data: {
extractedText: extracted.text,
suggestedTitle: extracted.title,
wordCount: extracted.wordCount,
pageCount: extracted.pageCount,
},
};
}
/**
* 获取文章详情
*/
@Get('articles/:id')
async getArticle(@Param('id') id: string) {
const article = await this.knowledgeService.getArticle(id);
if (!article) {
return {
success: false,
error: 'Article not found',
};
}
return {
success: true,
data: article,
};
}
/**
* 获取文章列表
*/
@Get('articles')
async listArticles(
@Query('category') category?: string,
@Query('publishedOnly') publishedOnly?: string,
@Query('page') page?: string,
@Query('pageSize') pageSize?: string,
) {
const result = await this.knowledgeService.listArticles({
category,
publishedOnly: publishedOnly === 'true',
page: page ? parseInt(page) : 1,
pageSize: pageSize ? parseInt(pageSize) : 20,
});
return {
success: true,
data: result,
};
}
/**
* 更新文章
*/
@Put('articles/:id')
async updateArticle(
@Param('id') id: string,
@Body() dto: UpdateArticleDto,
) {
const article = await this.knowledgeService.updateArticle(id, dto);
return {
success: true,
data: article,
};
}
/**
* 删除文章
*/
@Delete('articles/:id')
@HttpCode(HttpStatus.NO_CONTENT)
async deleteArticle(@Param('id') id: string) {
await this.knowledgeService.deleteArticle(id);
}
/**
* 发布文章
*/
@Post('articles/:id/publish')
async publishArticle(@Param('id') id: string) {
await this.knowledgeService.publishArticle(id);
return {
success: true,
message: 'Article published',
};
}
/**
* 取消发布
*/
@Post('articles/:id/unpublish')
async unpublishArticle(@Param('id') id: string) {
await this.knowledgeService.unpublishArticle(id);
return {
success: true,
message: 'Article unpublished',
};
}
/**
* 搜索文章
*/
@Post('articles/search')
async searchArticles(@Body() dto: SearchArticlesDto) {
const results = await this.knowledgeService.searchArticles(dto);
return {
success: true,
data: results,
};
}
/**
* 记录反馈
*/
@Post('articles/:id/feedback')
async recordFeedback(
@Param('id') id: string,
@Body() dto: FeedbackDto,
) {
await this.knowledgeService.recordFeedback(id, dto.helpful);
return {
success: true,
message: 'Feedback recorded',
};
}
/**
* 批量导入
*/
@Post('articles/import')
async importArticles(@Body() dto: ImportArticlesDto) {
const result = await this.knowledgeService.importArticles(dto.articles);
return {
success: true,
data: result,
};
}
/**
* 获取统计信息
*/
@Get('statistics')
async getStatistics() {
const stats = await this.knowledgeService.getStatistics();
return {
success: true,
data: stats,
};
}
// ========== RAG检索接口 ==========
/**
* RAG知识检索供对话服务调用
*/
@Post('retrieve')
async retrieveKnowledge(@Body() dto: RetrieveKnowledgeDto) {
const result = await this.ragService.retrieve(dto);
return {
success: true,
data: result,
};
}
/**
* 检索并格式化为提示词
*/
@Post('retrieve/prompt')
async retrieveForPrompt(@Body() dto: RetrieveKnowledgeDto) {
const context = await this.ragService.retrieveForPrompt({
query: dto.query,
userId: dto.userId,
category: dto.category,
});
return {
success: true,
data: { context },
};
}
/**
* 检查是否离题
*/
@Post('check-off-topic')
async checkOffTopic(@Body() body: { query: string }) {
const result = await this.ragService.checkOffTopic(body.query);
return {
success: true,
data: result,
};
}
}