rdmlx commited on
Commit
b3dfc35
·
1 Parent(s): 7817fe3

Add API test script and remove deployment guide

Browse files

- Add test_api.sh: Comprehensive test suite for API validation
- Tests health check endpoint
- Validates semantic search with query 'what did jesus say about eternal life'
- Asserts top result is John 17 with similarity >= 0.77
- Tests testament filter functionality
- Checks interactive documentation accessibility
- All 8 tests passing ✓

- Remove DEPLOYMENT_GUIDE.md (no longer needed post-deployment)

Test results: Book jhn, Chapter 17, Similarity 0.789 (> 0.77 threshold)

Files changed (2) hide show
  1. DEPLOYMENT_GUIDE.md +0 -326
  2. test_api.sh +146 -0
DEPLOYMENT_GUIDE.md DELETED
@@ -1,326 +0,0 @@
1
- # Deployment Guide: Biblos API to Hugging Face Spaces
2
-
3
- This guide walks you through deploying the Biblos Semantic Search API to Hugging Face Spaces.
4
-
5
- ## Prerequisites
6
-
7
- 1. **Hugging Face Account** - Sign up at [huggingface.co](https://huggingface.co)
8
- 2. **Git** - Installed on your machine
9
- 3. **Python 3.10+** - For running the data preparation script
10
-
11
- ---
12
-
13
- ## Step 1: Prepare the Data
14
-
15
- First, extract the Bible embeddings from your existing ZIP files:
16
-
17
- ```bash
18
- # Navigate to the hf-spaces directory
19
- cd hf-spaces
20
-
21
- # Run the data preparation script (uses desktop embeddings by default)
22
- python prepare_data.py
23
-
24
- # OR, use iOS embeddings (smaller, quantized):
25
- python prepare_data.py --ios
26
-
27
- # OR, specify custom paths:
28
- python prepare_data.py --source ../public/data --output ./data
29
- ```
30
-
31
- This will:
32
- - Extract JSON files from ZIP archives
33
- - Validate embeddings
34
- - Create a `data/` directory with 66 JSON files (one per book)
35
- - Total size: ~200-250MB
36
-
37
- **Verify the extraction:**
38
- ```bash
39
- ls -lh data/
40
- # Should show 66 .json files
41
- ```
42
-
43
- ---
44
-
45
- ## Step 2: Test Locally (Optional but Recommended)
46
-
47
- Before deploying, test the API locally:
48
-
49
- ```bash
50
- # Install dependencies
51
- pip install -r requirements.txt
52
-
53
- # Run the server
54
- python -m uvicorn app:app --host 0.0.0.0 --port 7860
55
-
56
- # In another terminal, test the API
57
- curl -X POST http://localhost:7860/search \
58
- -H "Content-Type: application/json" \
59
- -d '{"query": "love one another", "limit": 3}'
60
- ```
61
-
62
- Visit http://localhost:7860/docs for interactive API documentation.
63
-
64
- ---
65
-
66
- ## Step 3: Create a Hugging Face Space
67
-
68
- 1. **Go to Hugging Face** - Visit [huggingface.co/spaces](https://huggingface.co/spaces)
69
-
70
- 2. **Click "Create new Space"**
71
-
72
- 3. **Configure the Space:**
73
- - **Space name**: Choose a name (e.g., `biblos-api`)
74
- - **License**: MIT
75
- - **SDK**: Select **Docker**
76
- - **Space hardware**: CPU basic (free)
77
- - **Visibility**: Public or Private (your choice)
78
-
79
- 4. **Click "Create Space"**
80
-
81
- ---
82
-
83
- ## Step 4: Upload Files to Your Space
84
-
85
- ### Option A: Using Git (Recommended)
86
-
87
- ```bash
88
- # Clone your Space repository (replace YOUR-USERNAME and YOUR-SPACE-NAME)
89
- git clone https://huggingface.co/spaces/YOUR-USERNAME/YOUR-SPACE-NAME
90
- cd YOUR-SPACE-NAME
91
-
92
- # Copy all files from hf-spaces directory
93
- cp -r ../hf-spaces/* .
94
-
95
- # Add all files to git
96
- git add .
97
-
98
- # Commit
99
- git commit -m "Initial deployment of Biblos API"
100
-
101
- # Push to Hugging Face (this triggers deployment)
102
- git push
103
- ```
104
-
105
- ### Option B: Using Web Interface
106
-
107
- 1. Click "Files and versions" tab in your Space
108
- 2. Click "Add file" → "Upload files"
109
- 3. Upload these files from the `hf-spaces/` directory:
110
- - `app.py`
111
- - `requirements.txt`
112
- - `Dockerfile`
113
- - `README.md`
114
- - The entire `data/` directory (66 JSON files)
115
- 4. Commit the changes
116
-
117
- **Important:** Make sure to upload the `data/` directory with all 66 JSON files!
118
-
119
- ---
120
-
121
- ## Step 5: Wait for Deployment
122
-
123
- After pushing/uploading:
124
-
125
- 1. **HF Spaces will automatically build** your Docker container
126
- 2. You'll see logs in the "Logs" tab
127
- 3. Initial build takes **5-10 minutes**
128
- 4. Once complete, you'll see: `Application startup complete`
129
-
130
- **Build process:**
131
- - Install Python dependencies
132
- - Download the BGE-large model (~639MB)
133
- - Load all Bible embeddings into memory
134
- - Start the FastAPI server
135
-
136
- ---
137
-
138
- ## Step 6: Test Your Deployed API
139
-
140
- Once deployment is complete, your API is live!
141
-
142
- **Your API URL:**
143
- ```
144
- https://YOUR-USERNAME-YOUR-SPACE-NAME.hf.space
145
- ```
146
-
147
- ### Test Endpoints
148
-
149
- **Health Check:**
150
- ```bash
151
- curl https://YOUR-USERNAME-YOUR-SPACE-NAME.hf.space/
152
- ```
153
-
154
- **Search:**
155
- ```bash
156
- curl -X POST https://YOUR-USERNAME-YOUR-SPACE-NAME.hf.space/search \
157
- -H "Content-Type: application/json" \
158
- -d '{
159
- "query": "faith without works",
160
- "testament": "new",
161
- "limit": 5
162
- }'
163
- ```
164
-
165
- **Interactive Docs:**
166
- Visit: `https://YOUR-USERNAME-YOUR-SPACE-NAME.hf.space/docs`
167
-
168
- ---
169
-
170
- ## Step 7: Update Your Frontend
171
-
172
- Update your Biblos frontend to use the new API:
173
-
174
- **In your frontend code:**
175
- ```javascript
176
- // Instead of client-side search, call your API
177
- const API_URL = 'https://YOUR-USERNAME-YOUR-SPACE-NAME.hf.space'
178
-
179
- async function searchBible(query, options = {}) {
180
- const response = await fetch(`${API_URL}/search`, {
181
- method: 'POST',
182
- headers: { 'Content-Type': 'application/json' },
183
- body: JSON.stringify({ query, ...options })
184
- })
185
-
186
- const data = await response.json()
187
- return data.results
188
- }
189
- ```
190
-
191
- ---
192
-
193
- ## Troubleshooting
194
-
195
- ### Build Fails
196
-
197
- **Check logs** in the "Logs" tab. Common issues:
198
-
199
- 1. **Missing data files**
200
- - Ensure all 66 JSON files are in `data/` directory
201
- - Re-run `prepare_data.py` if needed
202
-
203
- 2. **Out of memory**
204
- - Reduce model size (use iOS embeddings)
205
- - Upgrade to larger Space hardware (paid)
206
-
207
- 3. **Import errors**
208
- - Check `requirements.txt` versions
209
- - Ensure all dependencies are listed
210
-
211
- ### API Returns 503 Error
212
-
213
- This means the model hasn't loaded yet:
214
- - Wait a few more seconds
215
- - Check logs for model loading progress
216
- - First request after cold start takes 2-3 seconds
217
-
218
- ### Slow Response Times
219
-
220
- - First request: Expected (~2-3s for model loading)
221
- - Subsequent requests: Should be 50-100ms
222
- - If consistently slow:
223
- - Check Space hardware in settings
224
- - Consider upgrading to GPU (faster inference)
225
-
226
- ---
227
-
228
- ## Monitoring & Maintenance
229
-
230
- ### View Logs
231
- 1. Go to your Space page
232
- 2. Click "Logs" tab
233
- 3. See real-time logs of API requests and responses
234
-
235
- ### Update the API
236
- 1. Make changes locally
237
- 2. Commit and push:
238
- ```bash
239
- git add .
240
- git commit -m "Update API"
241
- git push
242
- ```
243
- 3. HF Spaces automatically rebuilds
244
-
245
- ### Space Sleep
246
- - Free CPU Spaces may sleep after 48h of inactivity
247
- - First request after sleep has ~30s cold start
248
- - To prevent: Upgrade to persistent hardware (paid)
249
-
250
- ---
251
-
252
- ## Cost & Limits
253
-
254
- ### Free Tier (CPU Basic)
255
- - ✅ Perfect for moderate traffic
256
- - ✅ No time limit
257
- - ✅ No request limit
258
- - ⚠️ May sleep after 48h inactivity
259
- - ⚠️ Slower inference (CPU only)
260
-
261
- ### Paid Tiers
262
- If you need more performance:
263
- - **CPU Upgrade** ($0.04/hour) - Faster CPU, no sleep
264
- - **GPU T4** ($0.60/hour) - 10x faster inference
265
- - **GPU A10G** ($3.15/hour) - Best performance
266
-
267
- Upgrade in Space Settings → "Change hardware"
268
-
269
- ---
270
-
271
- ## Security Considerations
272
-
273
- 1. **CORS** - Currently allows all origins. To restrict:
274
- ```python
275
- # In app.py, change:
276
- allow_origins=["https://yourdomain.com"]
277
- ```
278
-
279
- 2. **Rate Limiting** - Consider adding:
280
- ```bash
281
- pip install slowapi
282
- ```
283
- See [slowapi docs](https://slowapi.readthedocs.io/)
284
-
285
- 3. **API Keys** - For private use, add authentication:
286
- ```python
287
- from fastapi.security import HTTPBearer
288
- ```
289
-
290
- ---
291
-
292
- ## Next Steps
293
-
294
- 1. ✅ Deploy your API
295
- 2. ✅ Test all endpoints
296
- 3. ✅ Update frontend to use API
297
- 4. ✅ Share API URL with other developers
298
- 5. ✅ Monitor usage and performance
299
- 6. Consider: Add caching, rate limiting, analytics
300
-
301
- ---
302
-
303
- ## Support
304
-
305
- - **HF Spaces Docs**: [huggingface.co/docs/hub/spaces](https://huggingface.co/docs/hub/spaces)
306
- - **FastAPI Docs**: [fastapi.tiangolo.com](https://fastapi.tiangolo.com)
307
- - **Community Forum**: [discuss.huggingface.co](https://discuss.huggingface.co)
308
-
309
- ---
310
-
311
- ## Summary
312
-
313
- ```bash
314
- # Quick deployment checklist:
315
- ☐ Run prepare_data.py to extract embeddings
316
- ☐ Create new Space on Hugging Face (Docker SDK)
317
- ☐ Upload all files (app.py, requirements.txt, Dockerfile, README.md, data/)
318
- ☐ Wait for build to complete (~5-10 min)
319
- ☐ Test API endpoints
320
- ☐ Update frontend to use new API URL
321
- ☐ 🎉 Your API is live!
322
- ```
323
-
324
- **Estimated total time:** 15-30 minutes
325
-
326
- Good luck! 🚀
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
test_api.sh ADDED
@@ -0,0 +1,146 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+
3
+ # Biblos API Test Script
4
+ # Tests the semantic search API with expected results
5
+
6
+ API_URL="https://dssjon-biblos-api.hf.space"
7
+ QUERY="what did jesus say about eternal life"
8
+ EXPECTED_BOOK="jhn"
9
+ EXPECTED_CHAPTER=17
10
+ MIN_SIMILARITY=0.77
11
+
12
+ echo "======================================"
13
+ echo "Biblos API Test Suite"
14
+ echo "======================================"
15
+ echo ""
16
+
17
+ # Colors for output
18
+ GREEN='\033[0;32m'
19
+ RED='\033[0;31m'
20
+ NC='\033[0m'
21
+
22
+ pass_count=0
23
+ fail_count=0
24
+
25
+ print_pass() {
26
+ echo -e "${GREEN}✓ PASS${NC}: $1"
27
+ ((pass_count++))
28
+ }
29
+
30
+ print_fail() {
31
+ echo -e "${RED}✗ FAIL${NC}: $1"
32
+ ((fail_count++))
33
+ }
34
+
35
+ # Test 1: Health Check
36
+ echo "Test 1: Health Check (GET /)"
37
+ health=$(curl -s "$API_URL/")
38
+ status=$(echo "$health" | jq -r '.status' 2>/dev/null)
39
+
40
+ if [ "$status" = "online" ]; then
41
+ print_pass "API is online and responding"
42
+ else
43
+ print_fail "API health check failed"
44
+ fi
45
+
46
+ books=$(echo "$health" | jq -r '.books_loaded' 2>/dev/null)
47
+ if [ "$books" = "66" ]; then
48
+ print_pass "All 66 books loaded"
49
+ else
50
+ print_fail "Expected 66 books, got $books"
51
+ fi
52
+ echo ""
53
+
54
+ # Test 2: Semantic Search
55
+ echo "Test 2: Semantic Search"
56
+ echo "Query: \"$QUERY\""
57
+ search=$(curl -s -X POST "$API_URL/search" \
58
+ -H "Content-Type: application/json" \
59
+ -d "{\"query\":\"$QUERY\",\"limit\":3}")
60
+
61
+ # Check if we got results
62
+ results_count=$(echo "$search" | jq -r '.results | length' 2>/dev/null)
63
+ if [ "$results_count" -gt 0 ]; then
64
+ print_pass "Search returned $results_count results"
65
+ else
66
+ print_fail "No search results returned"
67
+ exit 1
68
+ fi
69
+ echo ""
70
+
71
+ # Test 3: Validate Top Result
72
+ echo "Test 3: Validate Top Result"
73
+ book=$(echo "$search" | jq -r '.results[0].book')
74
+ chapter=$(echo "$search" | jq -r '.results[0].chapter')
75
+ similarity=$(echo "$search" | jq -r '.results[0].similarity')
76
+ content=$(echo "$search" | jq -r '.results[0].content' | head -c 80)
77
+
78
+ echo "Top Result:"
79
+ echo " Book: $book"
80
+ echo " Chapter: $chapter"
81
+ echo " Similarity: $similarity"
82
+ echo " Content: ${content}..."
83
+ echo ""
84
+
85
+ if [ "$book" = "$EXPECTED_BOOK" ]; then
86
+ print_pass "Book matches expected: $EXPECTED_BOOK"
87
+ else
88
+ print_fail "Expected book '$EXPECTED_BOOK', got '$book'"
89
+ fi
90
+
91
+ if [ "$chapter" = "$EXPECTED_CHAPTER" ]; then
92
+ print_pass "Chapter matches expected: $EXPECTED_CHAPTER"
93
+ else
94
+ print_fail "Expected chapter $EXPECTED_CHAPTER, got $chapter"
95
+ fi
96
+
97
+ # Check similarity threshold
98
+ if (( $(echo "$similarity >= $MIN_SIMILARITY" | bc -l) )); then
99
+ print_pass "Similarity score $similarity >= $MIN_SIMILARITY"
100
+ else
101
+ print_fail "Similarity score $similarity < $MIN_SIMILARITY"
102
+ fi
103
+ echo ""
104
+
105
+ # Test 4: Testament Filter
106
+ echo "Test 4: Testament Filter"
107
+ nt_search=$(curl -s -X POST "$API_URL/search" \
108
+ -H "Content-Type: application/json" \
109
+ -d '{"query":"love","testament":"new","limit":1}')
110
+ testament=$(echo "$nt_search" | jq -r '.results[0].testament')
111
+
112
+ if [ "$testament" = "NT" ]; then
113
+ print_pass "Testament filter working correctly"
114
+ else
115
+ print_fail "Testament filter returned: $testament"
116
+ fi
117
+ echo ""
118
+
119
+ # Test 5: Interactive Docs
120
+ echo "Test 5: Interactive Documentation"
121
+ docs_code=$(curl -s -o /dev/null -w "%{http_code}" "$API_URL/docs")
122
+
123
+ if [ "$docs_code" = "200" ]; then
124
+ print_pass "Interactive docs accessible at /docs"
125
+ else
126
+ print_fail "Docs endpoint returned HTTP $docs_code"
127
+ fi
128
+ echo ""
129
+
130
+ # Summary
131
+ echo "======================================"
132
+ echo "Test Summary"
133
+ echo "======================================"
134
+ total=$((pass_count + fail_count))
135
+ echo -e "${GREEN}Passed: $pass_count/$total${NC}"
136
+
137
+ if [ $fail_count -gt 0 ]; then
138
+ echo -e "${RED}Failed: $fail_count/$total${NC}"
139
+ echo ""
140
+ echo -e "${RED}Some tests failed!${NC}"
141
+ exit 1
142
+ else
143
+ echo ""
144
+ echo -e "${GREEN}All tests passed! ✓${NC}"
145
+ exit 0
146
+ fi