openai/openai-python
Publicmirrored from https://github.com/openai/openai-pythonAvailable
openai/api_resources/file.py
261lines · modeblame
7ddcba1aRachel Lim5 years ago | 1 | import json |
| 2 | import os | |
62f8d40fMadeleine Thompson4 years ago | 3 | from typing import cast |
7ddcba1aRachel Lim5 years ago | 4 | |
3c6d4cd6Greg Brockman5 years ago | 5 | import openai |
02e4008dSorin Suciu4 years ago | 6 | from openai import api_requestor, util, error |
62f8d40fMadeleine Thompson4 years ago | 7 | from openai.api_resources.abstract import DeletableAPIResource, ListableAPIResource |
02e4008dSorin Suciu4 years ago | 8 | from openai.util import ApiType |
3c6d4cd6Greg Brockman5 years ago | 9 | |
| 10 | | |
4e381798hallacy5 years ago | 11 | class File(ListableAPIResource, DeletableAPIResource): |
64c45330hallacy4 years ago | 12 | OBJECT_NAME = "files" |
3c6d4cd6Greg Brockman5 years ago | 13 | |
| 14 | @classmethod | |
0abf6413Andrew Chen Wang3 years ago | 15 | def __prepare_file_create( |
62f8d40fMadeleine Thompson4 years ago | 16 | cls, |
| 17 | file, | |
| 18 | purpose, | |
| 19 | model=None, | |
| 20 | api_key=None, | |
| 21 | api_base=None, | |
02e4008dSorin Suciu4 years ago | 22 | api_type=None, |
62f8d40fMadeleine Thompson4 years ago | 23 | api_version=None, |
| 24 | organization=None, | |
f4f6f90cRachel Lim4 years ago | 25 | user_provided_filename=None, |
3c6d4cd6Greg Brockman5 years ago | 26 | ): |
| 27 | requestor = api_requestor.APIRequestor( | |
| 28 | api_key, | |
62f8d40fMadeleine Thompson4 years ago | 29 | api_base=api_base or openai.api_base, |
02e4008dSorin Suciu4 years ago | 30 | api_type=api_type, |
3c6d4cd6Greg Brockman5 years ago | 31 | api_version=api_version, |
| 32 | organization=organization, | |
| 33 | ) | |
53e5ba4bt-asutedjo4 years ago | 34 | typed_api_type, api_version = cls._get_api_type_and_version( |
7884a7b9Ted Sanders3 years ago | 35 | api_type, api_version |
| 36 | ) | |
02e4008dSorin Suciu4 years ago | 37 | |
53e5ba4bt-asutedjo4 years ago | 38 | if typed_api_type in (ApiType.AZURE, ApiType.AZURE_AD): |
02e4008dSorin Suciu4 years ago | 39 | base = cls.class_url() |
7884a7b9Ted Sanders3 years ago | 40 | url = "/%s%s?api-version=%s" % (cls.azure_api_prefix, base, api_version) |
02e4008dSorin Suciu4 years ago | 41 | elif typed_api_type == ApiType.OPEN_AI: |
| 42 | url = cls.class_url() | |
| 43 | else: | |
7884a7b9Ted Sanders3 years ago | 44 | raise error.InvalidAPIType("Unsupported API type %s" % api_type) |
02e4008dSorin Suciu4 years ago | 45 | |
62f8d40fMadeleine Thompson4 years ago | 46 | # Set the filename on 'purpose' and 'model' to None so they are |
| 47 | # interpreted as form data. | |
f4f6f90cRachel Lim4 years ago | 48 | files = [("purpose", (None, purpose))] |
62f8d40fMadeleine Thompson4 years ago | 49 | if model is not None: |
| 50 | files.append(("model", (None, model))) | |
f4f6f90cRachel Lim4 years ago | 51 | if user_provided_filename is not None: |
53e5ba4bt-asutedjo4 years ago | 52 | files.append( |
7884a7b9Ted Sanders3 years ago | 53 | ("file", (user_provided_filename, file, "application/octet-stream")) |
| 54 | ) | |
f4f6f90cRachel Lim4 years ago | 55 | else: |
7884a7b9Ted Sanders3 years ago | 56 | files.append(("file", ("file", file, "application/octet-stream"))) |
0abf6413Andrew Chen Wang3 years ago | 57 | |
| 58 | return requestor, url, files | |
| 59 | | |
| 60 | @classmethod | |
| 61 | def create( | |
| 62 | cls, | |
| 63 | file, | |
| 64 | purpose, | |
| 65 | model=None, | |
| 66 | api_key=None, | |
| 67 | api_base=None, | |
| 68 | api_type=None, | |
| 69 | api_version=None, | |
| 70 | organization=None, | |
| 71 | user_provided_filename=None, | |
| 72 | ): | |
| 73 | requestor, url, files = cls.__prepare_file_create( | |
| 74 | file, | |
| 75 | purpose, | |
| 76 | model, | |
| 77 | api_key, | |
| 78 | api_base, | |
| 79 | api_type, | |
| 80 | api_version, | |
| 81 | organization, | |
| 82 | user_provided_filename, | |
| 83 | ) | |
62f8d40fMadeleine Thompson4 years ago | 84 | response, _, api_key = requestor.request("post", url, files=files) |
3c6d4cd6Greg Brockman5 years ago | 85 | return util.convert_to_openai_object( |
| 86 | response, api_key, api_version, organization | |
| 87 | ) | |
7ddcba1aRachel Lim5 years ago | 88 | |
| 89 | @classmethod | |
0abf6413Andrew Chen Wang3 years ago | 90 | async def acreate( |
| 91 | cls, | |
| 92 | file, | |
| 93 | purpose, | |
| 94 | model=None, | |
| 95 | api_key=None, | |
| 96 | api_base=None, | |
| 97 | api_type=None, | |
| 98 | api_version=None, | |
| 99 | organization=None, | |
| 100 | user_provided_filename=None, | |
| 101 | ): | |
| 102 | requestor, url, files = cls.__prepare_file_create( | |
| 103 | file, | |
| 104 | purpose, | |
| 105 | model, | |
| 106 | api_key, | |
| 107 | api_base, | |
| 108 | api_type, | |
| 109 | api_version, | |
| 110 | organization, | |
| 111 | user_provided_filename, | |
| 112 | ) | |
| 113 | response, _, api_key = await requestor.arequest("post", url, files=files) | |
| 114 | return util.convert_to_openai_object( | |
| 115 | response, api_key, api_version, organization | |
| 116 | ) | |
| 117 | | |
| 118 | @classmethod | |
| 119 | def __prepare_file_download( | |
53e5ba4bt-asutedjo4 years ago | 120 | cls, |
| 121 | id, | |
| 122 | api_key=None, | |
02e4008dSorin Suciu4 years ago | 123 | api_base=None, |
| 124 | api_type=None, | |
53e5ba4bt-asutedjo4 years ago | 125 | api_version=None, |
7884a7b9Ted Sanders3 years ago | 126 | organization=None, |
7ddcba1aRachel Lim5 years ago | 127 | ): |
| 128 | requestor = api_requestor.APIRequestor( | |
| 129 | api_key, | |
62f8d40fMadeleine Thompson4 years ago | 130 | api_base=api_base or openai.api_base, |
02e4008dSorin Suciu4 years ago | 131 | api_type=api_type, |
7ddcba1aRachel Lim5 years ago | 132 | api_version=api_version, |
| 133 | organization=organization, | |
| 134 | ) | |
53e5ba4bt-asutedjo4 years ago | 135 | typed_api_type, api_version = cls._get_api_type_and_version( |
7884a7b9Ted Sanders3 years ago | 136 | api_type, api_version |
| 137 | ) | |
02e4008dSorin Suciu4 years ago | 138 | |
53e5ba4bt-asutedjo4 years ago | 139 | if typed_api_type in (ApiType.AZURE, ApiType.AZURE_AD): |
02e4008dSorin Suciu4 years ago | 140 | base = cls.class_url() |
88b267b9James Chua3 years ago | 141 | url = f"/{cls.azure_api_prefix}{base}/{id}/content?api-version={api_version}" |
02e4008dSorin Suciu4 years ago | 142 | elif typed_api_type == ApiType.OPEN_AI: |
88b267b9James Chua3 years ago | 143 | url = f"{cls.class_url()}/{id}/content" |
02e4008dSorin Suciu4 years ago | 144 | else: |
7884a7b9Ted Sanders3 years ago | 145 | raise error.InvalidAPIType("Unsupported API type %s" % api_type) |
53e5ba4bt-asutedjo4 years ago | 146 | |
0abf6413Andrew Chen Wang3 years ago | 147 | return requestor, url |
| 148 | | |
| 149 | @classmethod | |
| 150 | def download( | |
| 151 | cls, | |
| 152 | id, | |
| 153 | api_key=None, | |
| 154 | api_base=None, | |
| 155 | api_type=None, | |
| 156 | api_version=None, | |
| 157 | organization=None, | |
| 158 | ): | |
| 159 | requestor, url = cls.__prepare_file_download( | |
| 160 | id, api_key, api_base, api_type, api_version, organization | |
| 161 | ) | |
| 162 | | |
62f8d40fMadeleine Thompson4 years ago | 163 | result = requestor.request_raw("get", url) |
| 164 | if not 200 <= result.status_code < 300: | |
7ddcba1aRachel Lim5 years ago | 165 | raise requestor.handle_error_response( |
62f8d40fMadeleine Thompson4 years ago | 166 | result.content, |
| 167 | result.status_code, | |
| 168 | json.loads(cast(bytes, result.content)), | |
| 169 | result.headers, | |
| 170 | stream_error=False, | |
7ddcba1aRachel Lim5 years ago | 171 | ) |
62f8d40fMadeleine Thompson4 years ago | 172 | return result.content |
7ddcba1aRachel Lim5 years ago | 173 | |
| 174 | @classmethod | |
0abf6413Andrew Chen Wang3 years ago | 175 | async def adownload( |
7ddcba1aRachel Lim5 years ago | 176 | cls, |
0abf6413Andrew Chen Wang3 years ago | 177 | id, |
7ddcba1aRachel Lim5 years ago | 178 | api_key=None, |
| 179 | api_base=None, | |
02e4008dSorin Suciu4 years ago | 180 | api_type=None, |
7ddcba1aRachel Lim5 years ago | 181 | api_version=None, |
| 182 | organization=None, | |
| 183 | ): | |
0abf6413Andrew Chen Wang3 years ago | 184 | requestor, url = cls.__prepare_file_download( |
| 185 | id, api_key, api_base, api_type, api_version, organization | |
| 186 | ) | |
| 187 | | |
7af43ce0Damien Deville3 years ago | 188 | async with api_requestor.aiohttp_session() as session: |
| 189 | result = await requestor.arequest_raw("get", url, session) | |
| 190 | if not 200 <= result.status < 300: | |
| 191 | raise requestor.handle_error_response( | |
| 192 | result.content, | |
| 193 | result.status, | |
| 194 | json.loads(cast(bytes, result.content)), | |
| 195 | result.headers, | |
| 196 | stream_error=False, | |
| 197 | ) | |
| 198 | return result.content | |
0abf6413Andrew Chen Wang3 years ago | 199 | |
| 200 | @classmethod | |
| 201 | def __find_matching_files(cls, name, all_files, purpose): | |
7ddcba1aRachel Lim5 years ago | 202 | matching_files = [] |
f4f6f90cRachel Lim4 years ago | 203 | basename = os.path.basename(name) |
7ddcba1aRachel Lim5 years ago | 204 | for f in all_files: |
| 205 | if f["purpose"] != purpose: | |
| 206 | continue | |
f4f6f90cRachel Lim4 years ago | 207 | file_basename = os.path.basename(f["filename"]) |
| 208 | if file_basename != basename: | |
7ddcba1aRachel Lim5 years ago | 209 | continue |
02e4008dSorin Suciu4 years ago | 210 | if "bytes" in f and f["bytes"] != bytes: |
| 211 | continue | |
| 212 | if "size" in f and int(f["size"]) != bytes: | |
7ddcba1aRachel Lim5 years ago | 213 | continue |
| 214 | matching_files.append(f) | |
| 215 | return matching_files | |
0abf6413Andrew Chen Wang3 years ago | 216 | |
| 217 | @classmethod | |
| 218 | def find_matching_files( | |
| 219 | cls, | |
| 220 | name, | |
| 221 | bytes, | |
| 222 | purpose, | |
| 223 | api_key=None, | |
| 224 | api_base=None, | |
| 225 | api_type=None, | |
| 226 | api_version=None, | |
| 227 | organization=None, | |
| 228 | ): | |
| 229 | """Find already uploaded files with the same name, size, and purpose.""" | |
| 230 | all_files = cls.list( | |
| 231 | api_key=api_key, | |
| 232 | api_base=api_base or openai.api_base, | |
| 233 | api_type=api_type, | |
| 234 | api_version=api_version, | |
| 235 | organization=organization, | |
| 236 | ).get("data", []) | |
| 237 | return cls.__find_matching_files(name, all_files, purpose) | |
| 238 | | |
| 239 | @classmethod | |
| 240 | async def afind_matching_files( | |
| 241 | cls, | |
| 242 | name, | |
| 243 | bytes, | |
| 244 | purpose, | |
| 245 | api_key=None, | |
| 246 | api_base=None, | |
| 247 | api_type=None, | |
| 248 | api_version=None, | |
| 249 | organization=None, | |
| 250 | ): | |
| 251 | """Find already uploaded files with the same name, size, and purpose.""" | |
| 252 | all_files = ( | |
| 253 | await cls.alist( | |
| 254 | api_key=api_key, | |
| 255 | api_base=api_base or openai.api_base, | |
| 256 | api_type=api_type, | |
| 257 | api_version=api_version, | |
| 258 | organization=organization, | |
| 259 | ) | |
| 260 | ).get("data", []) | |
| 261 | return cls.__find_matching_files(name, all_files, purpose) |