nutricore / tools.py
GitHub Actions
Deploy: fd7352bd4a3722db55d92a07f0e5e9dd211faf54
0d8c5a5
Raw
History Blame Contribute Delete
11 kB
"""
Nutricore Food Solution - Agent Tools (7 buyer-focused tools)
"""
import json
from agents import function_tool
from database import get_db, DELIVERY_INFO, RECIPES
# ─── Helpers ──────────────────────────────────────────────────────────────────
def _row_to_dict(row) -> dict:
return dict(row) if row else {}
def _get_product_by_id(product_id: int) -> dict:
conn = get_db()
cur = conn.cursor()
cur.execute("SELECT * FROM products WHERE id = %s", (product_id,))
row = cur.fetchone()
cur.close()
conn.close()
return _row_to_dict(row)
# ─── Tool Implementations ─────────────────────────────────────────────────────
def browse_products_impl(category: str = "") -> dict:
conn = get_db()
cur = conn.cursor()
if category and category.lower() != "all":
cur.execute(
"SELECT id, name, category, weight, price, description, image FROM products WHERE LOWER(category) LIKE %s ORDER BY id",
(f"%{category.lower()}%",)
)
else:
cur.execute(
"SELECT id, name, category, weight, price, description, image FROM products ORDER BY id"
)
rows = cur.fetchall()
cur.close()
conn.close()
products = [dict(r) for r in rows]
categories = list({p["category"] for p in products})
return {
"total": len(products),
"categories": sorted(categories),
"products": products
}
def get_product_info_impl(product_id: int) -> dict:
p = _get_product_by_id(product_id)
if not p:
return {"error": f"Product with id {product_id} not found"}
return p
def find_product_for_goal_impl(health_goal: str) -> dict:
GOAL_MAP = {
"weight_loss": "weight_loss",
"immunity": "immunity",
"energy": "energy",
"skin_health": "skin_health",
"digestion": "digestion",
"detox": "detox",
}
goal = GOAL_MAP.get(health_goal.lower().replace(" ", "_"), health_goal.lower())
conn = get_db()
cur = conn.cursor()
cur.execute(
"SELECT id, name, category, weight, price, description, benefits FROM products WHERE health_goals LIKE %s",
(f"%{goal}%",)
)
rows = cur.fetchall()
cur.close()
conn.close()
if not rows:
return {"error": f"No products found for goal: {health_goal}"}
products = [dict(r) for r in rows]
GOAL_DESCRIPTIONS = {
"weight_loss": "These products support weight loss through fiber, low calories, and metabolism boost.",
"immunity": "These products are rich in Vitamin C, antioxidants, and immune-boosting compounds.",
"energy": "These products provide natural energy through nutrients, iron, and carbohydrates.",
"skin_health": "These products contain antioxidants, Vitamin C, and nutrients for glowing skin.",
"digestion": "These products contain fiber, enzymes, and probiotics that support healthy digestion.",
"detox": "These products help cleanse the body and support liver and kidney function.",
}
return {
"health_goal": health_goal,
"explanation": GOAL_DESCRIPTIONS.get(goal, f"Products recommended for {health_goal}"),
"total": len(products),
"recommended_products": products
}
def get_recipe_ideas_impl(product_id: int = 0) -> dict:
if product_id and product_id > 0:
recipes = RECIPES.get(product_id, [])
product = _get_product_by_id(product_id)
if not product:
return {"error": f"Product {product_id} not found"}
if not recipes:
return {
"product": product.get("name"),
"message": f"Mix 1-2 tbsp of {product.get('name')} in smoothies, juices, or warm water.",
"recipes": []
}
return {
"product": product.get("name"),
"recipes": recipes
}
# General recipes
all_recipes = []
for pid, recipe_list in RECIPES.items():
p = _get_product_by_id(pid)
if p and recipe_list:
all_recipes.append({
"product_id": pid,
"product_name": p.get("name"),
"recipe": recipe_list[0]
})
return {
"message": "Here are some popular recipes using our powders:",
"recipes": all_recipes[:6]
}
def compare_products_impl(product_id_1: int, product_id_2: int) -> dict:
p1 = _get_product_by_id(product_id_1)
p2 = _get_product_by_id(product_id_2)
if not p1:
return {"error": f"Product {product_id_1} not found"}
if not p2:
return {"error": f"Product {product_id_2} not found"}
return {
"comparison": {
"product_1": {
"id": p1["id"],
"name": p1["name"],
"category": p1["category"],
"weight": p1["weight"],
"price": p1["price"],
"benefits": p1["benefits"],
"health_goals": p1["health_goals"],
"how_to_use": p1["how_to_use"],
},
"product_2": {
"id": p2["id"],
"name": p2["name"],
"category": p2["category"],
"weight": p2["weight"],
"price": p2["price"],
"benefits": p2["benefits"],
"health_goals": p2["health_goals"],
"how_to_use": p2["how_to_use"],
}
},
"price_difference": abs(p1["price"] - p2["price"]),
"cheaper": p1["name"] if p1["price"] < p2["price"] else p2["name"],
}
def check_price_and_delivery_impl(product_id: int, city: str = "") -> dict:
p = _get_product_by_id(product_id)
if not p:
return {"error": f"Product {product_id} not found"}
city_key = city.lower().strip() if city else "other"
delivery = DELIVERY_INFO.get(city_key, DELIVERY_INFO["other"])
product_price = p["price"]
delivery_charge = delivery["charge"]
total = product_price + delivery_charge
return {
"product": {"id": p["id"], "name": p["name"], "weight": p["weight"], "price": product_price},
"delivery": {
"city": delivery["city"],
"charge": delivery_charge,
"estimated_time": delivery["days"]
},
"total_amount": total,
"note": "Free delivery on orders above PKR 3000"
}
def place_order_impl(name: str, phone: str, address: str, products: list) -> dict:
if not name or not phone or not address:
return {"error": "Please provide name, phone, and address to place order."}
if not products:
return {"error": "Please specify at least one product to order."}
total = 0
order_items = []
conn = get_db()
cur = conn.cursor()
for item in products:
product_id = item.get("product_id") or item.get("id")
qty = item.get("quantity", 1)
if product_id:
cur.execute("SELECT id, name, price FROM products WHERE id = %s", (product_id,))
row = cur.fetchone()
if row:
p = dict(row)
subtotal = p["price"] * qty
total += subtotal
order_items.append({"product": p["name"], "qty": qty, "price": p["price"], "subtotal": subtotal})
city = address.split(",")[-1].strip().lower() if "," in address else "other"
delivery = DELIVERY_INFO.get(city, DELIVERY_INFO["other"])
total += delivery["charge"]
import json as _json
cur.execute(
"INSERT INTO orders (name, phone, address, city, products, total_amount) VALUES (%s, %s, %s, %s, %s, %s) RETURNING id",
(name, phone, address, city, _json.dumps(order_items), total)
)
order_id = cur.fetchone()["id"]
cur.close()
conn.commit()
conn.close()
return {
"success": True,
"order_id": order_id,
"customer": name,
"items": order_items,
"delivery_charge": delivery["charge"],
"total_amount": total,
"estimated_delivery": delivery["days"],
"message": f"Order #{order_id} confirmed! Our team will contact you on {phone} via WhatsApp within 1 hour to confirm your order."
}
# ─── Function Tools ───────────────────────────────────────────────────────────
@function_tool
def browse_products(category: str = "") -> str:
"""Browse all products or filter by category.
Args:
category: Optional category filter - 'Fruit Powders', 'Vegetable Powders', 'Green Leaf Powders', or empty for all
"""
result = browse_products_impl(category)
return str(result)
@function_tool
def get_product_info(product_id: int) -> str:
"""Get full details about a specific product.
Args:
product_id: The product ID (1-12)
"""
result = get_product_info_impl(product_id)
return str(result)
@function_tool
def find_product_for_goal(health_goal: str) -> str:
"""Find products recommended for a specific health goal.
Args:
health_goal: One of: weight_loss, immunity, energy, skin_health, digestion, detox
"""
result = find_product_for_goal_impl(health_goal)
return str(result)
@function_tool
def get_recipe_ideas(product_id: int = 0) -> str:
"""Get recipe ideas for a product or general recipe suggestions.
Args:
product_id: Optional product ID (1-12). Use 0 for general recipes.
"""
result = get_recipe_ideas_impl(product_id)
return str(result)
@function_tool
def compare_products(product_id_1: int, product_id_2: int) -> str:
"""Compare two products side by side.
Args:
product_id_1: First product ID
product_id_2: Second product ID
"""
result = compare_products_impl(product_id_1, product_id_2)
return str(result)
@function_tool
def check_price_and_delivery(product_id: int, city: str = "") -> str:
"""Check product price and delivery charges for a city.
Args:
product_id: The product ID
city: Delivery city (lahore, karachi, islamabad, rawalpindi, faisalabad, multan, peshawar, or other)
"""
result = check_price_and_delivery_impl(product_id, city)
return str(result)
@function_tool
def place_order(name: str, phone: str, address: str, products: list) -> str:
"""Place a new order for the customer.
Args:
name: Customer full name
phone: WhatsApp number
address: Full delivery address
products: List of dicts with product_id and quantity e.g. [{"product_id": 1, "quantity": 2}]
"""
result = place_order_impl(name, phone, address, products)
return str(result)