Spaces:
Running
Running
Jesse Liu commited on
Commit ·
6a725a4
1
Parent(s): 58ee581
init hf
Browse files- .gitignore +11 -0
- DEPLOY_INSTRUCTIONS.md +52 -0
- DEPLOY_NOW.md +37 -0
- DEPLOY_SIMPLE.md +62 -0
- HUGGINGFACE_DEPLOY.md +168 -0
- QUICK_SETUP.md +94 -0
- README.md +69 -3
- chatgpt.py +31 -8
- deploy_git.sh +98 -0
- deploy_hf.sh +63 -0
- get_refresh_token.py +41 -0
- google_drive_setup_guide.md +117 -0
- google_drive_sync.py +125 -5
- src/server.py +14 -0
.gitignore
CHANGED
|
@@ -81,3 +81,14 @@ Thumbs.db
|
|
| 81 |
/summaries/*
|
| 82 |
/assets/*
|
| 83 |
trace_back_results_30patient_2ad/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 81 |
/summaries/*
|
| 82 |
/assets/*
|
| 83 |
trace_back_results_30patient_2ad/
|
| 84 |
+
|
| 85 |
+
# Google Drive credentials (sensitive)
|
| 86 |
+
service-account-key.json
|
| 87 |
+
*service-account*.json
|
| 88 |
+
user_tokens/
|
| 89 |
+
*.pickle
|
| 90 |
+
*.pkl
|
| 91 |
+
|
| 92 |
+
# Environment variables
|
| 93 |
+
.env
|
| 94 |
+
.env.local
|
DEPLOY_INSTRUCTIONS.md
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 🚀 Steps to Deploy on Hugging Face
|
| 2 |
+
|
| 3 |
+
## Step 1: Generate a Hugging Face token
|
| 4 |
+
|
| 5 |
+
1. Visit https://huggingface.co/settings/tokens
|
| 6 |
+
2. Click **“New token”**
|
| 7 |
+
3. Choose **“Write”** permission
|
| 8 |
+
4. Copy the generated token
|
| 9 |
+
|
| 10 |
+
## Step 2: Log in to Hugging Face
|
| 11 |
+
|
| 12 |
+
Run in your terminal:
|
| 13 |
+
|
| 14 |
+
```bash
|
| 15 |
+
huggingface-cli login
|
| 16 |
+
```
|
| 17 |
+
|
| 18 |
+
Then paste your token when prompted.
|
| 19 |
+
|
| 20 |
+
Or provide it via environment variable:
|
| 21 |
+
|
| 22 |
+
```bash
|
| 23 |
+
export HF_TOKEN="your_token"
|
| 24 |
+
huggingface-cli login --token $HF_TOKEN
|
| 25 |
+
```
|
| 26 |
+
|
| 27 |
+
## Step 3: Deploy the app
|
| 28 |
+
|
| 29 |
+
Run:
|
| 30 |
+
|
| 31 |
+
```bash
|
| 32 |
+
gradio deploy
|
| 33 |
+
```
|
| 34 |
+
|
| 35 |
+
Or use the helper script:
|
| 36 |
+
|
| 37 |
+
```bash
|
| 38 |
+
./deploy_hf.sh
|
| 39 |
+
```
|
| 40 |
+
|
| 41 |
+
## Step 4: Add Google Drive secrets (post-deployment)
|
| 42 |
+
|
| 43 |
+
1. Open your Space page: `https://huggingface.co/spaces/<username>/<space-name>`
|
| 44 |
+
2. Go to the **“Settings”** tab
|
| 45 |
+
3. Under **“Repository secrets”** add:
|
| 46 |
+
- **Name**: `GOOGLE_SERVICE_ACCOUNT_JSON`
|
| 47 |
+
- **Value**: paste the full Service Account JSON content
|
| 48 |
+
|
| 49 |
+
## Done!
|
| 50 |
+
|
| 51 |
+
Wait 2–5 minutes for the build to finish, then open your Space URL.
|
| 52 |
+
|
DEPLOY_NOW.md
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 🚀 Deploy to Hugging Face Right Now
|
| 2 |
+
|
| 3 |
+
## Problem
|
| 4 |
+
The CLI error shows that Space names cannot contain spaces, so you must provide a valid identifier.
|
| 5 |
+
|
| 6 |
+
## Solution
|
| 7 |
+
|
| 8 |
+
Run this inside your `chatbot` environment:
|
| 9 |
+
|
| 10 |
+
```bash
|
| 11 |
+
gradio deploy --space chatbot-mimic-notes
|
| 12 |
+
```
|
| 13 |
+
|
| 14 |
+
Or include your Hugging Face username:
|
| 15 |
+
|
| 16 |
+
```bash
|
| 17 |
+
gradio deploy --space your-username/chatbot-mimic-notes
|
| 18 |
+
```
|
| 19 |
+
|
| 20 |
+
## Valid Space Name Rules
|
| 21 |
+
- ✅ Letters, digits, hyphen `-`, underscore `_`, dot `.`
|
| 22 |
+
- ✅ Cannot start or end with `-` or `.`
|
| 23 |
+
- ✅ `--` and `..` are not allowed
|
| 24 |
+
- ✅ Maximum length 96 characters
|
| 25 |
+
- ❌ No spaces
|
| 26 |
+
|
| 27 |
+
## Examples
|
| 28 |
+
```bash
|
| 29 |
+
# Valid
|
| 30 |
+
gradio deploy --space chatbot-mimic-notes
|
| 31 |
+
gradio deploy --space my-chatbot-app
|
| 32 |
+
gradio deploy --space chatbot_123
|
| 33 |
+
|
| 34 |
+
# Invalid (contains spaces)
|
| 35 |
+
gradio deploy --space "Chatbot Mimic Notes"
|
| 36 |
+
```
|
| 37 |
+
|
DEPLOY_SIMPLE.md
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 🚀 Simplest Deployment Path
|
| 2 |
+
|
| 3 |
+
Because this version of `gradio deploy` does not accept the `--space` flag, use Git-based deployment instead.
|
| 4 |
+
|
| 5 |
+
## Option 1: Deployment Script (recommended)
|
| 6 |
+
|
| 7 |
+
```bash
|
| 8 |
+
./deploy_git.sh
|
| 9 |
+
```
|
| 10 |
+
|
| 11 |
+
The script automatically:
|
| 12 |
+
1. Checks login status
|
| 13 |
+
2. Creates or updates the Space
|
| 14 |
+
3. Copies files and pushes via Git
|
| 15 |
+
|
| 16 |
+
## Option 2: Manual Git Workflow
|
| 17 |
+
|
| 18 |
+
### Step 1: Create the Space
|
| 19 |
+
|
| 20 |
+
Visit https://huggingface.co/new-space or run:
|
| 21 |
+
|
| 22 |
+
```bash
|
| 23 |
+
huggingface-cli repo create chatbot-mimic-notes --type space --sdk gradio
|
| 24 |
+
```
|
| 25 |
+
|
| 26 |
+
### Step 2: Clone the Space
|
| 27 |
+
|
| 28 |
+
```bash
|
| 29 |
+
git clone https://huggingface.co/spaces/jesseliu/chatbot-mimic-notes
|
| 30 |
+
cd chatbot-mimic-notes
|
| 31 |
+
```
|
| 32 |
+
|
| 33 |
+
### Step 3: Copy project files
|
| 34 |
+
|
| 35 |
+
```bash
|
| 36 |
+
# Copy required files
|
| 37 |
+
cp ../chatbot-mimic-notes/chatgpt.py .
|
| 38 |
+
cp ../chatbot-mimic-notes/README.md .
|
| 39 |
+
cp ../chatbot-mimic-notes/requirements.txt .
|
| 40 |
+
cp -r ../chatbot-mimic-notes/src ./src
|
| 41 |
+
cp ../chatbot-mimic-notes/google_drive_sync.py .
|
| 42 |
+
```
|
| 43 |
+
|
| 44 |
+
### Step 4: Commit and push
|
| 45 |
+
|
| 46 |
+
```bash
|
| 47 |
+
git add .
|
| 48 |
+
git commit -m "Initial deployment"
|
| 49 |
+
git push
|
| 50 |
+
```
|
| 51 |
+
|
| 52 |
+
## Done!
|
| 53 |
+
|
| 54 |
+
Wait 2–5 minutes for the build, then visit:
|
| 55 |
+
https://huggingface.co/spaces/jesseliu/chatbot-mimic-notes
|
| 56 |
+
|
| 57 |
+
## Configure Google Drive Secrets
|
| 58 |
+
|
| 59 |
+
1. Open Space Settings
|
| 60 |
+
2. Add secret: `GOOGLE_SERVICE_ACCOUNT_JSON`
|
| 61 |
+
3. Paste the full Service Account JSON content
|
| 62 |
+
|
HUGGINGFACE_DEPLOY.md
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 🚀 Hugging Face Spaces Deployment Guide
|
| 2 |
+
|
| 3 |
+
This guide walks through deploying the chatbot to Hugging Face Spaces so you have a permanent HTTPS endpoint.
|
| 4 |
+
|
| 5 |
+
## 📋 Prerequisites
|
| 6 |
+
|
| 7 |
+
1. **Hugging Face account**
|
| 8 |
+
- Sign up at [huggingface.co](https://huggingface.co)
|
| 9 |
+
- Verify your email
|
| 10 |
+
|
| 11 |
+
2. **CLI tooling**
|
| 12 |
+
```bash
|
| 13 |
+
pip install huggingface_hub[cli]
|
| 14 |
+
```
|
| 15 |
+
|
| 16 |
+
## 🎯 Deployment Paths
|
| 17 |
+
|
| 18 |
+
### Option 1: Deployment script (easiest)
|
| 19 |
+
|
| 20 |
+
```bash
|
| 21 |
+
# 1. Log in to Hugging Face
|
| 22 |
+
huggingface-cli login
|
| 23 |
+
|
| 24 |
+
# 2. Run the helper script
|
| 25 |
+
python deploy_to_huggingface.py
|
| 26 |
+
```
|
| 27 |
+
|
| 28 |
+
### Option 2: Gradio CLI
|
| 29 |
+
|
| 30 |
+
```bash
|
| 31 |
+
huggingface-cli login
|
| 32 |
+
gradio deploy
|
| 33 |
+
```
|
| 34 |
+
|
| 35 |
+
### Option 3: Manual Git push
|
| 36 |
+
|
| 37 |
+
```bash
|
| 38 |
+
# 1. Create a Space at https://huggingface.co/new-space (select Gradio SDK)
|
| 39 |
+
|
| 40 |
+
# 2. Clone the Space repo
|
| 41 |
+
git clone https://huggingface.co/spaces/<username>/<space-name>
|
| 42 |
+
cd <space-name>
|
| 43 |
+
|
| 44 |
+
# 3. Copy project files
|
| 45 |
+
cp -r /path/to/chatbot-mimic-notes/* .
|
| 46 |
+
|
| 47 |
+
# 4. Commit and push
|
| 48 |
+
git add .
|
| 49 |
+
git commit -m "Initial deployment"
|
| 50 |
+
git push
|
| 51 |
+
```
|
| 52 |
+
|
| 53 |
+
## 🔐 Configure Google Drive (important)
|
| 54 |
+
|
| 55 |
+
Spaces should rely on environment variables for Drive credentials.
|
| 56 |
+
|
| 57 |
+
### Step 1: Obtain the Service Account JSON
|
| 58 |
+
|
| 59 |
+
1. Follow `QUICK_SETUP.md`
|
| 60 |
+
2. Download the JSON key file
|
| 61 |
+
|
| 62 |
+
### Step 2: Add Hugging Face secrets
|
| 63 |
+
|
| 64 |
+
1. Open `https://huggingface.co/spaces/<username>/<space-name>`
|
| 65 |
+
2. Go to **Settings → Repository secrets**
|
| 66 |
+
3. Add the required secrets:
|
| 67 |
+
|
| 68 |
+
#### Option A: Service Account (recommended)
|
| 69 |
+
|
| 70 |
+
1. Copy the full JSON content
|
| 71 |
+
2. Add a secret:
|
| 72 |
+
- **Name**: `GOOGLE_SERVICE_ACCOUNT_JSON`
|
| 73 |
+
- **Value**: entire JSON blob
|
| 74 |
+
|
| 75 |
+
#### Option B: Refresh token flow
|
| 76 |
+
|
| 77 |
+
Add these secrets if you prefer OAuth refresh tokens:
|
| 78 |
+
- **Name**: `GOOGLE_REFRESH_TOKEN`
|
| 79 |
+
- **Name**: `GOOGLE_CLIENT_ID` (optional override)
|
| 80 |
+
- **Name**: `GOOGLE_CLIENT_SECRET` (optional override)
|
| 81 |
+
|
| 82 |
+
### Step 3: Environment variable support
|
| 83 |
+
|
| 84 |
+
The code already reads credentials from environment variables. If you supply the JSON via secret, no extra code changes are needed.
|
| 85 |
+
|
| 86 |
+
## 📝 README front matter
|
| 87 |
+
|
| 88 |
+
Ensure the top of `README.md` contains:
|
| 89 |
+
|
| 90 |
+
```yaml
|
| 91 |
+
---
|
| 92 |
+
title: Chatbot Mimic Notes
|
| 93 |
+
emoji: 🤖
|
| 94 |
+
colorFrom: blue
|
| 95 |
+
colorTo: green
|
| 96 |
+
sdk: gradio
|
| 97 |
+
sdk_version: 3.50.2
|
| 98 |
+
app_file: chatgpt.py
|
| 99 |
+
pinned: false
|
| 100 |
+
---
|
| 101 |
+
```
|
| 102 |
+
|
| 103 |
+
## ✅ Post-deployment checklist
|
| 104 |
+
|
| 105 |
+
1. **Visit the Space**
|
| 106 |
+
`https://<username>-<space-name>.hf.space` (build takes ~2–5 minutes)
|
| 107 |
+
|
| 108 |
+
2. **Smoke test**
|
| 109 |
+
- Confirm the UI loads
|
| 110 |
+
- Trigger a sample Google Drive sync
|
| 111 |
+
- Verify data persistence
|
| 112 |
+
|
| 113 |
+
3. **Check logs**
|
| 114 |
+
- Open the “Logs” tab to inspect errors
|
| 115 |
+
|
| 116 |
+
## 🔧 Troubleshooting
|
| 117 |
+
|
| 118 |
+
### Build failed
|
| 119 |
+
|
| 120 |
+
- Confirm `requirements.txt` lists every dependency
|
| 121 |
+
- Review the build logs
|
| 122 |
+
- Ensure Python 3.10 compatibility
|
| 123 |
+
|
| 124 |
+
### Google Drive sync fails
|
| 125 |
+
|
| 126 |
+
1. Verify Space secrets
|
| 127 |
+
2. Confirm the Service Account has Drive access
|
| 128 |
+
3. Ensure the Drive API is enabled
|
| 129 |
+
4. Review runtime logs
|
| 130 |
+
|
| 131 |
+
### App won’t start
|
| 132 |
+
|
| 133 |
+
- Make sure `app_file` matches `chatgpt.py`
|
| 134 |
+
- Confirm `chatgpt.py` exists in the repo
|
| 135 |
+
- Read the log output for stack traces
|
| 136 |
+
|
| 137 |
+
## 📦 Updating the Space
|
| 138 |
+
|
| 139 |
+
### Via Git
|
| 140 |
+
|
| 141 |
+
```bash
|
| 142 |
+
cd <space-repo>
|
| 143 |
+
git add .
|
| 144 |
+
git commit -m "Update: describe changes"
|
| 145 |
+
git push
|
| 146 |
+
```
|
| 147 |
+
|
| 148 |
+
### Via the web UI
|
| 149 |
+
|
| 150 |
+
1. Open the Space and click **Files**
|
| 151 |
+
2. Upload or edit files
|
| 152 |
+
3. Commit the changes online
|
| 153 |
+
|
| 154 |
+
## 🎉 What you get
|
| 155 |
+
|
| 156 |
+
- ✅ Permanent HTTPS URL
|
| 157 |
+
- ✅ Free hosting tier
|
| 158 |
+
- ✅ Automatic certificates
|
| 159 |
+
- ✅ Global CDN
|
| 160 |
+
- ✅ Version history & rollbacks
|
| 161 |
+
|
| 162 |
+
## 💡 Tips
|
| 163 |
+
|
| 164 |
+
- **Custom domain**: configure under Space Settings
|
| 165 |
+
- **Resources**: upgrade if you need more CPU/RAM
|
| 166 |
+
- **Private Spaces**: toggle visibility in Settings
|
| 167 |
+
- **Monitoring**: use the built-in analytics/logs
|
| 168 |
+
|
QUICK_SETUP.md
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 🚀 Google Drive Quick Setup Guide
|
| 2 |
+
|
| 3 |
+
If you run into `invalid_client` errors, **use the Service Account approach** (simpler and more reliable).
|
| 4 |
+
|
| 5 |
+
## ⭐ Recommended: Service Account (≈5 minutes)
|
| 6 |
+
|
| 7 |
+
### Step 1: Create a Service Account (≈2 minutes)
|
| 8 |
+
|
| 9 |
+
1. Visit [Google Cloud Console](https://console.cloud.google.com/)
|
| 10 |
+
2. Create a new project or select an existing one
|
| 11 |
+
3. Enable the Google Drive API:
|
| 12 |
+
- Left menu → “APIs & Services” → “Library”
|
| 13 |
+
- Search “Google Drive API” → click “Enable”
|
| 14 |
+
4. Create the Service Account:
|
| 15 |
+
- Left menu → “IAM & Admin” → “Service Accounts”
|
| 16 |
+
- Click “Create Service Account”
|
| 17 |
+
- Name it `chatbot-drive-uploader`
|
| 18 |
+
- Click “Create and Continue” → “Done”
|
| 19 |
+
|
| 20 |
+
### Step 2: Download the key (≈1 minute)
|
| 21 |
+
|
| 22 |
+
1. Open the Service Account you just created
|
| 23 |
+
2. Go to the “Keys” tab
|
| 24 |
+
3. Click “Add Key” → “Create new key”
|
| 25 |
+
4. Choose **JSON**
|
| 26 |
+
5. Click “Create” (the file downloads automatically)
|
| 27 |
+
6. Rename it to `service-account-key.json`
|
| 28 |
+
7. Place it in the project root (next to `google_drive_sync.py`)
|
| 29 |
+
|
| 30 |
+
### Step 3: Share the Google Drive folder (≈1 minute)
|
| 31 |
+
|
| 32 |
+
1. Create a folder in Google Drive (e.g., “Chatbot_Data”)
|
| 33 |
+
2. Right-click → “Share”
|
| 34 |
+
3. Open `service-account-key.json`, find `client_email`
|
| 35 |
+
- Example: `chatbot-drive-uploader@your-project.iam.gserviceaccount.com`
|
| 36 |
+
4. Invite that email with “Editor” permission
|
| 37 |
+
5. Click “Send”
|
| 38 |
+
|
| 39 |
+
### Step 4: Update the code (≈1 minute)
|
| 40 |
+
|
| 41 |
+
Open `google_drive_sync.py` and set:
|
| 42 |
+
|
| 43 |
+
```python
|
| 44 |
+
SERVICE_ACCOUNT_FILE = "service-account-key.json"
|
| 45 |
+
```
|
| 46 |
+
|
| 47 |
+
### Done! ✅
|
| 48 |
+
|
| 49 |
+
All data will now sync to your Drive folder automatically without manual intervention.
|
| 50 |
+
|
| 51 |
+
---
|
| 52 |
+
|
| 53 |
+
## 🔄 Alternative: Fix the OAuth client (refresh token flow)
|
| 54 |
+
|
| 55 |
+
If you prefer refresh tokens, create a new OAuth client.
|
| 56 |
+
|
| 57 |
+
### Step 1: Create the OAuth client
|
| 58 |
+
|
| 59 |
+
1. Visit [Google Cloud Console](https://console.cloud.google.com/)
|
| 60 |
+
2. Select your project
|
| 61 |
+
3. Left menu → “APIs & Services” → “Credentials”
|
| 62 |
+
4. Click “Create Credentials” → “OAuth client ID”
|
| 63 |
+
5. If prompted, configure the consent screen (choose “External”)
|
| 64 |
+
6. App name: `Chatbot Drive Uploader`
|
| 65 |
+
7. User support email: your email
|
| 66 |
+
8. Developer contact: your email
|
| 67 |
+
9. Click through “Save and Continue” to finish
|
| 68 |
+
10. Click “Create Credentials” → “OAuth client ID” again
|
| 69 |
+
11. Choose **“Desktop app”**
|
| 70 |
+
12. Name it `Chatbot Desktop Client`
|
| 71 |
+
13. Click “Create”
|
| 72 |
+
14. Copy the **Client ID** and **Client secret**
|
| 73 |
+
|
| 74 |
+
### Step 2: Update the code
|
| 75 |
+
|
| 76 |
+
```python
|
| 77 |
+
CLIENT_ID = "your new client id"
|
| 78 |
+
CLIENT_SECRET = "your new client secret"
|
| 79 |
+
```
|
| 80 |
+
|
| 81 |
+
### Step 3: Fetch a new refresh token
|
| 82 |
+
|
| 83 |
+
```bash
|
| 84 |
+
python get_refresh_token.py
|
| 85 |
+
```
|
| 86 |
+
|
| 87 |
+
---
|
| 88 |
+
|
| 89 |
+
## 📝 Notes
|
| 90 |
+
|
| 91 |
+
- The Service Account JSON is sensitive — **never commit it to Git**
|
| 92 |
+
- Add `service-account-key.json` to `.gitignore`
|
| 93 |
+
- Service Accounts are safer because no user credentials live in code
|
| 94 |
+
|
README.md
CHANGED
|
@@ -1,10 +1,18 @@
|
|
| 1 |
---
|
| 2 |
-
title:
|
| 3 |
-
|
|
|
|
|
|
|
| 4 |
sdk: gradio
|
| 5 |
sdk_version: 3.50.2
|
|
|
|
|
|
|
|
|
|
| 6 |
---
|
| 7 |
-
|
|
|
|
|
|
|
|
|
|
| 8 |
|
| 9 |
## Prerequisites
|
| 10 |
- Python 3.x
|
|
@@ -35,3 +43,61 @@ python -m src.server
|
|
| 35 |
|
| 36 |
## Usage
|
| 37 |
- Open Chrome and visit `http://localhost:7860` to interact with the chatbot.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
---
|
| 2 |
+
title: Chatbot Mimic Notes
|
| 3 |
+
emoji: 🤖
|
| 4 |
+
colorFrom: blue
|
| 5 |
+
colorTo: green
|
| 6 |
sdk: gradio
|
| 7 |
sdk_version: 3.50.2
|
| 8 |
+
app_file: chatgpt.py
|
| 9 |
+
pinned: false
|
| 10 |
+
license: mit
|
| 11 |
---
|
| 12 |
+
|
| 13 |
+
# Chatbot Mimic Notes
|
| 14 |
+
|
| 15 |
+
A medical-focused chatbot that supports patient evaluations, structured conversation management, and optional Google Drive backups.
|
| 16 |
|
| 17 |
## Prerequisites
|
| 18 |
- Python 3.x
|
|
|
|
| 43 |
|
| 44 |
## Usage
|
| 45 |
- Open Chrome and visit `http://localhost:7860` to interact with the chatbot.
|
| 46 |
+
|
| 47 |
+
## Google Drive Auto-Backup
|
| 48 |
+
|
| 49 |
+
The chatbot can automatically push evaluation data to Google Drive so the latest files are available when deploying to Hugging Face.
|
| 50 |
+
|
| 51 |
+
### Storage Layout
|
| 52 |
+
|
| 53 |
+
1. **Patient evaluations** (`patient_evaluations/`)
|
| 54 |
+
- Synced to the `Patient_Evaluations` folder in Drive
|
| 55 |
+
- Includes per-evaluation JSON files plus the master CSV summary
|
| 56 |
+
|
| 57 |
+
2. **Conversation logs** (`user_data/`)
|
| 58 |
+
- Synced to the `Chatbot_Conversations` folder in Drive
|
| 59 |
+
- Includes conversation transcripts and memory graphs
|
| 60 |
+
|
| 61 |
+
### Configuration Options (choose one)
|
| 62 |
+
|
| 63 |
+
#### ⭐ Option 1: Service Account (recommended)
|
| 64 |
+
|
| 65 |
+
Use this if you see an `invalid_client` error or want a hands-off setup.
|
| 66 |
+
|
| 67 |
+
1. Create a Service Account in Google Cloud Console and download the JSON key
|
| 68 |
+
2. Share your destination Drive folder with the Service Account email
|
| 69 |
+
3. Update `google_drive_sync.py`:
|
| 70 |
+
```python
|
| 71 |
+
SERVICE_ACCOUNT_FILE = "service-account-key.json"
|
| 72 |
+
```
|
| 73 |
+
|
| 74 |
+
**Full walkthrough (≈5 minutes):** see `QUICK_SETUP.md`
|
| 75 |
+
|
| 76 |
+
#### Option 2: Refresh Token (requires an OAuth client)
|
| 77 |
+
|
| 78 |
+
1. Generate a refresh token:
|
| 79 |
+
```bash
|
| 80 |
+
python get_refresh_token.py
|
| 81 |
+
```
|
| 82 |
+
2. If you hit `invalid_client`, create a new OAuth client (see `QUICK_SETUP.md`)
|
| 83 |
+
3. Complete the browser authentication flow
|
| 84 |
+
4. Copy the printed `refresh_token`
|
| 85 |
+
5. Update `google_drive_sync.py`:
|
| 86 |
+
```python
|
| 87 |
+
REFRESH_TOKEN = "your_refresh_token"
|
| 88 |
+
```
|
| 89 |
+
|
| 90 |
+
See `google_drive_setup_guide.md` or `QUICK_SETUP.md` for detailed steps.
|
| 91 |
+
|
| 92 |
+
#### Option 3: Interactive OAuth (manual in UI)
|
| 93 |
+
|
| 94 |
+
1. Click **“Login to Google Drive”** inside the Gradio interface
|
| 95 |
+
2. Complete the browser authentication
|
| 96 |
+
3. Future saves will automatically sync to Drive
|
| 97 |
+
|
| 98 |
+
### Notes
|
| 99 |
+
|
| 100 |
+
- Without authentication, all files remain in local storage
|
| 101 |
+
- Upload failures are silent but local saves always succeed
|
| 102 |
+
- Only your own Drive account receives files; no shared storage is involved
|
| 103 |
+
- **Security:** never commit credentials or tokens into the repo
|
chatgpt.py
CHANGED
|
@@ -277,6 +277,18 @@ def save_patient_evaluation(patient_id, patient_input, ai_summary, rating, feedb
|
|
| 277 |
len(sentence_comments) if sentence_comments else 0
|
| 278 |
])
|
| 279 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 280 |
return f"Patient evaluation saved successfully at {timestamp}"
|
| 281 |
|
| 282 |
def submit_patient_evaluation(patient_id, patient_input, ai_summary, overall_rating,
|
|
@@ -1334,11 +1346,22 @@ with gr.Blocks(css=css) as app:
|
|
| 1334 |
print("3. Deploy: gradio deploy")
|
| 1335 |
print("4. This will give you a permanent https://yourname-appname.hf.space URL")
|
| 1336 |
|
| 1337 |
-
#
|
| 1338 |
-
|
| 1339 |
-
|
| 1340 |
-
|
| 1341 |
-
|
| 1342 |
-
|
| 1343 |
-
|
| 1344 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 277 |
len(sentence_comments) if sentence_comments else 0
|
| 278 |
])
|
| 279 |
|
| 280 |
+
# Auto-upload to Google Drive if authenticated
|
| 281 |
+
try:
|
| 282 |
+
from google_drive_sync import auto_upload_to_drive
|
| 283 |
+
# Upload JSON file
|
| 284 |
+
auto_upload_to_drive(eval_file, folder_name="Patient_Evaluations")
|
| 285 |
+
# Upload CSV file (only if it was just created, to avoid duplicates)
|
| 286 |
+
if not file_exists:
|
| 287 |
+
auto_upload_to_drive(csv_file, folder_name="Patient_Evaluations")
|
| 288 |
+
except Exception as e:
|
| 289 |
+
# Fail silently if Google Drive upload fails
|
| 290 |
+
pass
|
| 291 |
+
|
| 292 |
return f"Patient evaluation saved successfully at {timestamp}"
|
| 293 |
|
| 294 |
def submit_patient_evaluation(patient_id, patient_input, ai_summary, overall_rating,
|
|
|
|
| 1346 |
print("3. Deploy: gradio deploy")
|
| 1347 |
print("4. This will give you a permanent https://yourname-appname.hf.space URL")
|
| 1348 |
|
| 1349 |
+
# Check if running on Hugging Face Spaces
|
| 1350 |
+
hf_space = os.getenv("SPACE_ID") is not None
|
| 1351 |
+
|
| 1352 |
+
if hf_space:
|
| 1353 |
+
# Running on Hugging Face Spaces
|
| 1354 |
+
app.launch(
|
| 1355 |
+
server_name="0.0.0.0",
|
| 1356 |
+
server_port=7860,
|
| 1357 |
+
show_error=True
|
| 1358 |
+
)
|
| 1359 |
+
else:
|
| 1360 |
+
# Running locally
|
| 1361 |
+
app.launch(
|
| 1362 |
+
share=True,
|
| 1363 |
+
max_threads=10,
|
| 1364 |
+
server_name="0.0.0.0", # Allow external connections
|
| 1365 |
+
server_port=7860,
|
| 1366 |
+
show_error=True
|
| 1367 |
+
)
|
deploy_git.sh
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/bash
|
| 2 |
+
|
| 3 |
+
# Git-based deployment to Hugging Face Spaces
|
| 4 |
+
|
| 5 |
+
echo "🚀 Chatbot Mimic Notes - Git deployment to Hugging Face"
|
| 6 |
+
echo "======================================================="
|
| 7 |
+
echo ""
|
| 8 |
+
|
| 9 |
+
# Check login status
|
| 10 |
+
if ! huggingface-cli whoami &> /dev/null; then
|
| 11 |
+
echo "❌ Not logged into Hugging Face"
|
| 12 |
+
echo "Run: huggingface-cli login"
|
| 13 |
+
exit 1
|
| 14 |
+
fi
|
| 15 |
+
|
| 16 |
+
USERNAME=$(huggingface-cli whoami | head -n 1)
|
| 17 |
+
echo "✅ Logged in as: $USERNAME"
|
| 18 |
+
echo ""
|
| 19 |
+
|
| 20 |
+
# Prompt for Space name
|
| 21 |
+
read -p "Enter Space name (e.g., chatbot-mimic-notes): " SPACE_NAME
|
| 22 |
+
|
| 23 |
+
if [ -z "$SPACE_NAME" ]; then
|
| 24 |
+
echo "❌ Space name cannot be empty"
|
| 25 |
+
exit 1
|
| 26 |
+
fi
|
| 27 |
+
|
| 28 |
+
FULL_SPACE_NAME="${USERNAME}/${SPACE_NAME}"
|
| 29 |
+
SPACE_URL="https://huggingface.co/spaces/${FULL_SPACE_NAME}"
|
| 30 |
+
|
| 31 |
+
echo ""
|
| 32 |
+
echo "📦 Preparing deployment to: $FULL_SPACE_NAME"
|
| 33 |
+
echo ""
|
| 34 |
+
|
| 35 |
+
# Check if Space exists
|
| 36 |
+
if huggingface-cli repo exists "$FULL_SPACE_NAME" &> /dev/null; then
|
| 37 |
+
echo "✅ Space already exists: $SPACE_URL"
|
| 38 |
+
echo " Updating existing Space"
|
| 39 |
+
else
|
| 40 |
+
echo "🆕 Creating a new Space..."
|
| 41 |
+
huggingface-cli repo create "$SPACE_NAME" --type space --sdk gradio
|
| 42 |
+
if [ $? -ne 0 ]; then
|
| 43 |
+
echo "❌ Failed to create Space"
|
| 44 |
+
exit 1
|
| 45 |
+
fi
|
| 46 |
+
echo "✅ Space created successfully"
|
| 47 |
+
fi
|
| 48 |
+
|
| 49 |
+
echo ""
|
| 50 |
+
echo "📤 Preparing Git push..."
|
| 51 |
+
echo ""
|
| 52 |
+
|
| 53 |
+
# Create temp directory
|
| 54 |
+
TEMP_DIR=$(mktemp -d)
|
| 55 |
+
echo "Temp directory: $TEMP_DIR"
|
| 56 |
+
|
| 57 |
+
# Clone Space repo
|
| 58 |
+
echo "Cloning Space..."
|
| 59 |
+
git clone "$SPACE_URL.git" "$TEMP_DIR/space" 2>/dev/null || {
|
| 60 |
+
echo "Clone failed, initializing empty repo..."
|
| 61 |
+
mkdir -p "$TEMP_DIR/space"
|
| 62 |
+
cd "$TEMP_DIR/space"
|
| 63 |
+
git init
|
| 64 |
+
git remote add origin "$SPACE_URL.git"
|
| 65 |
+
}
|
| 66 |
+
|
| 67 |
+
cd "$TEMP_DIR/space"
|
| 68 |
+
|
| 69 |
+
# Copy project files
|
| 70 |
+
echo "Copying files..."
|
| 71 |
+
cp -r /Users/liuzijie/Desktop/chatbot-mimic-notes/chatgpt.py .
|
| 72 |
+
cp -r /Users/liuzijie/Desktop/chatbot-mimic-notes/README.md .
|
| 73 |
+
cp -r /Users/liuzijie/Desktop/chatbot-mimic-notes/requirements.txt .
|
| 74 |
+
cp -r /Users/liuzijie/Desktop/chatbot-mimic-notes/src ./src 2>/dev/null || true
|
| 75 |
+
cp -r /Users/liuzijie/Desktop/chatbot-mimic-notes/google_drive_sync.py . 2>/dev/null || true
|
| 76 |
+
|
| 77 |
+
# Remove sensitive files
|
| 78 |
+
rm -f service-account-key.json
|
| 79 |
+
rm -rf user_tokens/
|
| 80 |
+
|
| 81 |
+
# Commit & push
|
| 82 |
+
echo "Committing changes..."
|
| 83 |
+
git add .
|
| 84 |
+
git commit -m "Deploy chatbot application" || echo "No changes to commit"
|
| 85 |
+
git push origin main || git push origin master
|
| 86 |
+
|
| 87 |
+
echo ""
|
| 88 |
+
echo "✅ Deployment finished!"
|
| 89 |
+
echo "🌐 Space URL: $SPACE_URL"
|
| 90 |
+
echo ""
|
| 91 |
+
echo "💡 Notes:"
|
| 92 |
+
echo " - First build takes 2–5 minutes"
|
| 93 |
+
echo " - Configure Google Drive secrets via Space Settings > Repository secrets"
|
| 94 |
+
echo " - Add secret: GOOGLE_SERVICE_ACCOUNT_JSON"
|
| 95 |
+
|
| 96 |
+
# Cleanup
|
| 97 |
+
rm -rf "$TEMP_DIR"
|
| 98 |
+
|
deploy_hf.sh
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/bash
|
| 2 |
+
|
| 3 |
+
# Quick deployment script for Hugging Face Spaces
|
| 4 |
+
|
| 5 |
+
echo "🚀 Chatbot Mimic Notes - Hugging Face deployment script"
|
| 6 |
+
echo "======================================================="
|
| 7 |
+
echo ""
|
| 8 |
+
|
| 9 |
+
# Check login status
|
| 10 |
+
if ! huggingface-cli whoami &> /dev/null; then
|
| 11 |
+
echo "❌ Not logged into Hugging Face"
|
| 12 |
+
echo "Run: huggingface-cli login"
|
| 13 |
+
exit 1
|
| 14 |
+
fi
|
| 15 |
+
|
| 16 |
+
echo "✅ Logged into Hugging Face"
|
| 17 |
+
USERNAME=$(huggingface-cli whoami | head -n 1)
|
| 18 |
+
echo " User: $USERNAME"
|
| 19 |
+
echo ""
|
| 20 |
+
|
| 21 |
+
# Prompt for Space name
|
| 22 |
+
read -p "Enter Space name (e.g., chatbot-mimic-notes): " SPACE_NAME
|
| 23 |
+
|
| 24 |
+
if [ -z "$SPACE_NAME" ]; then
|
| 25 |
+
echo "❌ Space name cannot be empty"
|
| 26 |
+
exit 1
|
| 27 |
+
fi
|
| 28 |
+
|
| 29 |
+
FULL_SPACE_NAME="${USERNAME}/${SPACE_NAME}"
|
| 30 |
+
|
| 31 |
+
echo ""
|
| 32 |
+
echo "📦 Preparing deployment to: $FULL_SPACE_NAME"
|
| 33 |
+
echo ""
|
| 34 |
+
|
| 35 |
+
# Check existing Space
|
| 36 |
+
if huggingface-cli repo exists "$FULL_SPACE_NAME" &> /dev/null; then
|
| 37 |
+
echo "⚠️ Space already exists; update in place?"
|
| 38 |
+
read -p "Continue? (y/n): " -n 1 -r
|
| 39 |
+
echo
|
| 40 |
+
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
| 41 |
+
exit 1
|
| 42 |
+
fi
|
| 43 |
+
else
|
| 44 |
+
echo "🆕 Creating a new Space..."
|
| 45 |
+
huggingface-cli repo create "$SPACE_NAME" --type space --sdk gradio
|
| 46 |
+
fi
|
| 47 |
+
|
| 48 |
+
echo ""
|
| 49 |
+
echo "📤 Starting deployment..."
|
| 50 |
+
echo ""
|
| 51 |
+
|
| 52 |
+
# Use gradio CLI
|
| 53 |
+
gradio deploy --space "$FULL_SPACE_NAME" --app-file chatgpt.py
|
| 54 |
+
|
| 55 |
+
echo ""
|
| 56 |
+
echo "✅ Deployment finished!"
|
| 57 |
+
echo "🌐 URL: https://huggingface.co/spaces/$FULL_SPACE_NAME"
|
| 58 |
+
echo ""
|
| 59 |
+
echo "💡 Tips:"
|
| 60 |
+
echo " - First build takes 2–5 minutes"
|
| 61 |
+
echo " - Configure Google Drive secrets in Space Settings"
|
| 62 |
+
echo " - See HUGGINGFACE_DEPLOY.md for full details"
|
| 63 |
+
|
get_refresh_token.py
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""
|
| 3 |
+
Helper script for retrieving a Google Drive refresh token.
|
| 4 |
+
|
| 5 |
+
Run it once, finish the OAuth flow, then copy the printed token into
|
| 6 |
+
REFRESH_TOKEN inside google_drive_sync.py.
|
| 7 |
+
|
| 8 |
+
If you hit an invalid_client error, consider switching to the Service
|
| 9 |
+
Account approach, which is more reliable.
|
| 10 |
+
"""
|
| 11 |
+
|
| 12 |
+
from google_drive_sync import get_refresh_token
|
| 13 |
+
|
| 14 |
+
if __name__ == "__main__":
|
| 15 |
+
print("="*60)
|
| 16 |
+
print("Google Drive Refresh Token Helper")
|
| 17 |
+
print("="*60)
|
| 18 |
+
print("\n⚠️ If you see 'invalid_client', the OAuth client is misconfigured.")
|
| 19 |
+
print(" Use the Service Account method instead (no OAuth required).")
|
| 20 |
+
print(" See google_drive_setup_guide.md for the full walkthrough.\n")
|
| 21 |
+
print("A browser window will open so you can complete Google sign-in...\n")
|
| 22 |
+
|
| 23 |
+
refresh_token = get_refresh_token()
|
| 24 |
+
|
| 25 |
+
if refresh_token:
|
| 26 |
+
print("\n✅ Success! Copy the refresh_token above into google_drive_sync.py.")
|
| 27 |
+
else:
|
| 28 |
+
print("\n" + "="*60)
|
| 29 |
+
print("❌ Failed to get refresh_token")
|
| 30 |
+
print("="*60)
|
| 31 |
+
print("\nPossible fixes:")
|
| 32 |
+
print("1. Use a Service Account (recommended):")
|
| 33 |
+
print(" - See option B in google_drive_setup_guide.md")
|
| 34 |
+
print(" - Create a Service Account and download the JSON key")
|
| 35 |
+
print(" - Set SERVICE_ACCOUNT_FILE inside google_drive_sync.py")
|
| 36 |
+
print("\n2. Create a new OAuth client:")
|
| 37 |
+
print(" - Visit https://console.cloud.google.com/")
|
| 38 |
+
print(" - Create a new OAuth 2.0 client ID")
|
| 39 |
+
print(" - Update CLIENT_ID and CLIENT_SECRET in google_drive_sync.py")
|
| 40 |
+
print("="*60)
|
| 41 |
+
|
google_drive_setup_guide.md
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Google Drive Hard-Coded Auth Guide
|
| 2 |
+
|
| 3 |
+
Use this guide to enable automatic Drive uploads without running OAuth each time.
|
| 4 |
+
|
| 5 |
+
## Option 1: Refresh Token (recommended, simple)
|
| 6 |
+
|
| 7 |
+
### Step 1: Obtain a refresh token
|
| 8 |
+
|
| 9 |
+
1. In a Python shell run:
|
| 10 |
+
|
| 11 |
+
```python
|
| 12 |
+
from google_drive_sync import get_refresh_token
|
| 13 |
+
refresh_token = get_refresh_token()
|
| 14 |
+
```
|
| 15 |
+
|
| 16 |
+
2. A browser window opens for Google sign-in
|
| 17 |
+
3. The terminal prints your `refresh_token`, e.g.
|
| 18 |
+
```
|
| 19 |
+
REFRESH_TOKEN = "1//0gxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
| 20 |
+
```
|
| 21 |
+
|
| 22 |
+
### Step 2: Configure the refresh token
|
| 23 |
+
|
| 24 |
+
Open `google_drive_sync.py` and set:
|
| 25 |
+
|
| 26 |
+
```python
|
| 27 |
+
REFRESH_TOKEN = None # place your refresh token here
|
| 28 |
+
```
|
| 29 |
+
|
| 30 |
+
Replace `None` with your token:
|
| 31 |
+
|
| 32 |
+
```python
|
| 33 |
+
REFRESH_TOKEN = "1//0gxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" # your refresh token
|
| 34 |
+
```
|
| 35 |
+
|
| 36 |
+
### Step 3: Done
|
| 37 |
+
|
| 38 |
+
Save the file; future uploads happen automatically without another login.
|
| 39 |
+
|
| 40 |
+
---
|
| 41 |
+
|
| 42 |
+
## Option 2: Service Account (more secure, production-friendly)
|
| 43 |
+
|
| 44 |
+
### Step 1: Create the Service Account
|
| 45 |
+
|
| 46 |
+
1. Visit [Google Cloud Console](https://console.cloud.google.com/)
|
| 47 |
+
2. Select or create a project
|
| 48 |
+
3. Enable the Google Drive API
|
| 49 |
+
4. Go to “IAM & Admin” → “Service Accounts”
|
| 50 |
+
5. Click “Create Service Account”
|
| 51 |
+
6. Provide a name/description, click “Create and Continue”
|
| 52 |
+
7. Grant the “Editor” role, then “Continue” → “Done”
|
| 53 |
+
|
| 54 |
+
### Step 2: Create and download the key
|
| 55 |
+
|
| 56 |
+
1. Open the Service Account
|
| 57 |
+
2. Go to the “Keys” tab
|
| 58 |
+
3. Click “Add Key” → “Create new key”
|
| 59 |
+
4. Choose JSON → “Create”
|
| 60 |
+
5. Save the JSON into your project directory (e.g., `service-account-key.json`)
|
| 61 |
+
|
| 62 |
+
### Step 3: Share the Drive folder with the Service Account
|
| 63 |
+
|
| 64 |
+
1. Create a folder in Drive (e.g., “Chatbot_Data”)
|
| 65 |
+
2. Right-click → “Share”
|
| 66 |
+
3. In the JSON file find `client_email` (looks like `xxx@xxx.iam.gserviceaccount.com`)
|
| 67 |
+
4. Add that email to the folder with “Editor” access
|
| 68 |
+
|
| 69 |
+
### Step 4: Point the code to the Service Account file
|
| 70 |
+
|
| 71 |
+
Set this in `google_drive_sync.py`:
|
| 72 |
+
|
| 73 |
+
```python
|
| 74 |
+
SERVICE_ACCOUNT_FILE = None # e.g. "path/to/service-account-key.json"
|
| 75 |
+
```
|
| 76 |
+
|
| 77 |
+
Replace `None` with your JSON path:
|
| 78 |
+
|
| 79 |
+
```python
|
| 80 |
+
SERVICE_ACCOUNT_FILE = "service-account-key.json" # your Service Account JSON path
|
| 81 |
+
```
|
| 82 |
+
|
| 83 |
+
### Step 5: Done
|
| 84 |
+
|
| 85 |
+
All data now syncs to the folder you shared with the Service Account!
|
| 86 |
+
|
| 87 |
+
---
|
| 88 |
+
|
| 89 |
+
## Verify the setup
|
| 90 |
+
|
| 91 |
+
Run the app and confirm uploads reach Drive. If not, check:
|
| 92 |
+
|
| 93 |
+
1. Refresh token or Service Account path is correct
|
| 94 |
+
2. Network connectivity
|
| 95 |
+
3. Google Drive API is enabled
|
| 96 |
+
4. Service Account has access to the folder
|
| 97 |
+
|
| 98 |
+
## Notes
|
| 99 |
+
|
| 100 |
+
⚠️ **Security reminders**
|
| 101 |
+
- Never commit credentials to public repos
|
| 102 |
+
- Add `google_drive_sync.py` or secrets to `.gitignore` if needed
|
| 103 |
+
- Protect the Service Account JSON carefully
|
| 104 |
+
|
| 105 |
+
## Troubleshooting
|
| 106 |
+
|
| 107 |
+
### Refresh token expired
|
| 108 |
+
Re-run `get_refresh_token()` to obtain a new one.
|
| 109 |
+
|
| 110 |
+
### Service Account can’t access the folder
|
| 111 |
+
Ensure the Service Account email was invited with the proper permission.
|
| 112 |
+
|
| 113 |
+
### Authentication failure
|
| 114 |
+
1. Double-check `CLIENT_ID` / `CLIENT_SECRET`
|
| 115 |
+
2. Confirm the Drive API is enabled
|
| 116 |
+
3. Verify your network connection
|
| 117 |
+
|
google_drive_sync.py
CHANGED
|
@@ -5,6 +5,7 @@ from datetime import datetime
|
|
| 5 |
|
| 6 |
from google.auth.transport.requests import Request
|
| 7 |
from google.oauth2.credentials import Credentials
|
|
|
|
| 8 |
from google_auth_oauthlib.flow import InstalledAppFlow
|
| 9 |
from googleapiclient.discovery import build
|
| 10 |
from googleapiclient.http import MediaFileUpload
|
|
@@ -12,16 +13,33 @@ from googleapiclient.http import MediaFileUpload
|
|
| 12 |
# Google Drive API scopes
|
| 13 |
SCOPES = ['https://www.googleapis.com/auth/drive.file']
|
| 14 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
# Real OAuth 2.0 configuration - Public client credentials for this app
|
| 16 |
# These are safe to include in public code (they're meant to be public)
|
| 17 |
CLIENT_CONFIG = {
|
| 18 |
"installed": {
|
| 19 |
-
"client_id":
|
| 20 |
"project_id": "patient-eval-app-439620",
|
| 21 |
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
|
| 22 |
"token_uri": "https://oauth2.googleapis.com/token",
|
| 23 |
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
|
| 24 |
-
"client_secret":
|
| 25 |
"redirect_uris": ["http://localhost"]
|
| 26 |
}
|
| 27 |
}
|
|
@@ -55,10 +73,56 @@ class GoogleDriveSync:
|
|
| 55 |
return False, f"Authentication error: {str(e)}"
|
| 56 |
|
| 57 |
def authenticate(self):
|
| 58 |
-
"""Authenticate with existing token or start new flow"""
|
| 59 |
creds = None
|
| 60 |
|
| 61 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 62 |
if os.path.exists(self.token_file):
|
| 63 |
try:
|
| 64 |
with open(self.token_file, 'rb') as token:
|
|
@@ -259,4 +323,60 @@ def check_user_authentication(user_id="default"):
|
|
| 259 |
"""Check if user is already authenticated"""
|
| 260 |
sync = get_user_sync(user_id)
|
| 261 |
success, message = sync.authenticate()
|
| 262 |
-
return success, message
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
|
| 6 |
from google.auth.transport.requests import Request
|
| 7 |
from google.oauth2.credentials import Credentials
|
| 8 |
+
from google.oauth2 import service_account
|
| 9 |
from google_auth_oauthlib.flow import InstalledAppFlow
|
| 10 |
from googleapiclient.discovery import build
|
| 11 |
from googleapiclient.http import MediaFileUpload
|
|
|
|
| 13 |
# Google Drive API scopes
|
| 14 |
SCOPES = ['https://www.googleapis.com/auth/drive.file']
|
| 15 |
|
| 16 |
+
# ============================================================================
|
| 17 |
+
# Hard-coded Google Drive auth configuration
|
| 18 |
+
# Option 1: Service Account (recommended)
|
| 19 |
+
# Option 2: Refresh Token
|
| 20 |
+
# ============================================================================
|
| 21 |
+
|
| 22 |
+
# Option 1: Service Account JSON file (env-var friendly for Spaces)
|
| 23 |
+
SERVICE_ACCOUNT_FILE = os.getenv("GOOGLE_SERVICE_ACCOUNT_FILE", None) # e.g. "path/to/service-account-key.json"
|
| 24 |
+
|
| 25 |
+
# Option 2: Refresh Token (requires OAuth flow once)
|
| 26 |
+
REFRESH_TOKEN = os.getenv("GOOGLE_REFRESH_TOKEN", None)
|
| 27 |
+
CLIENT_ID = os.getenv("GOOGLE_CLIENT_ID")
|
| 28 |
+
CLIENT_SECRET = os.getenv("GOOGLE_CLIENT_SECRET")
|
| 29 |
+
|
| 30 |
+
# Fallback: interactive OAuth
|
| 31 |
+
USE_HARDCODED_AUTH = SERVICE_ACCOUNT_FILE is not None or REFRESH_TOKEN is not None
|
| 32 |
+
|
| 33 |
# Real OAuth 2.0 configuration - Public client credentials for this app
|
| 34 |
# These are safe to include in public code (they're meant to be public)
|
| 35 |
CLIENT_CONFIG = {
|
| 36 |
"installed": {
|
| 37 |
+
"client_id": CLIENT_ID,
|
| 38 |
"project_id": "patient-eval-app-439620",
|
| 39 |
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
|
| 40 |
"token_uri": "https://oauth2.googleapis.com/token",
|
| 41 |
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
|
| 42 |
+
"client_secret": CLIENT_SECRET,
|
| 43 |
"redirect_uris": ["http://localhost"]
|
| 44 |
}
|
| 45 |
}
|
|
|
|
| 73 |
return False, f"Authentication error: {str(e)}"
|
| 74 |
|
| 75 |
def authenticate(self):
|
| 76 |
+
"""Authenticate with hardcoded credentials, existing token, or start new flow"""
|
| 77 |
creds = None
|
| 78 |
|
| 79 |
+
# Option 1: Service Account (supports env JSON for Spaces)
|
| 80 |
+
service_account_json = os.getenv("GOOGLE_SERVICE_ACCOUNT_JSON")
|
| 81 |
+
if service_account_json:
|
| 82 |
+
try:
|
| 83 |
+
import tempfile
|
| 84 |
+
import json as json_lib
|
| 85 |
+
# Persist JSON string to a temporary file
|
| 86 |
+
with tempfile.NamedTemporaryFile(mode='w', suffix='.json', delete=False) as f:
|
| 87 |
+
json_lib.dump(json_lib.loads(service_account_json), f)
|
| 88 |
+
temp_file = f.name
|
| 89 |
+
creds = service_account.Credentials.from_service_account_file(
|
| 90 |
+
temp_file, scopes=SCOPES)
|
| 91 |
+
self.service = build('drive', 'v3', credentials=creds)
|
| 92 |
+
os.unlink(temp_file) # remove temp file
|
| 93 |
+
return True, "Authenticated with Service Account (from env)"
|
| 94 |
+
except Exception as e:
|
| 95 |
+
return False, f"Service Account authentication error: {str(e)}"
|
| 96 |
+
|
| 97 |
+
if SERVICE_ACCOUNT_FILE and os.path.exists(SERVICE_ACCOUNT_FILE):
|
| 98 |
+
try:
|
| 99 |
+
creds = service_account.Credentials.from_service_account_file(
|
| 100 |
+
SERVICE_ACCOUNT_FILE, scopes=SCOPES)
|
| 101 |
+
self.service = build('drive', 'v3', credentials=creds)
|
| 102 |
+
return True, "Authenticated with Service Account"
|
| 103 |
+
except Exception as e:
|
| 104 |
+
return False, f"Service Account authentication error: {str(e)}"
|
| 105 |
+
|
| 106 |
+
# Option 2: hard-coded refresh token
|
| 107 |
+
if REFRESH_TOKEN:
|
| 108 |
+
if not CLIENT_ID or not CLIENT_SECRET:
|
| 109 |
+
return False, "Refresh token provided but GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET are missing."
|
| 110 |
+
try:
|
| 111 |
+
creds = Credentials(
|
| 112 |
+
token=None,
|
| 113 |
+
refresh_token=REFRESH_TOKEN,
|
| 114 |
+
token_uri="https://oauth2.googleapis.com/token",
|
| 115 |
+
client_id=CLIENT_ID,
|
| 116 |
+
client_secret=CLIENT_SECRET
|
| 117 |
+
)
|
| 118 |
+
# Refresh to obtain a fresh access token
|
| 119 |
+
creds.refresh(Request())
|
| 120 |
+
self.service = build('drive', 'v3', credentials=creds)
|
| 121 |
+
return True, "Authenticated with Refresh Token"
|
| 122 |
+
except Exception as e:
|
| 123 |
+
return False, f"Refresh Token authentication error: {str(e)}"
|
| 124 |
+
|
| 125 |
+
# Option 3: previously saved token file
|
| 126 |
if os.path.exists(self.token_file):
|
| 127 |
try:
|
| 128 |
with open(self.token_file, 'rb') as token:
|
|
|
|
| 323 |
"""Check if user is already authenticated"""
|
| 324 |
sync = get_user_sync(user_id)
|
| 325 |
success, message = sync.authenticate()
|
| 326 |
+
return success, message
|
| 327 |
+
|
| 328 |
+
def get_refresh_token():
|
| 329 |
+
"""
|
| 330 |
+
Helper: run once to fetch a refresh token for the hard-coded config.
|
| 331 |
+
Complete the OAuth flow, copy the printed token into REFRESH_TOKEN.
|
| 332 |
+
"""
|
| 333 |
+
try:
|
| 334 |
+
flow = InstalledAppFlow.from_client_config(CLIENT_CONFIG, SCOPES)
|
| 335 |
+
creds = flow.run_local_server(port=0, open_browser=True)
|
| 336 |
+
|
| 337 |
+
if creds and creds.refresh_token:
|
| 338 |
+
print("\n" + "="*60)
|
| 339 |
+
print("✅ Refresh token retrieved!")
|
| 340 |
+
print("="*60)
|
| 341 |
+
print(f"\nPaste the following refresh_token into REFRESH_TOKEN:\n")
|
| 342 |
+
print(f"REFRESH_TOKEN = \"{creds.refresh_token}\"")
|
| 343 |
+
print("\n" + "="*60 + "\n")
|
| 344 |
+
return creds.refresh_token
|
| 345 |
+
else:
|
| 346 |
+
print("❌ Could not obtain refresh_token. Please retry.")
|
| 347 |
+
return None
|
| 348 |
+
except Exception as e:
|
| 349 |
+
print(f"❌ Error retrieving refresh_token: {str(e)}")
|
| 350 |
+
return None
|
| 351 |
+
|
| 352 |
+
def auto_upload_to_drive(file_path, user_id="default", folder_name="Chatbot_Data"):
|
| 353 |
+
"""
|
| 354 |
+
Automatically upload a file to Google Drive if user is authenticated.
|
| 355 |
+
Returns (success, message) tuple. If not authenticated, returns (False, None) silently.
|
| 356 |
+
This function fails silently to not interrupt normal operation.
|
| 357 |
+
"""
|
| 358 |
+
try:
|
| 359 |
+
sync = get_user_sync(user_id)
|
| 360 |
+
|
| 361 |
+
# Check authentication (uses hard-coded creds if configured)
|
| 362 |
+
success, message = sync.authenticate()
|
| 363 |
+
if not success:
|
| 364 |
+
# Log once when hard-coded auth was expected but failed
|
| 365 |
+
if USE_HARDCODED_AUTH:
|
| 366 |
+
print(f"⚠️ Google Drive authentication failed: {message}")
|
| 367 |
+
return False, None # Not authenticated, fail silently
|
| 368 |
+
|
| 369 |
+
# Create or get folder (use custom folder name for chatbot data)
|
| 370 |
+
folder_id, folder_message = sync.create_or_get_folder(folder_name)
|
| 371 |
+
if not folder_id:
|
| 372 |
+
return False, None # Fail silently if folder creation fails
|
| 373 |
+
|
| 374 |
+
# Upload file
|
| 375 |
+
success, result = sync.upload_file(file_path)
|
| 376 |
+
if success:
|
| 377 |
+
return True, f"✅ Auto-uploaded to Google Drive: {result.get('name', 'file')}"
|
| 378 |
+
else:
|
| 379 |
+
return False, None # Fail silently on upload error
|
| 380 |
+
except Exception as e:
|
| 381 |
+
# Fail silently if there's an error (e.g., network issue, import error)
|
| 382 |
+
return False, None
|
src/server.py
CHANGED
|
@@ -232,6 +232,20 @@ def configure_routes(app, args):
|
|
| 232 |
# save memory graph
|
| 233 |
server.doctor.memory_graph.save(local_memory_graph_file)
|
| 234 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 235 |
return jsonify({"message": "Current conversation and memory graph are saved!"}), 200
|
| 236 |
|
| 237 |
@app.route('/responses/doctor', methods=['POST'])
|
|
|
|
| 232 |
# save memory graph
|
| 233 |
server.doctor.memory_graph.save(local_memory_graph_file)
|
| 234 |
|
| 235 |
+
# Auto-upload to Google Drive if authenticated
|
| 236 |
+
try:
|
| 237 |
+
import sys
|
| 238 |
+
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
| 239 |
+
from google_drive_sync import auto_upload_to_drive
|
| 240 |
+
|
| 241 |
+
# Upload conversation file
|
| 242 |
+
auto_upload_to_drive(local_conv_file_path, user_id=username, folder_name="Chatbot_Conversations")
|
| 243 |
+
# Upload memory graph file
|
| 244 |
+
auto_upload_to_drive(local_memory_graph_file, user_id=username, folder_name="Chatbot_Conversations")
|
| 245 |
+
except Exception as e:
|
| 246 |
+
# Fail silently if Google Drive upload fails
|
| 247 |
+
print(f"Google Drive auto-upload failed (non-critical): {str(e)}")
|
| 248 |
+
|
| 249 |
return jsonify({"message": "Current conversation and memory graph are saved!"}), 200
|
| 250 |
|
| 251 |
@app.route('/responses/doctor', methods=['POST'])
|