Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 1 addition & 6 deletions llama_stack/cli/stack/_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,12 +295,7 @@ def _generate_run_config(
if build_config.external_providers_dir
else EXTERNAL_PROVIDERS_DIR,
)
if not run_config.inference_store:
run_config.inference_store = SqliteSqlStoreConfig(
**SqliteSqlStoreConfig.sample_run_config(
__distro_dir__=(DISTRIBS_BASE_DIR / image_name).as_posix(), db_name="inference_store.db"
)
)
# Persistence config defaults are handled by PersistenceConfig model validators
# build providers dict
provider_registry = get_provider_registry(build_config)
for api in apis:
Expand Down
26 changes: 10 additions & 16 deletions llama_stack/core/conversations/conversations.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
# This source code is licensed under the terms described in the LICENSE file in
# the root directory of this source tree.

import os
import secrets
import time
from typing import Any
Expand All @@ -21,30 +20,23 @@
Conversations,
Metadata,
)
from llama_stack.core.datatypes import AccessRule
from llama_stack.core.utils.config_dirs import DISTRIBS_BASE_DIR
from llama_stack.core.datatypes import AccessRule, StackRunConfig
from llama_stack.log import get_logger
from llama_stack.providers.utils.sqlstore.api import ColumnDefinition, ColumnType
from llama_stack.providers.utils.sqlstore.authorized_sqlstore import AuthorizedSqlStore
from llama_stack.providers.utils.sqlstore.sqlstore import (
SqliteSqlStoreConfig,
SqlStoreConfig,
sqlstore_impl,
)
from llama_stack.providers.utils.sqlstore.sqlstore import sqlstore_impl

logger = get_logger(name=__name__, category="openai_conversations")


class ConversationServiceConfig(BaseModel):
"""Configuration for the built-in conversation service.

:param conversations_store: SQL store configuration for conversations (defaults to SQLite)
:param run_config: Stack run configuration for resolving persistence
:param policy: Access control rules
"""

conversations_store: SqlStoreConfig = SqliteSqlStoreConfig(
db_path=(DISTRIBS_BASE_DIR / "conversations.db").as_posix()
)
run_config: StackRunConfig
policy: list[AccessRule] = []


Expand All @@ -63,14 +55,16 @@ def __init__(self, config: ConversationServiceConfig, deps: dict[Any, Any]):
self.deps = deps
self.policy = config.policy

base_sql_store = sqlstore_impl(config.conversations_store)
# Use conversations store reference from storage config
conversations_ref = config.run_config.storage.conversations
if not conversations_ref:
raise ValueError("storage.conversations must be configured in run config")

base_sql_store = sqlstore_impl(conversations_ref)
self.sql_store = AuthorizedSqlStore(base_sql_store, self.policy)

async def initialize(self) -> None:
"""Initialize the store and create tables."""
if isinstance(self.config.conversations_store, SqliteSqlStoreConfig):
os.makedirs(os.path.dirname(self.config.conversations_store.db_path), exist_ok=True)

