Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8acd4f4080 | ||
|
|
f3d604e1f8 | ||
|
|
d77ad8beb3 | ||
|
|
bd87c5faf9 |
@@ -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
|
||||
@@ -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.")
|
||||
```
|
||||
@@ -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 |
|
||||
+206
@@ -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
|
||||
+123
@@ -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
|
||||
+12
-12
@@ -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
|
||||
|
||||
|
||||
+371
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user