├── 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 | a cat 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 | ) --------------------------------------------------------------------------------