await self.sql_store.create_table(
"openai_conversations",
{
Expand Down
40 changes: 6 additions & 34 deletions llama_stack/core/datatypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,8 @@
from llama_stack.apis.vector_dbs import VectorDB, VectorDBInput
from llama_stack.apis.vector_io import VectorIO
from llama_stack.core.access_control.datatypes import AccessRule
from llama_stack.core.storage.datatypes import KVStoreReference, StorageConfig
from llama_stack.providers.datatypes import Api, ProviderSpec
from llama_stack.providers.utils.kvstore.config import KVStoreConfig, SqliteKVStoreConfig
from llama_stack.providers.utils.sqlstore.sqlstore import SqlStoreConfig

LLAMA_STACK_BUILD_CONFIG_VERSION = 2
LLAMA_STACK_RUN_CONFIG_VERSION = 2
Expand Down Expand Up @@ -356,7 +355,7 @@


class QuotaConfig(BaseModel):
kvstore: SqliteKVStoreConfig = Field(description="Config for KV store backend (SQLite only for now)")
kvstore: KVStoreReference = Field(description="Config for KV store backend (SQLite only for now)")
anonymous_max_requests: int = Field(default=100, description="Max requests for unauthenticated clients per period")
authenticated_max_requests: int = Field(
default=1000, description="Max requests for authenticated clients per period"
Expand Down Expand Up @@ -438,18 +437,6 @@
)


class InferenceStoreConfig(BaseModel):
sql_store_config: SqlStoreConfig
max_write_queue_size: int = Field(default=10000, description="Max queued writes for inference store")
num_writers: int = Field(default=4, description="Number of concurrent background writers")


class ResponsesStoreConfig(BaseModel):
sql_store_config: SqlStoreConfig
max_write_queue_size: int = Field(default=10000, description="Max queued writes for responses store")
num_writers: int = Field(default=4, description="Number of concurrent background writers")


class StackRunConfig(BaseModel):
version: int = LLAMA_STACK_RUN_CONFIG_VERSION

Expand All @@ -476,26 +463,11 @@
can be instantiated multiple times (with different configs) if necessary.
""",
)
metadata_store: KVStoreConfig | None = Field(
default=None,
description="""
Configuration for the persistence store used by the distribution registry. If not specified,
a default SQLite store will be used.""",
)

inference_store: InferenceStoreConfig | SqlStoreConfig | None = Field(
default=None,
storage: StorageConfig = Field(
description="""
Configuration for the persistence store used by the inference API. Can be either a
InferenceStoreConfig (with queue tuning parameters) or a SqlStoreConfig (deprecated).
If not specified, a default SQLite store will be used.""",
)

conversations_store: SqlStoreConfig | None = Field(
default=None,
description="""
Configuration for the persistence store used by the conversations API.
If not specified, a default SQLite store will be used.""",
Storage backend configurations. Each backend is named, and can be referenced by various components

Check failure on line 468 in llama_stack/core/datatypes.py

View workflow job for this annotation

GitHub Actions / pre-commit

Ruff (W291)

llama_stack/core/datatypes.py:468:99: W291 Trailing whitespace
throughout the Stack (both by its core as well as providers).
""",
)

# registry of "resources" in the distribution
Expand Down
12 changes: 7 additions & 5 deletions llama_stack/core/prompts/prompts.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@

from llama_stack.apis.prompts import ListPromptsResponse, Prompt, Prompts
from llama_stack.core.datatypes import StackRunConfig
from llama_stack.core.utils.config_dirs import DISTRIBS_BASE_DIR
from llama_stack.core.storage.datatypes import KVStoreReference
from llama_stack.providers.utils.kvstore import KVStore, kvstore_impl
from llama_stack.providers.utils.kvstore.config import SqliteKVStoreConfig


class PromptServiceConfig(BaseModel):
Expand Down Expand Up @@ -41,10 +40,13 @@ def __init__(self, config: PromptServiceConfig, deps: dict[Any, Any]):
self.kvstore: KVStore

async def initialize(self) -> None:
kvstore_config = SqliteKVStoreConfig(
db_path=(DISTRIBS_BASE_DIR / self.config.run_config.image_name / "prompts.db").as_posix()
# Use metadata store backend with prompts-specific namespace
metadata_ref = self.config.run_config.storage.metadata
prompts_ref = KVStoreReference(
namespace="prompts",
backend=metadata_ref.backend if metadata_ref else None,
)
self.kvstore = await kvstore_impl(kvstore_config)
self.kvstore = await kvstore_impl(prompts_ref)

def _get_default_key(self, prompt_id: str) -> str:
"""Get the KVStore key that stores the default version number."""
Expand Down
13 changes: 10 additions & 3 deletions llama_stack/core/routers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@

from typing import Any

from llama_stack.core.datatypes import AccessRule, RoutedProtocol
from llama_stack.core.datatypes import (
AccessRule,
RoutedProtocol,
)
from llama_stack.core.stack import StackRunConfig
from llama_stack.core.store import DistributionRegistry
from llama_stack.providers.datatypes import Api, RoutingTable
Expand Down Expand Up @@ -76,9 +79,13 @@ async def get_auto_router_impl(
api_to_dep_impl[dep_name] = deps[dep_api]

# TODO: move pass configs to routers instead
if api == Api.inference and run_config.inference_store:
if api == Api.inference:
inference_ref = run_config.storage.inference
if not inference_ref:
raise ValueError("storage.inference must be configured in run config")

inference_store = InferenceStore(
config=run_config.inference_store,
reference=inference_ref,
policy=policy,
)
await inference_store.initialize()
Expand Down
23 changes: 22 additions & 1 deletion llama_stack/core/stack.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
from llama_stack.core.providers import ProviderImpl, ProviderImplConfig
from llama_stack.core.resolver import ProviderRegistry, resolve_impls
from llama_stack.core.routing_tables.common import CommonRoutingTableImpl
from llama_stack.core.storage.datatypes import StorageBackendConfig
from llama_stack.core.store.registry import create_dist_registry
from llama_stack.core.utils.dynamic import instantiate_class_type
from llama_stack.log import get_logger
Expand Down Expand Up @@ -329,6 +330,25 @@ def add_internal_implementations(impls: dict[Api, Any], run_config: StackRunConf
impls[Api.conversations] = conversations_impl


def _initialize_storage(run_config: StackRunConfig):
kv_backends: dict[str, StorageBackendConfig] = {}
sql_backends: dict[str, StorageBackendConfig] = {}
for backend_name, backend_config in run_config.storage.backends.items():
type = backend_config.type.value
if type.startswith("kv_"):
kv_backends[backend_name] = backend_config
elif type.startswith("sql_"):
sql_backends[backend_name] = backend_config
else:
raise ValueError(f"Unknown storage backend type: {type}")

from llama_stack.providers.utils.kvstore.kvstore import register_kvstore_backends
from llama_stack.providers.utils.sqlstore.sqlstore import register_sqlstore_backends

register_kvstore_backends(kv_backends)
register_sqlstore_backends(sql_backends)


class Stack:
def __init__(self, run_config: StackRunConfig, provider_registry: ProviderRegistry | None = None):
self.run_config = run_config
Expand All @@ -347,7 +367,8 @@ async def initialize(self):
TEST_RECORDING_CONTEXT.__enter__()
logger.info(f"API recording enabled: mode={os.environ.get('LLAMA_STACK_TEST_INFERENCE_MODE')}")

dist_registry, _ = await create_dist_registry(self.run_config.metadata_store, self.run_config.image_name)
_initialize_storage(self.run_config)
dist_registry, _ = await create_dist_registry(self.run_config.storage, self.run_config.image_name)
policy = self.run_config.server.auth.access_policy if self.run_config.server.auth else []

internal_impls = {}
Expand Down
5 changes: 5 additions & 0 deletions llama_stack/core/storage/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Copyright (c) Meta Platforms, Inc. and affiliates.
# All rights reserved.
#
# This source code is licensed under the terms described in the LICENSE file in
# the root directory of this source tree.
Loading
Loading