Environment methods
This commit is contained in:
parent
cba9d1e341
commit
2a85845835
18
.gitignore
vendored
18
.gitignore
vendored
@ -1,10 +1,10 @@
|
||||
.env
|
||||
.DS_Store
|
||||
.vscode
|
||||
.idea
|
||||
__pycache__
|
||||
.pytest_cache
|
||||
.coverage
|
||||
.coverage.*
|
||||
.coverage.*.*
|
||||
.coverage.*.*.*
|
||||
.coverage.*.*.*.*
|
||||
|
||||
.DS_Store
|
||||
|
||||
.env
|
||||
|
||||
|
||||
data/init_data/
|
||||
logs/
|
||||
50
Dockerfile
50
Dockerfile
@ -1,38 +1,34 @@
|
||||
# Example Dockerfile showing how to use the new startup system
|
||||
# This is a reference - not meant to replace your existing Dockerfile
|
||||
|
||||
FROM python:3.11-slim
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /app
|
||||
|
||||
# Install system dependencies
|
||||
RUN apt-get update && apt-get install -y \
|
||||
libreoffice \
|
||||
poppler-utils \
|
||||
libpq-dev \
|
||||
gcc \
|
||||
python3-dev \
|
||||
postgresql-client \
|
||||
curl \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Set up virtual environment
|
||||
RUN python -m venv /opt/venv
|
||||
ENV PATH="/opt/venv/bin:$PATH"
|
||||
|
||||
# Install Python packages
|
||||
# Copy requirements and install dependencies
|
||||
COPY requirements.txt .
|
||||
RUN pip install --no-cache-dir --upgrade pip && \
|
||||
pip install --no-cache-dir -r requirements.txt
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
# Copy the application
|
||||
# Copy application code
|
||||
COPY . .
|
||||
|
||||
# Create necessary directories
|
||||
RUN mkdir -p static templates/admin logs
|
||||
# Make startup script executable
|
||||
RUN chmod +x start.sh
|
||||
|
||||
# Create entrypoint script
|
||||
COPY docker-entrypoint.sh /usr/local/bin/
|
||||
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
|
||||
# Set environment variables
|
||||
ENV PYTHONPATH=/app
|
||||
ENV UVICORN_PORT=8000
|
||||
ENV UVICORN_WORKERS=4
|
||||
|
||||
EXPOSE ${PORT_BACKEND}
|
||||
# Expose port
|
||||
EXPOSE 8000
|
||||
|
||||
ENTRYPOINT ["docker-entrypoint.sh"]
|
||||
CMD ["python", "main.py"]
|
||||
# Use the new startup script in production mode
|
||||
CMD ["./start.sh", "prod"]
|
||||
|
||||
# Alternative: Run initialization first, then production server
|
||||
# CMD ["sh", "-c", "./start.sh init && ./start.sh prod"]
|
||||
|
||||
# Alternative: Use Python directly
|
||||
# CMD ["python3", "main.py", "--mode", "prod"]
|
||||
|
||||
@ -1,38 +0,0 @@
|
||||
FROM python:3.11-slim
|
||||
|
||||
WORKDIR /app/backend
|
||||
|
||||
# Install system dependencies
|
||||
RUN apt-get update && apt-get install -y \
|
||||
libreoffice \
|
||||
poppler-utils \
|
||||
libpq-dev \
|
||||
gcc \
|
||||
python3-dev \
|
||||
postgresql-client \
|
||||
curl \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Set up virtual environment
|
||||
RUN python -m venv /opt/venv
|
||||
ENV PATH="/opt/venv/bin:$PATH"
|
||||
|
||||
# Install Python packages
|
||||
COPY requirements.txt .
|
||||
RUN pip install --no-cache-dir --upgrade pip && \
|
||||
pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
# Copy the application
|
||||
COPY . .
|
||||
|
||||
# Create necessary directories
|
||||
RUN mkdir -p static templates/admin logs
|
||||
|
||||
# Create entrypoint script
|
||||
COPY docker-entrypoint.sh /usr/local/bin/
|
||||
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
|
||||
|
||||
EXPOSE ${PORT_BACKEND}
|
||||
|
||||
ENTRYPOINT ["docker-entrypoint.sh"]
|
||||
CMD ["python", "main.py"]
|
||||
@ -1,38 +0,0 @@
|
||||
FROM python:3.11-slim
|
||||
|
||||
WORKDIR /app/backend
|
||||
|
||||
# Install system dependencies
|
||||
RUN apt-get update && apt-get install -y \
|
||||
libreoffice \
|
||||
poppler-utils \
|
||||
libpq-dev \
|
||||
gcc \
|
||||
python3-dev \
|
||||
postgresql-client \
|
||||
curl \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Set up virtual environment
|
||||
RUN python -m venv /opt/venv
|
||||
ENV PATH="/opt/venv/bin:$PATH"
|
||||
|
||||
# Install Python packages
|
||||
COPY requirements.txt .
|
||||
RUN pip install --no-cache-dir --upgrade pip && \
|
||||
pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
# Copy the application
|
||||
COPY . .
|
||||
|
||||
# Create necessary directories
|
||||
RUN mkdir -p static templates/admin logs
|
||||
|
||||
# Create entrypoint script
|
||||
COPY docker-entrypoint.sh /usr/local/bin/
|
||||
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
|
||||
|
||||
EXPOSE ${PORT_BACKEND}
|
||||
|
||||
ENTRYPOINT ["docker-entrypoint.sh"]
|
||||
CMD ["python", "main.py"]
|
||||
108
README.md
108
README.md
@ -1,108 +0,0 @@
|
||||
The main issues are with system-level dependencies like `libreoffice` and `gcc` which aren't typically managed through conda on macOS.
|
||||
|
||||
```yaml:backend/requirements.conda.yml
|
||||
name: classroomcopilot-backend
|
||||
channels:
|
||||
- conda-forge
|
||||
- nodefaults
|
||||
dependencies:
|
||||
- python=3.11
|
||||
# Core dependencies
|
||||
- pip
|
||||
- setuptools
|
||||
- wheel
|
||||
# Server dependencies
|
||||
- fastapi
|
||||
- uvicorn
|
||||
- python-dotenv
|
||||
- python-multipart
|
||||
- python-jose
|
||||
- pyjwt
|
||||
- jinja2
|
||||
# Database and Auth
|
||||
- sqlalchemy
|
||||
- sqlalchemy-utils
|
||||
- asyncpg
|
||||
- redis-py
|
||||
# Neo4j
|
||||
- neo4j-python-driver
|
||||
# Data Processing
|
||||
- pandas
|
||||
- scipy
|
||||
- requests
|
||||
- openpyxl
|
||||
- scikit-learn
|
||||
# Testing
|
||||
- pytest
|
||||
- pytest-html
|
||||
# Database clients
|
||||
- postgresql
|
||||
- libpq
|
||||
# Additional dependencies via pip
|
||||
- pip:
|
||||
# Supabase
|
||||
- supabase
|
||||
# Neo4j specific
|
||||
- neontology
|
||||
# Document Processing
|
||||
- python-pptx
|
||||
- python-docx
|
||||
- pdfminer.six
|
||||
- Pillow
|
||||
- psutil
|
||||
# Web Scraping and Processing
|
||||
- emoji
|
||||
- extruct
|
||||
- w3lib
|
||||
# Google APIs
|
||||
- youtube-transcript-api
|
||||
- google-api-python-client
|
||||
- google-auth-oauthlib
|
||||
# LangChain Ecosystem
|
||||
- "langchain[llms]"
|
||||
- langchain-community
|
||||
- langchain-openai
|
||||
- langgraph
|
||||
# OpenAI
|
||||
- openai
|
||||
- ollama
|
||||
# Microsoft Authentication
|
||||
- msal
|
||||
```
|
||||
I've made several important changes to make the conda environment more compatible:
|
||||
|
||||
1. Removed system-level dependencies that should be installed via the system package manager:
|
||||
- `libreoffice` - Install via Homebrew on macOS (`brew install libreoffice`)
|
||||
- `gcc` - Install via Xcode Command Line Tools on macOS
|
||||
- `poppler` - Install via Homebrew on macOS (`brew install poppler`)
|
||||
|
||||
2. Changed channel configuration:
|
||||
- Using only `conda-forge` with `nodefaults` to avoid package conflicts
|
||||
- This provides better consistency across platforms
|
||||
|
||||
3. Fixed the `langchain[llms]` specification by adding quotes to handle the square brackets properly
|
||||
|
||||
For macOS users, here are the steps to set up the environment:
|
||||
|
||||
1. First, install system dependencies:
|
||||
```bash
|
||||
# Install Xcode Command Line Tools (if not already installed)
|
||||
xcode-select --install
|
||||
|
||||
# Install other system dependencies via Homebrew
|
||||
brew install libreoffice poppler postgresql
|
||||
```
|
||||
|
||||
2. Then create the conda environment:
|
||||
```bash
|
||||
conda env create -f backend/requirements.conda.yml
|
||||
```
|
||||
|
||||
3. Activate the environment:
|
||||
```bash
|
||||
conda activate classroomcopilot-backend
|
||||
```
|
||||
|
||||
This setup should now work properly on macOS while still maintaining compatibility with the Docker environment for production. The system-level dependencies are handled by the appropriate system package manager (Homebrew for macOS) rather than conda, which is the recommended approach for these types of dependencies.
|
||||
|
||||
Would you like me to make any additional adjustments to the environment configuration?
|
||||
Binary file not shown.
@ -1,12 +1,14 @@
|
||||
services:
|
||||
backend:
|
||||
container_name: ccapi
|
||||
container_name: cc-api
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
env_file: .env
|
||||
env_file:
|
||||
- .env
|
||||
- .env.app.prod
|
||||
ports:
|
||||
- "${PORT_BACKEND}:${PORT_BACKEND}"
|
||||
- 8000:8000
|
||||
networks:
|
||||
- kevlarai-network
|
||||
|
||||
|
||||
@ -1,43 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Add backend to Python path
|
||||
export PYTHONPATH="/app:${PYTHONPATH}"
|
||||
|
||||
# Create init directories
|
||||
mkdir -p /init
|
||||
|
||||
# Function to check if initialization is needed
|
||||
check_init_needed() {
|
||||
if [ ! -f "/init/status.json" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Check if any status is incomplete
|
||||
incomplete=$(python -c "
|
||||
import json
|
||||
try:
|
||||
with open('/init/status.json', 'r') as f:
|
||||
status = json.load(f)
|
||||
print(not all(v for k, v in status.items() if k != 'timestamp'))
|
||||
except (FileNotFoundError, json.JSONDecodeError):
|
||||
print('True')
|
||||
")
|
||||
|
||||
if [ "$incomplete" = "True" ]; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Run initialization if needed
|
||||
if check_init_needed; then
|
||||
echo "Running initialization..."
|
||||
python -c "from run.initialization import initialize_system; initialize_system()"
|
||||
else
|
||||
echo "System already initialized, skipping..."
|
||||
fi
|
||||
|
||||
# Execute the main command
|
||||
exec "$@"
|
||||
92
main.py
92
main.py
@ -1,4 +1,6 @@
|
||||
import os
|
||||
import argparse
|
||||
import sys
|
||||
from modules.logger_tool import initialise_logger
|
||||
logger = initialise_logger(__name__, os.getenv("LOG_LEVEL"), os.getenv("LOG_PATH"), 'default', True)
|
||||
from fastapi import FastAPI, HTTPException
|
||||
@ -100,34 +102,94 @@ def initialize_with_retry(max_attempts: int = 3, initial_delay: int = 5) -> bool
|
||||
|
||||
return False
|
||||
|
||||
if __name__ == "__main__":
|
||||
import uvicorn
|
||||
import os
|
||||
def run_initialization_mode():
|
||||
"""Run only the initialization process"""
|
||||
logger.info("Running in initialization mode")
|
||||
logger.info("Starting system initialization...")
|
||||
|
||||
# Run initialization with retry logic
|
||||
if not initialize_with_retry():
|
||||
logger.error("Failed to initialize system after multiple attempts")
|
||||
# Continue anyway to allow the API to start and handle health checks
|
||||
if initialize_with_retry():
|
||||
logger.info("Initialization completed successfully")
|
||||
return True
|
||||
else:
|
||||
logger.error("Initialization failed after multiple attempts")
|
||||
return False
|
||||
|
||||
def run_development_mode():
|
||||
"""Run the server in development mode with auto-reload"""
|
||||
logger.info("Running in development mode")
|
||||
logger.info("Starting uvicorn server with auto-reload...")
|
||||
|
||||
if os.getenv('BACKEND_DEV_MODE') == 'true':
|
||||
logger.info("Running with Reload")
|
||||
uvicorn.run(
|
||||
"main:app",
|
||||
host="0.0.0.0",
|
||||
port=int(os.getenv('PORT_BACKEND', 8000)),
|
||||
log_level="info",
|
||||
port=int(os.getenv('UVICORN_PORT', 8000)),
|
||||
log_level=os.getenv('LOG_LEVEL', 'info'),
|
||||
proxy_headers=True,
|
||||
timeout_keep_alive=10,
|
||||
reload=True
|
||||
)
|
||||
else:
|
||||
logger.info("Running without Reload and without SSL (behind reverse proxy)")
|
||||
|
||||
def run_production_mode():
|
||||
"""Run the server in production mode"""
|
||||
logger.info("Running in production mode")
|
||||
logger.info("Starting uvicorn server in production mode...")
|
||||
|
||||
uvicorn.run(
|
||||
"main:app",
|
||||
host="0.0.0.0",
|
||||
port=int(os.getenv('PORT_BACKEND', 8000)), # <-- not 443
|
||||
log_level="info",
|
||||
port=int(os.getenv('UVICORN_PORT', 8000)),
|
||||
log_level=os.getenv('LOG_LEVEL', 'info'),
|
||||
proxy_headers=True,
|
||||
timeout_keep_alive=10,
|
||||
workers=int(os.getenv('UVICORN_WORKERS', '1'))
|
||||
)
|
||||
|
||||
def parse_arguments():
|
||||
"""Parse command line arguments"""
|
||||
parser = argparse.ArgumentParser(
|
||||
description="ClassroomCopilot API Server",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
epilog="""
|
||||
Startup modes:
|
||||
init - Run initialization scripts (database setup, etc.)
|
||||
dev - Run development server with auto-reload
|
||||
prod - Run production server (for Docker/containerized deployment)
|
||||
"""
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--mode', '-m',
|
||||
choices=['init', 'dev', 'prod'],
|
||||
default='dev',
|
||||
help='Startup mode (default: dev)'
|
||||
)
|
||||
|
||||
return parser.parse_args()
|
||||
|
||||
if __name__ == "__main__":
|
||||
args = parse_arguments()
|
||||
|
||||
# Set environment variable for backward compatibility
|
||||
if args.mode == 'dev':
|
||||
os.environ['BACKEND_DEV_MODE'] = 'true'
|
||||
else:
|
||||
os.environ['BACKEND_DEV_MODE'] = 'false'
|
||||
|
||||
logger.info(f"Starting ClassroomCopilot API in {args.mode} mode")
|
||||
|
||||
if args.mode == 'init':
|
||||
# Run initialization only
|
||||
success = run_initialization_mode()
|
||||
sys.exit(0 if success else 1)
|
||||
|
||||
elif args.mode == 'dev':
|
||||
# Run development server
|
||||
run_development_mode()
|
||||
|
||||
elif args.mode == 'prod':
|
||||
# Run production server
|
||||
run_production_mode()
|
||||
|
||||
else:
|
||||
logger.error(f"Invalid mode: {args.mode}")
|
||||
sys.exit(1)
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -2,7 +2,7 @@ import os
|
||||
from typing import Dict, Optional, Any, TypedDict, List
|
||||
from supabase import create_client, Client
|
||||
from supabase.lib.client_options import SyncClientOptions
|
||||
from gotrue import SyncMemoryStorage
|
||||
from supabase_auth import SyncMemoryStorage
|
||||
from modules.logger_tool import initialise_logger
|
||||
|
||||
logger = initialise_logger(__name__, os.getenv("LOG_LEVEL"), os.getenv("LOG_PATH"), 'default', True)
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -2,7 +2,11 @@ import os
|
||||
import sys
|
||||
import logging
|
||||
import datetime
|
||||
try:
|
||||
import pytest
|
||||
PYTEST_AVAILABLE = True
|
||||
except ImportError:
|
||||
PYTEST_AVAILABLE = False
|
||||
from dotenv import load_dotenv, find_dotenv
|
||||
|
||||
# Load environment variables
|
||||
@ -86,6 +90,7 @@ class FileFormatter(logging.Formatter):
|
||||
return logging.Formatter(LOG_FORMAT).format(record)
|
||||
|
||||
class PytestFormatter:
|
||||
if PYTEST_AVAILABLE:
|
||||
@pytest.hookimpl(hookwrapper=True)
|
||||
def pytest_runtest_makereport(self, item, call):
|
||||
outcome = yield
|
||||
@ -97,6 +102,10 @@ class PytestFormatter:
|
||||
logging.error(f"❌ Test failed: {item.name}")
|
||||
elif report.skipped:
|
||||
logging.warning(f"⏭️ Test skipped: {item.name}")
|
||||
else:
|
||||
# Dummy implementation when pytest is not available
|
||||
def pytest_runtest_makereport(self, item, call):
|
||||
pass
|
||||
|
||||
# Custom logger methods
|
||||
def _add_custom_log_methods():
|
||||
|
||||
@ -1,74 +0,0 @@
|
||||
name: classroomcopilot-backend
|
||||
channels:
|
||||
- conda-forge
|
||||
- nodefaults
|
||||
dependencies:
|
||||
- python=3.11
|
||||
# Core dependencies
|
||||
- pip
|
||||
- setuptools
|
||||
- wheel
|
||||
# Server dependencies
|
||||
- fastapi
|
||||
- uvicorn
|
||||
- python-dotenv
|
||||
- python-multipart
|
||||
- python-jose
|
||||
- pyjwt
|
||||
- jinja2
|
||||
# Database and Auth
|
||||
- sqlalchemy
|
||||
- sqlalchemy-utils
|
||||
- asyncpg
|
||||
- redis-py
|
||||
# Neo4j
|
||||
- neo4j-python-driver
|
||||
# HTTP and Async
|
||||
- aiohttp
|
||||
# Data Processing
|
||||
- pandas
|
||||
- scipy
|
||||
- requests
|
||||
- openpyxl
|
||||
- scikit-learn
|
||||
# Testing
|
||||
- pytest
|
||||
- pytest-html
|
||||
# Database clients
|
||||
- postgresql
|
||||
- libpq
|
||||
# LibreOffice for document conversion
|
||||
- libreoffice
|
||||
# Additional dependencies via pip
|
||||
- pip:
|
||||
# Supabase
|
||||
- supabase
|
||||
# Neo4j specific
|
||||
- neontology
|
||||
# HTTP and Async
|
||||
- sseclient-py
|
||||
# Document Processing
|
||||
- python-pptx
|
||||
- python-docx
|
||||
- pdfminer.six
|
||||
- Pillow
|
||||
- psutil
|
||||
- PyPDF2>=3.0.0
|
||||
# Web Scraping and Processing
|
||||
- emoji
|
||||
- extruct
|
||||
- w3lib
|
||||
# Google APIs
|
||||
- youtube-transcript-api
|
||||
- google-api-python-client
|
||||
- google-auth-oauthlib
|
||||
# LangChain Ecosystem
|
||||
- "langchain[llms]"
|
||||
- langchain-community
|
||||
- langchain-openai
|
||||
- langgraph
|
||||
# OpenAI
|
||||
- openai
|
||||
- ollama
|
||||
# Microsoft Authentication
|
||||
- msal
|
||||
@ -13,6 +13,7 @@ jinja2
|
||||
|
||||
# Database and Auth
|
||||
supabase
|
||||
supabase_auth
|
||||
sqlalchemy
|
||||
sqlalchemy-utils
|
||||
asyncpg
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user