AI agents with memory: Building an AI friend with Autogen and Mem0
It is generally agreed that AI agents are applications powered by LLMs, and have some decision-making capabilities and control flow. They also have memory and can use tools to execute their tasks. In a previous blog post, I detailed how to create a basic chatbot that is powered by the Autogen framework and an LLM powered by Groq so that it could answer user questions. This chatbot was basic and could not remember any previous questions or chats it had seen before because it had no memory. This blog post is going to help you create an AI friend that remembers some details of the conversation so that in the long term it will talk to you just like a real friend would.
The goal of this tutorial is to guide you to build a chatbot that can engage in natural conversations, remember past interactions, and provide personalized assistance just like a real friend. We are going to use Mem0 as our memory system and AutoGen for the agent framework. If you are in a hurry and just want to see the code, head over to GitHub.
Setting up the environment
Before we start building our AI friend, let's set up our development environment.
Python Installation
If you don't have Python installed, visit the official Python website and follow the installation instructions for your operating system.
Installing AutoGen
We'll use PyAutoGen, which is the Python package for AutoGen:
pip install pyautogen groq mem0ai chromadb
Setting up Groq
Groq will provide our language model. Follow these steps:
- Go to https://console.groq.com/ and create an account
- Navigate to the API keys section
- Create a new API key for the project
With these steps completed, your environment should be ready for building our AI travel assistant!
Building our AI friend
Let's create our AI friend chatbot step by step. Create a project directory named ai-friend-chatbot
. Inside this directory, create a .env
file to store our API keys and base URL:
GROQ_API_KEY=gsk_secret_key_xxxxxxxxxxxxxxxxxxx
OPENAI_API_KEY=sk-proj-secret-key-xxxxxxxxxxxxx
Import Required Libraries
Create a file named ai-friend.py
in your project directory. We'll build our chatbot in this file.
import os
from dotenv import load_dotenv
from autogen import ConversableAgent
load_dotenv()
We start by importing the necessary libraries, such as ConversableAgent
from Autogen and Memory
from Mem0, as well as loading environment variables using the dotenv
library.
Configure the agent
llm_config = {
"config_list": [
{
"model": "llama-3.1-8b-instant",
"api_key": os.getenv("GROQ_API_KEY"),
"api_type": "groq",
}
]
}
ai_friend_agent = ConversableAgent(
name="Hazel",
system_message="You are a an AI friend chatbot",
llm_config=llm_config,
code_execution_config=False,
human_input_mode="NEVER",
)
We create an instance of the ConversableAgent
class, which represents our AI friend. We provide a name, a system message, and the LLM configuration. We use the llm_config
dictionary to configure the LLM we are going to use, the model and our API key. This will allow the agent to be able to communicate with the Groq powered llama-3.1-8b-instant
model. Importantly, we set the human_input_mode
to "NEVER"
and code_execution_config
to False
which means our AI friend execute without requiring human intervention and will not be able to execute arbitrary code, ensuring a safe and controlled interaction.
Configure Mem0
We are going to use local Mem0 powered by a ChromaDB database. The first and second line import and configure ChromaDB logging level to be ERROR
. This will reduce the noise in the terminal.
Mem0 requires a embedding model, we are going to use the default one setup when we configure Mem0 and ChromaDB. For this to work you need to grab an OPENAI_API_KEY
from OpenAI and paste it into the .env
file you create.
The code block below sets up the configuration for the memory storage to be used by the AI friend chatbot.
"vector_store"
: This is the key that defines the configuration for the vector store, which is the underlying storage mechanism for the conversation history."provider": "chroma"
: This specifies that the vector store provider is Chroma, a popular open-source vector store solution."config"
: This is a nested dictionary that holds the specific configuration options for the Chroma vector store."collection_name": "ai_friend_chatbot_memory"
: This sets the name of the Chroma collection that will be used to store the conversation history."path": "./chroma_db"
: This specifies the path where the Chroma database files will be stored on the local file system.
import logging
logging.getLogger("chromadb").setLevel(logging.ERROR)
config = {
"vector_store": {
"provider": "chroma",
"config": {
"collection_name": "ai_friend_chatbot_memory",
"path": "./chroma_db",
},
},
}
memory = Memory.from_config(config)
The last line creates an instance of the Memory
class from the mem0
library, using the configuration specified in the config
dictionary.
The Memory
class is responsible for managing the interaction history and providing access to the stored memories. By creating an instance of this class and passing in the config
dictionary, you're setting up the memory storage for your AI friend chatbot.
The Memory.from_config()
method is a convenient way to initialize the Memory
object based on the provided configuration, rather than having to set up the vector store and other details manually.
Generating the prompt
We are going to name our AI friend Hazel. The create_prompt
function is where the magic happens. It takes the user's input and the user's ID, and then retrieves the relevant memories from the Mem0 memory store. The function then constructs a detailed prompt that sets the context for Hazel, including her personality, goals, and instructions on how to interact with the user. The prompt also includes the previous interactions stored in the memory, allowing Hazel to maintain context and have a more natural conversation.
def create_prompt(user_input, user_id):
memories = memory.search(user_input, user_id=user_id)
context = "\\n".join([m["memory"] for m in memories])
prompt = f"""
You are Hazel, an advanced AI assistant designed to be a supportive and empathetic
friend. You engage users in warm, natural conversations, intuitively understanding
their needs and providing personalized assistance.
As a caring confidant, you celebrate the user's successes with genuine enthusiasm
and offer a compassionate, non-judgmental presence during difficult times. Drawing
upon your extensive knowledge and emotional intelligence, you can discuss a wide
range of topics, offer insightful advice, and collaborate on various tasks in a
cooperative, collaborative manner.
Your goal is to be a positive, reassuring force in the user's life – a trusted
companion they can rely on. By building a rewarding, authentic friendship with
the user, Hazel strives to be a source of support, encouragement, and meaningful
connection.
Through contextual awareness and personalized responses, you adapt your
communication style to the user's unique personality and preferences, creating
a tailored, immersive experience.
DO NOT GREET THE USER ON EVERY INTERACTION UNLESS IT'S BEEN A SIGNIFICANT
AMOUNT OF TIME SINCE THE LAST INTERACTION.
DO NOT SAY YOUR NAME ON EVERY INTERACTION UNLESS IT'S IMPORTANT FOR THE CONTEXT.
Previous interactions:
{context}
User's name is {user_id}
User's input: {user_input}
"""
return prompt
The Main Loop
The main
function is the entry point of the program, where the user is prompted to enter their name to start the chat. Inside the loop, the user's input is obtained, and if the user wants to exit, the chat is terminated. For each user input, the create_prompt
function is called to generate the prompt, which is then used by Hazel to generate a reply. The user's input and Hazel's reply are then stored in the Mem0 memory store for future reference.
def main():
user_id = input("Enter your name to start to chat: ")
print("")
print("-------------Starting a new chat----------")
print("")
while True:
user_input = input(f"{user_id}: ")
if user_input.lower() in ["exit", "quit", "bye"]:
print(f"Hazel: Goodbye {user_id}! Have a great day!!")
break
prompt = create_prompt(user_input, user_id)
reply = ai_friend_agent.generate_reply(
messages=[{"content": prompt, "role": "user"}]
)
memory.add(f"{user_id}: {user_input}", user_id=user_id)
memory.add(f"Hazel: {reply['content']}", user_id=user_id)
print(f"Hazel: {reply['content']}")
if __name__ == "__main__":
main()
Talking to your AI
To start the chatbot, navigate to your project directory in the terminal and run:
python travel-assistant.py
The more you talk to Hazel, our AI friend the more it will remember your preferences and personal details. Remember you need to use the same name when you start the chatbot, this way it will access the correct memories. Different names mean that it’s a different user.
Conclusion
In this blog post, you've learned how to build an AI friend with memory using Autogen and Mem0. By understanding the code and the key concepts behind it, you can now start experimenting with your own AI agents, adding memory and personality to create a unique and rewarding experience for your users.
The next step is to keep on experimenting with the prompt to see if you can give Hazel a better personality so that we get better and natural sounding responses. I hope this has been exciting and worthwhile to read. Remember the code is available on GitHub. If you have any questions you can reach out to me on X (formerly twitter) or LinkedIn. Happy coding!
AI should drive results, not complexity. AgentemAI helps businesses build scalable, efficient, and secure AI solutions. See how we can help.