refactor(api): rename "files" API to "artifacts"

The term "artifacts" better represents the purpose of this API, which
handles outputs generated by API executions, eventually stored objects
that can be of served by any storage interface (file, objects).

This aligns better with the industry convention of 'artifacts' (build
outputs, process results) rather than generic 'files'. 'files' would
be appropriate if the goal was to store and retrieve files purely.

Additionally, in our context, artifact is a better term since it will
handle:

* Data produced by SDG (Synthetic Data Generation) - as input
* Output of a trained model - as output

Signed-off-by: Sébastien Han <seb@redhat.com>
This commit is contained in:
Sébastien Han 2025-05-12 11:13:23 +02:00
parent a5d14749a5
commit fb3c9be1fd
10 changed files with 479 additions and 567 deletions

View file

@ -4,4 +4,4 @@
# This source code is licensed under the terms described in the LICENSE file in
# the root directory of this source tree.
from .files import * # noqa: F401 F403
from .artifacts import * # noqa: F401 F403

View file

@ -0,0 +1,166 @@
# 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.
from typing import Protocol, runtime_checkable
from pydantic import BaseModel
from llama_stack.apis.common.responses import PaginatedResponse
from llama_stack.providers.utils.telemetry.trace_protocol import trace_protocol
from llama_stack.schema_utils import json_schema_type, webmethod
@json_schema_type
class ArtifactUploadResponse(BaseModel):
"""
Response after initiating an artifact upload session.
:param id: ID of the upload session
:param uri: Upload URI for the artifact or artifact parts
:param offset: Upload content offset
:param size: Upload content size
"""
id: str
uri: str
offset: int
size: int
@json_schema_type
class ArtifactResponse(BaseModel):
"""
Response representing an artifact entry.
:param key: Key under which the artifact is stored (valid chars: a-zA-Z0-9_-/.)
:param mime_type: MIME type of the artifact
:param uri: Upload URI for the artifact contents
:param size: Size of the artifact in bytes
:param created_at: Timestamp of when the artifact was created
"""
key: str
mime_type: str
uri: str
size: int
created_at: int
@json_schema_type
class ArtifactDeleteRequest(BaseModel):
"""
Request model for deleting a single artifact.
:param key: Key under which the artifact is stored (valid chars: a-zA-Z0-9_-/.)
"""
key: str
@json_schema_type
class BulkDeleteRequest(BaseModel):
"""
Request model for bulk deletion of artifacts.
:param artifacts: List of artifacts to delete
"""
artifacts: list[ArtifactDeleteRequest]
@runtime_checkable
@trace_protocol
class Artifacts(Protocol):
@webmethod(route="/artifacts", method="POST")
async def create_upload_session(
self,
key: str,
mime_type: str,
size: int,
) -> ArtifactUploadResponse:
"""
Create a new upload session for an artifact identified by a key.
:param key: Key under which the artifact is stored (valid chars: a-zA-Z0-9_-/.)
:param mime_type: MIME type of the artifact
:param size: Artifact size in bytes
"""
...
@webmethod(route="/artifacts/sessions/{upload_id}", method="POST", raw_bytes_request_body=True)
async def upload_content_to_session(
self,
upload_id: str,
) -> ArtifactResponse | None:
"""
Upload artifact content to an existing upload session.
On the server, request body will have the raw bytes that are uploaded.
:param upload_id: ID of the upload session
"""
...
@webmethod(route="/artifacts/sessions/{upload_id}", method="GET")
async def get_upload_session_info(
self,
upload_id: str,
) -> ArtifactUploadResponse:
"""
Returns information about an existing upload session
:param upload_id: ID of the upload session
"""
...
@webmethod(route="/artifacts", method="GET")
async def list_artifacts(
self,
start_index: int | None = None,
limit: int | None = None,
) -> PaginatedResponse:
"""
List all artifacts with pagination.
:param start_index: Start index of the artifacts to list
:param limit: Number of artifacts to list
"""
...
@webmethod(route="/artifacts/{key:path}", method="GET")
async def get_artifact(
self,
key: str,
) -> ArtifactResponse:
"""
Get an artifact info identified by a key.
:param key: Key under which the artifact is stored (valid chars: a-zA-Z0-9_-/.)
"""
...
@webmethod(route="/artifacts/{key:path}", method="DELETE")
async def delete_artifact(
self,
key: str,
) -> None:
"""
Delete an artifact identified by a key.
:param key: Key under which the artifact is stored (valid chars: a-zA-Z0-9_-/.)
"""
...
@webmethod(route="/artifacts/bulk", method="POST")
async def bulk_delete_artifacts(
self,
request: BulkDeleteRequest,
) -> None:
"""
Delete multiple artifacts in a single request.
:param request: Bulk delete request containing list of artifacts to delete
"""
...

