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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +48 -48
app.py CHANGED
@@ -3,97 +3,97 @@ 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, AutoProcessor
9
 
10
- # --- 1. Глобальная загрузка модели (СВЕРХБЫСТРЫЙ СТАРТ) ---
11
- processor = None
12
  model = None
 
 
13
  device = "cpu"
14
 
15
  try:
16
- print(">>> Инициализация загрузки модели LightOnOCR-1B-1025...")
17
 
18
- # Определяем устройство
19
  device = "cuda" if torch.cuda.is_available() else "cpu"
20
- print(f">>> Используемое устройство: {device}")
21
 
22
- # Загружаем процессор (он обрабатывает и картинки, и текст)
23
- processor = AutoProcessor.from_pretrained("lightonai/LightOnOCR-1B-1025")
 
 
24
 
25
- # Загружаем саму модель
26
- # Если есть GPU, используем float16/bfloat16 для скорости. Если CPU - float32 (по умолчанию)
27
- dtype = torch.bfloat16 if device == "cuda" else torch.float32
28
 
 
 
29
  model = AutoModelForImageTextToText.from_pretrained(
30
- "lightonai/LightOnOCR-1B-1025",
31
  torch_dtype=dtype,
32
  low_cpu_mem_usage=True
33
  ).to(device)
34
 
35
- print(">>> Модель и процессор успешно загружены!")
36
 
37
  except Exception as e:
38
- print(f"КРИТИЧЕСКАЯ ОШИБКА при загрузке модели: {e}")
39
 
40
  # Инициализация FastAPI
41
- app = FastAPI(
42
- title="LightOnOCR API",
43
- description="Прямой инференс через Processor + Model",
44
- version="2.0.0",
45
- )
46
-
47
- # --- 2. Эндпоинт API ---
48
 
49
  @app.post("/api/ocr")
50
  async def run_ocr(file: UploadFile = File(...)):
51
- if model is None or processor is None:
52
- return Response(content="Сервер не готов. Модель не загрузилась.", status_code=503)
53
 
54
  try:
55
- # 1. Чтение файла
56
  contents = await file.read()
57
  image = Image.open(io.BytesIO(contents)).convert("RGB")
58
 
59
- # 2. Подготовка промпта
60
- # Эта модель требует текстовую инструкцию для начала работы
61
- prompt_text = "Perform Optical Character Recognition (OCR) on the image. Transcribe all the text."
 
62
 
63
- # 3. Препроцессинг (Самый важный этап, где мы соединяем картинку и текст)
64
- inputs = processor(
65
- text=prompt_text,
66
- images=image,
67
- return_tensors="pt"
68
- )
69
 
70
- # Переносим тензоры на то же устройство, где модель (GPU или CPU)
71
- inputs = {k: v.to(device) for k, v in inputs.items()}
 
72
 
73
- # 4. Генерация (Собственно OCR)
74
- # max_new_tokens ограничивает длину ответа, можно увелич��ть при необходимости
75
  generated_ids = model.generate(
76
- **inputs,
 
 
77
  max_new_tokens=1024,
78
- do_sample=False # False делает ответ детерминированным (стабильным)
 
79
  )
80
 
81
- # 5. Декодирование ответа
82
- generated_text = processor.batch_decode(generated_ids, skip_special_tokens=True)[0]
83
 
84
- # Очистка результата (иногда модель повторяет промпт в ответе, уберем его если нужно)
85
- # Обычно batch_decode возвращает чистый текст, но на всякий случай просто вернем результат
 
 
86
 
87
- return {"text": generated_text}
88
 
89
  except Exception as e:
90
- print(f"Ошибка во время обработки: {e}")
91
- # Возвращаем JSON с ошибкой для наглядности в тестере
92
  return Response(content=f"Error: {str(e)}", status_code=500)
93
 
94
  @app.get("/")
95
  async def home():
96
- return {"message": "OCR API is running via Processor/Model approach. POST image to /api/ocr"}
97
 
98
  if __name__ == "__main__":
99
  uvicorn.run(app, host="0.0.0.0", port=7860)
 
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
 
10
+ # --- 1. Глобальная загрузка компонентов ---
 
11
  model = None
12
+ tokenizer = None
13
+ 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. Загружаем модель
31
+ dtype = torch.bfloat16 if device == "cuda" else torch.float32
32
  model = AutoModelForImageTextToText.from_pretrained(
33
+ repo_id,
34
  torch_dtype=dtype,
35
  low_cpu_mem_usage=True
36
  ).to(device)
37
 
38
+ print(">>> Все компоненты успешно загружены!")
39
 
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)