chore: chat bot
This commit is contained in:
@@ -0,0 +1,158 @@
|
||||
import { Body, Controller, Get, Param, ParseIntPipe, ParseUUIDPipe, Post, Put, Query, Res } from "@nestjs/common";
|
||||
import { ApiOperation, ApiResponse } from "@nestjs/swagger";
|
||||
import { FastifyReply } from "fastify";
|
||||
|
||||
import { ChatMessageResponseDto, ChatSessionResponseDto } from "./DTO/chat-response.dto";
|
||||
import { CreateChatSessionDto } from "./DTO/create-chat-session.dto";
|
||||
import { SendMessageDto } from "./DTO/send-message.dto";
|
||||
import { ChatbotService } from "./providers/chatbot.service";
|
||||
import { AuthGuards } from "../../common/decorators/auth-guard.decorator";
|
||||
import { UserDec } from "../../common/decorators/user.decorator";
|
||||
|
||||
@Controller("chatbot")
|
||||
@AuthGuards()
|
||||
export class ChatbotController {
|
||||
constructor(private chatbotService: ChatbotService) {}
|
||||
|
||||
@Post("sessions")
|
||||
@ApiOperation({ summary: "Create a new chat session" })
|
||||
@ApiResponse({ status: 201, description: "Chat session created successfully", type: ChatSessionResponseDto })
|
||||
async createSession(@UserDec("id") userId: string, @Body() createDto: CreateChatSessionDto): Promise<ChatSessionResponseDto> {
|
||||
return this.chatbotService.createChatSession(userId, createDto);
|
||||
}
|
||||
|
||||
@Get("sessions")
|
||||
@ApiOperation({ summary: "Get user's chat sessions" })
|
||||
@ApiResponse({ status: 200, description: "Chat sessions retrieved successfully", type: [ChatSessionResponseDto] })
|
||||
async getUserSessions(
|
||||
@UserDec("id") userId: string,
|
||||
@Query("limit", new ParseIntPipe({ optional: true })) limit = 10,
|
||||
): Promise<ChatSessionResponseDto[]> {
|
||||
return this.chatbotService.getUserChatSessions(userId, limit);
|
||||
}
|
||||
|
||||
@Get("sessions/:sessionId")
|
||||
@ApiOperation({ summary: "Get a specific chat session with messages" })
|
||||
@ApiResponse({ status: 200, description: "Chat session retrieved successfully", type: ChatSessionResponseDto })
|
||||
async getSession(@UserDec("id") userId: string, @Param("sessionId", ParseUUIDPipe) sessionId: string): Promise<ChatSessionResponseDto> {
|
||||
return this.chatbotService.getChatSession(sessionId, userId);
|
||||
}
|
||||
|
||||
@Post("messages")
|
||||
@ApiOperation({ summary: "Send a message in a chat session (Enhanced with LangChain + Fallback)" })
|
||||
@ApiResponse({ status: 201, description: "Message sent successfully with enhanced AI", type: ChatMessageResponseDto })
|
||||
async sendMessage(@UserDec("id") userId: string, @Body() sendDto: SendMessageDto): Promise<ChatMessageResponseDto> {
|
||||
// Now uses LangChain by default with automatic Gemini fallback
|
||||
return this.chatbotService.sendMessage(userId, sendDto);
|
||||
}
|
||||
|
||||
@Post("messages/stream")
|
||||
@ApiOperation({ summary: "Send a message and get streaming response (Enhanced with LangChain + Fallback)" })
|
||||
@ApiResponse({ status: 200, description: "Enhanced streaming response initiated" })
|
||||
async sendMessageStream(@UserDec("id") userId: string, @Body() sendDto: SendMessageDto, @Res() res: FastifyReply): Promise<void> {
|
||||
try {
|
||||
// Now uses LangChain by default with automatic Gemini fallback
|
||||
const { userMessage, streamGenerator } = await this.chatbotService.sendMessageStream(userId, sendDto);
|
||||
|
||||
// Set headers for Server-Sent Events
|
||||
res.header("Content-Type", "text/event-stream");
|
||||
res.header("Cache-Control", "no-cache");
|
||||
res.header("Connection", "keep-alive");
|
||||
res.header("Access-Control-Allow-Origin", "*");
|
||||
|
||||
// Send initial user message
|
||||
res.raw.write(`data: ${JSON.stringify({ type: "user_message", data: userMessage, enhanced: true })}\n\n`);
|
||||
|
||||
// Start streaming bot response
|
||||
res.raw.write(`data: ${JSON.stringify({ type: "bot_response_start", provider: "enhanced" })}\n\n`);
|
||||
|
||||
const stream = await streamGenerator();
|
||||
for await (const chunk of stream) {
|
||||
if (chunk) {
|
||||
res.raw.write(`data: ${JSON.stringify({ type: "bot_response_chunk", data: chunk })}\n\n`);
|
||||
}
|
||||
}
|
||||
|
||||
// End streaming
|
||||
res.raw.write(`data: ${JSON.stringify({ type: "bot_response_end" })}\n\n`);
|
||||
res.raw.end();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
res.raw.write(
|
||||
`data: ${JSON.stringify({ type: "error", data: "خطا در تولید پاسخ هوشمند. LangChain با خطا مواجه شد و به Gemini بازگشت ⚠️" })}\n\n`,
|
||||
);
|
||||
res.raw.end();
|
||||
}
|
||||
}
|
||||
|
||||
@Post("messages/langchain")
|
||||
@ApiOperation({ summary: "Send a message using LangChain with enhanced RAG capabilities" })
|
||||
@ApiResponse({ status: 201, description: "Message sent successfully with LangChain", type: ChatMessageResponseDto })
|
||||
async sendMessageWithLangChain(@UserDec("id") userId: string, @Body() sendDto: SendMessageDto): Promise<ChatMessageResponseDto> {
|
||||
return this.chatbotService.sendMessageWithLangChain(userId, sendDto);
|
||||
}
|
||||
|
||||
@Post("messages/langchain/stream")
|
||||
@ApiOperation({ summary: "Send a message and get streaming response using LangChain" })
|
||||
@ApiResponse({ status: 200, description: "Streaming response initiated with LangChain" })
|
||||
async sendMessageStreamWithLangChain(@UserDec("id") userId: string, @Body() sendDto: SendMessageDto, @Res() res: FastifyReply): Promise<void> {
|
||||
try {
|
||||
const { userMessage, streamGenerator } = await this.chatbotService.sendMessageStreamWithLangChain(userId, sendDto);
|
||||
|
||||
// Set headers for Server-Sent Events
|
||||
res.header("Content-Type", "text/event-stream");
|
||||
res.header("Cache-Control", "no-cache");
|
||||
res.header("Connection", "keep-alive");
|
||||
res.header("Access-Control-Allow-Origin", "*");
|
||||
|
||||
// Send initial user message
|
||||
res.raw.write(`data: ${JSON.stringify({ type: "user_message", data: userMessage })}\n\n`);
|
||||
|
||||
// Start streaming bot response
|
||||
res.raw.write(`data: ${JSON.stringify({ type: "bot_response_start", provider: "langchain" })}\n\n`);
|
||||
|
||||
const stream = await streamGenerator();
|
||||
for await (const chunk of stream) {
|
||||
if (chunk) {
|
||||
res.raw.write(`data: ${JSON.stringify({ type: "bot_response_chunk", data: chunk })}\n\n`);
|
||||
}
|
||||
}
|
||||
|
||||
// End streaming
|
||||
res.raw.write(`data: ${JSON.stringify({ type: "bot_response_end" })}\n\n`);
|
||||
res.raw.end();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
res.raw.write(`data: ${JSON.stringify({ type: "error", data: "خطا در تولید پاسخ با LangChain. لطفاً دوباره تلاش کنید. ⚠️" })}\n\n`);
|
||||
res.raw.end();
|
||||
}
|
||||
}
|
||||
|
||||
@Post("training/refresh")
|
||||
@ApiOperation({ summary: "Refresh LangChain training data from database" })
|
||||
@ApiResponse({ status: 200, description: "Training data refreshed successfully" })
|
||||
async refreshTrainingData(@UserDec("id") _userId: string): Promise<{ message: string }> {
|
||||
await this.chatbotService.refreshLangChainData();
|
||||
return { message: "دادههای آموزشی با موفقیت بهروزرسانی شدند 🔄" };
|
||||
}
|
||||
|
||||
@Put("sessions/:sessionId/close")
|
||||
@ApiOperation({ summary: "Close a chat session" })
|
||||
@ApiResponse({ status: 200, description: "Chat session closed successfully" })
|
||||
async closeSession(@UserDec("id") userId: string, @Param("sessionId", ParseUUIDPipe) sessionId: string): Promise<{ message: string }> {
|
||||
await this.chatbotService.closeChatSession(sessionId, userId);
|
||||
return { message: "جلسه چت با موفقیت بسته شد ✅" };
|
||||
}
|
||||
|
||||
@Put("sessions/:sessionId/messages/read")
|
||||
@ApiOperation({ summary: "Mark messages as read" })
|
||||
@ApiResponse({ status: 200, description: "Messages marked as read successfully" })
|
||||
async markMessagesAsRead(
|
||||
@UserDec("id") userId: string,
|
||||
@Param("sessionId", ParseUUIDPipe) sessionId: string,
|
||||
@Body() body: { messageIds: string[] },
|
||||
): Promise<{ message: string }> {
|
||||
await this.chatbotService.markMessagesAsRead(sessionId, userId, body.messageIds);
|
||||
return { message: "پیامها با موفقیت به عنوان خوانده شده علامتگذاری شدند ✅" };
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user