Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds development server #7

Merged
merged 30 commits into from
Feb 18, 2025
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
9b59aeb
config file for environment specific variable
andrewheusser Jan 30, 2025
cfe1f3d
update deploy script to require environment parameter
andrewheusser Jan 30, 2025
1ac4ee7
new script to build a docker container and f
andrewheusser Jan 30, 2025
45887fb
update config with external IP for development server
andrewheusser Jan 30, 2025
882811c
update build script to use env specific params
andrewheusser Jan 30, 2025
9bd8da5
updated development IP and deployment script
andrewheusser Jan 30, 2025
7a728e2
attempt at setting up nginx, deployment failed
andrewheusser Jan 30, 2025
f52d19e
update readme for development env
andrewheusser Jan 30, 2025
bb90dcb
more readme updates
andrewheusser Jan 30, 2025
1815ac6
update dev VM IP address
andrewheusser Jan 31, 2025
206c8c9
attempts to fix redis misconfiguration
andrewheusser Feb 4, 2025
4ba6ecc
update tests to include development server
andrewheusser Feb 4, 2025
79742e4
fixes permissions, no R needed
andrewheusser Feb 4, 2025
911da84
add allow-tcp-5000 to networking tags
andrewheusser Feb 4, 2025
fcd491d
checking in progress
andrewheusser Feb 6, 2025
99754c3
updated code to handle new payload, cant yet test locally
andrewheusser Feb 7, 2025
a946866
model persistence working, able to run extract_summary_statistics
andrewheusser Feb 10, 2025
2fcc068
saving latest progress
andrewheusser Feb 11, 2025
db4a7df
saving updated api spec and prompt
andrewheusser Feb 11, 2025
a2b8533
changing how we instantiate the celery app, hoping that fixes the red…
andrewheusser Feb 11, 2025
70d83a6
explicitly setting logfile and data dirs to see if it fixes redis wri…
andrewheusser Feb 13, 2025
329bb2e
minor tweaks to the prompt
andrewheusser Feb 13, 2025
154f57a
register serializer with kombu instead of manually serializing
andrewheusser Feb 15, 2025
870ffe4
removing some WIP work I accidentally commited
andrewheusser Feb 15, 2025
203ff30
updates to api spec and prompt
andrewheusser Feb 16, 2025
9b782db
reminder to be concise in responses
andrewheusser Feb 17, 2025
1e03f56
adds auth
andrewheusser Feb 17, 2025
b61986e
add api key to test request
andrewheusser Feb 17, 2025
4efb379
Merge pull request #8 from pymc-labs/refactor-server-endpoints
andrewheusser Feb 18, 2025
7b19c6b
update version, remove commented route
andrewheusser Feb 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ RUN micromamba install -y -n base -f /tmp/env.yaml && \
mkdir -p /opt/conda/var/db && \
chown $MAMBA_USER:$MAMBA_USER /opt/conda/var/db && \
mkdir -p /opt/conda/var/db/redis && \
chown $MAMBA_USER:$MAMBA_USER /opt/conda/var/db/redis
chown $MAMBA_USER:$MAMBA_USER /opt/conda/var/db/redis && \
chmod 750 /opt/conda/var/db/redis

# Copy the start script
COPY --chown=$MAMBA_USER:$MAMBA_USER start.sh $APP_HOME/start.sh
Expand Down
74 changes: 52 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ A cloud-based Marketing Mix Modeling (MMM) solution deployed on Google Cloud Pla

## Quick Deployment
```bash
./deploy.sh # Deploy the latest version to production
./deploy.sh production # Deploy the latest version to production
./deploy.sh development # Deploy the latest version to development
```

## System Architecture
Expand All @@ -18,6 +19,7 @@ GPT-Bayes consists of two main components:

2. **Backend Service**
- Production URL: https://nextgen-mmm.pymc-labs.com
- Development URL: https://dev-nextgen-mmm.pymc-labs.com
- Function: Handles model fitting and parameter management via API endpoints
- Infrastructure: Hosted on Google Cloud Engine (GCE) under the `gpt-bayes` project

Expand All @@ -31,8 +33,10 @@ GPT-Bayes consists of two main components:
- `nginx/` - NGINX reverse proxy settings
- `dockerfile` - Container specifications
- `start.sh` - Container initialization
- `build.sh` - Build the container image
- `deploy.sh` - Deployment automation
- `environment.yml` - Development environment specifications
- `config.yaml` - Environment configuration settings

