Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: introducing a "Generate" API for prompt-based content generation with saved prompts #19

Merged
merged 4 commits into from
Sep 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
### Changelog
#### Unreleased

All notable changes to this project will be documented in this file. Dates are displayed in UTC.
- feat: introducing a "Generate" API for prompt-based content generation with saved prompts

Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
<!-- auto-changelog-below -->

#### [v0.1.49](https://github.com/Portkey-AI/portkey-python-sdk/compare/v0.1.48...v0.1.49)

> 16 September 2023

- fix: Fixing the issue with the capturing of env variables [`#13`](https://github.com/Portkey-AI/portkey-python-sdk/pull/13)

#### [v0.1.48](https://github.com/Portkey-AI/portkey-python-sdk/compare/v0.1.45...v0.1.48)

> 14 September 2023

- fix: cache age type fix [`#11`](https://github.com/Portkey-AI/portkey-python-sdk/pull/11)
- docs: updated change log [`#10`](https://github.com/Portkey-AI/portkey-python-sdk/pull/10)

#### [v0.1.45](https://github.com/Portkey-AI/portkey-python-sdk/compare/v0.1.44...v0.1.45)

Expand Down
2 changes: 2 additions & 0 deletions portkey/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
ChatCompletionChunk,
TextCompletion,
TextCompletionChunk,
Generations,
)
from portkey.version import VERSION
from portkey.api_resources.global_constants import (
Expand Down Expand Up @@ -50,6 +51,7 @@
"ChatCompletionChunk",
"TextCompletion",
"TextCompletionChunk",
"Generations",
"Config",
"api_key",
"base_url",
Expand Down
3 changes: 2 additions & 1 deletion portkey/api_resources/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
""""""
from .apis import ChatCompletions, Completions
from .apis import ChatCompletions, Completions, Generations
from .utils import (
Modes,
ModesLiteral,
Expand Down Expand Up @@ -41,4 +41,5 @@
"ChatCompletionChunk",
"TextCompletion",
"TextCompletionChunk",
"Generations",
]
47 changes: 30 additions & 17 deletions portkey/api_resources/apis.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
ChatCompletion,
TextCompletion,
TextCompletionChunk,
ApiType,
GenericResponse,
)

from .streaming import Stream
Expand Down Expand Up @@ -49,7 +49,7 @@ def create(
max_tokens: Optional[int] = None,
top_k: Optional[int] = None,
top_p: Optional[float] = None,
**kwargs
**kwargs,
) -> Stream[TextCompletionChunk]:
...

Expand All @@ -65,7 +65,7 @@ def create(
max_tokens: Optional[int] = None,
top_k: Optional[int] = None,
top_p: Optional[float] = None,
**kwargs
**kwargs,
) -> TextCompletion:
...

Expand All @@ -81,7 +81,7 @@ def create(
max_tokens: Optional[int] = None,
top_k: Optional[int] = None,
top_p: Optional[float] = None,
**kwargs
**kwargs,
) -> Union[TextCompletion, Stream[TextCompletionChunk]]:
...

Expand All @@ -96,7 +96,7 @@ def create(
max_tokens: Optional[int] = None,
top_k: Optional[int] = None,
top_p: Optional[float] = None,
**kwargs
**kwargs,
) -> Union[TextCompletion, Stream[TextCompletionChunk]]:
if config is None:
config = retrieve_config()
Expand All @@ -107,7 +107,7 @@ def create(
max_tokens=max_tokens,
top_k=top_k,
top_p=top_p,
**kwargs
**kwargs,
)
if config.mode == Modes.SINGLE.value:
return cls(_client)._post(
Expand All @@ -118,7 +118,6 @@ def create(
cast_to=TextCompletion,
stream_cls=Stream[TextCompletionChunk],
stream=stream,
_type=ApiType.COMPLETIONS,
)
if config.mode == Modes.FALLBACK.value:
return cls(_client)._post(
Expand All @@ -129,7 +128,6 @@ def create(
cast_to=TextCompletion,
stream_cls=Stream[TextCompletionChunk],
stream=stream,
_type=ApiType.COMPLETIONS,
)
if config.mode == Modes.AB_TEST.value:
return cls(_client)._post(
Expand All @@ -140,7 +138,6 @@ def create(
cast_to=TextCompletion,
stream_cls=Stream[TextCompletionChunk],
stream=stream,
_type=ApiType.COMPLETIONS,
)
raise NotImplementedError("Mode not implemented.")

Expand All @@ -158,7 +155,7 @@ def create(
max_tokens: Optional[int] = None,
top_k: Optional[int] = None,
top_p: Optional[float] = None,
**kwargs
**kwargs,
) -> Stream[ChatCompletionChunk]:
...

Expand All @@ -174,7 +171,7 @@ def create(
max_tokens: Optional[int] = None,
top_k: Optional[int] = None,
top_p: Optional[float] = None,
**kwargs
**kwargs,
) -> ChatCompletion:
...

Expand All @@ -190,7 +187,7 @@ def create(
max_tokens: Optional[int] = None,
top_k: Optional[int] = None,
top_p: Optional[float] = None,
**kwargs
**kwargs,
) -> Union[ChatCompletion, Stream[ChatCompletionChunk]]:
...

Expand All @@ -205,7 +202,7 @@ def create(
max_tokens: Optional[int] = None,
top_k: Optional[int] = None,
top_p: Optional[float] = None,
**kwargs
**kwargs,
) -> Union[ChatCompletion, Stream[ChatCompletionChunk]]:
if config is None:
config = retrieve_config()
Expand All @@ -216,7 +213,7 @@ def create(
max_tokens=max_tokens,
top_k=top_k,
top_p=top_p,
**kwargs
**kwargs,
)
if config.mode == Modes.SINGLE.value:
return cls(_client)._post(
Expand All @@ -227,7 +224,6 @@ def create(
cast_to=ChatCompletion,
stream_cls=Stream[ChatCompletionChunk],
stream=stream,
_type=ApiType.CHAT_COMPLETION,
)
if config.mode == Modes.FALLBACK.value:
return cls(_client)._post(
Expand All @@ -238,7 +234,6 @@ def create(
cast_to=ChatCompletion,
stream_cls=Stream[ChatCompletionChunk],
stream=stream,
_type=ApiType.CHAT_COMPLETION,
)
if config.mode == Modes.AB_TEST.value:
return cls(_client)._post(
Expand All @@ -249,6 +244,24 @@ def create(
cast_to=ChatCompletion,
stream_cls=Stream[ChatCompletionChunk],
stream=stream,
_type=ApiType.CHAT_COMPLETION,
)
raise NotImplementedError("Mode not implemented.")


class Generations(APIResource):
@classmethod
def create(
cls, *, prompt_id: str, config: Optional[Config] = None, **kwargs
) -> Union[GenericResponse, Stream[GenericResponse]]:
if config is None:
config = retrieve_config()
_client = APIClient(api_key=config.api_key, base_url=config.base_url)
return cls(_client)._post(
f"/v1/prompts/{prompt_id}/generate",
body=config.llms,
mode=None,
params=None,
cast_to=GenericResponse,
stream_cls=Stream[GenericResponse],
stream=False,
)
74 changes: 56 additions & 18 deletions portkey/api_resources/base_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
Type,
overload,
Literal,
get_args,
)
import httpx
import platform
Expand All @@ -26,7 +27,7 @@
ProviderOptions,
Params,
Constructs,
ApiType,
PortkeyApiPaths,
)
from .exceptions import (
APIStatusError,
Expand Down Expand Up @@ -91,7 +92,6 @@ def post(
stream: Literal[True],
stream_cls: type[StreamT],
params: Params,
_type: ApiType,
) -> StreamT:
...

Expand All @@ -106,7 +106,6 @@ def post(
stream: Literal[False],
stream_cls: type[StreamT],
params: Params,
_type: ApiType,
) -> ResponseT:
...

Expand All @@ -121,35 +120,68 @@ def post(
stream: bool,
stream_cls: type[StreamT],
params: Params,
_type: ApiType,
) -> Union[ResponseT, StreamT]:
...

def post(
self,
path: str,
*,
body: List[Body],
body: Union[List[Body], Any],
mode: str,
cast_to: Type[ResponseT],
stream: bool,
stream_cls: type[StreamT],
params: Params,
_type: ApiType,
) -> Union[ResponseT, StreamT]:
body = cast(List[Body], body)
opts = self._construct(
method="post", url=path, body=body, mode=mode, stream=stream, params=params
)
if path in [PortkeyApiPaths.CHAT_COMPLETION, PortkeyApiPaths.COMPLETION]:
body = cast(List[Body], body)
opts = self._construct(
method="post",
url=path,
body=body,
mode=mode,
stream=stream,
params=params,
)
elif path.endswith("/generate"):
opts = self._construct_generate_options(
method="post",
url=path,
body=body,
mode=mode,
stream=stream,
params=params,
)
else:
raise NotImplementedError(f"This API path `{path}` is not implemented.")

res = self._request(
options=opts,
stream=stream,
cast_to=cast_to,
stream_cls=stream_cls,
_type=_type,
)
return res

def _construct_generate_options(
self,
*,
method: str,
url: str,
body: Any,
mode: str,
stream: bool,
params: Params,
) -> Options:
opts = Options.construct()
opts.method = method
opts.url = url
json_body = body
opts.json_body = remove_empty_values(json_body)
opts.headers = None
return opts

def _construct(
self,
*,
Expand Down Expand Up @@ -252,7 +284,6 @@ def _request(
stream: Literal[False],
cast_to: Type[ResponseT],
stream_cls: Type[StreamT],
_type: ApiType,
) -> ResponseT:
...

Expand All @@ -264,7 +295,6 @@ def _request(
stream: Literal[True],
cast_to: Type[ResponseT],
stream_cls: Type[StreamT],
_type: ApiType,
) -> StreamT:
...

Expand All @@ -276,7 +306,6 @@ def _request(
stream: bool,
cast_to: Type[ResponseT],
stream_cls: Type[StreamT],
_type: ApiType,
) -> Union[ResponseT, StreamT]:
...

Expand All @@ -287,7 +316,6 @@ def _request(
stream: bool,
cast_to: Type[ResponseT],
stream_cls: Type[StreamT],
_type: ApiType,
) -> Union[ResponseT, StreamT]:
request = self._build_request(options)
try:
Expand All @@ -302,18 +330,28 @@ def _request(
raise APITimeoutError(request=request) from err
except Exception as err:
raise APIConnectionError(request=request) from err
if stream:
# stream_cls = stream_cls
if stream or res.headers["content-type"] == "text/event-stream":
if stream_cls is None:
raise MissingStreamClassError()
stream_response = stream_cls(response=res, _type=_type)
stream_response = stream_cls(
response=res, cast_to=self._extract_stream_chunk_type(stream_cls)
)
return stream_response

response = cast(
ResponseT,
cast_to(**res.json()),
)
return response

def _extract_stream_chunk_type(self, stream_cls: Type) -> type:
args = get_args(stream_cls)
if not args:
raise TypeError(
f"Expected stream_cls to have been given a generic type argument, e.g. Stream[Foo] but received {stream_cls}",
)
return cast(type, args[0])

def _make_status_error_from_response(
self,
request: httpx.Request,
Expand Down
Loading