Production-ready semantic search API deployed on Google Cloud Run. This service provides endpoints for generating text embeddings and performing semantic search using sentence-transformers.
- 🚀 Fast & Scalable: Auto-scales from 0 to handle traffic spikes
- 🔒 Secure: API key authentication with Secret Manager integration
- 💰 Cost-Effective: Pay only for what you use, generous free tier
- 🐳 Containerized: Docker-based deployment for consistency
- 📊 Model Support: Uses sentence-transformers (all-MiniLM-L6-v2)
- 🌐 CORS Enabled: Ready for web application integration
GET /healthReturns service health status and model information.
POST /generate-embedding
Headers: X-Api-Key: your-api-key
Body: {"text": "your text here"}Generates a 384-dimensional embedding vector for the input text.
POST /generate-batch-embeddings
Headers: X-Api-Key: your-api-key
Body: {"texts": ["text1", "text2", "text3"]}Generates embeddings for multiple texts (up to 100 per request).
POST /semantic-search
Headers: X-Api-Key: your-api-key
Body: {
"query": "search query",
"embeddings_data": [...],
"top_k": 5,
"min_score": 0.5
}Finds most similar items to the query using cosine similarity.
POST /find-insights
Headers: X-Api-Key: your-api-key
Body: {
"query": "business idea",
"embeddings_data": [...],
"top_k": 10
}Finds and groups insights by category (startup ideas, marketing strategies, etc.).
- Google Cloud Platform account
gcloudCLI installed- Docker (optional, for local testing)
- Clone and navigate to directory:
cd "c:\Users\LENOVE\Documents\youtube app\cloudrun"- Set up Google Cloud:
gcloud init
gcloud config set project YOUR_PROJECT_ID
gcloud services enable run.googleapis.com cloudbuild.googleapis.com secretmanager.googleapis.com- Create API key secret:
echo -n "your-secure-api-key" | gcloud secrets create semantic-search-api-key \
--data-file=- \
--replication-policy="automatic"- Deploy:
gcloud run deploy semantic-search-api \
--source . \
--platform managed \
--region us-central1 \
--allow-unauthenticated \
--memory 4Gi \
--cpu 2 \
--timeout 300 \
--max-instances 10 \
--set-secrets=API_KEY=semantic-search-api-key:latest- Get service URL:
gcloud run services describe semantic-search-api \
--region us-central1 \
--format 'value(status.url)'See README_DEPLOYMENT.md for detailed deployment instructions.
docker build -t semantic-search-api .
docker run -p 8080:8080 -e API_KEY="test-key" semantic-search-apipip install -r requirements.txt
export API_KEY="test-key"
python main.pypython test_cloudrun.py http://localhost:8080 test-keycloudrun/
├── main.py # Flask application (Cloud Run entry point)
├── embeddings.py # Embedding generation logic
├── semantic_search.py # Search and similarity functions
├── Dockerfile # Container configuration
├── requirements.txt # Python dependencies
├── README_DEPLOYMENT.md # Detailed deployment guide
├── test_cloudrun.py # Testing suite
├── .env.example # Environment variables template
└── .gitignore # Git ignore rules
API_KEY: API key for authentication (injected from Secret Manager)PORT: Port to run the service (default: 8080)MODEL_NAME: Sentence-transformers model to useTRANSFORMERS_CACHE: Directory for model cache
- Memory: 4 GB (adjustable based on model size)
- CPU: 2 vCPUs (adjustable based on performance needs)
- Timeout: 300 seconds (5 minutes)
- Concurrency: 10 requests per instance
import requests
API_URL = "https://your-service-url.run.app"
API_KEY = "your-api-key"
# Generate embedding
response = requests.post(
f"{API_URL}/generate-embedding",
headers={"X-Api-Key": API_KEY, "Content-Type": "application/json"},
json={"text": "Hello, world!"}
)
embedding = response.json()["embedding"]
# Semantic search
response = requests.post(
f"{API_URL}/semantic-search",
headers={"X-Api-Key": API_KEY, "Content-Type": "application/json"},
json={
"query": "machine learning",
"embeddings_data": embeddings_data,
"top_k": 5
}
)
results = response.json()["results"]const API_URL = "https://your-service-url.run.app";
const API_KEY = "your-api-key";
// Generate embedding
const response = await fetch(`${API_URL}/generate-embedding`, {
method: 'POST',
headers: {
'X-Api-Key': API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({ text: "Hello, world!" })
});
const { embedding } = await response.json();gcloud run services logs tail semantic-search-api --region us-central1- Go to Cloud Run Console
- Select your service
- View metrics in the "METRICS" tab
With Cloud Run's pricing:
- Free tier: 2M requests/month, 360,000 vCPU-seconds, 180,000 GiB-seconds
- Cost per request: ~$0.0001164 (with 4GB memory, 2 vCPUs, 2s duration)
- Monthly cost (1M requests): ~$116.40
See README_DEPLOYMENT.md for detailed cost optimization strategies.
-
Cold starts: First request may take 30-60 seconds (model loading)
- Solution: Use minimum instances (costs more) or accept cold starts
-
Out of memory: Increase memory allocation
gcloud run services update semantic-search-api --memory 8Gi
-
Timeout: Increase timeout limit
gcloud run services update semantic-search-api --timeout 600
This service is a direct replacement for the AWS Lambda version. Key differences:
| Feature | AWS Lambda | Google Cloud Run |
|---|---|---|
| Max Memory | 10 GB | 32 GB |
| Max Timeout | 15 minutes | 60 minutes |
| Container Support | Limited | Native |
| Pricing | Per 1ms | Per 100ms |
| Cold Start | 3-8s | 2-5s |
- ✅ API key authentication
- ✅ CORS enabled
- ✅ Secrets stored in Secret Manager
- ✅ HTTPS only
⚠️ Currently allows unauthenticated access (API key validated in app)
For production, consider:
- Enabling Cloud IAM authentication
- Using VPC connector for private networking
- Adding Cloud Armor for DDoS protection
- Make your changes
- Test locally:
python test_cloudrun.py - Test with Docker:
docker build -t test . && docker run -p 8080:8080 test - Deploy:
gcloud run deploy semantic-search-api --source .
MIT License - see LICENSE file for details
- AWS Lambda Version: See
../lambda/directory - Streamlit App: Integration example in main app
- sentence-transformers: https://www.sbert.net/
Built with ❤️ using Google Cloud Run and sentence-transformers