### AI Agent Settings
- `gpt-agent/gpt_prompt.md` - System instructions
Expand All @@ -45,23 +49,33 @@ GPT-Bayes consists of two main components:

## Deployment Guide

The application runs on Google Compute Engine (GCE) under the `gpt-bayes` project, accessible at `https://nextgen-mmm.pymc-labs.com`.
The application runs on Google Compute Engine (GCE) under the `gpt-bayes` project, accessible at `https://nextgen-mmm.pymc-labs.com` (production) and `https://dev-nextgen-mmm.pymc-labs.com` (development).

### Build and Push Docker Image

Build and push the Docker image to Google Artifact Registry (GAR).
```bash
./build.sh production # Build and publish to production
./build.sh development # Build and publish to development
```

### Standard Deployment

Use `deploy.sh` to update the application. This script handles:
Once the Docker image is built and pushed to GAR, use `deploy.sh` to update the application. This script handles:
- Updating the container in Google Artifact Registry (GAR)
- Deploying to the production environment
- Deploying to the specified environment

```bash
./deploy.sh
./deploy.sh production # Deploy the latest version to production
./deploy.sh development # Deploy the latest version to development
```

### Server Management

Access the production server:
Access the specified server:
```bash
gcloud compute ssh gpt-bayes --zone us-central1-a
gcloud compute ssh dev-gpt-bayes --zone us-central1-a
```

Container management commands:
Expand All @@ -81,10 +95,11 @@ docker exec -it CONTAINER_ID /bin/bash

Build and publish to Google Artifact Registry:
```bash
gcloud builds submit
./build.sh production # Build and publish to production
./build.sh development # Build and publish to development
```

Note: This updates the container image but doesn't affect the production deployment.
Note: This updates the container image but doesn't affect the specified deployment.

### Server Instance Management

Expand All @@ -93,42 +108,57 @@ View available Container-Optimized OS images:
gcloud compute images list --project cos-cloud --no-standard-images
```

Update production container:
Update specified container:
```bash
# Clear existing containers
gcloud compute ssh gpt-bayes --zone us-central1-a --command 'docker system prune -f -a'
gcloud compute ssh dev-gpt-bayes --zone us-central1-a --command 'docker system prune -f -a'

# Deploy new container
gcloud compute instances update-container gpt-bayes \
--zone=us-central1-a \
--container-image=us-central1-docker.pkg.dev/bayes-gpt/gpt-bayes/gpt-bayes:latest

gcloud compute instances update-container dev-gpt-bayes \
--zone=us-central1-a \
--container-image=us-central1-docker.pkg.dev/bayes-gpt/dev-gpt-bayes/dev-gpt-bayes:latest
```

Create new server instance:
```bash
gcloud compute instances create gpt-bayes \
--machine-type e2-standard-4 \
--boot-disk-size 20GB \
--image image-name \
--image-project cos-cloud \
--zone us-central1 \
--metadata container-image=your-container-image-name \
--tags http-server \
--firewall-create allow-http
gcloud compute instances create-with-container gpt-bayes \
--machine-type e2-standard-4 \
--boot-disk-size 20GB \
--image cos-stable-117-18613-164-4 \
--image-project cos-cloud \
--zone us-central1-a \
--container-image=us-central1-docker.pkg.dev/bayes-gpt/gpt-bayes/gpt-bayes:latest \
--tags http-server,https-server,allow-tcp-5000

gcloud compute instances create-with-container dev-gpt-bayes \
--machine-type e2-standard-4 \
--boot-disk-size 20GB \
--image cos-stable-117-18613-164-4 \
--image-project cos-cloud \
--zone us-central1-a \
--container-image=us-central1-docker.pkg.dev/bayes-gpt/dev-gpt-bayes/dev-gpt-bayes:latest \
--tags http-server,https-server,allow-tcp-5000

```

### NGINX Configuration (Advanced)

Deploy NGINX reverse proxy updates:
```bash
cd nginx
gcloud builds submit
./deploy.sh production # Deploy the latest version to production
./deploy.sh development # Deploy the latest version to development
```

Update backend IP address:
1. Navigate to `nginx/nginx.conf`
2. Modify the `proxy_pass` directive with the new IP
3. Example: `proxy_pass http://35.208.203.115:5000;`
1. Navigate to `config.yaml`
2. Modify the `ipAddress` directive with the new IP
3. Example: `ipAddress: 35.208.203.115`

## Local Development

