Skip to content

Commit

Permalink
Merge pull request #15 from tommylees112/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
tommylees112 authored Sep 13, 2024
2 parents 2a37c30 + 14596c5 commit 93f49b7
Show file tree
Hide file tree
Showing 8 changed files with 160 additions and 41 deletions.
1 change: 0 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
FLASK_APP=INSERT_HERE
COHERE_API_KEY=INSERT_HERE
TWILIO_ACCOUNT_SID=INSERT_HERE
TWILIO_AUTH_TOKEN=INSERT_HERE
Expand Down
77 changes: 77 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# .github/workflows/deploy.yml

name: Deploy FastAPI to Google Cloud Run

on:
push:
branches:
- main # Triggers the workflow on pushes to the 'main' branch
- dev
workflow_dispatch: # Allows manual triggering

env:
GCP_PROJECT_ID: whatsappllm
GCP_REGION: europe-west3

jobs:
deploy:
runs-on: ubuntu-latest

steps:
# Step 1: Checkout the repository
- name: Checkout Repository
uses: actions/checkout@v4

# Step 2: Authenticate to Google Cloud
- name: Authenticate to Google Cloud
uses: google-github-actions/auth@v1
with:
credentials_json: ${{ secrets.GCP_SA_KEY }}

# Step 2.1: Verify Authentication [DEBUG]
- name: Verify Authentication
run: |
gcloud auth list
gcloud config list project
# Step 3: Configure Docker to use Google Cloud credentials
- name: Configure Docker for GCR
run: |
gcloud auth configure-docker gcr.io
# Step 3.1: Test Docker Authentication
- name: Test Docker Authentication
run: |
docker info
# Step 4: Build the Docker image
- name: Build Docker Image
run: |
IMAGE=gcr.io/$GCP_PROJECT_ID/whatsappllm:${{ github.sha }}
docker build -t $IMAGE .
# Step 5: Push the Docker image to GCR
- name: Push Docker Image to GCR
run: |
IMAGE=gcr.io/$GCP_PROJECT_ID/whatsappllm:${{ github.sha }}
docker push $IMAGE
# Ensure the image name matches the build step

# Step 6: Deploy to Google Cloud Run
- name: Deploy to Cloud Run
run: |
gcloud run deploy whatsappllm-service \
--image gcr.io/$GCP_PROJECT_ID/whatsappllm:${{ github.sha }} \
--region $GCP_REGION \
--platform managed \
--allow-unauthenticated \
--update-secrets=TWILIO_ACCOUNT_SID=TWILIO_ACCOUNT_SID:latest \
--update-secrets=TWILIO_AUTH_TOKEN=TWILIO_AUTH_TOKEN:latest \
--update-secrets=TWILIO_PHONE_NUMBER=TWILIO_PHONE_NUMBER:latest \
--update-secrets=COHERE_API_KEY=COHERE_API_KEY:latest
# Optional Step 7: Clean Up Docker Images (To save storage on the runner)
- name: Clean Up Docker Images
if: always()
run: |
docker image prune -f
8 changes: 3 additions & 5 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
FROM python:3.9-slim@sha256:980b778550c0d938574f1b556362b27601ea5c620130a572feb63ac1df03eda5
FROM python:3.11

ENV PYTHONUNBUFFERED True

ENV APP_HOME /app
WORKDIR $APP_HOME
COPY . ./

# set the port to 1234
ENV PORT 1234

# create the environment and install the dependencies
RUN pip install --no-cache-dir -r requirements.txt

