sterepando commited on
Commit
5705c9e
·
verified ·
1 Parent(s): c17ab8e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +38 -31
app.py CHANGED
@@ -2,8 +2,6 @@ import io
2
  import uvicorn
3
  from PIL import Image
4
  from fastapi import FastAPI, UploadFile, File, Response
5
-
6
- # Импорты
7
  import torch
8
  from transformers import AutoModelForImageTextToText, AutoTokenizer, AutoImageProcessor
9
 
@@ -14,17 +12,18 @@ image_processor = None
14
  device = "cpu"
15
 
16
  try:
17
- print(">>> Инициализация загрузки LightOnOCR-1B...")
18
 
19
  device = "cuda" if torch.cuda.is_available() else "cpu"
20
  print(f">>> Устройство: {device}")
21
 
22
  repo_id = "lightonai/LightOnOCR-1B-1025"
23
 
24
- # 1. Загружаем токенизатор (для текста)
25
  tokenizer = AutoTokenizer.from_pretrained(repo_id)
26
 
27
- # 2. Загружаем обработчик изображений (для картинок)
 
28
  image_processor = AutoImageProcessor.from_pretrained(repo_id)
29
 
30
  # 3. Загружаем модель
@@ -40,60 +39,68 @@ try:
40
  except Exception as e:
41
  print(f"КРИТИЧЕСКАЯ ОШИБКА загрузки: {e}")
42
 
43
- # Инициализация FastAPI
44
- app = FastAPI(title="LightOnOCR Manual API", version="3.0.0")
45
 
46
  @app.post("/api/ocr")
47
  async def run_ocr(file: UploadFile = File(...)):
48
  if model is None:
49
- return Response(content="Сервер не готов. Модель не загружена.", status_code=503)
50
 
51
  try:
52
- # 1. Чтение и конвертация картинки
53
  contents = await file.read()
54
  image = Image.open(io.BytesIO(contents)).convert("RGB")
55
 
56
- # 2. Обработка изображения (получаем тензоры пикселей)
57
- # image_processor вернет словарь с ключом 'pixel_values'
 
58
  vision_outputs = image_processor(images=image, return_tensors="pt")
59
- pixel_values = vision_outputs["pixel_values"].to(device)
60
 
61
- # 3. Подготовка текста (Промпта)
62
- # Критически важно добавить <image>, чтобы модель знала контекст
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63
  prompt = "<image>\nTranscribe the text in this image."
64
 
65
  text_inputs = tokenizer(prompt, return_tensors="pt")
66
- input_ids = text_inputs["input_ids"].to(device)
67
- attention_mask = text_inputs["attention_mask"].to(device)
68
 
69
  # 4. Генерация
70
- # Передаем все компоненты в generate
71
- generated_ids = model.generate(
72
- input_ids=input_ids,
73
- attention_mask=attention_mask,
74
- pixel_values=pixel_values,
75
- max_new_tokens=1024,
76
- do_sample=False, # Детерминированный результат (лучше для OCR)
77
- pad_token_id=tokenizer.pad_token_id
78
- )
79
 
80
  # 5. Декодирование
81
  generated_text = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]
82
 
83
- # Очистка: иногда модель возвращает сам промпт и��и артефакты в начале.
84
- # Обычно batch_decode(skiыp_special_tokens=True) убирает <image>, но может оставить текст промпта.
85
- # Простая очистка (опционально):
86
  clean_text = generated_text.replace("Transcribe the text in this image.", "").strip()
87
 
88
  return {"text": clean_text}
89
 
90
  except Exception as e:
91
- print(f"Ошибка инференса: {e}")
92
- return Response(content=f"Error: {str(e)}", status_code=500)
 
93
 
94
  @app.get("/")
95
  async def home():
96
- return {"message": "OCR API Ready. Use POST /api/ocr"}
97
 
98
  if __name__ == "__main__":
99
  uvicorn.run(app, host="0.0.0.0", port=7860)
 
2
  import uvicorn
3
  from PIL import Image
4
  from fastapi import FastAPI, UploadFile, File, Response
 
 
5
  import torch