Expand Down
17 changes: 15 additions & 2 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@
app.config['broker_url'] = 'redis://localhost:6379/0'
app.config['result_backend'] = 'redis://localhost:6379/0'


celery = Celery(app.name, broker=app.config['broker_url'])
celery.conf.update(app.config)
celery.conf.update(
Expand All @@ -62,9 +61,23 @@
task_time_limit=600, # Add 1-hour timeout
broker_connection_retry_on_startup=True, # Retry broker connection on startup
worker_redirect_stdouts=False, # Don't redirect stdout/stderr
worker_redirect_stdouts_level='DEBUG' # Log level for stdout/stderr
worker_redirect_stdouts_level='DEBUG', # Log level for stdout/stderr
broker_transport_options={
'retry_on_timeout': True,
'max_retries': 3,
},
redis_max_connections=10,
broker_pool_limit=None, # Disable connection pool size limit
)

# Add Redis error logging
logging.info("Initializing Celery with Redis backend")
try:
celery.backend.client.ping()
logging.info("Successfully connected to Redis backend")
except Exception as e:
logging.error("Failed to connect to Redis: %s", str(e), exc_info=True)

logging.info("App started. Version: %s", __version__)

# Create a data directory if it doesn't exist
Expand Down
24 changes: 24 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/bin/bash

# Validate environment argument
if [ "$1" != "production" ] && [ "$1" != "development" ]; then
echo "Error: Environment must be specified as either 'production' or 'development'"
echo "Usage: $0 <environment>"
exit 1
fi

ENVIRONMENT=$1

# Function to read config value
get_config() {
local key=$1
yq ".$ENVIRONMENT.$key" config.yaml | tr -d '"'
}

# Get configuration values
INSTANCE_NAME=$(get_config "instanceName")
REGION=$(get_config "region")

echo "Building $INSTANCE_NAME in $REGION"

gcloud builds submit --config cloudbuild.yaml --substitutions=_REPO_NAME=$INSTANCE_NAME,_SERVICE_NAME=$INSTANCE_NAME,_REGION=$REGION
3 changes: 0 additions & 3 deletions cloudbuild.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,3 @@ images:

substitutions:
_SERVICE_FOLDER: .
_REPO_NAME: gpt-bayes # Name of Google Artifact Registry (GAR)'s repo
_SERVICE_NAME: gpt-bayes # Name of Cloud Run Service
_REGION: us-central1
22 changes: 22 additions & 0 deletions config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
production:
instanceName: gpt-bayes
region: us-central1
zone: us-central1-a
nginx:
repoName: gcr2gce-proxy
serviceName: gcr2gce-proxy
serverName: nextgen-mmm.pymc-labs.com
ipAddress: 35.208.203.115
port: 5000
region: us-central1
development:
instanceName: dev-gpt-bayes
region: us-central1
zone: us-central1-a
nginx:
repoName: dev-gcr2gce-proxy
serviceName: dev-gcr2gce-proxy
serverName: dev-nextgen-mmm.pymc-labs.com
ipAddress: 34.59.137.141
port: 5000
region: us-central1
38 changes: 29 additions & 9 deletions deploy.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,25 @@
#!/bin/bash

# Validate environment argument
if [ "$1" != "production" ] && [ "$1" != "development" ]; then
echo "Error: Environment must be specified as either 'production' or 'development'"
echo "Usage: $0 <environment>"
exit 1
fi

ENVIRONMENT=$1

# Function to read config value
get_config() {
local key=$1
yq ".$ENVIRONMENT.$key" config.yaml | tr -d '"'
}

# Get configuration values
INSTANCE_NAME=$(get_config "instanceName")
REGION=$(get_config "region")
ZONE=$(get_config "zone")

