|
|
const { v4: uuidv4 } = require("uuid"); |
|
|
const { reqBody, userFromSession, multiUserMode } = require("../utils/http"); |
|
|
const { validatedRequest } = require("../utils/middleware/validatedRequest"); |
|
|
const { Telemetry } = require("../models/telemetry"); |
|
|
const { streamChatWithWorkspace } = require("../utils/chats/stream"); |
|
|
const { |
|
|
ROLES, |
|
|
flexUserRoleValid, |
|
|
} = require("../utils/middleware/multiUserProtected"); |
|
|
const { EventLogs } = require("../models/eventLogs"); |
|
|
const { |
|
|
validWorkspaceAndThreadSlug, |
|
|
validWorkspaceSlug, |
|
|
} = require("../utils/middleware/validWorkspace"); |
|
|
const { writeResponseChunk } = require("../utils/helpers/chat/responses"); |
|
|
const { WorkspaceThread } = require("../models/workspaceThread"); |
|
|
const { User } = require("../models/user"); |
|
|
const truncate = require("truncate"); |
|
|
const { getModelTag } = require("./utils"); |
|
|
|
|
|
function chatEndpoints(app) { |
|
|
if (!app) return; |
|
|
|
|
|
app.post( |
|
|
"/workspace/:slug/stream-chat", |
|
|
[validatedRequest, flexUserRoleValid([ROLES.all]), validWorkspaceSlug], |
|
|
async (request, response) => { |
|
|
try { |
|
|
const user = await userFromSession(request, response); |
|
|
const { message, attachments = [] } = reqBody(request); |
|
|
const workspace = response.locals.workspace; |
|
|
|
|
|
if (!message?.length) { |
|
|
response.status(400).json({ |
|
|
id: uuidv4(), |
|
|
type: "abort", |
|
|
textResponse: null, |
|
|
sources: [], |
|
|
close: true, |
|
|
error: !message?.length ? "Message is empty." : null, |
|
|
}); |
|
|
return; |
|
|
} |
|
|
|
|
|
response.setHeader("Cache-Control", "no-cache"); |
|
|
response.setHeader("Content-Type", "text/event-stream"); |
|
|
response.setHeader("Access-Control-Allow-Origin", "*"); |
|
|
response.setHeader("Connection", "keep-alive"); |
|
|
response.flushHeaders(); |
|
|
|
|
|
if (multiUserMode(response) && !(await User.canSendChat(user))) { |
|
|
writeResponseChunk(response, { |
|
|
id: uuidv4(), |
|
|
type: "abort", |
|
|
textResponse: null, |
|
|
sources: [], |
|
|
close: true, |
|
|
error: `You have met your maximum 24 hour chat quota of ${user.dailyMessageLimit} chats. Try again later.`, |
|
|
}); |
|
|
return; |
|
|
} |
|
|
|
|
|
await streamChatWithWorkspace( |
|
|
response, |
|
|
workspace, |
|
|
message, |
|
|
workspace?.chatMode, |
|
|
user, |
|
|
null, |
|
|
attachments |
|
|
); |
|
|
await Telemetry.sendTelemetry("sent_chat", { |
|
|
multiUserMode: multiUserMode(response), |
|
|
LLMSelection: process.env.LLM_PROVIDER || "openai", |
|
|
Embedder: process.env.EMBEDDING_ENGINE || "inherit", |
|
|
VectorDbSelection: process.env.VECTOR_DB || "lancedb", |
|
|
multiModal: Array.isArray(attachments) && attachments?.length !== 0, |
|
|
TTSSelection: process.env.TTS_PROVIDER || "native", |
|
|
LLMModel: getModelTag(), |
|
|
}); |
|
|
|
|
|
await EventLogs.logEvent( |
|
|
"sent_chat", |
|
|
{ |
|
|
workspaceName: workspace?.name, |
|
|
chatModel: workspace?.chatModel || "System Default", |
|
|
}, |
|
|
user?.id |
|
|
); |
|
|
response.end(); |
|
|
} catch (e) { |
|
|
console.error(e); |
|
|
writeResponseChunk(response, { |
|
|
id: uuidv4(), |
|
|
type: "abort", |
|
|
textResponse: null, |
|
|
sources: [], |
|
|
close: true, |
|
|
error: e.message, |
|
|
}); |
|
|
response.end(); |
|
|
} |
|
|
} |
|
|
); |
|
|
|
|
|
app.post( |
|
|
"/workspace/:slug/thread/:threadSlug/stream-chat", |
|
|
[ |
|
|
validatedRequest, |
|
|
flexUserRoleValid([ROLES.all]), |
|
|
validWorkspaceAndThreadSlug, |
|
|
], |
|
|
async (request, response) => { |
|
|
try { |
|
|
const user = await userFromSession(request, response); |
|
|
const { message, attachments = [] } = reqBody(request); |
|
|
const workspace = response.locals.workspace; |
|
|
const thread = response.locals.thread; |
|
|
|
|
|
if (!message?.length) { |
|
|
response.status(400).json({ |
|
|
id: uuidv4(), |
|
|
type: "abort", |
|
|
textResponse: null, |
|
|
sources: [], |
|
|
close: true, |
|
|
error: !message?.length ? "Message is empty." : null, |
|
|
}); |
|
|
return; |
|
|
} |
|
|
|
|
|
response.setHeader("Cache-Control", "no-cache"); |
|
|
response.setHeader("Content-Type", "text/event-stream"); |
|
|
response.setHeader("Access-Control-Allow-Origin", "*"); |
|
|
response.setHeader("Connection", "keep-alive"); |
|
|
response.flushHeaders(); |
|
|
|
|
|
if (multiUserMode(response) && !(await User.canSendChat(user))) { |
|
|
writeResponseChunk(response, { |
|
|
id: uuidv4(), |
|
|
type: "abort", |
|
|
textResponse: null, |
|
|
sources: [], |
|
|
close: true, |
|
|
error: `You have met your maximum 24 hour chat quota of ${user.dailyMessageLimit} chats. Try again later.`, |
|
|
}); |
|
|
return; |
|
|
} |
|
|
|
|
|
await streamChatWithWorkspace( |
|
|
response, |
|
|
workspace, |
|
|
message, |
|
|
workspace?.chatMode, |
|
|
user, |
|
|
thread, |
|
|
attachments |
|
|
); |
|
|
|
|
|
|
|
|
await WorkspaceThread.autoRenameThread({ |
|
|
thread, |
|
|
workspace, |
|
|
user, |
|
|
newName: truncate(message, 22), |
|
|
onRename: (thread) => { |
|
|
writeResponseChunk(response, { |
|
|
action: "rename_thread", |
|
|
thread: { |
|
|
slug: thread.slug, |
|
|
name: thread.name, |
|
|
}, |
|
|
}); |
|
|
}, |
|
|
}); |
|
|
|
|
|
await Telemetry.sendTelemetry("sent_chat", { |
|
|
multiUserMode: multiUserMode(response), |
|
|
LLMSelection: process.env.LLM_PROVIDER || "openai", |
|
|
Embedder: process.env.EMBEDDING_ENGINE || "inherit", |
|
|
VectorDbSelection: process.env.VECTOR_DB || "lancedb", |
|
|
multiModal: Array.isArray(attachments) && attachments?.length !== 0, |
|
|
TTSSelection: process.env.TTS_PROVIDER || "native", |
|
|
LLMModel: getModelTag(), |
|
|
}); |
|
|
|
|
|
await EventLogs.logEvent( |
|
|
"sent_chat", |
|
|
{ |
|
|
workspaceName: workspace.name, |
|
|
thread: thread.name, |
|
|
chatModel: workspace?.chatModel || "System Default", |
|
|
}, |
|
|
user?.id |
|
|
); |
|
|
response.end(); |
|
|
} catch (e) { |
|
|
console.error(e); |
|
|
writeResponseChunk(response, { |
|
|
id: uuidv4(), |
|
|
type: "abort", |
|
|
textResponse: null, |
|
|
sources: [], |
|
|
close: true, |
|
|
error: e.message, |
|
|
}); |
|
|
response.end(); |
|
|
} |
|
|
} |
|
|
); |
|
|
} |
|
|
|
|
|
module.exports = { chatEndpoints }; |
|
|
|