├── LICENCE
├── README.md
├── openai_async
├── __init__.py
├── openai_async.py
├── test_openai_async.py
└── test_utils.py
├── pyproject.toml
└── setup.py
/LICENCE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 itayzit
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # openai-async
2 |
3 | A light-weight, asynchronous client for OpenAI API - chat completion, text completion, image generation and embeddings.
4 | For the full documentation, go to the [openAI website](https://beta.openai.com/docs/api-reference).
5 |
6 |
7 | # Installation
8 |
9 | `pip install openai-async`
10 |
11 | # Use
12 |
13 | ## Chat completion
14 | response = await openai_async.chat_complete(
15 | _OPEN_AI_API_KEY,
16 | timeout=2,
17 | payload={
18 | "model": "gpt-3.5-turbo",
19 | "messages": [{"role": "user", "content": "Hello!"}],
20 | },
21 | )
22 | print(response.json()["choices"][0]["message"])
23 | >>> {"role": "assistant", "content": "\n\nHello there! How can I assist you today?"}
24 | Visit the [official documentation](https://platform.openai.com/docs/api-reference/chat) for more info.
25 | ## Text completion
26 | import openai_async
27 |
28 | response = await openai_async.complete(
29 | "",
30 | timeout=2,
31 | payload={
32 | "model": "text-davinci-003",
33 | "prompt": "Correct this sentence: Me like you.",
34 | "temperature": 0.7,
35 | },
36 | )
37 | print(response.json()["choices"][0]["text"].strip())
38 | >>> "I like you."
39 | Visit the [official documentation](https://platform.openai.com/docs/api-reference/completions) for more info.
40 | ## Image generation
41 | import openai_async
42 | import urllib.request
43 | from PIL import Image
44 |
45 | response = await openai_async.generate_img(
46 | "",
47 | timeout=8,
48 | payload={
49 | "prompt": "a white siamese cat",
50 | "n": 1,
51 | "size": "512x512"
52 | },
53 | )
54 | urllib.request.urlretrieve(response.json()["data"][0]["url"], "img.png")
55 | Image.open("img.png").show()
56 |
57 |
58 |
59 |
60 | ## Embeddings
61 | import openai_async
62 |
63 | response = await openai_async.embeddings(
64 | ,
65 | timeout=2,
66 | payload={"model": "text-embedding-ada-002", "input": "a cat"},
67 | )
68 | print(response.json()["data"][0]["embedding"])
69 | >>> [-0.019408401,
70 | -0.009246278,
71 | -0.014390069,
72 | -0.012294915,
73 | -0.0025609178,
74 | 0.021252638,
75 | ...]
76 |
77 | Visit the [official documentation](https://beta.openai.com/docs/api-reference/embeddings) for more info.
78 |
79 | # Get an API key
80 | To generate an openAI API key, while in the [openAI website](https://beta.openai.com), click on your username in the top right corner, then go to "View API keys" and create a key.
81 |
82 |
83 | ### Disclaimer
84 |
85 | This repository has no connection whatsoever to openAI.
--------------------------------------------------------------------------------
/openai_async/__init__.py:
--------------------------------------------------------------------------------
1 | from openai_async.openai_async import complete, generate_img, embeddings, chat_complete
2 |
--------------------------------------------------------------------------------
/openai_async/openai_async.py:
--------------------------------------------------------------------------------
1 | import httpx
2 |
3 |
4 | def _send_to_openai(endpoint_url: str,):
5 | async def send_to_openai(api_key: str, timeout: float, payload: dict) -> httpx.Response:
6 | """
7 | Send a request to openai.
8 | :param api_key: your api key
9 | :param timeout: timeout in seconds
10 | :param payload: the request body, as detailed here: https://beta.openai.com/docs/api-reference
11 | """
12 | async with httpx.AsyncClient() as client:
13 | return await client.post(
14 | url=endpoint_url,
15 | json=payload,
16 | headers={"content_type": "application/json", "Authorization": f"Bearer {api_key}"},
17 | timeout=timeout,
18 | )
19 |
20 | return send_to_openai
21 |
22 |
23 | complete = _send_to_openai("https://api.openai.com/v1/completions")
24 | generate_img = _send_to_openai("https://api.openai.com/v1/images/generations")
25 | embeddings = _send_to_openai("https://api.openai.com/v1/embeddings")
26 | chat_complete = _send_to_openai("https://api.openai.com/v1/chat/completions")
27 |
--------------------------------------------------------------------------------
/openai_async/test_openai_async.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | import openai_async
3 | import os
4 | from openai_async import test_utils
5 |
6 | _OPEN_AI_API_KEY = os.getenv("OPENAI_API_KEY")
7 |
8 |
9 | @pytest.mark.asyncio
10 | async def test_complete():
11 | response = await openai_async.complete(
12 | _OPEN_AI_API_KEY,
13 | timeout=2,
14 | payload={
15 | "model": "text-davinci-003",
16 | "prompt": "How much is 1 + 2?",
17 | "temperature": 0.0,
18 | },
19 | )
20 | assert response.json()["choices"][0]["text"].strip() == "1 + 2 = 3"
21 |
22 |
23 | @pytest.mark.asyncio
24 | async def test_generate_img():
25 | response = await openai_async.generate_img(
26 | _OPEN_AI_API_KEY,
27 | timeout=8,
28 | payload={
29 | "prompt": "a white siamese cat",
30 | "n": 1,
31 | "size": "256x256"
32 | },
33 | )
34 | assert test_utils.is_image_url(response.json()["data"][0]["url"])
35 |
36 |
37 | @pytest.mark.asyncio
38 | async def test_embeddings():
39 | response1 = await openai_async.embeddings(
40 | _OPEN_AI_API_KEY,
41 | timeout=2,
42 | payload={"model": "text-embedding-ada-002", "input": "tooth doctor"},
43 | )
44 | response2 = await openai_async.embeddings(
45 | _OPEN_AI_API_KEY,
46 | timeout=2,
47 | payload={"model": "text-embedding-ada-002", "input": "dentist"},
48 | )
49 | assert (
50 | test_utils.cosine_similarity(
51 | response1.json()["data"][0]["embedding"],
52 | response2.json()["data"][0]["embedding"],
53 | )
54 | > 0.9
55 | )
56 |
57 |
58 | @pytest.mark.asyncio
59 | async def test_chat_complete():
60 | response = await openai_async.chat_complete(
61 | _OPEN_AI_API_KEY,
62 | timeout=2,
63 | payload={
64 | "model": "gpt-3.5-turbo",
65 | "messages": [{"role": "user", "content": "Hello!"}],
66 | "temperature": 0.0,
67 | },
68 | )
69 | assert response.json()["choices"][0]["message"] == {
70 | "role": "assistant",
71 | "content": "\n\nHello there! How can I assist you today?",
72 | }
73 |
--------------------------------------------------------------------------------
/openai_async/test_utils.py:
--------------------------------------------------------------------------------
1 | import math
2 | import re
3 |
4 |
5 | def cosine_similarity(vec1, vec2):
6 | dot_product = sum([x * y for x, y in zip(vec1, vec2)])
7 | norm1 = math.sqrt(sum([x ** 2 for x in vec1]))
8 | norm2 = math.sqrt(sum([x ** 2 for x in vec2]))
9 | norm_product = norm1 * norm2
10 | if norm_product == 0:
11 | return 0
12 | else:
13 | return dot_product / norm_product
14 |
15 |
16 | def is_image_url(url: str) -> bool:
17 | return any(re.search(pattern, url, re.IGNORECASE) for pattern in ['.jpg', '.jpeg', '.png', '.gif'])
18 |
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [build-system]
2 | requires = [
3 | "setuptools",
4 | "wheel"
5 | ]
6 | build-backend = "setuptools.build_meta"
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | import setuptools
2 |
3 | with open("README.md", "r") as fh:
4 | _LONG_DESCRIPTION = fh.read()
5 |
6 |
7 | setuptools.setup(
8 | name="openai-async",
9 | license='MIT',
10 | author="itayzit",
11 | version="0.0.3",
12 | author_email="itayzit@gmail.com",
13 | description="A light-weight, asynchronous client for OpenAI API - text completion, image generation and embeddings.",
14 | long_description=_LONG_DESCRIPTION,
15 | long_description_content_type="text/markdown",
16 | url="https://github.com/itayzit/openai-async",
17 | packages=setuptools.find_namespace_packages(),
18 | install_requires=["httpx", "pytest"],
19 | )
--------------------------------------------------------------------------------