Build a Chatbot with Memory
Build a chatbot that remembers users across conversations. Takes about 15 minutes.
What You'll Build
A chatbot that:
- Remembers user preferences and facts
- Retrieves relevant context for each message
- Learns automatically from conversations
Prerequisites
- Python 3.9+
- Tensorheart API key (sign up)
- OpenAI API key
Step 1: Set Up
Install dependencies:
pip install openai requests
Set your API keys:
export TENSORHEART_API_KEY="mem_live_..."
export OPENAI_API_KEY="sk-..."
Step 2: Create Memory Functions
Create a file called memory.py:
import os
import requests
MEMORY_API = "https://api.memory.tensorheart.com/v1"
API_KEY = os.environ["TENSORHEART_API_KEY"]
def save_memory(user_id: str, text: str):
"""Save a memory for a user."""
requests.post(
f"{MEMORY_API}/memories",
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"text": text,
"space_id": f"user_{user_id}"
}
)
def get_memories(user_id: str, query: str, max_results: int = 5) -> list[str]:
"""Get relevant memories for a user."""
response = requests.post(
f"{MEMORY_API}/query",
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"context": query,
"space_id": f"user_{user_id}",
"max_memories": max_results
}
)
data = response.json()
return [m["text"] for m in data.get("data", {}).get("memories", [])]
def extract_memories(user_id: str, conversation: str):
"""Auto-extract memories from a conversation."""
requests.post(
f"{MEMORY_API}/query/extract",
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"content": conversation,
"content_type": "conversation",
"space_id": f"user_{user_id}"
}
)
Step 3: Create the Chatbot
Create chatbot.py:
import os
from openai import OpenAI
from memory import get_memories, extract_memories
openai = OpenAI()
def chat(user_id: str, message: str, history: list) -> str:
"""Process a chat message with memory context."""
# 1. Get relevant memories
memories = get_memories(user_id, message)
memory_text = "\n".join(f"- {m}" for m in memories) if memories else "None yet."
# 2. Build the prompt
system_prompt = f"""You are a friendly assistant with memory.
What you remember about this user:
{memory_text}
Use this context naturally. Don't list facts—weave them in."""
# 3. Get response
messages = [
{"role": "system", "content": system_prompt},
*history,
{"role": "user", "content": message}
]
response = openai.chat.completions.create(
model="gpt-4o",
messages=messages
)
assistant_reply = response.choices[0].message.content
# 4. Learn from this exchange
exchange = f"User: {message}\nAssistant: {assistant_reply}"
extract_memories(user_id, exchange)
return assistant_reply
Step 4: Run the Chatbot
Create main.py:
from chatbot import chat
def main():
user_id = "demo_user"
history = []
print("Chatbot ready! Type 'quit' to exit.\n")
while True:
user_input = input("You: ")
if user_input.lower() == "quit":
break
response = chat(user_id, user_input, history)
print(f"Bot: {response}\n")
# Update history
history.append({"role": "user", "content": user_input})
history.append({"role": "assistant", "content": response})
if __name__ == "__main__":
main()
Run it:
python main.py
Step 5: Test Memory
Try this conversation:
You: Hi! I'm Alex and I work at Stripe.
Bot: Nice to meet you, Alex! Working at Stripe must be exciting...
You: quit
Start a new session:
python main.py
You: What company do I work at?
Bot: You work at Stripe!
The bot remembers across sessions.
How It Works
┌────────────────────────────────────────────────┐
│ Chat Flow │
│ │
│ User Message │
│ │ │
│ ▼ │
│ ┌─────────┐ relevant ┌───────────────┐ │
│ │ Memory │───memories──▶│ LLM + context│ │
│ │ Query │ │ │ │
│ └─────────┘ └───────┬───────┘ │
│ │ │
│ ▼ │
│ Response │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ Extract & │ │
│ │ Save New │ │
│ │ Memories │ │
│ └─────────────┘ │
└────────────────────────────────────────────────┘
Improvements to Try
Add Metadata
Tag memories with categories:
def save_memory(user_id: str, text: str, category: str = "general"):
requests.post(
f"{MEMORY_API}/memories",
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"text": text,
"space_id": f"user_{user_id}",
"metadata": {"category": category}
}
)
Filter by Relevance
Only use high-confidence memories:
def get_memories(user_id: str, query: str) -> list[str]:
response = requests.post(
f"{MEMORY_API}/query",
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"context": query,
"space_id": f"user_{user_id}",
"relevance_threshold": 0.7 # Only high relevance
}
)
# ...
Handle Errors Gracefully
def get_memories(user_id: str, query: str) -> list[str]:
try:
response = requests.post(...)
return [m["text"] for m in response.json().get("data", {}).get("memories", [])]
except Exception:
return [] # Continue without memories
Complete Code
See the full example: GitHub Gist
Next Steps
- Building Agents — More patterns
- Use Cases — Real-world examples
- API Reference — Full documentation