mihimanshu commited on
Commit
8a19ce5
ยท
1 Parent(s): 8b0c3b9

fastapi hf deployment

Browse files
ai-experiments/hf_models/DEPLOYMENT_GUIDE.md ADDED
@@ -0,0 +1,245 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Deployment Guide: Hugging Face Spaces
2
+
3
+ This guide will help you deploy your Career Prep LLM Services to Hugging Face Spaces and test it with user prompts.
4
+
5
+ ## Table of Contents
6
+ 1. [Prerequisites](#prerequisites)
7
+ 2. [Best Deployment Methods](#best-deployment-methods)
8
+ 3. [Step-by-Step Deployment](#step-by-step-deployment)
9
+ 4. [Testing Your Deployment](#testing-your-deployment)
10
+ 5. [Troubleshooting](#troubleshooting)
11
+
12
+ ## Prerequisites
13
+
14
+ 1. **Hugging Face Account**
15
+ - Sign up at https://huggingface.co/join
16
+ - Verify your email
17
+
18
+ 2. **Hugging Face Access Token**
19
+ - Go to https://huggingface.co/settings/tokens
20
+ - Create a new token with "Write" permissions
21
+ - Save it securely (you'll need it for Git operations)
22
+
23
+ 3. **Git Repository**
24
+ - Your code should be in a Git repository (GitHub, GitLab, or Hugging Face's Git)
25
+ - Make sure all files are committed
26
+
27
+ 4. **Model Selection**
28
+ - Choose a model that fits your hardware budget
29
+ - See [Model Recommendations](#model-recommendations) below
30
+
31
+ ## Best Deployment Methods
32
+
33
+ ### Method 1: Docker SDK (Recommended for FastAPI)
34
+ โœ… **Best for**: FastAPI applications, custom dependencies, full control
35
+ - Uses Dockerfile for deployment
36
+ - Full control over environment
37
+ - Supports complex applications
38
+
39
+ ### Method 2: Gradio SDK
40
+ โŒ **Not recommended** for this project (FastAPI-based)
41
+
42
+ ### Method 3: Static SDK
43
+ โŒ **Not recommended** for this project (API service)
44
+
45
+ ## Step-by-Step Deployment
46
+
47
+ ### Step 1: Prepare Your Repository
48
+
49
+ 1. **Ensure all files are committed:**
50
+ ```bash
51
+ cd ai-experiments/hf_models
52
+ git status
53
+ git add .
54
+ git commit -m "Prepare for Hugging Face Spaces deployment"
55
+ ```
56
+
57
+ 2. **Verify key files exist:**
58
+ - โœ… `app.py` (main FastAPI application)
59
+ - โœ… `requirements.txt` (Python dependencies)
60
+ - โœ… `Dockerfile` (Docker configuration)
61
+ - โœ… `services/` directory (all service files)
62
+
63
+ ### Step 2: Create Hugging Face Space
64
+
65
+ 1. **Go to Hugging Face Spaces:**
66
+ - Visit https://huggingface.co/spaces
67
+ - Click **"Create new Space"**
68
+
69
+ 2. **Configure Space:**
70
+ - **Space name**: `career-prep-llm-services` (or your preferred name)
71
+ - **SDK**: Select **"Docker"**
72
+ - **Visibility**: Choose Public or Private
73
+ - **Hardware**:
74
+ - For small models (GPT-2, DialoGPT-small): `CPU basic`
75
+ - For medium models (DialoGPT-medium): `CPU upgrade` or `T4 small`
76
+ - For large models (Mistral-7B): `GPU` or `GPU small`
77
+ - Click **"Create Space"**
78
+
79
+ ### Step 3: Connect Git Repository
80
+
81
+ **Option A: Push to Hugging Face Git (Recommended)**
82
+
83
+ 1. **Add Hugging Face as remote:**
84
+ ```bash
85
+ cd ai-experiments/hf_models
86
+ git remote add hf https://huggingface.co/spaces/YOUR_USERNAME/YOUR_SPACE_NAME
87
+ # Replace YOUR_USERNAME and YOUR_SPACE_NAME with your actual values
88
+ ```
89
+
90
+ 2. **Push to Hugging Face:**
91
+ ```bash
92
+ git push hf main
93
+ # You'll be prompted for username and password (use your HF token as password)
94
+ ```
95
+
96
+ **Option B: Connect External Git Repository**
97
+
98
+ 1. In your Space settings, go to **"Repository"** tab
99
+ 2. Click **"Connect repository"**
100
+ 3. Select your Git provider (GitHub, GitLab, etc.)
101
+ 4. Authorize and select your repository
102
+ 5. Set the branch (usually `main` or `master`)
103
+
104
+ ### Step 4: Configure Environment Variables
105
+
106
+ 1. **Go to Space Settings:**
107
+ - Click on your Space
108
+ - Go to **"Settings"** tab
109
+ - Scroll to **"Environment variables"**
110
+
111
+ 2. **Add Required Variables:**
112
+ - `HF_MODEL_NAME`: Your model name (e.g., `gpt2`, `microsoft/DialoGPT-medium`, `mistralai/Mistral-7B-Instruct-v0.2`)
113
+ - `PORT`: `7860` (usually auto-set, but can specify)
114
+
115
+ 3. **Save Settings**
116
+
117
+ ### Step 5: Wait for Build
118
+
119
+ - Hugging Face will automatically build your Docker image
120
+ - This can take 5-15 minutes depending on model size
121
+ - Monitor progress in the **"Logs"** tab
122
+ - You'll see build logs and then runtime logs
123
+
124
+ ### Step 6: Verify Deployment
125
+
126
+ 1. **Check Health Endpoint:**
127
+ - Visit: `https://YOUR_USERNAME-YOUR_SPACE_NAME.hf.space/health`
128
+ - Should return: `{"status": "healthy", ...}`
129
+
130
+ 2. **Check Root Endpoint:**
131
+ - Visit: `https://YOUR_USERNAME-YOUR_SPACE_NAME.hf.space/`
132
+ - Should show service information
133
+
134
+ ## Testing Your Deployment
135
+
136
+ ### Quick Test with cURL
137
+
138
+ ```bash
139
+ # Health check
140
+ curl https://YOUR_USERNAME-YOUR_SPACE_NAME.hf.space/health
141
+
142
+ # Generic LLM test
143
+ curl -X POST https://YOUR_USERNAME-YOUR_SPACE_NAME.hf.space/api/v1/llm \
144
+ -H "Content-Type: application/json" \
145
+ -d '{
146
+ "prompt": "What are the top 5 skills for a data scientist?",
147
+ "max_tokens": 200,
148
+ "temperature": 0.7
149
+ }'
150
+ ```
151
+
152
+ ### Use the Test Script
153
+
154
+ See `test_deployment.py` for an interactive testing script.
155
+
156
+ ## Model Recommendations
157
+
158
+ ### Small Models (CPU Basic - Free Tier)
159
+ - `gpt2` - Fast, lightweight
160
+ - `microsoft/DialoGPT-small` - Conversational
161
+ - **Pros**: Fast startup, low cost
162
+ - **Cons**: Lower quality responses
163
+
164
+ ### Medium Models (CPU Upgrade / T4 Small)
165
+ - `microsoft/DialoGPT-medium` - Better quality
166
+ - `EleutherAI/gpt-neo-125M` - Good balance
167
+ - **Pros**: Better quality, reasonable speed
168
+ - **Cons**: Slower than small models
169
+
170
+ ### Large Models (GPU Required)
171
+ - `mistralai/Mistral-7B-Instruct-v0.2` - High quality
172
+ - `meta-llama/Llama-2-7b-chat-hf` - Excellent (requires request)
173
+ - **Pros**: Best quality responses
174
+ - **Cons**: Requires GPU, slower, more expensive
175
+
176
+ ### Recommended Starting Point
177
+ Start with `gpt2` or `microsoft/DialoGPT-medium` to test deployment, then upgrade to larger models if needed.
178
+
179
+ ## Hardware Selection Guide
180
+
181
+ | Model Size | Recommended Hardware | Cost |
182
+ |------------|---------------------|------|
183
+ | < 1B params | CPU basic | Free |
184
+ | 1-3B params | CPU upgrade / T4 small | Low |
185
+ | 3-7B params | T4 medium / GPU small | Medium |
186
+ | 7B+ params | GPU / GPU large | High |
187
+
188
+ ## Testing Best Practices
189
+
190
+ 1. **Start with Health Check**: Always verify `/health` first
191
+ 2. **Test Simple Prompts**: Use `/api/v1/llm` with simple prompts
192
+ 3. **Test Each Endpoint**: Verify all endpoints work
193
+ 4. **Monitor Logs**: Check Space logs for errors
194
+ 5. **Test with Real Data**: Use realistic user prompts
195
+ 6. **Load Testing**: Test with multiple concurrent requests (if needed)
196
+
197
+ ## Troubleshooting
198
+
199
+ ### Build Fails
200
+ - **Check Dockerfile**: Ensure it's correct
201
+ - **Check requirements.txt**: Verify all dependencies are listed
202
+ - **Check logs**: Look for specific error messages
203
+
204
+ ### Model Loading Fails
205
+ - **Check model name**: Verify `HF_MODEL_NAME` is correct
206
+ - **Check hardware**: Ensure hardware is sufficient for model size
207
+ - **Check logs**: Look for model loading errors
208
+
209
+ ### API Returns 500 Errors
210
+ - **Check logs**: Look for Python errors
211
+ - **Check model**: Ensure model loaded successfully
212
+ - **Check memory**: Large models may need more memory
213
+
214
+ ### Slow Responses
215
+ - **Model too large**: Consider smaller model
216
+ - **Hardware insufficient**: Upgrade hardware tier
217
+ - **First request slow**: Normal (model loads on first request)
218
+
219
+ ## Security Considerations
220
+
221
+ 1. **CORS**: Update CORS settings in `app.py` for production
222
+ 2. **Rate Limiting**: Consider adding rate limiting
223
+ 3. **Authentication**: Add API keys if needed
224
+ 4. **Input Validation**: Already handled by Pydantic models
225
+
226
+ ## Cost Optimization
227
+
228
+ 1. **Use appropriate hardware**: Don't over-provision
229
+ 2. **Choose right model**: Balance quality vs. cost
230
+ 3. **Monitor usage**: Track API calls and costs
231
+ 4. **Consider caching**: Cache common responses if possible
232
+
233
+ ## Next Steps
234
+
235
+ 1. โœ… Deploy to Hugging Face Spaces
236
+ 2. โœ… Test all endpoints
237
+ 3. โœ… Monitor performance
238
+ 4. โœ… Optimize model/hardware selection
239
+ 5. โœ… Set up monitoring/alerting (optional)
240
+
241
+ ## Support
242
+
243
+ - Hugging Face Spaces Docs: https://huggingface.co/docs/hub/spaces
244
+ - FastAPI Docs: https://fastapi.tiangolo.com/
245
+ - Transformers Docs: https://huggingface.co/docs/transformers
ai-experiments/hf_models/QUICK_START.md ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Quick Start: Deploy to Hugging Face Spaces
2
+
3
+ ## ๐Ÿš€ Fast Deployment (5 minutes)
4
+
5
+ ### 1. Prepare Your Code
6
+ ```bash
7
+ cd ai-experiments/hf_models
8
+ git add .
9
+ git commit -m "Ready for HF Spaces deployment"
10
+ ```
11
+
12
+ ### 2. Create Hugging Face Space
13
+ 1. Go to https://huggingface.co/spaces
14
+ 2. Click **"Create new Space"**
15
+ 3. Fill in:
16
+ - **Name**: `career-prep-llm-services`
17
+ - **SDK**: `Docker`
18
+ - **Hardware**: `CPU basic` (for testing) or `T4 small` (for better models)
19
+ - **Visibility**: Your choice
20
+
21
+ ### 3. Push Code to Hugging Face
22
+ ```bash
23
+ # Add HF as remote (replace YOUR_USERNAME and YOUR_SPACE_NAME)
24
+ git remote add hf https://huggingface.co/spaces/YOUR_USERNAME/YOUR_SPACE_NAME
25
+
26
+ # Push code
27
+ git push hf main
28
+ # Username: YOUR_USERNAME
29
+ # Password: YOUR_HF_TOKEN (get from https://huggingface.co/settings/tokens)
30
+ ```
31
+
32
+ ### 4. Configure Environment
33
+ 1. In Space settings โ†’ **Environment variables**
34
+ 2. Add: `HF_MODEL_NAME` = `gpt2` (or your preferred model)
35
+ 3. Save
36
+
37
+ ### 5. Wait for Build
38
+ - Check **Logs** tab
39
+ - Wait 5-15 minutes
40
+ - Look for "Application startup complete"
41
+
42
+ ### 6. Test It!
43
+ ```bash
44
+ # Run the test script
45
+ python test_deployment.py
46
+
47
+ # Or test manually
48
+ curl https://YOUR_USERNAME-YOUR_SPACE_NAME.hf.space/health
49
+ ```
50
+
51
+ ## ๐Ÿ“ Quick Test Commands
52
+
53
+ ### Health Check
54
+ ```bash
55
+ curl https://YOUR_USERNAME-YOUR_SPACE_NAME.hf.space/health
56
+ ```
57
+
58
+ ### Test LLM with Custom Prompt
59
+ ```bash
60
+ curl -X POST https://YOUR_USERNAME-YOUR_SPACE_NAME.hf.space/api/v1/llm \
61
+ -H "Content-Type: application/json" \
62
+ -d '{
63
+ "prompt": "What are the top 5 skills for a data scientist?",
64
+ "max_tokens": 300,
65
+ "temperature": 0.7
66
+ }'
67
+ ```
68
+
69
+ ## ๐ŸŽฏ Model Recommendations
70
+
71
+ | Use Case | Model | Hardware |
72
+ |----------|-------|----------|
73
+ | Quick testing | `gpt2` | CPU basic (free) |
74
+ | Better quality | `microsoft/DialoGPT-medium` | CPU upgrade / T4 small |
75
+ | Best quality | `mistralai/Mistral-7B-Instruct-v0.2` | GPU / GPU small |
76
+
77
+ ## โšก Common Issues
78
+
79
+ **Build fails?**
80
+ - Check Dockerfile exists
81
+ - Check requirements.txt is correct
82
+ - Check logs for specific errors
83
+
84
+ **Model won't load?**
85
+ - Verify `HF_MODEL_NAME` is correct
86
+ - Check hardware is sufficient
87
+ - Try smaller model first
88
+
89
+ **API returns 500?**
90
+ - Check Space logs
91
+ - Verify model loaded (check `/health`)
92
+ - Check memory usage
93
+
94
+ ## ๐Ÿ“š Full Documentation
95
+
96
+ See `DEPLOYMENT_GUIDE.md` for detailed instructions.
ai-experiments/hf_models/SETUP.md ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Setup Guide
2
+
3
+ ## Quick Setup
4
+
5
+ ### 1. Activate Virtual Environment
6
+
7
+ **On macOS/Linux:**
8
+ ```bash
9
+ cd ai-experiments/hf_models
10
+ source venv/bin/activate
11
+ ```
12
+
13
+ **On Windows:**
14
+ ```bash
15
+ cd ai-experiments/hf_models
16
+ venv\Scripts\activate
17
+ ```
18
+
19
+ ### 2. Install Dependencies
20
+
21
+ If dependencies aren't installed yet:
22
+ ```bash
23
+ pip install -r requirements.txt
24
+ ```
25
+
26
+ ### 3. Verify Installation
27
+
28
+ ```bash
29
+ python -c "import fastapi; print('FastAPI installed successfully!')"
30
+ ```
31
+
32
+ ### 4. Run the Application
33
+
34
+ ```bash
35
+ python app.py
36
+ ```
37
+
38
+ The server will start on `http://localhost:7860`
39
+
40
+ ## Common Issues
41
+
42
+ ### "No module named fastapi"
43
+
44
+ **Solution:** Make sure you've activated the virtual environment and installed dependencies:
45
+
46
+ ```bash
47
+ # Activate venv
48
+ source venv/bin/activate # macOS/Linux
49
+ # or
50
+ venv\Scripts\activate # Windows
51
+
52
+ # Install dependencies
53
+ pip install -r requirements.txt
54
+ ```
55
+
56
+ ### "Command not found: python"
57
+
58
+ **Solution:** Use `python3` instead:
59
+ ```bash
60
+ python3 app.py
61
+ ```
62
+
63
+ ### Virtual Environment Not Working
64
+
65
+ **Solution:** Create a new virtual environment:
66
+
67
+ ```bash
68
+ # Remove old venv (optional)
69
+ rm -rf venv
70
+
71
+ # Create new venv
72
+ python3 -m venv venv
73
+
74
+ # Activate it
75
+ source venv/bin/activate # macOS/Linux
76
+ # or
77
+ venv\Scripts\activate # Windows
78
+
79
+ # Install dependencies
80
+ pip install -r requirements.txt
81
+ ```
82
+
83
+ ## Testing
84
+
85
+ After setup, test the application:
86
+
87
+ ```bash
88
+ # In one terminal - start the server
89
+ python app.py
90
+
91
+ # In another terminal - run tests
92
+ python test_deployment.py
93
+ ```
94
+
95
+ ## Environment Variables
96
+
97
+ You can set environment variables before running:
98
+
99
+ ```bash
100
+ export HF_MODEL_NAME="gpt2" # macOS/Linux
101
+ # or
102
+ set HF_MODEL_NAME=gpt2 # Windows
103
+
104
+ python app.py
105
+ ```
106
+
107
+ ## Next Steps
108
+
109
+ 1. โœ… Setup complete
110
+ 2. โœ… Test locally with `python app.py`
111
+ 3. โœ… Run `python test_deployment.py` to test endpoints
112
+ 4. โœ… Deploy to Hugging Face Spaces (see `DEPLOYMENT_GUIDE.md`)
ai-experiments/hf_models/app.py CHANGED
@@ -14,6 +14,7 @@ from services.llm_service import LLMService
14
  from services.diagnosis_service import DiagnosisService
15
  from services.breakthrough_service import BreakthroughService
16
  from services.roadmap_service import RoadmapService
 
17
 
18
  app = FastAPI(
19
  title="Career Prep LLM Services",
 
14
  from services.diagnosis_service import DiagnosisService
15
  from services.breakthrough_service import BreakthroughService
16
  from services.roadmap_service import RoadmapService
17
+ from services.resume_service import ResumeService
18
 
19
  app = FastAPI(
20
  title="Career Prep LLM Services",
ai-experiments/hf_models/test_deployment.py ADDED
@@ -0,0 +1,375 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Interactive Test Script for Hugging Face Spaces Deployment
3
+ Tests all endpoints with user prompts
4
+ """
5
+
6
+ import requests
7
+ import json
8
+ import sys
9
+ from typing import Optional
10
+
11
+ # Configuration
12
+ DEFAULT_BASE_URL = "http://localhost:7860" # For local testing
13
+ HF_SPACE_URL_TEMPLATE = "https://{username}-{space_name}.hf.space"
14
+
15
+ def get_base_url() -> str:
16
+ """Get the base URL from user input or use default"""
17
+ print("\n" + "="*70)
18
+ print("Career Prep LLM Services - Deployment Test Script")
19
+ print("="*70)
20
+
21
+ print("\nSelect deployment to test:")
22
+ print("1. Local (http://localhost:7860)")
23
+ print("2. Hugging Face Space (enter URL)")
24
+ print("3. Custom URL")
25
+
26
+ choice = input("\nEnter choice (1-3) [default: 1]: ").strip() or "1"
27
+
28
+ if choice == "1":
29
+ return DEFAULT_BASE_URL
30
+ elif choice == "2":
31
+ username = input("Enter your Hugging Face username: ").strip()
32
+ space_name = input("Enter your Space name: ").strip()
33
+ return HF_SPACE_URL_TEMPLATE.format(username=username, space_name=space_name)
34
+ elif choice == "3":
35
+ url = input("Enter custom URL: ").strip()
36
+ return url.rstrip('/')
37
+ else:
38
+ print("Invalid choice, using local URL")
39
+ return DEFAULT_BASE_URL
40
+
41
+
42
+ def test_health(base_url: str) -> bool:
43
+ """Test health check endpoint"""
44
+ print("\n" + "-"*70)
45
+ print("1. Testing Health Check")
46
+ print("-"*70)
47
+
48
+ try:
49
+ response = requests.get(f"{base_url}/health", timeout=10)
50
+ response.raise_for_status()
51
+ data = response.json()
52
+ print("โœ… Health check passed!")
53
+ print(f" Status: {data.get('status')}")
54
+ print(f" LLM Loaded: {data.get('llm_loaded', 'Unknown')}")
55
+ print(f" Timestamp: {data.get('timestamp')}")
56
+ return True
57
+ except requests.exceptions.RequestException as e:
58
+ print(f"โŒ Health check failed: {e}")
59
+ if hasattr(e, 'response') and e.response is not None:
60
+ print(f" Response: {e.response.text}")
61
+ return False
62
+
63
+
64
+ def test_generic_llm(base_url: str, prompt: Optional[str] = None) -> bool:
65
+ """Test generic LLM endpoint with user prompt"""
66
+ print("\n" + "-"*70)
67
+ print("2. Testing Generic LLM Endpoint")
68
+ print("-"*70)
69
+
70
+ if prompt is None:
71
+ prompt = input("\nEnter your prompt (or press Enter for default): ").strip()
72
+ if not prompt:
73
+ prompt = "What are the top 5 skills needed for a data scientist role? Explain each briefly."
74
+
75
+ payload = {
76
+ "prompt": prompt,
77
+ "max_tokens": 500,
78
+ "temperature": 0.7
79
+ }
80
+
81
+ print(f"\n๐Ÿ“ Prompt: {prompt}")
82
+ print("โณ Sending request...")
83
+
84
+ try:
85
+ response = requests.post(
86
+ f"{base_url}/api/v1/llm",
87
+ json=payload,
88
+ timeout=120 # LLM requests can take time
89
+ )
90
+ response.raise_for_status()
91
+ data = response.json()
92
+ print("\nโœ… LLM response received!")
93
+ print(f"\n๐Ÿ“„ Response:\n{data.get('response', 'No response')}")
94
+ print(f"\nโฐ Timestamp: {data.get('timestamp')}")
95
+ return True
96
+ except requests.exceptions.RequestException as e:
97
+ print(f"\nโŒ LLM request failed: {e}")
98
+ if hasattr(e, 'response') and e.response is not None:
99
+ print(f" Status Code: {e.response.status_code}")
100
+ print(f" Response: {e.response.text}")
101
+ return False
102
+
103
+
104
+ def test_diagnosis(base_url: str) -> bool:
105
+ """Test diagnosis endpoint"""
106
+ print("\n" + "-"*70)
107
+ print("3. Testing Career Diagnosis Endpoint")
108
+ print("-"*70)
109
+
110
+ print("\nEnter user information for diagnosis:")
111
+ current_role = input("Current role [default: Software Engineer]: ").strip() or "Software Engineer"
112
+ years_exp = input("Years of experience [default: 3]: ").strip() or "3"
113
+ skills_input = input("Skills (comma-separated) [default: Python, JavaScript]: ").strip() or "Python, JavaScript"
114
+ skills = [s.strip() for s in skills_input.split(",")]
115
+ career_goals = input("Career goals [default: Senior Engineer at FAANG]: ").strip() or "Senior Engineer at FAANG"
116
+
117
+ payload = {
118
+ "user_status": {
119
+ "current_role": current_role,
120
+ "years_of_experience": float(years_exp),
121
+ "skills": skills,
122
+ "career_goals": career_goals
123
+ },
124
+ "additional_context": "User wants to advance their career"
125
+ }
126
+
127
+ print(f"\n๐Ÿ“ Analyzing career situation for: {current_role} with {years_exp} years experience")
128
+ print("โณ Sending request...")
129
+
130
+ try:
131
+ response = requests.post(
132
+ f"{base_url}/api/v1/diagnose",
133
+ json=payload,
134
+ timeout=120
135
+ )
136
+ response.raise_for_status()
137
+ data = response.json()
138
+ print("\nโœ… Diagnosis received!")
139
+ print(f"\n๐Ÿ“Š Diagnosis:\n{data.get('diagnosis', 'N/A')}")
140
+ print(f"\nโœจ Strengths: {', '.join(data.get('strengths', []))}")
141
+ print(f"โš ๏ธ Weaknesses: {', '.join(data.get('weaknesses', []))}")
142
+ print(f"๐Ÿ’ก Recommendations: {len(data.get('recommendations', []))} items")
143
+ return True
144
+ except requests.exceptions.RequestException as e:
145
+ print(f"\nโŒ Diagnosis request failed: {e}")
146
+ if hasattr(e, 'response') and e.response is not None:
147
+ print(f" Response: {e.response.text}")
148
+ return False
149
+
150
+
151
+ def test_breakthrough(base_url: str) -> bool:
152
+ """Test breakthrough analysis endpoint"""
153
+ print("\n" + "-"*70)
154
+ print("4. Testing Breakthrough Analysis Endpoint")
155
+ print("-"*70)
156
+
157
+ current_role = input("\nCurrent role [default: Software Engineer]: ").strip() or "Software Engineer"
158
+ target_companies_input = input("Target companies (comma-separated) [default: Google, Microsoft]: ").strip() or "Google, Microsoft"
159
+ target_companies = [c.strip() for c in target_companies_input.split(",")]
160
+
161
+ payload = {
162
+ "user_status": {
163
+ "current_role": current_role,
164
+ "years_of_experience": 3.5,
165
+ "skills": ["Python", "JavaScript"],
166
+ "career_goals": f"Senior role at {target_companies[0]}"
167
+ },
168
+ "target_companies": target_companies,
169
+ "target_roles": ["Senior Software Engineer"]
170
+ }
171
+
172
+ print(f"\n๐Ÿ“ Analyzing breakthrough opportunities for: {current_role}")
173
+ print("โณ Sending request...")
174
+
175
+ try:
176
+ response = requests.post(
177
+ f"{base_url}/api/v1/breakthrough",
178
+ json=payload,
179
+ timeout=120
180
+ )
181
+ response.raise_for_status()
182
+ data = response.json()
183
+ print("\nโœ… Breakthrough analysis received!")
184
+ print(f"\n๐Ÿ” Analysis:\n{data.get('breakthrough_analysis', 'N/A')[:200]}...")
185
+ print(f"\n๐ŸŽฏ Opportunities: {len(data.get('opportunities', []))} found")
186
+ print(f"๐Ÿ“‹ Action Items: {len(data.get('action_items', []))} items")
187
+ return True
188
+ except requests.exceptions.RequestException as e:
189
+ print(f"\nโŒ Breakthrough request failed: {e}")
190
+ if hasattr(e, 'response') and e.response is not None:
191
+ print(f" Response: {e.response.text}")
192
+ return False
193
+
194
+
195
+ def test_roadmap(base_url: str) -> bool:
196
+ """Test roadmap generation endpoint"""
197
+ print("\n" + "-"*70)
198
+ print("5. Testing Roadmap Generation Endpoint")
199
+ print("-"*70)
200
+
201
+ target_company = input("\nTarget company [default: Google]: ").strip() or "Google"
202
+ target_role = input("Target role [default: Senior Software Engineer]: ").strip() or "Senior Software Engineer"
203
+ timeline = input("Timeline in weeks [default: 16]: ").strip() or "16"
204
+
205
+ payload = {
206
+ "user_status": {
207
+ "current_role": "Software Engineer",
208
+ "years_of_experience": 3.5,
209
+ "skills": ["Python", "JavaScript"]
210
+ },
211
+ "target_company": target_company,
212
+ "target_role": target_role,
213
+ "timeline_weeks": int(timeline)
214
+ }
215
+
216
+ print(f"\n๐Ÿ“ Generating roadmap for: {target_role} at {target_company}")
217
+ print("โณ Sending request...")
218
+
219
+ try:
220
+ response = requests.post(
221
+ f"{base_url}/api/v1/roadmap",
222
+ json=payload,
223
+ timeout=120
224
+ )
225
+ response.raise_for_status()
226
+ data = response.json()
227
+ print("\nโœ… Roadmap generated!")
228
+ print(f"\n๐Ÿ—บ๏ธ Roadmap Overview:\n{data.get('roadmap', 'N/A')[:300]}...")
229
+ print(f"\n๐Ÿ“… Milestones: {len(data.get('milestones', []))} milestones")
230
+ print(f"๐ŸŽฏ Skill Gaps: {len(data.get('skill_gaps', []))} identified")
231
+ print(f"๐Ÿ“Š Estimated Readiness: {data.get('estimated_readiness', 'N/A')}")
232
+ return True
233
+ except requests.exceptions.RequestException as e:
234
+ print(f"\nโŒ Roadmap request failed: {e}")
235
+ if hasattr(e, 'response') and e.response is not None:
236
+ print(f" Response: {e.response.text}")
237
+ return False
238
+
239
+
240
+ def test_resume_analysis(base_url: str) -> bool:
241
+ """Test resume analysis endpoint"""
242
+ print("\n" + "-"*70)
243
+ print("6. Testing Resume Analysis Endpoint")
244
+ print("-"*70)
245
+
246
+ print("\nEnter resume text (or press Enter for sample):")
247
+ resume_text = input().strip()
248
+
249
+ if not resume_text:
250
+ resume_text = """
251
+ John Doe
252
+ Software Engineer
253
+
254
+ EXPERIENCE
255
+ Software Engineer | Tech Corp | 2020-Present
256
+ - Developed web applications using Python and React
257
+ - Led team of 3 developers
258
+ - Improved system performance by 40%
259
+
260
+ SKILLS
261
+ Python, JavaScript, React, Node.js, SQL
262
+
263
+ EDUCATION
264
+ Bachelor's in Computer Science | State University | 2020
265
+ """
266
+
267
+ target_role = input("\nTarget role [default: Senior Software Engineer]: ").strip() or "Senior Software Engineer"
268
+
269
+ payload = {
270
+ "resume_text": resume_text,
271
+ "target_role": target_role
272
+ }
273
+
274
+ print(f"\n๐Ÿ“ Analyzing resume for: {target_role}")
275
+ print("โณ Sending request...")
276
+
277
+ try:
278
+ response = requests.post(
279
+ f"{base_url}/api/v1/resume/analyze",
280
+ json=payload,
281
+ timeout=120
282
+ )
283
+ response.raise_for_status()
284
+ data = response.json()
285
+ print("\nโœ… Resume analysis received!")
286
+ ats_score = data.get('ats_score', {})
287
+ print(f"\n๐Ÿ“Š ATS Score: {ats_score.get('score', 'N/A')}/100 ({ats_score.get('grade', 'N/A')})")
288
+ print(f"โœจ Strengths: {len(data.get('strengths', []))} identified")
289
+ print(f"โš ๏ธ Weaknesses: {len(data.get('weaknesses', []))} identified")
290
+ print(f"๐Ÿ’ก Improvement Suggestions: {len(data.get('improvement_suggestions', []))} items")
291
+ return True
292
+ except requests.exceptions.RequestException as e:
293
+ print(f"\nโŒ Resume analysis failed: {e}")
294
+ if hasattr(e, 'response') and e.response is not None:
295
+ print(f" Response: {e.response.text}")
296
+ return False
297
+
298
+
299
+ def run_all_tests(base_url: str):
300
+ """Run all tests interactively"""
301
+ results = {}
302
+
303
+ # Test 1: Health check (always run first)
304
+ results['health'] = test_health(base_url)
305
+
306
+ if not results['health']:
307
+ print("\nโš ๏ธ Health check failed. Please check your deployment.")
308
+ return
309
+
310
+ # Ask which tests to run
311
+ print("\n" + "="*70)
312
+ print("Select tests to run:")
313
+ print("1. Generic LLM (with custom prompt)")
314
+ print("2. Career Diagnosis")
315
+ print("3. Breakthrough Analysis")
316
+ print("4. Roadmap Generation")
317
+ print("5. Resume Analysis")
318
+ print("6. Run all tests")
319
+ print("0. Exit")
320
+
321
+ choice = input("\nEnter choice (0-6): ").strip()
322
+
323
+ if choice == "0":
324
+ print("Exiting...")
325
+ return
326
+ elif choice == "1":
327
+ results['llm'] = test_generic_llm(base_url)
328
+ elif choice == "2":
329
+ results['diagnosis'] = test_diagnosis(base_url)
330
+ elif choice == "3":
331
+ results['breakthrough'] = test_breakthrough(base_url)
332
+ elif choice == "4":
333
+ results['roadmap'] = test_roadmap(base_url)
334
+ elif choice == "5":
335
+ results['resume'] = test_resume_analysis(base_url)
336
+ elif choice == "6":
337
+ # Run all tests
338
+ results['llm'] = test_generic_llm(base_url, "What are the top 5 skills for a data scientist?")
339
+ results['diagnosis'] = test_diagnosis(base_url)
340
+ results['breakthrough'] = test_breakthrough(base_url)
341
+ results['roadmap'] = test_roadmap(base_url)
342
+ results['resume'] = test_resume_analysis(base_url)
343
+ else:
344
+ print("Invalid choice")
345
+ return
346
+
347
+ # Summary
348
+ print("\n" + "="*70)
349
+ print("Test Summary")
350
+ print("="*70)
351
+ for test_name, passed in results.items():
352
+ status = "โœ… PASSED" if passed else "โŒ FAILED"
353
+ print(f"{test_name.upper():20} {status}")
354
+
355
+ print("\n" + "="*70)
356
+
357
+
358
+ def main():
359
+ """Main function"""
360
+ try:
361
+ base_url = get_base_url()
362
+ print(f"\n๐ŸŒ Testing deployment at: {base_url}")
363
+
364
+ run_all_tests(base_url)
365
+
366
+ except KeyboardInterrupt:
367
+ print("\n\nโš ๏ธ Interrupted by user")
368
+ sys.exit(0)
369
+ except Exception as e:
370
+ print(f"\nโŒ Unexpected error: {e}")
371
+ sys.exit(1)
372
+
373
+
374
+ if __name__ == "__main__":
375
+ main()