![advanced AI shopping assistant](https://virtust.com/wp-content/uploads/2024/10/advanced-AI-shopping-assistant-1024x468.png)
In the ever-evolving landscape of e-commerce, providing customers with personalized and immediate assistance is paramount. Amazon’s answer to this need is Rufus, a shopping assistant powered by generative AI. Rufus helps customers make informed shopping decisions by answering a wide range of questions within the Amazon app, effectively simulating the experience of interacting with a knowledgeable sales associate in a brick-and-mortar store.
We will delve into what Amazon Rufus is, its functionalities, and its limitations. Furthermore, we’ll explore how to build an advanced AI shopping assistant with enhanced capabilities like on-command adding products to the cart and automated checkout processes. We’ll also implement and explain Python code that demonstrates these concepts, leveraging AI agents and event-driven functionalities.
Understanding Amazon Rufus
What is Rufus?
Amazon Rufus is a conversational AI assistant designed to help Amazon customers navigate their shopping experience more effectively. Powered by a custom large language model (LLM) specialized for shopping, Rufus can:
- Answer open-ended questions.
- Provide product details and comparisons.
- Offer personalized product recommendations.
How Does Rufus Work?
Rufus employs several advanced AI techniques:
- Custom LLM Training: Unlike general-purpose LLMs, Rufus is trained from the ground up on shopping-specific data, including the entire Amazon catalog, customer reviews, and community Q&A posts.
- Retrieval-Augmented Generation (RAG): Rufus can fetch and incorporate up-to-date information from reliable sources to provide accurate answers.
- Reinforcement Learning: Customer feedback is used to continually improve Rufus’s responses over time.
- High-Performance Computing: Utilizing Amazon’s specialized AI chips, Trainium and Inferentia, Rufus achieves low latency and high throughput.
- Advanced Streaming Architecture: Responses are streamed to the customer as they are generated, improving the user experience.
Limitations of Amazon Rufus
While Rufus represents a significant advancement in AI-driven customer service, it has its limitations:
- Transactional Capabilities: Rufus primarily focuses on providing information and lacks the ability to perform transactions like adding items to a cart or processing checkouts.
- Limited Personalization: Although it offers recommendations, Rufus may not fully leverage individual user data to personalize interactions deeply.
Enhancing Rufus: Advanced Functionalities
To overcome these limitations, we can consider the following enhancements:
1. Transactional Functions
- On-Command Cart Management: Allow the assistant to add products to the cart or initiate checkouts upon user request.
- Order Processing: Enable functionalities like order placement, refunds, and notifications.
2. Enhanced Personalization
- Real-Time Data Integration: Use real-time user data and browsing history to tailor recommendations and responses.
- Event-Driven Training: Implement event triggers to update the model with the latest user interactions.
3. Scalability Solutions
- Efficient Resource Allocation: Optimize computational resources to handle higher loads without compromising performance.
- Distributed Computing: Employ distributed systems to manage requests more effectively.
4. AI Agents for Modular Functionality
- Specialized Agents: Break down functionalities into specialized agents (e.g., Sales Agent, Refunds Agent) to handle specific tasks.
- Triage System: Implement a triage agent to direct user requests to the appropriate specialized agent.
Building a Rufus-Like Assistant with Advanced Functionalities
Key Components
- Custom LLM Training: Train the model on both static catalog data and dynamic user interaction data.
- Event-Driven Architecture: Use event triggers to update the model and database in real-time when users interact with the system.
- AI Agents Framework: Utilize AI agents to modularize functionalities, making the system more maintainable and scalable.
- Transactional Capabilities: Integrate functions that can modify the user’s cart, process orders, and handle refunds.
Implementation Overview
- Data Handling: Create a database to store user information, purchase history, and product details.
- Function Definitions: Define functions for refunding items, notifying customers, and ordering items.
- Agents Setup: Set up specialized agents for handling refunds and sales, along with a triage agent to route requests.
- User Interaction Loop: Implement a loop to handle user inputs and interact with the agents accordingly.
Code Implementation and Explanation
Below is a Python implementation that demonstrates how to build an AI shopping assistant with advanced functionalities.
Prerequisites
- Python 3.10
- SQLite3 for database management
- OpenAI
swarm
for AI agents, Read about how to setup OpenAI Swarm
main.py
– The Core Application
import datetime
import random
import database
from swarm import Agent
from swarm.agents import create_triage_agent
from swarm.repl import run_demo_loop
def refund_item(user_id, item_id):
"""Initiate a refund based on the user ID and item ID.
Takes as input arguments in the format '{"user_id":"1","item_id":"3"}'
"""
conn = database.get_connection()
cursor = conn.cursor()
cursor.execute(
"""
SELECT amount FROM PurchaseHistory
WHERE user_id = ? AND item_id = ?
""",
(user_id, item_id),
)
result = cursor.fetchone()
if result:
amount = result[0]
print(f"Refunding ${amount} to user ID {user_id} for item ID {item_id}.")
else:
print(f"No purchase found for user ID {user_id} and item ID {item_id}.")
print("Refund initiated")
def notify_customer(user_id, method):
"""Notify a customer by their preferred method of either phone or email.
Takes as input arguments in the format '{"user_id":"1","method":"email"}'"""
conn = database.get_connection()
cursor = conn.cursor()
cursor.execute(
"""
SELECT email, phone FROM Users
WHERE user_id = ?
""",
(user_id,),
)
user = cursor.fetchone()
if user:
email, phone = user
if method == "email" and email:
print(f"Emailed customer {email} a notification.")
elif method == "phone" and phone:
print(f"Texted customer {phone} a notification.")
else:
print(f"No {method} contact available for user ID {user_id}.")
else:
print(f"User ID {user_id} not found.")
def order_item(user_id, product_id):
"""Place an order for a product based on the user ID and product ID.
Takes as input arguments in the format '{"user_id":"1","product_id":"2"}'"""
date_of_purchase = datetime.datetime.now()
item_id = random.randint(1, 300)
conn = database.get_connection()
cursor = conn.cursor()
cursor.execute(
"""
SELECT product_id, product_name, price FROM Products
WHERE product_id = ?
""",
(product_id,),
)
result = cursor.fetchone()
if result:
product_id, product_name, price = result
print(
f"Ordering product {product_name} for user ID {user_id}. The price is {price}."
)
# Add the purchase to the database
database.add_purchase(user_id, date_of_purchase, item_id, price)
else:
print(f"Product {product_id} not found.")
# Initialize the database
database.initialize_database()
# Preview tables
database.preview_table("Users")
database.preview_table("PurchaseHistory")
database.preview_table("Products")
# Define the agents
refunds_agent = Agent(
name="Refunds Agent",
description=f"""You are a refund agent that handles all actions related to refunds after a return has been processed.
You must ask for both the user ID and item ID to initiate a refund. Ask for both user_id and item_id in one message.
If the user asks you to notify them, you must ask them what their preferred method of notification is. For notifications, you must
ask them for user_id and method in one message.""",
functions=[refund_item, notify_customer],
)
sales_agent = Agent(
name="Sales Agent",
description=f"""You are a sales agent that handles all actions related to placing an order to purchase an item.
Regardless of what the user wants to purchase, must ask for BOTH the user ID and product ID to place an order.
An order cannot be placed without these two pieces of information. Ask for both user_id and product_id in one message.
If the user asks you to notify them, you must ask them what their preferred method is. For notifications, you must
ask them for user_id and method in one message.
""",
functions=[order_item, notify_customer],
)
triage_agent = create_triage_agent(
name="Triage Agent",
instructions=f"""You are to triage a users request, and call a tool to transfer to the right intent.
Once you are ready to transfer to the right intent, call the tool to transfer to the right intent.
You dont need to know specifics, just the topic of the request.
If the user request is about making an order or purchasing an item, transfer to the Sales Agent.
If the user request is about getting a refund on an item or returning a product, transfer to the Refunds Agent.
When you need more information to triage the request to an agent, ask a direct question without explaining why you're asking it.
Do not share your thought process with the user! Do not make unreasonable assumptions on behalf of user.""",
agents=[sales_agent, refunds_agent],
add_backlinks=True,
)
if __name__ == "__main__":
# Run the demo loop
run_demo_loop(triage_agent, debug=False)
- Import Statements: Import necessary modules and the
database
module we’ll create. - Function Definitions: Define
refund_item
,notify_customer
, andorder_item
functions to handle respective actions. - Database Initialization: Initialize the database and preview tables to ensure they are correctly set up.
- Agents Setup: Define the
refunds_agent
,sales_agent
, andtriage_agent
with appropriate descriptions and functions. - Main Execution: Run the application by starting the demo loop with the
triage_agent
.
database.py
– Managing Data Storage
import sqlite3
# Global connection
conn = None
def get_connection():
global conn
if conn is None:
conn = sqlite3.connect("application.db")
return conn
def create_database():
conn = get_connection()
cursor = conn.cursor()
# Create Users table
cursor.execute(
"""
CREATE TABLE IF NOT EXISTS Users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER,
first_name TEXT,
last_name TEXT,
email TEXT UNIQUE,
phone TEXT
)
"""
)
# Create PurchaseHistory table
cursor.execute(
"""
CREATE TABLE IF NOT EXISTS PurchaseHistory (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER,
date_of_purchase TEXT,
item_id INTEGER,
amount REAL,
FOREIGN KEY (user_id) REFERENCES Users(user_id)
)
"""
)
# Create Products table
cursor.execute(
"""
CREATE TABLE IF NOT EXISTS Products (
product_id INTEGER PRIMARY KEY,
product_name TEXT NOT NULL,
price REAL NOT NULL
);
"""
)
conn.commit()
def add_user(user_id, first_name, last_name, email, phone):
conn = get_connection()
cursor = conn.cursor()
# Check if the user already exists
cursor.execute("SELECT * FROM Users WHERE user_id = ?", (user_id,))
if cursor.fetchone():
return
try:
cursor.execute(
"""
INSERT INTO Users (user_id, first_name, last_name, email, phone)
VALUES (?, ?, ?, ?, ?)
""",
(user_id, first_name, last_name, email, phone),
)
conn.commit()
except sqlite3.Error as e:
print(f"Database Error: {e}")
def add_purchase(user_id, date_of_purchase, item_id, amount):
conn = get_connection()
cursor = conn.cursor()
# Check if the purchase already exists
cursor.execute(
"""
SELECT * FROM PurchaseHistory
WHERE user_id = ? AND item_id = ? AND date_of_purchase = ?
""",
(user_id, item_id, date_of_purchase),
)
if cursor.fetchone():
return
try:
cursor.execute(
"""
INSERT INTO PurchaseHistory (user_id, date_of_purchase, item_id, amount)
VALUES (?, ?, ?, ?)
""",
(user_id, date_of_purchase, item_id, amount),
)
conn.commit()
except sqlite3.Error as e:
print(f"Database Error: {e}")
def add_product(product_id, product_name, price):
conn = get_connection()
cursor = conn.cursor()
try:
cursor.execute(
"""
INSERT INTO Products (product_id, product_name, price)
VALUES (?, ?, ?);
""",
(product_id, product_name, price),
)
conn.commit()
except sqlite3.Error as e:
print(f"Database Error: {e}")
def preview_table(table_name):
conn = sqlite3.connect("application.db")
cursor = conn.cursor()
cursor.execute(f"SELECT * FROM {table_name} LIMIT 5;")
rows = cursor.fetchall()
for row in rows:
print(row)
conn.close()
def initialize_database():
global conn
create_database()
# Add some initial users
initial_users = [
(1, "Alice", "Smith", "alice@test.com", "123-456-7890"),
(2, "Bob", "Johnson", "bob@test.com", "234-567-8901"),
(3, "Sarah", "Brown", "sarah@test.com", "555-567-8901"),
]
for user in initial_users:
add_user(*user)
# Add some initial purchases
initial_purchases = [
(1, "2024-01-01", 101, 99.99),
(2, "2023-12-25", 100, 39.99),
(3, "2023-11-14", 307, 49.99),
]
for purchase in initial_purchases:
add_purchase(*purchase)
# Add some initial products
initial_products = [
(7, "Hat", 19.99),
(8, "Wool socks", 29.99),
(9, "Shoes", 39.99),
]
for product in initial_products:
add_product(*product)
- Connection Management: Establishes a connection to the SQLite database using
get_connection()
. - Database Schema Creation:
create_database()
defines tables for Users, PurchaseHistory, and Products. - Data Insertion Functions: Functions like
add_user
,add_purchase
, andadd_product
insert data into the database. - Data Preview:
preview_table()
allows for previewing the contents of a table. - Initialization:
initialize_database()
sets up the database with initial data for testing purposes.
Running the Application
When you run main.py
, the application:
- Initializes the database with sample data.
- Sets up the agents for handling different user intents.
- Starts a loop where you can input requests as if you were a user interacting with the AI assistant.
- The triage agent routes your request to the appropriate agent based on intent.
- The agent performs the requested action, such as placing an order or initiating a refund.
Complete code: https://github.com/Virtust/AI-shopping-assistant
Virtust is a pioneering IT company with deep expertise in Artificial Intelligence and web3 technologies. Contact Us to get setup multi-agent system for your workflow and automation of your business.