feat(memory-lancedb): Venice embeddings support (text-embedding-bge-m3)

- Add `provider: \"venice\" ` + baseUrl (https://api.venice.ai/api/v1)
- Dims: 1024 for bge-m3
- OpenAI client proxy
- UI/schema/enum support

Unlocks semantic memory w/o OpenAI key. Tested API response.
This commit is contained in:
Molty (Clawdbot PR Bot) 2026-01-28 16:56:52 -05:00
parent a7534dc223
commit 756c2cb621
2 changed files with 21 additions and 5 deletions

View File

@ -4,9 +4,10 @@ import { join } from "node:path";
export type MemoryConfig = { export type MemoryConfig = {
embedding: { embedding: {
provider: "openai"; provider: "openai" | "venice";
model?: string; model?: string;
apiKey: string; apiKey: string;
baseUrl?: string;
}; };
dbPath?: string; dbPath?: string;
autoCapture?: boolean; autoCapture?: boolean;
@ -22,6 +23,7 @@ const DEFAULT_DB_PATH = join(homedir(), ".clawdbot", "memory", "lancedb");
const EMBEDDING_DIMENSIONS: Record<string, number> = { const EMBEDDING_DIMENSIONS: Record<string, number> = {
"text-embedding-3-small": 1536, "text-embedding-3-small": 1536,
"text-embedding-3-large": 3072, "text-embedding-3-large": 3072,
"text-embedding-bge-m3": 1024,
}; };
function assertAllowedKeys( function assertAllowedKeys(
@ -70,15 +72,19 @@ export const memoryConfigSchema = {
if (!embedding || typeof embedding.apiKey !== "string") { if (!embedding || typeof embedding.apiKey !== "string") {
throw new Error("embedding.apiKey is required"); throw new Error("embedding.apiKey is required");
} }
assertAllowedKeys(embedding, ["apiKey", "model"], "embedding config"); assertAllowedKeys(embedding, ["apiKey", "model", "provider", "baseUrl"], "embedding config");
const provider = (embedding.provider as string) || "openai";
const baseUrl = embedding.baseUrl as string | undefined;
const model = resolveEmbeddingModel(embedding); const model = resolveEmbeddingModel(embedding);
return { return {
embedding: { embedding: {
provider: "openai", provider,
model, model,
apiKey: resolveEnvVars(embedding.apiKey), apiKey: resolveEnvVars(embedding.apiKey),
baseUrl,
}, },
dbPath: typeof cfg.dbPath === "string" ? cfg.dbPath : DEFAULT_DB_PATH, dbPath: typeof cfg.dbPath === "string" ? cfg.dbPath : DEFAULT_DB_PATH,
autoCapture: cfg.autoCapture !== false, autoCapture: cfg.autoCapture !== false,
@ -97,6 +103,15 @@ export const memoryConfigSchema = {
placeholder: DEFAULT_MODEL, placeholder: DEFAULT_MODEL,
help: "OpenAI embedding model to use", help: "OpenAI embedding model to use",
}, },
"embedding.provider": {
label: "Embedding Provider",
enum: {"openai": "OpenAI", "venice": "Venice"}
},
"embedding.baseUrl": {
label: "Base URL",
placeholder: "https://api.venice.ai/api/v1",
help: "For Venice or custom endpoints"
},
dbPath: { dbPath: {
label: "Database Path", label: "Database Path",
placeholder: "~/.clawdbot/memory/lancedb", placeholder: "~/.clawdbot/memory/lancedb",

View File

@ -156,8 +156,9 @@ class Embeddings {
constructor( constructor(
apiKey: string, apiKey: string,
private model: string, private model: string,
baseUrl?: string,
) { ) {
this.client = new OpenAI({ apiKey }); this.client = new OpenAI({ apiKey, baseURL: baseUrl });
} }
async embed(text: string): Promise<number[]> { async embed(text: string): Promise<number[]> {
@ -225,7 +226,7 @@ const memoryPlugin = {
const resolvedDbPath = api.resolvePath(cfg.dbPath!); const resolvedDbPath = api.resolvePath(cfg.dbPath!);
const vectorDim = vectorDimsForModel(cfg.embedding.model ?? "text-embedding-3-small"); const vectorDim = vectorDimsForModel(cfg.embedding.model ?? "text-embedding-3-small");
const db = new MemoryDB(resolvedDbPath, vectorDim); const db = new MemoryDB(resolvedDbPath, vectorDim);
const embeddings = new Embeddings(cfg.embedding.apiKey, cfg.embedding.model!); const embeddings = new Embeddings(cfg.embedding.apiKey, cfg.embedding.model!, cfg.embedding.baseUrl);
api.logger.info( api.logger.info(
`memory-lancedb: plugin registered (db: ${resolvedDbPath}, lazy init)`, `memory-lancedb: plugin registered (db: ${resolvedDbPath}, lazy init)`,