6
  from transformers import AutoModelForImageTextToText, AutoTokenizer, AutoImageProcessor
7
 
 
12
  device = "cpu"
13
 
14
  try:
15
+ print(">>> Инициализация загрузки LightOnOCR-1B (Fixed VLM pipeline)...")
16
 
17
  device = "cuda" if torch.cuda.is_available() else "cpu"
18
  print(f">>> Устройство: {device}")
19
 
20
  repo_id = "lightonai/LightOnOCR-1B-1025"
21
 
22
+ # 1. Загружаем токенизатор
23
  tokenizer = AutoTokenizer.from_pretrained(repo_id)
24
 
25
+ # 2. Загружаем обработчик изображений
26
+ # Используем AutoImageProcessor, он должен вернуть правильный класс
27
  image_processor = AutoImageProcessor.from_pretrained(repo_id)
28
 
29
  # 3. Загружаем модель
 
39
  except Exception as e:
40
  print(f"КРИТИЧЕСКАЯ ОШИБКА загрузки: {e}")
41
 
42
+ app = FastAPI(title="LightOnOCR Robust API", version="4.0.0")
 
43
 
44
  @app.post("/api/ocr")
45
  async def run_ocr(file: UploadFile = File(...)):
46
  if model is None:
47
+ return Response(content="Сервер не готов.", status_code=503)
48
 
49
  try:
50
+ # 1. Загрузка картинки
51
  contents = await file.read()
52
  image = Image.open(io.BytesIO(contents)).convert("RGB")
53
 
54
+ # 2. Подготовка визуальных данных
55
+ # ВАЖНО: Мы не просто берем pixel_values, мы берем ВСЕ, что вернет процессор.
56
+ # Современные модели требуют 'image_sizes' или 'aspect_ratio_ids'.
57
  vision_outputs = image_processor(images=image, return_tensors="pt")
 
58
 
59
+ # Переносим тензоры на устройство (GPU/CPU)
60
+ # Создаем словарь аргументов для генерации
61
+ gen_kwargs = {
62
+ "max_new_tokens": 1024,
63
+ "do_sample": False,
64
+ "pad_token_id": tokenizer.pad_token_id
65
+ }
66
+
67
+ # Автоматически добавляем все выходы процессора (pixel_values, image_sizes и т.д.)
68
+ for key, value in vision_outputs.items():
69
+ if isinstance(value, torch.Tensor):
70
+ gen_kwargs[key] = value.to(device)
71
+ else:
72
+ gen_kwargs[key] = value
73
+
74
+ # 3. Подготовка текста
75
+ # Стандартный формат промпта для LLaVA-подобных моделей
76
  prompt = "<image>\nTranscribe the text in this image."
77
 
78
  text_inputs = tokenizer(prompt, return_tensors="pt")
79
+ gen_kwargs["input_ids"] = text_inputs["input_ids"].to(device)
80
+ gen_kwargs["attention_mask"] = text_inputs["attention_mask"].to(device)
81
 
82
  # 4. Генерация
83
+ # Теперь gen_kwargs содержит и pixel_values, и image_sizes (если они нужны модели)
84
+ with torch.inference_mode():
85
+ generated_ids = model.generate(**gen_kwargs)
 
 
 
 
 
 
86
 
87
  # 5. Декодирование
88
  generated_text = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]
89
 
90
+ # Очистка от артефактов промпта (опционально)
91
+ # Часто модель возвращает "Transcribe... \n Результат". Уберем промпт.
 
92
  clean_text = generated_text.replace("Transcribe the text in this image.", "").strip()
93
 
94
  return {"text": clean_text}
95
 
96
  except Exception as e:
97
+ import traceback
98
+ traceback.print_exc() # Печатаем полный лог ошибки в консоль сервера
99
+ return Response(content=f"Server Error: {str(e)}", status_code=500)
100
 
101
  @app.get("/")
102
  async def home():
103
+ return {"message": "OCR API Ready. POST image to /api/ocr"}
104
 
105
  if __name__ == "__main__":
106
  uvicorn.run(app, host="0.0.0.0", port=7860)