mirror of
https://github.com/meta-llama/llama-stack.git
synced 2026-01-02 21:22:00 +00:00
Squashed commit of the following:
commit a95d2b15b83057e194cf69e57a03deeeeeadd7c2
Author: m-misiura <mmisiura@redhat.com>
Date: Mon Mar 24 14:33:50 2025 +0000
🚧 working on the config file so that it is inheriting from pydantic base models
commit 0546379f817e37bca030247b48c72ce84899a766
Author: m-misiura <mmisiura@redhat.com>
Date: Mon Mar 24 09:14:31 2025 +0000
🚧 dealing with ruff checks
commit 8abe39ee4cb4b8fb77c7252342c4809fa6ddc432
Author: m-misiura <mmisiura@redhat.com>
Date: Mon Mar 24 09:03:18 2025 +0000
🚧 dealing with mypy errors in `base.py`
commit 045f833e79c9a25af3d46af6c8896da91a0e6e62
Author: m-misiura <mmisiura@redhat.com>
Date: Fri Mar 21 17:31:25 2025 +0000
🚧 fixing mypy errors in content.py
commit a9c1ee4e92ad1b5db89039317555cd983edbde65
Author: m-misiura <mmisiura@redhat.com>
Date: Fri Mar 21 17:09:02 2025 +0000
🚧 fixing mypy errors in chat.py
commit 69e8ddc2f8a4e13cecbab30272fd7d685d7864ec
Author: m-misiura <mmisiura@redhat.com>
Date: Fri Mar 21 16:57:28 2025 +0000
🚧 fixing mypy errors
commit 56739d69a145c55335ac2859ecbe5b43d556e3b1
Author: m-misiura <mmisiura@redhat.com>
Date: Fri Mar 21 14:01:03 2025 +0000
🚧 fixing mypy errors in `__init__.py`
commit 4d2e3b55c4102ed75d997c8189847bbc5524cb2c
Author: m-misiura <mmisiura@redhat.com>
Date: Fri Mar 21 12:58:06 2025 +0000
🚧 ensuring routing_tables.py do not fail the ci
commit c0cc7b4b09ef50d5ec95fdb0a916c7ed228bf366
Author: m-misiura <mmisiura@redhat.com>
Date: Fri Mar 21 12:09:24 2025 +0000
🐛 fixing linter problems
commit 115a50211b604feb4106275204fe7f863da865f6
Author: m-misiura <mmisiura@redhat.com>
Date: Fri Mar 21 11:47:04 2025 +0000
🐛 fixing ruff errors
commit 29b5bfaabc77a35ea036b57f75fded711228dbbf
Author: m-misiura <mmisiura@redhat.com>
Date: Fri Mar 21 11:33:31 2025 +0000
🎨 automatic ruff fixes
commit 7c5a334c7d4649c2fc297993f89791c1e5643e5b
Author: m-misiura <mmisiura@redhat.com>
Date: Fri Mar 21 11:15:02 2025 +0000
Squashed commit of the following:
commit e671aae5bcd4ea57d601ee73c9e3adf5e223e830
Merge: b0dd9a4f 9114bef4
Author: Mac Misiura <82826099+m-misiura@users.noreply.github.com>
Date: Fri Mar 21 09:45:08 2025 +0000
Merge branch 'meta-llama:main' into feat_fms_remote_safety_provider
commit b0dd9a4f746b0c8c54d1189d381a7ff8e51c812c
Author: m-misiura <mmisiura@redhat.com>
Date: Fri Mar 21 09:27:21 2025 +0000
📝 updated `provider_id`
commit 4c8906c1a4e960968b93251d09d5e5735db15026
Author: m-misiura <mmisiura@redhat.com>
Date: Thu Mar 20 16:54:46 2025 +0000
📝 renaming from `fms` to `trustyai_fms`
commit 4c0b62abc51b02143b5c818f2d30e1a1fee9e4f3
Merge: bb842d69 54035825
Author: m-misiura <mmisiura@redhat.com>
Date: Thu Mar 20 16:35:52 2025 +0000
Merge branch 'main' into feat_fms_remote_safety_provider
commit bb842d69548df256927465792e0cd107a267d2a0
Author: m-misiura <mmisiura@redhat.com>
Date: Wed Mar 19 15:03:17 2025 +0000
✨ added a better way of handling params from the configs
commit 58b6beabf0994849ac50317ed00b748596e8961d
Merge: a22cf36c 7c044845
Author: m-misiura <mmisiura@redhat.com>
Date: Wed Mar 19 09:19:57 2025 +0000
Merge main into feat_fms_remote_safety_provider, resolve conflicts by keeping main version
commit a22cf36c8757f74ed656c1310a4be6b288bf923a
Author: m-misiura <mmisiura@redhat.com>
Date: Wed Mar 5 16:17:46 2025 +0000
🎉 added a new remote safety provider compatible with FMS Orchestrator API and Detectors API
Signed-off-by: m-misiura <mmisiura@redhat.com>
This commit is contained in:
parent
9e1ddf2b53
commit
87d209d6ef
7 changed files with 2883 additions and 20 deletions
|
|
@ -118,7 +118,9 @@ class CommonRoutingTableImpl(RoutingTable):
|
|||
self.dist_registry = dist_registry
|
||||
|
||||
async def initialize(self) -> None:
|
||||
async def add_objects(objs: List[RoutableObjectWithProvider], provider_id: str, cls) -> None:
|
||||
async def add_objects(
|
||||
objs: List[RoutableObjectWithProvider], provider_id: str, cls
|
||||
) -> None:
|
||||
for obj in objs:
|
||||
if cls is None:
|
||||
obj.provider_id = provider_id
|
||||
|
|
@ -153,7 +155,9 @@ class CommonRoutingTableImpl(RoutingTable):
|
|||
for p in self.impls_by_provider_id.values():
|
||||
await p.shutdown()
|
||||
|
||||
def get_provider_impl(self, routing_key: str, provider_id: Optional[str] = None) -> Any:
|
||||
def get_provider_impl(
|
||||
self, routing_key: str, provider_id: Optional[str] = None
|
||||
) -> Any:
|
||||
def apiname_object():
|
||||
if isinstance(self, ModelsRoutingTable):
|
||||
return ("Inference", "model")
|
||||
|
|
@ -191,24 +195,32 @@ class CommonRoutingTableImpl(RoutingTable):
|
|||
|
||||
raise ValueError(f"Provider not found for `{routing_key}`")
|
||||
|
||||
async def get_object_by_identifier(self, type: str, identifier: str) -> Optional[RoutableObjectWithProvider]:
|
||||
async def get_object_by_identifier(
|
||||
self, type: str, identifier: str
|
||||
) -> Optional[RoutableObjectWithProvider]:
|
||||
# Get from disk registry
|
||||
obj = await self.dist_registry.get(type, identifier)
|
||||
if not obj:
|
||||
return None
|
||||
|
||||
# Check if user has permission to access this object
|
||||
if not check_access(obj.identifier, getattr(obj, "access_attributes", None), get_auth_attributes()):
|
||||
logger.debug(f"Access denied to {type} '{identifier}' based on attribute mismatch")
|
||||
if not check_access(obj, get_auth_attributes()):
|
||||
logger.debug(
|
||||
f"Access denied to {type} '{identifier}' based on attribute mismatch"
|
||||
)
|
||||
return None
|
||||
|
||||
return obj
|
||||
|
||||
async def unregister_object(self, obj: RoutableObjectWithProvider) -> None:
|
||||
await self.dist_registry.delete(obj.type, obj.identifier)
|
||||
await unregister_object_from_provider(obj, self.impls_by_provider_id[obj.provider_id])
|
||||
await unregister_object_from_provider(
|
||||
obj, self.impls_by_provider_id[obj.provider_id]
|
||||
)
|
||||
|
||||
async def register_object(self, obj: RoutableObjectWithProvider) -> RoutableObjectWithProvider:
|
||||
async def register_object(
|
||||
self, obj: RoutableObjectWithProvider
|
||||
) -> RoutableObjectWithProvider:
|
||||
# if provider_id is not specified, pick an arbitrary one from existing entries
|
||||
if not obj.provider_id and len(self.impls_by_provider_id) > 0:
|
||||
obj.provider_id = list(self.impls_by_provider_id.keys())[0]
|
||||
|
|
@ -223,7 +235,9 @@ class CommonRoutingTableImpl(RoutingTable):
|
|||
creator_attributes = get_auth_attributes()
|
||||
if creator_attributes:
|
||||
obj.access_attributes = AccessAttributes(**creator_attributes)
|
||||
logger.info(f"Setting access attributes for {obj.type} '{obj.identifier}' based on creator's identity")
|
||||
logger.info(
|
||||
f"Setting access attributes for {obj.type} '{obj.identifier}' based on creator's identity"
|
||||
)
|
||||
|
||||
registered_obj = await register_object_with_provider(obj, p)
|
||||
# TODO: This needs to be fixed for all APIs once they return the registered object
|
||||
|
|
@ -242,9 +256,7 @@ class CommonRoutingTableImpl(RoutingTable):
|
|||
# Apply attribute-based access control filtering
|
||||
if filtered_objs:
|
||||
filtered_objs = [
|
||||
obj
|
||||
for obj in filtered_objs
|
||||
if check_access(obj.identifier, getattr(obj, "access_attributes", None), get_auth_attributes())
|
||||
obj for obj in filtered_objs if check_access(obj, get_auth_attributes())
|
||||
]
|
||||
|
||||
return filtered_objs
|
||||
|
|
@ -283,7 +295,9 @@ class ModelsRoutingTable(CommonRoutingTableImpl, Models):
|
|||
if model_type is None:
|
||||
model_type = ModelType.llm
|
||||
if "embedding_dimension" not in metadata and model_type == ModelType.embedding:
|
||||
raise ValueError("Embedding model must have an embedding dimension in its metadata")
|
||||
raise ValueError(
|
||||
"Embedding model must have an embedding dimension in its metadata"
|
||||
)
|
||||
model = ModelWithACL(
|
||||
identifier=model_id,
|
||||
provider_resource_id=provider_model_id,
|
||||
|
|
@ -302,8 +316,54 @@ class ModelsRoutingTable(CommonRoutingTableImpl, Models):
|
|||
|
||||
|
||||
class ShieldsRoutingTable(CommonRoutingTableImpl, Shields):
|
||||
async def initialize(self) -> None:
|
||||
"""Initialize routing table and providers"""
|
||||
# First do the common initialization
|
||||
await super().initialize()
|
||||
|
||||
# Then explicitly initialize each safety provider
|
||||
for provider_id, provider in self.impls_by_provider_id.items():
|
||||
api = get_impl_api(provider)
|
||||
if api == Api.safety:
|
||||
logger.info(f"Explicitly initializing safety provider: {provider_id}")
|
||||
await provider.initialize()
|
||||
|
||||
# Fetch shields after initialization - with robust error handling
|
||||
try:
|
||||
# Check if the provider implements list_shields
|
||||
if hasattr(provider, "list_shields") and callable(
|
||||
getattr(provider, "list_shields")
|
||||
):
|
||||
shields_response = await provider.list_shields()
|
||||
if (
|
||||
shields_response
|
||||
and hasattr(shields_response, "data")
|
||||
and shields_response.data
|
||||
):
|
||||
for shield in shields_response.data:
|
||||
# Ensure type is set
|
||||
if not hasattr(shield, "type") or not shield.type:
|
||||
shield.type = ResourceType.shield.value
|
||||
await self.dist_registry.register(shield)
|
||||
logger.info(
|
||||
f"Registered {len(shields_response.data)} shields from provider {provider_id}"
|
||||
)
|
||||
else:
|
||||
logger.info(f"No shields found for provider {provider_id}")
|
||||
else:
|
||||
logger.info(
|
||||
f"Provider {provider_id} does not support listing shields"
|
||||
)
|
||||
except Exception as e:
|
||||
# Log the error but continue initialization
|
||||
logger.warning(
|
||||
f"Error listing shields from provider {provider_id}: {str(e)}"
|
||||
)
|
||||
|
||||
async def list_shields(self) -> ListShieldsResponse:
|
||||
return ListShieldsResponse(data=await self.get_all_with_type(ResourceType.shield.value))
|
||||
return ListShieldsResponse(
|
||||
data=await self.get_all_with_type(ResourceType.shield.value)
|
||||
)
|
||||
|
||||
async def get_shield(self, identifier: str) -> Shield:
|
||||
shield = await self.get_object_by_identifier("shield", identifier)
|
||||
|
|
@ -368,14 +428,18 @@ class VectorDBsRoutingTable(CommonRoutingTableImpl, VectorDBs):
|
|||
f"No provider specified and multiple providers available. Arbitrarily selected the first provider {provider_id}."
|
||||
)
|
||||
else:
|
||||
raise ValueError("No provider available. Please configure a vector_io provider.")
|
||||
raise ValueError(
|
||||
"No provider available. Please configure a vector_io provider."
|
||||
)
|
||||
model = await self.get_object_by_identifier("model", embedding_model)
|
||||
if model is None:
|
||||
raise ValueError(f"Model {embedding_model} not found")
|
||||
if model.model_type != ModelType.embedding:
|
||||
raise ValueError(f"Model {embedding_model} is not an embedding model")
|
||||
if "embedding_dimension" not in model.metadata:
|
||||
raise ValueError(f"Model {embedding_model} does not have an embedding dimension")
|
||||
raise ValueError(
|
||||
f"Model {embedding_model} does not have an embedding dimension"
|
||||
)
|
||||
vector_db_data = {
|
||||
"identifier": vector_db_id,
|
||||
"type": ResourceType.vector_db.value,
|
||||
|
|
@ -397,7 +461,9 @@ class VectorDBsRoutingTable(CommonRoutingTableImpl, VectorDBs):
|
|||
|
||||
class DatasetsRoutingTable(CommonRoutingTableImpl, Datasets):
|
||||
async def list_datasets(self) -> ListDatasetsResponse:
|
||||
return ListDatasetsResponse(data=await self.get_all_with_type(ResourceType.dataset.value))
|
||||
return ListDatasetsResponse(
|
||||
data=await self.get_all_with_type(ResourceType.dataset.value)
|
||||
)
|
||||
|
||||
async def get_dataset(self, dataset_id: str) -> Dataset:
|
||||
dataset = await self.get_object_by_identifier("dataset", dataset_id)
|
||||
|
|
@ -459,10 +525,14 @@ class DatasetsRoutingTable(CommonRoutingTableImpl, Datasets):
|
|||
|
||||
class ScoringFunctionsRoutingTable(CommonRoutingTableImpl, ScoringFunctions):
|
||||
async def list_scoring_functions(self) -> ListScoringFunctionsResponse:
|
||||
return ListScoringFunctionsResponse(data=await self.get_all_with_type(ResourceType.scoring_function.value))
|
||||
return ListScoringFunctionsResponse(
|
||||
data=await self.get_all_with_type(ResourceType.scoring_function.value)
|
||||
)
|
||||
|
||||
async def get_scoring_function(self, scoring_fn_id: str) -> ScoringFn:
|
||||
scoring_fn = await self.get_object_by_identifier("scoring_function", scoring_fn_id)
|
||||
scoring_fn = await self.get_object_by_identifier(
|
||||
"scoring_function", scoring_fn_id
|
||||
)
|
||||
if scoring_fn is None:
|
||||
raise ValueError(f"Scoring function '{scoring_fn_id}' not found")
|
||||
return scoring_fn
|
||||
|
|
@ -565,8 +635,12 @@ class ToolGroupsRoutingTable(CommonRoutingTableImpl, ToolGroups):
|
|||
args: Optional[Dict[str, Any]] = None,
|
||||
) -> None:
|
||||
tools = []
|
||||
tool_defs = await self.impls_by_provider_id[provider_id].list_runtime_tools(toolgroup_id, mcp_endpoint)
|
||||
tool_host = ToolHost.model_context_protocol if mcp_endpoint else ToolHost.distribution
|
||||
tool_defs = await self.impls_by_provider_id[provider_id].list_runtime_tools(
|
||||
toolgroup_id, mcp_endpoint
|
||||
)
|
||||
tool_host = (
|
||||
ToolHost.model_context_protocol if mcp_endpoint else ToolHost.distribution
|
||||
)
|
||||
|
||||
for tool_def in tool_defs:
|
||||
tools.append(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue