Search Shortcut cmd + k | ctrl + k
anofox_similarity

Multi-modal product similarity search for manufacturing supply chain planning. Find similar materials by BOM component overlap (Jaccard), graph-structural similarity (Weisfeiler-Lehman kernel), text embeddings, and transactional patterns, with predecessor detection and cold-start analog matching for demand forecasting.

Maintainer(s): jrosskopf

Compatibility Matrix

This table covers all DuckDB releases that have not reached end-of-life, including LTS releases, and shows the 2 most recent patch releases of each. Older patch releases are not listed, but the extension may be available for them as well.

Platform 1.4.4 1.4.5 1.5.5 1.5.6 2.0.0
Linux AMD64
Linux ARM64
macOS AMD64
macOS ARM64
Windows AMD64
Windows ARM64
WebAssembly

Installing and Loading

INSTALL anofox_similarity FROM community;
LOAD anofox_similarity;

Example

-- Components (BOM) for each product
CREATE TABLE bom_items (parent_id VARCHAR, child_id VARCHAR);
INSERT INTO bom_items VALUES
  ('PUMP-A', 'SEAL-001'), ('PUMP-A', 'BEARING-X'), ('PUMP-A', 'MOTOR-M1'),
  ('PUMP-B', 'SEAL-001'), ('PUMP-B', 'BEARING-X'), ('PUMP-B', 'MOTOR-M1'), ('PUMP-B', 'GASKET-Y'),
  ('PUMP-C', 'FILTER-F1'), ('PUMP-C', 'VALVE-V2');

-- Find the 3 materials most similar to PUMP-A by shared components
SELECT material_id, similarity, shared_components, total_components
FROM find_similar_materials_jaccard('PUMP-A', 3, bom_table := 'bom_items')
ORDER BY similarity DESC;
-- PUMP-B   0.75  3  4   (high overlap)
-- PUMP-C   0.0   0  5   (disjoint)

-- Structural similarity that also weighs BOM topology, not just component sets
SELECT wl_kernel_similarity('PUMP-A', 'PUMP-B', iterations := 3, bom_table := 'bom_items');

About anofox_similarity

anofox_similarity helps manufacturers answer "which existing product is this new one most like?" directly against ERP master data (SAP, Microsoft Dynamics 365, or a plain bom_items table), which is the key input for cold-start demand forecasting, predecessor detection, and analog-based planning for products with no sales history yet.

Similarity signals compose across several table functions:

  • find_similar_materials_jaccard ranks materials by BOM component overlap.
  • wl_kernel_similarity / find_similar_materials_wl_kernel use a Weisfeiler-Lehman graph kernel to capture BOM topology, not just which components are shared but how they're structurally arranged.
  • infer_predecessors detects predecessor/successor relationships from structural similarity plus temporal anti-correlation in goods-movement history (an old part's usage declining as a new part's usage rises).
  • cold_start_analogs finds established products to seed a forecast for a brand-new material with no history at all.
  • compute_fused_embeddings combines structural, transactional, and text embedding signals into one fusable vector, indexable with DuckDB's vss extension via the bundled HNSW index helpers.

SAP (MARA/MAKT/MAST/STKO/STPO) and Dynamics 365 transformation macros (sap_to_bom_items, sap_to_materials_with_desc, …) normalize common ERP exports into the BOM/material schema the rest of the extension expects, so integration is mostly SELECT * FROM sap_to_bom_items(...).

All table functions accept a fully qualified read-only DuckDB database and degrade gracefully when optional companion extensions (anofox_forecast for time-series features, duckpgq for property-graph BOM queries) are not loaded.

The extension collects anonymous usage telemetry (an envelope-only extension_loaded event; never table names, keys, or SQL). Disable with SET anofox_telemetry_enabled = false or DATAZOO_DISABLE_TELEMETRY=1; see TELEMETRY.md in the repository.

Added Functions

