-
Notifications
You must be signed in to change notification settings - Fork 2.5k
/
Copy pathbuffer_token_memory.ts
129 lines (111 loc) Β· 3.72 KB
/
buffer_token_memory.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import type { BaseLanguageModelInterface } from "@langchain/core/language_models/base";
import {
InputValues,
MemoryVariables,
OutputValues,
} from "@langchain/core/memory";
import { getBufferString } from "@langchain/core/messages";
import { BaseChatMemory, BaseChatMemoryInput } from "./chat_memory.js";
/**
* Interface for the input parameters of the `BufferTokenMemory` class.
*/
export interface ConversationTokenBufferMemoryInput
extends BaseChatMemoryInput {
/* Prefix for human messages in the buffer. */
humanPrefix?: string;
/* Prefix for AI messages in the buffer. */
aiPrefix?: string;
/* The LLM for this instance. */
llm: BaseLanguageModelInterface;
/* Memory key for buffer instance. */
memoryKey?: string;
/* Maximmum number of tokens allowed in the buffer. */
maxTokenLimit?: number;
}
/**
* Class that represents a conversation chat memory with a token buffer.
* It extends the `BaseChatMemory` class and implements the
* `ConversationTokenBufferMemoryInput` interface.
* @example
* ```typescript
* const memory = new ConversationTokenBufferMemory({
* llm: new ChatOpenAI({}),
* maxTokenLimit: 10,
* });
*
* // Save conversation context
* await memory.saveContext({ input: "hi" }, { output: "whats up" });
* await memory.saveContext({ input: "not much you" }, { output: "not much" });
*
* // Load memory variables
* const result = await memory.loadMemoryVariables({});
* console.log(result);
* ```
*/
export class ConversationTokenBufferMemory
extends BaseChatMemory
implements ConversationTokenBufferMemoryInput
{
humanPrefix = "Human";
aiPrefix = "AI";
memoryKey = "history";
maxTokenLimit = 2000; // Default max token limit of 2000 which can be overridden
llm: BaseLanguageModelInterface;
constructor(fields: ConversationTokenBufferMemoryInput) {
super(fields);
this.llm = fields.llm;
this.humanPrefix = fields?.humanPrefix ?? this.humanPrefix;
this.aiPrefix = fields?.aiPrefix ?? this.aiPrefix;
this.memoryKey = fields?.memoryKey ?? this.memoryKey;
this.maxTokenLimit = fields?.maxTokenLimit ?? this.maxTokenLimit;
}
get memoryKeys() {
return [this.memoryKey];
}
/**
* Loads the memory variables. It takes an `InputValues` object as a
* parameter and returns a `Promise` that resolves with a
* `MemoryVariables` object.
* @param _values `InputValues` object.
* @returns A `Promise` that resolves with a `MemoryVariables` object.
*/
async loadMemoryVariables(_values: InputValues): Promise<MemoryVariables> {
const messages = await this.chatHistory.getMessages();
if (this.returnMessages) {
const result = {
[this.memoryKey]: messages,
};
return result;
}
const result = {
[this.memoryKey]: getBufferString(
messages,
this.humanPrefix,
this.aiPrefix
),
};
return result;
}
/**
* Saves the context from this conversation to buffer. If the amount
* of tokens required to save the buffer exceeds MAX_TOKEN_LIMIT,
* prune it.
*/
async saveContext(inputValues: InputValues, outputValues: OutputValues) {
await super.saveContext(inputValues, outputValues);
// Prune buffer if it exceeds the max token limit set for this instance.
const buffer = await this.chatHistory.getMessages();
let currBufferLength = await this.llm.getNumTokens(
getBufferString(buffer, this.humanPrefix, this.aiPrefix)
);
if (currBufferLength > this.maxTokenLimit) {
const prunedMemory = [];
while (currBufferLength > this.maxTokenLimit) {
prunedMemory.push(buffer.shift());
currBufferLength = await this.llm.getNumTokens(
getBufferString(buffer, this.humanPrefix, this.aiPrefix)
);
}
}
}
}