lucianotonet commited on
Commit
29a9d45
·
1 Parent(s): 690d40a

Atualiza processamento de imagens e simplifica código

Browse files

Melhorou o processo de manipulação de imagens ao permitir a entrada através de URL, base64 ou caminho local de forma mais eficiente. Removeu parâmetros de configuração desnecessários para o processador, facilitando a inicialização. A validação de mensagens foi aprimorada para garantir que apenas formatos válidos sejam aceitos, evitando erros. Essa refatoração torna o código mais limpo e robusto, melhorando a manutenabilidade e a legibilidade.

Files changed (1) hide show
  1. app.py +18 -26
app.py CHANGED
@@ -1,6 +1,5 @@
1
  from fastapi import FastAPI, Body
2
  from transformers import Qwen2VLForConditionalGeneration, AutoProcessor
3
- from qwen_vl_utils import process_vision_info
4
  import torch
5
  from typing import List, Dict, Union
6
  import base64
@@ -10,13 +9,13 @@ from io import BytesIO
10
 
11
  app = FastAPI()
12
 
 
13
  model = Qwen2VLForConditionalGeneration.from_pretrained("Qwen/Qwen2-VL-2B-Instruct", torch_dtype="auto", device_map="auto")
14
- min_pixels = 256 * 28 * 28
15
- max_pixels = 1280 * 28 * 28
16
- processor = AutoProcessor.from_pretrained("Qwen/Qwen2-VL-2B-Instruct", min_pixels=min_pixels, max_pixels=max_pixels)
17
 
18
  def process_image(image_data: str) -> Image.Image:
19
- if image_data.startswith("http://") or image_data.startswith("https://"):
 
20
  response = requests.get(image_data)
21
  response.raise_for_status()
22
  img = Image.open(BytesIO(response.content))
@@ -31,44 +30,37 @@ def process_image(image_data: str) -> Image.Image:
31
  async def predict(messages: List[Dict[str, Union[str, List[Dict[str, str]]]]] = Body(...)):
32
  texts = []
33
  image_inputs = []
34
- video_inputs = []
35
 
 
36
  for message in messages:
37
  content = message.get("content")
38
  if isinstance(content, str):
39
  texts.append(processor.apply_chat_template(content, tokenize=False, add_generation_prompt=True))
40
  elif isinstance(content, list):
41
  for item in content:
42
- if isinstance(item, dict) and "type" in item:
43
- if item["type"] == "text":
44
- texts.append(processor.apply_chat_template(item["text"], tokenize=False, add_generation_prompt=True))
45
- elif item["type"] == "image":
46
- image = process_image(item["image"])
47
- image_inputs.append(image)
48
  else:
49
  raise ValueError(f"Formato inválido para o item: {item}")
50
  else:
51
  raise ValueError(f"Formato inválido para o conteúdo: {content}")
52
 
53
- if not image_inputs:
54
- raise ValueError("Nenhuma imagem fornecida para processamento.")
55
-
56
- print(f"Imagens processadas: {image_inputs}")
57
-
58
  inputs = processor(
59
  text=texts,
60
- images=[image_inputs], # Passa as imagens como uma lista de listas
61
- videos=video_inputs,
62
  padding=True,
63
  return_tensors="pt"
64
- )
65
- inputs = inputs.to("cpu")
66
 
 
67
  generated_ids = model.generate(**inputs, max_new_tokens=128)
68
- generated_ids_trimmed = [
69
- out_ids[len(in_ids):] for in_ids, out_ids in zip(inputs.input_ids, generated_ids)
70
- ]
71
  output_texts = processor.batch_decode(
72
- generated_ids_trimmed, skip_special_tokens=True, clean_up_tokenization_spaces=False
 
 
73
  )
74
- return {"response": output_texts}
 
1
  from fastapi import FastAPI, Body
2
  from transformers import Qwen2VLForConditionalGeneration, AutoProcessor
 
3
  import torch
4
  from typing import List, Dict, Union
5
  import base64
 
9
 
10
  app = FastAPI()
11
 
12
+ # Carrega o modelo e o processor
13
  model = Qwen2VLForConditionalGeneration.from_pretrained("Qwen/Qwen2-VL-2B-Instruct", torch_dtype="auto", device_map="auto")
14
+ processor = AutoProcessor.from_pretrained("Qwen/Qwen2-VL-2B-Instruct")
 
 
15
 
16
  def process_image(image_data: str) -> Image.Image:
17
+ """Processa uma imagem a partir de URL, base64 ou caminho local."""
18
+ if image_data.startswith(("http://", "https://")):
19
  response = requests.get(image_data)
20
  response.raise_for_status()
21
  img = Image.open(BytesIO(response.content))
 
30
  async def predict(messages: List[Dict[str, Union[str, List[Dict[str, str]]]]] = Body(...)):
31
  texts = []
32
  image_inputs = []
 
33
 
34
+ # Processa as mensagens recebidas
35
  for message in messages:
36
  content = message.get("content")
37
  if isinstance(content, str):
38
  texts.append(processor.apply_chat_template(content, tokenize=False, add_generation_prompt=True))
39
  elif isinstance(content, list):
40
  for item in content:
41
+ if item.get("type") == "text":
42
+ texts.append(processor.apply_chat_template(item["text"], tokenize=False, add_generation_prompt=True))
43
+ elif item.get("type") == "image":
44
+ image = process_image(item["image"])
45
+ image_inputs.append(image)
 
46
  else:
47
  raise ValueError(f"Formato inválido para o item: {item}")
48
  else:
49
  raise ValueError(f"Formato inválido para o conteúdo: {content}")
50
 
51
+ # Prepara inputs para o modelo
 
 
 
 
52
  inputs = processor(
53
  text=texts,
54
+ images=image_inputs if image_inputs else None, # Passa as imagens se houver
 
55
  padding=True,
56
  return_tensors="pt"
57
+ ).to("cpu")
 
58
 
59
+ # Gera as respostas
60
  generated_ids = model.generate(**inputs, max_new_tokens=128)
 
 
 
61
  output_texts = processor.batch_decode(
62
+ generated_ids[:, inputs.input_ids.shape[-1]:],
63
+ skip_special_tokens=True,
64
+ clean_up_tokenization_spaces=False
65
  )
66
+ return {"response": output_texts}