From 639d26e1ac7e8641f04f93a7d7253aa78e72161e Mon Sep 17 00:00:00 2001 From: Vedant Thakkar <75464324+vedant381@users.noreply.github.com> Date: Thu, 23 Oct 2025 18:36:25 +0530 Subject: [PATCH] feat(api): add vector store configuration endpoints (#3583) --- openmemory/api/app/routers/config.py | 62 +++++++++++++++++++++++++--- 1 file changed, 57 insertions(+), 5 deletions(-) diff --git a/openmemory/api/app/routers/config.py b/openmemory/api/app/routers/config.py index 7eaae4bfa..d55cf7829 100644 --- a/openmemory/api/app/routers/config.py +++ b/openmemory/api/app/routers/config.py @@ -29,16 +29,22 @@ class EmbedderProvider(BaseModel): provider: str = Field(..., description="Embedder provider name") config: EmbedderConfig +class VectorStoreProvider(BaseModel): + provider: str = Field(..., description="Vector store provider name") + # Below config can vary widely based on the vector store used. Refer https://docs.mem0.ai/components/vectordbs/config + config: Dict[str, Any] = Field(..., description="Vector store-specific configuration") + class OpenMemoryConfig(BaseModel): custom_instructions: Optional[str] = Field(None, description="Custom instructions for memory management and fact extraction") class Mem0Config(BaseModel): llm: Optional[LLMProvider] = None embedder: Optional[EmbedderProvider] = None + vector_store: Optional[VectorStoreProvider] = None class ConfigSchema(BaseModel): openmemory: Optional[OpenMemoryConfig] = None - mem0: Mem0Config + mem0: Optional[Mem0Config] = None def get_default_configuration(): """Get the default configuration with sensible defaults for LLM and embedder.""" @@ -62,7 +68,8 @@ def get_default_configuration(): "model": "text-embedding-3-small", "api_key": "env:OPENAI_API_KEY" } - } + }, + "vector_store": None } } @@ -97,7 +104,11 @@ def get_config_from_db(db: Session, key: str = "main"): # Ensure embedder config exists with defaults if "embedder" not in config_value["mem0"] or config_value["mem0"]["embedder"] is None: config_value["mem0"]["embedder"] = default_config["mem0"]["embedder"] - + + # Ensure vector_store config exists with defaults + if "vector_store" not in config_value["mem0"]: + config_value["mem0"]["vector_store"] = default_config["mem0"]["vector_store"] + # Save the updated config back to database if it was modified if config_value != config.value: config.value = config_value @@ -144,11 +155,28 @@ async def update_configuration(config: ConfigSchema, db: Session = Depends(get_d # Update mem0 settings updated_config["mem0"] = config.mem0.dict(exclude_none=True) - # Save the configuration to database + +@router.patch("/", response_model=ConfigSchema) +async def patch_configuration(config_update: ConfigSchema, db: Session = Depends(get_db)): + """Update parts of the configuration.""" + current_config = get_config_from_db(db) + + def deep_update(source, overrides): + for key, value in overrides.items(): + if isinstance(value, dict) and key in source and isinstance(source[key], dict): + source[key] = deep_update(source[key], value) + else: + source[key] = value + return source + + update_data = config_update.dict(exclude_unset=True) + updated_config = deep_update(current_config, update_data) + save_config_to_db(db, updated_config) reset_memory_client() return updated_config + @router.post("/reset", response_model=ConfigSchema) async def reset_configuration(db: Session = Depends(get_db)): """Reset the configuration to default values.""" @@ -214,6 +242,30 @@ async def update_embedder_configuration(embedder_config: EmbedderProvider, db: S reset_memory_client() return current_config["mem0"]["embedder"] +@router.get("/mem0/vector_store", response_model=Optional[VectorStoreProvider]) +async def get_vector_store_configuration(db: Session = Depends(get_db)): + """Get only the Vector Store configuration.""" + config = get_config_from_db(db) + vector_store_config = config.get("mem0", {}).get("vector_store", None) + return vector_store_config + +@router.put("/mem0/vector_store", response_model=VectorStoreProvider) +async def update_vector_store_configuration(vector_store_config: VectorStoreProvider, db: Session = Depends(get_db)): + """Update only the Vector Store configuration.""" + current_config = get_config_from_db(db) + + # Ensure mem0 key exists + if "mem0" not in current_config: + current_config["mem0"] = {} + + # Update the Vector Store configuration + current_config["mem0"]["vector_store"] = vector_store_config.dict(exclude_none=True) + + # Save the configuration to database + save_config_to_db(db, current_config) + reset_memory_client() + return current_config["mem0"]["vector_store"] + @router.get("/openmemory", response_model=OpenMemoryConfig) async def get_openmemory_configuration(db: Session = Depends(get_db)): """Get only the OpenMemory configuration.""" @@ -236,4 +288,4 @@ async def update_openmemory_configuration(openmemory_config: OpenMemoryConfig, d # Save the configuration to database save_config_to_db(db, current_config) reset_memory_client() - return current_config["openmemory"] \ No newline at end of file + return current_config["openmemory"]