Add Supabase History DB to run Mem0 OSS on Serverless (#2429)
This commit is contained in:
@@ -301,6 +301,56 @@ await memory.deleteAll({ userId: "alice" });
|
|||||||
await memory.reset(); // Reset all memories
|
await memory.reset(); // Reset all memories
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### History Store
|
||||||
|
|
||||||
|
Mem0 TypeScript SDK support history stores to run on a serverless environment:
|
||||||
|
|
||||||
|
We recommend using `Supabase` as a history store for serverless environments or disable history store to run on a serverless environment.
|
||||||
|
|
||||||
|
<CodeGroup>
|
||||||
|
```typescript Supabase
|
||||||
|
import { Memory } from 'mem0ai/oss';
|
||||||
|
|
||||||
|
const memory = new Memory({
|
||||||
|
historyStore: {
|
||||||
|
provider: 'supabase',
|
||||||
|
config: {
|
||||||
|
supabaseUrl: process.env.SUPABASE_URL || '',
|
||||||
|
supabaseKey: process.env.SUPABASE_KEY || '',
|
||||||
|
tableName: 'memory_history',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
```typescript Disable History
|
||||||
|
import { Memory } from 'mem0ai/oss';
|
||||||
|
|
||||||
|
const memory = new Memory({
|
||||||
|
disableHistory: true,
|
||||||
|
});
|
||||||
|
```
|
||||||
|
</CodeGroup>
|
||||||
|
|
||||||
|
Mem0 uses SQLite as a default history store.
|
||||||
|
|
||||||
|
#### Create Memory History Table in Supabase
|
||||||
|
|
||||||
|
You may need to create a memory history table in Supabase to store the history of memories. Use the following SQL command in `SQL Editor` on the Supabase project dashboard to create a memory history table:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
create table memory_history (
|
||||||
|
id text primary key,
|
||||||
|
memory_id text not null,
|
||||||
|
previous_value text,
|
||||||
|
new_value text,
|
||||||
|
action text not null,
|
||||||
|
created_at timestamp with time zone default timezone('utc', now()),
|
||||||
|
updated_at timestamp with time zone,
|
||||||
|
is_deleted integer default 0
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
## Configuration Parameters
|
## Configuration Parameters
|
||||||
|
|
||||||
Mem0 offers extensive configuration options to customize its behavior according to your needs. These configurations span across different components like vector stores, language models, embedders, and graph stores.
|
Mem0 offers extensive configuration options to customize its behavior according to your needs. These configurations span across different components like vector stores, language models, embedders, and graph stores.
|
||||||
@@ -352,6 +402,14 @@ Mem0 offers extensive configuration options to customize its behavior according
|
|||||||
| `customPrompt` | Custom prompt for memory processing | None |
|
| `customPrompt` | Custom prompt for memory processing | None |
|
||||||
</Accordion>
|
</Accordion>
|
||||||
|
|
||||||
|
<Accordion title="History Table Configuration">
|
||||||
|
| Parameter | Description | Default |
|
||||||
|
|------------------|--------------------------------------|----------------------------|
|
||||||
|
| `provider` | History store provider | "sqlite" |
|
||||||
|
| `config` | History store configuration | None (Defaults to SQLite) |
|
||||||
|
| `disableHistory` | Disable history store | false |
|
||||||
|
</Accordion>
|
||||||
|
|
||||||
<Accordion title="Complete Configuration Example">
|
<Accordion title="Complete Configuration Example">
|
||||||
```typescript
|
```typescript
|
||||||
const config = {
|
const config = {
|
||||||
@@ -377,7 +435,15 @@ const config = {
|
|||||||
model: 'gpt-4-turbo-preview',
|
model: 'gpt-4-turbo-preview',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
historyDbPath: 'memory.db',
|
historyStore: {
|
||||||
|
provider: 'supabase',
|
||||||
|
config: {
|
||||||
|
supabaseUrl: process.env.SUPABASE_URL || '',
|
||||||
|
supabaseKey: process.env.SUPABASE_KEY || '',
|
||||||
|
tableName: 'memories',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
disableHistory: false, // This is false by default
|
||||||
customPrompt: "I'm a virtual assistant. I'm here to help you with your queries.",
|
customPrompt: "I'm a virtual assistant. I'm here to help you with your queries.",
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "mem0ai",
|
"name": "mem0ai",
|
||||||
"version": "2.1.9",
|
"version": "2.1.10",
|
||||||
"description": "The Memory Layer For Your AI Apps",
|
"description": "The Memory Layer For Your AI Apps",
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
"module": "./dist/index.mjs",
|
"module": "./dist/index.mjs",
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { MemoryConfig } from "../types";
|
import { MemoryConfig } from "../types";
|
||||||
|
|
||||||
export const DEFAULT_MEMORY_CONFIG: MemoryConfig = {
|
export const DEFAULT_MEMORY_CONFIG: MemoryConfig = {
|
||||||
|
disableHistory: false,
|
||||||
version: "v1.1",
|
version: "v1.1",
|
||||||
embedder: {
|
embedder: {
|
||||||
provider: "openai",
|
provider: "openai",
|
||||||
@@ -38,5 +39,10 @@ export const DEFAULT_MEMORY_CONFIG: MemoryConfig = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
historyStore: {
|
||||||
|
provider: "sqlite",
|
||||||
|
config: {
|
||||||
historyDbPath: "memory.db",
|
historyDbPath: "memory.db",
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -51,6 +51,12 @@ export class ConfigManager {
|
|||||||
...DEFAULT_MEMORY_CONFIG.graphStore,
|
...DEFAULT_MEMORY_CONFIG.graphStore,
|
||||||
...userConfig.graphStore,
|
...userConfig.graphStore,
|
||||||
},
|
},
|
||||||
|
historyStore: {
|
||||||
|
...DEFAULT_MEMORY_CONFIG.historyStore,
|
||||||
|
...userConfig.historyStore,
|
||||||
|
},
|
||||||
|
disableHistory:
|
||||||
|
userConfig.disableHistory || DEFAULT_MEMORY_CONFIG.disableHistory,
|
||||||
enableGraph: userConfig.enableGraph || DEFAULT_MEMORY_CONFIG.enableGraph,
|
enableGraph: userConfig.enableGraph || DEFAULT_MEMORY_CONFIG.enableGraph,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import {
|
|||||||
EmbedderFactory,
|
EmbedderFactory,
|
||||||
LLMFactory,
|
LLMFactory,
|
||||||
VectorStoreFactory,
|
VectorStoreFactory,
|
||||||
|
HistoryManagerFactory,
|
||||||
} from "../utils/factory";
|
} from "../utils/factory";
|
||||||
import {
|
import {
|
||||||
getFactRetrievalMessages,
|
getFactRetrievalMessages,
|
||||||
@@ -19,7 +20,7 @@ import {
|
|||||||
parseMessages,
|
parseMessages,
|
||||||
removeCodeBlocks,
|
removeCodeBlocks,
|
||||||
} from "../prompts";
|
} from "../prompts";
|
||||||
import { SQLiteManager } from "../storage";
|
import { DummyHistoryManager } from "../storage/DummyHistoryManager";
|
||||||
import { Embedder } from "../embeddings/base";
|
import { Embedder } from "../embeddings/base";
|
||||||
import { LLM } from "../llms/base";
|
import { LLM } from "../llms/base";
|
||||||
import { VectorStore } from "../vector_stores/base";
|
import { VectorStore } from "../vector_stores/base";
|
||||||
@@ -32,14 +33,14 @@ import {
|
|||||||
GetAllMemoryOptions,
|
GetAllMemoryOptions,
|
||||||
} from "./memory.types";
|
} from "./memory.types";
|
||||||
import { parse_vision_messages } from "../utils/memory";
|
import { parse_vision_messages } from "../utils/memory";
|
||||||
|
import { HistoryManager } from "../storage/base";
|
||||||
export class Memory {
|
export class Memory {
|
||||||
private config: MemoryConfig;
|
private config: MemoryConfig;
|
||||||
private customPrompt: string | undefined;
|
private customPrompt: string | undefined;
|
||||||
private embedder: Embedder;
|
private embedder: Embedder;
|
||||||
private vectorStore: VectorStore;
|
private vectorStore: VectorStore;
|
||||||
private llm: LLM;
|
private llm: LLM;
|
||||||
private db: SQLiteManager;
|
private db: HistoryManager;
|
||||||
private collectionName: string;
|
private collectionName: string;
|
||||||
private apiVersion: string;
|
private apiVersion: string;
|
||||||
private graphMemory?: MemoryGraph;
|
private graphMemory?: MemoryGraph;
|
||||||
@@ -62,7 +63,25 @@ export class Memory {
|
|||||||
this.config.llm.provider,
|
this.config.llm.provider,
|
||||||
this.config.llm.config,
|
this.config.llm.config,
|
||||||
);
|
);
|
||||||
this.db = new SQLiteManager(this.config.historyDbPath || ":memory:");
|
if (this.config.disableHistory) {
|
||||||
|
this.db = new DummyHistoryManager();
|
||||||
|
} else {
|
||||||
|
const defaultConfig = {
|
||||||
|
provider: "sqlite",
|
||||||
|
config: {
|
||||||
|
historyDbPath: this.config.historyDbPath || ":memory:",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
this.db =
|
||||||
|
this.config.historyStore && !this.config.disableHistory
|
||||||
|
? HistoryManagerFactory.create(
|
||||||
|
this.config.historyStore.provider,
|
||||||
|
this.config.historyStore,
|
||||||
|
)
|
||||||
|
: HistoryManagerFactory.create("sqlite", defaultConfig);
|
||||||
|
}
|
||||||
|
|
||||||
this.collectionName = this.config.vectorStore.config.collectionName;
|
this.collectionName = this.config.vectorStore.config.collectionName;
|
||||||
this.apiVersion = this.config.version || "v1.0";
|
this.apiVersion = this.config.version || "v1.0";
|
||||||
this.enableGraph = this.config.enableGraph || false;
|
this.enableGraph = this.config.enableGraph || false;
|
||||||
|
|||||||
27
mem0-ts/src/oss/src/storage/DummyHistoryManager.ts
Normal file
27
mem0-ts/src/oss/src/storage/DummyHistoryManager.ts
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
export class DummyHistoryManager {
|
||||||
|
constructor() {}
|
||||||
|
|
||||||
|
async addHistory(
|
||||||
|
memoryId: string,
|
||||||
|
previousValue: string | null,
|
||||||
|
newValue: string | null,
|
||||||
|
action: string,
|
||||||
|
createdAt?: string,
|
||||||
|
updatedAt?: string,
|
||||||
|
isDeleted: number = 0,
|
||||||
|
): Promise<void> {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getHistory(memoryId: string): Promise<any[]> {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
async reset(): Promise<void> {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
close(): void {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
58
mem0-ts/src/oss/src/storage/MemoryHistoryManager.ts
Normal file
58
mem0-ts/src/oss/src/storage/MemoryHistoryManager.ts
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
import { v4 as uuidv4 } from "uuid";
|
||||||
|
import { HistoryManager } from "./base";
|
||||||
|
interface HistoryEntry {
|
||||||
|
id: string;
|
||||||
|
memory_id: string;
|
||||||
|
previous_value: string | null;
|
||||||
|
new_value: string | null;
|
||||||
|
action: string;
|
||||||
|
created_at: string;
|
||||||
|
updated_at: string | null;
|
||||||
|
is_deleted: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class MemoryHistoryManager implements HistoryManager {
|
||||||
|
private memoryStore: Map<string, HistoryEntry> = new Map();
|
||||||
|
|
||||||
|
async addHistory(
|
||||||
|
memoryId: string,
|
||||||
|
previousValue: string | null,
|
||||||
|
newValue: string | null,
|
||||||
|
action: string,
|
||||||
|
createdAt?: string,
|
||||||
|
updatedAt?: string,
|
||||||
|
isDeleted: number = 0,
|
||||||
|
): Promise<void> {
|
||||||
|
const historyEntry: HistoryEntry = {
|
||||||
|
id: uuidv4(),
|
||||||
|
memory_id: memoryId,
|
||||||
|
previous_value: previousValue,
|
||||||
|
new_value: newValue,
|
||||||
|
action: action,
|
||||||
|
created_at: createdAt || new Date().toISOString(),
|
||||||
|
updated_at: updatedAt || null,
|
||||||
|
is_deleted: isDeleted,
|
||||||
|
};
|
||||||
|
|
||||||
|
this.memoryStore.set(historyEntry.id, historyEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getHistory(memoryId: string): Promise<any[]> {
|
||||||
|
return Array.from(this.memoryStore.values())
|
||||||
|
.filter((entry) => entry.memory_id === memoryId)
|
||||||
|
.sort(
|
||||||
|
(a, b) =>
|
||||||
|
new Date(b.created_at).getTime() - new Date(a.created_at).getTime(),
|
||||||
|
)
|
||||||
|
.slice(0, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
async reset(): Promise<void> {
|
||||||
|
this.memoryStore.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
close(): void {
|
||||||
|
// No need to close anything for in-memory storage
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import sqlite3 from "sqlite3";
|
import sqlite3 from "sqlite3";
|
||||||
import { promisify } from "util";
|
import { HistoryManager } from "./base";
|
||||||
|
|
||||||
export class SQLiteManager {
|
export class SQLiteManager implements HistoryManager {
|
||||||
private db: sqlite3.Database;
|
private db: sqlite3.Database;
|
||||||
|
|
||||||
constructor(dbPath: string) {
|
constructor(dbPath: string) {
|
||||||
|
|||||||
121
mem0-ts/src/oss/src/storage/SupabaseHistoryManager.ts
Normal file
121
mem0-ts/src/oss/src/storage/SupabaseHistoryManager.ts
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
import { createClient, SupabaseClient } from "@supabase/supabase-js";
|
||||||
|
import { v4 as uuidv4 } from "uuid";
|
||||||
|
import { HistoryManager } from "./base";
|
||||||
|
|
||||||
|
interface HistoryEntry {
|
||||||
|
id: string;
|
||||||
|
memory_id: string;
|
||||||
|
previous_value: string | null;
|
||||||
|
new_value: string | null;
|
||||||
|
action: string;
|
||||||
|
created_at: string;
|
||||||
|
updated_at: string | null;
|
||||||
|
is_deleted: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SupabaseHistoryConfig {
|
||||||
|
supabaseUrl: string;
|
||||||
|
supabaseKey: string;
|
||||||
|
tableName?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SupabaseHistoryManager implements HistoryManager {
|
||||||
|
private supabase: SupabaseClient;
|
||||||
|
private readonly tableName: string;
|
||||||
|
|
||||||
|
constructor(config: SupabaseHistoryConfig) {
|
||||||
|
this.tableName = config.tableName || "memory_history";
|
||||||
|
this.supabase = createClient(config.supabaseUrl, config.supabaseKey);
|
||||||
|
this.initializeSupabase().catch(console.error);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async initializeSupabase(): Promise<void> {
|
||||||
|
// Check if table exists
|
||||||
|
const { error } = await this.supabase
|
||||||
|
.from(this.tableName)
|
||||||
|
.select("id")
|
||||||
|
.limit(1);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
console.error(
|
||||||
|
"Error: Table does not exist. Please run this SQL in your Supabase SQL Editor:",
|
||||||
|
);
|
||||||
|
console.error(`
|
||||||
|
create table ${this.tableName} (
|
||||||
|
id text primary key,
|
||||||
|
memory_id text not null,
|
||||||
|
previous_value text,
|
||||||
|
new_value text,
|
||||||
|
action text not null,
|
||||||
|
created_at timestamp with time zone default timezone('utc', now()),
|
||||||
|
updated_at timestamp with time zone,
|
||||||
|
is_deleted integer default 0
|
||||||
|
);
|
||||||
|
`);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async addHistory(
|
||||||
|
memoryId: string,
|
||||||
|
previousValue: string | null,
|
||||||
|
newValue: string | null,
|
||||||
|
action: string,
|
||||||
|
createdAt?: string,
|
||||||
|
updatedAt?: string,
|
||||||
|
isDeleted: number = 0,
|
||||||
|
): Promise<void> {
|
||||||
|
const historyEntry: HistoryEntry = {
|
||||||
|
id: uuidv4(),
|
||||||
|
memory_id: memoryId,
|
||||||
|
previous_value: previousValue,
|
||||||
|
new_value: newValue,
|
||||||
|
action: action,
|
||||||
|
created_at: createdAt || new Date().toISOString(),
|
||||||
|
updated_at: updatedAt || null,
|
||||||
|
is_deleted: isDeleted,
|
||||||
|
};
|
||||||
|
|
||||||
|
const { error } = await this.supabase
|
||||||
|
.from(this.tableName)
|
||||||
|
.insert(historyEntry);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
console.error("Error adding history to Supabase:", error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async getHistory(memoryId: string): Promise<any[]> {
|
||||||
|
const { data, error } = await this.supabase
|
||||||
|
.from(this.tableName)
|
||||||
|
.select("*")
|
||||||
|
.eq("memory_id", memoryId)
|
||||||
|
.order("created_at", { ascending: false })
|
||||||
|
.limit(100);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
console.error("Error getting history from Supabase:", error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data || [];
|
||||||
|
}
|
||||||
|
|
||||||
|
async reset(): Promise<void> {
|
||||||
|
const { error } = await this.supabase
|
||||||
|
.from(this.tableName)
|
||||||
|
.delete()
|
||||||
|
.neq("id", "");
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
console.error("Error resetting Supabase history:", error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
close(): void {
|
||||||
|
// No need to close anything as connections are handled by the client
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
14
mem0-ts/src/oss/src/storage/base.ts
Normal file
14
mem0-ts/src/oss/src/storage/base.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
export interface HistoryManager {
|
||||||
|
addHistory(
|
||||||
|
memoryId: string,
|
||||||
|
previousValue: string | null,
|
||||||
|
newValue: string | null,
|
||||||
|
action: string,
|
||||||
|
createdAt?: string,
|
||||||
|
updatedAt?: string,
|
||||||
|
isDeleted?: number,
|
||||||
|
): Promise<void>;
|
||||||
|
getHistory(memoryId: string): Promise<any[]>;
|
||||||
|
reset(): Promise<void>;
|
||||||
|
close(): void;
|
||||||
|
}
|
||||||
@@ -1 +1,5 @@
|
|||||||
export * from "./SQLiteManager";
|
export * from "./SQLiteManager";
|
||||||
|
export * from "./DummyHistoryManager";
|
||||||
|
export * from "./SupabaseHistoryManager";
|
||||||
|
export * from "./MemoryHistoryManager";
|
||||||
|
export * from "./base";
|
||||||
|
|||||||
@@ -24,6 +24,16 @@ export interface VectorStoreConfig {
|
|||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface HistoryStoreConfig {
|
||||||
|
provider: string;
|
||||||
|
config: {
|
||||||
|
historyDbPath?: string;
|
||||||
|
supabaseUrl?: string;
|
||||||
|
supabaseKey?: string;
|
||||||
|
tableName?: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export interface LLMConfig {
|
export interface LLMConfig {
|
||||||
provider?: string;
|
provider?: string;
|
||||||
config?: Record<string, any>;
|
config?: Record<string, any>;
|
||||||
@@ -58,6 +68,8 @@ export interface MemoryConfig {
|
|||||||
provider: string;
|
provider: string;
|
||||||
config: LLMConfig;
|
config: LLMConfig;
|
||||||
};
|
};
|
||||||
|
historyStore?: HistoryStoreConfig;
|
||||||
|
disableHistory?: boolean;
|
||||||
historyDbPath?: string;
|
historyDbPath?: string;
|
||||||
customPrompt?: string;
|
customPrompt?: string;
|
||||||
graphStore?: GraphStoreConfig;
|
graphStore?: GraphStoreConfig;
|
||||||
@@ -137,4 +149,11 @@ export const MemoryConfigSchema = z.object({
|
|||||||
customPrompt: z.string().optional(),
|
customPrompt: z.string().optional(),
|
||||||
})
|
})
|
||||||
.optional(),
|
.optional(),
|
||||||
|
historyStore: z
|
||||||
|
.object({
|
||||||
|
provider: z.string(),
|
||||||
|
config: z.record(z.string(), z.any()),
|
||||||
|
})
|
||||||
|
.optional(),
|
||||||
|
disableHistory: z.boolean().optional(),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -5,7 +5,12 @@ import { OpenAIStructuredLLM } from "../llms/openai_structured";
|
|||||||
import { AnthropicLLM } from "../llms/anthropic";
|
import { AnthropicLLM } from "../llms/anthropic";
|
||||||
import { GroqLLM } from "../llms/groq";
|
import { GroqLLM } from "../llms/groq";
|
||||||
import { MemoryVectorStore } from "../vector_stores/memory";
|
import { MemoryVectorStore } from "../vector_stores/memory";
|
||||||
import { EmbeddingConfig, LLMConfig, VectorStoreConfig } from "../types";
|
import {
|
||||||
|
EmbeddingConfig,
|
||||||
|
HistoryStoreConfig,
|
||||||
|
LLMConfig,
|
||||||
|
VectorStoreConfig,
|
||||||
|
} from "../types";
|
||||||
import { Embedder } from "../embeddings/base";
|
import { Embedder } from "../embeddings/base";
|
||||||
import { LLM } from "../llms/base";
|
import { LLM } from "../llms/base";
|
||||||
import { VectorStore } from "../vector_stores/base";
|
import { VectorStore } from "../vector_stores/base";
|
||||||
@@ -13,6 +18,10 @@ import { Qdrant } from "../vector_stores/qdrant";
|
|||||||
import { RedisDB } from "../vector_stores/redis";
|
import { RedisDB } from "../vector_stores/redis";
|
||||||
import { OllamaLLM } from "../llms/ollama";
|
import { OllamaLLM } from "../llms/ollama";
|
||||||
import { SupabaseDB } from "../vector_stores/supabase";
|
import { SupabaseDB } from "../vector_stores/supabase";
|
||||||
|
import { SQLiteManager } from "../storage/SQLiteManager";
|
||||||
|
import { MemoryHistoryManager } from "../storage/MemoryHistoryManager";
|
||||||
|
import { SupabaseHistoryManager } from "../storage/SupabaseHistoryManager";
|
||||||
|
import { HistoryManager } from "../storage/base";
|
||||||
|
|
||||||
export class EmbedderFactory {
|
export class EmbedderFactory {
|
||||||
static create(provider: string, config: EmbeddingConfig): Embedder {
|
static create(provider: string, config: EmbeddingConfig): Embedder {
|
||||||
@@ -62,3 +71,22 @@ export class VectorStoreFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class HistoryManagerFactory {
|
||||||
|
static create(provider: string, config: HistoryStoreConfig): HistoryManager {
|
||||||
|
switch (provider.toLowerCase()) {
|
||||||
|
case "sqlite":
|
||||||
|
return new SQLiteManager(config.config.historyDbPath || ":memory:");
|
||||||
|
case "supabase":
|
||||||
|
return new SupabaseHistoryManager({
|
||||||
|
supabaseUrl: config.config.supabaseUrl || "",
|
||||||
|
supabaseKey: config.config.supabaseKey || "",
|
||||||
|
tableName: config.config.tableName || "memory_history",
|
||||||
|
});
|
||||||
|
case "memory":
|
||||||
|
return new MemoryHistoryManager();
|
||||||
|
default:
|
||||||
|
throw new Error(`Unsupported history store provider: ${provider}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -97,6 +97,11 @@ export class SupabaseDB implements VectorStore {
|
|||||||
try {
|
try {
|
||||||
// Verify table exists and vector operations work by attempting a test insert
|
// Verify table exists and vector operations work by attempting a test insert
|
||||||
const testVector = Array(1536).fill(0);
|
const testVector = Array(1536).fill(0);
|
||||||
|
try {
|
||||||
|
await this.client.from(this.tableName).delete().eq("id", "test_vector");
|
||||||
|
} catch (error) {
|
||||||
|
console.warn("No test vector to delete, safe to ignore.");
|
||||||
|
}
|
||||||
const { error: testError } = await this.client
|
const { error: testError } = await this.client
|
||||||
.from(this.tableName)
|
.from(this.tableName)
|
||||||
.insert({
|
.insert({
|
||||||
@@ -113,6 +118,50 @@ export class SupabaseDB implements VectorStore {
|
|||||||
1. The vector extension is enabled
|
1. The vector extension is enabled
|
||||||
2. The table "${this.tableName}" exists with correct schema
|
2. The table "${this.tableName}" exists with correct schema
|
||||||
3. The match_vectors function is created
|
3. The match_vectors function is created
|
||||||
|
|
||||||
|
RUN THE FOLLOWING SQL IN YOUR SUPABASE SQL EDITOR:
|
||||||
|
|
||||||
|
-- Enable the vector extension
|
||||||
|
create extension if not exists vector;
|
||||||
|
|
||||||
|
-- Create the memories table
|
||||||
|
create table if not exists memories (
|
||||||
|
id text primary key,
|
||||||
|
embedding vector(1536),
|
||||||
|
metadata jsonb,
|
||||||
|
created_at timestamp with time zone default timezone('utc', now()),
|
||||||
|
updated_at timestamp with time zone default timezone('utc', now())
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Create the vector similarity search function
|
||||||
|
create or replace function match_vectors(
|
||||||
|
query_embedding vector(1536),
|
||||||
|
match_count int,
|
||||||
|
filter jsonb default '{}'::jsonb
|
||||||
|
)
|
||||||
|
returns table (
|
||||||
|
id text,
|
||||||
|
similarity float,
|
||||||
|
metadata jsonb
|
||||||
|
)
|
||||||
|
language plpgsql
|
||||||
|
as $$
|
||||||
|
begin
|
||||||
|
return query
|
||||||
|
select
|
||||||
|
id,
|
||||||
|
similarity,
|
||||||
|
metadata
|
||||||
|
from memories
|
||||||
|
where case
|
||||||
|
when filter::text = '{}'::text then true
|
||||||
|
else metadata @> filter
|
||||||
|
end
|
||||||
|
order by embedding <=> query_embedding
|
||||||
|
limit match_count;
|
||||||
|
end;
|
||||||
|
$$;
|
||||||
|
|
||||||
See the SQL migration instructions in the code comments.`,
|
See the SQL migration instructions in the code comments.`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user