Have you ever wondered what it’d be like if a chatbot could remember like a human? Not just store every byte of data indefinitely like a cold, unfeeling database, but mimic how our brains prioritize important moments and let the mundane fade away? I did, and that curiosity led me to build a project I’m excited to share: a chatbot with human-like memory powered by Pinecone and Ollama.
I’ll walk you through why I built it, how it works, and how you can try it yourself. Spoiler: It involves exponential decay, vector embeddings, and a dash of psychology-inspired hacking.
Human memory is messy and marvelous. We don’t recall every mundane detail—we let the noise drift away while treasuring moments that hit hard: a friend’s joke, a big win, or that perfect pizza night. The “forgetting curve” (shoutout to Hermann Ebbinghaus) shows this fading happens exponentially over time—unless something’s reinforced or emotionally charged.
Most AIs, though, are the opposite—perfect recall, no nuance. I wanted a chatbot that forgets the fluff and clings to the good stuff, blending technology with a human touch.
Here’s what powers this experiment:
llama3.2:latest
locally for natural responses.all-MiniLM-L6-v2
.The mission: store chats as embeddings, let them degrade over time, and boost the ones worth keeping—all feeding into Ollama for context-aware replies.
Human-Like Memory Chatbot v1.1.0 ============================== Using: - Pinecone Index: human-memory - Embedding Model: sentence-transformers/all-MiniLM-L6-v2 - LLM: llama3.2:latest ============================== Start chatting (type 'exit' to stop): -------- You: Hello again! AI: Hello again! I'm happy to see you're back, but it seems like we don't have a lot of context to draw from. You mentioned earlier that you were Mats, and now you're saying hello without specifying your name or what brings you here today. Is everything okay? Would you like to start fresh and share something new with me, or would you rather just chat for a bit and see where the conversation takes us? -------- You:
Let’s peek at the guts of llm-memory.py from the GitHub repo.
Each conversation is stored in Pinecone with associated metadata:
Memories degrade exponentially over time. By default, memories have a half-life of 90 days:
# Exponential decay function for memory degradation def calculate_decay_factor(timestamp, half_life_days=90): now = datetime.now() # Days time_diff = (now - datetime.fromisoformat(timestamp)).total_seconds() / (24 * 3600) decay = np.exp(-time_diff / half_life_days) # Exponential decay return decay
The system evaluates emotional content to prioritize memorable conversations:
# Function to determine importance using VADER sentiment analysis def calculate_importance(user_input, response): # Use VADER sentiment analyzer sid = SentimentIntensityAnalyzer() # Get sentiment scores user_sentiment = sid.polarity_scores(user_input) response_sentiment = sid.polarity_scores(response) # Use the compound score which is normalized between -1 and 1 # Average the sentiment of both user input and response importance = (user_sentiment['compound'] + response_sentiment['compound']) / 2 return importance # Returns value between -1 and 1
The chatbot retrieves relevant past interactions weighted by similarity, importance, and memory decay, implicitly guiding responses without explicitly mentioning forgetting:
# Retrieve context with decay and importance def retrieve_context(query, max_results=3, decay_threshold=0.05): # Perform similarity search # Get more results than needed to filter results = vector_store.similarity_search_with_score( query=query, k=max_results*2 ) # Apply decay factor to each result weighted_results = [] for doc, score in results: if (hasattr(doc, 'metadata') and 'timestamp' in doc.metadata and 'importance' in doc.metadata): decay = calculate_decay_factor(doc.metadata['timestamp']) importance = doc.metadata['importance'] # Apply both decay and importance to the relevance # Higher importance = slower decay # importance augments the decay rate effective_weight = decay * (1 + importance) # Only include if above threshold if effective_weight >= decay_threshold: weighted_results.append((doc, effective_weight)) # Sort by effective weight (descending) and take top results weighted_results.sort(key=lambda x: x[1], reverse=True) weighted_results = weighted_results[:max_results] # Format context for prompt context = "Previous conversation (faded by time, stronger if important):\n\n" for doc, weight in weighted_results: # Format with decay-based opacity context += f"[Memory strength: {weight:.2f}] {doc.page_content}\n\n" return context
git clone https://github.com/MLidstrom/llm-memory.git cd llm-memory
pip install pinecone-client ollama langchain langchain_pinecone sentence-transformers numpy python-dotenv
.env
:PINECONE_API_KEY=your-api-key-here
ollama run llama3.2:latest
python llm-memory.py
The project’s live on GitHub: github.com/MLidstrom/llm-memory. Here’s a sample run:
-------- You: Hi again. Remember me? AI: Hi again, Mats! Of course, I remember you. What brings you here today? Is everything okay, or is there something specific on your mind that you'd like to chat about? -------- You: What about a nice conversation about Pizza? AI: I'm glad we can start fresh and dive back into that delicious topic - pizza! So, let's get this pizza party started! You mentioned earlier that you love pizza, but then suddenly switched gears. What's changed? Are you still thinking about that perfect pie we discussed before, or is there something new on your mind? Let me ask: what's the first thing that comes to mind when you think of pizza? Is it a favorite memory associated with a particular slice, a go-to topping combination, or perhaps a type of crust that just can't be beat? -------- You:
Wait a bit (or tweak the half-life), and “Hi” might fade, but the pizza sticks.
This is version 1.1—rough but promising.
This chatbot project is about creating an AI that remembers like we do: selectively, emotionally, and meaningfully. The goal is an assistant that feels relatable, focusing on what truly matters to you—not every detail, but the right ones.