openai/openai-python
Publicmirrored from https://github.com/openai/openai-pythonAvailable
openai/api_resources/file.py
101lines · modecode
| 1 | import json |
| 2 | import os |
| 3 | from typing import cast |
| 4 | |
| 5 | import openai |
| 6 | from openai import api_requestor, util |
| 7 | from openai.api_resources.abstract import DeletableAPIResource, ListableAPIResource |
| 8 | |
| 9 | |
| 10 | class File(ListableAPIResource, DeletableAPIResource): |
| 11 | OBJECT_NAME = "file" |
| 12 | |
| 13 | @classmethod |
| 14 | def create( |
| 15 | cls, |
| 16 | file, |
| 17 | purpose, |
| 18 | model=None, |
| 19 | api_key=None, |
| 20 | api_base=None, |
| 21 | api_version=None, |
| 22 | organization=None, |
| 23 | ): |
| 24 | if purpose != "search" and model is not None: |
| 25 | raise ValueError("'model' is only meaningful if 'purpose' is 'search'") |
| 26 | requestor = api_requestor.APIRequestor( |
| 27 | api_key, |
| 28 | api_base=api_base or openai.api_base, |
| 29 | api_version=api_version, |
| 30 | organization=organization, |
| 31 | ) |
| 32 | url = cls.class_url() |
| 33 | # Set the filename on 'purpose' and 'model' to None so they are |
| 34 | # interpreted as form data. |
| 35 | files = [("file", file), ("purpose", (None, purpose))] |
| 36 | if model is not None: |
| 37 | files.append(("model", (None, model))) |
| 38 | response, _, api_key = requestor.request("post", url, files=files) |
| 39 | return util.convert_to_openai_object( |
| 40 | response, api_key, api_version, organization |
| 41 | ) |
| 42 | |
| 43 | @classmethod |
| 44 | def download( |
| 45 | cls, id, api_key=None, api_base=None, api_version=None, organization=None |
| 46 | ): |
| 47 | requestor = api_requestor.APIRequestor( |
| 48 | api_key, |
| 49 | api_base=api_base or openai.api_base, |
| 50 | api_version=api_version, |
| 51 | organization=organization, |
| 52 | ) |
| 53 | url = f"{cls.class_url()}/{id}/content" |
| 54 | result = requestor.request_raw("get", url) |
| 55 | if not 200 <= result.status_code < 300: |
| 56 | raise requestor.handle_error_response( |
| 57 | result.content, |
| 58 | result.status_code, |
| 59 | json.loads(cast(bytes, result.content)), |
| 60 | result.headers, |
| 61 | stream_error=False, |
| 62 | ) |
| 63 | return result.content |
| 64 | |
| 65 | @classmethod |
| 66 | def find_matching_files( |
| 67 | cls, |
| 68 | api_key=None, |
| 69 | api_base=None, |
| 70 | api_version=None, |
| 71 | organization=None, |
| 72 | file=None, |
| 73 | purpose=None, |
| 74 | ): |
| 75 | if file is None: |
| 76 | raise openai.error.InvalidRequestError( |
| 77 | "'file' is a required property", "file" |
| 78 | ) |
| 79 | if purpose is None: |
| 80 | raise openai.error.InvalidRequestError( |
| 81 | "'purpose' is a required property", "purpose" |
| 82 | ) |
| 83 | all_files = cls.list( |
| 84 | api_key=api_key, |
| 85 | api_base=api_base or openai.api_base, |
| 86 | api_version=api_version, |
| 87 | organization=organization, |
| 88 | ).get("data", []) |
| 89 | matching_files = [] |
| 90 | for f in all_files: |
| 91 | if f["purpose"] != purpose: |
| 92 | continue |
| 93 | if not hasattr(file, "name") or f["filename"] != file.name: |
| 94 | continue |
| 95 | file.seek(0, os.SEEK_END) |
| 96 | if f["bytes"] != file.tell(): |
| 97 | file.seek(0) |
| 98 | continue |
| 99 | file.seek(0) |
| 100 | matching_files.append(f) |
| 101 | return matching_files |
| 102 | |