Simplify store tools: minimal .bas using PRODUCTS, SEARCH PRODUCTS, LLM keywords
This commit is contained in:
parent
bfeba96a38
commit
c11160d37d
3 changed files with 13 additions and 420 deletions
|
|
@ -1,186 +1,7 @@
|
||||||
' Shipping and Cubage Calculator
|
PARAM product_id AS INTEGER
|
||||||
' Calculates shipping dimensions, volume, and estimated costs
|
PARAM quantity AS INTEGER OPTIONAL
|
||||||
|
|
||||||
PARAM product_id AS INTEGER DESCRIPTION "Product ID to calculate shipping for"
|
product = PRODUCT product_id
|
||||||
PARAM quantity AS INTEGER OPTIONAL DESCRIPTION "Quantity of items (default: 1)"
|
shipping = LLM "Calculate shipping for: " + product + ", qty: " + quantity + ". Return JSON {dimensions: {length_cm, width_cm, height_cm}, weight_kg, volume_cm3, shipping_options: [{carrier, cost, days}]}"
|
||||||
PARAM destination_zip AS STRING OPTIONAL DESCRIPTION "Destination ZIP code for shipping estimate"
|
|
||||||
|
|
||||||
DESCRIPTION "Calculate shipping dimensions, volumetric weight, and estimated shipping cost"
|
RETURN shipping
|
||||||
|
|
||||||
' Set defaults
|
|
||||||
IF NOT quantity THEN
|
|
||||||
quantity = 1
|
|
||||||
END IF
|
|
||||||
|
|
||||||
' Find product by ID
|
|
||||||
product = FIND "Products.csv", "ProductID = " + product_id
|
|
||||||
|
|
||||||
IF NOT product THEN
|
|
||||||
TALK "❌ Product not found with ID: " + product_id
|
|
||||||
RETURN { "error": "Product not found" }
|
|
||||||
END IF
|
|
||||||
|
|
||||||
' Get product dimensions from extended fields or estimate from quantity per unit
|
|
||||||
' Default dimensions in cm (length x width x height)
|
|
||||||
dimensions = {}
|
|
||||||
|
|
||||||
' Parse quantity per unit for dimension hints
|
|
||||||
qty_unit = product.QuantityPerUnit
|
|
||||||
IF qty_unit THEN
|
|
||||||
' Extract numeric values and unit types
|
|
||||||
IF CONTAINS(qty_unit, "kg") THEN
|
|
||||||
dimensions.estimated_weight = EXTRACT_NUMBER(qty_unit)
|
|
||||||
dimensions.weight_unit = "kg"
|
|
||||||
ELSE IF CONTAINS(qty_unit, "ml") OR CONTAINS(qty_unit, "cc") THEN
|
|
||||||
volume_ml = EXTRACT_NUMBER(qty_unit)
|
|
||||||
dimensions.estimated_weight = volume_ml / 1000
|
|
||||||
dimensions.weight_unit = "kg"
|
|
||||||
ELSE IF CONTAINS(qty_unit, "oz") THEN
|
|
||||||
oz_value = EXTRACT_NUMBER(qty_unit)
|
|
||||||
dimensions.estimated_weight = oz_value * 0.0283495
|
|
||||||
dimensions.weight_unit = "kg"
|
|
||||||
ELSE IF CONTAINS(qty_unit, "lb") THEN
|
|
||||||
lb_value = EXTRACT_NUMBER(qty_unit)
|
|
||||||
dimensions.estimated_weight = lb_value * 0.453592
|
|
||||||
dimensions.weight_unit = "kg"
|
|
||||||
ELSE
|
|
||||||
' Default weight estimate based on category
|
|
||||||
dimensions.estimated_weight = 0.5
|
|
||||||
dimensions.weight_unit = "kg"
|
|
||||||
END IF
|
|
||||||
END IF
|
|
||||||
|
|
||||||
' Use AI to estimate package dimensions if not available
|
|
||||||
BEGIN SYSTEM PROMPT
|
|
||||||
You are a logistics expert. Estimate realistic package dimensions for shipping.
|
|
||||||
Consider the product type, typical packaging, and quantity per unit.
|
|
||||||
Return dimensions in centimeters and weight in kilograms.
|
|
||||||
END SYSTEM PROMPT
|
|
||||||
|
|
||||||
estimation_prompt = "Estimate shipping package dimensions for: " + product.ProductName + " (Quantity per unit: " + product.QuantityPerUnit + "). Return JSON: {\"length_cm\": number, \"width_cm\": number, \"height_cm\": number, \"weight_kg\": number, \"package_type\": string}"
|
|
||||||
|
|
||||||
ai_estimate = ASK estimation_prompt
|
|
||||||
package = PARSE JSON ai_estimate
|
|
||||||
|
|
||||||
' Calculate for requested quantity
|
|
||||||
total_packages = CEIL(quantity / EXTRACT_NUMBER(product.QuantityPerUnit))
|
|
||||||
IF total_packages < 1 THEN
|
|
||||||
total_packages = 1
|
|
||||||
END IF
|
|
||||||
|
|
||||||
' Calculate cubic dimensions
|
|
||||||
length_cm = package.length_cm
|
|
||||||
width_cm = package.width_cm
|
|
||||||
height_cm = package.height_cm
|
|
||||||
weight_kg = package.weight_kg * total_packages
|
|
||||||
|
|
||||||
' Volume in cubic centimeters
|
|
||||||
volume_cm3 = length_cm * width_cm * height_cm * total_packages
|
|
||||||
|
|
||||||
' Volume in cubic meters
|
|
||||||
volume_m3 = volume_cm3 / 1000000
|
|
||||||
|
|
||||||
' Volumetric weight (dimensional weight)
|
|
||||||
' Standard divisor: 5000 for international, 6000 for domestic
|
|
||||||
volumetric_weight_intl = volume_cm3 / 5000
|
|
||||||
volumetric_weight_domestic = volume_cm3 / 6000
|
|
||||||
|
|
||||||
' Billable weight is the greater of actual and volumetric
|
|
||||||
billable_weight_intl = MAX(weight_kg, volumetric_weight_intl)
|
|
||||||
billable_weight_domestic = MAX(weight_kg, volumetric_weight_domestic)
|
|
||||||
|
|
||||||
' Calculate shipping estimates
|
|
||||||
shipping_estimates = []
|
|
||||||
|
|
||||||
' Ground shipping estimate
|
|
||||||
ground = {}
|
|
||||||
ground.carrier = "Ground"
|
|
||||||
ground.billable_weight = billable_weight_domestic
|
|
||||||
ground.estimated_days = "5-7 business days"
|
|
||||||
ground.base_rate = 5.99
|
|
||||||
ground.per_kg_rate = 1.50
|
|
||||||
ground.estimated_cost = ground.base_rate + (ground.billable_weight * ground.per_kg_rate)
|
|
||||||
PUSH shipping_estimates, ground
|
|
||||||
|
|
||||||
' Express shipping estimate
|
|
||||||
express = {}
|
|
||||||
express.carrier = "Express"
|
|
||||||
express.billable_weight = billable_weight_domestic
|
|
||||||
express.estimated_days = "2-3 business days"
|
|
||||||
express.base_rate = 12.99
|
|
||||||
express.per_kg_rate = 2.50
|
|
||||||
express.estimated_cost = express.base_rate + (express.billable_weight * express.per_kg_rate)
|
|
||||||
PUSH shipping_estimates, express
|
|
||||||
|
|
||||||
' Overnight shipping estimate
|
|
||||||
overnight = {}
|
|
||||||
overnight.carrier = "Overnight"
|
|
||||||
overnight.billable_weight = billable_weight_intl
|
|
||||||
overnight.estimated_days = "Next business day"
|
|
||||||
overnight.base_rate = 24.99
|
|
||||||
overnight.per_kg_rate = 4.00
|
|
||||||
overnight.estimated_cost = overnight.base_rate + (overnight.billable_weight * overnight.per_kg_rate)
|
|
||||||
PUSH shipping_estimates, overnight
|
|
||||||
|
|
||||||
' Build response
|
|
||||||
result = {}
|
|
||||||
result.product_id = product_id
|
|
||||||
result.product_name = product.ProductName
|
|
||||||
result.quantity = quantity
|
|
||||||
result.packages = total_packages
|
|
||||||
|
|
||||||
result.dimensions = {
|
|
||||||
"length_cm": length_cm,
|
|
||||||
"width_cm": width_cm,
|
|
||||||
"height_cm": height_cm,
|
|
||||||
"package_type": package.package_type
|
|
||||||
}
|
|
||||||
|
|
||||||
result.weight = {
|
|
||||||
"actual_kg": weight_kg,
|
|
||||||
"volumetric_domestic_kg": volumetric_weight_domestic,
|
|
||||||
"volumetric_intl_kg": volumetric_weight_intl,
|
|
||||||
"billable_domestic_kg": billable_weight_domestic,
|
|
||||||
"billable_intl_kg": billable_weight_intl
|
|
||||||
}
|
|
||||||
|
|
||||||
result.volume = {
|
|
||||||
"cm3": volume_cm3,
|
|
||||||
"m3": volume_m3
|
|
||||||
}
|
|
||||||
|
|
||||||
result.shipping_options = shipping_estimates
|
|
||||||
|
|
||||||
' Display results
|
|
||||||
TALK "📦 **Shipping Calculator Results**"
|
|
||||||
TALK ""
|
|
||||||
TALK "**Product:** " + product.ProductName
|
|
||||||
TALK "**Quantity:** " + quantity + " (" + total_packages + " package(s))"
|
|
||||||
TALK ""
|
|
||||||
TALK "**Package Dimensions:**"
|
|
||||||
TALK " 📏 " + length_cm + " × " + width_cm + " × " + height_cm + " cm"
|
|
||||||
TALK " 📦 Volume: " + FORMAT(volume_cm3, "#,##0") + " cm³ (" + FORMAT(volume_m3, "0.000") + " m³)"
|
|
||||||
TALK " ⚖️ Type: " + package.package_type
|
|
||||||
TALK ""
|
|
||||||
TALK "**Weight Analysis:**"
|
|
||||||
TALK " Actual Weight: " + FORMAT(weight_kg, "0.00") + " kg"
|
|
||||||
TALK " Volumetric (Domestic): " + FORMAT(volumetric_weight_domestic, "0.00") + " kg"
|
|
||||||
TALK " Volumetric (Intl): " + FORMAT(volumetric_weight_intl, "0.00") + " kg"
|
|
||||||
TALK " **Billable Weight:** " + FORMAT(billable_weight_domestic, "0.00") + " kg"
|
|
||||||
TALK ""
|
|
||||||
TALK "**Shipping Options:**"
|
|
||||||
|
|
||||||
FOR EACH option IN shipping_estimates
|
|
||||||
TALK " 🚚 **" + option.carrier + "**: $" + FORMAT(option.estimated_cost, "0.00") + " (" + option.estimated_days + ")"
|
|
||||||
NEXT
|
|
||||||
|
|
||||||
' Log calculation for analytics
|
|
||||||
LOG "shipping_calculation", {
|
|
||||||
"product_id": product_id,
|
|
||||||
"quantity": quantity,
|
|
||||||
"volume_cm3": volume_cm3,
|
|
||||||
"weight_kg": weight_kg,
|
|
||||||
"timestamp": NOW()
|
|
||||||
}
|
|
||||||
|
|
||||||
RETURN result
|
|
||||||
|
|
|
||||||
|
|
@ -1,117 +1,7 @@
|
||||||
' Product Classification Tool
|
PARAM query AS STRING
|
||||||
' Classifies products into categories using AI and store taxonomy
|
|
||||||
|
|
||||||
PARAM product_name AS STRING DESCRIPTION "Product name to classify (e.g., 'nike air max shoes')"
|
|
||||||
PARAM include_suggestions AS BOOLEAN OPTIONAL DESCRIPTION "Include alternative category suggestions"
|
|
||||||
|
|
||||||
DESCRIPTION "Classify a product into the store's category taxonomy using AI"
|
|
||||||
|
|
||||||
' Load store categories for context
|
|
||||||
categories = FIND "Categories.csv"
|
categories = FIND "Categories.csv"
|
||||||
|
result = SEARCH PRODUCTS query, 5
|
||||||
|
enhanced = LLM "Classify '" + query + "' into categories: " + categories + ". Similar products: " + result + ". Return JSON {category_id, category_name, confidence, attributes: {brand, type}}"
|
||||||
|
|
||||||
' Build taxonomy tree for AI context
|
RETURN enhanced
|
||||||
taxonomy = ""
|
|
||||||
FOR EACH cat IN categories
|
|
||||||
taxonomy = taxonomy + cat.CategoryID + ": " + cat.CategoryName + " - " + cat.Description + "\n"
|
|
||||||
NEXT
|
|
||||||
|
|
||||||
' Search existing products for similar items
|
|
||||||
similar_products = SEARCH "Products.csv", product_name, 5
|
|
||||||
|
|
||||||
similar_context = ""
|
|
||||||
IF similar_products THEN
|
|
||||||
FOR EACH p IN similar_products
|
|
||||||
similar_context = similar_context + "- " + p.ProductName + " (Category: " + p.CategoryID + ")\n"
|
|
||||||
NEXT
|
|
||||||
END IF
|
|
||||||
|
|
||||||
' Use AI to classify the product
|
|
||||||
BEGIN SYSTEM PROMPT
|
|
||||||
You are a product classification expert. Your task is to classify products into the correct category based on the store's taxonomy.
|
|
||||||
|
|
||||||
Available Categories:
|
|
||||||
${taxonomy}
|
|
||||||
|
|
||||||
Similar existing products in catalog:
|
|
||||||
${similar_context}
|
|
||||||
|
|
||||||
Rules:
|
|
||||||
1. Return the most specific category that fits
|
|
||||||
2. Consider product attributes like brand, type, material
|
|
||||||
3. If uncertain, suggest the most likely category with confidence level
|
|
||||||
4. Provide reasoning for the classification
|
|
||||||
END SYSTEM PROMPT
|
|
||||||
|
|
||||||
classification_prompt = "Classify this product: '" + product_name + "'\n\nReturn JSON format: {\"category_id\": number, \"category_name\": string, \"confidence\": number (0-100), \"reasoning\": string, \"attributes\": {\"brand\": string, \"type\": string, \"material\": string}}"
|
|
||||||
|
|
||||||
result = ASK classification_prompt
|
|
||||||
|
|
||||||
' Parse AI response
|
|
||||||
classification = PARSE JSON result
|
|
||||||
|
|
||||||
' Validate category exists
|
|
||||||
valid_category = FIND "Categories.csv", "CategoryID = " + classification.category_id
|
|
||||||
|
|
||||||
IF NOT valid_category THEN
|
|
||||||
' Fallback to closest match
|
|
||||||
TALK "⚠️ AI suggested invalid category, finding closest match..."
|
|
||||||
valid_category = FIND "Categories.csv", "CategoryName LIKE '%" + classification.category_name + "%'"
|
|
||||||
IF valid_category THEN
|
|
||||||
classification.category_id = valid_category.CategoryID
|
|
||||||
END IF
|
|
||||||
END IF
|
|
||||||
|
|
||||||
' Build response
|
|
||||||
response = {}
|
|
||||||
response.product_name = product_name
|
|
||||||
response.category_id = classification.category_id
|
|
||||||
response.category_name = classification.category_name
|
|
||||||
response.confidence = classification.confidence
|
|
||||||
response.reasoning = classification.reasoning
|
|
||||||
response.attributes = classification.attributes
|
|
||||||
|
|
||||||
' Add suggestions if requested
|
|
||||||
IF include_suggestions THEN
|
|
||||||
suggestions_prompt = "Suggest 2 alternative categories for '" + product_name + "' from: " + taxonomy
|
|
||||||
alt_result = ASK suggestions_prompt
|
|
||||||
response.alternative_categories = PARSE JSON alt_result
|
|
||||||
END IF
|
|
||||||
|
|
||||||
' Log classification for analytics
|
|
||||||
LOG "product_classification", {
|
|
||||||
"product": product_name,
|
|
||||||
"category": classification.category_id,
|
|
||||||
"confidence": classification.confidence,
|
|
||||||
"timestamp": NOW()
|
|
||||||
}
|
|
||||||
|
|
||||||
TALK "📦 **Product Classification Result**"
|
|
||||||
TALK ""
|
|
||||||
TALK "**Product:** " + product_name
|
|
||||||
TALK "**Category:** " + classification.category_name + " (ID: " + classification.category_id + ")"
|
|
||||||
TALK "**Confidence:** " + classification.confidence + "%"
|
|
||||||
TALK "**Reasoning:** " + classification.reasoning
|
|
||||||
TALK ""
|
|
||||||
|
|
||||||
IF classification.attributes THEN
|
|
||||||
TALK "**Detected Attributes:**"
|
|
||||||
IF classification.attributes.brand THEN
|
|
||||||
TALK " • Brand: " + classification.attributes.brand
|
|
||||||
END IF
|
|
||||||
IF classification.attributes.type THEN
|
|
||||||
TALK " • Type: " + classification.attributes.type
|
|
||||||
END IF
|
|
||||||
IF classification.attributes.material THEN
|
|
||||||
TALK " • Material: " + classification.attributes.material
|
|
||||||
END IF
|
|
||||||
END IF
|
|
||||||
|
|
||||||
IF include_suggestions AND response.alternative_categories THEN
|
|
||||||
TALK ""
|
|
||||||
TALK "**Alternative Categories:**"
|
|
||||||
FOR EACH alt IN response.alternative_categories
|
|
||||||
TALK " • " + alt.category_name + " (" + alt.confidence + "% confidence)"
|
|
||||||
NEXT
|
|
||||||
END IF
|
|
||||||
|
|
||||||
RETURN response
|
|
||||||
|
|
|
||||||
|
|
@ -1,124 +1,6 @@
|
||||||
' Product Search with Autocomplete and AI Descriptions
|
PARAM query AS STRING
|
||||||
' Provides fast product search with intelligent suggestions and enriched descriptions
|
|
||||||
|
|
||||||
PARAM query AS STRING DESCRIPTION "Search query (e.g., 'chai tea', 'chocolate', 'sauce')"
|
result = SEARCH PRODUCTS query, 10
|
||||||
PARAM limit AS INTEGER OPTIONAL DESCRIPTION "Maximum results to return (default: 10)"
|
enhanced = LLM "Enhance these product results with descriptions: " + result + ". Return JSON array with id, name, price, description"
|
||||||
PARAM include_description AS BOOLEAN OPTIONAL DESCRIPTION "Generate AI-enhanced product descriptions"
|
|
||||||
|
|
||||||
DESCRIPTION "Search products with autocomplete and AI-generated descriptions"
|
RETURN enhanced
|
||||||
|
|
||||||
' Set defaults
|
|
||||||
IF NOT limit THEN
|
|
||||||
limit = 10
|
|
||||||
END IF
|
|
||||||
|
|
||||||
' Perform fast search across products
|
|
||||||
results = SEARCH "Products.csv", query, limit
|
|
||||||
|
|
||||||
IF NOT results OR LEN(results) = 0 THEN
|
|
||||||
TALK "🔍 No products found matching '" + query + "'"
|
|
||||||
|
|
||||||
' Use AI to suggest alternatives
|
|
||||||
BEGIN SYSTEM PROMPT
|
|
||||||
You are a helpful store assistant. The user searched for a product that wasn't found.
|
|
||||||
Suggest what they might be looking for or alternative search terms.
|
|
||||||
END SYSTEM PROMPT
|
|
||||||
|
|
||||||
suggestion = ASK "The user searched for '" + query + "' but no products were found. Suggest alternatives or clarify what they might want."
|
|
||||||
TALK suggestion
|
|
||||||
|
|
||||||
RETURN { "results": [], "suggestions": suggestion }
|
|
||||||
END IF
|
|
||||||
|
|
||||||
' Load categories for enrichment
|
|
||||||
categories = FIND "Categories.csv"
|
|
||||||
|
|
||||||
' Build category lookup
|
|
||||||
category_map = {}
|
|
||||||
FOR EACH cat IN categories
|
|
||||||
category_map[cat.CategoryID] = cat.CategoryName
|
|
||||||
NEXT
|
|
||||||
|
|
||||||
' Enrich results with category names
|
|
||||||
enriched_results = []
|
|
||||||
FOR EACH product IN results
|
|
||||||
item = {}
|
|
||||||
item.id = product.ProductID
|
|
||||||
item.name = product.ProductName
|
|
||||||
item.price = product.UnitPrice
|
|
||||||
item.stock = product.UnitsInStock
|
|
||||||
item.category_id = product.CategoryID
|
|
||||||
item.category_name = category_map[product.CategoryID]
|
|
||||||
item.quantity_per_unit = product.QuantityPerUnit
|
|
||||||
item.discontinued = product.Discontinued
|
|
||||||
item.reorder_level = product.ReorderLevel
|
|
||||||
|
|
||||||
' Generate AI description if requested
|
|
||||||
IF include_description THEN
|
|
||||||
BEGIN SYSTEM PROMPT
|
|
||||||
You are a product copywriter. Write a brief, compelling product description (2-3 sentences).
|
|
||||||
Focus on benefits and key features. Be concise and engaging.
|
|
||||||
END SYSTEM PROMPT
|
|
||||||
|
|
||||||
desc_prompt = "Write a product description for: " + product.ProductName + " (Category: " + item.category_name + ", Quantity: " + product.QuantityPerUnit + ", Price: $" + product.UnitPrice + ")"
|
|
||||||
item.ai_description = ASK desc_prompt
|
|
||||||
END IF
|
|
||||||
|
|
||||||
PUSH enriched_results, item
|
|
||||||
NEXT
|
|
||||||
|
|
||||||
' Build autocomplete suggestions for future searches
|
|
||||||
related_terms = []
|
|
||||||
FOR EACH product IN results
|
|
||||||
words = SPLIT(product.ProductName, " ")
|
|
||||||
FOR EACH word IN words
|
|
||||||
IF LEN(word) > 3 AND NOT CONTAINS(related_terms, word) THEN
|
|
||||||
PUSH related_terms, word
|
|
||||||
END IF
|
|
||||||
NEXT
|
|
||||||
NEXT
|
|
||||||
|
|
||||||
' Display results
|
|
||||||
TALK "🔍 **Search Results for '" + query + "'** (" + LEN(enriched_results) + " found)"
|
|
||||||
TALK ""
|
|
||||||
|
|
||||||
FOR EACH item IN enriched_results
|
|
||||||
stock_status = "✅ In Stock"
|
|
||||||
IF item.stock = 0 THEN
|
|
||||||
stock_status = "❌ Out of Stock"
|
|
||||||
ELSE IF item.stock < item.reorder_level THEN
|
|
||||||
stock_status = "⚠️ Low Stock"
|
|
||||||
END IF
|
|
||||||
|
|
||||||
IF item.discontinued = 1 THEN
|
|
||||||
stock_status = "🚫 Discontinued"
|
|
||||||
END IF
|
|
||||||
|
|
||||||
TALK "**" + item.name + "** - $" + item.price
|
|
||||||
TALK " Category: " + item.category_name + " | " + item.quantity_per_unit
|
|
||||||
TALK " " + stock_status + " (" + item.stock + " units)"
|
|
||||||
|
|
||||||
IF include_description AND item.ai_description THEN
|
|
||||||
TALK " 📝 " + item.ai_description
|
|
||||||
END IF
|
|
||||||
TALK ""
|
|
||||||
NEXT
|
|
||||||
|
|
||||||
' Show related search terms
|
|
||||||
IF LEN(related_terms) > 0 THEN
|
|
||||||
TALK "**Related searches:** " + JOIN(related_terms, ", ")
|
|
||||||
END IF
|
|
||||||
|
|
||||||
' Log search for analytics
|
|
||||||
LOG "product_search", {
|
|
||||||
"query": query,
|
|
||||||
"results_count": LEN(enriched_results),
|
|
||||||
"timestamp": NOW()
|
|
||||||
}
|
|
||||||
|
|
||||||
RETURN {
|
|
||||||
"query": query,
|
|
||||||
"results": enriched_results,
|
|
||||||
"total": LEN(enriched_results),
|
|
||||||
"related_terms": related_terms
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue