Build a recipe recommender with the Personalization Agent
Sign up here for notifications on Weaviate Agents, or visit this page to see the latest updates and provide feedback.
The Weaviate Personalization Agent stores user persona profiles and interaction data within your Weaviate instance alongside your main data collection. Be mindful of data privacy regulations when implementing this agent.
In this tutorial, we will be building a simple food recommender service using the Weaviate Personalization Agent. This agent will learn about user preferences based on their defined profile (persona) and past interactions (e.g., recipe reviews) to provide personalized recommendations from a collection of recipes.
We've prepared a public dataset that you can use to explore the Personalization Agent: It is available on HuggingFace:
- Recipes: A dataset that lists recipe names, short descriptions, and cuisine types.
Introduction: What are Personalization Agents?
The Weaviate Personalization Agent is a pre-built agentic service designed to retrieve objects from a Weaviate collection in a way that is tailored to individual users. It achieves this by considering a user's defined persona (profile) and their history of interactions with items in the collection.

The Personalization Agent:
- Receives a request for recommendations for a specific user (persona).
- Retrieves the user's persona profile (e.g., likes, dislikes, favorite cuisines) and interaction history (e.g., liked/disliked recipes with associated weights).
- Queries the reference collection (e.g., "Recipes") to find candidate items.
- (Optionally) Uses an appropriate generative model (e.g., large language model) to re-rank the candidate items based on the persona, interactions, and potentially a specific instruction, providing a rationale for the ranking.
- Returns a personalized, ranked list of objects to the user.
Prerequisites
To use the Weaviate Agents and Weaviate Embedding service, you need to have a Weaviate Cloud account.
Step 1: Set up Weaviate
Now, let's get started by setting up a Weaviate Cloud instance that we will use for this tutorial and connecting it to the Python client.
1.1 Create a Weaviate Cloud cluster
- Create a free Sandbox cluster in Weaviate Cloud.
- Take note of the
REST Endpoint
andAdmin
API key to connect to your cluster. (for more info, check out the quickstart)
In this tutorial, we are using the Weaviate Embeddings service as the vectorizer, so you do not have to provide any extra keys for external embedding providers. Weaviate Embeddings uses the Snowflake/snowflake-arctic-embed-l-v2.0
as the default embedding model.
If you want to use another vectorizer, check out the list of supported model providers.
1.2 Install the Python libraries
In order to install the Weaviate Python client together with the agents
component, run:
- Python
pip install "weaviate-client[agents]"
You will also need datasets
, a lightweight library providing access to the publicly hosted datasets on HuggingFace.
- Python
pip install datasets
Troubleshooting: Force pip
to install the latest version
For existing installations, even pip install -U "weaviate-client[agents]"
may not upgrade weaviate-agents
to the latest version. If this occurs, additionally try to explicitly upgrade the weaviate-agents
package:
- Python
1.3 Connect to your instance
Now, you can finally connect to your Weaviate Cloud instance with the parameters from the first step:
- Python Client v4
import os
import weaviate
from weaviate.auth import Auth
# Best practice: store your credentials in environment variables
weaviate_url = os.environ["WEAVIATE_URL"]
weaviate_api_key = os.environ["WEAVIATE_API_KEY"]
client = weaviate.connect_to_weaviate_cloud(
cluster_url=weaviate_url,
auth_credentials=Auth.api_key(weaviate_api_key),
)
print(client.is_ready()) # Should print: `True`
# Your work goes here!
client.close() # Free up resources
After running this snippet, you should see the message True
printed out, which means that you have successfully connected to your instance.
Step 2: Prepare the collection
In the following code blocks, we will pull our demo recipe dataset from Hugging Face and write it to a new collection in our Weaviate Sandbox cluster. Before importing the data, we need to define the collection, setting up its schema and choosing the vectorizer.
2.1 Define the collection
Below you can see what the objects in the Recipes
dataset look like.

