You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

276 lines
7.8 KiB

11 months ago
  1. const { EventLogs } = require("../../../models/eventLogs");
  2. const { SystemSettings } = require("../../../models/systemSettings");
  3. const { purgeDocument } = require("../../../utils/files/purgeDocument");
  4. const { getVectorDbClass } = require("../../../utils/helpers");
  5. const {
  6. prepareWorkspaceChatsForExport,
  7. exportChatsAsType,
  8. } = require("../../../utils/helpers/chat/convertTo");
  9. const { dumpENV, updateENV } = require("../../../utils/helpers/updateENV");
  10. const { reqBody } = require("../../../utils/http");
  11. const { validApiKey } = require("../../../utils/middleware/validApiKey");
  12. function apiSystemEndpoints(app) {
  13. if (!app) return;
  14. app.get("/v1/system/env-dump", async (_, response) => {
  15. /*
  16. #swagger.tags = ['System Settings']
  17. #swagger.description = 'Dump all settings to file storage'
  18. #swagger.responses[403] = {
  19. schema: {
  20. "$ref": "#/definitions/InvalidAPIKey"
  21. }
  22. }
  23. */
  24. try {
  25. if (process.env.NODE_ENV !== "production")
  26. return response.sendStatus(200).end();
  27. dumpENV();
  28. response.sendStatus(200).end();
  29. } catch (e) {
  30. console.error(e.message, e);
  31. response.sendStatus(500).end();
  32. }
  33. });
  34. app.get("/v1/system", [validApiKey], async (_, response) => {
  35. /*
  36. #swagger.tags = ['System Settings']
  37. #swagger.description = 'Get all current system settings that are defined.'
  38. #swagger.responses[200] = {
  39. content: {
  40. "application/json": {
  41. schema: {
  42. type: 'object',
  43. example: {
  44. "settings": {
  45. "VectorDB": "pinecone",
  46. "PineConeKey": true,
  47. "PineConeIndex": "my-pinecone-index",
  48. "LLMProvider": "azure",
  49. "[KEY_NAME]": "KEY_VALUE",
  50. }
  51. }
  52. }
  53. }
  54. }
  55. }
  56. #swagger.responses[403] = {
  57. schema: {
  58. "$ref": "#/definitions/InvalidAPIKey"
  59. }
  60. }
  61. */
  62. try {
  63. const settings = await SystemSettings.currentSettings();
  64. response.status(200).json({ settings });
  65. } catch (e) {
  66. console.error(e.message, e);
  67. response.sendStatus(500).end();
  68. }
  69. });
  70. app.get("/v1/system/vector-count", [validApiKey], async (_, response) => {
  71. /*
  72. #swagger.tags = ['System Settings']
  73. #swagger.description = 'Number of all vectors in connected vector database'
  74. #swagger.responses[200] = {
  75. content: {
  76. "application/json": {
  77. schema: {
  78. type: 'object',
  79. example: {
  80. "vectorCount": 5450
  81. }
  82. }
  83. }
  84. }
  85. }
  86. #swagger.responses[403] = {
  87. schema: {
  88. "$ref": "#/definitions/InvalidAPIKey"
  89. }
  90. }
  91. */
  92. try {
  93. const VectorDb = getVectorDbClass();
  94. const vectorCount = await VectorDb.totalVectors();
  95. response.status(200).json({ vectorCount });
  96. } catch (e) {
  97. console.error(e.message, e);
  98. response.sendStatus(500).end();
  99. }
  100. });
  101. app.post(
  102. "/v1/system/update-env",
  103. [validApiKey],
  104. async (request, response) => {
  105. /*
  106. #swagger.tags = ['System Settings']
  107. #swagger.description = 'Update a system setting or preference.'
  108. #swagger.requestBody = {
  109. description: 'Key pair object that matches a valid setting and value. Get keys from GET /v1/system or refer to codebase.',
  110. required: true,
  111. content: {
  112. "application/json": {
  113. example: {
  114. VectorDB: "lancedb",
  115. AnotherKey: "updatedValue"
  116. }
  117. }
  118. }
  119. }
  120. #swagger.responses[200] = {
  121. content: {
  122. "application/json": {
  123. schema: {
  124. type: 'object',
  125. example: {
  126. newValues: {"[ENV_KEY]": 'Value'},
  127. error: 'error goes here, otherwise null'
  128. }
  129. }
  130. }
  131. }
  132. }
  133. #swagger.responses[403] = {
  134. schema: {
  135. "$ref": "#/definitions/InvalidAPIKey"
  136. }
  137. }
  138. */
  139. try {
  140. const body = reqBody(request);
  141. const { newValues, error } = await updateENV(body);
  142. response.status(200).json({ newValues, error });
  143. } catch (e) {
  144. console.error(e.message, e);
  145. response.sendStatus(500).end();
  146. }
  147. }
  148. );
  149. app.get(
  150. "/v1/system/export-chats",
  151. [validApiKey],
  152. async (request, response) => {
  153. /*
  154. #swagger.tags = ['System Settings']
  155. #swagger.description = 'Export all of the chats from the system in a known format. Output depends on the type sent. Will be send with the correct header for the output.'
  156. #swagger.parameters['type'] = {
  157. in: 'query',
  158. description: "Export format jsonl, json, csv, jsonAlpaca",
  159. required: false,
  160. type: 'string'
  161. }
  162. #swagger.responses[200] = {
  163. content: {
  164. "application/json": {
  165. schema: {
  166. type: 'object',
  167. example: [
  168. {
  169. "role": "user",
  170. "content": "What is AnythinglLM?"
  171. },
  172. {
  173. "role": "assistant",
  174. "content": "AnythingLLM is a knowledge graph and vector database management system built using NodeJS express server. It provides an interface for handling all interactions, including vectorDB management and LLM (Language Model) interactions."
  175. },
  176. ]
  177. }
  178. }
  179. }
  180. }
  181. #swagger.responses[403] = {
  182. schema: {
  183. "$ref": "#/definitions/InvalidAPIKey"
  184. }
  185. }
  186. */
  187. try {
  188. const { type = "jsonl" } = request.query;
  189. const chats = await prepareWorkspaceChatsForExport(type);
  190. const { contentType, data } = await exportChatsAsType(chats, type);
  191. await EventLogs.logEvent("exported_chats", {
  192. type,
  193. });
  194. response.setHeader("Content-Type", contentType);
  195. response.status(200).send(data);
  196. } catch (e) {
  197. console.error(e.message, e);
  198. response.sendStatus(500).end();
  199. }
  200. }
  201. );
  202. app.delete(
  203. "/v1/system/remove-documents",
  204. [validApiKey],
  205. async (request, response) => {
  206. /*
  207. #swagger.tags = ['System Settings']
  208. #swagger.description = 'Permanently remove documents from the system.'
  209. #swagger.requestBody = {
  210. description: 'Array of document names to be removed permanently.',
  211. required: true,
  212. content: {
  213. "application/json": {
  214. schema: {
  215. type: 'object',
  216. properties: {
  217. names: {
  218. type: 'array',
  219. items: {
  220. type: 'string'
  221. },
  222. example: [
  223. "custom-documents/file.txt-fc4beeeb-e436-454d-8bb4-e5b8979cb48f.json"
  224. ]
  225. }
  226. }
  227. }
  228. }
  229. }
  230. }
  231. #swagger.responses[200] = {
  232. description: 'Documents removed successfully.',
  233. content: {
  234. "application/json": {
  235. schema: {
  236. type: 'object',
  237. example: {
  238. success: true,
  239. message: 'Documents removed successfully'
  240. }
  241. }
  242. }
  243. }
  244. }
  245. #swagger.responses[403] = {
  246. description: 'Forbidden',
  247. schema: {
  248. "$ref": "#/definitions/InvalidAPIKey"
  249. }
  250. }
  251. #swagger.responses[500] = {
  252. description: 'Internal Server Error'
  253. }
  254. */
  255. try {
  256. const { names } = reqBody(request);
  257. for await (const name of names) await purgeDocument(name);
  258. response
  259. .status(200)
  260. .json({ success: true, message: "Documents removed successfully" })
  261. .end();
  262. } catch (e) {
  263. console.error(e.message, e);
  264. response.sendStatus(500).end();
  265. }
  266. }
  267. );
  268. }
  269. module.exports = { apiSystemEndpoints };