Skip to content

Commit 30d7019

Browse files
feat(api): add new replicate.search() method (beta)
...and remove the old replicate.models.search() method from the MCP server, so tools will not have to decide between the two.
1 parent ab2920d commit 30d7019

File tree

8 files changed

+423
-14
lines changed

8 files changed

+423
-14
lines changed

.stats.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
configured_endpoints: 35
1+
configured_endpoints: 36
22
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/replicate%2Freplicate-client-87c7c57bd75c54990c679c9e87d009851cdff572815a55d1b6ee4d4ee20adaa1.yml
33
openapi_spec_hash: d987f14befa536004eece7b49caad993
4-
config_hash: b1b4f5d24ba07b4667ffe7b9dec081e3
4+
config_hash: aeed03640ab6ab81b9c732cf0b9c727c

api.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
# Replicate
2+
3+
Types:
4+
5+
```python
6+
from replicate.types import SearchResponse
7+
```
8+
9+
Methods:
10+
11+
- <code title="get /search">replicate.<a href="./src/replicate/_client.py">search</a>(\*\*<a href="src/replicate/types/client_search_params.py">params</a>) -> <a href="./src/replicate/types/search_response.py">SearchResponse</a></code>
12+
113
# Collections
214

315
Types:

src/replicate/_client.py

Lines changed: 162 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,25 +27,42 @@
2727

2828
from . import _exceptions
2929
from ._qs import Querystring
30+
from .types import client_search_params
3031
from ._types import (
3132
NOT_GIVEN,
33+
Body,
3234
Omit,
35+
Query,
36+
Headers,
3337
Timeout,
3438
NotGiven,
3539
Transport,
3640
ProxiesTypes,
3741
RequestOptions,
3842
)
39-
from ._utils import is_given, get_async_library
43+
from ._utils import (
44+
is_given,
45+
maybe_transform,
46+
get_async_library,
47+
async_maybe_transform,
48+
)
4049
from ._compat import cached_property
4150
from ._version import __version__
51+
from ._response import (
52+
to_raw_response_wrapper,
53+
to_streamed_response_wrapper,
54+
async_to_raw_response_wrapper,
55+
async_to_streamed_response_wrapper,
56+
)
4257
from ._streaming import Stream as Stream, AsyncStream as AsyncStream
4358
from ._exceptions import APIStatusError, ReplicateError
4459
from ._base_client import (
4560
DEFAULT_MAX_RETRIES,
4661
SyncAPIClient,
4762
AsyncAPIClient,
63+
make_request_options,
4864
)
65+
from .types.search_response import SearchResponse
4966

