Files
dzone-api/src/modules/chatbot/chatbot.controller.ts
T
2025-06-09 11:12:17 +03:30

149 lines
7.0 KiB
TypeScript

import { Body, Controller, Get, Param, Post, Put, Query, Res } from "@nestjs/common";
import { ApiOperation, ApiResponse } from "@nestjs/swagger";
import { FastifyReply } from "fastify";
import { CreateChatSessionDto } from "./DTO/create-chat-session.dto";
import { SendMessageDto } from "./DTO/send-message.dto";
import { SessionIdParamDto } from "./DTO/session-id.param.dto";
import { ChatbotService } from "./providers/chatbot.service";
import { AuthGuards } from "../../common/decorators/auth-guard.decorator";
import { UserDec } from "../../common/decorators/user.decorator";
import { PaginationDto } from "../../common/DTO/pagination.dto";
@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" })
createSession(@UserDec("id") userId: string, @Body() createDto: CreateChatSessionDto) {
return this.chatbotService.createChatSession(userId, createDto);
}
@Get("sessions")
@ApiOperation({ summary: "Get user's chat sessions" })
@ApiResponse({ status: 200, description: "Chat sessions retrieved successfully" })
getUserSessions(@UserDec("id") userId: string, @Query() queryDto: PaginationDto) {
return this.chatbotService.getUserChatSessions(userId, queryDto.limit);
}
@Get("sessions/:sessionId")
@ApiOperation({ summary: "Get a specific chat session with messages" })
@ApiResponse({ status: 200, description: "Chat session retrieved successfully" })
getSession(@UserDec("id") userId: string, @Param() param: SessionIdParamDto) {
return this.chatbotService.getChatSession(param.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" })
sendMessage(@UserDec("id") userId: string, @Body() sendDto: SendMessageDto) {
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("training/refresh")
@ApiOperation({ summary: "Refresh LangChain training data from database" })
@ApiResponse({ status: 200, description: "Training data refreshed successfully" })
refreshTrainingData(@UserDec("id") _userId: string) {
return this.chatbotService.refreshLangChainData();
}
@Put("sessions/:sessionId/close")
@ApiOperation({ summary: "Close a chat session" })
@ApiResponse({ status: 200, description: "Chat session closed successfully" })
closeSession(@UserDec("id") userId: string, @Param() param: SessionIdParamDto) {
return this.chatbotService.closeChatSession(param.sessionId, userId);
}
@Put("sessions/:sessionId/messages/read")
@ApiOperation({ summary: "Mark messages as read" })
@ApiResponse({ status: 200, description: "Messages marked as read successfully" })
markMessagesAsRead(@UserDec("id") userId: string, @Param() param: SessionIdParamDto, @Body() body: { messageIds: string[] }) {
return this.chatbotService.markMessagesAsRead(param.sessionId, userId, body.messageIds);
}
// @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 })
// 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();
// }
// }
}