vimalk78 commited on
Commit
246e3d3
Β·
1 Parent(s): 1cecbce

feat: add Jetson ARM64 support and improve documentation

Browse files

- Add Dockerfile.jetson for NVIDIA Jetson Orin Nano/Xavier with L4T base
- Add run-jetson.sh build/run script with GPU runtime support
- Update CLAUDE.md: single test command, hack/ scripts section, GPU notes
- Add test_startrek_similarity.py for topic similarity testing

Files changed (5) hide show
  1. .gitignore +3 -1
  2. CLAUDE.md +26 -28
  3. Dockerfile.jetson +76 -0
  4. hack/test_startrek_similarity.py +63 -0
  5. run-jetson.sh +65 -0
.gitignore CHANGED
@@ -68,7 +68,7 @@ venv/
68
  crossword-app/backend-py/src/services/model_cache/
69
  hack/model_cache/
70
  .KARO.md
71
- CLAUDE.md
72
  crossword-app/backend-py/faiss_cache/
73
  cache-dir/models--google--flan-t5-base/
74
  cache-dir/models--google--flan-t5-large/
@@ -79,3 +79,5 @@ cache-dir/.locks/models--google--flan-t5-small/
79
  cache-dir/embeddings_all-mpnet-base-v2_100000.npy
80
  cache-dir/frequencies_100000.pkl
81
  cache-dir/vocabulary_100000.pkl
 
 
 
68
  crossword-app/backend-py/src/services/model_cache/
69
  hack/model_cache/
70
  .KARO.md
71
+ #CLAUDE.md
72
  crossword-app/backend-py/faiss_cache/
73
  cache-dir/models--google--flan-t5-base/
74
  cache-dir/models--google--flan-t5-large/
 
79
  cache-dir/embeddings_all-mpnet-base-v2_100000.npy
80
  cache-dir/frequencies_100000.pkl
81
  cache-dir/vocabulary_100000.pkl
82
+
83
+ train.jsonl
CLAUDE.md CHANGED
@@ -7,10 +7,12 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
7
  This is a full-stack AI-powered crossword puzzle generator:
8
  - **Python Backend** (`crossword-app/backend-py/`) - Primary implementation with dynamic word generation
9
  - **React Frontend** (`crossword-app/frontend/`) - Modern React app with interactive crossword UI
10
- - **Node.js Backend** (`backend/`) - Legacy implementation (deprecated)
11
 
12
  Current deployment uses the Python backend with Docker containerization.
13
 
 
 
14
  ## Development Commands
15
 
16
  ### Frontend Development
@@ -30,6 +32,7 @@ cd crossword-app/backend-py
30
  python run_tests.py # Run all tests
31
  pytest test-unit/ -v # Run unit tests
32
  pytest test-integration/ -v # Run integration tests
 
33
  python test_integration_minimal.py # Quick test without ML deps
34
 
35
  # Development server
@@ -41,14 +44,6 @@ python test_softmax_service.py # Test word selection logic
41
  python test_distribution_normalization.py # Test distribution normalization across topics
42
  ```
43
 
44
- ### Backend Development (Node.js - Legacy)
45
- ```bash
46
- cd backend
47
- npm install
48
- npm run dev # Start Express server on http://localhost:3000
49
- npm test # Run tests
50
- ```
51
-
52
  ### Docker Deployment
53
  ```bash
54
  # Build and run locally
@@ -72,6 +67,13 @@ cd crossword-app/frontend
72
  npm run lint # ESLint (if configured)
