feat: #70 ChatSession 新增 knowledgeItemIds 字段,限定 AI 检索范围
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 46s
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 46s
- Prisma schema: ChatSession 加 knowledgeItemIds Json? 字段 - createSession: 接受可选 knowledgeItemIds 参数 - loadContext: 支持 itemIds 过滤,传入时只检索指定知识点 - sendMessage/sendMessageStream: 读取 session.knowledgeItemIds 传入 loadContext Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
6d0cc9b6dc
commit
17f16cea67
@ -1001,6 +1001,7 @@ model ChatSession {
|
||||
userId String
|
||||
knowledgeBaseId String
|
||||
title String @default("新对话") @db.VarChar(200)
|
||||
knowledgeItemIds Json? @default("[]")
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
|
||||
@ -13,8 +13,8 @@ export class RagChatController {
|
||||
|
||||
@Post('sessions')
|
||||
@ApiOperation({ summary: '创建对话' })
|
||||
async createSession(@CurrentUser() user: UserPayload, @Body() dto: { knowledgeBaseId: string; title?: string }) {
|
||||
return this.svc.createSession(String(user.id), dto.knowledgeBaseId, dto.title);
|
||||
async createSession(@CurrentUser() user: UserPayload, @Body() dto: { knowledgeBaseId: string; title?: string; knowledgeItemIds?: string[] }) {
|
||||
return this.svc.createSession(String(user.id), dto.knowledgeBaseId, dto.title, dto.knowledgeItemIds);
|
||||
}
|
||||
|
||||
@Get('sessions')
|
||||
|
||||
@ -17,9 +17,14 @@ export class RagChatService {
|
||||
@Optional() private readonly aiGateway?: AiGatewayService,
|
||||
) {}
|
||||
|
||||
async createSession(userId: string, knowledgeBaseId: string, title?: string) {
|
||||
async createSession(userId: string, knowledgeBaseId: string, title?: string, knowledgeItemIds?: string[]) {
|
||||
return this.prisma.chatSession.create({
|
||||
data: { userId, knowledgeBaseId, title: title || '新对话' },
|
||||
data: {
|
||||
userId,
|
||||
knowledgeBaseId,
|
||||
title: title || '新对话',
|
||||
knowledgeItemIds: knowledgeItemIds ?? [],
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@ -55,7 +60,8 @@ export class RagChatService {
|
||||
|
||||
// Retrieve knowledge base context
|
||||
this.logger.log(`RAG: kbId=${session.knowledgeBaseId}, content preview: ${content.substring(0, 30)}`);
|
||||
const context = await this.loadContext(session.knowledgeBaseId);
|
||||
const itemIds = (session as any).knowledgeItemIds as string[] | undefined;
|
||||
const context = await this.loadContext(session.knowledgeBaseId, itemIds?.length ? itemIds : undefined);
|
||||
this.logger.log(`RAG context: isEmpty=${context.isEmpty}, textLen=${context.text.length}, citations=${context.citations.length}, aiGateway=${!!this.aiGateway}`);
|
||||
|
||||
// Generate AI response
|
||||
@ -141,7 +147,8 @@ export class RagChatService {
|
||||
// Also auto-title in sendMessage (this is the sync method)
|
||||
|
||||
// Load context
|
||||
const context = await this.loadContext(session.knowledgeBaseId);
|
||||
const itemIds = (session as any).knowledgeItemIds as string[] | undefined;
|
||||
const context = await this.loadContext(session.knowledgeBaseId, itemIds?.length ? itemIds : undefined);
|
||||
if (!context.text) {
|
||||
yield { type: 'content', content: this.fallbackReply(true) };
|
||||
} else {
|
||||
@ -186,10 +193,14 @@ export class RagChatService {
|
||||
|
||||
// ── Private ──
|
||||
|
||||
private async loadContext(kbId: string) {
|
||||
private async loadContext(kbId: string, itemIds?: string[]) {
|
||||
try {
|
||||
const items = await this.prisma.knowledgeItem.findMany({
|
||||
where: { knowledgeBaseId: kbId, deletedAt: null },
|
||||
where: {
|
||||
knowledgeBaseId: kbId,
|
||||
deletedAt: null,
|
||||
...(itemIds && itemIds.length > 0 ? { id: { in: itemIds } } : {}),
|
||||
},
|
||||
select: { id: true, title: true, content: true, summary: true },
|
||||
orderBy: { updatedAt: 'desc' },
|
||||
take: 30,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user