For the collection Recipes
, we will manually define the properties and include descriptions. While using auto-schema
is an option, providing explicit descriptions helps the Personalization Agent (especially the underlying LLM, when used for re-ranking) understand the context of your data better.
- Python Client v4
from weaviate.classes.config import Configure, DataType, Property
client.collections.create(
"Recipes",
description="A dataset that lists recipes with titles, descriptions, and labels indicating cuisine",
vectorizer_config=Configure.Vectorizer.text2vec_weaviate(),
properties=[
Property(
name="title", data_type=DataType.TEXT, description="title of the recipe"
),
Property(
name="labels",
data_type=DataType.TEXT,
description="the cuisine the recipe belongs to",
),
Property(
name="description",
data_type=DataType.TEXT,
description="short description of the recipe",
),
],
)
2.2 Populate the database
Now, we can import the recipe data (Recipes) into our Weaviate Cloud instance:
- Python Client v4
from datasets import load_dataset
# Ensure datasets library is installed: pip install datasets
dataset = load_dataset(
"weaviate/agents",
"personalization-agent-recipes",
split="train",
streaming=True,
)
recipes_collection = client.collections.get("Recipes")
with recipes_collection.batch.dynamic() as batch:
for i, item in enumerate(dataset):
if i < 200:
batch.add_object(properties=item["properties"])
failed_objects = recipes_collection.batch.failed_objects
if failed_objects:
print(f"Number of failed imports: {len(failed_objects)}")
print(f"First failed object: {failed_objects[0]}")
By calling len()
on our collections, we can check that the import has successfully concluded and see what the size of our collections is:
- Python Client v4
print(f"Size of the Recipes dataset: {len(recipes_collection)}")
Size of the Recipes dataset: 5117
Step 3: Set up the Personalization Agent
Now, let's create the PersonalizationAgent
instance linked to our "Recipes" collection.
When creating a new PersonalizationAgent
for the first time, we define user_properties
. These are the fields that will make up each user's persona profile. For our food recommender, properties like favorite cuisines, general food likes, and dislikes are relevant.
If an agent for this collection already exists (e.g., from a previous run), we can simply connect to it using PersonalizationAgent.connect()
. The code below handles both cases.
- Python Client v4
from weaviate.agents.personalization import PersonalizationAgent
from weaviate.classes.config import DataType
agent_exists = PersonalizationAgent.exists(client, "Recipes")
if agent_exists:
print("Connecting to existing Personalization Agent for 'Recipes' collection...")
agent = PersonalizationAgent.connect(
client=client,
reference_collection="Recipes",
)
print("Connected to existing agent.")
else:
print("Creating new Personalization Agent for 'Recipes' collection...")
agent = PersonalizationAgent.create(
client=client,
reference_collection="Recipes",
user_properties={
"favorite_cuisines": DataType.TEXT_ARRAY,
"likes": DataType.TEXT_ARRAY,
"dislikes": DataType.TEXT_ARRAY,
},
)
print("New agent created.")
You should see a message indicating whether a new agent was created or an existing one was connected.
Step 4: Use the Personalization Agent
With the agent set up, we can now add user data and retrieve recommendations.
4.1 Add a new persona
A "persona" represents a user profile. We use the agent.add_persona()
method, providing a unique persona_id
(a UUID is recommended) and the properties
we defined during agent creation.
Feel free to modify the example below to represent your own food preferences!
- Python Client v4
from uuid import uuid4
from weaviate.agents.classes import Persona
persona_id = uuid4()
print(f"Adding persona with ID: {persona_id}")
agent.add_persona(
Persona(
persona_id=persona_id,
properties={
"favorite_cuisines": ["Italian", "Thai"],
"likes": ["chocolate", "salmon", "pasta", "most veggies"],
"dislikes": ["okra", "mushroom"],
},
)
)
4.2 Add interactions
"Interactions" represent how a user has engaged with items in the collection. For our recommender, these could be explicit reviews, ratings, or implicit signals like viewing a recipe page.
Each PersonaInteraction
links a persona_id
to an item_id
(the UUID of an object in the "Recipes" collection) and includes a weight
from -1.0 (strong dislike) to 1.0 (strong like).

