From 91f1b352b4ca2c6d9a4624663bffbd2a8d98fb69 Mon Sep 17 00:00:00 2001 From: Charlie Doern Date: Tue, 18 Nov 2025 18:22:26 -0500 Subject: [PATCH] chore: add storage sane defaults (#4182) # What does this PR do? since `StackRunConfig` requires certain parts of `StorageConfig`, it'd probably make sense to template in some defaults that will "just work" for most usecases specifically introduce`ServerStoresConfig` defaults for inference, metadata, conversations and prompts. We already actually funnel in defaults for these sections ad-hoc throughout the codebase additionally set some `backends` defaults for the `StorageConfig`. This will alleviate some weirdness for `--providers` for run/list-deps and also some work I have to better align our list-deps/run datatypes --------- Signed-off-by: Charlie Doern --- src/llama_stack/core/storage/datatypes.py | 27 ++++++++++++++++--- .../unit/conversations/test_conversations.py | 6 +++++ tests/unit/core/test_stack_validation.py | 23 +++++++++++++--- 3 files changed, 49 insertions(+), 7 deletions(-) diff --git a/src/llama_stack/core/storage/datatypes.py b/src/llama_stack/core/storage/datatypes.py index 4b17b9ea9..527c1b828 100644 --- a/src/llama_stack/core/storage/datatypes.py +++ b/src/llama_stack/core/storage/datatypes.py @@ -12,6 +12,8 @@ from typing import Annotated, Literal from pydantic import BaseModel, Field, field_validator +from llama_stack.core.utils.config_dirs import DISTRIBS_BASE_DIR + class StorageBackendType(StrEnum): KV_REDIS = "kv_redis" @@ -256,15 +258,24 @@ class ResponsesStoreReference(InferenceStoreReference): class ServerStoresConfig(BaseModel): metadata: KVStoreReference | None = Field( - default=None, + default=KVStoreReference( + backend="kv_default", + namespace="registry", + ), description="Metadata store configuration (uses KV backend)", ) inference: InferenceStoreReference | None = Field( - default=None, + default=InferenceStoreReference( + backend="sql_default", + table_name="inference_store", + ), description="Inference store configuration (uses SQL backend)", ) conversations: SqlStoreReference | None = Field( - default=None, + default=SqlStoreReference( + backend="sql_default", + table_name="openai_conversations", + ), description="Conversations store configuration (uses SQL backend)", ) responses: ResponsesStoreReference | None = Field( @@ -272,13 +283,21 @@ class ServerStoresConfig(BaseModel): description="Responses store configuration (uses SQL backend)", ) prompts: KVStoreReference | None = Field( - default=None, + default=KVStoreReference(backend="kv_default", namespace="prompts"), description="Prompts store configuration (uses KV backend)", ) class StorageConfig(BaseModel): backends: dict[str, StorageBackendConfig] = Field( + default={ + "kv_default": SqliteKVStoreConfig( + db_path=f"${{env.SQLITE_STORE_DIR:={DISTRIBS_BASE_DIR}}}/kvstore.db", + ), + "sql_default": SqliteSqlStoreConfig( + db_path=f"${{env.SQLITE_STORE_DIR:={DISTRIBS_BASE_DIR}}}/sql_store.db", + ), + }, description="Named backend configurations (e.g., 'default', 'cache')", ) stores: ServerStoresConfig = Field( diff --git a/tests/unit/conversations/test_conversations.py b/tests/unit/conversations/test_conversations.py index e8286576b..3f9df5fc0 100644 --- a/tests/unit/conversations/test_conversations.py +++ b/tests/unit/conversations/test_conversations.py @@ -38,6 +38,9 @@ async def service(): }, stores=ServerStoresConfig( conversations=SqlStoreReference(backend="sql_test", table_name="openai_conversations"), + metadata=None, + inference=None, + prompts=None, ), ) register_sqlstore_backends({"sql_test": storage.backends["sql_test"]}) @@ -142,6 +145,9 @@ async def test_policy_configuration(): }, stores=ServerStoresConfig( conversations=SqlStoreReference(backend="sql_test", table_name="openai_conversations"), + metadata=None, + inference=None, + prompts=None, ), ) register_sqlstore_backends({"sql_test": storage.backends["sql_test"]}) diff --git a/tests/unit/core/test_stack_validation.py b/tests/unit/core/test_stack_validation.py index 462a25c8b..5f75bc522 100644 --- a/tests/unit/core/test_stack_validation.py +++ b/tests/unit/core/test_stack_validation.py @@ -10,8 +10,9 @@ from unittest.mock import AsyncMock import pytest -from llama_stack.core.datatypes import QualifiedModel, SafetyConfig, StackRunConfig, StorageConfig, VectorStoresConfig +from llama_stack.core.datatypes import QualifiedModel, SafetyConfig, StackRunConfig, VectorStoresConfig from llama_stack.core.stack import validate_safety_config, validate_vector_stores_config +from llama_stack.core.storage.datatypes import ServerStoresConfig, StorageConfig from llama_stack_api import Api, ListModelsResponse, ListShieldsResponse, Model, ModelType, Shield @@ -21,7 +22,15 @@ class TestVectorStoresValidation: run_config = StackRunConfig( image_name="test", providers={}, - storage=StorageConfig(backends={}, stores={}), + storage=StorageConfig( + backends={}, + stores=ServerStoresConfig( + metadata=None, + inference=None, + conversations=None, + prompts=None, + ), + ), vector_stores=VectorStoresConfig( default_provider_id="faiss", default_embedding_model=QualifiedModel( @@ -41,7 +50,15 @@ class TestVectorStoresValidation: run_config = StackRunConfig( image_name="test", providers={}, - storage=StorageConfig(backends={}, stores={}), + storage=StorageConfig( + backends={}, + stores=ServerStoresConfig( + metadata=None, + inference=None, + conversations=None, + prompts=None, + ), + ), vector_stores=VectorStoresConfig( default_provider_id="faiss", default_embedding_model=QualifiedModel(