Commit
·
a3556f1
1
Parent(s):
8882e41
fix main restart time
Browse files
main.py
CHANGED
@@ -19,86 +19,40 @@ load_dotenv()
|
|
19 |
BASE_DIR = '/tmp' # Use direct /tmp path for Hugging Face
|
20 |
log_dir = os.path.join(BASE_DIR, 'app_logs')
|
21 |
cache_dir = os.path.join(BASE_DIR, 'app_cache')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
|
23 |
def ensure_directory(path):
|
24 |
"""Create directory and ensure full permissions with better error handling"""
|
|
|
|
|
|
|
25 |
try:
|
26 |
-
# First try to create the directory with full permissions
|
27 |
os.makedirs(path, mode=0o777, exist_ok=True)
|
28 |
-
|
29 |
-
# Double-check the permissions and try to set them again if needed
|
30 |
-
current_mode = os.stat(path).st_mode & 0o777
|
31 |
-
if current_mode != 0o777:
|
32 |
-
os.chmod(path, 0o777)
|
33 |
-
|
34 |
-
# Verify the directory is writable
|
35 |
-
test_file = os.path.join(path, '.test_write')
|
36 |
-
try:
|
37 |
-
with open(test_file, 'w') as f:
|
38 |
-
f.write('test')
|
39 |
-
os.remove(test_file)
|
40 |
-
except Exception as e:
|
41 |
-
raise Exception(f"Directory {path} is not writable: {str(e)}")
|
42 |
-
|
43 |
except Exception as e:
|
44 |
-
# If we can't set full permissions, try with more restrictive ones
|
45 |
try:
|
46 |
os.makedirs(path, mode=0o755, exist_ok=True)
|
47 |
-
|
48 |
-
|
49 |
-
# Verify the directory is at least readable
|
50 |
-
if not os.access(path, os.R_OK | os.W_OK):
|
51 |
-
raise Exception(f"Cannot read/write to directory: {path}")
|
52 |
-
|
53 |
except Exception as nested_e:
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
log_file = os.path.join(log_dir, f'app_{datetime.now().strftime("%Y%m%d_%H%M%S")}.log')
|
64 |
-
try:
|
65 |
-
# Create log file with full permissions
|
66 |
-
with open(log_file, 'w') as f:
|
67 |
-
pass
|
68 |
-
os.chmod(log_file, 0o666)
|
69 |
-
except Exception as e:
|
70 |
-
print(f"Warning: Could not create log file: {e}")
|
71 |
-
log_file = os.path.join(BASE_DIR, 'app.log')
|
72 |
-
with open(log_file, 'w') as f:
|
73 |
-
pass
|
74 |
-
os.chmod(log_file, 0o666)
|
75 |
-
|
76 |
-
# Set up logging to both file and console
|
77 |
-
try:
|
78 |
-
logging.basicConfig(
|
79 |
-
level=logging.INFO,
|
80 |
-
format='%(asctime)s - %(levelname)s - %(message)s',
|
81 |
-
handlers=[
|
82 |
-
logging.FileHandler(log_file),
|
83 |
-
logging.StreamHandler(sys.stdout)
|
84 |
-
]
|
85 |
-
)
|
86 |
-
except Exception as e:
|
87 |
-
print(f"Warning: Could not set up file logging: {e}")
|
88 |
-
# Fallback to console-only logging
|
89 |
-
logging.basicConfig(
|
90 |
-
level=logging.INFO,
|
91 |
-
format='%(asctime)s - %(levelname)s - %(message)s',
|
92 |
-
handlers=[logging.StreamHandler(sys.stdout)]
|
93 |
-
)
|
94 |
-
|
95 |
-
# Create a custom logger
|
96 |
logger = logging.getLogger(__name__)
|
97 |
|
98 |
-
# Add a print function that also logs
|
99 |
def log_print(message, level="INFO"):
|
100 |
-
# Use the original print function to avoid recursion
|
101 |
-
builtins.print(message, flush=True)
|
102 |
if level == "INFO":
|
103 |
logger.info(message)
|
104 |
elif level == "ERROR":
|
@@ -106,24 +60,24 @@ def log_print(message, level="INFO"):
|
|
106 |
elif level == "WARNING":
|
107 |
logger.warning(message)
|
108 |
|
109 |
-
#
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
|
128 |
# Set environment variables
|
129 |
os.environ['HF_HOME'] = cache_dir
|
@@ -132,18 +86,12 @@ os.environ['GENSIM_DATA_DIR'] = gensim_data_dir
|
|
132 |
# Add the custom directory to NLTK's search path
|
133 |
nltk.data.path.insert(0, nltk_data_dir)
|
134 |
|
135 |
-
#
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
log_print(f"Downloading NLTK data: {data}")
|
140 |
-
nltk.download(data, download_dir=nltk_data_dir)
|
141 |
-
except Exception as e:
|
142 |
-
log_print(f"Error downloading NLTK data {data}: {e}", "ERROR")
|
143 |
-
raise
|
144 |
|
145 |
from flask import Flask, request, jsonify, render_template
|
146 |
-
import json
|
147 |
import torch
|
148 |
from werkzeug.utils import secure_filename
|
149 |
|
@@ -614,43 +562,52 @@ def allowed_file(filename, allowed_extensions):
|
|
614 |
return '.' in filename and \
|
615 |
filename.rsplit('.', 1)[1].lower() in allowed_extensions
|
616 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
617 |
def cleanup_temp_files():
|
618 |
"""Clean up temporary files with proper error handling"""
|
619 |
try:
|
620 |
if os.path.exists(images_dir):
|
621 |
-
# First ensure we have write permissions
|
622 |
-
try:
|
623 |
-
os.chmod(images_dir, 0o777)
|
624 |
-
except Exception as e:
|
625 |
-
log_print(f"Warning: Could not set directory permissions: {e}", "WARNING")
|
626 |
-
|
627 |
-
# Try to remove files
|
628 |
for file in os.listdir(images_dir):
|
629 |
-
file_path = os.path.join(images_dir, file)
|
630 |
try:
|
|
|
631 |
if os.path.isfile(file_path):
|
632 |
-
try:
|
633 |
-
os.chmod(file_path, 0o666) # Ensure we can delete the file
|
634 |
-
except:
|
635 |
-
pass
|
636 |
os.unlink(file_path)
|
637 |
except Exception as e:
|
638 |
log_print(f"Warning: Could not delete file {file_path}: {e}", "WARNING")
|
639 |
-
continue
|
640 |
-
|
641 |
-
# Recreate the directory with full permissions
|
642 |
-
ensure_directory(images_dir)
|
643 |
-
|
644 |
-
log_print("Successfully cleaned up temporary files")
|
645 |
except Exception as e:
|
646 |
log_print(f"Error cleaning up temporary files: {e}", "ERROR")
|
647 |
|
648 |
if __name__ == '__main__':
|
649 |
try:
|
650 |
-
#
|
651 |
-
for directory in
|
652 |
ensure_directory(directory)
|
653 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
654 |
port = int(os.environ.get('PORT', 7860))
|
655 |
app.run(host='0.0.0.0', port=port, debug=False)
|
656 |
finally:
|
|
|
19 |
BASE_DIR = '/tmp' # Use direct /tmp path for Hugging Face
|
20 |
log_dir = os.path.join(BASE_DIR, 'app_logs')
|
21 |
cache_dir = os.path.join(BASE_DIR, 'app_cache')
|
22 |
+
nltk_data_dir = os.path.join(BASE_DIR, 'nltk_data')
|
23 |
+
gensim_data_dir = os.path.join(BASE_DIR, 'gensim-data')
|
24 |
+
upload_dir = os.path.join(BASE_DIR, 'uploads')
|
25 |
+
ans_image_dir = os.path.join(BASE_DIR, 'ans_image')
|
26 |
+
images_dir = os.path.join(BASE_DIR, 'images')
|
27 |
+
|
28 |
+
# Global variables for model caching
|
29 |
+
global_models = {}
|
30 |
|
31 |
def ensure_directory(path):
|
32 |
"""Create directory and ensure full permissions with better error handling"""
|
33 |
+
if os.path.exists(path):
|
34 |
+
return path
|
35 |
+
|
36 |
try:
|
|
|
37 |
os.makedirs(path, mode=0o777, exist_ok=True)
|
38 |
+
return path
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
39 |
except Exception as e:
|
|
|
40 |
try:
|
41 |
os.makedirs(path, mode=0o755, exist_ok=True)
|
42 |
+
return path
|
|
|
|
|
|
|
|
|
|
|
43 |
except Exception as nested_e:
|
44 |
+
print(f"Warning: Could not create directory {path}: {nested_e}")
|
45 |
+
return path
|
46 |
+
|
47 |
+
# Simplified logging setup
|
48 |
+
logging.basicConfig(
|
49 |
+
level=logging.INFO,
|
50 |
+
format='%(asctime)s - %(levelname)s - %(message)s',
|
51 |
+
handlers=[logging.StreamHandler(sys.stdout)]
|
52 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
53 |
logger = logging.getLogger(__name__)
|
54 |
|
|
|
55 |
def log_print(message, level="INFO"):
|
|
|
|
|
56 |
if level == "INFO":
|
57 |
logger.info(message)
|
58 |
elif level == "ERROR":
|
|
|
60 |
elif level == "WARNING":
|
61 |
logger.warning(message)
|
62 |
|
63 |
+
# Initialize NLTK only if not already downloaded
|
64 |
+
def initialize_nltk():
|
65 |
+
required_nltk_data = ['stopwords', 'punkt', 'wordnet']
|
66 |
+
for data in required_nltk_data:
|
67 |
+
try:
|
68 |
+
# Check if the data exists in the custom directory
|
69 |
+
nltk.data.find(os.path.join('tokenizers', data))
|
70 |
+
except LookupError:
|
71 |
+
try:
|
72 |
+
log_print(f"Downloading NLTK data: {data}")
|
73 |
+
nltk.download(data, download_dir=nltk_data_dir, quiet=True)
|
74 |
+
except Exception as e:
|
75 |
+
log_print(f"Error downloading NLTK data {data}: {e}", "ERROR")
|
76 |
+
|
77 |
+
# Create essential directories only
|
78 |
+
essential_dirs = [cache_dir, upload_dir, images_dir]
|
79 |
+
for directory in essential_dirs:
|
80 |
+
ensure_directory(directory)
|
81 |
|
82 |
# Set environment variables
|
83 |
os.environ['HF_HOME'] = cache_dir
|
|
|
86 |
# Add the custom directory to NLTK's search path
|
87 |
nltk.data.path.insert(0, nltk_data_dir)
|
88 |
|
89 |
+
# Initialize NLTK in background
|
90 |
+
from threading import Thread
|
91 |
+
nltk_thread = Thread(target=initialize_nltk)
|
92 |
+
nltk_thread.start()
|
|
|
|
|
|
|
|
|
|
|
93 |
|
94 |
from flask import Flask, request, jsonify, render_template
|
|
|
95 |
import torch
|
96 |
from werkzeug.utils import secure_filename
|
97 |
|
|
|
562 |
return '.' in filename and \
|
563 |
filename.rsplit('.', 1)[1].lower() in allowed_extensions
|
564 |
|
565 |
+
def get_or_load_model(model_name):
|
566 |
+
"""Get a model from cache or load it if not present"""
|
567 |
+
if model_name not in global_models:
|
568 |
+
if model_name == 'fasttext':
|
569 |
+
from gensim.models.fasttext import FastText
|
570 |
+
global_models[model_name] = FastText.load(os.path.join(cache_dir, 'fasttext.model'))
|
571 |
+
elif model_name == 'llm':
|
572 |
+
# Add your LLM model loading here
|
573 |
+
pass
|
574 |
+
return global_models.get(model_name)
|
575 |
+
|
576 |
def cleanup_temp_files():
|
577 |
"""Clean up temporary files with proper error handling"""
|
578 |
try:
|
579 |
if os.path.exists(images_dir):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
580 |
for file in os.listdir(images_dir):
|
|
|
581 |
try:
|
582 |
+
file_path = os.path.join(images_dir, file)
|
583 |
if os.path.isfile(file_path):
|
|
|
|
|
|
|
|
|
584 |
os.unlink(file_path)
|
585 |
except Exception as e:
|
586 |
log_print(f"Warning: Could not delete file {file_path}: {e}", "WARNING")
|
|
|
|
|
|
|
|
|
|
|
|
|
587 |
except Exception as e:
|
588 |
log_print(f"Error cleaning up temporary files: {e}", "ERROR")
|
589 |
|
590 |
if __name__ == '__main__':
|
591 |
try:
|
592 |
+
# Create essential directories
|
593 |
+
for directory in essential_dirs:
|
594 |
ensure_directory(directory)
|
595 |
|
596 |
+
# Start the NLTK initialization in background
|
597 |
+
nltk_thread.start()
|
598 |
+
|
599 |
+
# Pre-load models in background
|
600 |
+
def preload_models():
|
601 |
+
try:
|
602 |
+
get_or_load_model('fasttext')
|
603 |
+
# Add other model preloading here
|
604 |
+
except Exception as e:
|
605 |
+
log_print(f"Warning: Could not preload models: {e}", "WARNING")
|
606 |
+
|
607 |
+
model_thread = Thread(target=preload_models)
|
608 |
+
model_thread.start()
|
609 |
+
|
610 |
+
# Start the Flask app
|
611 |
port = int(os.environ.get('PORT', 7860))
|
612 |
app.run(host='0.0.0.0', port=port, debug=False)
|
613 |
finally:
|