First, we fetch the UUIDs of some specific recipes the user has interacted with. Then, we define the interactions with appropriate weights. Finally, we add them to the agent using agent.add_interactions()
.
- Python Client v4
from weaviate.agents.classes import PersonaInteraction
from weaviate.collections.classes.filters import Filter
reviewed_foods = [
"Coq au Vin",
"Chicken Tikka Masala",
"Gnocchi alla Sorrentina",
"Matcha Ice Cream",
"Fiorentina Steak",
"Nabe",
"Duck Confit",
"Pappardelle with Porcini",
]
# Fetch the recipe objects to get their UUIDs
reviews_dict = {
recipe.properties["title"]: recipe
for recipe in recipes_collection.query.fetch_objects(
filters=Filter.by_property("title").contains_any(reviewed_foods),
limit=len(reviewed_foods), # Use len for limit
).objects
}
# Define the mapping of food titles to interaction weights
interaction_map = {
"Coq au Vin": 0.8,
"Chicken Tikka Masala": 0.8,
"Matcha Ice Cream": 0.8,
"Gnocchi alla Sorrentina": 0.5,
"Fiorentina Steak": 0.8,
"Nabe": 0.5,
"Duck Confit": 1.0,
"Pappardelle with Porcini": -1.0,
}
interactions = []
for food_title, weight in interaction_map.items():
if food_title in reviews_dict:
# If the recipe was found, create the interaction object
interaction = PersonaInteraction(
persona_id=persona_id,
item_id=reviews_dict[food_title].uuid, # Get UUID from fetched recipe
weight=weight,
)
interactions.append(interaction)
# Add the created interactions list to the agent
agent.add_interactions(interactions=interactions)
This block prepares the interaction data and sends it to the agent.
4.3 Get recommendations
Now for the core functionality: retrieving personalized recommendations using agent.get_objects()
. We provide the persona_id
for whom we want recommendations.
We can set use_agent_ranking=True
to enable the LLM-based re-ranking. This leverages the persona profile and interaction history to provide a more nuanced ranking and also generates a ranking_rationale
explaining why certain items were recommended.
- Python Client v4
print(f"\nGetting recommendations for persona {persona_id}...")
response = agent.get_objects(persona_id, limit=10, use_agent_ranking=True)
print("\nRanking Rationale:")
print(
response.ranking_rationale
if response.ranking_rationale
else "No rationale provided."
)
print("\nRecommended Recipes:")
if response.objects:
for i, obj in enumerate(response.objects):
print(f"----- Recommendation {i+1} -----")
print(f" Title: {obj.properties.get('title', 'N/A')}")
print(f" Cuisine: {obj.properties.get('labels', 'N/A')}")
print(f" UUID: {obj.uuid}")
else:
print("No recommendations found.")
The output will first show the ranking_rationale
generated by the agent's LLM, followed by the list of recommended recipes, including their title, description, and cuisine labels.
Example response (will vary based on persona/interactions and LLM):
Getting recommendations for persona e7239e3f-97f5-41b3-939a-5fbf3e0c7f16...
Ranking Rationale:
Because you love Italian dishes and have shown an interest in different cuisines, we've prioritized dishes with Italian, Japanese, and Indian labels, reflecting your preferences for Italian and Thai cuisines and prior positive interactions. We avoided items with mushroom content.
Recommended Recipes:
----- Recommendation 1 -----
Title: Chicken Tikka Masala
Cuisine: Indian
UUID: 5785f023-5ab2-49d8-bb43-0ab047083e16
----- Recommendation 2 -----
Title: Spicy Indian Tikka Masala
Cuisine: Indian
UUID: 753a036f-ec83-4efa-8a1a-5afa021acbc2
----- Recommendation 3 -----
Title: Paneer Tikka
Cuisine: Indian
UUID: 323b6f11-c026-4367-801b-b21f40e6591b
----- Recommendation 4 -----
Title: Paneer Butter Masala
Cuisine: Indian
UUID: 3bd11bc9-d329-4039-9f4a-205f1719048d
----- Recommendation 5 -----
Title: Butter Chicken
Cuisine: Indian
UUID: 4e056c59-e843-419a-8129-b6633fb8c2d3
----- Recommendation 6 -----
Title: Shabu-Shabu
Cuisine: Japanese
UUID: df0ae465-f724-42ed-9876-2c9b91516c13
----- Recommendation 7 -----
Title: Oden
Cuisine: Japanese
UUID: eb6088c1-05a6-46ed-9adc-477313c051d2
----- Recommendation 8 -----
Title: Tempura
Cuisine: Japanese
UUID: 625a5164-e150-4966-a3c6-0aed406db416
----- Recommendation 9 -----
Title: Ramen
Cuisine: Japanese
UUID: 708824b3-fc4a-4927-82bb-a8a4dbd5ee89
----- Recommendation 10 -----
Title: Udon Noodles
Cuisine: Japanese
UUID: 8d6a94b7-c9ae-4d1c-b29a-885717b9a55a
Summary
This guide demonstrated how to build a personalized food recommendation service using Weaviate's Personalization Agent. We covered:
- Setting up a Weaviate Cloud instance with the Python client.
- Defining a "Recipes" collection with descriptive properties.
- Importing data into the collection.
- Creating a Personalization Agent linked to the collection and defining user profile properties (
user_properties
). - Adding user profiles (
personas
) with specific preferences. - Recording user interactions with items, using weighted scores.
- Retrieving personalized recommendations using
get_objects
, leveraging LLM-based re-ranking (use_agent_ranking=True
) to get tailored results and explanations (ranking_rationale
).
The Personalization Agent allows you to easily add sophisticated, personalized retrieval capabilities to your applications built on Weaviate.
Further resources
Questions and feedback
The official changelog for Weaviate Agents can be found here. If you have feedback, such as feature requests, bug reports or questions, please submit them here, where you will be able to see the status of your feedback and vote on others' feedback.
If you have any questions or feedback, let us know in the user forum.