# As an example here we're running the web service with one worker on uvicorn.
CMD exec uvicorn src.main:app --host 0.0.0.0 --port ${PORT} --workers 1
# CMD exec uvicorn src.main:app --host 0.0.0.0 --workers 1
CMD fastapi dev --port=$PORT --host=0.0.0.0 src/main.py
34 changes: 31 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ This project is a WhatsApp chatbot that uses the Cohere Command R+ model to summ
TWILIO_ACCOUNT_SID=your_twilio_account_sid
TWILIO_AUTH_TOKEN=your_twilio_auth_token
TWILIO_PHONE_NUMBER=your_twilio_phone_number
OG_TWILIO_PHONE_NUMBER=your_og_twilio_phone_number
COHERE_API_KEY=your_cohere_api_key
```

4. Run the FastAPI server locally:
Expand All @@ -44,8 +44,16 @@ This project is a WhatsApp chatbot that uses the Cohere Command R+ model to summ

## Deployment

If you want to test the deployment manually, follow this [guide](https://github.com/sekR4/FastAPI-on-Google-Cloud-Run?tab=readme-ov-file)
```bash
gcloud builds submit --tag $TAG
gcloud run deploy $APP --image $TAG --platform managed --region $REGION --allow-unauthenticated
```

Following this [guide](https://github.com/sekR4/FastAPI-on-Google-Cloud-Run?tab=readme-ov-file)

[Automatically deployed to cloudrun](https://github.com/google-github-actions/deploy-cloudrun) on push to main or dev

This project is set up to be deployed on Google Cloud Run. Use the following commands to build and deploy:

```bash
Expand All @@ -66,6 +74,14 @@ gh secret set TWILIO_AUTH_TOKEN --body "KEY_GOES_HERE"
gh secret set TWILIO_PHONE_NUMBER --body "KEY_GOES_HERE"
```

Add secret variables to the [google Secret Manager](https://console.cloud.google.com/security/secret-manager?referrer=search&hl=en&project=whatsappllm) and read from [`deploy.yml`](https://stackoverflow.com/questions/65857870/how-to-use-a-google-secret-in-a-deployed-cloud-run-service-managed).
```bash
gcloud secrets create COHERE_API_KEY --data-file=.env
gcloud secrets create TWILIO_ACCOUNT_SID --data-file=.env
gcloud secrets create TWILIO_AUTH_TOKEN --data-file=.env
gcloud secrets create TWILIO_PHONE_NUMBER --data-file=.env
```

# See all info about the app
```bash
gcloud run services describe $APP --region $REGION
Expand All @@ -79,7 +95,6 @@ gcloud run services update my-service \
--update-env-vars=MY_VAR=my_value,ANOTHER_VAR=another_value
```


## Monitoring

- [Twilio Whatsapp Senders](https://console.twilio.com/us1/develop/sms/senders/whatsapp-senders/XE2357b321ff41b31f05ca6b44fd626c5d)
Expand Down Expand Up @@ -109,4 +124,17 @@ Contributions are welcome! Please feel free to submit a Pull Request.

## License

This project is open source and available under the [MIT License](LICENSE).
This project is open source and available under the [MIT License](LICENSE).

## CLI Option
Hit the api using curl
```bash
function llm() {
local url=$1
curl -s -X 'POST' \
'<GCLOUD URL>/summarize' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d "{\"url\": \"$url\"}" | jq -r ".summary" | bat
}
```
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ python-dotenv
python-multipart
twilio
uvicorn
nltk
nltk
fastapi[standard]
59 changes: 39 additions & 20 deletions src/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,39 +5,58 @@
"""

import os
from typing import Optional

from dotenv import load_dotenv
from pydantic import Field
from pydantic_settings import BaseSettings

# Load environment variables from .env file
load_dotenv()


class Settings(BaseSettings):
# FastAPI settings
APP_NAME: str = "WhatsappLLM"
DEBUG: bool = os.getenv("DEBUG", "False").lower() == "true"
ENVIRONMENT: str = os.getenv("ENVIRONMENT", "production")
# class Settings(BaseSettings):
# # FastAPI settings
# APP_NAME: str = "WhatsappLLM"
# DEBUG: bool = os.getenv("DEBUG", "False").lower() == "true"

# Twilio settings
TWILIO_ACCOUNT_SID: str = Field(..., env="TWILIO_ACCOUNT_SID")
TWILIO_AUTH_TOKEN: str = Field(..., env="TWILIO_AUTH_TOKEN")
TWILIO_PHONE_NUMBER: str = Field(..., env="TWILIO_PHONE_NUMBER")
OG_TWILIO_PHONE_NUMBER: str = Field(..., env="OG_TWILIO_PHONE_NUMBER")
MY_PHONE_NUMBER: str = Field(..., env="MY_PHONE_NUMBER")
# # Twilio settings
# TWILIO_ACCOUNT_SID: str = Field(alias="TWILIO_ACCOUNT_SID")
# TWILIO_AUTH_TOKEN: str = Field(alias="TWILIO_AUTH_TOKEN")
# TWILIO_PHONE_NUMBER: str = Field(alias="TWILIO_PHONE_NUMBER")

# Cohere settings
COHERE_API_KEY: str = Field(..., env="COHERE_API_KEY")
# # Cohere settings
# COHERE_API_KEY: str = Field(alias="COHERE_API_KEY")

class Config:
env_file = ".env"
case_sensitive = True
extra = "ignore"

# class Config:
# env_file = ".env"
# case_sensitive = True
# extra = "ignore"


class Settings:
DEBUG: Optional[bool] = os.getenv("DEBUG", "False").lower() == "true"
TWILIO_ACCOUNT_SID: Optional[str] = os.environ.get("TWILIO_ACCOUNT_SID")
TWILIO_AUTH_TOKEN: Optional[str] = os.environ.get("TWILIO_AUTH_TOKEN")
TWILIO_PHONE_NUMBER: Optional[str] = os.environ.get("TWILIO_PHONE_NUMBER")
COHERE_API_KEY: Optional[str] = os.environ.get("COHERE_API_KEY")

def model_dump(self):
return {
"DEBUG": self.DEBUG,
"TWILIO_ACCOUNT_SID": self.TWILIO_ACCOUNT_SID,
"TWILIO_AUTH_TOKEN": self.TWILIO_AUTH_TOKEN,
"TWILIO_PHONE_NUMBER": self.TWILIO_PHONE_NUMBER,
"COHERE_API_KEY": self.COHERE_API_KEY,
}


def get_settings() -> Settings:
return Settings()
return Settings(
# TWILIO_ACCOUNT_SID=os.environ.get("TWILIO_ACCOUNT_SID"),
# TWILIO_AUTH_TOKEN=os.environ.get("TWILIO_AUTH_TOKEN"),
# TWILIO_PHONE_NUMBER=os.environ.get("TWILIO_PHONE_NUMBER"),
# COHERE_API_KEY=os.environ.get("COHERE_API_KEY"),
)


# Create a global instance of the settings
Expand Down
8 changes: 0 additions & 8 deletions src/main.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import json
import os

import uvicorn
from fastapi import Depends, FastAPI, HTTPException, Request, Response
from loguru import logger
from pydantic import BaseModel, Field
Expand Down Expand Up @@ -95,9 +93,3 @@ async def webhook(
return {"message": "Invalid command"}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))


if __name__ == "__main__":
logger.info("Starting FastAPI server...")
port = int(os.environ.get("PORT", 8080))
uvicorn.run("src.main:app", host="0.0.0.0", port=8000, reload=True)
11 changes: 8 additions & 3 deletions src/services/twilio.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import os

from loguru import logger
from twilio.rest import Client

Expand All @@ -13,7 +15,8 @@ def __init__(
):
# Setup Twilio number
if settings.DEBUG:
self.from_number = f"whatsapp:{settings.OG_TWILIO_PHONE_NUMBER}"
logger.debug(f"SENDING MSG FROM {os.getenv('OG_TWILIO_PHONE_NUMBER')}")
self.from_number = f"whatsapp:{os.getenv('OG_TWILIO_PHONE_NUMBER')}"
else:
self.from_number = f"whatsapp:{settings.TWILIO_PHONE_NUMBER}"

Expand All @@ -36,10 +39,12 @@ def send_message(self, from_number: str, to_number: str, message: str):


if __name__ == "__main__":
import os

# python -m src.services.twilio
twilio_service = TwilioService()
twilio_service.send_message(
to_number=f"whatsapp:{settings.MY_PHONE_NUMBER}",
to_number=f"whatsapp:{os.getenv('MY_PHONE_NUMBER')}",
message="Hello, world!",
from_number=f"whatsapp:{settings.OG_TWILIO_PHONE_NUMBER}",
from_number=f"whatsapp:{os.getenv('OG_TWILIO_PHONE_NUMBER')}",
)

0 comments on commit 93f49b7

Please sign in to comment.