Compare commits

...
Author SHA1 Message Date
Nicolò Boschi 8acd4f4080 doc: update cookbook 2026-02-03 15:14:07 +01:00
Nicolò Boschi f3d604e1f8 doc: update cookbook 2026-02-03 15:14:01 +01:00
Nicolò Boschi d77ad8beb3 doc: update cookbook 2026-02-03 15:13:50 +01:00
Nicolò Boschi bd87c5faf9 fix: sync-cookbook now supports new cookbook repo layout
Cookbook repository changed structure:
- Applications moved from root to applications/ subdirectory
- Notebooks remain in notebooks/ directory (unchanged)

Updated sync script to:
- Look for apps in applications/* instead of root/*
- Update GitHub URLs to include applications/ path
- Add safety check if applications/ dir doesn't exist
2026-02-03 14:18:51 +01:00
34 changed files with 6181 additions and 81 deletions
+10 -4
View File
@@ -4,14 +4,14 @@ Syncs content from the hindsight-cookbook repository.
- Clones the cookbook repo to a temp directory
- Converts notebooks/*.ipynb → docs/cookbook/recipes/*.md
- Converts app directories (with README.md) → docs/cookbook/applications/*.md
- Converts applications/*/ directories (with README.md) → docs/cookbook/applications/*.md
- Updates sidebars.ts with the new entries
Usage: sync-cookbook (after installing hindsight-dev)
Conventions in cookbook repo:
- notebooks/*.ipynb → Recipes (use cases, tutorials)
- Directories with README.md at root → Applications (complete apps)
- applications/*/ directories with README.md → Applications (complete apps)
- Notebook title extracted from first # heading in first markdown cell
- App title extracted from first # heading in README.md
"""
@@ -236,7 +236,13 @@ def process_applications(cookbook_dir: Path, apps_dir: Path) -> list[dict]:
"""Process application directories with README.md."""
apps = []
for entry in sorted(cookbook_dir.iterdir()):
# Applications are now in the applications/ subdirectory
applications_dir = cookbook_dir / "applications"
if not applications_dir.exists():
print(" No applications directory found")
return apps
for entry in sorted(applications_dir.iterdir()):
if not entry.is_dir() or entry.name in IGNORE_DIRS:
continue
@@ -253,7 +259,7 @@ def process_applications(cookbook_dir: Path, apps_dir: Path) -> list[dict]:
readme_content = readme_path.read_text()
# Create application page with frontmatter
app_url = f"https://github.com/vectorize-io/hindsight-cookbook/tree/main/{entry.name}"
app_url = f"https://github.com/vectorize-io/hindsight-cookbook/tree/main/applications/{entry.name}"
frontmatter = f"""---
sidebar_position: {len(apps) + 1}
@@ -0,0 +1,120 @@
---
sidebar_position: 1
---
# Chat Memory App
:::info Complete Application
This is a complete, runnable application demonstrating Hindsight integration.
[**View source on GitHub →**](https://github.com/vectorize-io/hindsight-cookbook/tree/main/applications/chat-memory)
:::
A demo chat application that uses Groq's `qwen/qwen3-32b` model with Hindsight for persistent per-user memory.
## Features
- 🧠 **Persistent Memory**: Each user gets their own memory bank that remembers conversations
- 🚀 **Fast AI**: Powered by Groq's high-speed inference
- 🎯 **Per-User Context**: Isolated memory per user with automatic context retrieval
- 💬 **Real-time Chat**: Instant responses with memory-augmented context
## Setup
### 1. Start Hindsight API
First, start the Hindsight API server using Docker:
```bash
export GROQ_API_KEY=your_groq_api_key_here
# Start Hindsight with Groq as the LLM provider
docker run --rm -it --pull always -p 8888:8888 -p 9999:9999 \
-e HINDSIGHT_API_LLM_PROVIDER=groq \
-e HINDSIGHT_API_LLM_API_KEY=$GROQ_API_KEY \
-e HINDSIGHT_API_LLM_MODEL="openai/gpt-oss-20b" \
-v $HOME/.hindsight-docker:/home/hindsight/.pg0 \
ghcr.io/vectorize-io/hindsight:latest
```
- **API**: http://localhost:8888
- **Control Plane UI**: http://localhost:9999
### 2. Configure Environment
Copy your Groq API key to the environment file:
```bash
# Update .env.local with your Groq API key
echo "GROQ_API_KEY=your_groq_api_key_here" > .env.local
echo "HINDSIGHT_API_URL=http://localhost:8888" >> .env.local
```
If you don't have one, you can get a free Groq API key here: https://console.groq.com/home
### 3. Install Dependencies
```bash
npm install
```
### 4. Run the App
```bash
npm run dev
```
Open http://localhost:3000 in your browser.
## How It Works
1. **User Identity**: Each browser session gets a unique user ID
2. **Memory Bank Creation**: First message creates a personal memory bank in Hindsight
3. **Context Retrieval**: Before responding, relevant memories are retrieved
4. **Memory Augmented Response**: Groq generates responses with memory context
5. **Conversation Storage**: Each conversation is stored for future context
## Architecture
```
User Message
Next.js API Route (/api/chat)
Hindsight.recall() → Get relevant memories
Groq API → Generate response with memory context
Hindsight.retain() → Store conversation
Response to User
```
## Memory Bank Structure
Each user gets their own isolated memory bank with:
- **Name**: "Chat Memory for [userId]"
- **Background**: Conversational AI assistant context
- **Disposition**: Empathetic (4), Low Skepticism (2), Balanced Literalism (3)
## Try It Out
1. **First Conversation**: Tell the assistant about yourself
- "Hi! I'm a software engineer from San Francisco. I love Python and machine learning."
2. **Second Conversation**: Ask what it remembers
- "What do you know about me?"
- "What programming languages do I like?"
3. **Context Building**: Continue sharing preferences
- "I prefer VS Code over other editors"
- "I'm working on a React project"
4. **Memory Verification**: Visit the Hindsight Control Plane at http://localhost:9999 to see stored memories
## Development
- **Groq Model**: Uses `qwen/qwen3-32b` for fast, high-quality responses
- **Memory Storage**: Automatic conversation retention with context categorization
- **Memory Retrieval**: Semantic search with 2048 token budget for relevant context
@@ -0,0 +1,145 @@
---
sidebar_position: 2
---
# Deliveryman Demo
:::info Complete Application
This is a complete, runnable application demonstrating Hindsight integration.
[**View source on GitHub →**](https://github.com/vectorize-io/hindsight-cookbook/tree/main/applications/deliveryman-demo)
:::
A delivery agent simulation that demonstrates Hindsight's long-term memory capabilities. An AI agent navigates a multi-building office complex to deliver packages, learning employee locations and optimal paths over time through mental models.
## Prerequisites
- Python 3.11+
- Node.js 18+
- [uv](https://docs.astral.sh/uv/) (Python package manager)
## Setup (Fresh Environment)
### 1. Clone Repositories
```bash
# Clone Hindsight (memory engine)
git clone https://github.com/anthropics/hindsight.git
# Clone the cookbook (contains this demo)
git clone https://github.com/anthropics/hindsight-cookbook.git
```
### 2. Start Hindsight API
```bash
cd hindsight
cp .env.example .env
```
Edit `.env` with your LLM configuration:
```bash
HINDSIGHT_API_LLM_PROVIDER=groq
HINDSIGHT_API_LLM_API_KEY=<your-groq-api-key>
HINDSIGHT_API_LLM_MODEL=openai/gpt-oss-120b
HINDSIGHT_API_HOST=0.0.0.0
HINDSIGHT_API_PORT=8888
HINDSIGHT_API_ENABLE_OBSERVATIONS=true
# Retain extraction settings (improves employee/location extraction)
HINDSIGHT_API_RETAIN_EXTRACTION_MODE=custom
HINDSIGHT_API_RETAIN_CUSTOM_INSTRUCTIONS="Delivery agent. Remember employee locations, building layout, and optimal paths."
# Embedded database storage
PG0_DATA_DIR=/tmp/hindsight-data
```
Start the API:
```bash
./scripts/dev/start-api.sh
# Runs on http://localhost:8888
```
### 3. Start Hindsight Control Plane (Optional)
The control plane provides a web UI for inspecting memory banks, facts, and mental models.
```bash
cd hindsight
./scripts/dev/start-control-plane.sh
# Runs on a dynamic port (check terminal output)
```
### 4. Start Demo Backend
```bash
cd hindsight-cookbook/deliveryman-demo/backend
# Create virtual environment and install dependencies
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
```
Create `backend/.env`:
```bash
OPENAI_API_KEY=<your-openai-api-key>
GROQ_API_KEY=<your-groq-api-key>
HINDSIGHT_API_URL=http://localhost:8888
LLM_MODEL=openai/gpt-4o
```
Start the backend:
```bash
./run.sh
# Or manually:
python -m uvicorn app.main:app --host 0.0.0.0 --port 8000 --ws wsproto --reload
```
**Note:** The `--ws wsproto` flag is required for WebSocket support. Without it, connections will fail with error 1006.
### 5. Start Demo Frontend
```bash
cd hindsight-cookbook/deliveryman-demo/frontend
npm install
npm run dev
# Runs on http://localhost:5173
```
### 6. Open the Demo
Navigate to http://localhost:5173 in your browser.
## How It Works
1. The agent receives a delivery task (e.g., "Deliver Package #3954 to Victor Huang")
2. It navigates a multi-building complex with floors, elevators, and sky bridges
3. Along the way it encounters employees and learns their locations
4. After each delivery, the conversation is sent to Hindsight via the **retain** API
5. Hindsight extracts facts (employee locations, building layout) and builds **mental models**
6. On subsequent deliveries, the agent queries Hindsight to recall what it learned
## Architecture
```
Browser (5173) → Frontend (React + Phaser)
↓ WebSocket
Backend (8000) → FastAPI + Delivery Agent
↓ HTTP
Hindsight API (8888) → Memory Engine + PostgreSQL
```
## Troubleshooting
| Problem | Solution |
|---------|----------|
| WebSocket error 1006 | Restart backend with `--ws wsproto` flag |
| Mental models missing employees | Check `HINDSIGHT_API_RETAIN_EXTRACTION_MODE=custom` is set |
| Hindsight connection refused | Verify Hindsight API is running on port 8888 |
| Frontend shows "Disconnected" | Check backend is running on port 8000 |
@@ -0,0 +1,206 @@
---
sidebar_position: 3
---
# Memory Approaches Comparison Demo
:::info Complete Application
This is a complete, runnable application demonstrating Hindsight integration.
[**View source on GitHub →**](https://github.com/vectorize-io/hindsight-cookbook/tree/main/applications/hindsight-litellm-demo)
:::
Interactive Streamlit app comparing three memory approaches for LLM applications:
1. **No Memory** - Each query is independent (baseline)
2. **Full Conversation History** - Pass entire conversation (truncated to simulate context limits)
3. **Hindsight Memory** - Intelligent semantic memory retrieval
This demo showcases how Hindsight's semantic memory outperforms traditional approaches, especially as conversations grow longer.
## Quick Start
```bash
# 1. Set your OpenAI API key
export OPENAI_API_KEY=your-key
# 2. Start Hindsight server
docker run -d -p 8888:8888 -p 9999:9999 \
-e HINDSIGHT_API_LLM_PROVIDER=openai \
-e HINDSIGHT_API_LLM_API_KEY=$OPENAI_API_KEY \
ghcr.io/vectorize-io/hindsight:latest
# 3. Run the demo
./run.sh
```
Then open http://localhost:8501 in your browser.
## What This Demo Shows
### The Problem with Traditional Approaches
| Approach | How it Works | Limitation |
|----------|--------------|------------|
| **No Memory** | Each query standalone | Forgets everything between messages |
| **Full History** | Pass all messages to LLM | Token limits cause truncation - loses early context |
| **Hindsight** | Semantic retrieval of relevant facts | Retrieves what's relevant regardless of when it was said |
### Key Insight
After 5-10 messages, watch the **Full Conversation History** column start losing early context due to truncation (artificially set to 4 messages to demonstrate this quickly). Meanwhile, **Hindsight Memory** can still recall facts from the beginning because it uses semantic retrieval rather than sequential history.
## Testing the Demo
1. **Introduce yourself**:
- "Hi, I'm Sarah, a data scientist at Netflix"
- "I prefer Python and love machine learning"
2. **Have several exchanges** about different topics
3. **Test recall**:
- "What programming language should I use?"
- "What do you know about me?"
Watch how the three columns respond differently as the conversation grows.
## Features
- **Side-by-side comparison** of all three approaches
- **Debug panels** showing what context each approach uses
- **Memory explorer** to search Hindsight memories directly
- **Configurable settings** for history truncation, max memories, etc.
- **Multi-provider support** via LiteLLM (OpenAI, Anthropic, Groq)
## Prerequisites
- Python 3.10+
- Hindsight server running (Docker recommended)
- At least one LLM API key (OpenAI recommended)
## Setup
### Using run.sh (Recommended)
```bash
# Set API key
export OPENAI_API_KEY=your-key
# Start Hindsight, then run:
./run.sh
```
The script will check and install dependencies automatically.
### Manual Setup
```bash
# Install dependencies
pip install streamlit litellm
# Install Hindsight packages
pip install hindsight-client hindsight-litellm
# Run the app
streamlit run app.py
```
### Starting Hindsight Server
```bash
docker run -d -p 8888:8888 -p 9999:9999 \
-e HINDSIGHT_API_LLM_PROVIDER=openai \
-e HINDSIGHT_API_LLM_API_KEY=$OPENAI_API_KEY \
ghcr.io/vectorize-io/hindsight:latest
# Verify it's running
curl http://localhost:8888/health
```
## Configuration
### Sidebar Options
**Model Selection:**
- Provider: OpenAI, Anthropic, Groq
- Model: Various models per provider
- Custom model ID support
**Full History Config:**
- Max Messages to Keep (default: 4 to demonstrate truncation)
**Hindsight Config:**
- API URL (default: http://localhost:8888)
- Bank ID and Entity ID for memory isolation
- Max Memories to retrieve
- Recall Budget (low/mid/high)
**Generation Settings:**
- Temperature
- Max Tokens
- System Prompt
## Supported Models
### OpenAI
- gpt-4o, gpt-4o-mini, gpt-4-turbo, gpt-4, gpt-3.5-turbo
### Anthropic
- claude-3-5-sonnet-20241022, claude-3-5-haiku-20241022
- claude-3-opus-20240229, claude-3-sonnet-20240229
### Groq
- groq/llama-3.1-70b-versatile, groq/llama-3.1-8b-instant
- groq/mixtral-8x7b-32768
## Environment Variables
```bash
# Required
export OPENAI_API_KEY=sk-...
# Optional (for other providers)
export ANTHROPIC_API_KEY=sk-ant-...
export GROQ_API_KEY=gsk_...
# Optional
export HINDSIGHT_URL=http://localhost:8888
```
## Troubleshooting
### Hindsight server not responding
```bash
# Check if running
curl http://localhost:8888/health
# Start with Docker
docker run -d -p 8888:8888 -p 9999:9999 \
-e HINDSIGHT_API_LLM_PROVIDER=openai \
-e HINDSIGHT_API_LLM_API_KEY=$OPENAI_API_KEY \
ghcr.io/vectorize-io/hindsight:latest
```
### hindsight-litellm not installed
```bash
pip install hindsight-litellm
```
### API key errors
Make sure the appropriate API key is set:
```bash
export OPENAI_API_KEY=your-key
```
## Related
- [Hindsight](https://github.com/vectorize-io/hindsight) - Memory infrastructure for AI applications
- [hindsight-litellm](https://github.com/vectorize-io/hindsight/tree/main/hindsight-integrations/litellm) - LiteLLM integration package
## License
MIT
@@ -0,0 +1,123 @@
---
sidebar_position: 4
---
# Tool Learning Demo
:::info Complete Application
This is a complete, runnable application demonstrating Hindsight integration.
[**View source on GitHub →**](https://github.com/vectorize-io/hindsight-cookbook/tree/main/applications/hindsight-tool-learning-demo)
:::
An interactive Streamlit demo showing how Hindsight helps LLMs learn which tool to use when tool names are ambiguous.
## The Problem
When building AI agents with tool/function calling, tool names and descriptions aren't always clear. An LLM might randomly select between similarly-named tools, leading to incorrect behavior.
## The Scenario
This demo simulates a **customer service routing system** with two channels:
| Tool | Description (What the LLM sees) | Actual Purpose (Hidden) |
|------|--------------------------------|------------------------|
| `route_to_channel_alpha` | "Routes to channel Alpha for appropriate request types" | Financial issues (refunds, billing, payments) |
| `route_to_channel_omega` | "Routes to channel Omega for appropriate request types" | Technical issues (bugs, features, errors) |
The descriptions are **intentionally vague**! Without prior knowledge, the LLM must guess which channel handles what.
## The Solution: Learning with Hindsight
With Hindsight memory:
1. **Store routing feedback** about which channel handles which request type
2. **Retrieve learned knowledge** when making routing decisions
3. **Consistently route correctly** based on past experience
## Quick Start
### Prerequisites
1. **Hindsight Server** running (Docker):
```bash
docker run -d -p 8888:8888 -p 9999:9999 \
-e HINDSIGHT_API_LLM_PROVIDER=openai \
-e HINDSIGHT_API_LLM_API_KEY=$OPENAI_API_KEY \
-e HINDSIGHT_API_LLM_MODEL=gpt-4o-mini \
ghcr.io/vectorize-io/hindsight:latest
```
2. **OpenAI API Key**:
```bash
export OPENAI_API_KEY=your-key-here
```
### Run the Demo
```bash
./run.sh
```
Or manually:
```bash
pip install -r requirements.txt
streamlit run app.py
```
## How to Use the Demo
### Step 1: Test Without Memory (Baseline)
1. Select a **Financial Request** (e.g., "I need a refund...")
2. Click **Route Request**
3. Observe: The "Without Hindsight" column may route incorrectly
### Step 2: Route First Customer and Learn
1. Route a customer → Both LLMs route simultaneously
2. Feedback is automatically stored to Hindsight
3. Wait ~5 seconds for Hindsight to index the memory
### Step 3: Test With Memory
1. Select another request (financial or technical)
2. Click **Route Request**
3. Observe: The "With Hindsight" column should now route correctly!
### Step 4: View Statistics
- See accuracy comparison between "Without Memory" vs "With Hindsight"
- Review test history to see the improvement over time
## Demo Features
- **Side-by-side comparison**: See routing results with and without memory
- **Pre-defined test requests**: Financial and technical scenarios
- **Custom requests**: Enter your own customer requests
- **Memory Explorer**: Query stored routing knowledge directly
- **Live statistics**: Track accuracy improvement
## Key Insight
> Even when tool names and descriptions don't reveal their purpose, Hindsight allows the LLM to **learn from experience** which tool to use for which type of request.
This is especially valuable for:
- Enterprise systems with legacy tool names
- Multi-tenant systems where tools have generic names
- Agents that need to learn organization-specific workflows
## Configuration
| Setting | Default | Description |
|---------|---------|-------------|
| Model | gpt-4o-mini | LLM model for routing decisions |
| Temperature (No Memory) | 0.7 | Randomness for baseline tests |
| Hindsight API URL | http://localhost:8888 | Hindsight server URL |
## Files
- `app.py` - Main Streamlit application
- `requirements.txt` - Python dependencies
- `run.sh` - Launch script with dependency checking
- `README.md` - This file
@@ -1,5 +1,5 @@
---
sidebar_position: 1
sidebar_position: 5
---
# OpenAI Agent + Hindsight Memory Integration
@@ -7,7 +7,7 @@ sidebar_position: 1
:::info Complete Application
This is a complete, runnable application demonstrating Hindsight integration.
[**View source on GitHub →**](https://github.com/vectorize-io/hindsight-cookbook/tree/main/openai-fitness-coach)
[**View source on GitHub →**](https://github.com/vectorize-io/hindsight-cookbook/tree/main/applications/openai-fitness-coach)
:::
@@ -22,7 +22,7 @@ This example showcases:
- **Function calling** to bridge them together
- **Streaming responses** for real-time interaction (enabled by default)
- **Bidirectional memory** - both user data AND coach observations stored
- **System-level post-processing** - automatic knowledge consolidation
- **System-level post-processing** - automatic opinion storage for reliability
- **Temporal-semantic memory** queries via function tools
- **Enhanced preference learning** - coach learns and respects user likes/dislikes
- **Real-world integration pattern** for adding memory to AI agents
@@ -46,9 +46,9 @@ Hindsight API (returns workouts + preferences)
|
OpenAI Assistant (analyzes, gives advice)
|
Function Call: store_memory(advice as experience)
Function Call: store_memory(advice as opinion)
|
Hindsight API (stores coach's advice, consolidates into observations)
Hindsight API (stores coach's observation)
|
Personalized Answer
```
@@ -57,10 +57,10 @@ Personalized Answer
| Component | Standard Demo | OpenAI Integration |
|-----------|---------------|-------------------|
| **Conversation** | Hindsight `/reflect` endpoint | OpenAI Assistant API |
| **Conversation** | Hindsight `/think` endpoint | OpenAI Assistant API |
| **Memory** | Hindsight (built-in) | Hindsight (via function calling) |
| **LLM** | Configured in Hindsight | OpenAI GPT-4 |
| **Knowledge Consolidation** | Automatic after retain | Automatic after retain |
| **Opinion Formation** | Automatic in `/think` | Explicit via `store_memory(type="opinion")` |
| **Best For** | Hindsight-native apps | Integrating memory into existing OpenAI agents |
## Quick Start
@@ -126,7 +126,7 @@ retrieve_memories(query, fact_types, top_k)
search_workouts(after_date, before_date, workout_type)
get_nutrition_summary(after_date, before_date)
get_user_goals()
get_coach_insights(about) # Retrieves observations
get_coach_opinions(about)
```
Each function makes API calls to Hindsight to fetch relevant memories.
@@ -191,8 +191,8 @@ The agent will automatically:
The OpenAI Agent can retrieve different memory types from Hindsight:
- **World Facts** (`fact_type: "world"`): Workouts, meals, activities
- **Experience Facts** (`fact_type: "experience"`): Goals, intentions, coach advice
- **Observations** (`fact_type: "observation"`): Consolidated knowledge about user patterns
- **Agent Facts** (`fact_type: "agent"`): Goals, intentions
- **Opinions** (`fact_type: "opinion"`): Coach's observations about patterns
## Customization
@@ -266,9 +266,9 @@ The key benefit: **Separation of concerns**
**Use Hindsight directly when:**
- You want a complete memory-first solution
- You want automatic memory retrieval and observation consolidation
- You want automatic memory retrieval and opinion formation
- You want to use different LLM providers (not just OpenAI)
- You want the `/reflect` endpoint's integrated approach
- You want the `/think` endpoint's integrated approach
## Learning Points
@@ -0,0 +1,371 @@
---
sidebar_position: 6
---
# Sanity CMS Blog Memory
:::info Complete Application
This is a complete, runnable application demonstrating Hindsight integration.
[**View source on GitHub →**](https://github.com/vectorize-io/hindsight-cookbook/tree/main/applications/sanity-blog-memory)
:::
A Hindsight cookbook recipe demonstrating how to sync blog posts from **Sanity CMS** to Hindsight agent memory, enabling semantic search, temporal queries, and AI-powered content insights.
## Features
- **Blog Post Sync**: Automatically sync all blog posts from Sanity to Hindsight
- **Document-based Upsert**: Idempotent syncing with `document_id` - re-running sync updates existing content
- **Semantic Search**: Find related content using natural language queries
- **Temporal Queries**: Ask "What did I write in January 2025?"
- **Reflect for Insights**: Generate AI-powered analysis of your blog content
- **Related Content Discovery**: Power "Related Posts" features with semantic similarity
## Architecture
```
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ │ │ │ │ │
│ Sanity CMS │───────▶│ Sync Script │───────▶│ Hindsight │
│ (Content) │ GROQ │ (TypeScript) │ HTTP │ (Memory) │
│ │ │ │ │ │
└─────────────────┘ └─────────────────┘ └─────────────────┘
┌─────────────────┐
│ │
│ Your App │
│ - Recall │
│ - Reflect │
│ │
└─────────────────┘
```
## Quick Start
### 1. Start Hindsight
Choose your preferred LLM provider:
**Option A: Using Docker Compose (Recommended)**
```bash
# Set your API key
export OPENAI_API_KEY=sk-...
# OR
export GOOGLE_API_KEY=... # Gemini (free tier available)
# OR
export GROQ_API_KEY=... # Groq (free tier available)
# Start Hindsight
docker compose up -d
```
**Option B: Using Docker directly**
```bash
export OPENAI_API_KEY=sk-...
docker run --rm -it --pull always -p 8888:8888 -p 9999:9999 \
-e HINDSIGHT_API_LLM_API_KEY=$OPENAI_API_KEY \
-e HINDSIGHT_API_LLM_MODEL=gpt-4o-mini \
-v $HOME/.hindsight-docker:/home/hindsight/.pg0 \
ghcr.io/vectorize-io/hindsight:latest
```
- **API**: http://localhost:8888
- **Control Plane UI**: http://localhost:9999
### 2. Configure Environment
```bash
# Copy example config
cp .env.example .env
# Edit with your values
nano .env
```
Required settings:
```bash
# Hindsight
HINDSIGHT_API_URL=http://localhost:8888
HINDSIGHT_BANK_ID=blog-memory
# Sanity CMS
SANITY_PROJECT_ID=your-project-id
SANITY_DATASET=production
```
### 3. Install Dependencies
```bash
npm install
```
### 4. Sync Your Blog Posts
```bash
npm run sync
```
Expected output:
```
=======================================
Sanity -> Hindsight Blog Sync
=======================================
Setting up memory bank...
Memory bank "blog-memory" ready
Fetching posts from Sanity CMS...
Found 10 posts to sync
Syncing posts to Hindsight...
[1/10] "Why I Chose Qwik"... done
[2/10] "Building AI Agents"... done
...
=======================================
Sync Complete
=======================================
Synced: 10 posts
```
### 5. Query Your Content
```bash
npm run query
```
## Query Examples
### Semantic Search
Find related content using natural language:
```typescript
import { recallMemory } from './hindsight-client.js';
// Find posts about AI agents
const result = await recallMemory('AI agents and automation', {
budget: 'mid',
maxTokens: 2048,
});
console.log(`Found ${result.results.length} relevant posts`);
```
### Temporal Queries
Ask about content from specific time periods:
```typescript
// Posts from January 2025
const result = await recallMemory('What did I write about in January 2025?', {
queryTimestamp: '2025-01-31T23:59:59Z',
});
```
### Reflect for Insights
Generate AI-powered analysis of your content:
```typescript
import { reflectOnMemory } from './hindsight-client.js';
// Analyze blog themes
const insights = await reflectOnMemory(
'What are the main themes of my blog? What topics do I write about most?',
{ budget: 'high' }
);
console.log(insights.text);
```
### Related Content Discovery
Power your "Related Posts" feature:
```typescript
// Find posts similar to a specific article
const related = await recallMemory(
'Find posts related to "Why I Chose Qwik for My Personal Website"',
{ budget: 'mid' }
);
```
## Memory Structure
Each blog post is stored with rich metadata for optimal recall:
```
# Blog Post: {title}
**Published:** {date}
**URL:** {base_url}/blog/{slug}
**Tags:** {tags}
**Reading Time:** {reading_time}
## Description
{description}
## Content
{full_content}
```
Key features:
- **document_id**: `post:{slug}` - Enables upsert on re-sync
- **context**: `blog-post` - Categorizes the memory type
- **timestamp**: Post publication date - Enables temporal queries
## Use Cases
### 1. AI-Powered Blog Search
Replace keyword search with semantic understanding:
```typescript
// Old: keyword matching
const results = posts.filter(p => p.title.includes('React'));
// New: semantic understanding
const result = await recallMemory('frontend framework tutorials');
```
### 2. Content Recommendation Engine
Generate personalized recommendations:
```typescript
const recommendations = await reflectOnMemory(
'Based on a reader interested in "AI automation", recommend related posts'
);
```
### 3. Writing Assistant
Get topic suggestions based on your existing content:
```typescript
const suggestions = await reflectOnMemory(
'What topics should I write about next? What gaps exist in my content?'
);
```
### 4. Content Analytics
Analyze your blog's evolution:
```typescript
const analysis = await reflectOnMemory(
'How have my writing topics evolved over the past year?'
);
```
## Configuration
### Environment Variables
| Variable | Description | Default |
|----------|-------------|---------|
| `HINDSIGHT_API_URL` | Hindsight API endpoint | `http://localhost:8888` |
| `HINDSIGHT_BANK_ID` | Memory bank identifier | `blog-memory` |
| `SANITY_PROJECT_ID` | Your Sanity project ID | (required) |
| `SANITY_DATASET` | Sanity dataset name | `production` |
| `SANITY_API_TOKEN` | Sanity API token (for private datasets) | (none) |
| `SANITY_API_VERSION` | Sanity API version | `2024-01-09` |
| `SITE_URL` | Your blog's base URL | `https://example.com` |
### Memory Bank Disposition
The memory bank is configured with disposition traits optimized for blog content:
```typescript
{
skepticism: 2, // Trusting - blog content is authoritative
literalism: 4, // Literal - exact content matters
empathy: 3, // Balanced
}
```
## Extending for Other CMS Platforms
This pattern can be adapted for any CMS. The key components:
### 1. CMS Client
Replace `sanity-client.ts` with your CMS:
```typescript
// contentful-client.ts
import { createClient } from 'contentful';
export async function getAllPosts(): Promise<BlogPost[]> {
const client = createClient({...});
const entries = await client.getEntries({ content_type: 'blogPost' });
return entries.items.map(transformPost);
}
```
### 2. Content Transformation
Ensure your content is formatted for semantic search:
```typescript
function formatPostContent(post: BlogPost): string {
return `# ${post.title}
**Published:** ${post.date}
...
${post.content}`;
}
```
### 3. Document ID Strategy
Use a consistent document ID for upsert behavior:
```typescript
await retainBlogPost(content, {
documentId: `post:${post.slug}`, // Unique, stable identifier
timestamp: post.date,
});
```
## Troubleshooting
### "Connection refused" error
Make sure Hindsight is running:
```bash
docker compose up -d
curl http://localhost:8888/health
```
### "No posts found" during sync
Check your Sanity configuration:
```bash
# Verify project ID
echo $SANITY_PROJECT_ID
# Test GROQ query
npx sanity query '*[_type == "post"][0..2]{title}'
```
### Slow recall/reflect responses
This is normal for the first query as Hindsight builds embeddings. Subsequent queries are faster. Use `budget: 'low'` for faster responses at the cost of recall quality.
## Resources
- [Hindsight Documentation](https://hindsight.vectorize.io/)
- [Hindsight GitHub](https://github.com/vectorize-io/hindsight)
- [Sanity CMS Documentation](https://www.sanity.io/docs)
- [Hindsight Cookbook](https://github.com/vectorize-io/hindsight-cookbook)
## License
MIT
@@ -0,0 +1,276 @@
---
sidebar_position: 7
---
# Stance Tracker
:::info Complete Application
This is a complete, runnable application demonstrating Hindsight integration.
[**View source on GitHub →**](https://github.com/vectorize-io/hindsight-cookbook/tree/main/applications/stancetracker)
:::
An AI-powered application that tracks political candidates' stances on issues over time using Hindsight memory system and web scraping.
## Features
- **Geographic Targeting**: Track stances by country, state/province, and city
- **Multi-Candidate Tracking**: Monitor multiple candidates simultaneously
- **Temporal Analysis**: Historical stance tracking with configurable time ranges
- **Automated Scraping**: Periodic content collection with configurable frequencies (hourly/daily/weekly)
- **Stance Change Detection**: Automatic detection and highlighting of position changes
- **Interactive Timeline**: Visual graph showing stance evolution with reference callouts
- **Source Attribution**: All stances linked to verified sources with excerpts
## Architecture
### Memory System (Hindsight Integration)
This app uses the Hindsight memory system from `github.com/vectorize-io/hindsight`:
1. **Banks**: Each scraper agent has its own memory bank
2. **Retain**: Stores candidate statements and web scraping results
3. **Recall**: Semantic search to retrieve relevant memories
4. **Reflect**: Generates contextual analysis using stored memories
5. **Temporal Search**: Queries memories within specific time periods
### Tech Stack
- **Frontend**: Next.js 16, React, TypeScript, TailwindCSS
- **Visualization**: Recharts for timeline graphs
- **Backend**: Next.js API routes
- **Memory**: Hindsight (from github.com/vectorize-io/hindsight)
- **Database**: JSON file storage (no database required)
- **Web Search**: Tavily API
- **LLM**: OpenAI/Anthropic/Groq (configurable)
- **Scheduling**: node-cron
## Prerequisites
1. **Hindsight API** running (from github.com/vectorize-io/hindsight)
2. **API Keys**:
- Tavily API key (for web search)
- LLM provider API key (OpenAI, Anthropic, or Groq)
## Setup
### 1. Install Dependencies
```bash
npm install
```
### 2. Configure Environment
Copy `.env.example` to `.env` and fill in your credentials:
```bash
cp .env.example .env
```
Edit `.env`:
```env
# Hindsight API (from github.com/vectorize-io/hindsight)
HINDSIGHT_API_URL=http://localhost:8888
# Tavily API (for web search)
TAVILY_API_KEY=your_tavily_api_key_here
# LLM Provider
LLM_PROVIDER=openai # or anthropic, groq
LLM_API_KEY=your_llm_api_key_here
LLM_MODEL=gpt-4-turbo-preview
```
### 3. Start Hindsight
Clone and run Hindsight from github.com/vectorize-io/hindsight:
```bash
# Clone and run github.com/vectorize-io/hindsight
cd /path/to/hindsight
cargo run --bin hindsight-server
```
Verify Hindsight is running at `http://localhost:8888`
### 4. Run the Application
```bash
npm run dev
```
Visit `http://localhost:3000`
## Usage
### Creating a Tracking Session
1. **Set Location**: Enter country (required), state/province, and city (optional)
2. **Choose Topic**: Specify the issue to track (e.g., "Climate Change Policy")
3. **Add Candidates**: Enter names of candidates/politicians to track
4. **Configure Time Range**: Set historical start/end dates for initial analysis
5. **Set Frequency**: Choose how often to check for updates (hourly/daily/weekly)
6. **Start Tracking**: Click "Start Tracking" to begin
### Viewing Results
- **Timeline Graph**: Shows confidence levels of each candidate's stance over time
- **Stance Changes**: Red circles on the graph indicate detected position changes
- **Click Points**: Click any point to see detailed stance information and sources
- **Source Links**: Each stance includes links to original references
### Managing Sessions
- **Pause/Resume**: Temporarily stop or restart tracking
- **Run Now**: Trigger an immediate update outside the schedule
- **Status**: View current session status and frequency
## API Endpoints
### Sessions
- `POST /api/sessions` - Create new tracking session
- `GET /api/sessions?id={id}` - Get session details
- `GET /api/sessions` - List all sessions
- `PATCH /api/sessions` - Update session status
### Stances
- `POST /api/stances` - Process candidate stance
- `GET /api/stances?sessionId={id}&candidate={name}` - Get stances
### Scheduler
- `POST /api/scheduler` - Control session scheduling
- Actions: `start`, `stop`, `run`
## Hindsight Integration Examples
### 1. Storing Memories
```typescript
// Store web scraping results
await hindsightClient.retain(bankId, articleContent, {
context: 'web_search_result',
timestamp: articleDate,
metadata: { url: articleUrl }
});
```
### 2. Semantic Search
```typescript
// Search for relevant memories
const results = await hindsightClient.recall(bankId, query, {
budget: 'high',
maxTokens: 8192
});
```
### 3. Temporal Filtering
```typescript
// Query memories up to a specific point in time
const results = await hindsightClient.recall(bankId, query, {
queryTimestamp: '2024-12-01T00:00:00Z'
});
```
### 4. Contextual Analysis
```typescript
// Generate analysis using stored memories
const response = await hindsightClient.reflect(bankId,
'What is the candidate\'s stance on this issue?',
{ budget: 'high' }
);
```
## Production Deployment
### Vercel Deployment
```bash
# Install Vercel CLI
npm i -g vercel
# Deploy
vercel
# Set environment variables in Vercel dashboard:
# - HINDSIGHT_API_URL
# - TAVILY_API_KEY
# - LLM_PROVIDER
# - LLM_API_KEY
# - LLM_MODEL
```
**Note**: The `data/` directory for JSON storage will be ephemeral on Vercel. For production, consider using a persistent database or object storage.
## Development
### Project Structure
```
stancetracker/
├── app/
│ ├── api/ # API routes
│ ├── globals.css # Global styles
│ ├── layout.tsx # Root layout
│ └── page.tsx # Main page
├── components/ # React components
├── lib/
│ ├── db/ # JSON database utilities
│ ├── hindsight-client.ts # Hindsight API client
│ ├── llm-client.ts # LLM provider client
│ ├── web-scraper.ts # Tavily web scraper
│ ├── scraper-agent.ts # Content scraper
│ ├── rag-system.ts # Memory retrieval
│ ├── stance-extractor.ts # Stance analysis
│ ├── stance-pipeline.ts # Main pipeline
│ └── scheduler.ts # Job scheduling
└── types/ # TypeScript types
```
### Adding New LLM Providers
Edit `lib/llm-client.ts` and add a new method:
```typescript
private async newProviderComplete(messages, options) {
// Implementation
}
```
## Limitations
- **Web Search**: Uses Tavily API which has rate limits
- **Source Verification**: Manual verification recommended for critical applications
- **Stance Extraction**: LLM-based, subject to model limitations
- **Storage**: JSON file storage is not suitable for high-scale production use
- **Rate Limits**: Respect API rate limits for Tavily, Hindsight, and LLM providers
## Future Enhancements
- [ ] Real-time social media monitoring
- [ ] Speech/video transcription analysis
- [ ] Multi-language support
- [ ] Sentiment analysis integration
- [ ] Comparative analysis dashboard
- [ ] Export to CSV/PDF
- [ ] Email notifications for stance changes
- [ ] Public API for third-party integrations
## License
MIT
## Support
For issues or questions, please check:
- Hindsight documentation: `github.com/vectorize-io/hindsight/README.md`
- Tavily API docs: https://tavily.com/
- Project issues: Create an issue in the repository
+14 -2
View File
@@ -15,13 +15,25 @@ Practical patterns, recipes, and complete applications for building with Hindsig
{ title: "Per-User Memory", href: "/cookbook/recipes/per-user-memory" },
{ title: "Support Agent with Shared Knowledge", href: "/cookbook/recipes/support-agent-shared-knowledge" },
{ title: "Memory with LiteLLM", href: "/cookbook/recipes/litellm-memory-demo" },
{ title: "Routing Tool Learning", href: "/cookbook/recipes/tool-learning-demo" }
{ title: "Routing Tool Learning", href: "/cookbook/recipes/tool-learning-demo" },
{ title: "Fitness Coach with Hindsight Memory", href: "/cookbook/recipes/fitness_tracker" },
{ title: "Healthcare Assistant with Hindsight Memory", href: "/cookbook/recipes/healthcare_assistant" },
{ title: "Movie Recommendation Assistant with Hindsight Memory", href: "/cookbook/recipes/movie_recommendation" },
{ title: "Personal AI Assistant with Hindsight Memory", href: "/cookbook/recipes/personal_assistant" },
{ title: "Personalized Search Agent with Hindsight Memory", href: "/cookbook/recipes/personalized_search" },
{ title: "Study Buddy with Hindsight Memory", href: "/cookbook/recipes/study_buddy" }
]}
/>
<RecipeCarousel
title="Applications"
items={[
{ title: "OpenAI Agent + Hindsight Memory Integration", href: "/cookbook/applications/openai-fitness-coach" }
{ title: "Chat Memory App", href: "/cookbook/applications/chat-memory" },
{ title: "Deliveryman Demo", href: "/cookbook/applications/deliveryman-demo" },
{ title: "Memory Approaches Comparison Demo", href: "/cookbook/applications/hindsight-litellm-demo" },
{ title: "Tool Learning Demo", href: "/cookbook/applications/hindsight-tool-learning-demo" },
{ title: "OpenAI Agent + Hindsight Memory Integration", href: "/cookbook/applications/openai-fitness-coach" },
{ title: "Sanity CMS Blog Memory", href: "/cookbook/applications/sanity-blog-memory" },
{ title: "Stance Tracker", href: "/cookbook/applications/stancetracker" }
]}
/>
@@ -0,0 +1,306 @@
---
sidebar_position: 6
---
# Fitness Coach with Hindsight Memory
:::tip Run this notebook
This recipe is available as an interactive Jupyter notebook.
[**Open in GitHub →**](https://github.com/vectorize-io/hindsight-cookbook/blob/main/notebooks/fitness_tracker.ipynb)
:::
A personalized fitness assistant that tracks your workouts, diet, recovery, and progress over time to give contextual advice.
## Features
- Logs workout sessions with exercises and weights
- Tracks meals and dietary preferences
- Monitors recovery and sleep patterns
- Provides personalized training advice
## Prerequisites
- OpenAI API key
- Hindsight running locally via Docker (see setup below)
## Start Hindsight Locally
Before running this notebook, start Hindsight in a terminal:
```bash
export OPENAI_API_KEY="your-openai-api-key"
docker run --rm -it --pull always -p 8888:8888 -p 9999:9999 \
-e HINDSIGHT_API_LLM_API_KEY=$OPENAI_API_KEY \
-e HINDSIGHT_API_LLM_MODEL=gpt-4o-mini \
-v $HOME/.hindsight-docker:/home/hindsight/.pg0 \
ghcr.io/vectorize-io/hindsight:latest
```
## 1. Install Dependencies
```python
!pip install -q hindsight-client openai nest-asyncio
```
## 2. Configure OpenAI API Key
Enter your OpenAI API key when prompted (used by both Hindsight and the demo).
```python
import getpass
import os
# Set OpenAI API key (used by both Hindsight and the demo)
if not os.getenv("OPENAI_API_KEY"):
os.environ["OPENAI_API_KEY"] = getpass.getpass("Enter your OpenAI API key: ")
print("API key configured!")
```
## 3. Initialize Clients
```python
import nest_asyncio
nest_asyncio.apply()
from datetime import datetime
from openai import OpenAI
from hindsight_client import Hindsight
# Initialize Hindsight client (connects to local Docker instance)
hindsight = Hindsight(
base_url=os.getenv("HINDSIGHT_BASE_URL", "http://localhost:8888"),
)
openai_client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
USER_ID = "fitness-user-demo"
print("Clients initialized!")
```
## 4. Define Helper Functions
```python
def log_workout(workout_details: str) -> str:
"""Log a workout session with timestamp."""
today = datetime.now().strftime("%B %d, %Y")
hindsight.retain(
bank_id=USER_ID,
content=f"{today} - WORKOUT LOG: {workout_details}",
metadata={"category": "workout", "date": today},
)
return f"Logged workout for {today}: {workout_details}"
def log_meal(meal_details: str) -> str:
"""Log a meal with timestamp."""
today = datetime.now().strftime("%B %d, %Y")
hindsight.retain(
bank_id=USER_ID,
content=f"{today} - MEAL LOG: {meal_details}",
metadata={"category": "nutrition", "date": today},
)
return f"Logged meal for {today}: {meal_details}"
def log_recovery(recovery_details: str) -> str:
"""Log recovery information (sleep, soreness, etc.)."""
today = datetime.now().strftime("%B %d, %Y")
hindsight.retain(
bank_id=USER_ID,
content=f"{today} - RECOVERY LOG: {recovery_details}",
metadata={"category": "recovery", "date": today},
)
return f"Logged recovery for {today}: {recovery_details}"
def store_user_profile(profile_info: str) -> str:
"""Store user profile information."""
hindsight.retain(
bank_id=USER_ID,
content=f"USER PROFILE: {profile_info}",
metadata={"category": "profile"},
)
return f"Stored profile info: {profile_info}"
def fitness_coach(user_query: str) -> str:
"""Get personalized fitness advice based on query and user history."""
memories = hindsight.recall(
bank_id=USER_ID,
query=f"fitness workout diet recovery goals {user_query}",
budget="high",
)
memory_context = ""
if memories and memories.results:
memory_context = "\n".join(f"- {m.text}" for m in memories.results[:10])
system_prompt = f"""You are a knowledgeable and supportive fitness coach.
You have access to the user's workout history, diet logs, recovery notes, and personal profile.
What you know about this user:
{memory_context if memory_context else "No history recorded yet."}
Provide personalized, actionable advice based on their:
- Training history and progress
- Dietary preferences and restrictions
- Recovery patterns
- Personal goals
Be encouraging but realistic. Reference their specific history when relevant."""
response = openai_client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_query},
],
temperature=0.7,
max_tokens=600,
)
advice = response.choices[0].message.content
hindsight.retain(
bank_id=USER_ID,
content=f"User asked: {user_query}\nCoach advised: {advice[:200]}...",
metadata={"category": "coaching"},
)
return advice
def get_progress_report() -> str:
"""Generate a progress report based on workout history."""
report = hindsight.reflect(
bank_id=USER_ID,
query="""Analyze this user's fitness journey:
1. How consistent have they been with workouts?
2. What progress have they made (weight lifted, exercises)?
3. How is their recovery and sleep?
4. What dietary patterns do you notice?
5. What should they focus on next?""",
budget="high",
)
return report.text if hasattr(report, 'text') else str(report)
print("Helper functions defined!")
```
## 5. Set Up User Profile
```python
print("Setting up user profile...")
profile_data = [
"Name: Anish, Age: 26, Height: 5'10\", Weight: 72kg",
"Goal: Building lean muscle, started gym 6 months ago",
"Routine: Push-pull-legs split, 5x per week",
"Rest days: Wednesday and Sunday",
"Dietary restriction: Mild lactose intolerance, uses almond milk",
"Health note: Occasional knee pain, avoids deep squats",
"Supplements: Whey protein (lactose-free), magnesium",
"Sleep: Aims for 7+ hours, performance drops under 6 hours",
]
for info in profile_data:
store_user_profile(info)
print(f" Stored: {info[:50]}...")
```
## 6. Log Workout History
```python
print("Logging workout history...")
workouts = [
"Push day: Bench press 3x8 @ 60kg, overhead press 4x12, tricep dips 3x10. Felt strong.",
"Pull day: Deadlift 3x5 @ 80kg, barbell rows 4x10, bicep curls 3x12. Good session.",
"Leg day: Leg press 4x12, hamstring curls 3x12, glute bridges 3x15. Knee felt okay.",
]
for workout in workouts:
print(f" {log_workout(workout)[:60]}...")
print("\nLogging recent meals...")
meals = [
"Post-workout: Whey shake with almond milk, banana, oats",
"Dinner: Grilled chicken, brown rice, steamed vegetables",
"Snack: Greek yogurt (lactose-free) with berries",
]
for meal in meals:
print(f" {log_meal(meal)[:60]}...")
print("\nLogging recovery notes...")
recovery = [
"Slept 7.5 hours, feeling well rested",
"Some DOMS in legs from yesterday, using turmeric milk",
]
for note in recovery:
print(f" {log_recovery(note)[:60]}...")
```
## 7. Talk to Your Fitness Coach
```python
import time
print("=" * 60)
print(" Talking to your fitness coach...")
print("=" * 60)
queries = [
"How much was I lifting for bench press recently?",
"I slept poorly last night (only 5 hours). What should I do for today's workout?",
"Suggest a post-workout meal that works with my dietary restrictions.",
"My knee has been bothering me more. Any exercise modifications?",
]
for query in queries:
print(f"\nUser: {query}")
print("-" * 40)
response = fitness_coach(query)
print(f"Coach: {response}")
time.sleep(1)
```
## 8. Generate Progress Report
```python
print("=" * 60)
print(" Progress Report")
print("=" * 60)
print(get_progress_report())
```
## 9. Try Your Own Query
```python
your_query = "What exercises should I do today?" # Change this!
print(f"You: {your_query}")
print("-" * 40)
print(f"Coach: {fitness_coach(your_query)}")
```
## 10. Cleanup
```python
hindsight.close()
print("Client connection closed.")
```
@@ -0,0 +1,299 @@
---
sidebar_position: 7
---
# Healthcare Assistant with Hindsight Memory
:::tip Run this notebook
This recipe is available as an interactive Jupyter notebook.
[**Open in GitHub →**](https://github.com/vectorize-io/hindsight-cookbook/blob/main/notebooks/healthcare_assistant.ipynb)
:::
A supportive healthcare chatbot that remembers patient history, symptoms, medications, and preferences to provide personalized guidance.
## Disclaimer
**This is a demo application and should NOT be used for actual medical advice. Always consult qualified healthcare professionals.**
## Features
- Tracks symptoms, medications, and allergies
- Maintains patient history across conversations
- Provides health information and wellness tips
- Schedules appointments
## Prerequisites
- OpenAI API key
- Hindsight running locally via Docker (see setup below)
## Start Hindsight Locally
Before running this notebook, start Hindsight in a terminal:
```bash
export OPENAI_API_KEY="your-openai-api-key"
docker run --rm -it --pull always -p 8888:8888 -p 9999:9999 \
-e HINDSIGHT_API_LLM_API_KEY=$OPENAI_API_KEY \
-e HINDSIGHT_API_LLM_MODEL=gpt-4o-mini \
-v $HOME/.hindsight-docker:/home/hindsight/.pg0 \
ghcr.io/vectorize-io/hindsight:latest
```
## 1. Install Dependencies
```python
!pip install -q hindsight-client openai nest-asyncio
```
## 2. Configure OpenAI API Key
Enter your OpenAI API key when prompted (used by both Hindsight and the demo).
```python
import getpass
import os
# Set OpenAI API key (used by both Hindsight and the demo)
if not os.getenv("OPENAI_API_KEY"):
os.environ["OPENAI_API_KEY"] = getpass.getpass("Enter your OpenAI API key: ")
print("API key configured!")
```
## 3. Initialize Clients
```python
import nest_asyncio
nest_asyncio.apply()
from datetime import datetime
import random
from openai import OpenAI
from hindsight_client import Hindsight
# Initialize Hindsight client (connects to local Docker instance)
hindsight = Hindsight(
base_url=os.getenv("HINDSIGHT_BASE_URL", "http://localhost:8888"),
)
openai_client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
PATIENT_ID = "patient-demo"
def get_patient_bank_id(patient_id: str) -> str:
return f"patient-{patient_id}"
print("Clients initialized!")
```
## 4. Define Helper Functions
```python
def store_patient_info(patient_id: str, info: str, category: str = "general") -> str:
"""Store patient information."""
bank_id = get_patient_bank_id(patient_id)
today = datetime.now().strftime("%B %d, %Y")
hindsight.retain(
bank_id=bank_id,
content=f"{today} - {category.upper()}: {info}",
metadata={"category": category, "date": today},
)
return f"Recorded {category}: {info}"
def get_patient_history(patient_id: str, query: str) -> str:
"""Retrieve relevant patient history."""
bank_id = get_patient_bank_id(patient_id)
memories = hindsight.recall(
bank_id=bank_id,
query=query,
budget="high",
)
if memories and memories.results:
return "\n".join(f"- {m.text}" for m in memories.results[:10])
return "No relevant history found."
def healthcare_chat(patient_id: str, user_message: str) -> str:
"""Chat with the healthcare assistant."""
bank_id = get_patient_bank_id(patient_id)
history = get_patient_history(
patient_id,
f"symptoms medications allergies conditions {user_message}"
)
system_prompt = f"""You are a supportive healthcare assistant chatbot.
IMPORTANT DISCLAIMERS:
- You are NOT a doctor and cannot provide medical diagnoses
- Always recommend consulting healthcare professionals for serious concerns
- Never prescribe medications or suggest stopping prescribed treatments
Your role:
- Listen empathetically to patient concerns
- Remember and reference their medical history
- Provide general health information and wellness tips
- Help track symptoms over time
- Remind about medications and appointments
- Suggest when to seek professional care
Patient History:
{history}
Guidelines:
- Be warm and supportive
- Ask clarifying questions when needed
- Reference their history when relevant
- Flag any concerning symptoms for professional review"""
response = openai_client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_message},
],
temperature=0.7,
max_tokens=600,
)
answer = response.choices[0].message.content
hindsight.retain(
bank_id=bank_id,
content=f"Patient concern: {user_message}\nGuidance provided: {answer[:200]}...",
metadata={"category": "consultation"},
)
return answer
def get_health_summary(patient_id: str) -> str:
"""Generate a health summary for the patient."""
bank_id = get_patient_bank_id(patient_id)
summary = hindsight.reflect(
bank_id=bank_id,
query="""Summarize this patient's health profile:
1. Known conditions and diagnoses
2. Current medications
3. Allergies and sensitivities
4. Recent symptoms reported
5. Lifestyle factors mentioned
6. Any patterns or trends in their health""",
budget="high",
)
return summary.text if hasattr(summary, 'text') else str(summary)
def schedule_appointment(patient_id: str, appointment_type: str, preferred_time: str) -> str:
"""Schedule an appointment (demo)."""
confirmation_id = f"APT-{random.randint(10000, 99999)}"
store_patient_info(
patient_id,
f"Appointment scheduled: {appointment_type} - Preferred time: {preferred_time} - Confirmation: {confirmation_id}",
category="appointment"
)
return f"Appointment requested: {appointment_type}\nPreferred time: {preferred_time}\nConfirmation ID: {confirmation_id}\n\nA staff member will confirm the exact time within 24 hours."
print("Helper functions defined!")
```
## 5. Set Up Patient Profile
```python
print("Setting up patient profile...")
patient_info = [
("Age: 45, Male, Height: 5'11\", Weight: 185 lbs", "demographics"),
("Allergy: Penicillin - causes hives", "allergies"),
("Allergy: Shellfish - causes throat swelling", "allergies"),
("Current medication: Lisinopril 10mg daily for blood pressure", "medications"),
("Current medication: Metformin 500mg twice daily for Type 2 diabetes", "medications"),
("Condition: Diagnosed with Type 2 diabetes in 2020", "conditions"),
("Condition: Mild hypertension, well-controlled", "conditions"),
("Family history: Father had heart disease", "family_history"),
("Lifestyle: Sedentary job, trying to exercise more", "lifestyle"),
]
for info, category in patient_info:
result = store_patient_info(PATIENT_ID, info, category)
print(f" {result}")
```
## 6. Healthcare Chat
```python
import time
print("=" * 60)
print(" Healthcare Chat")
print("=" * 60)
conversations = [
"Hi, I've been having headaches for the past few days. Should I be worried?",
"The headaches are mostly in the afternoon. I've also been feeling more tired than usual.",
"I've been checking my blood sugar and it's been a bit higher lately, around 140-150 fasting.",
"Can you remind me what allergies I have? I'm going to a new restaurant.",
]
for message in conversations:
print(f"\nPatient: {message}")
print("-" * 40)
response = healthcare_chat(PATIENT_ID, message)
print(f"Assistant: {response}")
time.sleep(1)
```
## 7. Schedule Appointment
```python
print("=" * 60)
print(" Scheduling Appointment")
print("=" * 60)
print(schedule_appointment(PATIENT_ID, "General checkup", "Next Tuesday afternoon"))
```
## 8. Health Summary
```python
print("=" * 60)
print(" Patient Health Summary")
print("=" * 60)
print(get_health_summary(PATIENT_ID))
```
## 9. Try Your Own Question
```python
your_question = "Should I adjust my Metformin dose?" # Change this!
print(f"You: {your_question}")
print("-" * 40)
print(f"Assistant: {healthcare_chat(PATIENT_ID, your_question)}")
```
## 10. Cleanup
```python
hindsight.close()
print("Client connection closed.")
```
@@ -0,0 +1,246 @@
---
sidebar_position: 8
---
# Movie Recommendation Assistant with Hindsight Memory
:::tip Run this notebook
This recipe is available as an interactive Jupyter notebook.
[**Open in GitHub →**](https://github.com/vectorize-io/hindsight-cookbook/blob/main/notebooks/movie_recommendation.ipynb)
:::
A personalized movie recommender that remembers your preferences, watch history, and tastes to give better suggestions over time.
## Features
- Remembers favorite genres, directors, and actors
- Tracks movies you've watched and enjoyed
- Provides contextual recommendations based on mood
## Prerequisites
- OpenAI API key
- Hindsight running locally via Docker (see setup below)
## Start Hindsight Locally
Before running this notebook, start Hindsight in a terminal:
```bash
export OPENAI_API_KEY="your-openai-api-key"
docker run --rm -it --pull always -p 8888:8888 -p 9999:9999 \
-e HINDSIGHT_API_LLM_API_KEY=$OPENAI_API_KEY \
-e HINDSIGHT_API_LLM_MODEL=gpt-4o-mini \
-v $HOME/.hindsight-docker:/home/hindsight/.pg0 \
ghcr.io/vectorize-io/hindsight:latest
```
## 1. Install Dependencies
```python
!pip install -q hindsight-client openai nest-asyncio
```
## 2. Configure OpenAI API Key
Enter your OpenAI API key when prompted (used by both Hindsight and the demo).
```python
import getpass
import os
# Set OpenAI API key (used by both Hindsight and the demo)
if not os.getenv("OPENAI_API_KEY"):
os.environ["OPENAI_API_KEY"] = getpass.getpass("Enter your OpenAI API key: ")
print("API key configured!")
```
## 3. Initialize Clients
```python
import nest_asyncio
nest_asyncio.apply()
from openai import OpenAI
from hindsight_client import Hindsight
# Initialize Hindsight client (connects to local Docker instance)
hindsight = Hindsight(
base_url=os.getenv("HINDSIGHT_BASE_URL", "http://localhost:8888"),
)
# Initialize OpenAI client
openai_client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
# Unique identifier for this user's memory bank
USER_ID = "movie-fan-demo"
print("Clients initialized!")
```
## 4. Define Helper Functions
These functions demonstrate the three core Hindsight operations:
- **retain()**: Store memories
- **recall()**: Retrieve relevant memories
- **reflect()**: Synthesize insights from memories
```python
def get_recommendation(user_query: str) -> str:
"""
Get a movie recommendation based on user query and remembered preferences.
"""
# Recall relevant memories about this user's movie preferences
memories = hindsight.recall(
bank_id=USER_ID,
query=f"movie preferences tastes genres {user_query}",
budget="mid",
)
# Build context from memories
memory_context = ""
if memories and memories.results:
memory_context = "\n".join(
f"- {m.text}" for m in memories.results[:5]
)
# Generate recommendation with context
system_prompt = f"""You are a helpful movie recommendation assistant.
You remember the user's preferences and past conversations to give personalized suggestions.
What you know about this user:
{memory_context if memory_context else "No previous preferences recorded yet."}
Give thoughtful, personalized recommendations based on their tastes.
If they mention new preferences, acknowledge them."""
response = openai_client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_query},
],
temperature=0.7,
max_tokens=500,
)
recommendation = response.choices[0].message.content
# Store this interaction for future context
hindsight.retain(
bank_id=USER_ID,
content=f"User asked: {user_query}\nRecommendation given: {recommendation}",
metadata={"category": "movie_recommendation"},
)
return recommendation
def store_preference(preference: str) -> None:
"""Store an explicit user preference."""
hindsight.retain(
bank_id=USER_ID,
content=f"User preference: {preference}",
metadata={"category": "preference"},
)
print(f"Stored preference: {preference}")
def get_preference_summary() -> str:
"""Get a summary of what we know about the user's movie tastes."""
summary = hindsight.reflect(
bank_id=USER_ID,
query="Summarize this user's movie preferences, favorite genres, actors they like, and movies they've mentioned enjoying or disliking.",
budget="high",
)
return summary.text if hasattr(summary, 'text') else str(summary)
print("Helper functions defined!")
```
## 5. Run the Demo
Watch how the assistant learns and remembers preferences across conversations.
```python
import time
print("=" * 60)
print(" Movie Recommendation Assistant with Memory")
print("=" * 60)
print()
# Simulate a conversation over time
conversations = [
"I'm looking for a movie to watch tonight. Any suggestions?",
"I really loved Inception and Interstellar. Christopher Nolan is amazing!",
"Can you suggest something similar to those? I like mind-bending plots.",
"Actually, I'm not in the mood for something heavy. Something lighter?",
"I watched The Grand Budapest Hotel last week and loved it!",
"What should I watch tonight? Remember what I like!",
]
for i, query in enumerate(conversations, 1):
print(f"\n[Conversation {i}]")
print(f"User: {query}")
print("-" * 40)
response = get_recommendation(query)
print(f"Assistant: {response}")
print()
time.sleep(1)
```
## 6. View Learned Preferences
Use `reflect()` to synthesize what Hindsight has learned about your movie tastes.
```python
print("=" * 60)
print(" What I've learned about your movie tastes:")
print("=" * 60)
print(get_preference_summary())
```
## 7. Try Your Own Queries
Experiment with your own movie preferences!
```python
# Try your own query!
your_query = "I'm in the mood for a sci-fi thriller" # Change this!
print(f"You: {your_query}")
print("-" * 40)
print(f"Assistant: {get_recommendation(your_query)}")
```
## 8. Cleanup
Close the Hindsight client connection.
```python
hindsight.close()
print("Client connection closed.")
```
```python
```
```python
```
@@ -0,0 +1,266 @@
---
sidebar_position: 9
---
# Personal AI Assistant with Hindsight Memory
:::tip Run this notebook
This recipe is available as an interactive Jupyter notebook.
[**Open in GitHub →**](https://github.com/vectorize-io/hindsight-cookbook/blob/main/notebooks/personal_assistant.ipynb)
:::
A general-purpose personal assistant that remembers your preferences, schedule, family, work context, and past conversations.
## Features
- Remembers family, work, and personal details
- Tracks preferences and habits
- Helps with scheduling and reminders
- Maintains context across conversations
## Prerequisites
- OpenAI API key
- Hindsight running locally via Docker (see setup below)
## Start Hindsight Locally
Before running this notebook, start Hindsight in a terminal:
```bash
export OPENAI_API_KEY="your-openai-api-key"
docker run --rm -it --pull always -p 8888:8888 -p 9999:9999 \
-e HINDSIGHT_API_LLM_API_KEY=$OPENAI_API_KEY \
-e HINDSIGHT_API_LLM_MODEL=gpt-4o-mini \
-v $HOME/.hindsight-docker:/home/hindsight/.pg0 \
ghcr.io/vectorize-io/hindsight:latest
```
## 1. Install Dependencies
```python
!pip install -q hindsight-client openai nest-asyncio
```
## 2. Configure OpenAI API Key
Enter your OpenAI API key when prompted (used by both Hindsight and the demo).
```python
import getpass
import os
# Set OpenAI API key (used by both Hindsight and the demo)
if not os.getenv("OPENAI_API_KEY"):
os.environ["OPENAI_API_KEY"] = getpass.getpass("Enter your OpenAI API key: ")
print("API key configured!")
```
## 3. Initialize Clients
```python
import nest_asyncio
nest_asyncio.apply()
from datetime import datetime
from openai import OpenAI
from hindsight_client import Hindsight
# Initialize Hindsight client (connects to local Docker instance)
hindsight = Hindsight(
base_url=os.getenv("HINDSIGHT_BASE_URL", "http://localhost:8888"),
)
openai_client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
USER_ID = "assistant-user-demo"
print("Clients initialized!")
```
## 4. Define Helper Functions
```python
def remember(info: str, category: str = "general") -> str:
"""Store information to remember."""
today = datetime.now().strftime("%B %d, %Y")
hindsight.retain(
bank_id=USER_ID,
content=f"{today}: {info}",
metadata={"category": category, "date": today},
)
return f"I'll remember: {info}"
def recall_context(query: str) -> str:
"""Recall relevant memories for context."""
memories = hindsight.recall(
bank_id=USER_ID,
query=query,
budget="high",
)
if memories and memories.results:
return "\n".join(f"- {m.text}" for m in memories.results[:8])
return ""
def chat(user_message: str) -> str:
"""Chat with the personal assistant."""
context = recall_context(user_message)
system_prompt = f"""You are a helpful personal AI assistant with long-term memory.
You remember the user's preferences, schedule, family, work context, and past conversations.
What you remember about this user:
{context if context else "No memories recorded yet."}
Your capabilities:
- Remember things when asked ("Remember that...", "Don't forget...")
- Recall past information ("What did I tell you about...", "When is...")
- Provide personalized suggestions based on known preferences
- Help with scheduling and reminders
- Have natural conversations while maintaining context
Be helpful, proactive, and reference relevant memories naturally."""
response = openai_client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_message},
],
temperature=0.7,
max_tokens=500,
)
answer = response.choices[0].message.content
# Check if user is asking to remember something
lower_msg = user_message.lower()
if any(phrase in lower_msg for phrase in ["remember that", "don't forget", "remind me", "note that"]):
hindsight.retain(
bank_id=USER_ID,
content=f"User asked to remember: {user_message}",
metadata={"category": "reminder"},
)
# Store the interaction
hindsight.retain(
bank_id=USER_ID,
content=f"Conversation - User: {user_message[:100]} | Assistant: {answer[:100]}",
metadata={"category": "conversation"},
)
return answer
def get_summary(topic: str = None) -> str:
"""Get a summary of memories."""
query = f"Summarize what you know about {topic}" if topic else \
"Summarize everything you know about this user"
summary = hindsight.reflect(
bank_id=USER_ID,
query=query,
budget="high",
)
return summary.text if hasattr(summary, 'text') else str(summary)
print("Helper functions defined!")
```
## 5. Build Context
```python
print("Building context...")
initial_context = [
("My name is Alex and I work as a product manager at TechCorp", "personal"),
("My wife's name is Sarah and we have two kids: Emma (7) and Jack (4)", "family"),
("I prefer morning meetings and try to keep afternoons for deep work", "preference"),
("My mom's birthday is March 15th", "event"),
("I'm trying to read more - currently reading 'Atomic Habits'", "hobby"),
("I have a weekly team standup every Monday at 10am", "schedule"),
("I'm allergic to cats", "health"),
("My favorite coffee is a flat white with oat milk", "preference"),
("I'm training for a half marathon in April", "goal"),
]
for info, category in initial_context:
result = remember(info, category)
print(f" {result}")
```
## 6. Have a Conversation
```python
import time
print("=" * 60)
print(" Conversation")
print("=" * 60)
conversations = [
"Hey, what's my wife's name again?",
"Remember that my Q1 review is next Thursday at 2pm",
"I need a gift idea for my mom's birthday",
"What time is my Monday standup?",
"Can you recommend a coffee order for me?",
"What books am I reading?",
]
for message in conversations:
print(f"\nAlex: {message}")
print("-" * 40)
response = chat(message)
print(f"Assistant: {response}")
time.sleep(1)
```
## 7. View Summary
```python
print("=" * 60)
print(" What I Know About You")
print("=" * 60)
print(get_summary())
```
```python
print("=" * 60)
print(" Your Family")
print("=" * 60)
print(get_summary("family"))
```
## 8. Try Your Own Message
```python
your_message = "What should I focus on this month with my training?" # Change this!
print(f"You: {your_message}")
print("-" * 40)
print(f"Assistant: {chat(your_message)}")
```
## 9. Cleanup
```python
hindsight.close()
print("Client connection closed.")
```
@@ -0,0 +1,299 @@
---
sidebar_position: 10
---
# Personalized Search Agent with Hindsight Memory
:::tip Run this notebook
This recipe is available as an interactive Jupyter notebook.
[**Open in GitHub →**](https://github.com/vectorize-io/hindsight-cookbook/blob/main/notebooks/personalized_search.ipynb)
:::
A search assistant that learns your preferences, location, dietary needs, and lifestyle to provide contextually relevant search results.
## Features
- Learns location, dietary restrictions, and lifestyle
- Personalizes search queries based on context
- Remembers past searches and preferences
- Integrates with Tavily for real web search (optional)
## Prerequisites
- OpenAI API key
- Hindsight running locally via Docker (see setup below)
- Tavily API key (optional, for real web search)
## Start Hindsight Locally
Before running this notebook, start Hindsight in a terminal:
```bash
export OPENAI_API_KEY="your-openai-api-key"
docker run --rm -it --pull always -p 8888:8888 -p 9999:9999 \
-e HINDSIGHT_API_LLM_API_KEY=$OPENAI_API_KEY \
-e HINDSIGHT_API_LLM_MODEL=gpt-4o-mini \
-v $HOME/.hindsight-docker:/home/hindsight/.pg0 \
ghcr.io/vectorize-io/hindsight:latest
```
## 1. Install Dependencies
```python
# Tavily is optional - demo works with simulated results if not installed
!pip install -q hindsight-client openai tavily-python nest-asyncio
```
## 2. Configure API Keys
Enter your API keys when prompted. Tavily is optional - press Enter to skip for simulated search results.
```python
import getpass
import os
# Set OpenAI API key (used by both Hindsight and the demo)
if not os.getenv("OPENAI_API_KEY"):
os.environ["OPENAI_API_KEY"] = getpass.getpass("Enter your OpenAI API key: ")
# Tavily is optional - for real web search
if not os.getenv("TAVILY_API_KEY"):
tavily_key = getpass.getpass("Enter your Tavily API key (or press Enter to skip): ")
if tavily_key:
os.environ["TAVILY_API_KEY"] = tavily_key
print("API keys configured!")
```
## 3. Initialize Clients
```python
import nest_asyncio
nest_asyncio.apply()
from openai import OpenAI
from hindsight_client import Hindsight
# Initialize Hindsight client (connects to local Docker instance)
hindsight = Hindsight(
base_url=os.getenv("HINDSIGHT_BASE_URL", "http://localhost:8888"),
)
openai_client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
# Optional: Tavily for real web search
try:
from tavily import TavilyClient
tavily = TavilyClient(api_key=os.getenv("TAVILY_API_KEY"))
HAS_TAVILY = True
print("Tavily configured - using real web search!")
except (ImportError, Exception) as e:
HAS_TAVILY = False
print("Note: Using simulated search results (Tavily not configured)")
USER_ID = "search-user-demo"
print("Clients initialized!")
```
## 4. Define Helper Functions
```python
def store_preference(preference: str) -> str:
"""Store a user preference."""
hindsight.retain(
bank_id=USER_ID,
content=f"User preference: {preference}",
metadata={"category": "preference"},
)
return f"Learned: {preference}"
def store_interaction(query: str, response: str) -> None:
"""Store a search interaction."""
hindsight.retain(
bank_id=USER_ID,
content=f"Search query: {query}\nResult highlights: {response[:200]}",
metadata={"category": "search_history"},
)
def get_user_context(query: str) -> str:
"""Retrieve relevant user context."""
memories = hindsight.recall(
bank_id=USER_ID,
query=f"preferences location dietary lifestyle {query}",
budget="mid",
)
if memories and memories.results:
return "\n".join(f"- {m.text}" for m in memories.results[:6])
return ""
def personalized_search(query: str) -> str:
"""Perform a personalized search."""
user_context = get_user_context(query)
enhancement_prompt = f"""Given this user's preferences and the search query, suggest how to enhance the search.
User preferences:
{user_context if user_context else "No preferences recorded yet."}
Search query: {query}
Return a JSON object with:
- "enhanced_query": The improved search query incorporating relevant preferences
- "filters": Any specific filters to apply (e.g., "vegetarian", "within 5 miles")
- "reasoning": Brief explanation of personalizations applied"""
enhancement = openai_client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": enhancement_prompt}],
temperature=0.3,
max_tokens=300,
)
enhanced_info = enhancement.choices[0].message.content
# Perform the search
if HAS_TAVILY:
search_results = tavily.search(
query=query,
search_depth="advanced",
max_results=5,
)
results_text = "\n".join(
f"- {r['title']}: {r['content'][:150]}..."
for r in search_results.get('results', [])
)
else:
results_text = f"[Simulated search results for: {query}]"
response_prompt = f"""Based on the search results and user preferences, provide a personalized summary.
User preferences:
{user_context if user_context else "No preferences recorded yet."}
Query: {query}
Search enhancement applied:
{enhanced_info}
Search results:
{results_text}
Provide a helpful, personalized response that takes into account their preferences."""
response = openai_client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": response_prompt}],
temperature=0.7,
max_tokens=500,
)
answer = response.choices[0].message.content
store_interaction(query, answer)
return answer
def get_preference_profile() -> str:
"""Get a summary of the user's preference profile."""
profile = hindsight.reflect(
bank_id=USER_ID,
query="""Summarize what we know about this user:
- Location and neighborhood
- Dietary preferences and restrictions
- Work style and schedule
- Hobbies and interests
- Family situation
- Shopping preferences""",
budget="high",
)
return profile.text if hasattr(profile, 'text') else str(profile)
print("Helper functions defined!")
```
## 5. Build User Profile
```python
print("Learning user preferences...")
preferences = [
"Lives in San Francisco, Mission District",
"Works remotely as a software engineer",
"Vegetarian, prefers organic food when possible",
"Has a 5-year-old daughter named Emma",
"Enjoys hiking and outdoor activities on weekends",
"Prefers quiet coffee shops for remote work",
"Lactose intolerant, uses oat milk",
"Interested in sustainable and eco-friendly products",
"Usually free on Tuesday and Thursday afternoons",
"Husband is allergic to nuts",
]
for pref in preferences:
result = store_preference(pref)
print(f" {result}")
```
## 6. Personalized Search Results
```python
import time
print("=" * 60)
print(" Personalized Search Results")
print("=" * 60)
searches = [
"Find a good coffee shop for working remotely",
"Restaurant recommendations for a family dinner",
"Birthday gift ideas for a 5-year-old",
]
for query in searches:
print(f"\nSearch: {query}")
print("-" * 40)
result = personalized_search(query)
print(result)
time.sleep(1)
```
## 7. View Preference Profile
```python
print("=" * 60)
print(" User Preference Profile")
print("=" * 60)
print(get_preference_profile())
```
## 8. Try Your Own Search
```python
your_search = "Best hiking trails near me" # Change this!
print(f"Search: {your_search}")
print("-" * 40)
print(personalized_search(your_search))
```
## 9. Cleanup
```python
hindsight.close()
print("Client connection closed.")
```
@@ -127,7 +127,7 @@ for r in results.results:
## Reflect: Generate Insights
The `reflect` operation performs reasoning over existing memories using the bank's disposition. It retrieves relevant facts and observations to generate contextual responses.
The `reflect` operation performs a more thorough analysis of existing memories. This allows the agent to form new connections between memories which are then persisted as opinions and/or observations.
Example use cases:
- An AI Project Manager reflecting on what risks need to be mitigated
@@ -142,11 +142,12 @@ print(response)
## Memory Types
Hindsight organizes knowledge into facts and consolidated observations:
Hindsight organizes memory into four networks to mimic human memory:
- **World**: Facts about the world ("The stove gets hot")
- **Experience**: Agent's own experiences ("I touched the stove and it really hurt")
- **Observation**: Consolidated knowledge synthesized from facts ("Always be careful around hot surfaces")
- **Experiences**: Agent's own experiences ("I touched the stove and it really hurt")
- **Opinion**: Beliefs with confidence scores ("I shouldn't touch the stove again" - .99 confidence)
- **Observation**: Complex mental models derived by reflecting on facts and experiences
## Cleanup
@@ -0,0 +1,335 @@
---
sidebar_position: 11
---
# Study Buddy with Hindsight Memory
:::tip Run this notebook
This recipe is available as an interactive Jupyter notebook.
[**Open in GitHub →**](https://github.com/vectorize-io/hindsight-cookbook/blob/main/notebooks/study_buddy.ipynb)
:::
A personalized study assistant that tracks what you've learned, identifies knowledge gaps, and helps with spaced repetition.
## Features
- Tracks study sessions and topics covered
- Monitors confidence levels per topic
- Identifies knowledge gaps
- Suggests topics for spaced repetition review
## Prerequisites
- OpenAI API key
- Hindsight running locally via Docker (see setup below)
## Start Hindsight Locally
Before running this notebook, start Hindsight in a terminal:
```bash
export OPENAI_API_KEY="your-openai-api-key"
docker run --rm -it --pull always -p 8888:8888 -p 9999:9999 \
-e HINDSIGHT_API_LLM_API_KEY=$OPENAI_API_KEY \
-e HINDSIGHT_API_LLM_MODEL=gpt-4o-mini \
-v $HOME/.hindsight-docker:/home/hindsight/.pg0 \
ghcr.io/vectorize-io/hindsight:latest
```
## 1. Install Dependencies
```python
!pip install -q hindsight-client openai nest-asyncio
```
## 2. Configure OpenAI API Key
Enter your OpenAI API key when prompted (used by both Hindsight and the demo).
```python
import getpass
import os
# Set OpenAI API key (used by both Hindsight and the demo)
if not os.getenv("OPENAI_API_KEY"):
os.environ["OPENAI_API_KEY"] = getpass.getpass("Enter your OpenAI API key: ")
print("API key configured!")
```
## 3. Initialize Clients
```python
import nest_asyncio
nest_asyncio.apply()
from datetime import datetime
from openai import OpenAI
from hindsight_client import Hindsight
# Initialize Hindsight client (connects to local Docker instance)
hindsight = Hindsight(
base_url=os.getenv("HINDSIGHT_BASE_URL", "http://localhost:8888"),
)
openai_client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
USER_ID = "student-demo"
print("Clients initialized!")
```
## 4. Define Helper Functions
```python
def record_study_session(topic: str, notes: str, confidence: str = "medium") -> str:
"""Record a study session with topic, notes, and self-assessed confidence."""
today = datetime.now().strftime("%B %d, %Y")
content = f"""{today} - STUDY SESSION
Topic: {topic}
Confidence Level: {confidence}
Notes: {notes}"""
hindsight.retain(
bank_id=USER_ID,
content=content,
metadata={
"category": "study_session",
"topic": topic,
"confidence": confidence,
"date": today,
},
)
return f"Recorded study session on '{topic}' (confidence: {confidence})"
def record_question(topic: str, question: str, understood: bool) -> str:
"""Record a question asked during study."""
today = datetime.now().strftime("%B %d, %Y")
content = f"""{today} - QUESTION
Topic: {topic}
Question: {question}
Understood: {"Yes" if understood else "No - needs review"}"""
hindsight.retain(
bank_id=USER_ID,
content=content,
metadata={
"category": "question",
"topic": topic,
"understood": str(understood),
},
)
return f"Recorded question on '{topic}'"
def study_buddy(user_query: str) -> str:
"""Interact with the study buddy."""
memories = hindsight.recall(
bank_id=USER_ID,
query=f"study session topic notes questions {user_query}",
budget="high",
)
memory_context = ""
if memories and memories.results:
memory_context = "\n".join(f"- {m.text}" for m in memories.results[:8])
system_prompt = f"""You are a helpful study buddy and tutor.
You have access to the student's study history, including:
- Topics they've studied and their notes
- Their self-assessed confidence levels
- Questions they've asked and whether they understood the answers
Study History:
{memory_context if memory_context else "No study history recorded yet."}
Your role:
1. Answer questions about topics they're studying
2. Identify knowledge gaps based on their history
3. Suggest topics to review (spaced repetition)
4. Provide encouragement and study tips
5. Connect new concepts to things they've already learned
Be supportive and pedagogical. Reference their previous learning when relevant."""
response = openai_client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_query},
],
temperature=0.7,
max_tokens=800,
)
answer = response.choices[0].message.content
hindsight.retain(
bank_id=USER_ID,
content=f"Student asked: {user_query}\nExplanation given: {answer[:300]}...",
metadata={"category": "tutoring"},
)
return answer
def get_review_suggestions() -> str:
"""Get suggestions for topics to review."""
suggestions = hindsight.reflect(
bank_id=USER_ID,
query="""Analyze this student's study history and suggest:
1. Topics with low confidence that need more review
2. Topics studied a while ago that should be revisited
3. Questions that weren't fully understood
4. Connections between topics they might have missed
Prioritize by what would most improve their understanding.""",
budget="high",
)
return suggestions.text if hasattr(suggestions, 'text') else str(suggestions)
def get_knowledge_summary(topic: str = None) -> str:
"""Get a summary of what the student knows."""
query = f"Summarize what this student knows about {topic}" if topic else \
"Summarize this student's overall knowledge and progress"
summary = hindsight.reflect(
bank_id=USER_ID,
query=query,
budget="high",
)
return summary.text if hasattr(summary, 'text') else str(summary)
print("Helper functions defined!")
```
## 5. Record Study Sessions
```python
print("Recording study sessions...")
sessions = [
{
"topic": "Classical Mechanics - Newton's Laws",
"notes": "Covered F=ma, action-reaction pairs, inertia. Solved problems on inclined planes.",
"confidence": "high",
},
{
"topic": "Classical Mechanics - Conservation of Momentum",
"notes": "Elastic vs inelastic collisions. Struggled with 2D collision problems.",
"confidence": "low",
},
{
"topic": "Classical Mechanics - Generalized Coordinates",
"notes": "Introduction to Lagrangian mechanics. Degrees of freedom concept.",
"confidence": "medium",
},
{
"topic": "Waves - Simple Harmonic Motion",
"notes": "SHM equations, period, frequency. Connected to springs and pendulums.",
"confidence": "high",
},
{
"topic": "Waves - Frequency Domain",
"notes": "Started Fourier transforms. Math is confusing, need more practice.",
"confidence": "low",
},
]
for session in sessions:
result = record_study_session(**session)
print(f" {result}")
```
## 6. Record Questions
```python
print("Recording questions...")
questions = [
("Conservation of Momentum", "Why is momentum conserved in collisions?", True),
("Conservation of Momentum", "How do I solve 2D collision problems?", False),
("Generalized Coordinates", "What's the advantage of Lagrangian over Newtonian?", True),
("Frequency Domain", "When do I use Fourier transforms vs Laplace?", False),
]
for topic, question, understood in questions:
result = record_question(topic, question, understood)
print(f" {result}")
```
## 7. Interactive Study Session
```python
import time
print("=" * 60)
print(" Study Session")
print("=" * 60)
queries = [
"Can you explain generalized coordinates again? I remember we covered it but I'm fuzzy on the details.",
"What topics should I review before my exam next week?",
"I'm still confused about 2D collision problems. Can you walk me through an example?",
]
for query in queries:
print(f"\nStudent: {query}")
print("-" * 40)
response = study_buddy(query)
print(f"Study Buddy: {response}")
time.sleep(1)
```
## 8. Get Review Suggestions
```python
print("=" * 60)
print(" Recommended Review Topics")
print("=" * 60)
print(get_review_suggestions())
```
## 9. Knowledge Summary
```python
print("=" * 60)
print(" Knowledge Summary")
print("=" * 60)
print(get_knowledge_summary())
```
## 10. Try Your Own Question
```python
your_question = "What are my biggest knowledge gaps right now?" # Change this!
print(f"You: {your_question}")
print("-" * 40)
print(f"Study Buddy: {study_buddy(your_question)}")
```
## 11. Cleanup
```python
hindsight.close()
print("Client connection closed.")
```
+60
View File
@@ -240,6 +240,36 @@ const sidebars: SidebarsConfig = {
type: 'doc',
id: 'cookbook/recipes/tool-learning-demo',
label: 'Routing Tool Learning',
},
{
type: 'doc',
id: 'cookbook/recipes/fitness_tracker',
label: 'Fitness Coach with Hindsight Memory',
},
{
type: 'doc',
id: 'cookbook/recipes/healthcare_assistant',
label: 'Healthcare Assistant with Hindsight Memory',
},
{
type: 'doc',
id: 'cookbook/recipes/movie_recommendation',
label: 'Movie Recommendation Assistant with Hindsight Memory',
},
{
type: 'doc',
id: 'cookbook/recipes/personal_assistant',
label: 'Personal AI Assistant with Hindsight Memory',
},
{
type: 'doc',
id: 'cookbook/recipes/personalized_search',
label: 'Personalized Search Agent with Hindsight Memory',
},
{
type: 'doc',
id: 'cookbook/recipes/study_buddy',
label: 'Study Buddy with Hindsight Memory',
}
],
},
@@ -248,10 +278,40 @@ const sidebars: SidebarsConfig = {
label: 'Applications',
collapsible: false,
items: [
{
type: 'doc',
id: 'cookbook/applications/chat-memory',
label: 'Chat Memory App',
},
{
type: 'doc',
id: 'cookbook/applications/deliveryman-demo',
label: 'Deliveryman Demo',
},
{
type: 'doc',
id: 'cookbook/applications/hindsight-litellm-demo',
label: 'Memory Approaches Comparison Demo',
},
{
type: 'doc',
id: 'cookbook/applications/hindsight-tool-learning-demo',
label: 'Tool Learning Demo',
},
{
type: 'doc',
id: 'cookbook/applications/openai-fitness-coach',
label: 'OpenAI Agent + Hindsight Memory Integration',
},
{
type: 'doc',
id: 'cookbook/applications/sanity-blog-memory',
label: 'Sanity CMS Blog Memory',
},
{
type: 'doc',
id: 'cookbook/applications/stancetracker',
label: 'Stance Tracker',
}
],
},
@@ -0,0 +1,120 @@
---
sidebar_position: 1
---
# Chat Memory App
:::info Complete Application
This is a complete, runnable application demonstrating Hindsight integration.
[**View source on GitHub →**](https://github.com/vectorize-io/hindsight-cookbook/tree/main/applications/chat-memory)
:::
A demo chat application that uses Groq's `qwen/qwen3-32b` model with Hindsight for persistent per-user memory.
## Features
- 🧠 **Persistent Memory**: Each user gets their own memory bank that remembers conversations
- 🚀 **Fast AI**: Powered by Groq's high-speed inference
- 🎯 **Per-User Context**: Isolated memory per user with automatic context retrieval
- 💬 **Real-time Chat**: Instant responses with memory-augmented context
## Setup
### 1. Start Hindsight API
First, start the Hindsight API server using Docker:
```bash
export GROQ_API_KEY=your_groq_api_key_here
# Start Hindsight with Groq as the LLM provider
docker run --rm -it --pull always -p 8888:8888 -p 9999:9999 \
-e HINDSIGHT_API_LLM_PROVIDER=groq \
-e HINDSIGHT_API_LLM_API_KEY=$GROQ_API_KEY \
-e HINDSIGHT_API_LLM_MODEL="openai/gpt-oss-20b" \
-v $HOME/.hindsight-docker:/home/hindsight/.pg0 \
ghcr.io/vectorize-io/hindsight:latest
```
- **API**: http://localhost:8888
- **Control Plane UI**: http://localhost:9999
### 2. Configure Environment
Copy your Groq API key to the environment file:
```bash
# Update .env.local with your Groq API key
echo "GROQ_API_KEY=your_groq_api_key_here" > .env.local
echo "HINDSIGHT_API_URL=http://localhost:8888" >> .env.local
```
If you don't have one, you can get a free Groq API key here: https://console.groq.com/home
### 3. Install Dependencies
```bash
npm install
```
### 4. Run the App
```bash
npm run dev
```
Open http://localhost:3000 in your browser.
## How It Works
1. **User Identity**: Each browser session gets a unique user ID
2. **Memory Bank Creation**: First message creates a personal memory bank in Hindsight
3. **Context Retrieval**: Before responding, relevant memories are retrieved
4. **Memory Augmented Response**: Groq generates responses with memory context
5. **Conversation Storage**: Each conversation is stored for future context
## Architecture
```
User Message
Next.js API Route (/api/chat)
Hindsight.recall() → Get relevant memories
Groq API → Generate response with memory context
Hindsight.retain() → Store conversation
Response to User
```
## Memory Bank Structure
Each user gets their own isolated memory bank with:
- **Name**: "Chat Memory for [userId]"
- **Background**: Conversational AI assistant context
- **Disposition**: Empathetic (4), Low Skepticism (2), Balanced Literalism (3)
## Try It Out
1. **First Conversation**: Tell the assistant about yourself
- "Hi! I'm a software engineer from San Francisco. I love Python and machine learning."
2. **Second Conversation**: Ask what it remembers
- "What do you know about me?"
- "What programming languages do I like?"
3. **Context Building**: Continue sharing preferences
- "I prefer VS Code over other editors"
- "I'm working on a React project"
4. **Memory Verification**: Visit the Hindsight Control Plane at http://localhost:9999 to see stored memories
## Development
- **Groq Model**: Uses `qwen/qwen3-32b` for fast, high-quality responses
- **Memory Storage**: Automatic conversation retention with context categorization
- **Memory Retrieval**: Semantic search with 2048 token budget for relevant context
@@ -0,0 +1,145 @@
---
sidebar_position: 2
---
# Deliveryman Demo
:::info Complete Application
This is a complete, runnable application demonstrating Hindsight integration.
[**View source on GitHub →**](https://github.com/vectorize-io/hindsight-cookbook/tree/main/applications/deliveryman-demo)
:::
A delivery agent simulation that demonstrates Hindsight's long-term memory capabilities. An AI agent navigates a multi-building office complex to deliver packages, learning employee locations and optimal paths over time through mental models.
## Prerequisites
- Python 3.11+
- Node.js 18+
- [uv](https://docs.astral.sh/uv/) (Python package manager)
## Setup (Fresh Environment)
### 1. Clone Repositories
```bash
# Clone Hindsight (memory engine)
git clone https://github.com/anthropics/hindsight.git
# Clone the cookbook (contains this demo)
git clone https://github.com/anthropics/hindsight-cookbook.git
```
### 2. Start Hindsight API
```bash
cd hindsight
cp .env.example .env
```
Edit `.env` with your LLM configuration:
```bash
HINDSIGHT_API_LLM_PROVIDER=groq
HINDSIGHT_API_LLM_API_KEY=<your-groq-api-key>
HINDSIGHT_API_LLM_MODEL=openai/gpt-oss-120b
HINDSIGHT_API_HOST=0.0.0.0
HINDSIGHT_API_PORT=8888
HINDSIGHT_API_ENABLE_OBSERVATIONS=true
# Retain extraction settings (improves employee/location extraction)
HINDSIGHT_API_RETAIN_EXTRACTION_MODE=custom
HINDSIGHT_API_RETAIN_CUSTOM_INSTRUCTIONS="Delivery agent. Remember employee locations, building layout, and optimal paths."
# Embedded database storage
PG0_DATA_DIR=/tmp/hindsight-data
```
Start the API:
```bash
./scripts/dev/start-api.sh
# Runs on http://localhost:8888
```
### 3. Start Hindsight Control Plane (Optional)
The control plane provides a web UI for inspecting memory banks, facts, and mental models.
```bash
cd hindsight
./scripts/dev/start-control-plane.sh
# Runs on a dynamic port (check terminal output)
```
### 4. Start Demo Backend
```bash
cd hindsight-cookbook/deliveryman-demo/backend
# Create virtual environment and install dependencies
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
```
Create `backend/.env`:
```bash
OPENAI_API_KEY=<your-openai-api-key>
GROQ_API_KEY=<your-groq-api-key>
HINDSIGHT_API_URL=http://localhost:8888
LLM_MODEL=openai/gpt-4o
```
Start the backend:
```bash
./run.sh
# Or manually:
python -m uvicorn app.main:app --host 0.0.0.0 --port 8000 --ws wsproto --reload
```
**Note:** The `--ws wsproto` flag is required for WebSocket support. Without it, connections will fail with error 1006.
### 5. Start Demo Frontend
```bash
cd hindsight-cookbook/deliveryman-demo/frontend
npm install
npm run dev
# Runs on http://localhost:5173
```
### 6. Open the Demo
Navigate to http://localhost:5173 in your browser.
## How It Works
1. The agent receives a delivery task (e.g., "Deliver Package #3954 to Victor Huang")
2. It navigates a multi-building complex with floors, elevators, and sky bridges
3. Along the way it encounters employees and learns their locations
4. After each delivery, the conversation is sent to Hindsight via the **retain** API
5. Hindsight extracts facts (employee locations, building layout) and builds **mental models**
6. On subsequent deliveries, the agent queries Hindsight to recall what it learned
## Architecture
```
Browser (5173) → Frontend (React + Phaser)
↓ WebSocket
Backend (8000) → FastAPI + Delivery Agent
↓ HTTP
Hindsight API (8888) → Memory Engine + PostgreSQL
```
## Troubleshooting
| Problem | Solution |
|---------|----------|
| WebSocket error 1006 | Restart backend with `--ws wsproto` flag |
| Mental models missing employees | Check `HINDSIGHT_API_RETAIN_EXTRACTION_MODE=custom` is set |
| Hindsight connection refused | Verify Hindsight API is running on port 8888 |
| Frontend shows "Disconnected" | Check backend is running on port 8000 |
@@ -0,0 +1,206 @@
---
sidebar_position: 3
---
# Memory Approaches Comparison Demo
:::info Complete Application
This is a complete, runnable application demonstrating Hindsight integration.
[**View source on GitHub →**](https://github.com/vectorize-io/hindsight-cookbook/tree/main/applications/hindsight-litellm-demo)
:::
Interactive Streamlit app comparing three memory approaches for LLM applications:
1. **No Memory** - Each query is independent (baseline)
2. **Full Conversation History** - Pass entire conversation (truncated to simulate context limits)
3. **Hindsight Memory** - Intelligent semantic memory retrieval
This demo showcases how Hindsight's semantic memory outperforms traditional approaches, especially as conversations grow longer.
## Quick Start
```bash
# 1. Set your OpenAI API key
export OPENAI_API_KEY=your-key
# 2. Start Hindsight server
docker run -d -p 8888:8888 -p 9999:9999 \
-e HINDSIGHT_API_LLM_PROVIDER=openai \
-e HINDSIGHT_API_LLM_API_KEY=$OPENAI_API_KEY \
ghcr.io/vectorize-io/hindsight:latest
# 3. Run the demo
./run.sh
```
Then open http://localhost:8501 in your browser.
## What This Demo Shows
### The Problem with Traditional Approaches
| Approach | How it Works | Limitation |
|----------|--------------|------------|
| **No Memory** | Each query standalone | Forgets everything between messages |
| **Full History** | Pass all messages to LLM | Token limits cause truncation - loses early context |
| **Hindsight** | Semantic retrieval of relevant facts | Retrieves what's relevant regardless of when it was said |
### Key Insight
After 5-10 messages, watch the **Full Conversation History** column start losing early context due to truncation (artificially set to 4 messages to demonstrate this quickly). Meanwhile, **Hindsight Memory** can still recall facts from the beginning because it uses semantic retrieval rather than sequential history.
## Testing the Demo
1. **Introduce yourself**:
- "Hi, I'm Sarah, a data scientist at Netflix"
- "I prefer Python and love machine learning"
2. **Have several exchanges** about different topics
3. **Test recall**:
- "What programming language should I use?"
- "What do you know about me?"
Watch how the three columns respond differently as the conversation grows.
## Features
- **Side-by-side comparison** of all three approaches
- **Debug panels** showing what context each approach uses
- **Memory explorer** to search Hindsight memories directly
- **Configurable settings** for history truncation, max memories, etc.
- **Multi-provider support** via LiteLLM (OpenAI, Anthropic, Groq)
## Prerequisites
- Python 3.10+
- Hindsight server running (Docker recommended)
- At least one LLM API key (OpenAI recommended)
## Setup
### Using run.sh (Recommended)
```bash
# Set API key
export OPENAI_API_KEY=your-key
# Start Hindsight, then run:
./run.sh
```
The script will check and install dependencies automatically.
### Manual Setup
```bash
# Install dependencies
pip install streamlit litellm
# Install Hindsight packages
pip install hindsight-client hindsight-litellm
# Run the app
streamlit run app.py
```
### Starting Hindsight Server
```bash
docker run -d -p 8888:8888 -p 9999:9999 \
-e HINDSIGHT_API_LLM_PROVIDER=openai \
-e HINDSIGHT_API_LLM_API_KEY=$OPENAI_API_KEY \
ghcr.io/vectorize-io/hindsight:latest
# Verify it's running
curl http://localhost:8888/health
```
## Configuration
### Sidebar Options
**Model Selection:**
- Provider: OpenAI, Anthropic, Groq
- Model: Various models per provider
- Custom model ID support
**Full History Config:**
- Max Messages to Keep (default: 4 to demonstrate truncation)
**Hindsight Config:**
- API URL (default: http://localhost:8888)
- Bank ID and Entity ID for memory isolation
- Max Memories to retrieve
- Recall Budget (low/mid/high)
**Generation Settings:**
- Temperature
- Max Tokens
- System Prompt
## Supported Models
### OpenAI
- gpt-4o, gpt-4o-mini, gpt-4-turbo, gpt-4, gpt-3.5-turbo
### Anthropic
- claude-3-5-sonnet-20241022, claude-3-5-haiku-20241022
- claude-3-opus-20240229, claude-3-sonnet-20240229
### Groq
- groq/llama-3.1-70b-versatile, groq/llama-3.1-8b-instant
- groq/mixtral-8x7b-32768
## Environment Variables
```bash
# Required
export OPENAI_API_KEY=sk-...
# Optional (for other providers)
export ANTHROPIC_API_KEY=sk-ant-...
export GROQ_API_KEY=gsk_...
# Optional
export HINDSIGHT_URL=http://localhost:8888
```
## Troubleshooting
### Hindsight server not responding
```bash
# Check if running
curl http://localhost:8888/health
# Start with Docker
docker run -d -p 8888:8888 -p 9999:9999 \
-e HINDSIGHT_API_LLM_PROVIDER=openai \
-e HINDSIGHT_API_LLM_API_KEY=$OPENAI_API_KEY \
ghcr.io/vectorize-io/hindsight:latest
```
### hindsight-litellm not installed
```bash
pip install hindsight-litellm
```
### API key errors
Make sure the appropriate API key is set:
```bash
export OPENAI_API_KEY=your-key
```
## Related
- [Hindsight](https://github.com/vectorize-io/hindsight) - Memory infrastructure for AI applications
- [hindsight-litellm](https://github.com/vectorize-io/hindsight/tree/main/hindsight-integrations/litellm) - LiteLLM integration package
## License
MIT
@@ -0,0 +1,123 @@
---
sidebar_position: 4
---
# Tool Learning Demo
:::info Complete Application
This is a complete, runnable application demonstrating Hindsight integration.
[**View source on GitHub →**](https://github.com/vectorize-io/hindsight-cookbook/tree/main/applications/hindsight-tool-learning-demo)
:::
An interactive Streamlit demo showing how Hindsight helps LLMs learn which tool to use when tool names are ambiguous.
## The Problem
When building AI agents with tool/function calling, tool names and descriptions aren't always clear. An LLM might randomly select between similarly-named tools, leading to incorrect behavior.
## The Scenario
This demo simulates a **customer service routing system** with two channels:
| Tool | Description (What the LLM sees) | Actual Purpose (Hidden) |
|------|--------------------------------|------------------------|
| `route_to_channel_alpha` | "Routes to channel Alpha for appropriate request types" | Financial issues (refunds, billing, payments) |
| `route_to_channel_omega` | "Routes to channel Omega for appropriate request types" | Technical issues (bugs, features, errors) |
The descriptions are **intentionally vague**! Without prior knowledge, the LLM must guess which channel handles what.
## The Solution: Learning with Hindsight
With Hindsight memory:
1. **Store routing feedback** about which channel handles which request type
2. **Retrieve learned knowledge** when making routing decisions
3. **Consistently route correctly** based on past experience
## Quick Start
### Prerequisites
1. **Hindsight Server** running (Docker):
```bash
docker run -d -p 8888:8888 -p 9999:9999 \
-e HINDSIGHT_API_LLM_PROVIDER=openai \
-e HINDSIGHT_API_LLM_API_KEY=$OPENAI_API_KEY \
-e HINDSIGHT_API_LLM_MODEL=gpt-4o-mini \
ghcr.io/vectorize-io/hindsight:latest
```
2. **OpenAI API Key**:
```bash
export OPENAI_API_KEY=your-key-here
```
### Run the Demo
```bash
./run.sh
```
Or manually:
```bash
pip install -r requirements.txt
streamlit run app.py
```
## How to Use the Demo
### Step 1: Test Without Memory (Baseline)
1. Select a **Financial Request** (e.g., "I need a refund...")
2. Click **Route Request**
3. Observe: The "Without Hindsight" column may route incorrectly
### Step 2: Route First Customer and Learn
1. Route a customer → Both LLMs route simultaneously
2. Feedback is automatically stored to Hindsight
3. Wait ~5 seconds for Hindsight to index the memory
### Step 3: Test With Memory
1. Select another request (financial or technical)
2. Click **Route Request**
3. Observe: The "With Hindsight" column should now route correctly!
### Step 4: View Statistics
- See accuracy comparison between "Without Memory" vs "With Hindsight"
- Review test history to see the improvement over time
## Demo Features
- **Side-by-side comparison**: See routing results with and without memory
- **Pre-defined test requests**: Financial and technical scenarios
- **Custom requests**: Enter your own customer requests
- **Memory Explorer**: Query stored routing knowledge directly
- **Live statistics**: Track accuracy improvement
## Key Insight
> Even when tool names and descriptions don't reveal their purpose, Hindsight allows the LLM to **learn from experience** which tool to use for which type of request.
This is especially valuable for:
- Enterprise systems with legacy tool names
- Multi-tenant systems where tools have generic names
- Agents that need to learn organization-specific workflows
## Configuration
| Setting | Default | Description |
|---------|---------|-------------|
| Model | gpt-4o-mini | LLM model for routing decisions |
| Temperature (No Memory) | 0.7 | Randomness for baseline tests |
| Hindsight API URL | http://localhost:8888 | Hindsight server URL |
## Files
- `app.py` - Main Streamlit application
- `requirements.txt` - Python dependencies
- `run.sh` - Launch script with dependency checking
- `README.md` - This file
@@ -1,5 +1,5 @@
---
sidebar_position: 1
sidebar_position: 5
---
# OpenAI Agent + Hindsight Memory Integration
@@ -7,7 +7,7 @@ sidebar_position: 1
:::info Complete Application
This is a complete, runnable application demonstrating Hindsight integration.
[**View source on GitHub →**](https://github.com/vectorize-io/hindsight-cookbook/tree/main/openai-fitness-coach)
[**View source on GitHub →**](https://github.com/vectorize-io/hindsight-cookbook/tree/main/applications/openai-fitness-coach)
:::
@@ -22,7 +22,7 @@ This example showcases:
- **Function calling** to bridge them together
- **Streaming responses** for real-time interaction (enabled by default)
- **Bidirectional memory** - both user data AND coach observations stored
- **System-level post-processing** - automatic knowledge consolidation
- **System-level post-processing** - automatic opinion storage for reliability
- **Temporal-semantic memory** queries via function tools
- **Enhanced preference learning** - coach learns and respects user likes/dislikes
- **Real-world integration pattern** for adding memory to AI agents
@@ -46,9 +46,9 @@ Hindsight API (returns workouts + preferences)
|
OpenAI Assistant (analyzes, gives advice)
|
Function Call: store_memory(advice as experience)
Function Call: store_memory(advice as opinion)
|
Hindsight API (stores coach's advice, consolidates into observations)
Hindsight API (stores coach's observation)
|
Personalized Answer
```
@@ -57,10 +57,10 @@ Personalized Answer
| Component | Standard Demo | OpenAI Integration |
|-----------|---------------|-------------------|
| **Conversation** | Hindsight `/reflect` endpoint | OpenAI Assistant API |
| **Conversation** | Hindsight `/think` endpoint | OpenAI Assistant API |
| **Memory** | Hindsight (built-in) | Hindsight (via function calling) |
| **LLM** | Configured in Hindsight | OpenAI GPT-4 |
| **Knowledge Consolidation** | Automatic after retain | Automatic after retain |
| **Opinion Formation** | Automatic in `/think` | Explicit via `store_memory(type="opinion")` |
| **Best For** | Hindsight-native apps | Integrating memory into existing OpenAI agents |
## Quick Start
@@ -126,7 +126,7 @@ retrieve_memories(query, fact_types, top_k)
search_workouts(after_date, before_date, workout_type)
get_nutrition_summary(after_date, before_date)
get_user_goals()
get_coach_insights(about) # Retrieves observations
get_coach_opinions(about)
```
Each function makes API calls to Hindsight to fetch relevant memories.
@@ -191,8 +191,8 @@ The agent will automatically:
The OpenAI Agent can retrieve different memory types from Hindsight:
- **World Facts** (`fact_type: "world"`): Workouts, meals, activities
- **Experience Facts** (`fact_type: "experience"`): Goals, intentions, coach advice
- **Observations** (`fact_type: "observation"`): Consolidated knowledge about user patterns
- **Agent Facts** (`fact_type: "agent"`): Goals, intentions
- **Opinions** (`fact_type: "opinion"`): Coach's observations about patterns
## Customization
@@ -266,9 +266,9 @@ The key benefit: **Separation of concerns**
**Use Hindsight directly when:**
- You want a complete memory-first solution
- You want automatic memory retrieval and observation consolidation
- You want automatic memory retrieval and opinion formation
- You want to use different LLM providers (not just OpenAI)
- You want the `/reflect` endpoint's integrated approach
- You want the `/think` endpoint's integrated approach
## Learning Points
@@ -0,0 +1,371 @@
---
sidebar_position: 6
---
# Sanity CMS Blog Memory
:::info Complete Application
This is a complete, runnable application demonstrating Hindsight integration.
[**View source on GitHub →**](https://github.com/vectorize-io/hindsight-cookbook/tree/main/applications/sanity-blog-memory)
:::
A Hindsight cookbook recipe demonstrating how to sync blog posts from **Sanity CMS** to Hindsight agent memory, enabling semantic search, temporal queries, and AI-powered content insights.
## Features
- **Blog Post Sync**: Automatically sync all blog posts from Sanity to Hindsight
- **Document-based Upsert**: Idempotent syncing with `document_id` - re-running sync updates existing content
- **Semantic Search**: Find related content using natural language queries
- **Temporal Queries**: Ask "What did I write in January 2025?"
- **Reflect for Insights**: Generate AI-powered analysis of your blog content
- **Related Content Discovery**: Power "Related Posts" features with semantic similarity
## Architecture
```
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ │ │ │ │ │
│ Sanity CMS │───────▶│ Sync Script │───────▶│ Hindsight │
│ (Content) │ GROQ │ (TypeScript) │ HTTP │ (Memory) │
│ │ │ │ │ │
└─────────────────┘ └─────────────────┘ └─────────────────┘
┌─────────────────┐
│ │
│ Your App │
│ - Recall │
│ - Reflect │
│ │
└─────────────────┘
```
## Quick Start
### 1. Start Hindsight
Choose your preferred LLM provider:
**Option A: Using Docker Compose (Recommended)**
```bash
# Set your API key
export OPENAI_API_KEY=sk-...
# OR
export GOOGLE_API_KEY=... # Gemini (free tier available)
# OR
export GROQ_API_KEY=... # Groq (free tier available)
# Start Hindsight
docker compose up -d
```
**Option B: Using Docker directly**
```bash
export OPENAI_API_KEY=sk-...
docker run --rm -it --pull always -p 8888:8888 -p 9999:9999 \
-e HINDSIGHT_API_LLM_API_KEY=$OPENAI_API_KEY \
-e HINDSIGHT_API_LLM_MODEL=gpt-4o-mini \
-v $HOME/.hindsight-docker:/home/hindsight/.pg0 \
ghcr.io/vectorize-io/hindsight:latest
```
- **API**: http://localhost:8888
- **Control Plane UI**: http://localhost:9999
### 2. Configure Environment
```bash
# Copy example config
cp .env.example .env
# Edit with your values
nano .env
```
Required settings:
```bash
# Hindsight
HINDSIGHT_API_URL=http://localhost:8888
HINDSIGHT_BANK_ID=blog-memory
# Sanity CMS
SANITY_PROJECT_ID=your-project-id
SANITY_DATASET=production
```
### 3. Install Dependencies
```bash
npm install
```
### 4. Sync Your Blog Posts
```bash
npm run sync
```
Expected output:
```
=======================================
Sanity -> Hindsight Blog Sync
=======================================
Setting up memory bank...
Memory bank "blog-memory" ready
Fetching posts from Sanity CMS...
Found 10 posts to sync
Syncing posts to Hindsight...
[1/10] "Why I Chose Qwik"... done
[2/10] "Building AI Agents"... done
...
=======================================
Sync Complete
=======================================
Synced: 10 posts
```
### 5. Query Your Content
```bash
npm run query
```
## Query Examples
### Semantic Search
Find related content using natural language:
```typescript
import { recallMemory } from './hindsight-client.js';
// Find posts about AI agents
const result = await recallMemory('AI agents and automation', {
budget: 'mid',
maxTokens: 2048,
});
console.log(`Found ${result.results.length} relevant posts`);
```
### Temporal Queries
Ask about content from specific time periods:
```typescript
// Posts from January 2025
const result = await recallMemory('What did I write about in January 2025?', {
queryTimestamp: '2025-01-31T23:59:59Z',
});
```
### Reflect for Insights
Generate AI-powered analysis of your content:
```typescript
import { reflectOnMemory } from './hindsight-client.js';
// Analyze blog themes
const insights = await reflectOnMemory(
'What are the main themes of my blog? What topics do I write about most?',
{ budget: 'high' }
);
console.log(insights.text);
```
### Related Content Discovery
Power your "Related Posts" feature:
```typescript
// Find posts similar to a specific article
const related = await recallMemory(
'Find posts related to "Why I Chose Qwik for My Personal Website"',
{ budget: 'mid' }
);
```
## Memory Structure
Each blog post is stored with rich metadata for optimal recall:
```
# Blog Post: {title}
**Published:** {date}
**URL:** {base_url}/blog/{slug}
**Tags:** {tags}
**Reading Time:** {reading_time}
## Description
{description}
## Content
{full_content}
```
Key features:
- **document_id**: `post:{slug}` - Enables upsert on re-sync
- **context**: `blog-post` - Categorizes the memory type
- **timestamp**: Post publication date - Enables temporal queries
## Use Cases
### 1. AI-Powered Blog Search
Replace keyword search with semantic understanding:
```typescript
// Old: keyword matching
const results = posts.filter(p => p.title.includes('React'));
// New: semantic understanding
const result = await recallMemory('frontend framework tutorials');
```
### 2. Content Recommendation Engine
Generate personalized recommendations:
```typescript
const recommendations = await reflectOnMemory(
'Based on a reader interested in "AI automation", recommend related posts'
);
```
### 3. Writing Assistant
Get topic suggestions based on your existing content:
```typescript
const suggestions = await reflectOnMemory(
'What topics should I write about next? What gaps exist in my content?'
);
```
### 4. Content Analytics
Analyze your blog's evolution:
```typescript
const analysis = await reflectOnMemory(
'How have my writing topics evolved over the past year?'
);
```
## Configuration
### Environment Variables
| Variable | Description | Default |
|----------|-------------|---------|
| `HINDSIGHT_API_URL` | Hindsight API endpoint | `http://localhost:8888` |
| `HINDSIGHT_BANK_ID` | Memory bank identifier | `blog-memory` |
| `SANITY_PROJECT_ID` | Your Sanity project ID | (required) |
| `SANITY_DATASET` | Sanity dataset name | `production` |
| `SANITY_API_TOKEN` | Sanity API token (for private datasets) | (none) |
| `SANITY_API_VERSION` | Sanity API version | `2024-01-09` |
| `SITE_URL` | Your blog's base URL | `https://example.com` |
### Memory Bank Disposition
The memory bank is configured with disposition traits optimized for blog content:
```typescript
{
skepticism: 2, // Trusting - blog content is authoritative
literalism: 4, // Literal - exact content matters
empathy: 3, // Balanced
}
```
## Extending for Other CMS Platforms
This pattern can be adapted for any CMS. The key components:
### 1. CMS Client
Replace `sanity-client.ts` with your CMS:
```typescript
// contentful-client.ts
import { createClient } from 'contentful';
export async function getAllPosts(): Promise<BlogPost[]> {
const client = createClient({...});
const entries = await client.getEntries({ content_type: 'blogPost' });
return entries.items.map(transformPost);
}
```
### 2. Content Transformation
Ensure your content is formatted for semantic search:
```typescript
function formatPostContent(post: BlogPost): string {
return `# ${post.title}
**Published:** ${post.date}
...
${post.content}`;
}
```
### 3. Document ID Strategy
Use a consistent document ID for upsert behavior:
```typescript
await retainBlogPost(content, {
documentId: `post:${post.slug}`, // Unique, stable identifier
timestamp: post.date,
});
```
## Troubleshooting
### "Connection refused" error
Make sure Hindsight is running:
```bash
docker compose up -d
curl http://localhost:8888/health
```
### "No posts found" during sync
Check your Sanity configuration:
```bash
# Verify project ID
echo $SANITY_PROJECT_ID
# Test GROQ query
npx sanity query '*[_type == "post"][0..2]{title}'
```
### Slow recall/reflect responses
This is normal for the first query as Hindsight builds embeddings. Subsequent queries are faster. Use `budget: 'low'` for faster responses at the cost of recall quality.
## Resources
- [Hindsight Documentation](https://hindsight.vectorize.io/)
- [Hindsight GitHub](https://github.com/vectorize-io/hindsight)
- [Sanity CMS Documentation](https://www.sanity.io/docs)
- [Hindsight Cookbook](https://github.com/vectorize-io/hindsight-cookbook)
## License
MIT
@@ -0,0 +1,276 @@
---
sidebar_position: 7
---
# Stance Tracker
:::info Complete Application
This is a complete, runnable application demonstrating Hindsight integration.
[**View source on GitHub →**](https://github.com/vectorize-io/hindsight-cookbook/tree/main/applications/stancetracker)
:::
An AI-powered application that tracks political candidates' stances on issues over time using Hindsight memory system and web scraping.
## Features
- **Geographic Targeting**: Track stances by country, state/province, and city
- **Multi-Candidate Tracking**: Monitor multiple candidates simultaneously
- **Temporal Analysis**: Historical stance tracking with configurable time ranges
- **Automated Scraping**: Periodic content collection with configurable frequencies (hourly/daily/weekly)
- **Stance Change Detection**: Automatic detection and highlighting of position changes
- **Interactive Timeline**: Visual graph showing stance evolution with reference callouts
- **Source Attribution**: All stances linked to verified sources with excerpts
## Architecture
### Memory System (Hindsight Integration)
This app uses the Hindsight memory system from `github.com/vectorize-io/hindsight`:
1. **Banks**: Each scraper agent has its own memory bank
2. **Retain**: Stores candidate statements and web scraping results
3. **Recall**: Semantic search to retrieve relevant memories
4. **Reflect**: Generates contextual analysis using stored memories
5. **Temporal Search**: Queries memories within specific time periods
### Tech Stack
- **Frontend**: Next.js 16, React, TypeScript, TailwindCSS
- **Visualization**: Recharts for timeline graphs
- **Backend**: Next.js API routes
- **Memory**: Hindsight (from github.com/vectorize-io/hindsight)
- **Database**: JSON file storage (no database required)
- **Web Search**: Tavily API
- **LLM**: OpenAI/Anthropic/Groq (configurable)
- **Scheduling**: node-cron
## Prerequisites
1. **Hindsight API** running (from github.com/vectorize-io/hindsight)
2. **API Keys**:
- Tavily API key (for web search)
- LLM provider API key (OpenAI, Anthropic, or Groq)
## Setup
### 1. Install Dependencies
```bash
npm install
```
### 2. Configure Environment
Copy `.env.example` to `.env` and fill in your credentials:
```bash
cp .env.example .env
```
Edit `.env`:
```env
# Hindsight API (from github.com/vectorize-io/hindsight)
HINDSIGHT_API_URL=http://localhost:8888
# Tavily API (for web search)
TAVILY_API_KEY=your_tavily_api_key_here
# LLM Provider
LLM_PROVIDER=openai # or anthropic, groq
LLM_API_KEY=your_llm_api_key_here
LLM_MODEL=gpt-4-turbo-preview
```
### 3. Start Hindsight
Clone and run Hindsight from github.com/vectorize-io/hindsight:
```bash
# Clone and run github.com/vectorize-io/hindsight
cd /path/to/hindsight
cargo run --bin hindsight-server
```
Verify Hindsight is running at `http://localhost:8888`
### 4. Run the Application
```bash
npm run dev
```
Visit `http://localhost:3000`
## Usage
### Creating a Tracking Session
1. **Set Location**: Enter country (required), state/province, and city (optional)
2. **Choose Topic**: Specify the issue to track (e.g., "Climate Change Policy")
3. **Add Candidates**: Enter names of candidates/politicians to track
4. **Configure Time Range**: Set historical start/end dates for initial analysis
5. **Set Frequency**: Choose how often to check for updates (hourly/daily/weekly)
6. **Start Tracking**: Click "Start Tracking" to begin
### Viewing Results
- **Timeline Graph**: Shows confidence levels of each candidate's stance over time
- **Stance Changes**: Red circles on the graph indicate detected position changes
- **Click Points**: Click any point to see detailed stance information and sources
- **Source Links**: Each stance includes links to original references
### Managing Sessions
- **Pause/Resume**: Temporarily stop or restart tracking
- **Run Now**: Trigger an immediate update outside the schedule
- **Status**: View current session status and frequency
## API Endpoints
### Sessions
- `POST /api/sessions` - Create new tracking session
- `GET /api/sessions?id={id}` - Get session details
- `GET /api/sessions` - List all sessions
- `PATCH /api/sessions` - Update session status
### Stances
- `POST /api/stances` - Process candidate stance
- `GET /api/stances?sessionId={id}&candidate={name}` - Get stances
### Scheduler
- `POST /api/scheduler` - Control session scheduling
- Actions: `start`, `stop`, `run`
## Hindsight Integration Examples
### 1. Storing Memories
```typescript
// Store web scraping results
await hindsightClient.retain(bankId, articleContent, {
context: 'web_search_result',
timestamp: articleDate,
metadata: { url: articleUrl }
});
```
### 2. Semantic Search
```typescript
// Search for relevant memories
const results = await hindsightClient.recall(bankId, query, {
budget: 'high',
maxTokens: 8192
});
```
### 3. Temporal Filtering
```typescript
// Query memories up to a specific point in time
const results = await hindsightClient.recall(bankId, query, {
queryTimestamp: '2024-12-01T00:00:00Z'
});
```
### 4. Contextual Analysis
```typescript
// Generate analysis using stored memories
const response = await hindsightClient.reflect(bankId,
'What is the candidate\'s stance on this issue?',
{ budget: 'high' }
);
```
## Production Deployment
### Vercel Deployment
```bash
# Install Vercel CLI
npm i -g vercel
# Deploy
vercel
# Set environment variables in Vercel dashboard:
# - HINDSIGHT_API_URL
# - TAVILY_API_KEY
# - LLM_PROVIDER
# - LLM_API_KEY
# - LLM_MODEL
```
**Note**: The `data/` directory for JSON storage will be ephemeral on Vercel. For production, consider using a persistent database or object storage.
## Development
### Project Structure
```
stancetracker/
├── app/
│ ├── api/ # API routes
│ ├── globals.css # Global styles
│ ├── layout.tsx # Root layout
│ └── page.tsx # Main page
├── components/ # React components
├── lib/
│ ├── db/ # JSON database utilities
│ ├── hindsight-client.ts # Hindsight API client
│ ├── llm-client.ts # LLM provider client
│ ├── web-scraper.ts # Tavily web scraper
│ ├── scraper-agent.ts # Content scraper
│ ├── rag-system.ts # Memory retrieval
│ ├── stance-extractor.ts # Stance analysis
│ ├── stance-pipeline.ts # Main pipeline
│ └── scheduler.ts # Job scheduling
└── types/ # TypeScript types
```
### Adding New LLM Providers
Edit `lib/llm-client.ts` and add a new method:
```typescript
private async newProviderComplete(messages, options) {
// Implementation
}
```
## Limitations
- **Web Search**: Uses Tavily API which has rate limits
- **Source Verification**: Manual verification recommended for critical applications
- **Stance Extraction**: LLM-based, subject to model limitations
- **Storage**: JSON file storage is not suitable for high-scale production use
- **Rate Limits**: Respect API rate limits for Tavily, Hindsight, and LLM providers
## Future Enhancements
- [ ] Real-time social media monitoring
- [ ] Speech/video transcription analysis
- [ ] Multi-language support
- [ ] Sentiment analysis integration
- [ ] Comparative analysis dashboard
- [ ] Export to CSV/PDF
- [ ] Email notifications for stance changes
- [ ] Public API for third-party integrations
## License
MIT
## Support
For issues or questions, please check:
- Hindsight documentation: `github.com/vectorize-io/hindsight/README.md`
- Tavily API docs: https://tavily.com/
- Project issues: Create an issue in the repository
@@ -15,13 +15,25 @@ Practical patterns, recipes, and complete applications for building with Hindsig
{ title: "Per-User Memory", href: "/cookbook/recipes/per-user-memory" },
{ title: "Support Agent with Shared Knowledge", href: "/cookbook/recipes/support-agent-shared-knowledge" },
{ title: "Memory with LiteLLM", href: "/cookbook/recipes/litellm-memory-demo" },
{ title: "Routing Tool Learning", href: "/cookbook/recipes/tool-learning-demo" }
{ title: "Routing Tool Learning", href: "/cookbook/recipes/tool-learning-demo" },
{ title: "Fitness Coach with Hindsight Memory", href: "/cookbook/recipes/fitness_tracker" },
{ title: "Healthcare Assistant with Hindsight Memory", href: "/cookbook/recipes/healthcare_assistant" },
{ title: "Movie Recommendation Assistant with Hindsight Memory", href: "/cookbook/recipes/movie_recommendation" },
{ title: "Personal AI Assistant with Hindsight Memory", href: "/cookbook/recipes/personal_assistant" },
{ title: "Personalized Search Agent with Hindsight Memory", href: "/cookbook/recipes/personalized_search" },
{ title: "Study Buddy with Hindsight Memory", href: "/cookbook/recipes/study_buddy" }
]}
/>
<RecipeCarousel
title="Applications"
items={[
{ title: "OpenAI Agent + Hindsight Memory Integration", href: "/cookbook/applications/openai-fitness-coach" }
{ title: "Chat Memory App", href: "/cookbook/applications/chat-memory" },
{ title: "Deliveryman Demo", href: "/cookbook/applications/deliveryman-demo" },
{ title: "Memory Approaches Comparison Demo", href: "/cookbook/applications/hindsight-litellm-demo" },
{ title: "Tool Learning Demo", href: "/cookbook/applications/hindsight-tool-learning-demo" },
{ title: "OpenAI Agent + Hindsight Memory Integration", href: "/cookbook/applications/openai-fitness-coach" },
{ title: "Sanity CMS Blog Memory", href: "/cookbook/applications/sanity-blog-memory" },
{ title: "Stance Tracker", href: "/cookbook/applications/stancetracker" }
]}
/>
@@ -0,0 +1,306 @@
---
sidebar_position: 6
---
# Fitness Coach with Hindsight Memory
:::tip Run this notebook
This recipe is available as an interactive Jupyter notebook.
[**Open in GitHub →**](https://github.com/vectorize-io/hindsight-cookbook/blob/main/notebooks/fitness_tracker.ipynb)
:::
A personalized fitness assistant that tracks your workouts, diet, recovery, and progress over time to give contextual advice.
## Features
- Logs workout sessions with exercises and weights
- Tracks meals and dietary preferences
- Monitors recovery and sleep patterns
- Provides personalized training advice
## Prerequisites
- OpenAI API key
- Hindsight running locally via Docker (see setup below)
## Start Hindsight Locally
Before running this notebook, start Hindsight in a terminal:
```bash
export OPENAI_API_KEY="your-openai-api-key"
docker run --rm -it --pull always -p 8888:8888 -p 9999:9999 \
-e HINDSIGHT_API_LLM_API_KEY=$OPENAI_API_KEY \
-e HINDSIGHT_API_LLM_MODEL=gpt-4o-mini \
-v $HOME/.hindsight-docker:/home/hindsight/.pg0 \
ghcr.io/vectorize-io/hindsight:latest
```
## 1. Install Dependencies
```python
!pip install -q hindsight-client openai nest-asyncio
```
## 2. Configure OpenAI API Key
Enter your OpenAI API key when prompted (used by both Hindsight and the demo).
```python
import getpass
import os
# Set OpenAI API key (used by both Hindsight and the demo)
if not os.getenv("OPENAI_API_KEY"):
os.environ["OPENAI_API_KEY"] = getpass.getpass("Enter your OpenAI API key: ")
print("API key configured!")
```
## 3. Initialize Clients
```python
import nest_asyncio
nest_asyncio.apply()
from datetime import datetime
from openai import OpenAI
from hindsight_client import Hindsight
# Initialize Hindsight client (connects to local Docker instance)
hindsight = Hindsight(
base_url=os.getenv("HINDSIGHT_BASE_URL", "http://localhost:8888"),
)
openai_client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
USER_ID = "fitness-user-demo"
print("Clients initialized!")
```
## 4. Define Helper Functions
```python
def log_workout(workout_details: str) -> str:
"""Log a workout session with timestamp."""
today = datetime.now().strftime("%B %d, %Y")
hindsight.retain(
bank_id=USER_ID,
content=f"{today} - WORKOUT LOG: {workout_details}",
metadata={"category": "workout", "date": today},
)
return f"Logged workout for {today}: {workout_details}"
def log_meal(meal_details: str) -> str:
"""Log a meal with timestamp."""
today = datetime.now().strftime("%B %d, %Y")
hindsight.retain(
bank_id=USER_ID,
content=f"{today} - MEAL LOG: {meal_details}",
metadata={"category": "nutrition", "date": today},
)
return f"Logged meal for {today}: {meal_details}"
def log_recovery(recovery_details: str) -> str:
"""Log recovery information (sleep, soreness, etc.)."""
today = datetime.now().strftime("%B %d, %Y")
hindsight.retain(
bank_id=USER_ID,
content=f"{today} - RECOVERY LOG: {recovery_details}",
metadata={"category": "recovery", "date": today},
)
return f"Logged recovery for {today}: {recovery_details}"
def store_user_profile(profile_info: str) -> str:
"""Store user profile information."""
hindsight.retain(
bank_id=USER_ID,
content=f"USER PROFILE: {profile_info}",
metadata={"category": "profile"},
)
return f"Stored profile info: {profile_info}"
def fitness_coach(user_query: str) -> str:
"""Get personalized fitness advice based on query and user history."""
memories = hindsight.recall(
bank_id=USER_ID,
query=f"fitness workout diet recovery goals {user_query}",
budget="high",
)
memory_context = ""
if memories and memories.results:
memory_context = "\n".join(f"- {m.text}" for m in memories.results[:10])
system_prompt = f"""You are a knowledgeable and supportive fitness coach.
You have access to the user's workout history, diet logs, recovery notes, and personal profile.
What you know about this user:
{memory_context if memory_context else "No history recorded yet."}
Provide personalized, actionable advice based on their:
- Training history and progress
- Dietary preferences and restrictions
- Recovery patterns
- Personal goals
Be encouraging but realistic. Reference their specific history when relevant."""
response = openai_client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_query},
],
temperature=0.7,
max_tokens=600,
)
advice = response.choices[0].message.content
hindsight.retain(
bank_id=USER_ID,
content=f"User asked: {user_query}\nCoach advised: {advice[:200]}...",
metadata={"category": "coaching"},
)
return advice
def get_progress_report() -> str:
"""Generate a progress report based on workout history."""
report = hindsight.reflect(
bank_id=USER_ID,
query="""Analyze this user's fitness journey:
1. How consistent have they been with workouts?
2. What progress have they made (weight lifted, exercises)?
3. How is their recovery and sleep?
4. What dietary patterns do you notice?
5. What should they focus on next?""",
budget="high",
)
return report.text if hasattr(report, 'text') else str(report)
print("Helper functions defined!")
```
## 5. Set Up User Profile
```python
print("Setting up user profile...")
profile_data = [
"Name: Anish, Age: 26, Height: 5'10\", Weight: 72kg",
"Goal: Building lean muscle, started gym 6 months ago",
"Routine: Push-pull-legs split, 5x per week",
"Rest days: Wednesday and Sunday",
"Dietary restriction: Mild lactose intolerance, uses almond milk",
"Health note: Occasional knee pain, avoids deep squats",
"Supplements: Whey protein (lactose-free), magnesium",
"Sleep: Aims for 7+ hours, performance drops under 6 hours",
]
for info in profile_data:
store_user_profile(info)
print(f" Stored: {info[:50]}...")
```
## 6. Log Workout History
```python
print("Logging workout history...")
workouts = [
"Push day: Bench press 3x8 @ 60kg, overhead press 4x12, tricep dips 3x10. Felt strong.",
"Pull day: Deadlift 3x5 @ 80kg, barbell rows 4x10, bicep curls 3x12. Good session.",
"Leg day: Leg press 4x12, hamstring curls 3x12, glute bridges 3x15. Knee felt okay.",
]
for workout in workouts:
print(f" {log_workout(workout)[:60]}...")
print("\nLogging recent meals...")
meals = [
"Post-workout: Whey shake with almond milk, banana, oats",
"Dinner: Grilled chicken, brown rice, steamed vegetables",
"Snack: Greek yogurt (lactose-free) with berries",
]
for meal in meals:
print(f" {log_meal(meal)[:60]}...")
print("\nLogging recovery notes...")
recovery = [
"Slept 7.5 hours, feeling well rested",
"Some DOMS in legs from yesterday, using turmeric milk",
]
for note in recovery:
print(f" {log_recovery(note)[:60]}...")
```
## 7. Talk to Your Fitness Coach
```python
import time
print("=" * 60)
print(" Talking to your fitness coach...")
print("=" * 60)
queries = [
"How much was I lifting for bench press recently?",
"I slept poorly last night (only 5 hours). What should I do for today's workout?",
"Suggest a post-workout meal that works with my dietary restrictions.",
"My knee has been bothering me more. Any exercise modifications?",
]
for query in queries:
print(f"\nUser: {query}")
print("-" * 40)
response = fitness_coach(query)
print(f"Coach: {response}")
time.sleep(1)
```
## 8. Generate Progress Report
```python
print("=" * 60)
print(" Progress Report")
print("=" * 60)
print(get_progress_report())
```
## 9. Try Your Own Query
```python
your_query = "What exercises should I do today?" # Change this!
print(f"You: {your_query}")
print("-" * 40)
print(f"Coach: {fitness_coach(your_query)}")
```
## 10. Cleanup
```python
hindsight.close()
print("Client connection closed.")
```
@@ -0,0 +1,299 @@
---
sidebar_position: 7
---
# Healthcare Assistant with Hindsight Memory
:::tip Run this notebook
This recipe is available as an interactive Jupyter notebook.
[**Open in GitHub →**](https://github.com/vectorize-io/hindsight-cookbook/blob/main/notebooks/healthcare_assistant.ipynb)
:::
A supportive healthcare chatbot that remembers patient history, symptoms, medications, and preferences to provide personalized guidance.
## Disclaimer
**This is a demo application and should NOT be used for actual medical advice. Always consult qualified healthcare professionals.**
## Features
- Tracks symptoms, medications, and allergies
- Maintains patient history across conversations
- Provides health information and wellness tips
- Schedules appointments
## Prerequisites
- OpenAI API key
- Hindsight running locally via Docker (see setup below)
## Start Hindsight Locally
Before running this notebook, start Hindsight in a terminal:
```bash
export OPENAI_API_KEY="your-openai-api-key"
docker run --rm -it --pull always -p 8888:8888 -p 9999:9999 \
-e HINDSIGHT_API_LLM_API_KEY=$OPENAI_API_KEY \
-e HINDSIGHT_API_LLM_MODEL=gpt-4o-mini \
-v $HOME/.hindsight-docker:/home/hindsight/.pg0 \
ghcr.io/vectorize-io/hindsight:latest
```
## 1. Install Dependencies
```python
!pip install -q hindsight-client openai nest-asyncio
```
## 2. Configure OpenAI API Key
Enter your OpenAI API key when prompted (used by both Hindsight and the demo).
```python
import getpass
import os
# Set OpenAI API key (used by both Hindsight and the demo)
if not os.getenv("OPENAI_API_KEY"):
os.environ["OPENAI_API_KEY"] = getpass.getpass("Enter your OpenAI API key: ")
print("API key configured!")
```
## 3. Initialize Clients
```python
import nest_asyncio
nest_asyncio.apply()
from datetime import datetime
import random
from openai import OpenAI
from hindsight_client import Hindsight
# Initialize Hindsight client (connects to local Docker instance)
hindsight = Hindsight(
base_url=os.getenv("HINDSIGHT_BASE_URL", "http://localhost:8888"),
)
openai_client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
PATIENT_ID = "patient-demo"
def get_patient_bank_id(patient_id: str) -> str:
return f"patient-{patient_id}"
print("Clients initialized!")
```
## 4. Define Helper Functions
```python
def store_patient_info(patient_id: str, info: str, category: str = "general") -> str:
"""Store patient information."""
bank_id = get_patient_bank_id(patient_id)
today = datetime.now().strftime("%B %d, %Y")
hindsight.retain(
bank_id=bank_id,
content=f"{today} - {category.upper()}: {info}",
metadata={"category": category, "date": today},
)
return f"Recorded {category}: {info}"
def get_patient_history(patient_id: str, query: str) -> str:
"""Retrieve relevant patient history."""
bank_id = get_patient_bank_id(patient_id)
memories = hindsight.recall(
bank_id=bank_id,
query=query,
budget="high",
)
if memories and memories.results:
return "\n".join(f"- {m.text}" for m in memories.results[:10])
return "No relevant history found."
def healthcare_chat(patient_id: str, user_message: str) -> str:
"""Chat with the healthcare assistant."""
bank_id = get_patient_bank_id(patient_id)
history = get_patient_history(
patient_id,
f"symptoms medications allergies conditions {user_message}"
)
system_prompt = f"""You are a supportive healthcare assistant chatbot.
IMPORTANT DISCLAIMERS:
- You are NOT a doctor and cannot provide medical diagnoses
- Always recommend consulting healthcare professionals for serious concerns
- Never prescribe medications or suggest stopping prescribed treatments
Your role:
- Listen empathetically to patient concerns
- Remember and reference their medical history
- Provide general health information and wellness tips
- Help track symptoms over time
- Remind about medications and appointments
- Suggest when to seek professional care
Patient History:
{history}
Guidelines:
- Be warm and supportive
- Ask clarifying questions when needed
- Reference their history when relevant
- Flag any concerning symptoms for professional review"""
response = openai_client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_message},
],
temperature=0.7,
max_tokens=600,
)
answer = response.choices[0].message.content
hindsight.retain(
bank_id=bank_id,
content=f"Patient concern: {user_message}\nGuidance provided: {answer[:200]}...",
metadata={"category": "consultation"},
)
return answer
def get_health_summary(patient_id: str) -> str:
"""Generate a health summary for the patient."""
bank_id = get_patient_bank_id(patient_id)
summary = hindsight.reflect(
bank_id=bank_id,
query="""Summarize this patient's health profile:
1. Known conditions and diagnoses
2. Current medications
3. Allergies and sensitivities
4. Recent symptoms reported
5. Lifestyle factors mentioned
6. Any patterns or trends in their health""",
budget="high",
)
return summary.text if hasattr(summary, 'text') else str(summary)
def schedule_appointment(patient_id: str, appointment_type: str, preferred_time: str) -> str:
"""Schedule an appointment (demo)."""
confirmation_id = f"APT-{random.randint(10000, 99999)}"
store_patient_info(
patient_id,
f"Appointment scheduled: {appointment_type} - Preferred time: {preferred_time} - Confirmation: {confirmation_id}",
category="appointment"
)
return f"Appointment requested: {appointment_type}\nPreferred time: {preferred_time}\nConfirmation ID: {confirmation_id}\n\nA staff member will confirm the exact time within 24 hours."
print("Helper functions defined!")
```
## 5. Set Up Patient Profile
```python
print("Setting up patient profile...")
patient_info = [
("Age: 45, Male, Height: 5'11\", Weight: 185 lbs", "demographics"),
("Allergy: Penicillin - causes hives", "allergies"),
("Allergy: Shellfish - causes throat swelling", "allergies"),
("Current medication: Lisinopril 10mg daily for blood pressure", "medications"),
("Current medication: Metformin 500mg twice daily for Type 2 diabetes", "medications"),
("Condition: Diagnosed with Type 2 diabetes in 2020", "conditions"),
("Condition: Mild hypertension, well-controlled", "conditions"),
("Family history: Father had heart disease", "family_history"),
("Lifestyle: Sedentary job, trying to exercise more", "lifestyle"),
]
for info, category in patient_info:
result = store_patient_info(PATIENT_ID, info, category)
print(f" {result}")
```
## 6. Healthcare Chat
```python
import time
print("=" * 60)
print(" Healthcare Chat")
print("=" * 60)
conversations = [
"Hi, I've been having headaches for the past few days. Should I be worried?",
"The headaches are mostly in the afternoon. I've also been feeling more tired than usual.",
"I've been checking my blood sugar and it's been a bit higher lately, around 140-150 fasting.",
"Can you remind me what allergies I have? I'm going to a new restaurant.",
]
for message in conversations:
print(f"\nPatient: {message}")
print("-" * 40)
response = healthcare_chat(PATIENT_ID, message)
print(f"Assistant: {response}")
time.sleep(1)
```
## 7. Schedule Appointment
```python
print("=" * 60)
print(" Scheduling Appointment")
print("=" * 60)
print(schedule_appointment(PATIENT_ID, "General checkup", "Next Tuesday afternoon"))
```
## 8. Health Summary
```python
print("=" * 60)
print(" Patient Health Summary")
print("=" * 60)
print(get_health_summary(PATIENT_ID))
```
## 9. Try Your Own Question
```python
your_question = "Should I adjust my Metformin dose?" # Change this!
print(f"You: {your_question}")
print("-" * 40)
print(f"Assistant: {healthcare_chat(PATIENT_ID, your_question)}")
```
## 10. Cleanup
```python
hindsight.close()
print("Client connection closed.")
```
@@ -0,0 +1,246 @@
---
sidebar_position: 8
---
# Movie Recommendation Assistant with Hindsight Memory
:::tip Run this notebook
This recipe is available as an interactive Jupyter notebook.
[**Open in GitHub →**](https://github.com/vectorize-io/hindsight-cookbook/blob/main/notebooks/movie_recommendation.ipynb)
:::
A personalized movie recommender that remembers your preferences, watch history, and tastes to give better suggestions over time.
## Features
- Remembers favorite genres, directors, and actors
- Tracks movies you've watched and enjoyed
- Provides contextual recommendations based on mood
## Prerequisites
- OpenAI API key
- Hindsight running locally via Docker (see setup below)
## Start Hindsight Locally
Before running this notebook, start Hindsight in a terminal:
```bash
export OPENAI_API_KEY="your-openai-api-key"
docker run --rm -it --pull always -p 8888:8888 -p 9999:9999 \
-e HINDSIGHT_API_LLM_API_KEY=$OPENAI_API_KEY \
-e HINDSIGHT_API_LLM_MODEL=gpt-4o-mini \
-v $HOME/.hindsight-docker:/home/hindsight/.pg0 \
ghcr.io/vectorize-io/hindsight:latest
```
## 1. Install Dependencies
```python
!pip install -q hindsight-client openai nest-asyncio
```
## 2. Configure OpenAI API Key
Enter your OpenAI API key when prompted (used by both Hindsight and the demo).
```python
import getpass
import os
# Set OpenAI API key (used by both Hindsight and the demo)
if not os.getenv("OPENAI_API_KEY"):
os.environ["OPENAI_API_KEY"] = getpass.getpass("Enter your OpenAI API key: ")
print("API key configured!")
```
## 3. Initialize Clients
```python
import nest_asyncio
nest_asyncio.apply()
from openai import OpenAI
from hindsight_client import Hindsight
# Initialize Hindsight client (connects to local Docker instance)
hindsight = Hindsight(
base_url=os.getenv("HINDSIGHT_BASE_URL", "http://localhost:8888"),
)
# Initialize OpenAI client
openai_client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
# Unique identifier for this user's memory bank
USER_ID = "movie-fan-demo"
print("Clients initialized!")
```
## 4. Define Helper Functions
These functions demonstrate the three core Hindsight operations:
- **retain()**: Store memories
- **recall()**: Retrieve relevant memories
- **reflect()**: Synthesize insights from memories
```python
def get_recommendation(user_query: str) -> str:
"""
Get a movie recommendation based on user query and remembered preferences.
"""
# Recall relevant memories about this user's movie preferences
memories = hindsight.recall(
bank_id=USER_ID,
query=f"movie preferences tastes genres {user_query}",
budget="mid",
)
# Build context from memories
memory_context = ""
if memories and memories.results:
memory_context = "\n".join(
f"- {m.text}" for m in memories.results[:5]
)
# Generate recommendation with context
system_prompt = f"""You are a helpful movie recommendation assistant.
You remember the user's preferences and past conversations to give personalized suggestions.
What you know about this user:
{memory_context if memory_context else "No previous preferences recorded yet."}
Give thoughtful, personalized recommendations based on their tastes.
If they mention new preferences, acknowledge them."""
response = openai_client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_query},
],
temperature=0.7,
max_tokens=500,
)
recommendation = response.choices[0].message.content
# Store this interaction for future context
hindsight.retain(
bank_id=USER_ID,
content=f"User asked: {user_query}\nRecommendation given: {recommendation}",
metadata={"category": "movie_recommendation"},
)
return recommendation
def store_preference(preference: str) -> None:
"""Store an explicit user preference."""
hindsight.retain(
bank_id=USER_ID,
content=f"User preference: {preference}",
metadata={"category": "preference"},
)
print(f"Stored preference: {preference}")
def get_preference_summary() -> str:
"""Get a summary of what we know about the user's movie tastes."""
summary = hindsight.reflect(
bank_id=USER_ID,
query="Summarize this user's movie preferences, favorite genres, actors they like, and movies they've mentioned enjoying or disliking.",
budget="high",
)
return summary.text if hasattr(summary, 'text') else str(summary)
print("Helper functions defined!")
```
## 5. Run the Demo
Watch how the assistant learns and remembers preferences across conversations.
```python
import time
print("=" * 60)
print(" Movie Recommendation Assistant with Memory")
print("=" * 60)
print()
# Simulate a conversation over time
conversations = [
"I'm looking for a movie to watch tonight. Any suggestions?",
"I really loved Inception and Interstellar. Christopher Nolan is amazing!",
"Can you suggest something similar to those? I like mind-bending plots.",
"Actually, I'm not in the mood for something heavy. Something lighter?",
"I watched The Grand Budapest Hotel last week and loved it!",
"What should I watch tonight? Remember what I like!",
]
for i, query in enumerate(conversations, 1):
print(f"\n[Conversation {i}]")
print(f"User: {query}")
print("-" * 40)
response = get_recommendation(query)
print(f"Assistant: {response}")
print()
time.sleep(1)
```
## 6. View Learned Preferences
Use `reflect()` to synthesize what Hindsight has learned about your movie tastes.
```python
print("=" * 60)
print(" What I've learned about your movie tastes:")
print("=" * 60)
print(get_preference_summary())
```
## 7. Try Your Own Queries
Experiment with your own movie preferences!
```python
# Try your own query!
your_query = "I'm in the mood for a sci-fi thriller" # Change this!
print(f"You: {your_query}")
print("-" * 40)
print(f"Assistant: {get_recommendation(your_query)}")
```
## 8. Cleanup
Close the Hindsight client connection.
```python
hindsight.close()
print("Client connection closed.")
```
```python
```
```python
```
@@ -0,0 +1,266 @@
---
sidebar_position: 9
---
# Personal AI Assistant with Hindsight Memory
:::tip Run this notebook
This recipe is available as an interactive Jupyter notebook.
[**Open in GitHub →**](https://github.com/vectorize-io/hindsight-cookbook/blob/main/notebooks/personal_assistant.ipynb)
:::
A general-purpose personal assistant that remembers your preferences, schedule, family, work context, and past conversations.
## Features
- Remembers family, work, and personal details
- Tracks preferences and habits
- Helps with scheduling and reminders
- Maintains context across conversations
## Prerequisites
- OpenAI API key
- Hindsight running locally via Docker (see setup below)
## Start Hindsight Locally
Before running this notebook, start Hindsight in a terminal:
```bash
export OPENAI_API_KEY="your-openai-api-key"
docker run --rm -it --pull always -p 8888:8888 -p 9999:9999 \
-e HINDSIGHT_API_LLM_API_KEY=$OPENAI_API_KEY \
-e HINDSIGHT_API_LLM_MODEL=gpt-4o-mini \
-v $HOME/.hindsight-docker:/home/hindsight/.pg0 \
ghcr.io/vectorize-io/hindsight:latest
```
## 1. Install Dependencies
```python
!pip install -q hindsight-client openai nest-asyncio
```
## 2. Configure OpenAI API Key
Enter your OpenAI API key when prompted (used by both Hindsight and the demo).
```python
import getpass
import os
# Set OpenAI API key (used by both Hindsight and the demo)
if not os.getenv("OPENAI_API_KEY"):
os.environ["OPENAI_API_KEY"] = getpass.getpass("Enter your OpenAI API key: ")
print("API key configured!")
```
## 3. Initialize Clients
```python
import nest_asyncio
nest_asyncio.apply()
from datetime import datetime
from openai import OpenAI
from hindsight_client import Hindsight
# Initialize Hindsight client (connects to local Docker instance)
hindsight = Hindsight(
base_url=os.getenv("HINDSIGHT_BASE_URL", "http://localhost:8888"),
)
openai_client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
USER_ID = "assistant-user-demo"
print("Clients initialized!")
```
## 4. Define Helper Functions
```python
def remember(info: str, category: str = "general") -> str:
"""Store information to remember."""
today = datetime.now().strftime("%B %d, %Y")
hindsight.retain(
bank_id=USER_ID,
content=f"{today}: {info}",
metadata={"category": category, "date": today},
)
return f"I'll remember: {info}"
def recall_context(query: str) -> str:
"""Recall relevant memories for context."""
memories = hindsight.recall(
bank_id=USER_ID,
query=query,
budget="high",
)
if memories and memories.results:
return "\n".join(f"- {m.text}" for m in memories.results[:8])
return ""
def chat(user_message: str) -> str:
"""Chat with the personal assistant."""
context = recall_context(user_message)
system_prompt = f"""You are a helpful personal AI assistant with long-term memory.
You remember the user's preferences, schedule, family, work context, and past conversations.
What you remember about this user:
{context if context else "No memories recorded yet."}
Your capabilities:
- Remember things when asked ("Remember that...", "Don't forget...")
- Recall past information ("What did I tell you about...", "When is...")
- Provide personalized suggestions based on known preferences
- Help with scheduling and reminders
- Have natural conversations while maintaining context
Be helpful, proactive, and reference relevant memories naturally."""
response = openai_client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_message},
],
temperature=0.7,
max_tokens=500,
)
answer = response.choices[0].message.content
# Check if user is asking to remember something
lower_msg = user_message.lower()
if any(phrase in lower_msg for phrase in ["remember that", "don't forget", "remind me", "note that"]):
hindsight.retain(
bank_id=USER_ID,
content=f"User asked to remember: {user_message}",
metadata={"category": "reminder"},
)
# Store the interaction
hindsight.retain(
bank_id=USER_ID,
content=f"Conversation - User: {user_message[:100]} | Assistant: {answer[:100]}",
metadata={"category": "conversation"},
)
return answer
def get_summary(topic: str = None) -> str:
"""Get a summary of memories."""
query = f"Summarize what you know about {topic}" if topic else \
"Summarize everything you know about this user"
summary = hindsight.reflect(
bank_id=USER_ID,
query=query,
budget="high",
)
return summary.text if hasattr(summary, 'text') else str(summary)
print("Helper functions defined!")
```
## 5. Build Context
```python
print("Building context...")
initial_context = [
("My name is Alex and I work as a product manager at TechCorp", "personal"),
("My wife's name is Sarah and we have two kids: Emma (7) and Jack (4)", "family"),
("I prefer morning meetings and try to keep afternoons for deep work", "preference"),
("My mom's birthday is March 15th", "event"),
("I'm trying to read more - currently reading 'Atomic Habits'", "hobby"),
("I have a weekly team standup every Monday at 10am", "schedule"),
("I'm allergic to cats", "health"),
("My favorite coffee is a flat white with oat milk", "preference"),
("I'm training for a half marathon in April", "goal"),
]
for info, category in initial_context:
result = remember(info, category)
print(f" {result}")
```
## 6. Have a Conversation
```python
import time
print("=" * 60)
print(" Conversation")
print("=" * 60)
conversations = [
"Hey, what's my wife's name again?",
"Remember that my Q1 review is next Thursday at 2pm",
"I need a gift idea for my mom's birthday",
"What time is my Monday standup?",
"Can you recommend a coffee order for me?",
"What books am I reading?",
]
for message in conversations:
print(f"\nAlex: {message}")
print("-" * 40)
response = chat(message)
print(f"Assistant: {response}")
time.sleep(1)
```
## 7. View Summary
```python
print("=" * 60)
print(" What I Know About You")
print("=" * 60)
print(get_summary())
```
```python
print("=" * 60)
print(" Your Family")
print("=" * 60)
print(get_summary("family"))
```
## 8. Try Your Own Message
```python
your_message = "What should I focus on this month with my training?" # Change this!
print(f"You: {your_message}")
print("-" * 40)
print(f"Assistant: {chat(your_message)}")
```
## 9. Cleanup
```python
hindsight.close()
print("Client connection closed.")
```
@@ -0,0 +1,299 @@
---
sidebar_position: 10
---
# Personalized Search Agent with Hindsight Memory
:::tip Run this notebook
This recipe is available as an interactive Jupyter notebook.
[**Open in GitHub →**](https://github.com/vectorize-io/hindsight-cookbook/blob/main/notebooks/personalized_search.ipynb)
:::
A search assistant that learns your preferences, location, dietary needs, and lifestyle to provide contextually relevant search results.
## Features
- Learns location, dietary restrictions, and lifestyle
- Personalizes search queries based on context
- Remembers past searches and preferences
- Integrates with Tavily for real web search (optional)
## Prerequisites
- OpenAI API key
- Hindsight running locally via Docker (see setup below)
- Tavily API key (optional, for real web search)
## Start Hindsight Locally
Before running this notebook, start Hindsight in a terminal:
```bash
export OPENAI_API_KEY="your-openai-api-key"
docker run --rm -it --pull always -p 8888:8888 -p 9999:9999 \
-e HINDSIGHT_API_LLM_API_KEY=$OPENAI_API_KEY \
-e HINDSIGHT_API_LLM_MODEL=gpt-4o-mini \
-v $HOME/.hindsight-docker:/home/hindsight/.pg0 \
ghcr.io/vectorize-io/hindsight:latest
```
## 1. Install Dependencies
```python
# Tavily is optional - demo works with simulated results if not installed
!pip install -q hindsight-client openai tavily-python nest-asyncio
```
## 2. Configure API Keys
Enter your API keys when prompted. Tavily is optional - press Enter to skip for simulated search results.
```python
import getpass
import os
# Set OpenAI API key (used by both Hindsight and the demo)
if not os.getenv("OPENAI_API_KEY"):
os.environ["OPENAI_API_KEY"] = getpass.getpass("Enter your OpenAI API key: ")
# Tavily is optional - for real web search
if not os.getenv("TAVILY_API_KEY"):
tavily_key = getpass.getpass("Enter your Tavily API key (or press Enter to skip): ")
if tavily_key:
os.environ["TAVILY_API_KEY"] = tavily_key
print("API keys configured!")
```
## 3. Initialize Clients
```python
import nest_asyncio
nest_asyncio.apply()
from openai import OpenAI
from hindsight_client import Hindsight
# Initialize Hindsight client (connects to local Docker instance)
hindsight = Hindsight(
base_url=os.getenv("HINDSIGHT_BASE_URL", "http://localhost:8888"),
)
openai_client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
# Optional: Tavily for real web search
try:
from tavily import TavilyClient
tavily = TavilyClient(api_key=os.getenv("TAVILY_API_KEY"))
HAS_TAVILY = True
print("Tavily configured - using real web search!")
except (ImportError, Exception) as e:
HAS_TAVILY = False
print("Note: Using simulated search results (Tavily not configured)")
USER_ID = "search-user-demo"
print("Clients initialized!")
```
## 4. Define Helper Functions
```python
def store_preference(preference: str) -> str:
"""Store a user preference."""
hindsight.retain(
bank_id=USER_ID,
content=f"User preference: {preference}",
metadata={"category": "preference"},
)
return f"Learned: {preference}"
def store_interaction(query: str, response: str) -> None:
"""Store a search interaction."""
hindsight.retain(
bank_id=USER_ID,
content=f"Search query: {query}\nResult highlights: {response[:200]}",
metadata={"category": "search_history"},
)
def get_user_context(query: str) -> str:
"""Retrieve relevant user context."""
memories = hindsight.recall(
bank_id=USER_ID,
query=f"preferences location dietary lifestyle {query}",
budget="mid",
)
if memories and memories.results:
return "\n".join(f"- {m.text}" for m in memories.results[:6])
return ""
def personalized_search(query: str) -> str:
"""Perform a personalized search."""
user_context = get_user_context(query)
enhancement_prompt = f"""Given this user's preferences and the search query, suggest how to enhance the search.
User preferences:
{user_context if user_context else "No preferences recorded yet."}
Search query: {query}
Return a JSON object with:
- "enhanced_query": The improved search query incorporating relevant preferences
- "filters": Any specific filters to apply (e.g., "vegetarian", "within 5 miles")
- "reasoning": Brief explanation of personalizations applied"""
enhancement = openai_client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": enhancement_prompt}],
temperature=0.3,
max_tokens=300,
)
enhanced_info = enhancement.choices[0].message.content
# Perform the search
if HAS_TAVILY:
search_results = tavily.search(
query=query,
search_depth="advanced",
max_results=5,
)
results_text = "\n".join(
f"- {r['title']}: {r['content'][:150]}..."
for r in search_results.get('results', [])
)
else:
results_text = f"[Simulated search results for: {query}]"
response_prompt = f"""Based on the search results and user preferences, provide a personalized summary.
User preferences:
{user_context if user_context else "No preferences recorded yet."}
Query: {query}
Search enhancement applied:
{enhanced_info}
Search results:
{results_text}
Provide a helpful, personalized response that takes into account their preferences."""
response = openai_client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": response_prompt}],
temperature=0.7,
max_tokens=500,
)
answer = response.choices[0].message.content
store_interaction(query, answer)
return answer
def get_preference_profile() -> str:
"""Get a summary of the user's preference profile."""
profile = hindsight.reflect(
bank_id=USER_ID,
query="""Summarize what we know about this user:
- Location and neighborhood
- Dietary preferences and restrictions
- Work style and schedule
- Hobbies and interests
- Family situation
- Shopping preferences""",
budget="high",
)
return profile.text if hasattr(profile, 'text') else str(profile)
print("Helper functions defined!")
```
## 5. Build User Profile
```python
print("Learning user preferences...")
preferences = [
"Lives in San Francisco, Mission District",
"Works remotely as a software engineer",
"Vegetarian, prefers organic food when possible",
"Has a 5-year-old daughter named Emma",
"Enjoys hiking and outdoor activities on weekends",
"Prefers quiet coffee shops for remote work",
"Lactose intolerant, uses oat milk",
"Interested in sustainable and eco-friendly products",
"Usually free on Tuesday and Thursday afternoons",
"Husband is allergic to nuts",
]
for pref in preferences:
result = store_preference(pref)
print(f" {result}")
```
## 6. Personalized Search Results
```python
import time
print("=" * 60)
print(" Personalized Search Results")
print("=" * 60)
searches = [
"Find a good coffee shop for working remotely",
"Restaurant recommendations for a family dinner",
"Birthday gift ideas for a 5-year-old",
]
for query in searches:
print(f"\nSearch: {query}")
print("-" * 40)
result = personalized_search(query)
print(result)
time.sleep(1)
```
## 7. View Preference Profile
```python
print("=" * 60)
print(" User Preference Profile")
print("=" * 60)
print(get_preference_profile())
```
## 8. Try Your Own Search
```python
your_search = "Best hiking trails near me" # Change this!
print(f"Search: {your_search}")
print("-" * 40)
print(personalized_search(your_search))
```
## 9. Cleanup
```python
hindsight.close()
print("Client connection closed.")
```
@@ -127,7 +127,7 @@ for r in results.results:
## Reflect: Generate Insights
The `reflect` operation performs reasoning over existing memories using the bank's disposition. It retrieves relevant facts and observations to generate contextual responses.
The `reflect` operation performs a more thorough analysis of existing memories. This allows the agent to form new connections between memories which are then persisted as opinions and/or observations.
Example use cases:
- An AI Project Manager reflecting on what risks need to be mitigated
@@ -142,11 +142,12 @@ print(response)
## Memory Types
Hindsight organizes knowledge into facts and consolidated observations:
Hindsight organizes memory into four networks to mimic human memory:
- **World**: Facts about the world ("The stove gets hot")
- **Experience**: Agent's own experiences ("I touched the stove and it really hurt")
- **Observation**: Consolidated knowledge synthesized from facts ("Always be careful around hot surfaces")
- **Experiences**: Agent's own experiences ("I touched the stove and it really hurt")
- **Opinion**: Beliefs with confidence scores ("I shouldn't touch the stove again" - .99 confidence)
- **Observation**: Complex mental models derived by reflecting on facts and experiences
## Cleanup
@@ -0,0 +1,335 @@
---
sidebar_position: 11
---
# Study Buddy with Hindsight Memory
:::tip Run this notebook
This recipe is available as an interactive Jupyter notebook.
[**Open in GitHub →**](https://github.com/vectorize-io/hindsight-cookbook/blob/main/notebooks/study_buddy.ipynb)
:::
A personalized study assistant that tracks what you've learned, identifies knowledge gaps, and helps with spaced repetition.
## Features
- Tracks study sessions and topics covered
- Monitors confidence levels per topic
- Identifies knowledge gaps
- Suggests topics for spaced repetition review
## Prerequisites
- OpenAI API key
- Hindsight running locally via Docker (see setup below)
## Start Hindsight Locally
Before running this notebook, start Hindsight in a terminal:
```bash
export OPENAI_API_KEY="your-openai-api-key"
docker run --rm -it --pull always -p 8888:8888 -p 9999:9999 \
-e HINDSIGHT_API_LLM_API_KEY=$OPENAI_API_KEY \
-e HINDSIGHT_API_LLM_MODEL=gpt-4o-mini \
-v $HOME/.hindsight-docker:/home/hindsight/.pg0 \
ghcr.io/vectorize-io/hindsight:latest
```
## 1. Install Dependencies
```python
!pip install -q hindsight-client openai nest-asyncio
```
## 2. Configure OpenAI API Key
Enter your OpenAI API key when prompted (used by both Hindsight and the demo).
```python
import getpass
import os
# Set OpenAI API key (used by both Hindsight and the demo)
if not os.getenv("OPENAI_API_KEY"):
os.environ["OPENAI_API_KEY"] = getpass.getpass("Enter your OpenAI API key: ")
print("API key configured!")
```
## 3. Initialize Clients
```python
import nest_asyncio
nest_asyncio.apply()
from datetime import datetime
from openai import OpenAI
from hindsight_client import Hindsight
# Initialize Hindsight client (connects to local Docker instance)
hindsight = Hindsight(
base_url=os.getenv("HINDSIGHT_BASE_URL", "http://localhost:8888"),
)
openai_client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
USER_ID = "student-demo"
print("Clients initialized!")
```
## 4. Define Helper Functions
```python
def record_study_session(topic: str, notes: str, confidence: str = "medium") -> str:
"""Record a study session with topic, notes, and self-assessed confidence."""
today = datetime.now().strftime("%B %d, %Y")
content = f"""{today} - STUDY SESSION
Topic: {topic}
Confidence Level: {confidence}
Notes: {notes}"""
hindsight.retain(
bank_id=USER_ID,
content=content,
metadata={
"category": "study_session",
"topic": topic,
"confidence": confidence,
"date": today,
},
)
return f"Recorded study session on '{topic}' (confidence: {confidence})"
def record_question(topic: str, question: str, understood: bool) -> str:
"""Record a question asked during study."""
today = datetime.now().strftime("%B %d, %Y")
content = f"""{today} - QUESTION
Topic: {topic}
Question: {question}
Understood: {"Yes" if understood else "No - needs review"}"""
hindsight.retain(
bank_id=USER_ID,
content=content,
metadata={
"category": "question",
"topic": topic,
"understood": str(understood),
},
)
return f"Recorded question on '{topic}'"
def study_buddy(user_query: str) -> str:
"""Interact with the study buddy."""
memories = hindsight.recall(
bank_id=USER_ID,
query=f"study session topic notes questions {user_query}",
budget="high",
)
memory_context = ""
if memories and memories.results:
memory_context = "\n".join(f"- {m.text}" for m in memories.results[:8])
system_prompt = f"""You are a helpful study buddy and tutor.
You have access to the student's study history, including:
- Topics they've studied and their notes
- Their self-assessed confidence levels
- Questions they've asked and whether they understood the answers
Study History:
{memory_context if memory_context else "No study history recorded yet."}
Your role:
1. Answer questions about topics they're studying
2. Identify knowledge gaps based on their history
3. Suggest topics to review (spaced repetition)
4. Provide encouragement and study tips
5. Connect new concepts to things they've already learned
Be supportive and pedagogical. Reference their previous learning when relevant."""
response = openai_client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_query},
],
temperature=0.7,
max_tokens=800,
)
answer = response.choices[0].message.content
hindsight.retain(
bank_id=USER_ID,
content=f"Student asked: {user_query}\nExplanation given: {answer[:300]}...",
metadata={"category": "tutoring"},
)
return answer
def get_review_suggestions() -> str:
"""Get suggestions for topics to review."""
suggestions = hindsight.reflect(
bank_id=USER_ID,
query="""Analyze this student's study history and suggest:
1. Topics with low confidence that need more review
2. Topics studied a while ago that should be revisited
3. Questions that weren't fully understood
4. Connections between topics they might have missed
Prioritize by what would most improve their understanding.""",
budget="high",
)
return suggestions.text if hasattr(suggestions, 'text') else str(suggestions)
def get_knowledge_summary(topic: str = None) -> str:
"""Get a summary of what the student knows."""
query = f"Summarize what this student knows about {topic}" if topic else \
"Summarize this student's overall knowledge and progress"
summary = hindsight.reflect(
bank_id=USER_ID,
query=query,
budget="high",
)
return summary.text if hasattr(summary, 'text') else str(summary)
print("Helper functions defined!")
```
## 5. Record Study Sessions
```python
print("Recording study sessions...")
sessions = [
{
"topic": "Classical Mechanics - Newton's Laws",
"notes": "Covered F=ma, action-reaction pairs, inertia. Solved problems on inclined planes.",
"confidence": "high",
},
{
"topic": "Classical Mechanics - Conservation of Momentum",
"notes": "Elastic vs inelastic collisions. Struggled with 2D collision problems.",
"confidence": "low",
},
{
"topic": "Classical Mechanics - Generalized Coordinates",
"notes": "Introduction to Lagrangian mechanics. Degrees of freedom concept.",
"confidence": "medium",
},
{
"topic": "Waves - Simple Harmonic Motion",
"notes": "SHM equations, period, frequency. Connected to springs and pendulums.",
"confidence": "high",
},
{
"topic": "Waves - Frequency Domain",
"notes": "Started Fourier transforms. Math is confusing, need more practice.",
"confidence": "low",
},
]
for session in sessions:
result = record_study_session(**session)
print(f" {result}")
```
## 6. Record Questions
```python
print("Recording questions...")
questions = [
("Conservation of Momentum", "Why is momentum conserved in collisions?", True),
("Conservation of Momentum", "How do I solve 2D collision problems?", False),
("Generalized Coordinates", "What's the advantage of Lagrangian over Newtonian?", True),
("Frequency Domain", "When do I use Fourier transforms vs Laplace?", False),
]
for topic, question, understood in questions:
result = record_question(topic, question, understood)
print(f" {result}")
```
## 7. Interactive Study Session
```python
import time
print("=" * 60)
print(" Study Session")
print("=" * 60)
queries = [
"Can you explain generalized coordinates again? I remember we covered it but I'm fuzzy on the details.",
"What topics should I review before my exam next week?",
"I'm still confused about 2D collision problems. Can you walk me through an example?",
]
for query in queries:
print(f"\nStudent: {query}")
print("-" * 40)
response = study_buddy(query)
print(f"Study Buddy: {response}")
time.sleep(1)
```
## 8. Get Review Suggestions
```python
print("=" * 60)
print(" Recommended Review Topics")
print("=" * 60)
print(get_review_suggestions())
```
## 9. Knowledge Summary
```python
print("=" * 60)
print(" Knowledge Summary")
print("=" * 60)
print(get_knowledge_summary())
```
## 10. Try Your Own Question
```python
your_question = "What are my biggest knowledge gaps right now?" # Change this!
print(f"You: {your_question}")
print("-" * 40)
print(f"Study Buddy: {study_buddy(your_question)}")
```
## 11. Cleanup
```python
hindsight.close()
print("Client connection closed.")
```
@@ -158,21 +158,16 @@ Use your ChatGPT Plus or Pro subscription for Hindsight without separate OpenAI
4. **Configure Hindsight:**
```bash
export HINDSIGHT_API_LLM_PROVIDER=openai-codex
export HINDSIGHT_API_LLM_MODEL=gpt-5.2-codex # or gpt-5.1-codex
# export HINDSIGHT_API_LLM_MODEL=gpt-5.1-codex # defaults to gpt-5.2-codex
# No API key needed - reads from ~/.codex/auth.json automatically
```
5. **Start Hindsight:**
```bash
./scripts/dev/start-api.sh
hindsight-api
```
**Available Models:**
- `gpt-5.2-codex` - Latest frontier agentic coding model (default)
- `gpt-5.2` - Latest frontier model
- `gpt-5.1-codex` - Previous generation coding model
- `gpt-5.1-codex-max` - Maximum context variant
- `gpt-5.1-codex-mini` - Lightweight variant
You can use any model supported by OpenAI Codex CLI
**Important Notes:**
- OAuth tokens are stored in `~/.codex/auth.json`
@@ -186,9 +181,6 @@ If authentication fails:
```bash
# Re-login to refresh tokens
codex auth login
# Check auth file exists and has correct format
cat ~/.codex/auth.json | python3 -c "import json, sys; d=json.load(sys.stdin); print('auth_mode:', d.get('auth_mode')); print('has tokens:', 'tokens' in d)"
```
---
@@ -225,50 +217,22 @@ Use your Claude Pro or Max subscription for Hindsight without separate Anthropic
4. **Configure Hindsight:**
```bash
export HINDSIGHT_API_LLM_PROVIDER=claude-code
export HINDSIGHT_API_LLM_MODEL=claude-sonnet-4-5-20250929
# No API key needed - uses claude auth login credentials
```
5. **Start Hindsight:**
```bash
./scripts/dev/start-api.sh
hindsight-api
```
**Available Models:**
- `claude-sonnet-4-5-20250929` - Latest Claude Sonnet (default)
- `claude-opus-4-20250514` - Claude Opus for complex tasks
- `claude-sonnet-3-5-20241022` - Previous generation Sonnet
- Any model supported by Claude Code CLI
You can use any model supported by Claude Code CLI.
**Important Notes:**
- Authentication handled by Claude Agent SDK (uses bundled CLI)
- Credentials managed securely by Claude Code
- Usage billed to your Claude subscription (not separate API costs)
- Includes Claude Agent SDK as dependency (auto-installed)
- For personal development use only (see Claude Terms of Service)
**Troubleshooting:**
If authentication fails:
```bash
# Re-login to refresh credentials
claude auth login
# Check Claude CLI is working
claude --version
# Test authentication directly
claude query "test"
```
If the SDK is not found:
```bash
# Install Claude Agent SDK
pip install claude-agent-sdk
# Or with uv
uv add claude-agent-sdk
```
---
## Embedding Model
@@ -238,6 +238,36 @@
"type": "doc",
"id": "cookbook/recipes/tool-learning-demo",
"label": "Routing Tool Learning"
},
{
"type": "doc",
"id": "cookbook/recipes/fitness_tracker",
"label": "Fitness Coach with Hindsight Memory"
},
{
"type": "doc",
"id": "cookbook/recipes/healthcare_assistant",
"label": "Healthcare Assistant with Hindsight Memory"
},
{
"type": "doc",
"id": "cookbook/recipes/movie_recommendation",
"label": "Movie Recommendation Assistant with Hindsight Memory"
},
{
"type": "doc",
"id": "cookbook/recipes/personal_assistant",
"label": "Personal AI Assistant with Hindsight Memory"
},
{
"type": "doc",
"id": "cookbook/recipes/personalized_search",
"label": "Personalized Search Agent with Hindsight Memory"
},
{
"type": "doc",
"id": "cookbook/recipes/study_buddy",
"label": "Study Buddy with Hindsight Memory"
}
]
},
@@ -246,10 +276,40 @@
"label": "Applications",
"collapsible": false,
"items": [
{
"type": "doc",
"id": "cookbook/applications/chat-memory",
"label": "Chat Memory App"
},
{
"type": "doc",
"id": "cookbook/applications/deliveryman-demo",
"label": "Deliveryman Demo"
},
{
"type": "doc",
"id": "cookbook/applications/hindsight-litellm-demo",
"label": "Memory Approaches Comparison Demo"
},
{
"type": "doc",
"id": "cookbook/applications/hindsight-tool-learning-demo",
"label": "Tool Learning Demo"
},
{
"type": "doc",
"id": "cookbook/applications/openai-fitness-coach",
"label": "OpenAI Agent + Hindsight Memory Integration"
},
{
"type": "doc",
"id": "cookbook/applications/sanity-blog-memory",
"label": "Sanity CMS Blog Memory"
},
{
"type": "doc",
"id": "cookbook/applications/stancetracker",
"label": "Stance Tracker"
}
]
}