5067
if TYPE_CHECKING:
5168
from .resources import files, models, account, hardware, webhooks, trainings, collections, deployments, predictions
@@ -354,6 +371,70 @@ def copy(
354371
# client.with_options(timeout=10).foo.create(...)
355372
with_options = copy
356373

374+
def search(
375+
self,
376+
*,
377+
query: str,
378+
limit: int | NotGiven = NOT_GIVEN,
379+
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
380+
# The extra values given here take precedence over values defined on the client or passed to this method.
381+
extra_headers: Headers | None = None,
382+
extra_query: Query | None = None,
383+
extra_body: Body | None = None,
384+
timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
385+
) -> SearchResponse:
386+
"""
387+
Search for public models, collections, and docs using a text query.
388+
389+
For models, the response includes all model data, plus a new `metadata` object
390+
with the following fields:
391+
392+
- `generated_description`: A longer and more detailed AI-generated description
393+
of the model
394+
- `tags`: An array of tags for the model
395+
- `score`: A score for the model's relevance to the search query
396+
397+
Example cURL request:
398+
399+
```console
400+
curl -s \\
401+
-H "Authorization: Bearer $REPLICATE_API_TOKEN" \\
402+
"https://api.replicate.com/v1/search?query=nano+banana"
403+
```
404+
405+
Note: This search API is currently in beta and may change in future versions.
406+
407+
Args:
408+
query: The search query string
409+
410+
limit: Maximum number of model results to return (1-50, defaults to 20)
411+
412+
extra_headers: Send extra headers
413+
414+
extra_query: Add additional query parameters to the request
415+
416+
extra_body: Add additional JSON properties to the request
417+
418+
timeout: Override the client-level default timeout for this request, in seconds
419+
"""
420+
return self.get(
421+
"/search",
422+
options=make_request_options(
423+
extra_headers=extra_headers,
424+
extra_query=extra_query,
425+
extra_body=extra_body,
426+
timeout=timeout,
427+
query=maybe_transform(
428+
{
429+
"query": query,
430+
"limit": limit,
431+
},
432+
client_search_params.ClientSearchParams,
433+
),
434+
),
435+
cast_to=SearchResponse,
436+
)
437+
357438
@override
358439
def _make_status_error(
359440
self,
@@ -665,6 +746,70 @@ def copy(
665746
# client.with_options(timeout=10).foo.create(...)
666747
with_options = copy
667748

749+
async def search(
750+
self,
751+
*,
752+
query: str,
753+
limit: int | NotGiven = NOT_GIVEN,
754+
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
755+
# The extra values given here take precedence over values defined on the client or passed to this method.
756+
extra_headers: Headers | None = None,
757+
extra_query: Query | None = None,
758+
extra_body: Body | None = None,
759+
timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
760+
) -> SearchResponse:
761+
"""
762+
Search for public models, collections, and docs using a text query.
763+
764+
For models, the response includes all model data, plus a new `metadata` object
765+
with the following fields:
766+
767+
- `generated_description`: A longer and more detailed AI-generated description
768+
of the model
769+
- `tags`: An array of tags for the model
770+
- `score`: A score for the model's relevance to the search query
771+
772+
Example cURL request:
773+
774+
```console
775+
curl -s \\
776+
-H "Authorization: Bearer $REPLICATE_API_TOKEN" \\
777+
"https://api.replicate.com/v1/search?query=nano+banana"
778+
```
779+
780+
Note: This search API is currently in beta and may change in future versions.
781+
782+
Args:
783+
query: The search query string
784+
785+
limit: Maximum number of model results to return (1-50, defaults to 20)
786+
787+
extra_headers: Send extra headers
788+
789+
extra_query: Add additional query parameters to the request
790+
791+
extra_body: Add additional JSON properties to the request
792+
793+
timeout: Override the client-level default timeout for this request, in seconds
794+
"""
795+
return await self.get(
796+
"/search",
797+
options=make_request_options(
798+
extra_headers=extra_headers,
799+
extra_query=extra_query,
800+
extra_body=extra_body,
801+
timeout=timeout,
802+
query=await async_maybe_transform(
803+
{
804+
"query": query,
805+
"limit": limit,
806+
},
807+
client_search_params.ClientSearchParams,
808+
),
809+
),
810+
cast_to=SearchResponse,
811+
)
812+
668813
@override
669814
def _make_status_error(
670815
self,
@@ -705,6 +850,10 @@ class ReplicateWithRawResponse:
705850
def __init__(self, client: Replicate) -> None:
706851
self._client = client
707852

853+
self.search = to_raw_response_wrapper(
854+
client.search,
855+
)
856+
708857
@cached_property
709858
def collections(self) -> collections.CollectionsResourceWithRawResponse:
710859
from .resources.collections import CollectionsResourceWithRawResponse
@@ -766,6 +915,10 @@ class AsyncReplicateWithRawResponse:
766915
def __init__(self, client: AsyncReplicate) -> None:
767916
self._client = client
768917

918+
self.search = async_to_raw_response_wrapper(
919+
client.search,
920+
)
921+
769922
@cached_property
770923
def collections(self) -> collections.AsyncCollectionsResourceWithRawResponse:
771924
from .resources.collections import AsyncCollectionsResourceWithRawResponse
@@ -827,6 +980,10 @@ class ReplicateWithStreamedResponse:
827980
def __init__(self, client: Replicate) -> None:
828981
self._client = client
829982

983+
self.search = to_streamed_response_wrapper(
984+
client.search,
985+
)
986+
830987
@cached_property
831988
def collections(self) -> collections.CollectionsResourceWithStreamingResponse:
832989
from .resources.collections import CollectionsResourceWithStreamingResponse
@@ -888,6 +1045,10 @@ class AsyncReplicateWithStreamedResponse:
8881045
def __init__(self, client: AsyncReplicate) -> None:
8891046
self._client = client
8901047

1048+
self.search = async_to_streamed_response_wrapper(
1049+
client.search,
1050+
)
1051+
8911052
@cached_property
8921053
def collections(self) -> collections.AsyncCollectionsResourceWithStreamingResponse:
8931054
from .resources.collections import AsyncCollectionsResourceWithStreamingResponse

src/replicate/types/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from __future__ import annotations
44

55
from .prediction import Prediction as Prediction
6+
from .search_response import SearchResponse as SearchResponse
67
from .file_get_response import FileGetResponse as FileGetResponse
78
from .file_create_params import FileCreateParams as FileCreateParams
89
from .file_list_response import FileListResponse as FileListResponse
@@ -11,6 +12,7 @@
1112
from .model_list_response import ModelListResponse as ModelListResponse
1213
from .model_search_params import ModelSearchParams as ModelSearchParams
1314
from .account_get_response import AccountGetResponse as AccountGetResponse
15+
from .client_search_params import ClientSearchParams as ClientSearchParams
1416
from .file_create_response import FileCreateResponse as FileCreateResponse
1517
from .file_download_params import FileDownloadParams as FileDownloadParams
1618
from .model_create_response import ModelCreateResponse as ModelCreateResponse
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2+
3+
from __future__ import annotations
4+
5+
from typing_extensions import Required, TypedDict
6+
7+
__all__ = ["ClientSearchParams"]
8+
9+
10+
class ClientSearchParams(TypedDict, total=False):
11+
query: Required[str]
12+
"""The search query string"""
13+
14+
limit: int
15+
"""Maximum number of model results to return (1-50, defaults to 20)"""
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2+
3+
from typing import List, Optional
4+
from typing_extensions import Literal
5+
6+
from .._models import BaseModel
7+
8+
__all__ = ["SearchResponse", "Collection", "Model", "ModelMetadata", "ModelModel", "Page"]
9+
10+
11+
class Collection(BaseModel):
12+
description: str
13+
"""A description of the collection"""
14+
15+
name: str
16+
"""The name of the collection"""
17+
18+
slug: str
19+
"""The slug of the collection (lowercase with dashes)"""
20+
21+
models: Optional[List[str]] = None
22+
"""Array of model names in the collection"""
23+
24+
25+
class ModelMetadata(BaseModel):
26+
generated_description: Optional[str] = None
27+
"""AI-generated detailed description of the model"""
28+
29+
score: Optional[float] = None
30+
"""Search relevance score"""
31+
32+
tags: Optional[List[str]] = None
33+
"""Array of descriptive tags for the model"""
34+
35+
36+
class ModelModel(BaseModel):
37+
cover_image_url: Optional[str] = None
38+
"""A URL for the model's cover image"""
39+
40+
default_example: Optional[object] = None
41+
"""The model's default example prediction"""
42+
43+
description: Optional[str] = None
44+
"""A description of the model"""
45+
46+
github_url: Optional[str] = None
47+
"""A URL for the model's source code on GitHub"""
48+
49+
is_official: Optional[bool] = None
50+
"""Boolean indicating whether the model is officially maintained by Replicate.
51+
52+
Official models are always on, have stable API interfaces, and predictable
53+
pricing.
54+
"""
55+
56+
latest_version: Optional[object] = None
57+
"""The model's latest version"""
58+
59+
license_url: Optional[str] = None
60+
"""A URL for the model's license"""
61+
62+
name: Optional[str] = None
63+
"""The name of the model"""
64+
65+
owner: Optional[str] = None
66+
"""The name of the user or organization that owns the model"""
67+
68+
paper_url: Optional[str] = None
69+
"""A URL for the model's paper"""
70+
71+
run_count: Optional[int] = None
72+
"""The number of times the model has been run"""
73+
74+
url: Optional[str] = None
75+
"""The URL of the model on Replicate"""
76+
77+
visibility: Optional[Literal["public", "private"]] = None
78+
"""Whether the model is public or private"""
79+
80+
81+
class Model(BaseModel):
82+
metadata: ModelMetadata
83+
84+
model: ModelModel
85+
86+
87+
class Page(BaseModel):
88+
href: str
89+
"""URL path to the page"""
90+
91+
name: str
92+
"""Title of the page"""
93+
94+
95+
class SearchResponse(BaseModel):
96+
collections: List[Collection]
97+
"""Array of collections that match the search query"""
98+
99+
models: List[Model]
100+
"""
101+
Array of models that match the search query, each containing model data and
102+
extra metadata
103+
"""
104+
105+
pages: List[Page]
106+
"""Array of Replicate documentation pages that match the search query"""
107+
108+
query: str
109+
"""The search term that was evaluated"""

0 commit comments

Comments
 (0)