View file

@ -4,8 +4,6 @@
# This source code is licensed under the terms described in the LICENSE file in
# the root directory of this source tree.
from typing import Any
from pydantic import BaseModel
from llama_stack.schema_utils import json_schema_type
@ -19,5 +17,5 @@ class PaginatedResponse(BaseModel):
:param has_more: Whether there are more items available after this set
"""
data: list[dict[str, Any]]
data: list
has_more: bool

View file

@ -33,7 +33,7 @@ class Api(Enum):
scoring_functions = "scoring_functions"
benchmarks = "benchmarks"
tool_groups = "tool_groups"
files = "files"
artifacts = "artifacts"
# built-in API
inspect = "inspect"

View file

@ -1,174 +0,0 @@
# 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.
from typing import Protocol, runtime_checkable
from pydantic import BaseModel
from llama_stack.providers.utils.telemetry.trace_protocol import trace_protocol
from llama_stack.schema_utils import json_schema_type, webmethod
@json_schema_type
class FileUploadResponse(BaseModel):
"""
Response after initiating a file upload session.
:param id: ID of the upload session
:param url: Upload URL for the file or file parts
:param offset: Upload content offset
:param size: Upload content size
"""
id: str
url: str
offset: int
size: int
@json_schema_type
class BucketResponse(BaseModel):
name: str
@json_schema_type
class ListBucketResponse(BaseModel):
"""
Response representing a list of file entries.
:param data: List of FileResponse entries
"""
data: list[BucketResponse]
@json_schema_type
class FileResponse(BaseModel):
"""
Response representing a file entry.
:param bucket: Bucket under which the file is stored (valid chars: a-zA-Z0-9_-)
:param key: Key under which the file is stored (valid chars: a-zA-Z0-9_-/.)
:param mime_type: MIME type of the file
:param url: Upload URL for the file contents
:param bytes: Size of the file in bytes
:param created_at: Timestamp of when the file was created
"""
bucket: str
key: str
mime_type: str
url: str
bytes: int
created_at: int
@json_schema_type
class ListFileResponse(BaseModel):
"""
Response representing a list of file entries.
:param data: List of FileResponse entries
"""
data: list[FileResponse]
@runtime_checkable
@trace_protocol
class Files(Protocol):
@webmethod(route="/files", method="POST")
async def create_upload_session(
self,
bucket: str,
key: str,
mime_type: str,
size: int,
) -> FileUploadResponse:
"""
Create a new upload session for a file identified by a bucket and key.
:param bucket: Bucket under which the file is stored (valid chars: a-zA-Z0-9_-)
:param key: Key under which the file is stored (valid chars: a-zA-Z0-9_-/.)
:param mime_type: MIME type of the file
:param size: File size in bytes
"""
...
@webmethod(route="/files/session:{upload_id}", method="POST", raw_bytes_request_body=True)
async def upload_content_to_session(
self,
upload_id: str,
) -> FileResponse | None:
"""
Upload file content to an existing upload session.
On the server, request body will have the raw bytes that are uploaded.
:param upload_id: ID of the upload session
"""
...
@webmethod(route="/files/session:{upload_id}", method="GET")
async def get_upload_session_info(
self,
upload_id: str,
) -> FileUploadResponse:
"""
Returns information about an existsing upload session
:param upload_id: ID of the upload session
"""
...
@webmethod(route="/files", method="GET")
async def list_all_buckets(
self,
bucket: str,
) -> ListBucketResponse:
"""
List all buckets.
"""
...
@webmethod(route="/files/{bucket}", method="GET")
async def list_files_in_bucket(
self,
bucket: str,
) -> ListFileResponse:
"""
List all files in a bucket.
:param bucket: Bucket name (valid chars: a-zA-Z0-9_-)
"""
...
@webmethod(route="/files/{bucket}/{key:path}", method="GET")
async def get_file(
self,
bucket: str,
key: str,
) -> FileResponse:
"""
Get a file info identified by a bucket and key.
:param bucket: Bucket name (valid chars: a-zA-Z0-9_-)
:param key: Key under which the file is stored (valid chars: a-zA-Z0-9_-/.)
"""
...
@webmethod(route="/files/{bucket}/{key:path}", method="DELETE")
async def delete_file(
self,
bucket: str,
key: str,
) -> None:
"""
Delete a file identified by a bucket and key.
:param bucket: Bucket name (valid chars: a-zA-Z0-9_-)
:param key: Key under which the file is stored (valid chars: a-zA-Z0-9_-/.)
"""
...