|
|
const { v4: uuidv4 } = require("uuid"); |
|
|
const { Document } = require("../../../models/documents"); |
|
|
const { Telemetry } = require("../../../models/telemetry"); |
|
|
const { DocumentVectors } = require("../../../models/vectors"); |
|
|
const { Workspace } = require("../../../models/workspace"); |
|
|
const { WorkspaceChats } = require("../../../models/workspaceChats"); |
|
|
const { getVectorDbClass, getLLMProvider } = require("../../../utils/helpers"); |
|
|
const { multiUserMode, reqBody } = require("../../../utils/http"); |
|
|
const { validApiKey } = require("../../../utils/middleware/validApiKey"); |
|
|
const { VALID_CHAT_MODE } = require("../../../utils/chats/stream"); |
|
|
const { EventLogs } = require("../../../models/eventLogs"); |
|
|
const { |
|
|
convertToChatHistory, |
|
|
writeResponseChunk, |
|
|
} = require("../../../utils/helpers/chat/responses"); |
|
|
const { ApiChatHandler } = require("../../../utils/chats/apiChatHandler"); |
|
|
const { getModelTag } = require("../../utils"); |
|
|
|
|
|
function apiWorkspaceEndpoints(app) { |
|
|
if (!app) return; |
|
|
|
|
|
app.post("/v1/workspace/new", [validApiKey], async (request, response) => { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
const { name = null, ...additionalFields } = reqBody(request); |
|
|
const { workspace, message } = await Workspace.new( |
|
|
name, |
|
|
null, |
|
|
additionalFields |
|
|
); |
|
|
|
|
|
if (!workspace) { |
|
|
response.status(400).json({ workspace: null, message }); |
|
|
return; |
|
|
} |
|
|
|
|
|
await Telemetry.sendTelemetry("workspace_created", { |
|
|
multiUserMode: multiUserMode(response), |
|
|
LLMSelection: process.env.LLM_PROVIDER || "openai", |
|
|
Embedder: process.env.EMBEDDING_ENGINE || "inherit", |
|
|
VectorDbSelection: process.env.VECTOR_DB || "lancedb", |
|
|
TTSSelection: process.env.TTS_PROVIDER || "native", |
|
|
LLMModel: getModelTag(), |
|
|
}); |
|
|
await EventLogs.logEvent("api_workspace_created", { |
|
|
workspaceName: workspace?.name || "Unknown Workspace", |
|
|
}); |
|
|
response.status(200).json({ workspace, message }); |
|
|
} catch (e) { |
|
|
console.error(e.message, e); |
|
|
response.sendStatus(500).end(); |
|
|
} |
|
|
}); |
|
|
|
|
|
app.get("/v1/workspaces", [validApiKey], async (request, response) => { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
const workspaces = await Workspace._findMany({ |
|
|
where: {}, |
|
|
include: { |
|
|
threads: { |
|
|
select: { |
|
|
user_id: true, |
|
|
slug: true, |
|
|
name: true, |
|
|
}, |
|
|
}, |
|
|
}, |
|
|
}); |
|
|
response.status(200).json({ workspaces }); |
|
|
} catch (e) { |
|
|
console.error(e.message, e); |
|
|
response.sendStatus(500).end(); |
|
|
} |
|
|
}); |
|
|
|
|
|
app.get("/v1/workspace/:slug", [validApiKey], async (request, response) => { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
const { slug } = request.params; |
|
|
const workspace = await Workspace._findMany({ |
|
|
where: { |
|
|
slug: String(slug), |
|
|
}, |
|
|
include: { |
|
|
documents: true, |
|
|
threads: { |
|
|
select: { |
|
|
user_id: true, |
|
|
slug: true, |
|
|
}, |
|
|
}, |
|
|
}, |
|
|
}); |
|
|
|
|
|
response.status(200).json({ workspace }); |
|
|
} catch (e) { |
|
|
console.error(e.message, e); |
|
|
response.sendStatus(500).end(); |
|
|
} |
|
|
}); |
|
|
|
|
|
app.delete( |
|
|
"/v1/workspace/:slug", |
|
|
[validApiKey], |
|
|
async (request, response) => { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
const { slug = "" } = request.params; |
|
|
const VectorDb = getVectorDbClass(); |
|
|
const workspace = await Workspace.get({ slug }); |
|
|
|
|
|
if (!workspace) { |
|
|
response.sendStatus(400).end(); |
|
|
return; |
|
|
} |
|
|
|
|
|
const workspaceId = Number(workspace.id); |
|
|
await WorkspaceChats.delete({ workspaceId: workspaceId }); |
|
|
await DocumentVectors.deleteForWorkspace(workspaceId); |
|
|
await Document.delete({ workspaceId: workspaceId }); |
|
|
await Workspace.delete({ id: workspaceId }); |
|
|
|
|
|
await EventLogs.logEvent("api_workspace_deleted", { |
|
|
workspaceName: workspace?.name || "Unknown Workspace", |
|
|
}); |
|
|
try { |
|
|
await VectorDb["delete-namespace"]({ namespace: slug }); |
|
|
} catch (e) { |
|
|
console.error(e.message); |
|
|
} |
|
|
response.sendStatus(200).end(); |
|
|
} catch (e) { |
|
|
console.error(e.message, e); |
|
|
response.sendStatus(500).end(); |
|
|
} |
|
|
} |
|
|
); |
|
|
|
|
|
app.post( |
|
|
"/v1/workspace/:slug/update", |
|
|
[validApiKey], |
|
|
async (request, response) => { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
const { slug = null } = request.params; |
|
|
const data = reqBody(request); |
|
|
const currWorkspace = await Workspace.get({ slug }); |
|
|
|
|
|
if (!currWorkspace) { |
|
|
response.sendStatus(400).end(); |
|
|
return; |
|
|
} |
|
|
|
|
|
const { workspace, message } = await Workspace.update( |
|
|
currWorkspace.id, |
|
|
data |
|
|
); |
|
|
response.status(200).json({ workspace, message }); |
|
|
} catch (e) { |
|
|
console.error(e.message, e); |
|
|
response.sendStatus(500).end(); |
|
|
} |
|
|
} |
|
|
); |
|
|
|
|
|
app.get( |
|
|
"/v1/workspace/:slug/chats", |
|
|
[validApiKey], |
|
|
async (request, response) => { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
const { slug } = request.params; |
|
|
const { |
|
|
apiSessionId = null, |
|
|
limit = 100, |
|
|
orderBy = "asc", |
|
|
} = request.query; |
|
|
const workspace = await Workspace.get({ slug }); |
|
|
|
|
|
if (!workspace) { |
|
|
response.sendStatus(400).end(); |
|
|
return; |
|
|
} |
|
|
|
|
|
const validLimit = Math.max(1, parseInt(limit)); |
|
|
const validOrderBy = ["asc", "desc"].includes(orderBy) |
|
|
? orderBy |
|
|
: "asc"; |
|
|
|
|
|
const history = apiSessionId |
|
|
? await WorkspaceChats.forWorkspaceByApiSessionId( |
|
|
workspace.id, |
|
|
apiSessionId, |
|
|
validLimit, |
|
|
{ createdAt: validOrderBy } |
|
|
) |
|
|
: await WorkspaceChats.forWorkspace(workspace.id, validLimit, { |
|
|
createdAt: validOrderBy, |
|
|
}); |
|
|
response.status(200).json({ history: convertToChatHistory(history) }); |
|
|
} catch (e) { |
|
|
console.error(e.message, e); |
|
|
response.sendStatus(500).end(); |
|
|
} |
|
|
} |
|
|
); |
|
|
|
|
|
app.post( |
|
|
"/v1/workspace/:slug/update-embeddings", |
|
|
[validApiKey], |
|
|
async (request, response) => { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
const { slug = null } = request.params; |
|
|
const { adds = [], deletes = [] } = reqBody(request); |
|
|
const currWorkspace = await Workspace.get({ slug }); |
|
|
|
|
|
if (!currWorkspace) { |
|
|
response.sendStatus(400).end(); |
|
|
return; |
|
|
} |
|
|
|
|
|
await Document.removeDocuments(currWorkspace, deletes); |
|
|
await Document.addDocuments(currWorkspace, adds); |
|
|
const updatedWorkspace = await Workspace.get({ |
|
|
id: Number(currWorkspace.id), |
|
|
}); |
|
|
response.status(200).json({ workspace: updatedWorkspace }); |
|
|
} catch (e) { |
|
|
console.error(e.message, e); |
|
|
response.sendStatus(500).end(); |
|
|
} |
|
|
} |
|
|
); |
|
|
|
|
|
app.post( |
|
|
"/v1/workspace/:slug/update-pin", |
|
|
[validApiKey], |
|
|
async (request, response) => { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
const { slug = null } = request.params; |
|
|
const { docPath, pinStatus = false } = reqBody(request); |
|
|
const workspace = await Workspace.get({ slug }); |
|
|
|
|
|
const document = await Document.get({ |
|
|
workspaceId: workspace.id, |
|
|
docpath: docPath, |
|
|
}); |
|
|
if (!document) return response.sendStatus(404).end(); |
|
|
|
|
|
await Document.update(document.id, { pinned: pinStatus }); |
|
|
return response |
|
|
.status(200) |
|
|
.json({ message: "Pin status updated successfully" }) |
|
|
.end(); |
|
|
} catch (error) { |
|
|
console.error("Error processing the pin status update:", error); |
|
|
return response.status(500).end(); |
|
|
} |
|
|
} |
|
|
); |
|
|
|
|
|
app.post( |
|
|
"/v1/workspace/:slug/chat", |
|
|
[validApiKey], |
|
|
async (request, response) => { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
const { slug } = request.params; |
|
|
const { |
|
|
message, |
|
|
mode = "query", |
|
|
sessionId = null, |
|
|
attachments = [], |
|
|
reset = false, |
|
|
} = reqBody(request); |
|
|
const workspace = await Workspace.get({ slug: String(slug) }); |
|
|
|
|
|
if (!workspace) { |
|
|
response.status(400).json({ |
|
|
id: uuidv4(), |
|
|
type: "abort", |
|
|
textResponse: null, |
|
|
sources: [], |
|
|
close: true, |
|
|
error: `Workspace ${slug} is not a valid workspace.`, |
|
|
}); |
|
|
return; |
|
|
} |
|
|
|
|
|
if ((!message?.length || !VALID_CHAT_MODE.includes(mode)) && !reset) { |
|
|
response.status(400).json({ |
|
|
id: uuidv4(), |
|
|
type: "abort", |
|
|
textResponse: null, |
|
|
sources: [], |
|
|
close: true, |
|
|
error: !message?.length |
|
|
? "Message is empty" |
|
|
: `${mode} is not a valid mode.`, |
|
|
}); |
|
|
return; |
|
|
} |
|
|
|
|
|
const result = await ApiChatHandler.chatSync({ |
|
|
workspace, |
|
|
message, |
|
|
mode, |
|
|
user: null, |
|
|
thread: null, |
|
|
sessionId: !!sessionId ? String(sessionId) : null, |
|
|
attachments, |
|
|
reset, |
|
|
}); |
|
|
|
|
|
await Telemetry.sendTelemetry("sent_chat", { |
|
|
LLMSelection: |
|
|
workspace.chatProvider ?? process.env.LLM_PROVIDER ?? "openai", |
|
|
Embedder: process.env.EMBEDDING_ENGINE || "inherit", |
|
|
VectorDbSelection: process.env.VECTOR_DB || "lancedb", |
|
|
TTSSelection: process.env.TTS_PROVIDER || "native", |
|
|
}); |
|
|
await EventLogs.logEvent("api_sent_chat", { |
|
|
workspaceName: workspace?.name, |
|
|
chatModel: workspace?.chatModel || "System Default", |
|
|
}); |
|
|
return response.status(200).json({ ...result }); |
|
|
} catch (e) { |
|
|
console.error(e.message, e); |
|
|
response.status(500).json({ |
|
|
id: uuidv4(), |
|
|
type: "abort", |
|
|
textResponse: null, |
|
|
sources: [], |
|
|
close: true, |
|
|
error: e.message, |
|
|
}); |
|
|
} |
|
|
} |
|
|
); |
|
|
|
|
|
app.post( |
|
|
"/v1/workspace/:slug/stream-chat", |
|
|
[validApiKey], |
|
|
async (request, response) => { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
const { slug } = request.params; |
|
|
const { |
|
|
message, |
|
|
mode = "query", |
|
|
sessionId = null, |
|
|
attachments = [], |
|
|
reset = false, |
|
|
} = reqBody(request); |
|
|
const workspace = await Workspace.get({ slug: String(slug) }); |
|
|
|
|
|
if (!workspace) { |
|
|
response.status(400).json({ |
|
|
id: uuidv4(), |
|
|
type: "abort", |
|
|
textResponse: null, |
|
|
sources: [], |
|
|
close: true, |
|
|
error: `Workspace ${slug} is not a valid workspace.`, |
|
|
}); |
|
|
return; |
|
|
} |
|
|
|
|
|
if ((!message?.length || !VALID_CHAT_MODE.includes(mode)) && !reset) { |
|
|
response.status(400).json({ |
|
|
id: uuidv4(), |
|
|
type: "abort", |
|
|
textResponse: null, |
|
|
sources: [], |
|
|
close: true, |
|
|
error: !message?.length |
|
|
? "Message is empty" |
|
|
: `${mode} is not a valid mode.`, |
|
|
}); |
|
|
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(); |
|
|
|
|
|
await ApiChatHandler.streamChat({ |
|
|
response, |
|
|
workspace, |
|
|
message, |
|
|
mode, |
|
|
user: null, |
|
|
thread: null, |
|
|
sessionId: !!sessionId ? String(sessionId) : null, |
|
|
attachments, |
|
|
reset, |
|
|
}); |
|
|
await Telemetry.sendTelemetry("sent_chat", { |
|
|
LLMSelection: |
|
|
workspace.chatProvider ?? process.env.LLM_PROVIDER ?? "openai", |
|
|
Embedder: process.env.EMBEDDING_ENGINE || "inherit", |
|
|
VectorDbSelection: process.env.VECTOR_DB || "lancedb", |
|
|
TTSSelection: process.env.TTS_PROVIDER || "native", |
|
|
}); |
|
|
await EventLogs.logEvent("api_sent_chat", { |
|
|
workspaceName: workspace?.name, |
|
|
chatModel: workspace?.chatModel || "System Default", |
|
|
}); |
|
|
response.end(); |
|
|
} catch (e) { |
|
|
console.error(e.message, e); |
|
|
writeResponseChunk(response, { |
|
|
id: uuidv4(), |
|
|
type: "abort", |
|
|
textResponse: null, |
|
|
sources: [], |
|
|
close: true, |
|
|
error: e.message, |
|
|
}); |
|
|
response.end(); |
|
|
} |
|
|
} |
|
|
); |
|
|
|
|
|
app.post( |
|
|
"/v1/workspace/:slug/vector-search", |
|
|
[validApiKey], |
|
|
async (request, response) => { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
const { slug } = request.params; |
|
|
const { query, topN, scoreThreshold } = reqBody(request); |
|
|
const workspace = await Workspace.get({ slug: String(slug) }); |
|
|
|
|
|
if (!workspace) |
|
|
return response.status(400).json({ |
|
|
message: `Workspace ${slug} is not a valid workspace.`, |
|
|
}); |
|
|
|
|
|
if (!query?.length) |
|
|
return response.status(400).json({ |
|
|
message: "Query parameter cannot be empty.", |
|
|
}); |
|
|
|
|
|
const VectorDb = getVectorDbClass(); |
|
|
const hasVectorizedSpace = await VectorDb.hasNamespace(workspace.slug); |
|
|
const embeddingsCount = await VectorDb.namespaceCount(workspace.slug); |
|
|
|
|
|
if (!hasVectorizedSpace || embeddingsCount === 0) |
|
|
return response.status(200).json({ |
|
|
results: [], |
|
|
message: "No embeddings found for this workspace.", |
|
|
}); |
|
|
|
|
|
const parseSimilarityThreshold = () => { |
|
|
let input = parseFloat(scoreThreshold); |
|
|
if (isNaN(input) || input < 0 || input > 1) |
|
|
return workspace?.similarityThreshold ?? 0.25; |
|
|
return input; |
|
|
}; |
|
|
|
|
|
const parseTopN = () => { |
|
|
let input = Number(topN); |
|
|
if (isNaN(input) || input < 1) return workspace?.topN ?? 4; |
|
|
return input; |
|
|
}; |
|
|
|
|
|
const results = await VectorDb.performSimilaritySearch({ |
|
|
namespace: workspace.slug, |
|
|
input: String(query), |
|
|
LLMConnector: getLLMProvider(), |
|
|
similarityThreshold: parseSimilarityThreshold(), |
|
|
topN: parseTopN(), |
|
|
rerank: workspace?.vectorSearchMode === "rerank", |
|
|
}); |
|
|
|
|
|
response.status(200).json({ |
|
|
results: results.sources.map((source) => ({ |
|
|
id: source.id, |
|
|
text: source.text, |
|
|
metadata: { |
|
|
url: source.url, |
|
|
title: source.title, |
|
|
author: source.docAuthor, |
|
|
description: source.description, |
|
|
docSource: source.docSource, |
|
|
chunkSource: source.chunkSource, |
|
|
published: source.published, |
|
|
wordCount: source.wordCount, |
|
|
tokenCount: source.token_count_estimate, |
|
|
}, |
|
|
distance: source._distance, |
|
|
score: source.score, |
|
|
})), |
|
|
}); |
|
|
} catch (e) { |
|
|
console.error(e.message, e); |
|
|
response.sendStatus(500).end(); |
|
|
} |
|
|
} |
|
|
); |
|
|
} |
|
|
|
|
|
module.exports = { apiWorkspaceEndpoints }; |
|
|
|