# Function to check if rebuild is needed
should_rebuild() {
read -p "Did you modify Dockerfile, environment.yml or other dependencies? (y/N): " answer
Expand All @@ -15,23 +35,23 @@ should_rebuild() {

if should_rebuild; then
echo "Rebuilding container..."
gcloud builds submit
./build.sh $ENVIRONMENT

echo "Cleaning up docker system..."
gcloud compute ssh gpt-bayes --zone us-central1-a --command 'docker system prune -f -a'
gcloud compute ssh "$INSTANCE_NAME" --zone "$ZONE" --command 'docker system prune -f -a'

echo "Updating container..."
gcloud compute instances update-container gpt-bayes \
--zone=us-central1-a \
--container-image=us-central1-docker.pkg.dev/bayes-gpt/gpt-bayes/gpt-bayes:latest
gcloud compute instances update-container "$INSTANCE_NAME" \
--zone="$ZONE" \
--container-image=$REGION-docker.pkg.dev/bayes-gpt/$INSTANCE_NAME/$INSTANCE_NAME:latest
else
echo "Copying new files and restarting application..."
# First, copy files to the instance
gcloud compute scp --zone=us-central1-a --recurse ./*.py gpt-bayes:/tmp/
gcloud compute scp --zone="$ZONE" --recurse ./*.py "$INSTANCE_NAME":/tmp/

# Then copy files into the container and restart services
gcloud compute ssh gpt-bayes --zone=us-central1-a --command "
CONTAINER_ID=\$(docker ps --filter ancestor=us-central1-docker.pkg.dev/bayes-gpt/gpt-bayes/gpt-bayes:latest -q) && \
gcloud compute ssh "$INSTANCE_NAME" --zone="$ZONE" --command "
CONTAINER_ID=\$(docker ps --filter ancestor=$REGION-docker.pkg.dev/bayes-gpt/$INSTANCE_NAME/$INSTANCE_NAME:latest -q) && \
if [ -z \"\$CONTAINER_ID\" ]; then
echo \"Error: Could not find running container\"
exit 1
Expand All @@ -50,7 +70,7 @@ else

# Restart the container
echo "Restarting container..."
gcloud compute ssh gpt-bayes --zone=us-central1-a --command "docker restart \$(docker ps --filter ancestor=us-central1-docker.pkg.dev/bayes-gpt/gpt-bayes/gpt-bayes:latest -q)"
gcloud compute ssh "$INSTANCE_NAME" --zone="$ZONE" --command "docker restart \$(docker ps --filter ancestor=$REGION-docker.pkg.dev/bayes-gpt/$INSTANCE_NAME/$INSTANCE_NAME:latest -q)"
fi

echo "Deployment complete!"
1 change: 1 addition & 0 deletions environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ dependencies:
- vine=5.1.0
- redis-py=4.5.0
- procps-ng
- yq=2.12.0

5 changes: 1 addition & 4 deletions nginx/cloudbuild.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,4 @@ images:
- ${_REGION}-docker.pkg.dev/${PROJECT_ID}/${_REPO_NAME}/${_SERVICE_NAME}

substitutions:
_SERVICE_FOLDER: .
_REPO_NAME: gcr2gce-proxy # Name of Google Artifact Registry (GAR)'s repo
_SERVICE_NAME: gcr2gce-proxy # Name of Cloud Run Service
_REGION: us-central1
_SERVICE_FOLDER: .
36 changes: 36 additions & 0 deletions nginx/deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#!/bin/bash

# Validate environment argument
if [ "$1" != "production" ] && [ "$1" != "development" ]; then
echo "Error: Environment must be specified as either 'production' or 'development'"
echo "Usage: $0 <environment>"
exit 1
fi

ENVIRONMENT=$1

# Function to read config value
get_nginx_config() {
local key=$1
yq ".$ENVIRONMENT.nginx.$key" ../config.yaml | tr -d '"'
}

# Get configuration values
SERVER_NAME=$(get_nginx_config "serverName")
IP_ADDRESS=$(get_nginx_config "ipAddress")
PORT=$(get_nginx_config "port")
REPO_NAME=$(get_nginx_config "repoName")
SERVICE_NAME=$(get_nginx_config "serviceName")
REGION=$(get_nginx_config "region")

# Replace placeholders in nginx.conf.template
sed -e "s/\${SERVER_NAME}/$SERVER_NAME/g" \
-e "s/\${IP_ADDRESS}/$IP_ADDRESS/g" \
-e "s/\${PORT}/$PORT/g" nginx.conf.template > nginx.conf


# Deploy
gcloud builds submit --config cloudbuild.yaml --substitutions=_REPO_NAME=$REPO_NAME,_SERVICE_NAME=$SERVICE_NAME,_REGION=$REGION

# Clean up
rm nginx.conf
4 changes: 2 additions & 2 deletions nginx/nginx.conf → nginx/nginx.conf.template
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ http {

server {
listen 8080;
server_name nextgen-mmm.pymc-labs.com;
server_name ${SERVER_NAME};

location / {
proxy_pass http://35.208.203.115:5000;
proxy_pass http://${IP_ADDRESS}:${PORT};
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
Expand Down
Loading