fix: M2-02/06 audit — system KB seed + candidate Content Safety
Some checks failed
Deploy API Server / build-and-deploy (push) Failing after 19s
Some checks failed
Deploy API Server / build-and-deploy (push) Failing after 19s
- SystemKnowledgeBaseSeed: auto-creates built-in 新手引导知识库 - Content Safety check on candidate accept() and createCandidates() Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
0c07b59765
commit
3c242a807a
@ -1,14 +1,22 @@
|
|||||||
import { Injectable, NotFoundException } from '@nestjs/common';
|
import { Injectable, NotFoundException, Optional } from '@nestjs/common';
|
||||||
import { ImportCandidateRepository } from './import-candidate.repository';
|
import { ImportCandidateRepository } from './import-candidate.repository';
|
||||||
import { KnowledgeItemsRepository } from '../knowledge-items/knowledge-items.repository';
|
import { KnowledgeItemsRepository } from '../knowledge-items/knowledge-items.repository';
|
||||||
|
import { ContentSafetyService } from '../content-safety/content-safety.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ImportCandidateService {
|
export class ImportCandidateService {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly repository: ImportCandidateRepository,
|
private readonly repository: ImportCandidateRepository,
|
||||||
private readonly itemsRepo: KnowledgeItemsRepository,
|
private readonly itemsRepo: KnowledgeItemsRepository,
|
||||||
|
@Optional() private readonly safety?: ContentSafetyService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
private async checkSafety(title: string, content: string, userId: string): Promise<boolean> {
|
||||||
|
if (!this.safety) return true;
|
||||||
|
const check = await this.safety.check(title + ' ' + (content || '').slice(0, 200), { userId, contentType: 'candidate' });
|
||||||
|
return check.safe;
|
||||||
|
}
|
||||||
|
|
||||||
async findBySource(sourceId: string) {
|
async findBySource(sourceId: string) {
|
||||||
return this.repository.findBySource(sourceId);
|
return this.repository.findBySource(sourceId);
|
||||||
}
|
}
|
||||||
@ -23,6 +31,10 @@ export class ImportCandidateService {
|
|||||||
const candidate = await this.repository.findById(id);
|
const candidate = await this.repository.findById(id);
|
||||||
if (!candidate) throw new NotFoundException('候选知识点不存在');
|
if (!candidate) throw new NotFoundException('候选知识点不存在');
|
||||||
|
|
||||||
|
// Content safety check before accepting
|
||||||
|
const safe = await this.checkSafety(candidate.title, candidate.content || '', candidate.userId);
|
||||||
|
if (!safe) return { status: 'BLOCKED', reason: '内容安全审核未通过' };
|
||||||
|
|
||||||
await this.repository.updateStatus(id, 'ACCEPTED');
|
await this.repository.updateStatus(id, 'ACCEPTED');
|
||||||
|
|
||||||
// 生成 KnowledgeItem
|
// 生成 KnowledgeItem
|
||||||
@ -60,6 +72,13 @@ export class ImportCandidateService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async createCandidates(userId: string, knowledgeBaseId: string, sourceId: string, importId: string, candidates: Array<any>) {
|
async createCandidates(userId: string, knowledgeBaseId: string, sourceId: string, importId: string, candidates: Array<any>) {
|
||||||
return this.repository.createMany(userId, knowledgeBaseId, sourceId, importId, candidates);
|
// Filter out unsafe candidates
|
||||||
|
const safeCandidates = [];
|
||||||
|
for (const c of candidates) {
|
||||||
|
const safe = await this.checkSafety(c.title || '', c.content || '', userId);
|
||||||
|
if (safe) safeCandidates.push(c);
|
||||||
|
}
|
||||||
|
if (safeCandidates.length === 0) return { created: 0, filtered: candidates.length };
|
||||||
|
return this.repository.createMany(userId, knowledgeBaseId, sourceId, importId, safeCandidates);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,11 +2,12 @@ import { Module } from '@nestjs/common';
|
|||||||
import { KnowledgeBaseController } from './knowledge-base.controller';
|
import { KnowledgeBaseController } from './knowledge-base.controller';
|
||||||
import { KnowledgeBaseService } from './knowledge-base.service';
|
import { KnowledgeBaseService } from './knowledge-base.service';
|
||||||
import { KnowledgeBaseRepository } from './knowledge-base.repository';
|
import { KnowledgeBaseRepository } from './knowledge-base.repository';
|
||||||
|
import { SystemKnowledgeBaseSeed } from './system-kb.seed';
|
||||||
import { PrismaService } from '../../infrastructure/database/prisma.service';
|
import { PrismaService } from '../../infrastructure/database/prisma.service';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
controllers: [KnowledgeBaseController],
|
controllers: [KnowledgeBaseController],
|
||||||
providers: [KnowledgeBaseService, KnowledgeBaseRepository, PrismaService],
|
providers: [KnowledgeBaseService, KnowledgeBaseRepository, SystemKnowledgeBaseSeed, PrismaService],
|
||||||
exports: [KnowledgeBaseService],
|
exports: [KnowledgeBaseService],
|
||||||
})
|
})
|
||||||
export class KnowledgeBaseModule {}
|
export class KnowledgeBaseModule {}
|
||||||
|
|||||||
29
src/modules/knowledge-base/system-kb.seed.ts
Normal file
29
src/modules/knowledge-base/system-kb.seed.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import { Injectable, Logger, OnModuleInit } from '@nestjs/common';
|
||||||
|
import { PrismaService } from '../../infrastructure/database/prisma.service';
|
||||||
|
|
||||||
|
const SYSTEM_KB = {
|
||||||
|
id: 'system-builtin-kb',
|
||||||
|
userId: 'system',
|
||||||
|
title: '新手引导知识库',
|
||||||
|
description: '系统内置知识库,帮助新用户了解知习的使用方法',
|
||||||
|
status: 'active',
|
||||||
|
};
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class SystemKnowledgeBaseSeed implements OnModuleInit {
|
||||||
|
private readonly logger = new Logger(SystemKnowledgeBaseSeed.name);
|
||||||
|
|
||||||
|
constructor(private readonly prisma: PrismaService) {}
|
||||||
|
|
||||||
|
async onModuleInit() {
|
||||||
|
try {
|
||||||
|
await this.prisma.knowledgeBase.upsert({
|
||||||
|
where: { id: SYSTEM_KB.id },
|
||||||
|
update: {},
|
||||||
|
create: SYSTEM_KB,
|
||||||
|
});
|
||||||
|
} catch {
|
||||||
|
this.logger.warn('Failed to seed system knowledge base');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user