Spaces:
Sleeping
Sleeping
Hjgugugjhuhjggg
commited on
Update app.py
Browse files
app.py
CHANGED
@@ -1,18 +1,17 @@
|
|
1 |
import os
|
|
|
2 |
import boto3
|
3 |
-
import
|
4 |
from fastapi import FastAPI, HTTPException
|
5 |
from pydantic import BaseModel
|
6 |
-
import safetensors.torch
|
7 |
from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline
|
8 |
-
from
|
9 |
-
import
|
10 |
-
import
|
11 |
-
import
|
12 |
from dotenv import load_dotenv
|
|
|
13 |
import re
|
14 |
-
from tqdm import tqdm
|
15 |
-
from huggingface_hub import hf_hub_download
|
16 |
|
17 |
# Cargar las variables de entorno desde el archivo .env
|
18 |
load_dotenv()
|
@@ -54,7 +53,7 @@ class S3DirectStream:
|
|
54 |
try:
|
55 |
print(f"[INFO] Descargando archivo {key} desde S3...")
|
56 |
response = self.s3_client.get_object(Bucket=self.bucket_name, Key=key)
|
57 |
-
return response['Body'] # Devolver el cuerpo
|
58 |
except self.s3_client.exceptions.NoSuchKey:
|
59 |
raise HTTPException(status_code=404, detail=f"El archivo {key} no existe en el bucket S3.")
|
60 |
except Exception as e:
|
@@ -68,9 +67,11 @@ class S3DirectStream:
|
|
68 |
except self.s3_client.exceptions.ClientError:
|
69 |
return False
|
70 |
|
71 |
-
def
|
72 |
try:
|
73 |
print(f"[INFO] Cargando el modelo {model_name} desde S3...")
|
|
|
|
|
74 |
model_prefix = model_name.lower()
|
75 |
model_files = self.get_model_file_parts(model_prefix)
|
76 |
|
@@ -82,16 +83,16 @@ class S3DirectStream:
|
|
82 |
if not model_files:
|
83 |
raise HTTPException(status_code=404, detail=f"Archivos del modelo {model_name} no encontrados en S3.")
|
84 |
|
85 |
-
#
|
86 |
model_streams = []
|
87 |
-
for model_file in tqdm(model_files, desc="Cargando archivos del modelo", unit="archivo"):
|
88 |
model_streams.append(self.stream_from_s3(model_file))
|
89 |
|
90 |
config_stream = self.stream_from_s3(f"{model_prefix}/config.json")
|
91 |
-
config_data = config_stream.read().decode("utf-8")
|
92 |
|
93 |
# Cargar el modelo dependiendo del tipo de archivo (torch o safetensors)
|
94 |
-
if
|
95 |
print("[INFO] Cargando el modelo como safetensor...")
|
96 |
model = AutoModelForCausalLM.from_config(config_data)
|
97 |
model.load_state_dict(safetensors.torch.load_stream(model_streams[0]))
|
@@ -107,7 +108,7 @@ class S3DirectStream:
|
|
107 |
print(f"[ERROR] Error al cargar el modelo desde S3: {e}")
|
108 |
raise HTTPException(status_code=500, detail="Error al cargar el modelo desde S3.")
|
109 |
|
110 |
-
def
|
111 |
try:
|
112 |
print(f"[INFO] Cargando el tokenizer {model_name} desde S3...")
|
113 |
tokenizer_stream = self.stream_from_s3(f"{model_name}/tokenizer.json")
|
@@ -121,9 +122,10 @@ class S3DirectStream:
|
|
121 |
print(f"[INFO] Listando archivos del modelo en S3 con prefijo {model_name}...")
|
122 |
files = self.s3_client.list_objects_v2(Bucket=self.bucket_name, Prefix=model_name)
|
123 |
model_files = []
|
124 |
-
for obj in tqdm(files.get('Contents', []), desc="Verificando archivos", unit="archivo"):
|
125 |
key = obj['Key']
|
126 |
-
|
|
|
127 |
model_files.append(key)
|
128 |
if not model_files:
|
129 |
print(f"[WARNING] No se encontraron archivos para el modelo {model_name}.")
|
@@ -132,18 +134,16 @@ class S3DirectStream:
|
|
132 |
def download_and_upload_from_huggingface(self, model_name):
|
133 |
try:
|
134 |
print(f"[INFO] Descargando {model_name} desde Hugging Face...")
|
135 |
-
# Descargar los archivos
|
136 |
-
files_to_download =
|
137 |
-
"pytorch_model.bin",
|
138 |
-
"config.json",
|
139 |
-
"tokenizer.json",
|
140 |
-
]
|
141 |
|
|
|
142 |
for file in files_to_download:
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
|
|
147 |
except Exception as e:
|
148 |
print(f"[ERROR] Error al descargar y subir modelo desde Hugging Face: {e}")
|
149 |
raise HTTPException(status_code=500, detail="Error al descargar y subir modelo desde Hugging Face.")
|
@@ -153,44 +153,53 @@ class S3DirectStream:
|
|
153 |
print(f"[INFO] Subiendo archivo {file_path} a S3 con key {s3_key}...")
|
154 |
with open(file_path, 'rb') as data:
|
155 |
self.s3_client.put_object(Bucket=self.bucket_name, Key=s3_key, Body=data)
|
|
|
|
|
156 |
except Exception as e:
|
157 |
print(f"[ERROR] Error al subir archivo a S3: {e}")
|
158 |
raise HTTPException(status_code=500, detail="Error al subir archivo a S3.")
|
159 |
|
|
|
160 |
@app.post("/predict/")
|
161 |
async def predict(model_request: DownloadModelRequest):
|
162 |
try:
|
163 |
print(f"[INFO] Recibiendo solicitud para predecir con el modelo {model_request.model_name}...")
|
164 |
streamer = S3DirectStream(S3_BUCKET_NAME)
|
165 |
-
model = streamer.
|
166 |
-
tokenizer = streamer.
|
167 |
|
168 |
task = model_request.pipeline_task
|
169 |
-
if task not in ["text-generation", "sentiment-analysis", "translation", "fill-mask", "question-answering",
|
|
|
170 |
raise HTTPException(status_code=400, detail="Pipeline task no soportado")
|
171 |
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
elif task == "
|
183 |
-
|
184 |
-
|
|
|
185 |
elif task == "text-to-video":
|
186 |
-
|
187 |
-
|
|
|
|
|
|
|
|
|
188 |
|
189 |
-
return {"output": outputs}
|
190 |
except Exception as e:
|
191 |
-
print(f"[ERROR] Error
|
192 |
-
raise HTTPException(status_code=500, detail="Error
|
|
|
193 |
|
|
|
194 |
if __name__ == "__main__":
|
195 |
-
|
196 |
-
uvicorn.run(app, host="0.0.0.0", port=7860)
|
|
|
1 |
import os
|
2 |
+
import json
|
3 |
import boto3
|
4 |
+
import uvicorn
|
5 |
from fastapi import FastAPI, HTTPException
|
6 |
from pydantic import BaseModel
|
|
|
7 |
from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline
|
8 |
+
from huggingface_hub import hf_hub_download
|
9 |
+
from io import BytesIO
|
10 |
+
import torch
|
11 |
+
import safetensors
|
12 |
from dotenv import load_dotenv
|
13 |
+
import tqdm
|
14 |
import re
|
|
|
|
|
15 |
|
16 |
# Cargar las variables de entorno desde el archivo .env
|
17 |
load_dotenv()
|
|
|
53 |
try:
|
54 |
print(f"[INFO] Descargando archivo {key} desde S3...")
|
55 |
response = self.s3_client.get_object(Bucket=self.bucket_name, Key=key)
|
56 |
+
return BytesIO(response['Body'].read()) # Devolver el cuerpo como BytesIO
|
57 |
except self.s3_client.exceptions.NoSuchKey:
|
58 |
raise HTTPException(status_code=404, detail=f"El archivo {key} no existe en el bucket S3.")
|
59 |
except Exception as e:
|
|
|
67 |
except self.s3_client.exceptions.ClientError:
|
68 |
return False
|
69 |
|
70 |
+
def load_model_from_s3(self, model_name):
|
71 |
try:
|
72 |
print(f"[INFO] Cargando el modelo {model_name} desde S3...")
|
73 |
+
|
74 |
+
# Verificar si el modelo existe en S3
|
75 |
model_prefix = model_name.lower()
|
76 |
model_files = self.get_model_file_parts(model_prefix)
|
77 |
|
|
|
83 |
if not model_files:
|
84 |
raise HTTPException(status_code=404, detail=f"Archivos del modelo {model_name} no encontrados en S3.")
|
85 |
|
86 |
+
# Cargar todos los archivos del modelo desde S3
|
87 |
model_streams = []
|
88 |
+
for model_file in tqdm.tqdm(model_files, desc="Cargando archivos del modelo", unit="archivo"):
|
89 |
model_streams.append(self.stream_from_s3(model_file))
|
90 |
|
91 |
config_stream = self.stream_from_s3(f"{model_prefix}/config.json")
|
92 |
+
config_data = json.loads(config_stream.read().decode("utf-8"))
|
93 |
|
94 |
# Cargar el modelo dependiendo del tipo de archivo (torch o safetensors)
|
95 |
+
if any(file.endswith("model.safetensors") for file in model_files):
|
96 |
print("[INFO] Cargando el modelo como safetensor...")
|
97 |
model = AutoModelForCausalLM.from_config(config_data)
|
98 |
model.load_state_dict(safetensors.torch.load_stream(model_streams[0]))
|
|
|
108 |
print(f"[ERROR] Error al cargar el modelo desde S3: {e}")
|
109 |
raise HTTPException(status_code=500, detail="Error al cargar el modelo desde S3.")
|
110 |
|
111 |
+
def load_tokenizer_from_s3(self, model_name):
|
112 |
try:
|
113 |
print(f"[INFO] Cargando el tokenizer {model_name} desde S3...")
|
114 |
tokenizer_stream = self.stream_from_s3(f"{model_name}/tokenizer.json")
|
|
|
122 |
print(f"[INFO] Listando archivos del modelo en S3 con prefijo {model_name}...")
|
123 |
files = self.s3_client.list_objects_v2(Bucket=self.bucket_name, Prefix=model_name)
|
124 |
model_files = []
|
125 |
+
for obj in tqdm.tqdm(files.get('Contents', []), desc="Verificando archivos", unit="archivo"):
|
126 |
key = obj['Key']
|
127 |
+
# Verificar si es un archivo relevante del modelo
|
128 |
+
if re.match(rf"{model_name}/.*", key):
|
129 |
model_files.append(key)
|
130 |
if not model_files:
|
131 |
print(f"[WARNING] No se encontraron archivos para el modelo {model_name}.")
|
|
|
134 |
def download_and_upload_from_huggingface(self, model_name):
|
135 |
try:
|
136 |
print(f"[INFO] Descargando {model_name} desde Hugging Face...")
|
137 |
+
# Descargar todos los archivos del modelo
|
138 |
+
files_to_download = hf_hub_download(repo_id=model_name, use_auth_token=HUGGINGFACE_TOKEN)
|
|
|
|
|
|
|
|
|
139 |
|
140 |
+
# Subir a S3 los archivos descargados
|
141 |
for file in files_to_download:
|
142 |
+
file_name = os.path.basename(file)
|
143 |
+
s3_key = f"{model_name}/{file_name}"
|
144 |
+
if not self.file_exists_in_s3(s3_key):
|
145 |
+
self.upload_file_to_s3(file, s3_key)
|
146 |
+
|
147 |
except Exception as e:
|
148 |
print(f"[ERROR] Error al descargar y subir modelo desde Hugging Face: {e}")
|
149 |
raise HTTPException(status_code=500, detail="Error al descargar y subir modelo desde Hugging Face.")
|
|
|
153 |
print(f"[INFO] Subiendo archivo {file_path} a S3 con key {s3_key}...")
|
154 |
with open(file_path, 'rb') as data:
|
155 |
self.s3_client.put_object(Bucket=self.bucket_name, Key=s3_key, Body=data)
|
156 |
+
# Eliminar archivo local despu茅s de ser subido
|
157 |
+
os.remove(file_path)
|
158 |
except Exception as e:
|
159 |
print(f"[ERROR] Error al subir archivo a S3: {e}")
|
160 |
raise HTTPException(status_code=500, detail="Error al subir archivo a S3.")
|
161 |
|
162 |
+
|
163 |
@app.post("/predict/")
|
164 |
async def predict(model_request: DownloadModelRequest):
|
165 |
try:
|
166 |
print(f"[INFO] Recibiendo solicitud para predecir con el modelo {model_request.model_name}...")
|
167 |
streamer = S3DirectStream(S3_BUCKET_NAME)
|
168 |
+
model = streamer.load_model_from_s3(model_request.model_name)
|
169 |
+
tokenizer = streamer.load_tokenizer_from_s3(model_request.model_name)
|
170 |
|
171 |
task = model_request.pipeline_task
|
172 |
+
if task not in ["text-generation", "sentiment-analysis", "translation", "fill-mask", "question-answering",
|
173 |
+
"text-to-speech", "text-to-video", "text-to-image"]:
|
174 |
raise HTTPException(status_code=400, detail="Pipeline task no soportado")
|
175 |
|
176 |
+
# Configurar el pipeline de transformers seg煤n la tarea
|
177 |
+
nlp_pipeline = None
|
178 |
+
if task == "text-generation":
|
179 |
+
nlp_pipeline = pipeline("text-generation", model=model, tokenizer=tokenizer)
|
180 |
+
elif task == "sentiment-analysis":
|
181 |
+
nlp_pipeline = pipeline("sentiment-analysis", model=model, tokenizer=tokenizer)
|
182 |
+
elif task == "translation":
|
183 |
+
nlp_pipeline = pipeline("translation", model=model, tokenizer=tokenizer)
|
184 |
+
elif task == "fill-mask":
|
185 |
+
nlp_pipeline = pipeline("fill-mask", model=model, tokenizer=tokenizer)
|
186 |
+
elif task == "question-answering":
|
187 |
+
nlp_pipeline = pipeline("question-answering", model=model, tokenizer=tokenizer)
|
188 |
+
elif task == "text-to-speech":
|
189 |
+
nlp_pipeline = pipeline("text-to-speech", model=model, tokenizer=tokenizer)
|
190 |
elif task == "text-to-video":
|
191 |
+
nlp_pipeline = pipeline("text-to-video", model=model, tokenizer=tokenizer)
|
192 |
+
elif task == "text-to-image":
|
193 |
+
nlp_pipeline = pipeline("text-to-image", model=model, tokenizer=tokenizer)
|
194 |
+
|
195 |
+
result = nlp_pipeline(model_request.input_text)
|
196 |
+
return {"result": result}
|
197 |
|
|
|
198 |
except Exception as e:
|
199 |
+
print(f"[ERROR] Error en el proceso de predicci贸n: {str(e)}")
|
200 |
+
raise HTTPException(status_code=500, detail="Error en el proceso de predicci贸n")
|
201 |
+
|
202 |
|
203 |
+
# Ejecutar la app con Uvicorn
|
204 |
if __name__ == "__main__":
|
205 |
+
uvicorn.run(app, host="0.0.0.0", port=8000)
|
|