Spaces:
Paused
Paused
Upload 10 files
Browse files- .gitattributes +35 -35
- Dockerfile +32 -0
- README.md +12 -10
- app.py +6 -0
- app/__init__.py +9 -0
- app/config.py +6 -0
- app/routes.py +140 -0
- app/utils.py +105 -0
- docker-compose.yml +21 -0
- requirements.txt +8 -0
.gitattributes
CHANGED
@@ -1,35 +1,35 @@
|
|
1 |
-
*.7z filter=lfs diff=lfs merge=lfs -text
|
2 |
-
*.arrow filter=lfs diff=lfs merge=lfs -text
|
3 |
-
*.bin filter=lfs diff=lfs merge=lfs -text
|
4 |
-
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
5 |
-
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
6 |
-
*.ftz filter=lfs diff=lfs merge=lfs -text
|
7 |
-
*.gz filter=lfs diff=lfs merge=lfs -text
|
8 |
-
*.h5 filter=lfs diff=lfs merge=lfs -text
|
9 |
-
*.joblib filter=lfs diff=lfs merge=lfs -text
|
10 |
-
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
11 |
-
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
12 |
-
*.model filter=lfs diff=lfs merge=lfs -text
|
13 |
-
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
14 |
-
*.npy filter=lfs diff=lfs merge=lfs -text
|
15 |
-
*.npz filter=lfs diff=lfs merge=lfs -text
|
16 |
-
*.onnx filter=lfs diff=lfs merge=lfs -text
|
17 |
-
*.ot filter=lfs diff=lfs merge=lfs -text
|
18 |
-
*.parquet filter=lfs diff=lfs merge=lfs -text
|
19 |
-
*.pb filter=lfs diff=lfs merge=lfs -text
|
20 |
-
*.pickle filter=lfs diff=lfs merge=lfs -text
|
21 |
-
*.pkl filter=lfs diff=lfs merge=lfs -text
|
22 |
-
*.pt filter=lfs diff=lfs merge=lfs -text
|
23 |
-
*.pth filter=lfs diff=lfs merge=lfs -text
|
24 |
-
*.rar filter=lfs diff=lfs merge=lfs -text
|
25 |
-
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
26 |
-
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
27 |
-
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
28 |
-
*.tar filter=lfs diff=lfs merge=lfs -text
|
29 |
-
*.tflite filter=lfs diff=lfs merge=lfs -text
|
30 |
-
*.tgz filter=lfs diff=lfs merge=lfs -text
|
31 |
-
*.wasm filter=lfs diff=lfs merge=lfs -text
|
32 |
-
*.xz filter=lfs diff=lfs merge=lfs -text
|
33 |
-
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
-
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
-
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
1 |
+
*.7z filter=lfs diff=lfs merge=lfs -text
|
2 |
+
*.arrow filter=lfs diff=lfs merge=lfs -text
|
3 |
+
*.bin filter=lfs diff=lfs merge=lfs -text
|
4 |
+
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
5 |
+
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
6 |
+
*.ftz filter=lfs diff=lfs merge=lfs -text
|
7 |
+
*.gz filter=lfs diff=lfs merge=lfs -text
|
8 |
+
*.h5 filter=lfs diff=lfs merge=lfs -text
|
9 |
+
*.joblib filter=lfs diff=lfs merge=lfs -text
|
10 |
+
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
11 |
+
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
12 |
+
*.model filter=lfs diff=lfs merge=lfs -text
|
13 |
+
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
14 |
+
*.npy filter=lfs diff=lfs merge=lfs -text
|
15 |
+
*.npz filter=lfs diff=lfs merge=lfs -text
|
16 |
+
*.onnx filter=lfs diff=lfs merge=lfs -text
|
17 |
+
*.ot filter=lfs diff=lfs merge=lfs -text
|
18 |
+
*.parquet filter=lfs diff=lfs merge=lfs -text
|
19 |
+
*.pb filter=lfs diff=lfs merge=lfs -text
|
20 |
+
*.pickle filter=lfs diff=lfs merge=lfs -text
|
21 |
+
*.pkl filter=lfs diff=lfs merge=lfs -text
|
22 |
+
*.pt filter=lfs diff=lfs merge=lfs -text
|
23 |
+
*.pth filter=lfs diff=lfs merge=lfs -text
|
24 |
+
*.rar filter=lfs diff=lfs merge=lfs -text
|
25 |
+
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
26 |
+
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
27 |
+
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
28 |
+
*.tar filter=lfs diff=lfs merge=lfs -text
|
29 |
+
*.tflite filter=lfs diff=lfs merge=lfs -text
|
30 |
+
*.tgz filter=lfs diff=lfs merge=lfs -text
|
31 |
+
*.wasm filter=lfs diff=lfs merge=lfs -text
|
32 |
+
*.xz filter=lfs diff=lfs merge=lfs -text
|
33 |
+
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
+
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
+
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
Dockerfile
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
FROM python:3.10-slim
|
2 |
+
|
3 |
+
ENV PYTHONDONTWRITEBYTECODE=1
|
4 |
+
ENV PYTHONUNBUFFERED=1
|
5 |
+
ENV DEBIAN_FRONTEND=noninteractive
|
6 |
+
ENV MODEL_PATH=RufusRubin777/GOT-OCR2_0_CPU
|
7 |
+
|
8 |
+
WORKDIR /app
|
9 |
+
|
10 |
+
RUN apt-get update && apt-get install -y \
|
11 |
+
build-essential \
|
12 |
+
libpq-dev \
|
13 |
+
&& rm -rf /var/lib/apt/lists/*
|
14 |
+
|
15 |
+
COPY requirements.txt .
|
16 |
+
RUN pip install --no-cache-dir -r requirements.txt
|
17 |
+
|
18 |
+
RUN mkdir -p /root/.cache/huggingface
|
19 |
+
VOLUME /root/.cache/huggingface
|
20 |
+
|
21 |
+
RUN python -c "from transformers_modules.RufusRubin777.GOT_OCR2_0_CPU.modeling_GOT import GOTModel, GOTConfig; \
|
22 |
+
from transformers import AutoTokenizer; \
|
23 |
+
model_path='RufusRubin777/GOT-OCR2_0_CPU'; \
|
24 |
+
config = GOTConfig.from_pretrained(model_path); \
|
25 |
+
model = GOTModel.from_pretrained(model_path, config=config); \
|
26 |
+
tokenizer = AutoTokenizer.from_pretrained(model_path)"
|
27 |
+
|
28 |
+
COPY . .
|
29 |
+
|
30 |
+
EXPOSE 7860
|
31 |
+
|
32 |
+
CMD ["python", "app.py"]
|
README.md
CHANGED
@@ -1,10 +1,12 @@
|
|
1 |
-
---
|
2 |
-
title:
|
3 |
-
emoji:
|
4 |
-
colorFrom:
|
5 |
-
colorTo:
|
6 |
-
sdk:
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
|
|
|
|
|
1 |
+
---
|
2 |
+
title: Ocrfood
|
3 |
+
emoji: 🏢
|
4 |
+
colorFrom: pink
|
5 |
+
colorTo: blue
|
6 |
+
sdk: gradio
|
7 |
+
sdk_version: 5.6.0
|
8 |
+
app_file: app.py
|
9 |
+
pinned: false
|
10 |
+
---
|
11 |
+
|
12 |
+
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
app.py
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from app import create_app
|
2 |
+
|
3 |
+
app = create_app()
|
4 |
+
|
5 |
+
if __name__ == '__main__':
|
6 |
+
app.run(host='0.0.0.0', port=7860)
|
app/__init__.py
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from flask import Flask
|
2 |
+
|
3 |
+
def create_app():
|
4 |
+
app = Flask(__name__)
|
5 |
+
|
6 |
+
from app.routes import main
|
7 |
+
app.register_blueprint(main)
|
8 |
+
|
9 |
+
return app
|
app/config.py
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
|
3 |
+
class Config:
|
4 |
+
SECRET_KEY = os.environ.get('SECRET_KEY') or 'your-secret-key'
|
5 |
+
UPLOAD_FOLDER = 'instance/uploads'
|
6 |
+
MAX_CONTENT_LENGTH = 16 * 1024 * 1024 # 16MB max file size
|
app/routes.py
ADDED
@@ -0,0 +1,140 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# routes.py
|
2 |
+
from flask import Blueprint, jsonify, request
|
3 |
+
import io
|
4 |
+
from app.utils import OCRModel
|
5 |
+
import logging
|
6 |
+
|
7 |
+
logging.basicConfig(level=logging.INFO)
|
8 |
+
logger = logging.getLogger(__name__)
|
9 |
+
|
10 |
+
main = Blueprint('main', __name__)
|
11 |
+
ocr_model = OCRModel()
|
12 |
+
|
13 |
+
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg'}
|
14 |
+
|
15 |
+
KNOWN_ALLERGENS = {
|
16 |
+
'gluten': ['wheat', 'barley', 'rye', 'oats', 'gluten', 'flour', 'bread', 'pasta'],
|
17 |
+
'dairy': ['milk', 'yogurt', 'cheese', 'lactose', 'cream', 'butter', 'whey'],
|
18 |
+
'nuts': ['nuts', 'peanuts', 'almonds', 'walnuts', 'cashews', 'pistachios'],
|
19 |
+
'eggs': ['eggs', 'egg', 'albumin', 'mayonnaise'],
|
20 |
+
'soy': ['soy', 'soybeans', 'tofu', 'edamame'],
|
21 |
+
'fish': ['fish', 'salmon', 'tuna', 'cod', 'tilapia'],
|
22 |
+
'shellfish': ['shellfish', 'shrimp', 'crab', 'lobster', 'oyster', 'mussels'],
|
23 |
+
'sesame': ['sesame', 'tahini'],
|
24 |
+
'mustard': ['mustard'],
|
25 |
+
'celery': ['celery'],
|
26 |
+
'lupin': ['lupin'],
|
27 |
+
'sulfites': ['sulfites', 'sulphites']
|
28 |
+
}
|
29 |
+
|
30 |
+
def allowed_file(filename):
|
31 |
+
"""Validate file extension"""
|
32 |
+
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
|
33 |
+
|
34 |
+
def find_allergens(text, user_allergens):
|
35 |
+
"""Finding Sensitivities in the Text"""
|
36 |
+
text = text.lower()
|
37 |
+
found_allergens = set()
|
38 |
+
allergen_details = {}
|
39 |
+
allergen_locations = {}
|
40 |
+
|
41 |
+
for allergen in user_allergens:
|
42 |
+
allergen = allergen.strip().lower()
|
43 |
+
if allergen in KNOWN_ALLERGENS:
|
44 |
+
for variant in KNOWN_ALLERGENS[allergen]:
|
45 |
+
if variant.lower() in text:
|
46 |
+
found_allergens.add(allergen)
|
47 |
+
allergen_details[allergen] = variant
|
48 |
+
# Store the location of the word in the text
|
49 |
+
allergen_locations[allergen] = text.index(variant.lower())
|
50 |
+
elif allergen in text:
|
51 |
+
found_allergens.add(allergen)
|
52 |
+
allergen_details[allergen] = allergen
|
53 |
+
allergen_locations[allergen] = text.index(allergen)
|
54 |
+
|
55 |
+
return found_allergens, allergen_details, allergen_locations
|
56 |
+
|
57 |
+
@main.route('/')
|
58 |
+
def index():
|
59 |
+
return jsonify({
|
60 |
+
"message": "Welcome to the Text Recognition and Sensitivity Checking Service",
|
61 |
+
"endpoints": {
|
62 |
+
"/api/ocr": "POST - Image analysis and sensitivity testing",
|
63 |
+
"/api/allergens": "GET - List of known allergens"
|
64 |
+
},
|
65 |
+
"supported_formats": list(ALLOWED_EXTENSIONS),
|
66 |
+
"known_allergens": list(KNOWN_ALLERGENS.keys())
|
67 |
+
})
|
68 |
+
|
69 |
+
@main.route('/api/ocr', methods=['POST'])
|
70 |
+
def process_image():
|
71 |
+
try:
|
72 |
+
# Check if file exists
|
73 |
+
if 'file' not in request.files:
|
74 |
+
logger.warning("No file uploaded")
|
75 |
+
return jsonify({"error": "No file uploaded"}), 400
|
76 |
+
|
77 |
+
# Check the list of allergies
|
78 |
+
if 'allergens' not in request.form:
|
79 |
+
logger.warning("Allergens not specified")
|
80 |
+
return jsonify({"error": "Allergens not specified"}), 400
|
81 |
+
|
82 |
+
file = request.files['file']
|
83 |
+
if file.filename == '':
|
84 |
+
logger.warning("No file selected")
|
85 |
+
return jsonify({"error": "No file selected"}), 400
|
86 |
+
|
87 |
+
# Check file type
|
88 |
+
if not allowed_file(file.filename):
|
89 |
+
logger.warning(f"Invalid file type: {file.filename}")
|
90 |
+
return jsonify({
|
91 |
+
"error": "File type not supported",
|
92 |
+
"supported_formats": list(ALLOWED_EXTENSIONS)
|
93 |
+
}), 400
|
94 |
+
|
95 |
+
# Prepare a list of allergies.
|
96 |
+
user_allergens = request.form['allergens'].split(',')
|
97 |
+
logger.info(f"Processing image for allergens: {user_allergens}")
|
98 |
+
|
99 |
+
# Read image
|
100 |
+
file_bytes = file.read()
|
101 |
+
file_stream = io.BytesIO(file_bytes)
|
102 |
+
|
103 |
+
# Processing image
|
104 |
+
extracted_text = ocr_model.process_image(file_stream)
|
105 |
+
logger.info(f"Extracted text: {extracted_text}")
|
106 |
+
|
107 |
+
# Searching for allergies
|
108 |
+
found_allergens, allergen_details, allergen_locations = find_allergens(extracted_text, user_allergens)
|
109 |
+
|
110 |
+
# Response
|
111 |
+
response = {
|
112 |
+
"success": True,
|
113 |
+
"extracted_text": extracted_text,
|
114 |
+
"analysis": {
|
115 |
+
"found_allergens": list(found_allergens),
|
116 |
+
"allergen_details": allergen_details,
|
117 |
+
"allergen_locations": allergen_locations,
|
118 |
+
"has_allergens": len(found_allergens) > 0,
|
119 |
+
"warning": "⚠️ Warning: Allergens found!" if found_allergens else "✅ No allergens found",
|
120 |
+
"severity": "high" if len(found_allergens) > 0 else "none"
|
121 |
+
}
|
122 |
+
}
|
123 |
+
|
124 |
+
logger.info(f"Analysis completed successfully: {found_allergens}")
|
125 |
+
return jsonify(response)
|
126 |
+
|
127 |
+
except Exception as e:
|
128 |
+
logger.error(f"Error processing request: {str(e)}", exc_info=True)
|
129 |
+
return jsonify({
|
130 |
+
"error": "An error occurred while processing the image.",
|
131 |
+
"details": str(e)
|
132 |
+
}), 500
|
133 |
+
|
134 |
+
@main.route('/api/allergens', methods=['GET'])
|
135 |
+
def get_known_allergens():
|
136 |
+
return jsonify({
|
137 |
+
"allergens": KNOWN_ALLERGENS,
|
138 |
+
"total_count": len(KNOWN_ALLERGENS),
|
139 |
+
"last_updated": "2024-03-24" # Update this date when the list is updated.
|
140 |
+
})
|
app/utils.py
ADDED
@@ -0,0 +1,105 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# utils.py
|
2 |
+
import os
|
3 |
+
from transformers import AutoModel, AutoTokenizer
|
4 |
+
from PIL import Image, ImageEnhance, ImageFilter
|
5 |
+
import torch
|
6 |
+
import logging
|
7 |
+
|
8 |
+
logger = logging.getLogger(__name__)
|
9 |
+
|
10 |
+
class OCRModel:
|
11 |
+
_instance = None
|
12 |
+
|
13 |
+
def __new__(cls):
|
14 |
+
if cls._instance is None:
|
15 |
+
cls._instance = super(OCRModel, cls).__new__(cls)
|
16 |
+
cls._instance.initialize()
|
17 |
+
return cls._instance
|
18 |
+
|
19 |
+
def initialize(self):
|
20 |
+
try:
|
21 |
+
logger.info("Initializing OCR model...")
|
22 |
+
|
23 |
+
# Model initilization
|
24 |
+
self.tokenizer = AutoTokenizer.from_pretrained('RufusRubin777/GOT-OCR2_0_CPU', trust_remote_code=True)
|
25 |
+
self.model = AutoModel.from_pretrained(
|
26 |
+
'RufusRubin777/GOT-OCR2_0_CPU',
|
27 |
+
trust_remote_code=True,
|
28 |
+
low_cpu_mem_usage=True,
|
29 |
+
device_map='cpu',
|
30 |
+
use_safetensors=True,
|
31 |
+
pad_token_id=self.tokenizer.eos_token_id
|
32 |
+
)
|
33 |
+
|
34 |
+
# choose cpu
|
35 |
+
self.device = "cpu"
|
36 |
+
self.model = self.model.eval().cpu()
|
37 |
+
|
38 |
+
logger.info("Model initialization completed successfully")
|
39 |
+
|
40 |
+
except Exception as e:
|
41 |
+
logger.error(f"Error initializing model: {str(e)}", exc_info=True)
|
42 |
+
raise
|
43 |
+
|
44 |
+
def preprocess_image(self, image):
|
45 |
+
"""Image preprocessing to improve text recognition quality"""
|
46 |
+
try:
|
47 |
+
# Convert image to RGB if it is not already
|
48 |
+
if image.mode != 'RGB':
|
49 |
+
image = image.convert('RGB')
|
50 |
+
|
51 |
+
# Improve contrast
|
52 |
+
enhancer = ImageEnhance.Contrast(image)
|
53 |
+
image = enhancer.enhance(1.5)
|
54 |
+
|
55 |
+
# Improve Sharpness
|
56 |
+
enhancer = ImageEnhance.Sharpness(image)
|
57 |
+
image = enhancer.enhance(1.5)
|
58 |
+
|
59 |
+
# Improve Brightness
|
60 |
+
enhancer = ImageEnhance.Brightness(image)
|
61 |
+
image = enhancer.enhance(1.2)
|
62 |
+
|
63 |
+
# Apply a filter to soften the image a little.
|
64 |
+
image = image.filter(ImageFilter.SMOOTH)
|
65 |
+
|
66 |
+
return image
|
67 |
+
except Exception as e:
|
68 |
+
logger.error(f"Error in image preprocessing: {str(e)}", exc_info=True)
|
69 |
+
raise
|
70 |
+
|
71 |
+
def process_image(self, image_stream):
|
72 |
+
try:
|
73 |
+
logger.info("Starting image processing")
|
74 |
+
|
75 |
+
# Save image temporarily because the model requires a file path.
|
76 |
+
temp_image_path = "temp_image.jpg"
|
77 |
+
|
78 |
+
# Reset the start pointer for BytesIO
|
79 |
+
image_stream.seek(0)
|
80 |
+
|
81 |
+
# Open and save the image temporarily.
|
82 |
+
image = Image.open(image_stream).convert('RGB')
|
83 |
+
processed_image = self.preprocess_image(image)
|
84 |
+
processed_image.save(temp_image_path)
|
85 |
+
|
86 |
+
# ocr
|
87 |
+
try:
|
88 |
+
result = self.model.chat(self.tokenizer, temp_image_path, ocr_type='format')
|
89 |
+
logger.info(f"Successfully extracted text: {result[:100]}...")
|
90 |
+
|
91 |
+
# Delete temporary file
|
92 |
+
if os.path.exists(temp_image_path):
|
93 |
+
os.remove(temp_image_path)
|
94 |
+
|
95 |
+
return result.strip()
|
96 |
+
|
97 |
+
except Exception as e:
|
98 |
+
logger.error(f"Error in OCR processing: {str(e)}", exc_info=True)
|
99 |
+
if os.path.exists(temp_image_path):
|
100 |
+
os.remove(temp_image_path)
|
101 |
+
raise
|
102 |
+
|
103 |
+
except Exception as e:
|
104 |
+
logger.error(f"Error in image processing: {str(e)}", exc_info=True)
|
105 |
+
return f"Error processing image: {str(e)}"
|
docker-compose.yml
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
version: '3.10'
|
2 |
+
|
3 |
+
services:
|
4 |
+
app:
|
5 |
+
build: .
|
6 |
+
ports:
|
7 |
+
- "7860:7860"
|
8 |
+
volumes:
|
9 |
+
- huggingface_cache:/root/.cache/huggingface
|
10 |
+
environment:
|
11 |
+
- MODEL_PATH=RufusRubin777/GOT-OCR2_0_CPU
|
12 |
+
restart: unless-stopped
|
13 |
+
deploy:
|
14 |
+
resources:
|
15 |
+
limits:
|
16 |
+
memory: 4G
|
17 |
+
reservations:
|
18 |
+
memory: 2G
|
19 |
+
|
20 |
+
volumes:
|
21 |
+
huggingface_cache:
|
requirements.txt
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
accelerate==1.1.1
|
2 |
+
Flask==3.1.0
|
3 |
+
torch==2.5.1
|
4 |
+
torchvision==0.20.1
|
5 |
+
transformers==4.37.2
|
6 |
+
tiktoken==0.6.0
|
7 |
+
verovio==4.3.1
|
8 |
+
gunicorn
|