73
  ```
74
 
 
 
 
 
 
 
 
75
  ## Architecture Overview
76
 
77
  ### Full-Stack Components
@@ -82,6 +84,7 @@ npm run lint # ESLint (if configured)
82
  - Custom hook: `useCrossword.js` manages API calls and puzzle state
83
  - Interactive crossword grid with cell navigation and solution reveal
84
  - Debug tab for visualizing word selection process (when enabled)
 
85
 
86
  **Python Backend** (`crossword-app/backend-py/` - Primary)
87
  - FastAPI web framework serving both API and static frontend files
@@ -89,11 +92,7 @@ npm run lint # ESLint (if configured)
89
  - No static word files - all words generated on-demand from 100K+ vocabulary
90
  - WordNet-based clue generation with semantic definitions
91
  - Comprehensive caching system for models, embeddings, and vocabulary
92
-
93
- **Node.js Backend** (`backend/` - Legacy - Deprecated)
94
- - Express.js with static JSON word files
95
- - Original implementation, no longer actively maintained
96
- - Used for comparison and fallback testing only
97
 
98
  ### Core Python Backend Components
99
 
@@ -104,7 +103,7 @@ npm run lint # ESLint (if configured)
104
  - Temperature-controlled softmax for balanced word selection randomness
105
  - 50% word overgeneration strategy for better crossword grid fitting
106
  - **Multi-topic intersection**: `_compute_multi_topic_similarities()` with vectorized soft minimum, geometric/harmonic means
107
- - **Adaptive beta mechanism**: Automatically adjusts threshold (0.25β†’0.175β†’0.103...) to ensure 15+ word minimum
108
  - **Performance optimized**: 40x speedup through vectorized operations over loop-based approach
109
  - Key method: `generate_thematic_words()` - Returns words with semantic similarity scores and frequency tiers
110
 
@@ -143,17 +142,13 @@ npm run lint # ESLint (if configured)
143
 
144
  **Python Backend (Primary):**
145
  - FastAPI, uvicorn, pydantic (web framework)
146
- - sentence-transformers, torch (AI word generation)
147
  - wordfreq (vocabulary database)
148
  - nltk (WordNet clue generation)
149
  - scikit-learn (clustering and similarity)
150
  - numpy (embeddings and mathematical operations)
151
  - pytest, pytest-asyncio (testing)
152
 
153
- **Node.js Backend (Legacy - Deprecated):**
154
- - Express.js, cors, helmet
155
- - JSON file-based word storage
156
-
157
  The application requires AI dependencies for core functionality - no fallback to static word lists.
158
 
159
  ### API Endpoints
@@ -174,13 +169,13 @@ Python backend provides the following REST API:
174
  - `test-integration/test_local.py` - End-to-end integration testing
175
  - `test_integration_minimal.py` - Quick functionality test without heavy ML dependencies
176
 
177
- **Multi-Topic Testing & Development Scripts:**
178
- - `hack/test_soft_minimum_quick.py` - Quick soft minimum method verification
179
- - `hack/test_optimized_soft_minimum.py` - Performance testing (40x speedup validation)
180
- - `hack/debug_adaptive_beta_bug.py` - Adaptive beta mechanism debugging
181
- - `hack/test_adaptive_fix.py` - Full vocabulary testing with adaptive beta
182
- - `hack/test_simpler_case.py` - Compatible topic testing (animals + nature)
183
- - All hack/ scripts use shared cache-dir for model loading consistency
184
 
185
  **Frontend Tests:**
186
  - Component testing with React Testing Library (if configured)
@@ -293,4 +288,7 @@ VITE_API_BASE_URL=http://localhost:7860 # Points to Python backend
293
  - βœ… **Debug visualization**: Optional debug tab for development/analysis
294
  - βœ… **Comprehensive caching**: Models, embeddings, and vocabulary cached for performance
295
  - βœ… **Modern stack**: FastAPI + React with Docker deployment ready
296
- - the cache is present in root cache-dir/ folder. every program in hack folder should use this as the cache-dir for loading sentence transformer models
 
 
 
 
7
  This is a full-stack AI-powered crossword puzzle generator:
8
  - **Python Backend** (`crossword-app/backend-py/`) - Primary implementation with dynamic word generation
9
  - **React Frontend** (`crossword-app/frontend/`) - Modern React app with interactive crossword UI
10
+ - **Hack Scripts** (`hack/`) - Experimental/development scripts for testing algorithms
11
 
12
  Current deployment uses the Python backend with Docker containerization.
13
 
14
+ > **Note:** The `backend/` directory contains a deprecated Node.js implementation - do not use or modify.
15
+
16
  ## Development Commands
17
 
18
  ### Frontend Development
 
32
  python run_tests.py # Run all tests
33
  pytest test-unit/ -v # Run unit tests
34
  pytest test-integration/ -v # Run integration tests
35
+ pytest test-unit/test_crossword_generator.py::TestClassName::test_method -v # Run single test
36
  python test_integration_minimal.py # Quick test without ML deps
37
 
38
  # Development server
 
44
  python test_distribution_normalization.py # Test distribution normalization across topics
45
  ```
46
 
 
 
 
 
 
 
 
 
47
  ### Docker Deployment
48
  ```bash
49
  # Build and run locally
 
67
  npm run lint # ESLint (if configured)
68
  ```
