120 lines
4.1 KiB
JavaScript
120 lines
4.1 KiB
JavaScript
|
import { BaseChatMemory } from "./chat_memory.js";
|
||
|
/**
|
||
|
* Class that manages and manipulates previous chat messages. It extends
|
||
|
* from the BaseChatMemory class and implements the CombinedMemoryInput
|
||
|
* interface.
|
||
|
*/
|
||
|
export class CombinedMemory extends BaseChatMemory {
|
||
|
constructor(fields) {
|
||
|
super({
|
||
|
chatHistory: fields?.chatHistory,
|
||
|
returnMessages: fields?.returnMessages ?? false,
|
||
|
inputKey: fields?.inputKey,
|
||
|
outputKey: fields?.outputKey,
|
||
|
});
|
||
|
Object.defineProperty(this, "humanPrefix", {
|
||
|
enumerable: true,
|
||
|
configurable: true,
|
||
|
writable: true,
|
||
|
value: "Human"
|
||
|
});
|
||
|
Object.defineProperty(this, "aiPrefix", {
|
||
|
enumerable: true,
|
||
|
configurable: true,
|
||
|
writable: true,
|
||
|
value: "AI"
|
||
|
});
|
||
|
Object.defineProperty(this, "memoryKey", {
|
||
|
enumerable: true,
|
||
|
configurable: true,
|
||
|
writable: true,
|
||
|
value: "history"
|
||
|
});
|
||
|
Object.defineProperty(this, "memories", {
|
||
|
enumerable: true,
|
||
|
configurable: true,
|
||
|
writable: true,
|
||
|
value: []
|
||
|
});
|
||
|
this.memories = fields?.memories ?? this.memories;
|
||
|
this.humanPrefix = fields?.humanPrefix ?? this.humanPrefix;
|
||
|
this.aiPrefix = fields?.aiPrefix ?? this.aiPrefix;
|
||
|
this.memoryKey = fields?.memoryKey ?? this.memoryKey;
|
||
|
this.checkRepeatedMemoryVariable();
|
||
|
this.checkInputKey();
|
||
|
}
|
||
|
/**
|
||
|
* Checks for repeated memory variables across all memory objects. Throws
|
||
|
* an error if any are found.
|
||
|
*/
|
||
|
checkRepeatedMemoryVariable() {
|
||
|
const allVariables = [];
|
||
|
for (const memory of this.memories) {
|
||
|
const overlap = allVariables.filter((x) => memory.memoryKeys.includes(x));
|
||
|
if (overlap.length > 0) {
|
||
|
throw new Error(`The same variables ${[
|
||
|
...overlap,
|
||
|
]} are found in multiple memory objects, which is not allowed by CombinedMemory.`);
|
||
|
}
|
||
|
allVariables.push(...memory.memoryKeys);
|
||
|
}
|
||
|
}
|
||
|
/**
|
||
|
* Checks if input keys are set for all memory objects. Logs a warning if
|
||
|
* any are missing.
|
||
|
*/
|
||
|
checkInputKey() {
|
||
|
for (const memory of this.memories) {
|
||
|
if (memory.chatHistory !== undefined &&
|
||
|
memory.inputKey === undefined) {
|
||
|
console.warn(`When using CombinedMemory, input keys should be set so the input is known. Was not set on ${memory}.`);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
/**
|
||
|
* Loads memory variables from all memory objects.
|
||
|
* @param inputValues Input values to load memory variables from.
|
||
|
* @returns Promise that resolves with an object containing the loaded memory variables.
|
||
|
*/
|
||
|
async loadMemoryVariables(inputValues) {
|
||
|
let memoryData = {};
|
||
|
for (const memory of this.memories) {
|
||
|
const data = await memory.loadMemoryVariables(inputValues);
|
||
|
memoryData = {
|
||
|
...memoryData,
|
||
|
...data,
|
||
|
};
|
||
|
}
|
||
|
return memoryData;
|
||
|
}
|
||
|
/**
|
||
|
* Saves the context to all memory objects.
|
||
|
* @param inputValues Input values to save.
|
||
|
* @param outputValues Output values to save.
|
||
|
* @returns Promise that resolves when the context has been saved to all memory objects.
|
||
|
*/
|
||
|
async saveContext(inputValues, outputValues) {
|
||
|
for (const memory of this.memories) {
|
||
|
await memory.saveContext(inputValues, outputValues);
|
||
|
}
|
||
|
}
|
||
|
/**
|
||
|
* Clears all memory objects.
|
||
|
* @returns Promise that resolves when all memory objects have been cleared.
|
||
|
*/
|
||
|
async clear() {
|
||
|
for (const memory of this.memories) {
|
||
|
if (typeof memory.clear === "function") {
|
||
|
await memory.clear();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
get memoryKeys() {
|
||
|
const memoryKeys = [];
|
||
|
for (const memory of this.memories) {
|
||
|
memoryKeys.push(...memory.memoryKeys);
|
||
|
}
|
||
|
return memoryKeys;
|
||
|
}
|
||
|
}
|