forked from phoenix-oss/llama-stack-mirror
chore: move all Llama Stack types from llama-models to llama-stack (#1098)
llama-models should have extremely minimal cruft. Its sole purpose should be didactic -- show the simplest implementation of the llama models and document the prompt formats, etc. This PR is the complement to https://github.com/meta-llama/llama-models/pull/279 ## Test Plan Ensure all `llama` CLI `model` sub-commands work: ```bash llama model list llama model download --model-id ... llama model prompt-format -m ... ``` Ran tests: ```bash cd tests/client-sdk LLAMA_STACK_CONFIG=fireworks pytest -s -v inference/ LLAMA_STACK_CONFIG=fireworks pytest -s -v vector_io/ LLAMA_STACK_CONFIG=fireworks pytest -s -v agents/ ``` Create a fresh venv `uv venv && source .venv/bin/activate` and run `llama stack build --template fireworks --image-type venv` followed by `llama stack run together --image-type venv` <-- the server runs Also checked that the OpenAPI generator can run and there is no change in the generated files as a result. ```bash cd docs/openapi_generator sh run_openapi_generator.sh ```
This commit is contained in:
parent
c0ee512980
commit
314ee09ae3
138 changed files with 8491 additions and 465 deletions
182
llama_stack/strong_typing/name.py
Normal file
182
llama_stack/strong_typing/name.py
Normal file
|
@ -0,0 +1,182 @@
|
|||
# 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.
|
||||
|
||||
"""
|
||||
Type-safe data interchange for Python data classes.
|
||||
|
||||
:see: https://github.com/hunyadi/strong_typing
|
||||
"""
|
||||
|
||||
import typing
|
||||
from typing import Any, Literal, Optional, Tuple, Union
|
||||
|
||||
from .auxiliary import _auxiliary_types
|
||||
from .inspection import (
|
||||
TypeLike,
|
||||
is_generic_dict,
|
||||
is_generic_list,
|
||||
is_type_optional,
|
||||
is_type_union,
|
||||
unwrap_generic_dict,
|
||||
unwrap_generic_list,
|
||||
unwrap_optional_type,
|
||||
unwrap_union_types,
|
||||
)
|
||||
|
||||
|
||||
class TypeFormatter:
|
||||
"""
|
||||
Type formatter.
|
||||
|
||||
:param use_union_operator: Whether to emit union types as `X | Y` as per PEP 604.
|
||||
"""
|
||||
|
||||
use_union_operator: bool
|
||||
|
||||
def __init__(self, use_union_operator: bool = False) -> None:
|
||||
self.use_union_operator = use_union_operator
|
||||
|
||||
def union_to_str(self, data_type_args: Tuple[TypeLike, ...]) -> str:
|
||||
if self.use_union_operator:
|
||||
return " | ".join(self.python_type_to_str(t) for t in data_type_args)
|
||||
else:
|
||||
if len(data_type_args) == 2 and type(None) in data_type_args:
|
||||
# Optional[T] is represented as Union[T, None]
|
||||
origin_name = "Optional"
|
||||
data_type_args = tuple(t for t in data_type_args if t is not type(None))
|
||||
else:
|
||||
origin_name = "Union"
|
||||
|
||||
args = ", ".join(self.python_type_to_str(t) for t in data_type_args)
|
||||
return f"{origin_name}[{args}]"
|
||||
|
||||
def plain_type_to_str(self, data_type: TypeLike) -> str:
|
||||
"Returns the string representation of a Python type without metadata."
|
||||
|
||||
# return forward references as the annotation string
|
||||
if isinstance(data_type, typing.ForwardRef):
|
||||
fwd: typing.ForwardRef = data_type
|
||||
return fwd.__forward_arg__
|
||||
elif isinstance(data_type, str):
|
||||
return data_type
|
||||
|
||||
origin = typing.get_origin(data_type)
|
||||
if origin is not None:
|
||||
data_type_args = typing.get_args(data_type)
|
||||
|
||||
if origin is dict: # Dict[T]
|
||||
origin_name = "Dict"
|
||||
elif origin is list: # List[T]
|
||||
origin_name = "List"
|
||||
elif origin is set: # Set[T]
|
||||
origin_name = "Set"
|
||||
elif origin is Union:
|
||||
return self.union_to_str(data_type_args)
|
||||
elif origin is Literal:
|
||||
args = ", ".join(repr(arg) for arg in data_type_args)
|
||||
return f"Literal[{args}]"
|
||||
else:
|
||||
origin_name = origin.__name__
|
||||
|
||||
args = ", ".join(self.python_type_to_str(t) for t in data_type_args)
|
||||
return f"{origin_name}[{args}]"
|
||||
|
||||
return data_type.__name__
|
||||
|
||||
def python_type_to_str(self, data_type: TypeLike) -> str:
|
||||
"Returns the string representation of a Python type."
|
||||
|
||||
if data_type is type(None):
|
||||
return "None"
|
||||
|
||||
# use compact name for alias types
|
||||
name = _auxiliary_types.get(data_type)
|
||||
if name is not None:
|
||||
return name
|
||||
|
||||
metadata = getattr(data_type, "__metadata__", None)
|
||||
if metadata is not None:
|
||||
# type is Annotated[T, ...]
|
||||
metatuple: Tuple[Any, ...] = metadata
|
||||
arg = typing.get_args(data_type)[0]
|
||||
|
||||
# check for auxiliary types with user-defined annotations
|
||||
metaset = set(metatuple)
|
||||
for auxiliary_type, auxiliary_name in _auxiliary_types.items():
|
||||
auxiliary_arg = typing.get_args(auxiliary_type)[0]
|
||||
if arg is not auxiliary_arg:
|
||||
continue
|
||||
|
||||
auxiliary_metatuple: Optional[Tuple[Any, ...]] = getattr(auxiliary_type, "__metadata__", None)
|
||||
if auxiliary_metatuple is None:
|
||||
continue
|
||||
|
||||
if metaset.issuperset(auxiliary_metatuple):
|
||||
# type is an auxiliary type with extra annotations
|
||||
auxiliary_args = ", ".join(repr(m) for m in metatuple if m not in auxiliary_metatuple)
|
||||
return f"Annotated[{auxiliary_name}, {auxiliary_args}]"
|
||||
|
||||
# type is an annotated type
|
||||
args = ", ".join(repr(m) for m in metatuple)
|
||||
return f"Annotated[{self.plain_type_to_str(arg)}, {args}]"
|
||||
else:
|
||||
# type is a regular type
|
||||
return self.plain_type_to_str(data_type)
|
||||
|
||||
|
||||
def python_type_to_str(data_type: TypeLike, use_union_operator: bool = False) -> str:
|
||||
"""
|
||||
Returns the string representation of a Python type.
|
||||
|
||||
:param use_union_operator: Whether to emit union types as `X | Y` as per PEP 604.
|
||||
"""
|
||||
|
||||
fmt = TypeFormatter(use_union_operator)
|
||||
return fmt.python_type_to_str(data_type)
|
||||
|
||||
|
||||
def python_type_to_name(data_type: TypeLike, force: bool = False) -> str:
|
||||
"""
|
||||
Returns the short name of a Python type.
|
||||
|
||||
:param force: Whether to produce a name for composite types such as generics.
|
||||
"""
|
||||
|
||||
# use compact name for alias types
|
||||
name = _auxiliary_types.get(data_type)
|
||||
if name is not None:
|
||||
return name
|
||||
|
||||
# unwrap annotated types
|
||||
metadata = getattr(data_type, "__metadata__", None)
|
||||
if metadata is not None:
|
||||
# type is Annotated[T, ...]
|
||||
arg = typing.get_args(data_type)[0]
|
||||
return python_type_to_name(arg)
|
||||
|
||||
if force:
|
||||
# generic types
|
||||
if is_type_optional(data_type, strict=True):
|
||||
inner_name = python_type_to_name(unwrap_optional_type(data_type))
|
||||
return f"Optional__{inner_name}"
|
||||
elif is_generic_list(data_type):
|
||||
item_name = python_type_to_name(unwrap_generic_list(data_type))
|
||||
return f"List__{item_name}"
|
||||
elif is_generic_dict(data_type):
|
||||
key_type, value_type = unwrap_generic_dict(data_type)
|
||||
key_name = python_type_to_name(key_type)
|
||||
value_name = python_type_to_name(value_type)
|
||||
return f"Dict__{key_name}__{value_name}"
|
||||
elif is_type_union(data_type):
|
||||
member_types = unwrap_union_types(data_type)
|
||||
member_names = "__".join(python_type_to_name(member_type) for member_type in member_types)
|
||||
return f"Union__{member_names}"
|
||||
|
||||
# named system or user-defined type
|
||||
if hasattr(data_type, "__name__") and not typing.get_args(data_type):
|
||||
return data_type.__name__
|
||||
|
||||
raise TypeError(f"cannot assign a simple name to type: {data_type}")
|
Loading…
Add table
Add a link
Reference in a new issue