|
|
|
|
|
""" |
|
|
Verification script to check if CogniChat is ready for HuggingFace Spaces deployment. |
|
|
Run this before deploying to catch any configuration issues. |
|
|
""" |
|
|
|
|
|
import os |
|
|
import sys |
|
|
from pathlib import Path |
|
|
|
|
|
def print_header(text): |
|
|
"""Print a formatted header.""" |
|
|
print(f"\n{'='*60}") |
|
|
print(f" {text}") |
|
|
print(f"{'='*60}") |
|
|
|
|
|
def print_check(condition, message): |
|
|
"""Print a check result.""" |
|
|
status = "PASS" if condition else "FAIL" |
|
|
print(f"{status}: {message}") |
|
|
return condition |
|
|
|
|
|
def verify_files_exist(): |
|
|
"""Verify all required files exist.""" |
|
|
print_header("1. Checking Required Files") |
|
|
|
|
|
required_files = [ |
|
|
'app.py', |
|
|
'rag_processor.py', |
|
|
'Dockerfile', |
|
|
'requirements.txt', |
|
|
'templates/index.html' |
|
|
] |
|
|
|
|
|
all_exist = True |
|
|
for file in required_files: |
|
|
exists = Path(file).exists() |
|
|
all_exist = all_exist and print_check(exists, f"File exists: {file}") |
|
|
|
|
|
return all_exist |
|
|
|
|
|
def verify_upload_folder_config(): |
|
|
"""Verify upload folder configuration in app.py.""" |
|
|
print_header("2. Checking Upload Folder Configuration") |
|
|
|
|
|
with open('app.py', 'r') as f: |
|
|
app_content = f.read() |
|
|
|
|
|
checks = [ |
|
|
('SPACE_ID' in app_content, "Detects SPACE_ID environment variable"), |
|
|
("'/tmp/uploads'" in app_content, "Uses /tmp/uploads for HF Spaces"), |
|
|
('is_hf_spaces' in app_content, "Has HF Spaces detection logic"), |
|
|
('os.makedirs(app.config' in app_content, "Creates upload directory"), |
|
|
] |
|
|
|
|
|
all_pass = True |
|
|
for condition, message in checks: |
|
|
all_pass = all_pass and print_check(condition, message) |
|
|
|
|
|
return all_pass |
|
|
|
|
|
def verify_session_management(): |
|
|
"""Verify session management implementation.""" |
|
|
print_header("3. Checking Session Management") |
|
|
|
|
|
|
|
|
with open('app.py', 'r') as f: |
|
|
app_content = f.read() |
|
|
|
|
|
backend_checks = [ |
|
|
("session['session_id']" in app_content, "Stores session_id in Flask session"), |
|
|
("'session_id': session_id" in app_content, "Returns session_id in upload response"), |
|
|
("data.get('session_id')" in app_content, "Accepts session_id from request body"), |
|
|
] |
|
|
|
|
|
|
|
|
with open('templates/index.html', 'r') as f: |
|
|
html_content = f.read() |
|
|
|
|
|
frontend_checks = [ |
|
|
('sessionStorage.setItem' in html_content, "Frontend stores session_id"), |
|
|
('sessionStorage.getItem' in html_content, "Frontend retrieves session_id"), |
|
|
('requestBody.session_id' in html_content, "Frontend sends session_id in chat"), |
|
|
] |
|
|
|
|
|
all_pass = True |
|
|
print(" Backend Implementation:") |
|
|
for condition, message in backend_checks: |
|
|
all_pass = all_pass and print_check(condition, f" {message}") |
|
|
|
|
|
print("\n Frontend Implementation:") |
|
|
for condition, message in frontend_checks: |
|
|
all_pass = all_pass and print_check(condition, f" {message}") |
|
|
|
|
|
return all_pass |
|
|
|
|
|
def verify_error_handling(): |
|
|
"""Verify robust error handling.""" |
|
|
print_header("4. Checking Error Handling") |
|
|
|
|
|
with open('app.py', 'r') as f: |
|
|
app_content = f.read() |
|
|
|
|
|
checks = [ |
|
|
('try:' in app_content and 'except' in app_content, "Has try/except blocks"), |
|
|
('load_pdf_with_fallback' in app_content, "Has PDF fallback loading"), |
|
|
('failed_files' in app_content, "Tracks failed file uploads"), |
|
|
('fallback_dir' in app_content, "Has cache directory fallbacks"), |
|
|
] |
|
|
|
|
|
all_pass = True |
|
|
for condition, message in checks: |
|
|
all_pass = all_pass and print_check(condition, message) |
|
|
|
|
|
return all_pass |
|
|
|
|
|
def verify_environment_variables(): |
|
|
"""Check for environment variable handling.""" |
|
|
print_header("5. Checking Environment Variables") |
|
|
|
|
|
with open('app.py', 'r') as f: |
|
|
app_content = f.read() |
|
|
|
|
|
with open('rag_processor.py', 'r') as f: |
|
|
rag_content = f.read() |
|
|
|
|
|
checks = [ |
|
|
('GROQ_API_KEY' in rag_content, "RAG processor checks GROQ_API_KEY"), |
|
|
('SPACE_ID' in app_content, "App detects HF Spaces environment"), |
|
|
('HF_HOME' in app_content, "Sets HuggingFace cache paths"), |
|
|
('load_dotenv()' in rag_content, "Loads .env file for local dev"), |
|
|
] |
|
|
|
|
|
all_pass = True |
|
|
for condition, message in checks: |
|
|
all_pass = all_pass and print_check(condition, message) |
|
|
|
|
|
|
|
|
all_pass = all_pass and print_check( |
|
|
Path('.env.example').exists() or Path('README.md').exists(), |
|
|
"Has documentation for environment variables" |
|
|
) |
|
|
|
|
|
return all_pass |
|
|
|
|
|
def verify_dockerfile(): |
|
|
"""Verify Dockerfile configuration.""" |
|
|
print_header("6. Checking Dockerfile") |
|
|
|
|
|
if not Path('Dockerfile').exists(): |
|
|
print_check(False, "Dockerfile exists") |
|
|
return False |
|
|
|
|
|
with open('Dockerfile', 'r') as f: |
|
|
dockerfile_content = f.read() |
|
|
|
|
|
checks = [ |
|
|
('FROM python' in dockerfile_content, "Uses Python base image"), |
|
|
('WORKDIR /app' in dockerfile_content, "Sets working directory"), |
|
|
('EXPOSE 7860' in dockerfile_content, "Exposes port 7860 (HF requirement)"), |
|
|
('appuser' in dockerfile_content, "Runs as non-root user"), |
|
|
('CMD' in dockerfile_content or 'ENTRYPOINT' in dockerfile_content, "Has startup command"), |
|
|
] |
|
|
|
|
|
all_pass = True |
|
|
for condition, message in checks: |
|
|
all_pass = all_pass and print_check(condition, message) |
|
|
|
|
|
return all_pass |
|
|
|
|
|
def verify_requirements(): |
|
|
"""Verify requirements.txt has all dependencies.""" |
|
|
print_header("7. Checking Dependencies") |
|
|
|
|
|
with open('requirements.txt', 'r') as f: |
|
|
requirements = f.read().lower() |
|
|
|
|
|
critical_deps = [ |
|
|
'flask', |
|
|
'langchain', |
|
|
'groq', |
|
|
'faiss', |
|
|
'sentence-transformers', |
|
|
'pypdf', |
|
|
'gtts', |
|
|
'rank-bm25' |
|
|
] |
|
|
|
|
|
all_pass = True |
|
|
for dep in critical_deps: |
|
|
found = dep in requirements |
|
|
all_pass = all_pass and print_check(found, f"Has dependency: {dep}") |
|
|
|
|
|
return all_pass |
|
|
|
|
|
def verify_no_duplicates(): |
|
|
"""Check for duplicate content in index.html.""" |
|
|
print_header("8. Checking for Duplicates") |
|
|
|
|
|
with open('templates/index.html', 'r') as f: |
|
|
html_content = f.read() |
|
|
|
|
|
|
|
|
doctype_count = html_content.count('<!DOCTYPE html>') |
|
|
checks = [ |
|
|
(doctype_count == 1, f"Single HTML document (found {doctype_count} DOCTYPE declarations)"), |
|
|
(html_content.count('</html>') == 1, "Single closing </html> tag"), |
|
|
(html_content.count('uploadAndProcessFiles') <= 2, "No duplicate JavaScript functions"), |
|
|
] |
|
|
|
|
|
all_pass = True |
|
|
for condition, message in checks: |
|
|
all_pass = all_pass and print_check(condition, message) |
|
|
|
|
|
return all_pass |
|
|
|
|
|
def main(): |
|
|
"""Run all verification checks.""" |
|
|
print("\n" + "="*60) |
|
|
print(" HuggingFace Spaces Readiness Check for CogniChat") |
|
|
print("="*60) |
|
|
|
|
|
checks = [ |
|
|
verify_files_exist(), |
|
|
verify_upload_folder_config(), |
|
|
verify_session_management(), |
|
|
verify_error_handling(), |
|
|
verify_environment_variables(), |
|
|
verify_dockerfile(), |
|
|
verify_requirements(), |
|
|
verify_no_duplicates(), |
|
|
] |
|
|
|
|
|
print_header("Summary") |
|
|
|
|
|
passed = sum(checks) |
|
|
total = len(checks) |
|
|
|
|
|
if all(checks): |
|
|
print(f"\n✅ ALL CHECKS PASSED ({passed}/{total})") |
|
|
print("\n🚀 Your application is ready for HuggingFace Spaces deployment!") |
|
|
print("\nNext steps:") |
|
|
print("1. Go to https://huggingface.co/new-space") |
|
|
print("2. Select 'Docker' as SDK") |
|
|
print("3. Upload all project files") |
|
|
print("4. Set GROQ_API_KEY in Space secrets") |
|
|
print("5. Wait for build to complete") |
|
|
return 0 |
|
|
else: |
|
|
print(f"\n SOME CHECKS FAILED ({total - passed}/{total} issues)") |
|
|
print("\n Please fix the issues above before deploying.") |
|
|
print("\nFor detailed guidance, see:") |
|
|
print("- HF_SPACES_FILE_STORAGE_GUIDE.md") |
|
|
print("- DEPLOYMENT.md") |
|
|
print("- HF_SPACES_CHECKLIST.md") |
|
|
return 1 |
|
|
|
|
|
if __name__ == '__main__': |
|
|
exit_code = main() |
|
|
sys.exit(exit_code) |
|
|
|