| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091 |
- import { Router } from "express";
- import { z } from "zod";
- import { answerWithContext, answerWithContextStream } from "../../chat/chatChain.js";
- import { addMessage } from "../services/conversationsService.js";
- export const chatRouter = Router();
- const chatBodySchema = z.object({
- message: z.string().min(1),
- conversationId: z.coerce.number().int().positive().optional(),
- sessionId: z.string().min(1).optional(),
- model: z.string().min(1).optional(),
- options: z
- .object({
- temperature: z.number().min(0).max(2).optional(),
- top_p: z.number().min(0).max(1).optional()
- })
- .optional()
- });
- chatRouter.post("/", async (req, res, next) => {
- try {
- const body = chatBodySchema.parse(req.body);
- const result = await answerWithContext({
- message: body.message,
- conversationId: body.conversationId,
- options: body.options
- });
- const userId = req.user?.sub;
- if (userId && body.conversationId) {
- try {
- await Promise.all([
- addMessage(body.conversationId, { role: "user", content: body.message }),
- addMessage(body.conversationId, { role: "assistant", content: result.answer, sources: result.sources })
- ]);
- } catch (err) {
- console.error("[chat] falha ao salvar mensagem:", err);
- }
- }
- res.json(result);
- } catch (err) {
- next(err);
- }
- });
- chatRouter.post("/stream", async (req, res, next) => {
- let abortController;
- try {
- const body = chatBodySchema.parse(req.body);
- res.setHeader("Content-Type", "text/event-stream");
- res.setHeader("Cache-Control", "no-cache");
- res.setHeader("Connection", "keep-alive");
- res.setHeader("X-Accel-Buffering", "no");
- res.flushHeaders();
- abortController = new AbortController();
- res.on("close", () => abortController.abort());
- const result = await answerWithContextStream({
- message: body.message,
- conversationId: body.conversationId,
- options: body.options,
- signal: abortController.signal,
- onChunk: (delta) => {
- res.write(`data: ${JSON.stringify({ type: "delta", delta })}\n\n`);
- }
- });
- res.write(`data: ${JSON.stringify({ type: "sources", sources: result.sources })}\n\n`);
- res.write("data: [DONE]\n\n");
- res.end();
- const userId = req.user?.sub;
- if (userId && body.conversationId) {
- Promise.all([
- addMessage(body.conversationId, { role: "user", content: body.message }),
- addMessage(body.conversationId, { role: "assistant", content: result.answer, sources: result.sources })
- ]).catch((err) => console.error("[chat] falha ao salvar mensagem:", err));
- }
- } catch (err) {
- if (!res.headersSent) {
- next(err);
- } else if (err.name !== "AbortError") {
- res.write(`data: ${JSON.stringify({ type: "error", error: err.message })}\n\n`);
- res.end();
- }
- }
- });
|