Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
"""
|
| 2 |
-
|
| 3 |
Multilingual semantic embeddings for tabletop RPG product classification
|
| 4 |
"""
|
| 5 |
|
|
@@ -13,9 +13,9 @@ import spaces # ZeroGPU decorator
|
|
| 13 |
# Using Qwen3-Embedding-4B for 2560 native dimensions (truncate to 1536 for production)
|
| 14 |
# Qwen3-4B is optimal for 1536 dims: 60% retention (vs 42.9% for GTE-Qwen2-7B)
|
| 15 |
MODEL_NAME = "Qwen/Qwen3-Embedding-4B"
|
| 16 |
-
print(f"
|
| 17 |
model = SentenceTransformer(MODEL_NAME, trust_remote_code=True)
|
| 18 |
-
print(f"
|
| 19 |
print(f" Native Dimensions: {model.get_sentence_embedding_dimension()}")
|
| 20 |
print(f" Max Seq Length: {model.max_seq_length}")
|
| 21 |
print(f" Matryoshka Support: Yes (truncate to any dimension ≤ {model.get_sentence_embedding_dimension()})")
|
|
@@ -64,7 +64,7 @@ def generate_embeddings(
|
|
| 64 |
# Qwen3-Embedding models support truncation to any dimension ≤ native_dims
|
| 65 |
if output_dimensions != native_dims:
|
| 66 |
if output_dimensions > native_dims:
|
| 67 |
-
print(f"
|
| 68 |
output_dimensions = native_dims
|
| 69 |
embeddings = embeddings[:, :output_dimensions]
|
| 70 |
|
|
@@ -84,9 +84,9 @@ def batch_generate(texts_input: str, use_instruction: bool, output_dims: int) ->
|
|
| 84 |
try:
|
| 85 |
embeddings = generate_embeddings(texts, use_instruction, output_dims)
|
| 86 |
|
| 87 |
-
result = f"
|
| 88 |
-
result += f"
|
| 89 |
-
result += f"
|
| 90 |
result += "First embedding preview:\n"
|
| 91 |
result += f"[{', '.join(f'{x:.3f}' for x in embeddings[0][:10])}...]\n"
|
| 92 |
|
|
@@ -170,7 +170,7 @@ def calculate_similarity(text1: str, text2: str, use_instruction: bool) -> str:
|
|
| 170 |
Calculate comprehensive similarity metrics between two texts
|
| 171 |
"""
|
| 172 |
if not text1.strip() or not text2.strip():
|
| 173 |
-
return "
|
| 174 |
|
| 175 |
try:
|
| 176 |
embeddings = generate_embeddings([text1, text2], use_instruction)
|
|
@@ -181,7 +181,7 @@ def calculate_similarity(text1: str, text2: str, use_instruction: bool) -> str:
|
|
| 181 |
metrics = calculate_all_similarities(emb1, emb2)
|
| 182 |
|
| 183 |
# Build result string
|
| 184 |
-
result = "
|
| 185 |
|
| 186 |
# Cosine Similarity (Primary)
|
| 187 |
emoji, interpretation = interpret_similarity(metrics['cosine'], 'cosine')
|
|
@@ -222,23 +222,23 @@ def calculate_similarity(text1: str, text2: str, use_instruction: bool) -> str:
|
|
| 222 |
return f"❌ Error: {str(e)}"
|
| 223 |
|
| 224 |
# Create Gradio interface
|
| 225 |
-
with gr.Blocks(title="
|
| 226 |
gr.Markdown("""
|
| 227 |
-
#
|
| 228 |
|
| 229 |
**Powered by Qwen3-Embedding-4B** - Advanced Multilingual Embedding Model
|
| 230 |
|
| 231 |
-
-
|
| 232 |
-
-
|
| 233 |
-
-
|
| 234 |
-
-
|
| 235 |
-
-
|
| 236 |
-
-
|
| 237 |
|
| 238 |
Perfect for: Product classification, semantic search, recommendations, multilingual matching
|
| 239 |
""")
|
| 240 |
|
| 241 |
-
with gr.Tab("
|
| 242 |
gr.Markdown("""
|
| 243 |
Generate semantic embeddings for product descriptions, titles, or any text.
|
| 244 |
Enter one text per line for batch processing.
|
|
@@ -271,7 +271,7 @@ with gr.Blocks(title="FairFate Embeddings API - Qwen3", theme=gr.themes.Soft())
|
|
| 271 |
inputs=[input_text, use_inst, output_dims],
|
| 272 |
)
|
| 273 |
|
| 274 |
-
with gr.Tab("
|
| 275 |
gr.Markdown("""
|
| 276 |
**Comprehensive Similarity Analysis** - Compare two texts using multiple metrics:
|
| 277 |
|
|
@@ -314,9 +314,9 @@ with gr.Blocks(title="FairFate Embeddings API - Qwen3", theme=gr.themes.Soft())
|
|
| 314 |
inputs=[text1, text2, use_inst_sim],
|
| 315 |
)
|
| 316 |
|
| 317 |
-
with gr.Tab("
|
| 318 |
gr.Markdown("""
|
| 319 |
-
##
|
| 320 |
|
| 321 |
### Python
|
| 322 |
|
|
@@ -324,7 +324,7 @@ with gr.Blocks(title="FairFate Embeddings API - Qwen3", theme=gr.themes.Soft())
|
|
| 324 |
import requests
|
| 325 |
import numpy as np
|
| 326 |
|
| 327 |
-
url = "https://
|
| 328 |
|
| 329 |
# Generate embeddings
|
| 330 |
texts = [
|
|
@@ -350,7 +350,7 @@ with gr.Blocks(title="FairFate Embeddings API - Qwen3", theme=gr.themes.Soft())
|
|
| 350 |
### TypeScript/JavaScript
|
| 351 |
|
| 352 |
```typescript
|
| 353 |
-
const url = 'https://
|
| 354 |
|
| 355 |
const response = await fetch(url, {
|
| 356 |
method: 'POST',
|
|
@@ -373,7 +373,7 @@ with gr.Blocks(title="FairFate Embeddings API - Qwen3", theme=gr.themes.Soft())
|
|
| 373 |
|
| 374 |
```bash
|
| 375 |
curl -X POST \\
|
| 376 |
-
https://
|
| 377 |
-H "Content-Type: application/json" \\
|
| 378 |
-d '{
|
| 379 |
"data": [["Your text here"], true, 1536],
|
|
@@ -381,7 +381,7 @@ with gr.Blocks(title="FairFate Embeddings API - Qwen3", theme=gr.themes.Soft())
|
|
| 381 |
}'
|
| 382 |
```
|
| 383 |
|
| 384 |
-
##
|
| 385 |
|
| 386 |
| Parameter | Type | Default | Description |
|
| 387 |
|-----------|------|---------|-------------|
|
|
@@ -389,7 +389,7 @@ with gr.Blocks(title="FairFate Embeddings API - Qwen3", theme=gr.themes.Soft())
|
|
| 389 |
| `use_instruction` | boolean | true | Add instruction prefix (improves accuracy) |
|
| 390 |
| `output_dimensions` | number | 1536 | Output size (32-3584, production default: 1536) |
|
| 391 |
|
| 392 |
-
##
|
| 393 |
|
| 394 |
- **Product Classification**: Auto-tag by genre, system, theme
|
| 395 |
- **Semantic Search**: Find by meaning, not keywords
|
|
@@ -397,20 +397,13 @@ with gr.Blocks(title="FairFate Embeddings API - Qwen3", theme=gr.themes.Soft())
|
|
| 397 |
- **Duplicate Detection**: Find similar listings
|
| 398 |
- **Multilingual Matching**: Cross-language similarity
|
| 399 |
|
| 400 |
-
##
|
| 401 |
-
|
| 402 |
-
| Batch Size | GPU Throughput | CPU Throughput |
|
| 403 |
-
|------------|----------------|----------------|
|
| 404 |
-
| 1 | ~800/sec | ~80/sec |
|
| 405 |
-
| 32 | ~4000/sec | ~250/sec |
|
| 406 |
-
|
| 407 |
-
## 🌍 Supported Languages
|
| 408 |
|
| 409 |
English, Spanish, French, German, Italian, Portuguese, Russian, Polish, Dutch, Czech,
|
| 410 |
Chinese, Japanese, Korean, Arabic, Hebrew, Hindi, Thai, Vietnamese, Indonesian,
|
| 411 |
Turkish, Swedish, Norwegian, Danish, Finnish, Greek, Romanian, Hungarian, and 80+ more!
|
| 412 |
|
| 413 |
-
##
|
| 414 |
|
| 415 |
```bibtex
|
| 416 |
@misc{qwen3-embedding-2025,
|
|
@@ -422,7 +415,7 @@ with gr.Blocks(title="FairFate Embeddings API - Qwen3", theme=gr.themes.Soft())
|
|
| 422 |
```
|
| 423 |
""")
|
| 424 |
|
| 425 |
-
with gr.Tab("
|
| 426 |
gr.Markdown(f"""
|
| 427 |
## Model Details
|
| 428 |
|
|
|
|
| 1 |
"""
|
| 2 |
+
FF Embeddings API - Qwen3-Embedding-4B
|
| 3 |
Multilingual semantic embeddings for tabletop RPG product classification
|
| 4 |
"""
|
| 5 |
|
|
|
|
| 13 |
# Using Qwen3-Embedding-4B for 2560 native dimensions (truncate to 1536 for production)
|
| 14 |
# Qwen3-4B is optimal for 1536 dims: 60% retention (vs 42.9% for GTE-Qwen2-7B)
|
| 15 |
MODEL_NAME = "Qwen/Qwen3-Embedding-4B"
|
| 16 |
+
print(f" Loading model: {MODEL_NAME}")
|
| 17 |
model = SentenceTransformer(MODEL_NAME, trust_remote_code=True)
|
| 18 |
+
print(f" Model loaded successfully")
|
| 19 |
print(f" Native Dimensions: {model.get_sentence_embedding_dimension()}")
|
| 20 |
print(f" Max Seq Length: {model.max_seq_length}")
|
| 21 |
print(f" Matryoshka Support: Yes (truncate to any dimension ≤ {model.get_sentence_embedding_dimension()})")
|
|
|
|
| 64 |
# Qwen3-Embedding models support truncation to any dimension ≤ native_dims
|
| 65 |
if output_dimensions != native_dims:
|
| 66 |
if output_dimensions > native_dims:
|
| 67 |
+
print(f"Warning: Requested {output_dimensions} dims but model has {native_dims}. Using {native_dims}.")
|
| 68 |
output_dimensions = native_dims
|
| 69 |
embeddings = embeddings[:, :output_dimensions]
|
| 70 |
|
|
|
|
| 84 |
try:
|
| 85 |
embeddings = generate_embeddings(texts, use_instruction, output_dims)
|
| 86 |
|
| 87 |
+
result = f"Generated {len(embeddings)} embeddings\n"
|
| 88 |
+
result += f"Dimensions: {len(embeddings[0])}\n"
|
| 89 |
+
result += f"Languages: 100+ supported\n\n"
|
| 90 |
result += "First embedding preview:\n"
|
| 91 |
result += f"[{', '.join(f'{x:.3f}' for x in embeddings[0][:10])}...]\n"
|
| 92 |
|
|
|
|
| 170 |
Calculate comprehensive similarity metrics between two texts
|
| 171 |
"""
|
| 172 |
if not text1.strip() or not text2.strip():
|
| 173 |
+
return "Error: Please provide both texts"
|
| 174 |
|
| 175 |
try:
|
| 176 |
embeddings = generate_embeddings([text1, text2], use_instruction)
|
|
|
|
| 181 |
metrics = calculate_all_similarities(emb1, emb2)
|
| 182 |
|
| 183 |
# Build result string
|
| 184 |
+
result = "**Comprehensive Similarity Analysis**\n\n"
|
| 185 |
|
| 186 |
# Cosine Similarity (Primary)
|
| 187 |
emoji, interpretation = interpret_similarity(metrics['cosine'], 'cosine')
|
|
|
|
| 222 |
return f"❌ Error: {str(e)}"
|
| 223 |
|
| 224 |
# Create Gradio interface
|
| 225 |
+
with gr.Blocks(title="FF Embeddings API - Qwen3", theme=gr.themes.Soft()) as demo:
|
| 226 |
gr.Markdown("""
|
| 227 |
+
# FF Embeddings API
|
| 228 |
|
| 229 |
**Powered by Qwen3-Embedding-4B** - Advanced Multilingual Embedding Model
|
| 230 |
|
| 231 |
+
- **100+ Languages** (English, Spanish, French, German, Chinese, Japanese, etc.)
|
| 232 |
+
- **2560 Native Dimensions** (matryoshka truncation to 1536 for production)
|
| 233 |
+
- **32K Context** (massive text support)
|
| 234 |
+
- **Instruction-Aware** (optimized for RPG content)
|
| 235 |
+
- **Matryoshka Support** (flexible 32-2560 dimensions)
|
| 236 |
+
- **Optimal for 1536 dims** (60% dimension retention)
|
| 237 |
|
| 238 |
Perfect for: Product classification, semantic search, recommendations, multilingual matching
|
| 239 |
""")
|
| 240 |
|
| 241 |
+
with gr.Tab("Generate Embeddings"):
|
| 242 |
gr.Markdown("""
|
| 243 |
Generate semantic embeddings for product descriptions, titles, or any text.
|
| 244 |
Enter one text per line for batch processing.
|
|
|
|
| 271 |
inputs=[input_text, use_inst, output_dims],
|
| 272 |
)
|
| 273 |
|
| 274 |
+
with gr.Tab("Similarity Calculator"):
|
| 275 |
gr.Markdown("""
|
| 276 |
**Comprehensive Similarity Analysis** - Compare two texts using multiple metrics:
|
| 277 |
|
|
|
|
| 314 |
inputs=[text1, text2, use_inst_sim],
|
| 315 |
)
|
| 316 |
|
| 317 |
+
with gr.Tab("API Documentation"):
|
| 318 |
gr.Markdown("""
|
| 319 |
+
## Quick Start
|
| 320 |
|
| 321 |
### Python
|
| 322 |
|
|
|
|
| 324 |
import requests
|
| 325 |
import numpy as np
|
| 326 |
|
| 327 |
+
url = "https://TiniThingsInc-fairfate-embeddings.hf.space/api/predict"
|
| 328 |
|
| 329 |
# Generate embeddings
|
| 330 |
texts = [
|
|
|
|
| 350 |
### TypeScript/JavaScript
|
| 351 |
|
| 352 |
```typescript
|
| 353 |
+
const url = 'https://TiniThingsInc-fairfate-embeddings.hf.space/api/predict';
|
| 354 |
|
| 355 |
const response = await fetch(url, {
|
| 356 |
method: 'POST',
|
|
|
|
| 373 |
|
| 374 |
```bash
|
| 375 |
curl -X POST \\
|
| 376 |
+
https://TiniThingsInc-fairfate-embeddings.hf.space/api/predict \\
|
| 377 |
-H "Content-Type: application/json" \\
|
| 378 |
-d '{
|
| 379 |
"data": [["Your text here"], true, 1536],
|
|
|
|
| 381 |
}'
|
| 382 |
```
|
| 383 |
|
| 384 |
+
## Parameters
|
| 385 |
|
| 386 |
| Parameter | Type | Default | Description |
|
| 387 |
|-----------|------|---------|-------------|
|
|
|
|
| 389 |
| `use_instruction` | boolean | true | Add instruction prefix (improves accuracy) |
|
| 390 |
| `output_dimensions` | number | 1536 | Output size (32-3584, production default: 1536) |
|
| 391 |
|
| 392 |
+
## Use Cases
|
| 393 |
|
| 394 |
- **Product Classification**: Auto-tag by genre, system, theme
|
| 395 |
- **Semantic Search**: Find by meaning, not keywords
|
|
|
|
| 397 |
- **Duplicate Detection**: Find similar listings
|
| 398 |
- **Multilingual Matching**: Cross-language similarity
|
| 399 |
|
| 400 |
+
## Supported Languages
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 401 |
|
| 402 |
English, Spanish, French, German, Italian, Portuguese, Russian, Polish, Dutch, Czech,
|
| 403 |
Chinese, Japanese, Korean, Arabic, Hebrew, Hindi, Thai, Vietnamese, Indonesian,
|
| 404 |
Turkish, Swedish, Norwegian, Danish, Finnish, Greek, Romanian, Hungarian, and 80+ more!
|
| 405 |
|
| 406 |
+
## Citation
|
| 407 |
|
| 408 |
```bibtex
|
| 409 |
@misc{qwen3-embedding-2025,
|
|
|
|
| 415 |
```
|
| 416 |
""")
|
| 417 |
|
| 418 |
+
with gr.Tab("Model Info"):
|
| 419 |
gr.Markdown(f"""
|
| 420 |
## Model Details
|
| 421 |
|