Hjgugugjhuhjggg commited on
Commit
227ec7b
verified
1 Parent(s): 01774c0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +59 -50
app.py CHANGED
@@ -1,18 +1,17 @@
1
  import os
 
2
  import boto3
3
- import torch
4
  from fastapi import FastAPI, HTTPException
5
  from pydantic import BaseModel
6
- import safetensors.torch
7
  from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline
8
- from fastapi.responses import StreamingResponse
9
- import io
10
- import requests
11
- import uvicorn
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 directamente para el StreamingResponse
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 load_model_from_stream(self, model_name):
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
- # Leer y cargar todos los archivos del modelo
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 model_files[0].endswith("model.safetensors"):
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 load_tokenizer_from_stream(self, model_name):
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
- if re.match(rf"{model_name}/model(-\d+-of-\d+)?", key) or key.endswith("model.safetensors"):
 
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 necesarios de Hugging Face usando huggingface_hub
136
- files_to_download = [
137
- "pytorch_model.bin",
138
- "config.json",
139
- "tokenizer.json",
140
- ]
141
 
 
142
  for file in files_to_download:
143
- # Descargar cada archivo desde Hugging Face y subirlo a S3
144
- file_path = hf_hub_download(repo_id=model_name, filename=file, use_auth_token=HUGGINGFACE_TOKEN)
145
- s3_key = f"{model_name}/{file}"
146
- self.upload_file_to_s3(file_path, s3_key)
 
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.load_model_from_stream(model_request.model_name)
166
- tokenizer = streamer.load_tokenizer_from_stream(model_request.model_name)
167
 
168
  task = model_request.pipeline_task
169
- if task not in ["text-generation", "sentiment-analysis", "translation", "fill-mask", "question-answering", "text-to-speech", "text-to-image", "text-to-audio", "text-to-video"]:
 
170
  raise HTTPException(status_code=400, detail="Pipeline task no soportado")
171
 
172
- nlp_pipeline = pipeline(task, model=model, tokenizer=tokenizer, max_length=2046)
173
-
174
- input_text = model_request.input_text
175
- print(f"[INFO] Ejecutando tarea {task} con el texto de entrada...")
176
- outputs = nlp_pipeline(input_text)
177
-
178
- # Eliminaci贸n de archivo local despu茅s de subir a S3
179
- if task == "text-to-speech":
180
- s3_key = f"{model_request.model_name}/generated_audio.wav"
181
- return StreamingResponse(streamer.stream_from_s3(s3_key), media_type="audio/wav")
182
- elif task == "text-to-image":
183
- s3_key = f"{model_request.model_name}/generated_image.png"
184
- return StreamingResponse(streamer.stream_from_s3(s3_key), media_type="image/png")
 
185
  elif task == "text-to-video":
186
- s3_key = f"{model_request.model_name}/generated_video.mp4"
187
- return StreamingResponse(streamer.stream_from_s3(s3_key), media_type="video/mp4")
 
 
 
 
188
 
189
- return {"output": outputs}
190
  except Exception as e:
191
- print(f"[ERROR] Error al procesar la solicitud: {str(e)}")
192
- raise HTTPException(status_code=500, detail="Error al realizar la predicci贸n.")
 
193
 
 
194
  if __name__ == "__main__":
195
- print("Iniciando servidor de predicciones en localhost:8000")
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)