2023-11-03 20:50:56 +01:00
const { v4 : uuidv4 } = require ( "uuid" ) ;
2023-08-24 04:15:07 +02:00
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 } = require ( "../../../utils/helpers" ) ;
const { multiUserMode , reqBody } = require ( "../../../utils/http" ) ;
const { validApiKey } = require ( "../../../utils/middleware/validApiKey" ) ;
2024-08-21 23:47:06 +02:00
const { VALID _CHAT _MODE } = require ( "../../../utils/chats/stream" ) ;
[FEAT] Automated audit logging (#667)
* WIP event logging - new table for events and new settings view for viewing
* WIP add logging
* UI for log rows
* rename files to Logging to prevent getting gitignore
* add metadata for all logging events and colored badges in logs page
* remove unneeded comment
* cleanup namespace for logging
* clean up backend calls
* update logging to show to => from settings changes
* add logging for invitations, created, deleted, and accepted
* add logging for user created, updated, suspended, or removed
* add logging for workspace deleted
* add logging for chat logs exported
* add logging for API keys, LLM, embedder, vector db, embed chat, and reset button
* modify event logs
* update to event log types
* simplify rendering of event badges
---------
Co-authored-by: timothycarambat <rambat1010@gmail.com>
2024-02-07 00:21:40 +01:00
const { EventLogs } = require ( "../../../models/eventLogs" ) ;
2024-02-14 21:32:07 +01:00
const {
convertToChatHistory ,
writeResponseChunk ,
} = require ( "../../../utils/helpers/chat/responses" ) ;
2024-08-21 23:47:06 +02:00
const { ApiChatHandler } = require ( "../../../utils/chats/apiChatHandler" ) ;
2023-08-24 04:15:07 +02:00
function apiWorkspaceEndpoints ( app ) {
if ( ! app ) return ;
app . post ( "/v1/workspace/new" , [ validApiKey ] , async ( request , response ) => {
2023-09-28 23:00:03 +02:00
/ *
2023-08-24 04:15:07 +02:00
# swagger . tags = [ 'Workspaces' ]
# swagger . description = 'Create a new workspace'
# swagger . requestBody = {
2024-02-08 00:17:32 +01:00
description : 'JSON object containing new display name of workspace.' ,
required : true ,
type : 'object' ,
content : {
"application/json" : {
example : {
name : "My New Workspace" ,
2023-08-24 04:15:07 +02:00
}
}
}
2024-02-08 00:17:32 +01:00
}
2023-08-24 04:15:07 +02:00
# swagger . responses [ 200 ] = {
content : {
"application/json" : {
schema : {
type : 'object' ,
example : {
workspace : {
"id" : 79 ,
"name" : "Sample workspace" ,
"slug" : "sample-workspace" ,
"createdAt" : "2023-08-17 00:45:03" ,
"openAiTemp" : null ,
"lastUpdatedAt" : "2023-08-17 00:45:03" ,
"openAiHistory" : 20 ,
"openAiPrompt" : null
} ,
message : 'Workspace created'
}
}
2023-09-28 23:00:03 +02:00
}
2023-08-24 04:15:07 +02:00
}
2023-09-28 23:00:03 +02:00
}
2023-08-24 04:15:07 +02:00
# swagger . responses [ 403 ] = {
schema : {
"$ref" : "#/definitions/InvalidAPIKey"
}
}
* /
try {
const { name = null } = reqBody ( request ) ;
const { workspace , message } = await Workspace . new ( name ) ;
await Telemetry . sendTelemetry ( "workspace_created" , {
multiUserMode : multiUserMode ( response ) ,
LLMSelection : process . env . LLM _PROVIDER || "openai" ,
2023-12-07 17:53:37 +01:00
Embedder : process . env . EMBEDDING _ENGINE || "inherit" ,
2024-05-13 21:22:53 +02:00
VectorDbSelection : process . env . VECTOR _DB || "lancedb" ,
2024-08-07 20:09:51 +02:00
TTSSelection : process . env . TTS _PROVIDER || "native" ,
2023-08-24 04:15:07 +02:00
} ) ;
[FEAT] Automated audit logging (#667)
* WIP event logging - new table for events and new settings view for viewing
* WIP add logging
* UI for log rows
* rename files to Logging to prevent getting gitignore
* add metadata for all logging events and colored badges in logs page
* remove unneeded comment
* cleanup namespace for logging
* clean up backend calls
* update logging to show to => from settings changes
* add logging for invitations, created, deleted, and accepted
* add logging for user created, updated, suspended, or removed
* add logging for workspace deleted
* add logging for chat logs exported
* add logging for API keys, LLM, embedder, vector db, embed chat, and reset button
* modify event logs
* update to event log types
* simplify rendering of event badges
---------
Co-authored-by: timothycarambat <rambat1010@gmail.com>
2024-02-07 00:21:40 +01:00
await EventLogs . logEvent ( "api_workspace_created" , {
workspaceName : workspace ? . name || "Unknown Workspace" ,
} ) ;
2023-08-24 04:15:07 +02:00
response . status ( 200 ) . json ( { workspace , message } ) ;
} catch ( e ) {
2024-07-04 01:39:33 +02:00
console . error ( e . message , e ) ;
2023-08-24 04:15:07 +02:00
response . sendStatus ( 500 ) . end ( ) ;
}
} ) ;
app . get ( "/v1/workspaces" , [ validApiKey ] , async ( request , response ) => {
2023-09-28 23:00:03 +02:00
/ *
2023-08-24 04:15:07 +02:00
# swagger . tags = [ 'Workspaces' ]
# swagger . description = 'List all current workspaces'
# swagger . responses [ 200 ] = {
content : {
"application/json" : {
schema : {
type : 'object' ,
example : {
workspaces : [
{
"id" : 79 ,
"name" : "Sample workspace" ,
"slug" : "sample-workspace" ,
"createdAt" : "2023-08-17 00:45:03" ,
"openAiTemp" : null ,
"lastUpdatedAt" : "2023-08-17 00:45:03" ,
"openAiHistory" : 20 ,
2024-07-26 23:18:40 +02:00
"openAiPrompt" : null ,
"threads" : [ ]
2023-08-24 04:15:07 +02:00
}
] ,
}
}
2023-09-28 23:00:03 +02:00
}
2023-08-24 04:15:07 +02:00
}
2023-09-28 23:00:03 +02:00
}
2023-08-24 04:15:07 +02:00
# swagger . responses [ 403 ] = {
schema : {
"$ref" : "#/definitions/InvalidAPIKey"
}
}
* /
try {
2024-07-26 23:18:40 +02:00
const workspaces = await Workspace . _findMany ( {
where : { } ,
include : {
threads : {
select : {
user _id : true ,
slug : true ,
} ,
} ,
} ,
} ) ;
2023-08-24 04:15:07 +02:00
response . status ( 200 ) . json ( { workspaces } ) ;
} catch ( e ) {
2024-07-04 01:39:33 +02:00
console . error ( e . message , e ) ;
2023-08-24 04:15:07 +02:00
response . sendStatus ( 500 ) . end ( ) ;
}
} ) ;
app . get ( "/v1/workspace/:slug" , [ validApiKey ] , async ( request , response ) => {
2023-09-28 23:00:03 +02:00
/ *
2023-08-24 04:15:07 +02:00
# swagger . tags = [ 'Workspaces' ]
# swagger . description = 'Get a workspace by its unique slug.'
# swagger . parameters [ 'slug' ] = {
in : 'path' ,
description : 'Unique slug of workspace to find' ,
required : true ,
type : 'string'
}
# swagger . responses [ 200 ] = {
content : {
"application/json" : {
schema : {
type : 'object' ,
example : {
workspace : {
"id" : 79 ,
"name" : "My workspace" ,
"slug" : "my-workspace-123" ,
"createdAt" : "2023-08-17 00:45:03" ,
"openAiTemp" : null ,
"lastUpdatedAt" : "2023-08-17 00:45:03" ,
"openAiHistory" : 20 ,
"openAiPrompt" : null ,
2024-07-26 23:18:40 +02:00
"documents" : [ ] ,
"threads" : [ ]
2023-08-24 04:15:07 +02:00
}
}
}
2023-09-28 23:00:03 +02:00
}
2023-08-24 04:15:07 +02:00
}
2023-09-28 23:00:03 +02:00
}
2023-08-24 04:15:07 +02:00
# swagger . responses [ 403 ] = {
schema : {
"$ref" : "#/definitions/InvalidAPIKey"
}
}
* /
try {
const { slug } = request . params ;
2024-07-26 23:18:40 +02:00
const workspace = await Workspace . _findMany ( {
where : {
slug : String ( slug ) ,
} ,
include : {
documents : true ,
threads : {
select : {
user _id : true ,
slug : true ,
} ,
} ,
} ,
} ) ;
2023-08-24 04:15:07 +02:00
response . status ( 200 ) . json ( { workspace } ) ;
} catch ( e ) {
2024-07-04 01:39:33 +02:00
console . error ( e . message , e ) ;
2023-08-24 04:15:07 +02:00
response . sendStatus ( 500 ) . end ( ) ;
}
} ) ;
app . delete (
"/v1/workspace/:slug" ,
[ validApiKey ] ,
async ( request , response ) => {
2023-09-28 23:00:03 +02:00
/ *
2023-08-24 04:15:07 +02:00
# swagger . tags = [ 'Workspaces' ]
# swagger . description = 'Deletes a workspace by its slug.'
# swagger . parameters [ 'slug' ] = {
in : 'path' ,
description : 'Unique slug of workspace to delete' ,
required : true ,
type : 'string'
}
# swagger . responses [ 403 ] = {
schema : {
"$ref" : "#/definitions/InvalidAPIKey"
}
}
* /
try {
const { slug = "" } = request . params ;
const VectorDb = getVectorDbClass ( ) ;
2023-09-28 23:00:03 +02:00
const workspace = await Workspace . get ( { slug } ) ;
2023-08-24 04:15:07 +02:00
if ( ! workspace ) {
response . sendStatus ( 400 ) . end ( ) ;
return ;
}
2024-01-16 18:32:51 +01:00
const workspaceId = Number ( workspace . id ) ;
await WorkspaceChats . delete ( { workspaceId : workspaceId } ) ;
await DocumentVectors . deleteForWorkspace ( workspaceId ) ;
await Document . delete ( { workspaceId : workspaceId } ) ;
await Workspace . delete ( { id : workspaceId } ) ;
[FEAT] Automated audit logging (#667)
* WIP event logging - new table for events and new settings view for viewing
* WIP add logging
* UI for log rows
* rename files to Logging to prevent getting gitignore
* add metadata for all logging events and colored badges in logs page
* remove unneeded comment
* cleanup namespace for logging
* clean up backend calls
* update logging to show to => from settings changes
* add logging for invitations, created, deleted, and accepted
* add logging for user created, updated, suspended, or removed
* add logging for workspace deleted
* add logging for chat logs exported
* add logging for API keys, LLM, embedder, vector db, embed chat, and reset button
* modify event logs
* update to event log types
* simplify rendering of event badges
---------
Co-authored-by: timothycarambat <rambat1010@gmail.com>
2024-02-07 00:21:40 +01:00
await EventLogs . logEvent ( "api_workspace_deleted" , {
workspaceName : workspace ? . name || "Unknown Workspace" ,
} ) ;
2023-08-24 04:15:07 +02:00
try {
await VectorDb [ "delete-namespace" ] ( { namespace : slug } ) ;
} catch ( e ) {
console . error ( e . message ) ;
}
response . sendStatus ( 200 ) . end ( ) ;
} catch ( e ) {
2024-07-04 01:39:33 +02:00
console . error ( e . message , e ) ;
2023-08-24 04:15:07 +02:00
response . sendStatus ( 500 ) . end ( ) ;
}
}
) ;
app . post (
"/v1/workspace/:slug/update" ,
[ validApiKey ] ,
async ( request , response ) => {
2023-09-28 23:00:03 +02:00
/ *
2023-08-24 04:15:07 +02:00
# swagger . tags = [ 'Workspaces' ]
# swagger . description = 'Update workspace settings by its unique slug.'
# swagger . parameters [ 'slug' ] = {
in : 'path' ,
description : 'Unique slug of workspace to find' ,
required : true ,
type : 'string'
}
# swagger . requestBody = {
description : 'JSON object containing new settings to update a workspace. All keys are optional and will not update unless provided' ,
required : true ,
type : 'object' ,
content : {
"application/json" : {
example : {
"name" : 'Updated Workspace Name' ,
"openAiTemp" : 0.2 ,
"openAiHistory" : 20 ,
"openAiPrompt" : "Respond to all inquires and questions in binary - do not respond in any other format."
}
}
}
}
# swagger . responses [ 200 ] = {
content : {
"application/json" : {
schema : {
type : 'object' ,
example : {
workspace : {
"id" : 79 ,
"name" : "My workspace" ,
"slug" : "my-workspace-123" ,
"createdAt" : "2023-08-17 00:45:03" ,
"openAiTemp" : null ,
"lastUpdatedAt" : "2023-08-17 00:45:03" ,
"openAiHistory" : 20 ,
"openAiPrompt" : null ,
"documents" : [ ]
} ,
message : null ,
}
}
2023-09-28 23:00:03 +02:00
}
2023-08-24 04:15:07 +02:00
}
2023-09-28 23:00:03 +02:00
}
2023-08-24 04:15:07 +02:00
# swagger . responses [ 403 ] = {
schema : {
"$ref" : "#/definitions/InvalidAPIKey"
}
}
* /
try {
const { slug = null } = request . params ;
const data = reqBody ( request ) ;
2023-09-28 23:00:03 +02:00
const currWorkspace = await Workspace . get ( { slug } ) ;
2023-08-24 04:15:07 +02:00
if ( ! currWorkspace ) {
response . sendStatus ( 400 ) . end ( ) ;
return ;
}
const { workspace , message } = await Workspace . update (
currWorkspace . id ,
data
) ;
response . status ( 200 ) . json ( { workspace , message } ) ;
} catch ( e ) {
2024-07-04 01:39:33 +02:00
console . error ( e . message , e ) ;
2023-08-24 04:15:07 +02:00
response . sendStatus ( 500 ) . end ( ) ;
}
}
) ;
app . get (
"/v1/workspace/:slug/chats" ,
[ validApiKey ] ,
async ( request , response ) => {
2023-09-28 23:00:03 +02:00
/ *
2023-08-24 04:15:07 +02:00
# swagger . tags = [ 'Workspaces' ]
# swagger . description = 'Get a workspaces chats regardless of user by its unique slug.'
# swagger . parameters [ 'slug' ] = {
in : 'path' ,
description : 'Unique slug of workspace to find' ,
required : true ,
type : 'string'
}
# swagger . responses [ 200 ] = {
content : {
"application/json" : {
schema : {
type : 'object' ,
example : {
history : [
{
"role" : "user" ,
"content" : "What is AnythingLLM?" ,
"sentAt" : 1692851630
} ,
{
"role" : "assistant" ,
"content" : "AnythingLLM is a platform that allows you to convert notes, PDFs, and other source materials into a chatbot. It ensures privacy, cites its answers, and allows multiple people to interact with the same documents simultaneously. It is particularly useful for businesses to enhance the visibility and readability of various written communications such as SOPs, contracts, and sales calls. You can try it out with a free trial to see if it meets your business needs." ,
"sources" : [ { "source" : "object about source document and snippets used" } ]
}
]
}
}
2023-09-28 23:00:03 +02:00
}
2023-08-24 04:15:07 +02:00
}
2023-09-28 23:00:03 +02:00
}
2023-08-24 04:15:07 +02:00
# swagger . responses [ 403 ] = {
schema : {
"$ref" : "#/definitions/InvalidAPIKey"
}
}
* /
try {
const { slug } = request . params ;
2023-09-28 23:00:03 +02:00
const workspace = await Workspace . get ( { slug } ) ;
2023-08-24 04:15:07 +02:00
if ( ! workspace ) {
response . sendStatus ( 400 ) . end ( ) ;
return ;
}
const history = await WorkspaceChats . forWorkspace ( workspace . id ) ;
response . status ( 200 ) . json ( { history : convertToChatHistory ( history ) } ) ;
} catch ( e ) {
2024-07-04 01:39:33 +02:00
console . error ( e . message , e ) ;
2023-08-24 04:15:07 +02:00
response . sendStatus ( 500 ) . end ( ) ;
}
}
) ;
app . post (
"/v1/workspace/:slug/update-embeddings" ,
[ validApiKey ] ,
async ( request , response ) => {
2023-09-28 23:00:03 +02:00
/ *
2023-08-24 04:15:07 +02:00
# swagger . tags = [ 'Workspaces' ]
# swagger . description = 'Add or remove documents from a workspace by its unique slug.'
# swagger . parameters [ 'slug' ] = {
in : 'path' ,
description : 'Unique slug of workspace to find' ,
required : true ,
type : 'string'
}
# swagger . requestBody = {
description : 'JSON object of additions and removals of documents to add to update a workspace. The value should be the folder + filename with the exclusions of the top-level documents path.' ,
required : true ,
type : 'object' ,
content : {
"application/json" : {
example : {
2024-01-17 01:04:22 +01:00
adds : [ "custom-documents/my-pdf.pdf-hash.json" ] ,
deletes : [ "custom-documents/anythingllm.txt-hash.json" ]
2023-08-24 04:15:07 +02:00
}
}
}
}
# swagger . responses [ 200 ] = {
content : {
"application/json" : {
schema : {
type : 'object' ,
example : {
workspace : {
"id" : 79 ,
"name" : "My workspace" ,
"slug" : "my-workspace-123" ,
"createdAt" : "2023-08-17 00:45:03" ,
"openAiTemp" : null ,
"lastUpdatedAt" : "2023-08-17 00:45:03" ,
"openAiHistory" : 20 ,
"openAiPrompt" : null ,
"documents" : [ ]
} ,
message : null ,
}
}
2023-09-28 23:00:03 +02:00
}
2023-08-24 04:15:07 +02:00
}
2023-09-28 23:00:03 +02:00
}
2023-08-24 04:15:07 +02:00
# swagger . responses [ 403 ] = {
schema : {
"$ref" : "#/definitions/InvalidAPIKey"
}
}
* /
try {
const { slug = null } = request . params ;
const { adds = [ ] , deletes = [ ] } = reqBody ( request ) ;
2023-09-28 23:00:03 +02:00
const currWorkspace = await Workspace . get ( { slug } ) ;
2023-08-24 04:15:07 +02:00
if ( ! currWorkspace ) {
response . sendStatus ( 400 ) . end ( ) ;
return ;
}
await Document . removeDocuments ( currWorkspace , deletes ) ;
await Document . addDocuments ( currWorkspace , adds ) ;
2024-04-21 20:45:34 +02:00
const updatedWorkspace = await Workspace . get ( {
id : Number ( currWorkspace . id ) ,
} ) ;
2023-08-24 04:15:07 +02:00
response . status ( 200 ) . json ( { workspace : updatedWorkspace } ) ;
} catch ( e ) {
2024-07-04 01:39:33 +02:00
console . error ( e . message , e ) ;
2023-08-24 04:15:07 +02:00
response . sendStatus ( 500 ) . end ( ) ;
}
}
) ;
2023-09-29 22:45:35 +02:00
2024-05-19 19:47:47 +02:00
app . post (
"/v1/workspace/:slug/update-pin" ,
[ validApiKey ] ,
async ( request , response ) => {
/ *
# swagger . tags = [ 'Workspaces' ]
# swagger . description = 'Add or remove pin from a document in a workspace by its unique slug.'
# swagger . parameters [ 'slug' ] = {
in : 'path' ,
description : 'Unique slug of workspace to find' ,
required : true ,
type : 'string'
}
# swagger . requestBody = {
description : 'JSON object with the document path and pin status to update.' ,
required : true ,
type : 'object' ,
content : {
"application/json" : {
example : {
docPath : "custom-documents/my-pdf.pdf-hash.json" ,
pinStatus : true
}
}
}
}
# swagger . responses [ 200 ] = {
description : 'OK' ,
content : {
"application/json" : {
schema : {
type : 'object' ,
example : {
message : 'Pin status updated successfully'
}
}
}
}
}
# swagger . responses [ 404 ] = {
description : 'Document not found'
}
# swagger . responses [ 500 ] = {
description : 'Internal Server Error'
}
* /
try {
const { slug = null } = request . params ;
const { docPath , pinStatus = false } = reqBody ( request ) ;
const workspace = await Workspace . get ( { slug } ) ;
2024-05-19 20:20:23 +02:00
2024-05-19 19:47:47 +02:00
const document = await Document . get ( {
workspaceId : workspace . id ,
docpath : docPath ,
} ) ;
if ( ! document ) return response . sendStatus ( 404 ) . end ( ) ;
2024-05-19 20:20:23 +02:00
2024-05-19 19:47:47 +02:00
await Document . update ( document . id , { pinned : pinStatus } ) ;
2024-05-19 20:20:23 +02:00
return response
. status ( 200 )
. json ( { message : "Pin status updated successfully" } )
. end ( ) ;
2024-05-19 19:47:47 +02:00
} catch ( error ) {
console . error ( "Error processing the pin status update:" , error ) ;
return response . status ( 500 ) . end ( ) ;
}
}
) ;
2023-09-29 22:45:35 +02:00
app . post (
"/v1/workspace/:slug/chat" ,
[ validApiKey ] ,
async ( request , response ) => {
/ *
# swagger . tags = [ 'Workspaces' ]
# swagger . description = 'Execute a chat with a workspace'
# swagger . requestBody = {
2024-01-16 18:32:51 +01:00
description : 'Send a prompt to the workspace and the type of conversation (query or chat).<br/><b>Query:</b> Will not use LLM unless there are relevant sources from vectorDB & does not recall chat history.<br/><b>Chat:</b> Uses LLM general knowledge w/custom embeddings to produce output, uses rolling chat history.' ,
2023-09-29 22:45:35 +02:00
required : true ,
type : 'object' ,
content : {
"application/json" : {
example : {
message : "What is AnythingLLM?" ,
mode : "query | chat"
}
}
}
}
# swagger . responses [ 200 ] = {
content : {
"application/json" : {
schema : {
type : 'object' ,
example : {
id : 'chat-uuid' ,
type : "abort | textResponse" ,
textResponse : "Response to your query" ,
sources : [ { title : "anythingllm.txt" , chunk : "This is a context chunk used in the answer of the prompt by the LLM," } ] ,
close : true ,
error : "null | text string of the failure mode."
}
}
}
}
}
# swagger . responses [ 403 ] = {
schema : {
"$ref" : "#/definitions/InvalidAPIKey"
}
}
* /
try {
const { slug } = request . params ;
const { message , mode = "query" } = reqBody ( request ) ;
2024-08-21 23:47:06 +02:00
const workspace = await Workspace . get ( { slug : String ( slug ) } ) ;
2023-09-29 22:45:35 +02:00
if ( ! workspace ) {
2024-01-16 19:37:46 +01:00
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 ) ) {
response . status ( 400 ) . json ( {
id : uuidv4 ( ) ,
type : "abort" ,
textResponse : null ,
sources : [ ] ,
close : true ,
error : ! message ? . length
? "message parameter cannot be empty."
: ` ${ mode } is not a valid mode. ` ,
} ) ;
2023-09-29 22:45:35 +02:00
return ;
}
2024-08-21 23:47:06 +02:00
const result = await ApiChatHandler . chatSync ( {
workspace ,
message ,
mode ,
user : null ,
thread : null ,
} ) ;
2023-09-29 22:45:35 +02:00
await Telemetry . sendTelemetry ( "sent_chat" , {
2024-08-21 23:47:06 +02:00
LLMSelection :
workspace . chatProvider ? ? process . env . LLM _PROVIDER ? ? "openai" ,
2023-12-07 17:53:37 +01:00
Embedder : process . env . EMBEDDING _ENGINE || "inherit" ,
2024-05-13 21:22:53 +02:00
VectorDbSelection : process . env . VECTOR _DB || "lancedb" ,
2024-08-07 20:09:51 +02:00
TTSSelection : process . env . TTS _PROVIDER || "native" ,
2023-09-29 22:45:35 +02:00
} ) ;
[FEAT] Automated audit logging (#667)
* WIP event logging - new table for events and new settings view for viewing
* WIP add logging
* UI for log rows
* rename files to Logging to prevent getting gitignore
* add metadata for all logging events and colored badges in logs page
* remove unneeded comment
* cleanup namespace for logging
* clean up backend calls
* update logging to show to => from settings changes
* add logging for invitations, created, deleted, and accepted
* add logging for user created, updated, suspended, or removed
* add logging for workspace deleted
* add logging for chat logs exported
* add logging for API keys, LLM, embedder, vector db, embed chat, and reset button
* modify event logs
* update to event log types
* simplify rendering of event badges
---------
Co-authored-by: timothycarambat <rambat1010@gmail.com>
2024-02-07 00:21:40 +01:00
await EventLogs . logEvent ( "api_sent_chat" , {
workspaceName : workspace ? . name ,
chatModel : workspace ? . chatModel || "System Default" ,
} ) ;
2024-08-21 23:47:06 +02:00
return response . status ( 200 ) . json ( { ... result } ) ;
2023-09-29 22:45:35 +02:00
} catch ( e ) {
2024-07-04 01:39:33 +02:00
console . error ( e . message , e ) ;
2023-09-29 22:45:35 +02:00
response . status ( 500 ) . json ( {
id : uuidv4 ( ) ,
type : "abort" ,
textResponse : null ,
sources : [ ] ,
close : true ,
error : e . message ,
} ) ;
}
}
) ;
2024-01-16 19:37:46 +01:00
app . post (
"/v1/workspace/:slug/stream-chat" ,
[ validApiKey ] ,
async ( request , response ) => {
/ *
# swagger . tags = [ 'Workspaces' ]
# swagger . description = 'Execute a streamable chat with a workspace'
# swagger . requestBody = {
description : 'Send a prompt to the workspace and the type of conversation (query or chat).<br/><b>Query:</b> Will not use LLM unless there are relevant sources from vectorDB & does not recall chat history.<br/><b>Chat:</b> Uses LLM general knowledge w/custom embeddings to produce output, uses rolling chat history.' ,
required : true ,
type : 'object' ,
content : {
"application/json" : {
example : {
message : "What is AnythingLLM?" ,
mode : "query | chat"
}
}
}
}
# swagger . responses [ 200 ] = {
content : {
"text/event-stream" : {
schema : {
type : 'array' ,
example : [
{
id : 'uuid-123' ,
type : "abort | textResponseChunk" ,
textResponse : "First chunk" ,
sources : [ ] ,
close : false ,
error : "null | text string of the failure mode."
} ,
{
id : 'uuid-123' ,
type : "abort | textResponseChunk" ,
textResponse : "chunk two" ,
sources : [ ] ,
close : false ,
error : "null | text string of the failure mode."
} ,
{
id : 'uuid-123' ,
type : "abort | textResponseChunk" ,
textResponse : "final chunk of LLM output!" ,
sources : [ { title : "anythingllm.txt" , chunk : "This is a context chunk used in the answer of the prompt by the LLM. This will only return in the final chunk." } ] ,
close : true ,
error : "null | text string of the failure mode."
}
]
}
}
}
}
# swagger . responses [ 403 ] = {
schema : {
"$ref" : "#/definitions/InvalidAPIKey"
}
}
* /
try {
const { slug } = request . params ;
const { message , mode = "query" } = reqBody ( request ) ;
2024-08-21 23:47:06 +02:00
const workspace = await Workspace . get ( { slug : String ( slug ) } ) ;
2024-01-16 19:37:46 +01:00
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 ) ) {
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 ( ) ;
2024-08-21 23:47:06 +02:00
await ApiChatHandler . streamChat ( {
response ,
workspace ,
message ,
mode ,
user : null ,
thread : null ,
} ) ;
2024-01-16 19:37:46 +01:00
await Telemetry . sendTelemetry ( "sent_chat" , {
2024-08-21 23:47:06 +02:00
LLMSelection :
workspace . chatProvider ? ? process . env . LLM _PROVIDER ? ? "openai" ,
2024-01-16 19:37:46 +01:00
Embedder : process . env . EMBEDDING _ENGINE || "inherit" ,
2024-05-13 21:22:53 +02:00
VectorDbSelection : process . env . VECTOR _DB || "lancedb" ,
2024-08-07 20:09:51 +02:00
TTSSelection : process . env . TTS _PROVIDER || "native" ,
2024-01-16 19:37:46 +01:00
} ) ;
[FEAT] Automated audit logging (#667)
* WIP event logging - new table for events and new settings view for viewing
* WIP add logging
* UI for log rows
* rename files to Logging to prevent getting gitignore
* add metadata for all logging events and colored badges in logs page
* remove unneeded comment
* cleanup namespace for logging
* clean up backend calls
* update logging to show to => from settings changes
* add logging for invitations, created, deleted, and accepted
* add logging for user created, updated, suspended, or removed
* add logging for workspace deleted
* add logging for chat logs exported
* add logging for API keys, LLM, embedder, vector db, embed chat, and reset button
* modify event logs
* update to event log types
* simplify rendering of event badges
---------
Co-authored-by: timothycarambat <rambat1010@gmail.com>
2024-02-07 00:21:40 +01:00
await EventLogs . logEvent ( "api_sent_chat" , {
workspaceName : workspace ? . name ,
chatModel : workspace ? . chatModel || "System Default" ,
} ) ;
2024-01-16 19:37:46 +01:00
response . end ( ) ;
} catch ( e ) {
2024-07-04 01:39:33 +02:00
console . error ( e . message , e ) ;
2024-01-16 19:37:46 +01:00
writeResponseChunk ( response , {
id : uuidv4 ( ) ,
type : "abort" ,
textResponse : null ,
sources : [ ] ,
close : true ,
error : e . message ,
} ) ;
response . end ( ) ;
}
}
) ;
2023-08-24 04:15:07 +02:00
}
module . exports = { apiWorkspaceEndpoints } ;