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.

84 lines
2.9 KiB

11 months ago
  1. const { WorkspaceChats } = require("../../../../models/workspaceChats");
  2. /**
  3. * Plugin to save chat history to AnythingLLM DB.
  4. */
  5. const chatHistory = {
  6. name: "chat-history",
  7. startupConfig: {
  8. params: {},
  9. },
  10. plugin: function () {
  11. return {
  12. name: this.name,
  13. setup: function (aibitat) {
  14. aibitat.onMessage(async () => {
  15. try {
  16. const lastResponses = aibitat.chats.slice(-2);
  17. if (lastResponses.length !== 2) return;
  18. const [prev, last] = lastResponses;
  19. // We need a full conversation reply with prev being from
  20. // the USER and the last being from anyone other than the user.
  21. if (prev.from !== "USER" || last.from === "USER") return;
  22. // If we have a post-reply flow we should save the chat using this special flow
  23. // so that post save cleanup and other unique properties can be run as opposed to regular chat.
  24. if (aibitat.hasOwnProperty("_replySpecialAttributes")) {
  25. await this._storeSpecial(aibitat, {
  26. prompt: prev.content,
  27. response: last.content,
  28. options: aibitat._replySpecialAttributes,
  29. });
  30. delete aibitat._replySpecialAttributes;
  31. return;
  32. }
  33. await this._store(aibitat, {
  34. prompt: prev.content,
  35. response: last.content,
  36. });
  37. } catch {}
  38. });
  39. },
  40. _store: async function (aibitat, { prompt, response } = {}) {
  41. const invocation = aibitat.handlerProps.invocation;
  42. await WorkspaceChats.new({
  43. workspaceId: Number(invocation.workspace_id),
  44. prompt,
  45. response: {
  46. text: response,
  47. sources: [],
  48. type: "chat",
  49. },
  50. user: { id: invocation?.user_id || null },
  51. threadId: invocation?.thread_id || null,
  52. });
  53. },
  54. _storeSpecial: async function (
  55. aibitat,
  56. { prompt, response, options = {} } = {}
  57. ) {
  58. const invocation = aibitat.handlerProps.invocation;
  59. await WorkspaceChats.new({
  60. workspaceId: Number(invocation.workspace_id),
  61. prompt,
  62. response: {
  63. sources: options?.sources ?? [],
  64. // when we have a _storeSpecial called the options param can include a storedResponse() function
  65. // that will override the text property to store extra information in, depending on the special type of chat.
  66. text: options.hasOwnProperty("storedResponse")
  67. ? options.storedResponse(response)
  68. : response,
  69. type: options?.saveAsType ?? "chat",
  70. },
  71. user: { id: invocation?.user_id || null },
  72. threadId: invocation?.thread_id || null,
  73. });
  74. options?.postSave();
  75. },
  76. };
  77. },
  78. };
  79. module.exports = { chatHistory };