feat: member portal Sprint 9 — Ask AI (RAG over message archive)
- AskAIQuery model + migration (logs question/answer/citations per member) - AskAIService: RAG pipeline — retrieve via tenant-isolated SearchService (Meili), ground LLM in top-8 snippets with inline [n] citations, degrade gracefully when OPENROUTER_API_KEY absent or no context (snippet fallback) - Shared api/common/llm-client.ts (mirrors worker's OpenRouter client) - SearchModule now exports SearchService - Member endpoints: GET/POST /my/ask (history + ask) - /my/ask page + AskChat client component: question box, answer cards with sources - Ask AI nav item (top of member nav) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,7 @@ import { Body, Controller, Delete, Get, Param, Patch, Post, Query } from '@nestj
|
||||
import { MyService } from './my.service';
|
||||
import { SevaService } from '../seva/seva.service';
|
||||
import { CirclesService } from '../circles/circles.service';
|
||||
import { AskAIService } from '../ask-ai/ask-ai.service';
|
||||
import { MemberAuth } from '../auth/member-auth.decorator';
|
||||
import { CurrentMember } from '../auth/current-member.decorator';
|
||||
import type { MemberJwtPayload } from '@tower/types';
|
||||
@@ -28,8 +29,19 @@ export class MyController {
|
||||
private readonly service: MyService,
|
||||
private readonly seva: SevaService,
|
||||
private readonly circles: CirclesService,
|
||||
private readonly askAI: AskAIService,
|
||||
) {}
|
||||
|
||||
@Get('ask')
|
||||
askHistory(@CurrentMember() member: MemberJwtPayload) {
|
||||
return this.askAI.history(member.sub, member.tenantId);
|
||||
}
|
||||
|
||||
@Post('ask')
|
||||
ask(@CurrentMember() member: MemberJwtPayload, @Body() body: { question: string }) {
|
||||
return this.askAI.ask(member.sub, member.tenantId, body.question);
|
||||
}
|
||||
|
||||
@Get('seva')
|
||||
sevaList(@CurrentMember() member: MemberJwtPayload) {
|
||||
return this.seva.listForMember(member.sub, member.tenantId);
|
||||
|
||||
@@ -5,9 +5,10 @@ import { AuthModule } from '../auth/auth.module';
|
||||
import { SevaModule } from '../seva/seva.module';
|
||||
import { GamificationModule } from '../gamification/gamification.module';
|
||||
import { CirclesModule } from '../circles/circles.module';
|
||||
import { AskAIModule } from '../ask-ai/ask-ai.module';
|
||||
|
||||
@Module({
|
||||
imports: [AuthModule, SevaModule, GamificationModule, CirclesModule],
|
||||
imports: [AuthModule, SevaModule, GamificationModule, CirclesModule, AskAIModule],
|
||||
controllers: [MyController],
|
||||
providers: [MyService],
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user