-
Notifications
You must be signed in to change notification settings - Fork 2.5k
/
Copy pathvector_store.ts
134 lines (123 loc) Β· 3.99 KB
/
vector_store.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
130
131
132
133
134
import type { VectorStoreRetrieverInterface } from "@langchain/core/vectorstores";
import { Document } from "@langchain/core/documents";
import {
BaseMemory,
getInputValue,
InputValues,
MemoryVariables,
OutputValues,
} from "@langchain/core/memory";
import { formatDocumentsAsString } from "../util/document.js";
type Metadata = Record<string, unknown>;
type MetadataFunction = (
inputValues?: InputValues,
outputValues?: OutputValues
) => Metadata;
/**
* Interface for the parameters required to initialize a
* VectorStoreRetrieverMemory instance.
*/
export interface VectorStoreRetrieverMemoryParams {
vectorStoreRetriever: VectorStoreRetrieverInterface;
inputKey?: string;
outputKey?: string;
memoryKey?: string;
returnDocs?: boolean;
/**
* Metadata to be added to the document when saving context.
*/
metadata?: Metadata | MetadataFunction;
}
/**
* Class for managing long-term memory in Large Language Model (LLM)
* applications. It provides a way to persist and retrieve relevant
* documents from a vector store database, which can be useful for
* maintaining conversation history or other types of memory in an LLM
* application.
* @example
* ```typescript
* const vectorStore = new MemoryVectorStore(new OpenAIEmbeddings());
* const memory = new VectorStoreRetrieverMemory({
* vectorStoreRetriever: vectorStore.asRetriever(1),
* memoryKey: "history",
* });
*
* // Saving context to memory
* await memory.saveContext(
* { input: "My favorite food is pizza" },
* { output: "thats good to know" },
* );
* await memory.saveContext(
* { input: "My favorite sport is soccer" },
* { output: "..." },
* );
* await memory.saveContext({ input: "I don't the Celtics" }, { output: "ok" });
*
* // Loading memory variables
* console.log(
* await memory.loadMemoryVariables({ prompt: "what sport should i watch?" }),
* );
* ```
*/
export class VectorStoreRetrieverMemory
extends BaseMemory
implements VectorStoreRetrieverMemoryParams
{
vectorStoreRetriever: VectorStoreRetrieverInterface;
inputKey?: string;
memoryKey: string;
returnDocs: boolean;
metadata?: Metadata | MetadataFunction;
constructor(fields: VectorStoreRetrieverMemoryParams) {
super();
this.vectorStoreRetriever = fields.vectorStoreRetriever;
this.inputKey = fields.inputKey;
this.memoryKey = fields.memoryKey ?? "memory";
this.returnDocs = fields.returnDocs ?? false;
this.metadata = fields.metadata;
}
get memoryKeys(): string[] {
return [this.memoryKey];
}
/**
* Method to load memory variables. It uses the vectorStoreRetriever to
* get relevant documents based on the query obtained from the input
* values.
* @param values An InputValues object.
* @returns A Promise that resolves to a MemoryVariables object.
*/
async loadMemoryVariables(values: InputValues): Promise<MemoryVariables> {
const query = getInputValue(values, this.inputKey);
const results = await this.vectorStoreRetriever.getRelevantDocuments(query);
return {
[this.memoryKey]: this.returnDocs
? results
: formatDocumentsAsString(results),
};
}
/**
* Method to save context. It constructs a document from the input and
* output values (excluding the memory key) and adds it to the vector
* store database using the vectorStoreRetriever.
* @param inputValues An InputValues object.
* @param outputValues An OutputValues object.
* @returns A Promise that resolves to void.
*/
async saveContext(
inputValues: InputValues,
outputValues: OutputValues
): Promise<void> {
const metadata =
typeof this.metadata === "function"
? this.metadata(inputValues, outputValues)
: this.metadata;
const text = Object.entries(inputValues)
.filter(([k]) => k !== this.memoryKey)
.concat(Object.entries(outputValues))
.map(([k, v]) => `${k}: ${v}`)
.join("\n");
await this.vectorStoreRetriever.addDocuments([
new Document({ pageContent: text, metadata }),
]);
}
}