69
 
70
+ ### Running hack/ Scripts
71
+ ```bash
72
+ # All hack/ scripts should use cache-dir/ from root for model loading
73
+ cd hack
74
+ python test_soft_minimum_quick.py # Most scripts auto-detect cache-dir
75
+ ```
76
+
77
  ## Architecture Overview
78
 
79
  ### Full-Stack Components
 
84
  - Custom hook: `useCrossword.js` manages API calls and puzzle state
85
  - Interactive crossword grid with cell navigation and solution reveal
86
  - Debug tab for visualizing word selection process (when enabled)
87
+ - Frontend controls for similarity temperature and difficulty weight tuning
88
 
89
  **Python Backend** (`crossword-app/backend-py/` - Primary)
90
  - FastAPI web framework serving both API and static frontend files
 
92
  - No static word files - all words generated on-demand from 100K+ vocabulary
93
  - WordNet-based clue generation with semantic definitions
94
  - Comprehensive caching system for models, embeddings, and vocabulary
95
+ - PyTorch tensor support with GPU optimization for embeddings
 
 
 
 
96
 
97
  ### Core Python Backend Components
98
 
 
103
  - Temperature-controlled softmax for balanced word selection randomness
104
  - 50% word overgeneration strategy for better crossword grid fitting
105
  - **Multi-topic intersection**: `_compute_multi_topic_similarities()` with vectorized soft minimum, geometric/harmonic means
106
+ - **Adaptive beta mechanism**: Automatically adjusts threshold (10.0β†’7.0β†’4.9... via 0.7x decay) to ensure 15+ word minimum
107
  - **Performance optimized**: 40x speedup through vectorized operations over loop-based approach
108
  - Key method: `generate_thematic_words()` - Returns words with semantic similarity scores and frequency tiers
109
 
 
142
 
143
  **Python Backend (Primary):**
144
  - FastAPI, uvicorn, pydantic (web framework)
145
+ - sentence-transformers, torch (AI word generation with GPU support)
146
  - wordfreq (vocabulary database)
147
  - nltk (WordNet clue generation)
148
  - scikit-learn (clustering and similarity)
149
  - numpy (embeddings and mathematical operations)
150
  - pytest, pytest-asyncio (testing)
151
 
 
 
 
 
152
  The application requires AI dependencies for core functionality - no fallback to static word lists.
153
 
154
  ### API Endpoints
 
169
  - `test-integration/test_local.py` - End-to-end integration testing
170
  - `test_integration_minimal.py` - Quick functionality test without heavy ML dependencies
171
 
172
+ **Multi-Topic Testing & Development Scripts** (`hack/`):
173
+ - `test_soft_minimum_quick.py` - Quick soft minimum method verification
174
+ - `test_optimized_soft_minimum.py` - Performance testing (40x speedup validation)
175
+ - `debug_adaptive_beta_bug.py` - Adaptive beta mechanism debugging
176
+ - `test_adaptive_fix.py` - Full vocabulary testing with adaptive beta
177
+ - `test_simpler_case.py` - Compatible topic testing (animals + nature)
178
+ - All hack/ scripts must use `cache-dir/` from project root for model loading
179
 
180
  **Frontend Tests:**
181
  - Component testing with React Testing Library (if configured)
 
288
  - βœ… **Debug visualization**: Optional debug tab for development/analysis
289
  - βœ… **Comprehensive caching**: Models, embeddings, and vocabulary cached for performance
290
  - βœ… **Modern stack**: FastAPI + React with Docker deployment ready
