Back

Dec 12, 2025

Semantic Product Search

H
Hyperfold Team
SearchAgents

Understanding Embeddings

Semantic search uses vector embeddings to find products based on meaning, not just keywords. This enables natural language queries like "waterproof shoes for running in rain" to match relevant products.

Hyperfold uses Vertex AI's text-embedding model to generate 768-dimensional vectors for each product.

Catalog Indexing

Index your products with semantic embeddings:

typescript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// Semantic indexing with Vertex AI
import { VertexAI } from '@google-cloud/vertexai';
const vertexAI = new VertexAI({ project: 'your-project' });
const embeddingModel = vertexAI.preview.getGenerativeModel({
model: 'text-embedding-004',
});
async function indexProduct(product: Product) {
// Create rich text for embedding
const textToEmbed = [
product.name,
product.description,
product.attributes.brand,
product.semantics.category,
...product.semantics.usage_context,
...product.semantics.visual_tags,
].join(' ');
// Generate embedding
const response = await embeddingModel.generateContent({
contents: [{ role: 'user', parts: [{ text: textToEmbed }] }],
});
const embedding = response.response.candidates[0].content.parts[0].embedding;
// Store in Firestore with vector index
await db.collection('products').doc(product.product_id).set({
...product,
embedding: FieldValue.vector(embedding),
});
}
Run bulk indexing with hyperfold catalog optimize --embedto generate embeddings for your entire catalog.

Search Queries

Handle semantic search requests from buyer agents:

typescript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// Semantic search implementation
@OnACPEvent('search')
async handleSearch(request: SearchRequest) {
const { query, filters, limit = 10 } = request;
// Generate query embedding
const queryEmbedding = await generateEmbedding(query);
// Vector similarity search
const results = await db.collection('products')
.findNearest({
vectorField: 'embedding',
queryVector: queryEmbedding,
limit: limit * 2, // Fetch extra for filtering
distanceMeasure: 'COSINE',
});
// Apply filters
let filtered = results.docs.map(doc => doc.data());
if (filters?.price_max) {
filtered = filtered.filter(p => p.pricing.list_price <= filters.price_max);
}
if (filters?.in_stock) {
filtered = filtered.filter(p => p.inventory.quantity > 0);
}
return {
results: filtered.slice(0, limit),
total_count: filtered.length,
semantic_confidence: calculateConfidence(results),
};
}

Filtering Results

Combine semantic similarity with structured filters:

typescript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Search with filters
const results = await search({
query: "running shoes for marathon",
filters: {
price_max: 200,
size: "10",
color_preference: ["blue", "black"],
in_stock: true,
},
buyer_context: {
loyalty_tier: "gold",
location: "US",
},
});

Search Optimization

Tips for improving search quality:

  • Rich product descriptions: Include usage contexts and attributes
  • Consistent taxonomy: Use standardized category names
  • Regular re-indexing: Update embeddings when descriptions change
  • Query expansion: Add synonyms and related terms