repositories
loading repo index
repositories
loading repo index
repository
loading code, commits, and activity
public Clawd ADK gateway launch mirror
stars
latest
clone command
git clone gitlawb://did:key:z6Mkq5mY...iFZ5/my-project-publ...git clone gitlawb://did:key:z6Mkq5mY.../my-project-publ...2fa351d6docs: add automaton and perps launch sources16d ago| #1 | from typing import Any, Dict, Optional |
| #2 | |
| #3 | from app.database import get_db |
| #4 | from app.models import Config as ConfigModel |
| #5 | from app.utils.memory import reset_memory_client |
| #6 | from fastapi import APIRouter, Depends, HTTPException |
| #7 | from pydantic import BaseModel, Field |
| #8 | from sqlalchemy.orm import Session |
| #9 | |
| #10 | router = APIRouter(prefix="/api/v1/config", tags=["config"]) |
| #11 | |
| #12 | class LLMConfig(BaseModel): |
| #13 | model: str = Field(..., description="LLM model name") |
| #14 | temperature: float = Field(..., description="Temperature setting for the model") |
| #15 | max_tokens: int = Field(..., description="Maximum tokens to generate") |
| #16 | api_key: Optional[str] = Field(None, description="API key or 'env:API_KEY' to use environment variable") |
| #17 | ollama_base_url: Optional[str] = Field(None, description="Base URL for Ollama server (e.g., http://host.docker.internal:11434)") |
| #18 | |
| #19 | class LLMProvider(BaseModel): |
| #20 | provider: str = Field(..., description="LLM provider name") |
| #21 | config: LLMConfig |
| #22 | |
| #23 | class EmbedderConfig(BaseModel): |
| #24 | model: str = Field(..., description="Embedder model name") |
| #25 | api_key: Optional[str] = Field(None, description="API key or 'env:API_KEY' to use environment variable") |
| #26 | ollama_base_url: Optional[str] = Field(None, description="Base URL for Ollama server (e.g., http://host.docker.internal:11434)") |
| #27 | |
| #28 | class EmbedderProvider(BaseModel): |
| #29 | provider: str = Field(..., description="Embedder provider name") |
| #30 | config: EmbedderConfig |
| #31 | |
| #32 | class VectorStoreProvider(BaseModel): |
| #33 | provider: str = Field(..., description="Vector store provider name") |
| #34 | # Below config can vary widely based on the vector store used. Refer https://docs.mem0.ai/components/vectordbs/config |
| #35 | config: Dict[str, Any] = Field(..., description="Vector store-specific configuration") |
| #36 | |
| #37 | class OpenMemoryConfig(BaseModel): |
| #38 | custom_instructions: Optional[str] = Field(None, description="Custom instructions for memory management and fact extraction") |
| #39 | |
| #40 | class Mem0Config(BaseModel): |
| #41 | llm: Optional[LLMProvider] = None |
| #42 | embedder: Optional[EmbedderProvider] = None |
| #43 | vector_store: Optional[VectorStoreProvider] = None |
| #44 | |
| #45 | class ConfigSchema(BaseModel): |
| #46 | openmemory: Optional[OpenMemoryConfig] = None |
| #47 | mem0: Optional[Mem0Config] = None |
| #48 | |
| #49 | def get_default_configuration(): |
| #50 | """Get the default configuration with sensible defaults for LLM and embedder.""" |
| #51 | return { |
| #52 | "openmemory": { |
| #53 | "custom_instructions": None |
| #54 | }, |
| #55 | "mem0": { |
| #56 | "llm": { |
| #57 | "provider": "openai", |
| #58 | "config": { |
| #59 | "model": "gpt-4o-mini", |
| #60 | "temperature": 0.1, |
| #61 | "max_tokens": 2000, |
| #62 | "api_key": "env:OPENAI_API_KEY" |
| #63 | } |
| #64 | }, |
| #65 | "embedder": { |
| #66 | "provider": "openai", |
| #67 | "config": { |
| #68 | "model": "text-embedding-3-small", |
| #69 | "api_key": "env:OPENAI_API_KEY" |
| #70 | } |
| #71 | }, |
| #72 | "vector_store": None |
| #73 | } |
| #74 | } |
| #75 | |
| #76 | def get_config_from_db(db: Session, key: str = "main"): |
| #77 | """Get configuration from database.""" |
| #78 | config = db.query(ConfigModel).filter(ConfigModel.key == key).first() |
| #79 | |
| #80 | if not config: |
| #81 | # Create default config with proper provider configurations |
| #82 | default_config = get_default_configuration() |
| #83 | db_config = ConfigModel(key=key, value=default_config) |
| #84 | db.add(db_config) |
| #85 | db.commit() |
| #86 | db.refresh(db_config) |
| #87 | return default_config |
| #88 | |
| #89 | # Ensure the config has all required sections with defaults |
| #90 | config_value = config.value |
| #91 | default_config = get_default_configuration() |
| #92 | |
| #93 | # Merge with defaults to ensure all required fields exist |
| #94 | if "openmemory" not in config_value: |
| #95 | config_value["openmemory"] = default_config["openmemory"] |
| #96 | |
| #97 | if "mem0" not in config_value: |
| #98 | config_value["mem0"] = default_config["mem0"] |
| #99 | else: |
| #100 | # Ensure LLM config exists with defaults |
| #101 | if "llm" not in config_value["mem0"] or config_value["mem0"]["llm"] is None: |
| #102 | config_value["mem0"]["llm"] = default_config["mem0"]["llm"] |
| #103 | |
| #104 | # Ensure embedder config exists with defaults |
| #105 | if "embedder" not in config_value["mem0"] or config_value["mem0"]["embedder"] is None: |
| #106 | config_value["mem0"]["embedder"] = default_config["mem0"]["embedder"] |
| #107 | |
| #108 | # Ensure vector_store config exists with defaults |
| #109 | if "vector_store" not in config_value["mem0"]: |
| #110 | config_value["mem0"]["vector_store"] = default_config["mem0"]["vector_store"] |
| #111 | |
| #112 | # Save the updated config back to database if it was modified |
| #113 | if config_value != config.value: |
| #114 | config.value = config_value |
| #115 | db.commit() |
| #116 | db.refresh(config) |
| #117 | |
| #118 | return config_value |
| #119 | |
| #120 | def save_config_to_db(db: Session, config: Dict[str, Any], key: str = "main"): |
| #121 | """Save configuration to database.""" |
| #122 | db_config = db.query(ConfigModel).filter(ConfigModel.key == key).first() |
| #123 | |
| #124 | if db_config: |
| #125 | db_config.value = config |
| #126 | db_config.updated_at = None # Will trigger the onupdate to set current time |
| #127 | else: |
| #128 | db_config = ConfigModel(key=key, value=config) |
| #129 | db.add(db_config) |
| #130 | |
| #131 | db.commit() |
| #132 | db.refresh(db_config) |
| #133 | return db_config.value |
| #134 | |
| #135 | @router.get("/", response_model=ConfigSchema) |
| #136 | async def get_configuration(db: Session = Depends(get_db)): |
| #137 | """Get the current configuration.""" |
| #138 | config = get_config_from_db(db) |
| #139 | return config |
| #140 | |
| #141 | @router.put("/", response_model=ConfigSchema) |
| #142 | async def update_configuration(config: ConfigSchema, db: Session = Depends(get_db)): |
| #143 | """Update the configuration.""" |
| #144 | current_config = get_config_from_db(db) |
| #145 | |
| #146 | # Convert to dict for processing |
| #147 | updated_config = current_config.copy() |
| #148 | |
| #149 | # Update openmemory settings if provided |
| #150 | if config.openmemory is not None: |
| #151 | if "openmemory" not in updated_config: |
| #152 | updated_config["openmemory"] = {} |
| #153 | updated_config["openmemory"].update(config.openmemory.dict(exclude_none=True)) |
| #154 | |
| #155 | # Update mem0 settings |
| #156 | updated_config["mem0"] = config.mem0.dict(exclude_none=True) |
| #157 | |
| #158 | |
| #159 | @router.patch("/", response_model=ConfigSchema) |
| #160 | async def patch_configuration(config_update: ConfigSchema, db: Session = Depends(get_db)): |
| #161 | """Update parts of the configuration.""" |
| #162 | current_config = get_config_from_db(db) |
| #163 | |
| #164 | def deep_update(source, overrides): |
| #165 | for key, value in overrides.items(): |
| #166 | if isinstance(value, dict) and key in source and isinstance(source[key], dict): |
| #167 | source[key] = deep_update(source[key], value) |
| #168 | else: |
| #169 | source[key] = value |
| #170 | return source |
| #171 | |
| #172 | update_data = config_update.dict(exclude_unset=True) |
| #173 | updated_config = deep_update(current_config, update_data) |
| #174 | |
| #175 | save_config_to_db(db, updated_config) |
| #176 | reset_memory_client() |
| #177 | return updated_config |
| #178 | |
| #179 | |
| #180 | @router.post("/reset", response_model=ConfigSchema) |
| #181 | async def reset_configuration(db: Session = Depends(get_db)): |
| #182 | """Reset the configuration to default values.""" |
| #183 | try: |
| #184 | # Get the default configuration with proper provider setups |
| #185 | default_config = get_default_configuration() |
| #186 | |
| #187 | # Save it as the current configuration in the database |
| #188 | save_config_to_db(db, default_config) |
| #189 | reset_memory_client() |
| #190 | return default_config |
| #191 | except Exception as e: |
| #192 | raise HTTPException( |
| #193 | status_code=500, |
| #194 | detail=f"Failed to reset configuration: {str(e)}" |
| #195 | ) |
| #196 | |
| #197 | @router.get("/mem0/llm", response_model=LLMProvider) |
| #198 | async def get_llm_configuration(db: Session = Depends(get_db)): |
| #199 | """Get only the LLM configuration.""" |
| #200 | config = get_config_from_db(db) |
| #201 | llm_config = config.get("mem0", {}).get("llm", {}) |
| #202 | return llm_config |
| #203 | |
| #204 | @router.put("/mem0/llm", response_model=LLMProvider) |
| #205 | async def update_llm_configuration(llm_config: LLMProvider, db: Session = Depends(get_db)): |
| #206 | """Update only the LLM configuration.""" |
| #207 | current_config = get_config_from_db(db) |
| #208 | |
| #209 | # Ensure mem0 key exists |
| #210 | if "mem0" not in current_config: |
| #211 | current_config["mem0"] = {} |
| #212 | |
| #213 | # Update the LLM configuration |
| #214 | current_config["mem0"]["llm"] = llm_config.dict(exclude_none=True) |
| #215 | |
| #216 | # Save the configuration to database |
| #217 | save_config_to_db(db, current_config) |
| #218 | reset_memory_client() |
| #219 | return current_config["mem0"]["llm"] |
| #220 | |
| #221 | @router.get("/mem0/embedder", response_model=EmbedderProvider) |
| #222 | async def get_embedder_configuration(db: Session = Depends(get_db)): |
| #223 | """Get only the Embedder configuration.""" |
| #224 | config = get_config_from_db(db) |
| #225 | embedder_config = config.get("mem0", {}).get("embedder", {}) |
| #226 | return embedder_config |
| #227 | |
| #228 | @router.put("/mem0/embedder", response_model=EmbedderProvider) |
| #229 | async def update_embedder_configuration(embedder_config: EmbedderProvider, db: Session = Depends(get_db)): |
| #230 | """Update only the Embedder configuration.""" |
| #231 | current_config = get_config_from_db(db) |
| #232 | |
| #233 | # Ensure mem0 key exists |
| #234 | if "mem0" not in current_config: |
| #235 | current_config["mem0"] = {} |
| #236 | |
| #237 | # Update the Embedder configuration |
| #238 | current_config["mem0"]["embedder"] = embedder_config.dict(exclude_none=True) |
| #239 | |
| #240 | # Save the configuration to database |
| #241 | save_config_to_db(db, current_config) |
| #242 | reset_memory_client() |
| #243 | return current_config["mem0"]["embedder"] |
| #244 | |
| #245 | @router.get("/mem0/vector_store", response_model=Optional[VectorStoreProvider]) |
| #246 | async def get_vector_store_configuration(db: Session = Depends(get_db)): |
| #247 | """Get only the Vector Store configuration.""" |
| #248 | config = get_config_from_db(db) |
| #249 | vector_store_config = config.get("mem0", {}).get("vector_store", None) |
| #250 | return vector_store_config |
| #251 | |
| #252 | @router.put("/mem0/vector_store", response_model=VectorStoreProvider) |
| #253 | async def update_vector_store_configuration(vector_store_config: VectorStoreProvider, db: Session = Depends(get_db)): |
| #254 | """Update only the Vector Store configuration.""" |
| #255 | current_config = get_config_from_db(db) |
| #256 | |
| #257 | # Ensure mem0 key exists |
| #258 | if "mem0" not in current_config: |
| #259 | current_config["mem0"] = {} |
| #260 | |
| #261 | # Update the Vector Store configuration |
| #262 | current_config["mem0"]["vector_store"] = vector_store_config.dict(exclude_none=True) |
| #263 | |
| #264 | # Save the configuration to database |
| #265 | save_config_to_db(db, current_config) |
| #266 | reset_memory_client() |
| #267 | return current_config["mem0"]["vector_store"] |
| #268 | |
| #269 | @router.get("/openmemory", response_model=OpenMemoryConfig) |
| #270 | async def get_openmemory_configuration(db: Session = Depends(get_db)): |
| #271 | """Get only the OpenMemory configuration.""" |
| #272 | config = get_config_from_db(db) |
| #273 | openmemory_config = config.get("openmemory", {}) |
| #274 | return openmemory_config |
| #275 | |
| #276 | @router.put("/openmemory", response_model=OpenMemoryConfig) |
| #277 | async def update_openmemory_configuration(openmemory_config: OpenMemoryConfig, db: Session = Depends(get_db)): |
| #278 | """Update only the OpenMemory configuration.""" |
| #279 | current_config = get_config_from_db(db) |
| #280 | |
| #281 | # Ensure openmemory key exists |
| #282 | if "openmemory" not in current_config: |
| #283 | current_config["openmemory"] = {} |
| #284 | |
| #285 | # Update the OpenMemory configuration |
| #286 | current_config["openmemory"].update(openmemory_config.dict(exclude_none=True)) |
| #287 | |
| #288 | # Save the configuration to database |
| #289 | save_config_to_db(db, current_config) |
| #290 | reset_memory_client() |
| #291 | return current_config["openmemory"] |
| #292 |