291
+ - βœ… **GPU support**: PyTorch tensor operations with optional CUDA acceleration
292
+
293
+ ### Cache Directory
294
+ The model cache is located at `cache-dir/` in the project root. All `hack/` scripts must use this directory for loading sentence-transformer models to ensure consistency.
Dockerfile.jetson ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Dockerfile for NVIDIA Jetson (ARM64) - Jetson Orin Nano, Xavier, etc.
2
+ # Uses NVIDIA's L4T PyTorch container as base for proper GPU support
3
+
4
+ # Stage 1: Builder
5
+ FROM nvcr.io/nvidia/l4t-pytorch:r36.2.0-pth2.1-py3 AS builder
6
+
7
+ WORKDIR /app
8
+
9
+ # Install Node.js for frontend build
10
+ RUN apt-get update && apt-get install -y \
11
+ curl \
12
+ git \
13
+ && curl -fsSL https://deb.nodesource.com/setup_18.x | bash - \
14
+ && apt-get install -y nodejs \
15
+ && rm -rf /var/lib/apt/lists/*
16
+
17
+ # Copy frontend package files and install dependencies
18
+ COPY crossword-app/frontend/package*.json ./frontend/
19
+ RUN cd frontend && npm ci
20
+
21
+ # Install Python dependencies (PyTorch already included in base image)
22
+ COPY crossword-app/backend-py/requirements.txt ./backend-py/
23
+ RUN pip install --no-cache-dir -r backend-py/requirements.txt
24
+
25
+ # Copy all source code
26
+ COPY crossword-app/frontend/ ./frontend/
27
+ COPY crossword-app/backend-py/ ./backend-py/
28
+ COPY crossword-app/words/ ./backend-py/words/
29
+
30
+ # Copy cache directory with pre-built models and NLTK data
31
+ COPY cache-dir/ ./cache-dir/
32
+ RUN chmod -R 755 ./cache-dir/ || true
33
+
34
+ # Build the React frontend
35
+ RUN cd frontend && npm run build
36
+
37
+ # Copy built frontend files to Python backend public directory
38
+ RUN mkdir -p backend-py/public && cp -r frontend/dist/* backend-py/public/
39
+
40
+ # Stage 2: Runtime
41
+ FROM nvcr.io/nvidia/l4t-pytorch:r36.2.0-pth2.1-py3 AS runtime
42
+
43
+ # Install minimal runtime dependencies
44
+ RUN apt-get update && apt-get install -y \
45
+ curl \
46
+ && rm -rf /var/lib/apt/lists/*
47
+
48
+ # Create non-root user
49
+ RUN useradd -m -u 1000 appuser
50
+
51
+ WORKDIR /app/backend-py
52
+
53
+ # Copy Python packages from builder (sentence-transformers, etc.)
54
+ COPY --from=builder /usr/local/lib/python3.10/dist-packages /usr/local/lib/python3.10/dist-packages
55
+
56
+ # Copy built application files
57
+ COPY --from=builder --chown=appuser:appuser /app/backend-py ./
58
+
59
+ # Copy cache directory
60
+ COPY --from=builder --chown=appuser:appuser /app/cache-dir /app/backend-py/cache
61
+
62
+ USER appuser
63
+
64
+ EXPOSE 7860
65
+
66
+ ENV NODE_ENV=production
67
+ ENV PORT=7860
68
+ ENV PYTHONPATH=/app/backend-py
69
+ ENV PYTHONUNBUFFERED=1
70
+ ENV PIP_NO_CACHE_DIR=1
71
+ ENV CACHE_DIR=/app/backend-py/cache
72
+ ENV NLTK_DATA=/app/backend-py/cache/nltk_data
73
+ ENV VOCAB_SOURCE=norvig
74
+ ENV NORVIG_VOCAB_PATH=/app/backend-py/words/norvig/count_1w100k.txt
75
+
76
+ CMD ["python", "-m", "uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860", "--workers", "1"]
hack/test_startrek_similarity.py ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Test semantic similarity between spock/kirk and startrek"""
3
+
4
+ import sys
5
+ import os
6
+ sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'crossword-app', 'backend-py', 'src'))
7
+
8
+ from services.thematic_word_service import ThematicWordService
9
+ import torch
10
+ import torch.nn.functional as F
11
+
12
+ # Initialize service with Norvig vocabulary
13
+ service = ThematicWordService(
14
+ cache_dir="../cache-dir",
15
+ vocab_size_limit=100000
16
+ )
17
+ service.initialize()
18
+
19
+ # Check if startrek is in vocabulary
20
+ if 'startrek' in service.vocabulary:
21
+ startrek_idx = service.vocabulary.index('startrek')
22
+ print(f'βœ… startrek found at index {startrek_idx} in vocabulary')
23
+ else:
24
+ print('❌ startrek NOT in vocabulary')
25
+ sys.exit(1)
26
+
27
+ # Get startrek embedding
28
+ startrek_embedding = service.vocab_embeddings[startrek_idx]
29
+ print(f'Startrek embedding shape: {startrek_embedding.shape}')
30
+
31
+ # Encode spock and kirk
32
+ spock_embedding = service.model.encode(['spock'], convert_to_tensor=True)[0]
33
+ kirk_embedding = service.model.encode(['kirk'], convert_to_tensor=True)[0]
34
+
35
+ # Calculate cosine similarities
36
+ startrek_norm = F.normalize(startrek_embedding.unsqueeze(0), p=2, dim=1)
37
+ spock_norm = F.normalize(spock_embedding.unsqueeze(0), p=2, dim=1)
38
+ kirk_norm = F.normalize(kirk_embedding.unsqueeze(0), p=2, dim=1)
39
+
40
+ sim_spock_startrek = torch.mm(spock_norm, startrek_norm.T).item()
41
+ sim_kirk_startrek = torch.mm(kirk_norm, startrek_norm.T).item()
42
+
43
+ print(f'\nπŸ“Š Semantic Similarities:')
44
+ print(f'spock β†’ startrek: {sim_spock_startrek:.4f}')
45
+ print(f'kirk β†’ startrek: {sim_kirk_startrek:.4f}')
46
+
47
+ # Now test with combined "spock kirk" as topic
48
+ combined_embedding = service.model.encode(['spock kirk'], convert_to_tensor=True)[0]
49
+ combined_norm = F.normalize(combined_embedding.unsqueeze(0), p=2, dim=1)
50
+ sim_combined_startrek = torch.mm(combined_norm, startrek_norm.T).item()
51
+ print(f'spock kirk β†’ startrek: {sim_combined_startrek:.4f}')
52
+
53
+ # Check similarity to some other words for comparison
54
+ test_words = ['enterprise', 'space', 'science', 'fiction', 'television', 'show', 'series', 'star', 'trek']
55
+ print(f'\nπŸ“Š Comparison with other words:')
56
+ for word in test_words:
57
+ if word in service.vocabulary:
58
+ word_idx = service.vocabulary.index(word)
59
+ word_embedding = service.vocab_embeddings[word_idx]
60
+ word_norm = F.normalize(word_embedding.unsqueeze(0), p=2, dim=1)
61
+ sim_spock = torch.mm(spock_norm, word_norm.T).item()
62
+ sim_kirk = torch.mm(kirk_norm, word_norm.T).item()
63
+ print(f'{word:12} β†’ spock: {sim_spock:.4f}, kirk: {sim_kirk:.4f}')
run-jetson.sh ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ set -e
3
+
4
+ # Build and run script for NVIDIA Jetson devices (Orin Nano, Xavier, etc.)
5
+
6
+ show_usage() {
7
+ echo "Usage: $0 [COMMAND]"
8
+ echo ""
9
+ echo "Commands:"
10
+ echo " build - Build the Jetson Docker image"
11
+ echo " run - Run the container with GPU support"
12
+ echo " both - Build and run (default)"
13
+ echo " shell - Run with bash shell for debugging"
14
+ echo ""
15
+ }
16
+
17
+ IMAGE_NAME="crossword-py-ai:jetson"
18
+ DOCKER_ARGS="--rm -p 7860:7860 --runtime nvidia \
19
+ -e ENABLE_DEBUG_TAB=true \
20
+ -e VOCAB_SOURCE=norvig \
21
+ -e DIFFICULTY_WEIGHT=0.2"
22
+
23
+ build_image() {
24
+ echo "πŸ”¨ Building Jetson Docker image..."
25
+ docker build -f Dockerfile.jetson -t $IMAGE_NAME .
26
+ }
27
+
28
+ run_container() {
29
+ echo "πŸš€ Running on Jetson with GPU..."
30
+ docker run $DOCKER_ARGS $IMAGE_NAME
31
+ }
32
+
33
+ run_shell() {
34
+ echo "🐚 Running shell for debugging..."
35
+ docker run -it $DOCKER_ARGS $IMAGE_NAME /bin/bash
36
+ }
37
+
38
+ # Parse command
39
+ COMMAND="${1:-both}"
40
+
41
+ case "$COMMAND" in
42
+ build)
43
+ build_image
44
+ ;;
45
+ run)
46
+ run_container
47
+ ;;
48
+ both)
49
+ build_image
50
+ run_container
51
+ ;;
52
+ shell)
53
+ build_image
54
+ run_shell
55
+ ;;
56
+ -h|--help|help)
57
+ show_usage
58
+ exit 0
59
+ ;;
60
+ *)
61
+ echo "Error: Unknown command '$COMMAND'"
62
+ show_usage
63
+ exit 1
64
+ ;;
65
+ esac