| --- |
| title: Semantick |
| emoji: 🧠 |
| colorFrom: gray |
| colorTo: green |
| sdk: docker |
| app_port: 7860 |
| --- |
| |
| # Semantick |
|
|
| A semantic word-guessing game. Guess the secret word based on meaning similarity. |
|
|
| ## Architecture |
|
|
| ``` |
| Client (React) ──POST /api/game/{id}/guess──▶ Server (FastAPI) |
| │ |
| ▼ |
| embeddings.npz |
| (word → vector) |
| │ |
| ▼ |
| cosine similarity |
| │ |
| ◀── { score, rank } |
| ``` |
|
|
| The server holds all embeddings in memory. Each guess is a vector lookup + dot product — sub-millisecond. |
|
|
| ## Setup |
|
|
| ```bash |
| pip install -r requirements.txt |
| |
| # Generate mock embeddings (for development) |
| python generate_embeddings.py |
| |
| # Start server |
| uvicorn server:app --reload --port 8000 |
| ``` |
|
|
| ## Replacing Mock Embeddings with Real Ones |
|
|
| The game ships with random vectors for testing. To use real semantic embeddings: |
|
|
| ```python |
| import numpy as np |
| |
| # Your embedding pipeline |
| words = [...] # list of vocabulary words |
| vectors = model.encode(words) # shape: (vocab_size, dim) |
| |
| # Normalize to unit vectors (required for cosine similarity via dot product) |
| norms = np.linalg.norm(vectors, axis=1, keepdims=True) |
| vectors = vectors / norms |
| |
| np.savez_compressed("embeddings.npz", words=np.array(words), vectors=vectors.astype(np.float32)) |
| ``` |
|
|
| Recommended models: `all-MiniLM-L6-v2` (384-dim, fast), `all-mpnet-base-v2` (768-dim, better quality), or OpenAI/Cohere embedding APIs. |
|
|
| ## API |
|
|
| | Endpoint | Method | Description | |
| |---|---|---| |
| | `/api/new-game` | POST | Start new game, returns `game_id` | |
| | `/api/game/{id}/guess` | POST | Submit guess `{"word": "..."}`, returns score + rank | |
| | `/api/game/{id}/give-up` | POST | Reveal secret word | |
| | `/api/health` | GET | Server status | |
|
|
| **Guess response:** |
| - `score`: 0-100 similarity (mapped from cosine similarity) |
| - `rank`: word's rank among all vocab by similarity to the secret (1 = closest) |
| - `solved`: true if exact match |
| - HTTP 422 if word not in dictionary |
|
|