diff --git a/.release-please-manifest.json b/.release-please-manifest.json index b4e9013..6db19b9 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.16.0" + ".": "0.17.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index d1c4212..f5eb7d0 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 18 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/premai%2Fpremai-25d63a01824adb74eba6e672fea1205184b5ed7105af5be98dc0b8e45bc65fad.yml -openapi_spec_hash: b0c6d81a06eb23d7f31d3074afad7b2d -config_hash: 4c4b619097d71f725c588da6ada0a0f5 +configured_endpoints: 17 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/premai%2Fpremai-d71329d1d7714d540c1a90fdb5178337061b3a73cb691a24b8869c25d4f0abcb.yml +openapi_spec_hash: 9530f7daf03545cd24167b1adcb03f50 +config_hash: a84721ef021ce1dbb70854ae5ff9d7c5 diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a5b82a..5721867 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 0.17.0 (2025-11-12) + +Full Changelog: [v0.16.0...v0.17.0](https://github.com/premAI-io/prem-py-sdk/compare/v0.16.0...v0.17.0) + +### Features + +* **api:** api update ([739a8d7](https://github.com/premAI-io/prem-py-sdk/commit/739a8d7fa6b045c6e9c30fd7510245772344d50a)) + ## 0.16.0 (2025-11-12) Full Changelog: [v0.15.4...v0.16.0](https://github.com/premAI-io/prem-py-sdk/compare/v0.15.4...v0.16.0) diff --git a/api.md b/api.md index 5d18db1..dcb0ef5 100644 --- a/api.md +++ b/api.md @@ -69,13 +69,12 @@ Methods: Types: ```python -from premai.types import SnapshotCreateResponse, SnapshotCreateFromFilesResponse +from premai.types import SnapshotCreateResponse ``` Methods: - client.snapshots.create(\*\*params) -> SnapshotCreateResponse -- client.snapshots.create_from_files(\*\*params) -> SnapshotCreateFromFilesResponse # Recommendations diff --git a/pyproject.toml b/pyproject.toml index 3ad3bb0..bedcaa5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "premai" -version = "0.16.0" +version = "0.17.0" description = "The official Python library for the PremAI API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/premai/_version.py b/src/premai/_version.py index a48e9b0..1c4bb0e 100644 --- a/src/premai/_version.py +++ b/src/premai/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "premai" -__version__ = "0.16.0" # x-release-please-version +__version__ = "0.17.0" # x-release-please-version diff --git a/src/premai/resources/snapshots.py b/src/premai/resources/snapshots.py index 030b4d5..cf05152 100644 --- a/src/premai/resources/snapshots.py +++ b/src/premai/resources/snapshots.py @@ -2,13 +2,11 @@ from __future__ import annotations -from typing import Mapping, cast - import httpx -from ..types import snapshot_create_params, snapshot_create_from_files_params -from .._types import Body, Omit, Query, Headers, NotGiven, FileTypes, omit, not_given -from .._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform +from ..types import snapshot_create_params +from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given +from .._utils import maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -19,7 +17,6 @@ ) from .._base_client import make_request_options from ..types.snapshot_create_response import SnapshotCreateResponse -from ..types.snapshot_create_from_files_response import SnapshotCreateFromFilesResponse __all__ = ["SnapshotsResource", "AsyncSnapshotsResource"] @@ -88,65 +85,6 @@ def create( cast_to=SnapshotCreateResponse, ) - def create_from_files( - self, - *, - label: str, - project_id: str, - training_file: FileTypes, - validation_file: FileTypes, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> SnapshotCreateFromFilesResponse: - """ - Create snapshot from separate training and validation files - - Args: - label: Snapshot name shown in the dashboard once the snapshot is created. - - project_id: Project ID that will own the generated snapshot. Must match an existing project. - - training_file: Required JSONL training file. Upload line-delimited messages that will form the - training split. - - validation_file: Required JSONL validation file. Upload line-delimited messages reserved for - validation. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - body = deepcopy_minimal( - { - "label": label, - "project_id": project_id, - "training_file": training_file, - "validation_file": validation_file, - } - ) - files = extract_files(cast(Mapping[str, object], body), paths=[["training_file"], ["validation_file"]]) - # It should be noted that the actual Content-Type header that will be - # sent to the server will contain a `boundary` parameter, e.g. - # multipart/form-data; boundary=---abc-- - extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} - return self._post( - "/api/v1/public/snapshots/create-from-files", - body=maybe_transform(body, snapshot_create_from_files_params.SnapshotCreateFromFilesParams), - files=files, - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=SnapshotCreateFromFilesResponse, - ) - class AsyncSnapshotsResource(AsyncAPIResource): @cached_property @@ -212,65 +150,6 @@ async def create( cast_to=SnapshotCreateResponse, ) - async def create_from_files( - self, - *, - label: str, - project_id: str, - training_file: FileTypes, - validation_file: FileTypes, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> SnapshotCreateFromFilesResponse: - """ - Create snapshot from separate training and validation files - - Args: - label: Snapshot name shown in the dashboard once the snapshot is created. - - project_id: Project ID that will own the generated snapshot. Must match an existing project. - - training_file: Required JSONL training file. Upload line-delimited messages that will form the - training split. - - validation_file: Required JSONL validation file. Upload line-delimited messages reserved for - validation. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - body = deepcopy_minimal( - { - "label": label, - "project_id": project_id, - "training_file": training_file, - "validation_file": validation_file, - } - ) - files = extract_files(cast(Mapping[str, object], body), paths=[["training_file"], ["validation_file"]]) - # It should be noted that the actual Content-Type header that will be - # sent to the server will contain a `boundary` parameter, e.g. - # multipart/form-data; boundary=---abc-- - extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} - return await self._post( - "/api/v1/public/snapshots/create-from-files", - body=await async_maybe_transform(body, snapshot_create_from_files_params.SnapshotCreateFromFilesParams), - files=files, - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=SnapshotCreateFromFilesResponse, - ) - class SnapshotsResourceWithRawResponse: def __init__(self, snapshots: SnapshotsResource) -> None: @@ -279,9 +158,6 @@ def __init__(self, snapshots: SnapshotsResource) -> None: self.create = to_raw_response_wrapper( snapshots.create, ) - self.create_from_files = to_raw_response_wrapper( - snapshots.create_from_files, - ) class AsyncSnapshotsResourceWithRawResponse: @@ -291,9 +167,6 @@ def __init__(self, snapshots: AsyncSnapshotsResource) -> None: self.create = async_to_raw_response_wrapper( snapshots.create, ) - self.create_from_files = async_to_raw_response_wrapper( - snapshots.create_from_files, - ) class SnapshotsResourceWithStreamingResponse: @@ -303,9 +176,6 @@ def __init__(self, snapshots: SnapshotsResource) -> None: self.create = to_streamed_response_wrapper( snapshots.create, ) - self.create_from_files = to_streamed_response_wrapper( - snapshots.create_from_files, - ) class AsyncSnapshotsResourceWithStreamingResponse: @@ -315,6 +185,3 @@ def __init__(self, snapshots: AsyncSnapshotsResource) -> None: self.create = async_to_streamed_response_wrapper( snapshots.create, ) - self.create_from_files = async_to_streamed_response_wrapper( - snapshots.create_from_files, - ) diff --git a/src/premai/types/__init__.py b/src/premai/types/__init__.py index 2bdab36..d1a8049 100644 --- a/src/premai/types/__init__.py +++ b/src/premai/types/__init__.py @@ -29,6 +29,4 @@ from .dataset_create_from_jsonl_params import DatasetCreateFromJSONLParams as DatasetCreateFromJSONLParams from .recommendation_generate_response import RecommendationGenerateResponse as RecommendationGenerateResponse from .dataset_create_synthetic_response import DatasetCreateSyntheticResponse as DatasetCreateSyntheticResponse -from .snapshot_create_from_files_params import SnapshotCreateFromFilesParams as SnapshotCreateFromFilesParams from .dataset_create_from_jsonl_response import DatasetCreateFromJSONLResponse as DatasetCreateFromJSONLResponse -from .snapshot_create_from_files_response import SnapshotCreateFromFilesResponse as SnapshotCreateFromFilesResponse diff --git a/src/premai/types/recommendation_get_response.py b/src/premai/types/recommendation_get_response.py index cb8bb07..8448142 100644 --- a/src/premai/types/recommendation_get_response.py +++ b/src/premai/types/recommendation_get_response.py @@ -3,47 +3,64 @@ from typing import List, Optional from typing_extensions import Literal -from pydantic import Field as FieldInfo - from .._models import BaseModel __all__ = [ "RecommendationGetResponse", + "RecommendedExperiment", "RecommendedModel", "RecommendedModelFullHyperparameters", "RecommendedModelLoraHyperparameters", ] +class RecommendedExperiment(BaseModel): + base_model_id: str + + batch_size: int + + learning_rate_multiplier: float + + lora: bool + + n_epochs: int + + reason_for_recommendation: Optional[str] = None + + recommended: bool + + class RecommendedModelFullHyperparameters(BaseModel): - batch_size: int = FieldInfo(alias="batchSize") + batch_size: int - learning_rate_multiplier: float = FieldInfo(alias="learningRateMultiplier") + learning_rate_multiplier: float - n_epochs: int = FieldInfo(alias="nEpochs") + n_epochs: int class RecommendedModelLoraHyperparameters(BaseModel): - batch_size: int = FieldInfo(alias="batchSize") + batch_size: int - learning_rate_multiplier: float = FieldInfo(alias="learningRateMultiplier") + learning_rate_multiplier: float - n_epochs: int = FieldInfo(alias="nEpochs") + n_epochs: int class RecommendedModel(BaseModel): - base_model_id: str = FieldInfo(alias="baseModelId") + base_model_id: str - full_hyperparameters: RecommendedModelFullHyperparameters + full_hyperparameters: Optional[RecommendedModelFullHyperparameters] = None - lora_hyperparameters: RecommendedModelLoraHyperparameters + lora_hyperparameters: Optional[RecommendedModelLoraHyperparameters] = None - reason_for_recommendation: Optional[str] = FieldInfo(alias="reasonForRecommendation", default=None) + reason_for_recommendation: Optional[str] = None recommended: bool class RecommendationGetResponse(BaseModel): + recommended_experiments: Optional[List[RecommendedExperiment]] = None + recommended_models: Optional[List[RecommendedModel]] = None snapshot_id: str diff --git a/src/premai/types/snapshot_create_from_files_params.py b/src/premai/types/snapshot_create_from_files_params.py deleted file mode 100644 index ee25bca..0000000 --- a/src/premai/types/snapshot_create_from_files_params.py +++ /dev/null @@ -1,32 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import Required, TypedDict - -from .._types import FileTypes - -__all__ = ["SnapshotCreateFromFilesParams"] - - -class SnapshotCreateFromFilesParams(TypedDict, total=False): - label: Required[str] - """Snapshot name shown in the dashboard once the snapshot is created.""" - - project_id: Required[str] - """Project ID that will own the generated snapshot. - - Must match an existing project. - """ - - training_file: Required[FileTypes] - """Required JSONL training file. - - Upload line-delimited messages that will form the training split. - """ - - validation_file: Required[FileTypes] - """Required JSONL validation file. - - Upload line-delimited messages reserved for validation. - """ diff --git a/src/premai/types/snapshot_create_from_files_response.py b/src/premai/types/snapshot_create_from_files_response.py deleted file mode 100644 index ab17412..0000000 --- a/src/premai/types/snapshot_create_from_files_response.py +++ /dev/null @@ -1,9 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from .._models import BaseModel - -__all__ = ["SnapshotCreateFromFilesResponse"] - - -class SnapshotCreateFromFilesResponse(BaseModel): - snapshot_id: str diff --git a/tests/api_resources/test_snapshots.py b/tests/api_resources/test_snapshots.py index dd59479..cea7f88 100644 --- a/tests/api_resources/test_snapshots.py +++ b/tests/api_resources/test_snapshots.py @@ -9,10 +9,7 @@ from premai import PremAI, AsyncPremAI from tests.utils import assert_matches_type -from premai.types import ( - SnapshotCreateResponse, - SnapshotCreateFromFilesResponse, -) +from premai.types import SnapshotCreateResponse base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -63,49 +60,6 @@ def test_streaming_response_create(self, client: PremAI) -> None: assert cast(Any, response.is_closed) is True - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_method_create_from_files(self, client: PremAI) -> None: - snapshot = client.snapshots.create_from_files( - label="x", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - training_file=b"raw file contents", - validation_file=b"raw file contents", - ) - assert_matches_type(SnapshotCreateFromFilesResponse, snapshot, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_raw_response_create_from_files(self, client: PremAI) -> None: - response = client.snapshots.with_raw_response.create_from_files( - label="x", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - training_file=b"raw file contents", - validation_file=b"raw file contents", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - snapshot = response.parse() - assert_matches_type(SnapshotCreateFromFilesResponse, snapshot, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - def test_streaming_response_create_from_files(self, client: PremAI) -> None: - with client.snapshots.with_streaming_response.create_from_files( - label="x", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - training_file=b"raw file contents", - validation_file=b"raw file contents", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - snapshot = response.parse() - assert_matches_type(SnapshotCreateFromFilesResponse, snapshot, path=["response"]) - - assert cast(Any, response.is_closed) is True - class TestAsyncSnapshots: parametrize = pytest.mark.parametrize( @@ -154,46 +108,3 @@ async def test_streaming_response_create(self, async_client: AsyncPremAI) -> Non assert_matches_type(SnapshotCreateResponse, snapshot, path=["response"]) assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_method_create_from_files(self, async_client: AsyncPremAI) -> None: - snapshot = await async_client.snapshots.create_from_files( - label="x", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - training_file=b"raw file contents", - validation_file=b"raw file contents", - ) - assert_matches_type(SnapshotCreateFromFilesResponse, snapshot, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_raw_response_create_from_files(self, async_client: AsyncPremAI) -> None: - response = await async_client.snapshots.with_raw_response.create_from_files( - label="x", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - training_file=b"raw file contents", - validation_file=b"raw file contents", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - snapshot = await response.parse() - assert_matches_type(SnapshotCreateFromFilesResponse, snapshot, path=["response"]) - - @pytest.mark.skip(reason="Prism tests are disabled") - @parametrize - async def test_streaming_response_create_from_files(self, async_client: AsyncPremAI) -> None: - async with async_client.snapshots.with_streaming_response.create_from_files( - label="x", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - training_file=b"raw file contents", - validation_file=b"raw file contents", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - snapshot = await response.parse() - assert_matches_type(SnapshotCreateFromFilesResponse, snapshot, path=["response"]) - - assert cast(Any, response.is_closed) is True