UNPKG

@langchain/community

Version:
1 lines 7.42 kB
{"version":3,"file":"file_system.cjs","names":["BaseListChatMessageHistory","fs"],"sources":["../../../src/stores/message/file_system.ts"],"sourcesContent":["import { promises as fs } from \"node:fs\";\nimport { dirname } from \"node:path\";\n\nimport { BaseListChatMessageHistory } from \"@langchain/core/chat_history\";\nimport {\n BaseMessage,\n StoredMessage,\n mapChatMessagesToStoredMessages,\n mapStoredMessagesToChatMessages,\n} from \"@langchain/core/messages\";\n\nexport const FILE_HISTORY_DEFAULT_FILE_PATH = \".history/history.json\";\n\n/**\n * Represents a lightweight file chat session.\n */\nexport type FileChatSession = {\n id: string;\n context: Record<string, unknown>;\n};\n\n/**\n * Represents a stored chat session.\n */\nexport type StoredFileChatSession = FileChatSession & {\n messages: StoredMessage[];\n};\n\n/**\n * Type for the store of chat sessions.\n */\nexport type FileChatStore = {\n [userId: string]: Record<string, StoredFileChatSession>;\n};\n\n/**\n * Type for the input to the `FileSystemChatMessageHistory` constructor.\n */\nexport interface FileSystemChatMessageHistoryInput {\n sessionId: string;\n userId?: string;\n filePath?: string;\n}\n\nlet store: FileChatStore;\n\n/**\n * Store chat message history using a local JSON file.\n * For demo and development purposes only.\n *\n * @example\n * ```typescript\n * const model = new ChatOpenAI({\n * model: \"gpt-3.5-turbo\",\n * temperature: 0,\n * });\n * const prompt = ChatPromptTemplate.fromMessages([\n * [\n * \"system\",\n * \"You are a helpful assistant. Answer all questions to the best of your ability.\",\n * ],\n * [\"placeholder\", \"chat_history\"],\n * [\"human\", \"{input}\"],\n * ]);\n *\n * const chain = prompt.pipe(model).pipe(new StringOutputParser());\n * const chainWithHistory = new RunnableWithMessageHistory({\n * runnable: chain,\n * inputMessagesKey: \"input\",\n * historyMessagesKey: \"chat_history\",\n * getMessageHistory: async (sessionId) => {\n * const chatHistory = new FileSystemChatMessageHistory({\n * sessionId: sessionId,\n * userId: \"userId\", // Optional\n * })\n * return chatHistory;\n * },\n * });\n * await chainWithHistory.invoke(\n * { input: \"What did I just say my name was?\" },\n * { configurable: { sessionId: \"session-id\" } }\n * );\n * ```\n */\nexport class FileSystemChatMessageHistory extends BaseListChatMessageHistory {\n lc_namespace = [\"langchain\", \"stores\", \"message\", \"file\"];\n\n private sessionId: string;\n\n private userId: string;\n\n private filePath: string;\n\n constructor(chatHistoryInput: FileSystemChatMessageHistoryInput) {\n super();\n\n this.sessionId = chatHistoryInput.sessionId;\n this.userId = chatHistoryInput.userId ?? \"\";\n this.filePath = chatHistoryInput.filePath ?? FILE_HISTORY_DEFAULT_FILE_PATH;\n }\n\n private async init(): Promise<void> {\n if (store) {\n return;\n }\n try {\n store = await this.loadStore();\n } catch (error) {\n console.error(\"Error initializing FileSystemChatMessageHistory:\", error);\n throw error;\n }\n }\n\n protected async loadStore(): Promise<FileChatStore> {\n try {\n const store = await fs.readFile(this.filePath, \"utf-8\");\n return JSON.parse(store) as FileChatStore;\n } catch (_error) {\n const error = _error as NodeJS.ErrnoException;\n if (error.code === \"ENOENT\") {\n return {};\n }\n throw new Error(\n `Error loading FileSystemChatMessageHistory store: ${error}`\n );\n }\n }\n\n protected async saveStore(): Promise<void> {\n try {\n await fs.mkdir(dirname(this.filePath), { recursive: true });\n await fs.writeFile(this.filePath, JSON.stringify(store));\n } catch (error) {\n throw new Error(\n `Error saving FileSystemChatMessageHistory store: ${error}`\n );\n }\n }\n\n async getMessages(): Promise<BaseMessage[]> {\n await this.init();\n const messages = store[this.userId]?.[this.sessionId]?.messages ?? [];\n return mapStoredMessagesToChatMessages(messages);\n }\n\n async addMessage(message: BaseMessage): Promise<void> {\n await this.init();\n const messages = await this.getMessages();\n messages.push(message);\n const storedMessages = mapChatMessagesToStoredMessages(messages);\n store[this.userId] ??= {};\n store[this.userId][this.sessionId] = {\n ...store[this.userId][this.sessionId],\n messages: storedMessages,\n };\n await this.saveStore();\n }\n\n async clear(): Promise<void> {\n await this.init();\n if (store[this.userId]) {\n delete store[this.userId][this.sessionId];\n }\n await this.saveStore();\n }\n\n async getContext(): Promise<Record<string, unknown>> {\n await this.init();\n return store[this.userId]?.[this.sessionId]?.context ?? {};\n }\n\n async setContext(context: Record<string, unknown>): Promise<void> {\n await this.init();\n store[this.userId] ??= {};\n store[this.userId][this.sessionId] = {\n ...store[this.userId][this.sessionId],\n context,\n };\n await this.saveStore();\n }\n\n async clearAllSessions() {\n await this.init();\n delete store[this.userId];\n await this.saveStore();\n }\n\n async getAllSessions(): Promise<FileChatSession[]> {\n await this.init();\n const userSessions = store[this.userId]\n ? Object.entries(store[this.userId]).map(([id, session]) => ({\n id,\n context: session.context,\n }))\n : [];\n return userSessions;\n }\n}\n"],"mappings":";;;;;;;;;;;AAWA,MAAa,iCAAiC;AAiC9C,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwCJ,IAAa,+BAAb,cAAkDA,6BAAAA,2BAA2B;CAC3E,eAAe;EAAC;EAAa;EAAU;EAAW;EAAO;CAEzD;CAEA;CAEA;CAEA,YAAY,kBAAqD;AAC/D,SAAO;AAEP,OAAK,YAAY,iBAAiB;AAClC,OAAK,SAAS,iBAAiB,UAAU;AACzC,OAAK,WAAW,iBAAiB,YAAA;;CAGnC,MAAc,OAAsB;AAClC,MAAI,MACF;AAEF,MAAI;AACF,WAAQ,MAAM,KAAK,WAAW;WACvB,OAAO;AACd,WAAQ,MAAM,oDAAoD,MAAM;AACxE,SAAM;;;CAIV,MAAgB,YAAoC;AAClD,MAAI;GACF,MAAM,QAAQ,MAAMC,QAAAA,SAAG,SAAS,KAAK,UAAU,QAAQ;AACvD,UAAO,KAAK,MAAM,MAAM;WACjB,QAAQ;GACf,MAAM,QAAQ;AACd,OAAI,MAAM,SAAS,SACjB,QAAO,EAAE;AAEX,SAAM,IAAI,MACR,qDAAqD,QACtD;;;CAIL,MAAgB,YAA2B;AACzC,MAAI;AACF,SAAMA,QAAAA,SAAG,OAAA,GAAA,UAAA,SAAc,KAAK,SAAS,EAAE,EAAE,WAAW,MAAM,CAAC;AAC3D,SAAMA,QAAAA,SAAG,UAAU,KAAK,UAAU,KAAK,UAAU,MAAM,CAAC;WACjD,OAAO;AACd,SAAM,IAAI,MACR,oDAAoD,QACrD;;;CAIL,MAAM,cAAsC;AAC1C,QAAM,KAAK,MAAM;AAEjB,UAAA,GAAA,yBAAA,iCADiB,MAAM,KAAK,UAAU,KAAK,YAAY,YAAY,EAAE,CACrB;;CAGlD,MAAM,WAAW,SAAqC;AACpD,QAAM,KAAK,MAAM;EACjB,MAAM,WAAW,MAAM,KAAK,aAAa;AACzC,WAAS,KAAK,QAAQ;EACtB,MAAM,kBAAA,GAAA,yBAAA,iCAAiD,SAAS;AAChE,QAAM,KAAK,YAAY,EAAE;AACzB,QAAM,KAAK,QAAQ,KAAK,aAAa;GACnC,GAAG,MAAM,KAAK,QAAQ,KAAK;GAC3B,UAAU;GACX;AACD,QAAM,KAAK,WAAW;;CAGxB,MAAM,QAAuB;AAC3B,QAAM,KAAK,MAAM;AACjB,MAAI,MAAM,KAAK,QACb,QAAO,MAAM,KAAK,QAAQ,KAAK;AAEjC,QAAM,KAAK,WAAW;;CAGxB,MAAM,aAA+C;AACnD,QAAM,KAAK,MAAM;AACjB,SAAO,MAAM,KAAK,UAAU,KAAK,YAAY,WAAW,EAAE;;CAG5D,MAAM,WAAW,SAAiD;AAChE,QAAM,KAAK,MAAM;AACjB,QAAM,KAAK,YAAY,EAAE;AACzB,QAAM,KAAK,QAAQ,KAAK,aAAa;GACnC,GAAG,MAAM,KAAK,QAAQ,KAAK;GAC3B;GACD;AACD,QAAM,KAAK,WAAW;;CAGxB,MAAM,mBAAmB;AACvB,QAAM,KAAK,MAAM;AACjB,SAAO,MAAM,KAAK;AAClB,QAAM,KAAK,WAAW;;CAGxB,MAAM,iBAA6C;AACjD,QAAM,KAAK,MAAM;AAOjB,SANqB,MAAM,KAAK,UAC5B,OAAO,QAAQ,MAAM,KAAK,QAAQ,CAAC,KAAK,CAAC,IAAI,cAAc;GACzD;GACA,SAAS,QAAQ;GAClB,EAAE,GACH,EAAE"}