function_name function_type description comment examples
aggregate_material_components table_macro NULL NULL  
bom_common_components table_macro NULL NULL  
bom_dfs_neighborhood table_macro NULL NULL  
bom_explosion_1level table_macro NULL NULL  
bom_explosion_multilevel table_macro NULL NULL  
bom_to_items table_macro NULL NULL  
bom_where_used table_macro NULL NULL  
check_anofox_forecast_available macro NULL NULL  
check_duckpgq_available macro NULL NULL  
check_statistics_freshness table Returns a single-row summary of the transactional_embedding_statistics table including stat_count, max_samples, current_version, last_updated, and is_fresh. is_fresh is TRUE when >= 30 statistics rows exist and last_updated is within 7 days. NULL [SELECT * FROM check_statistics_freshness();]
cold_start_analogs table Finds structural analogs for a cold-start material (one with little or no demand history). Returns established materials that are structurally similar and have at least min_history_months of goods movement data, enabling surrogate forecasting. NULL [SELECT * FROM cold_start_analogs('NEW-PART', 5);, SELECT * FROM cold_start_analogs('NEW-PART', 10, min_history_months := 12, min_similarity := 0.4);]
compute_domain_specific_statistics table_macro NULL NULL  
compute_fused_embeddings table_macro NULL NULL  
compute_jaccard_embeddings table Computes and RETURNS 128-dimensional MinHash embeddings (one row per material/seed) from BOM component sets; it does not write to material_embeddings — aggregate and upsert the result yourself. Each material's embedding is derived from its set of direct child components. Requires bom_table with columns parent_id and child_id. NULL [SELECT * FROM compute_jaccard_embeddings();, SELECT * FROM compute_jaccard_embeddings(bom_table := 'sap_stpo');]
compute_textual_embeddings table_macro NULL NULL  
compute_transactional_embeddings table Computes 128-dimensional transactional embeddings from goods movement data and upserts them into material_embeddings. Features include demand velocity, seasonality, frequency, and quantity statistics normalized against transactional_embedding_statistics. Supports batched computation via batch_size and batch_offset. NULL [SELECT * FROM compute_transactional_embeddings();, SELECT * FROM compute_transactional_embeddings(movements_table := 'sap_mseg', time_window_days := 365);, SELECT * FROM compute_transactional_embeddings(batch_size := 1000, batch_offset := 0);]
create_bom_property_graph table_macro NULL NULL  
dynamics365_to_bom_component table_macro NULL NULL  
dynamics365_to_bom_header table_macro NULL NULL  
dynamics365_to_materials table_macro NULL NULL  
embed_text macro NULL NULL  
embedding_backend scalar Generates a 384-dimensional text embedding (FLOAT[384]) for the given text. provider selects the backend and provider_config is a JSON string of provider-specific options (api_key, endpoint). NOTE: unless the extension is built with a local OpenVINO model or a real API backend is configured, all providers return a deterministic, hash-based PLACEHOLDER embedding (useful for wiring and tests, not semantic search). NULL [SELECT embedding_backend('diesel pump', 'gemma-local', '{}');, SELECT embedding_backend('valve seat', 'gemini-api', '{"api_key": "…"}');]
extract_material_descriptions table_macro NULL NULL  
extract_ts_features table_macro NULL NULL  
filter_recent_movements table_macro NULL NULL  
find_similar_materials_jaccard table Finds the k most structurally similar materials to a query material using exact Jaccard similarity on BOM component sets. Returns material_id, similarity, shared_components, and total_components. Filtered by min_similarity threshold. NULL [SELECT * FROM find_similar_materials_jaccard('MAT-001', 10);, SELECT * FROM find_similar_materials_jaccard('MAT-001', 20, min_similarity := 0.3);]
find_similar_materials_wl_kernel table Finds the k most structurally similar materials using the Weisfeiler-Lehman graph kernel, which captures multi-hop BOM structure beyond direct component overlap. iterations controls the number of WL refinement rounds (default 3). NULL [SELECT * FROM find_similar_materials_wl_kernel('MAT-001', 10);, SELECT * FROM find_similar_materials_wl_kernel('MAT-001', 10, iterations := 3, min_similarity := 0.2);]
fuse_embeddings scalar Fuses structural (FLOAT[256]), textual (FLOAT[384]), and transactional (FLOAT[128]) embeddings into a single 768-dimensional combined embedding using weighted concatenation. Each component is scaled by sqrt(weight). Weights do not need to sum to 1.0. NULL [SELECT fuse_embeddings(se, te, xe, {'structural':0.5,'textual':0.5,'transactional':0.0}) FROM material_embeddings;]
hnsw_compact_index pragma NULL NULL  
hnsw_index_scan table NULL NULL  
infer_predecessors table Identifies predecessor (superseded) materials for a given successor by combining BOM structural similarity with anti-correlated consumption patterns. Returns predecessor candidates ranked by confidence score along with correlation, similarity, and temporal overlap data. Useful for lifecycle transition planning and inventory run-down. NULL [SELECT * FROM infer_predecessors('NEW-PART');, SELECT * FROM infer_predecessors('NEW-PART', lookback_months := 24, min_similarity := 0.5, min_confidence := 0.6, lag_weeks := 4);]
items_to_bom table_macro NULL NULL  
jaccard_similarity scalar Computes the Jaccard similarity coefficient between two lists treated as sets. Returns a value in [0.0, 1.0] equal to |intersection| / |union|. Duplicates within each list are deduplicated before comparison. Returns NULL if either argument is NULL; returns 0.0 if both lists are empty. NULL [SELECT jaccard_similarity(['A','B','C'], ['B','C','D']); – 0.5, SELECT jaccard_similarity([1,2,3,4], [3,4,5,6]); – 0.3333]
pragma_hnsw_index_info table NULL NULL  
recompute_embedding_statistics table_macro NULL NULL  
sap_to_bom_items table_macro NULL NULL  
sap_to_materials table_macro NULL NULL  
sap_to_materials_with_desc table_macro NULL NULL  
vss_join table_macro NULL NULL  
vss_match table_macro NULL NULL  
wl_fingerprint table_macro NULL NULL  
wl_kernel_similarity macro NULL NULL  

Overloaded Functions

This extension does not add any function overloads.

Added Types

This extension does not add any types.

Added Settings

name description input_type scope aliases
anofox_telemetry_enabled Enable or disable anonymous usage telemetry BOOLEAN GLOBAL []
anofox_telemetry_key PostHog API key for telemetry VARCHAR GLOBAL []
datazoo_banner Show the DataZoo feedback banner when an extension is loaded in an interactive terminal (at most once a day per extension). BOOLEAN GLOBAL []
hnsw_ef_search experimental: override the ef_search parameter when scanning HNSW indexes BIGINT GLOBAL []
hnsw_enable_experimental_persistence experimental: enable creating HNSW indexes in persistent databases BOOLEAN GLOBAL []