Spaces:
Runtime error
Runtime error
File size: 5,811 Bytes
105b369 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
from typing import Any, Optional, Dict
from typing_extensions import Literal
from pydantic import BaseModel, ConfigDict
from phi.assistant.openai.exceptions import FileIdNotSet
from phi.utils.log import logger
try:
from openai import OpenAI
from openai.types.file_object import FileObject as OpenAIFile
from openai.types.file_deleted import FileDeleted as OpenAIFileDeleted
except ImportError:
logger.error("`openai` not installed")
raise
class File(BaseModel):
# -*- File settings
name: Optional[str] = None
# File id which can be referenced in API endpoints.
id: Optional[str] = None
# The object type, populated by the API. Always file.
object: Optional[str] = None
# The size of the file, in bytes.
bytes: Optional[int] = None
# The name of the file.
filename: Optional[str] = None
# The intended purpose of the file.
# Supported values are fine-tune, fine-tune-results, assistants, and assistants_output.
purpose: Literal["fine-tune", "assistants"] = "assistants"
# The current status of the file, which can be either `uploaded`, `processed`, or `error`.
status: Optional[Literal["uploaded", "processed", "error"]] = None
status_details: Optional[str] = None
# The Unix timestamp (in seconds) for when the file was created.
created_at: Optional[int] = None
openai: Optional[OpenAI] = None
openai_file: Optional[OpenAIFile] = None
model_config = ConfigDict(arbitrary_types_allowed=True)
@property
def client(self) -> OpenAI:
return self.openai or OpenAI()
def read(self) -> Any:
raise NotImplementedError
def get_filename(self) -> Optional[str]:
return self.filename
def load_from_openai(self, openai_file: OpenAIFile):
self.id = openai_file.id
self.object = openai_file.object
self.bytes = openai_file.bytes
self.created_at = openai_file.created_at
self.filename = openai_file.filename
self.status = openai_file.status
self.status_details = openai_file.status_details
def create(self) -> "File":
self.openai_file = self.client.files.create(file=self.read(), purpose=self.purpose)
self.load_from_openai(self.openai_file)
logger.debug(f"File created: {self.openai_file.id}")
logger.debug(f"File: {self.openai_file}")
return self
def get_id(self) -> Optional[str]:
return self.id or self.openai_file.id if self.openai_file else None
def get_using_filename(self) -> Optional[OpenAIFile]:
file_list = self.client.files.list(purpose=self.purpose)
file_name = self.get_filename()
if file_name is None:
return None
logger.debug(f"Getting id for: {file_name}")
for file in file_list:
if file.filename == file_name:
logger.debug(f"Found file: {file.id}")
return file
return None
def get_from_openai(self) -> OpenAIFile:
_file_id = self.get_id()
if _file_id is None:
oai_file = self.get_using_filename()
else:
oai_file = self.client.files.retrieve(file_id=_file_id)
if oai_file is None:
raise FileIdNotSet("File.id not set")
self.openai_file = oai_file
self.load_from_openai(self.openai_file)
return self.openai_file
def get(self, use_cache: bool = True) -> "File":
if self.openai_file is not None and use_cache:
return self
self.get_from_openai()
return self
def get_or_create(self, use_cache: bool = True) -> "File":
try:
return self.get(use_cache=use_cache)
except FileIdNotSet:
return self.create()
def download(self, path: Optional[str] = None, suffix: Optional[str] = None) -> str:
from tempfile import NamedTemporaryFile
try:
file_to_download = self.get_from_openai()
if file_to_download is not None:
logger.debug(f"Downloading file: {file_to_download.id}")
response = self.client.files.with_raw_response.retrieve_content(file_id=file_to_download.id)
if path:
with open(path, "wb") as f:
f.write(response.content)
return path
else:
with NamedTemporaryFile(delete=False, mode="wb", suffix=f"{suffix}") as temp_file:
temp_file.write(response.content)
temp_file_path = temp_file.name
return temp_file_path
raise ValueError("File not available")
except FileIdNotSet:
logger.warning("File not available")
raise
def delete(self) -> OpenAIFileDeleted:
try:
file_to_delete = self.get_from_openai()
if file_to_delete is not None:
deletion_status = self.client.files.delete(
file_id=file_to_delete.id,
)
logger.debug(f"File deleted: {file_to_delete.id}")
return deletion_status
except FileIdNotSet:
logger.warning("File not available")
raise
def to_dict(self) -> Dict[str, Any]:
return self.model_dump(
exclude_none=True,
include={
"filename",
"id",
"object",
"bytes",
"purpose",
"created_at",
},
)
def pprint(self):
"""Pretty print using rich"""
from rich.pretty import pprint
pprint(self.to_dict())
def __str__(self) -> str:
import json
return json.dumps(self.to_dict(), indent=4)
|