sterepando commited on
Commit
32ecb63
·
verified ·
1 Parent(s): ea17727

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +67 -63
app.py CHANGED
@@ -2,94 +2,98 @@ import io
2
  import uvicorn
3
  from PIL import Image
4
  from fastapi import FastAPI, UploadFile, File, Response
5
- from transformers import pipeline
6
- import torch
 
 
7
 
8
  # --- 1. Глобальная загрузка модели (СВЕРХБЫСТРЫЙ СТАРТ) ---
9
- # Модель загружается только один раз при запуске сервера.
10
- # Используем пайплайн для простоты и эффективности.
 
 
11
  try:
12
- print(">>> Загрузка модели LightOnOCR-1B-1025... Это может занять несколько минут при первом запуске.")
13
- # Этот код теперь будет работать, так как torch импортирован!
14
- device_to_use = "cuda" if torch.cuda.is_available() else "cpu"
15
- dtype_to_use = torch.bfloat16 if device_to_use == "cuda" else None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
 
17
- ocr_pipeline = pipeline(
18
- "image-to-text",
19
- model="lightonai/LightOnOCR-1B-1025",
20
- device=device_to_use,
21
- torch_dtype=dtype_to_use,
22
- )
23
- print(">>> Модель успешно загружена!")
24
  except Exception as e:
25
- # Ошибка 503 возникает, потому что код попадает сюда.
26
- print(f"Ошибка при загрузке модели: {e}")
27
- ocr_pipeline = None
28
 
29
  # Инициализация FastAPI
30
  app = FastAPI(
31
- title="LightOnOCR Super-Fast API",
32
- description="Публичный API для высокоскоростного распознавания текста.",
33
- version="1.0.0",
34
  )
35
 
36
  # --- 2. Эндпоинт API ---
37
 
38
- # ... (остальной код)
39
-
40
- @app.post(
41
- "/api/ocr",
42
- summary="Запустить OCR по изображению",
43
- response_description="Расшифрованный текст",
44
- )
45
- async def run_ocr(file: UploadFile = File(..., description="Изображение для расшифровки")):
46
- """
47
- Принимает изображение (JPG, PNG и т.д.) и возвращает распознанный текст.
48
- """
49
- if ocr_pipeline is None:
50
- return Response(content="Сервер не готов. Модель не загружена.", status_code=503)
51
 
52
  try:
53
- # 1. Чтение файла в память
54
  contents = await file.read()
55
-
56
- # 2. Конвертация байтов в объект PIL Image
57
- # Важно: .convert("RGB") гарантирует 3 канала, что часто требуется для VLM.
58
  image = Image.open(io.BytesIO(contents)).convert("RGB")
59
 
60
- # --- ИСПРАВЛЕНИЕ: ДОБАВЛЕНИЕ ПРОМПТА И ИЗМЕНЕНИЕ ФОРМАТА ВЫЗОВА ---
 
 
 
 
 
 
 
 
 
61
 
62
- # Рекомендуемый промпт для OCR с этой моделью
63
- # (взято из документации LightOnOCR)
64
- ocr_prompt = "Perform Optical Character Recognition (OCR) on the image. Transcribe all the text."
65
 
66
- # 3. Запуск пайплайна с использованием кортежа (изображение, промпт)
67
- results = ocr_pipeline(
68
- (image, ocr_prompt),
69
- generate_kwargs={"max_new_tokens": 1024}
 
 
70
  )
71
 
72
- # 4. Извлечение текста (остается прежним)
73
- if results and isinstance(results, list) and 'generated_text' in results[0]:
74
- decoded_text = results[0]['generated_text']
75
- return {"text": decoded_text}
76
- else:
77
- return {"text": "Ошибка: Не удалось распознать текст или результат пуст."}
 
78
 
79
  except Exception as e:
80
- # Логирование ошибок для отладки
81
- print(f"Ошибка обработки запроса: {e}")
82
- return Response(content=f"Внутренняя ошибка сервера: {str(e)}", status_code=500)
83
-
84
- # --- 3. Главная страница (для совместимости с HF Space) ---
85
 
86
- @app.get("/", include_in_schema=False)
87
  async def home():
88
- """Перенаправление на документацию API."""
89
- return {"message": "API запущен. Используйте эндпоинт /api/ocr (POST) или посмотрите документацию по /docs"}
90
 
91
- # --- 4. Запуск сервера (для локального тестирования) ---
92
  if __name__ == "__main__":
93
- # На Hugging Face Space этот блок не запускается,
94
- # сервер запускается через команду uvicorn (см. ниже)
95
  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
+
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)