diff --git a/hindsight-dev/hindsight_dev/sync_cookbook.py b/hindsight-dev/hindsight_dev/sync_cookbook.py index 3458df6c..362bd4c3 100644 --- a/hindsight-dev/hindsight_dev/sync_cookbook.py +++ b/hindsight-dev/hindsight_dev/sync_cookbook.py @@ -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} diff --git a/hindsight-docs/docs/cookbook/applications/chat-memory.md b/hindsight-docs/docs/cookbook/applications/chat-memory.md new file mode 100644 index 00000000..cf36aa9e --- /dev/null +++ b/hindsight-docs/docs/cookbook/applications/chat-memory.md @@ -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 diff --git a/hindsight-docs/docs/cookbook/applications/deliveryman-demo.md b/hindsight-docs/docs/cookbook/applications/deliveryman-demo.md new file mode 100644 index 00000000..866c3e21 --- /dev/null +++ b/hindsight-docs/docs/cookbook/applications/deliveryman-demo.md @@ -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= +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= +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 | diff --git a/hindsight-docs/docs/cookbook/applications/hindsight-litellm-demo.md b/hindsight-docs/docs/cookbook/applications/hindsight-litellm-demo.md new file mode 100644 index 00000000..ea55cd0e --- /dev/null +++ b/hindsight-docs/docs/cookbook/applications/hindsight-litellm-demo.md @@ -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 diff --git a/hindsight-docs/docs/cookbook/applications/hindsight-tool-learning-demo.md b/hindsight-docs/docs/cookbook/applications/hindsight-tool-learning-demo.md new file mode 100644 index 00000000..f8f8cf7b --- /dev/null +++ b/hindsight-docs/docs/cookbook/applications/hindsight-tool-learning-demo.md @@ -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 diff --git a/hindsight-docs/docs/cookbook/applications/openai-fitness-coach.md b/hindsight-docs/docs/cookbook/applications/openai-fitness-coach.md index 67f88ac9..d5bb278f 100644 --- a/hindsight-docs/docs/cookbook/applications/openai-fitness-coach.md +++ b/hindsight-docs/docs/cookbook/applications/openai-fitness-coach.md @@ -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 diff --git a/hindsight-docs/docs/cookbook/applications/sanity-blog-memory.md b/hindsight-docs/docs/cookbook/applications/sanity-blog-memory.md new file mode 100644 index 00000000..798ced50 --- /dev/null +++ b/hindsight-docs/docs/cookbook/applications/sanity-blog-memory.md @@ -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 { + 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 diff --git a/hindsight-docs/docs/cookbook/applications/stancetracker.md b/hindsight-docs/docs/cookbook/applications/stancetracker.md new file mode 100644 index 00000000..9e6ce781 --- /dev/null +++ b/hindsight-docs/docs/cookbook/applications/stancetracker.md @@ -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 diff --git a/hindsight-docs/docs/cookbook/index.mdx b/hindsight-docs/docs/cookbook/index.mdx index 27e96d04..4d6d367e 100644 --- a/hindsight-docs/docs/cookbook/index.mdx +++ b/hindsight-docs/docs/cookbook/index.mdx @@ -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" } ]} /> diff --git a/hindsight-docs/docs/cookbook/recipes/fitness_tracker.md b/hindsight-docs/docs/cookbook/recipes/fitness_tracker.md new file mode 100644 index 00000000..a411eede --- /dev/null +++ b/hindsight-docs/docs/cookbook/recipes/fitness_tracker.md @@ -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.") +``` diff --git a/hindsight-docs/docs/cookbook/recipes/healthcare_assistant.md b/hindsight-docs/docs/cookbook/recipes/healthcare_assistant.md new file mode 100644 index 00000000..995f621b --- /dev/null +++ b/hindsight-docs/docs/cookbook/recipes/healthcare_assistant.md @@ -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.") +``` diff --git a/hindsight-docs/docs/cookbook/recipes/movie_recommendation.md b/hindsight-docs/docs/cookbook/recipes/movie_recommendation.md new file mode 100644 index 00000000..1dc3bf4a --- /dev/null +++ b/hindsight-docs/docs/cookbook/recipes/movie_recommendation.md @@ -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 + +``` diff --git a/hindsight-docs/docs/cookbook/recipes/personal_assistant.md b/hindsight-docs/docs/cookbook/recipes/personal_assistant.md new file mode 100644 index 00000000..ecc520d6 --- /dev/null +++ b/hindsight-docs/docs/cookbook/recipes/personal_assistant.md @@ -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.") +``` diff --git a/hindsight-docs/docs/cookbook/recipes/personalized_search.md b/hindsight-docs/docs/cookbook/recipes/personalized_search.md new file mode 100644 index 00000000..61ac26f5 --- /dev/null +++ b/hindsight-docs/docs/cookbook/recipes/personalized_search.md @@ -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.") +``` diff --git a/hindsight-docs/docs/cookbook/recipes/quickstart.md b/hindsight-docs/docs/cookbook/recipes/quickstart.md index affb8392..b219fe9a 100644 --- a/hindsight-docs/docs/cookbook/recipes/quickstart.md +++ b/hindsight-docs/docs/cookbook/recipes/quickstart.md @@ -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 diff --git a/hindsight-docs/docs/cookbook/recipes/study_buddy.md b/hindsight-docs/docs/cookbook/recipes/study_buddy.md new file mode 100644 index 00000000..3174c210 --- /dev/null +++ b/hindsight-docs/docs/cookbook/recipes/study_buddy.md @@ -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.") +``` diff --git a/hindsight-docs/sidebars.ts b/hindsight-docs/sidebars.ts index 5b37b0b5..b6964bbd 100644 --- a/hindsight-docs/sidebars.ts +++ b/hindsight-docs/sidebars.ts @@ -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', } ], }, diff --git a/hindsight-docs/versioned_docs/version-0.4/cookbook/applications/chat-memory.md b/hindsight-docs/versioned_docs/version-0.4/cookbook/applications/chat-memory.md new file mode 100644 index 00000000..cf36aa9e --- /dev/null +++ b/hindsight-docs/versioned_docs/version-0.4/cookbook/applications/chat-memory.md @@ -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 diff --git a/hindsight-docs/versioned_docs/version-0.4/cookbook/applications/deliveryman-demo.md b/hindsight-docs/versioned_docs/version-0.4/cookbook/applications/deliveryman-demo.md new file mode 100644 index 00000000..866c3e21 --- /dev/null +++ b/hindsight-docs/versioned_docs/version-0.4/cookbook/applications/deliveryman-demo.md @@ -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= +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= +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 | diff --git a/hindsight-docs/versioned_docs/version-0.4/cookbook/applications/hindsight-litellm-demo.md b/hindsight-docs/versioned_docs/version-0.4/cookbook/applications/hindsight-litellm-demo.md new file mode 100644 index 00000000..ea55cd0e --- /dev/null +++ b/hindsight-docs/versioned_docs/version-0.4/cookbook/applications/hindsight-litellm-demo.md @@ -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 diff --git a/hindsight-docs/versioned_docs/version-0.4/cookbook/applications/hindsight-tool-learning-demo.md b/hindsight-docs/versioned_docs/version-0.4/cookbook/applications/hindsight-tool-learning-demo.md new file mode 100644 index 00000000..f8f8cf7b --- /dev/null +++ b/hindsight-docs/versioned_docs/version-0.4/cookbook/applications/hindsight-tool-learning-demo.md @@ -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 diff --git a/hindsight-docs/versioned_docs/version-0.4/cookbook/applications/openai-fitness-coach.md b/hindsight-docs/versioned_docs/version-0.4/cookbook/applications/openai-fitness-coach.md index 67f88ac9..d5bb278f 100644 --- a/hindsight-docs/versioned_docs/version-0.4/cookbook/applications/openai-fitness-coach.md +++ b/hindsight-docs/versioned_docs/version-0.4/cookbook/applications/openai-fitness-coach.md @@ -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 diff --git a/hindsight-docs/versioned_docs/version-0.4/cookbook/applications/sanity-blog-memory.md b/hindsight-docs/versioned_docs/version-0.4/cookbook/applications/sanity-blog-memory.md new file mode 100644 index 00000000..798ced50 --- /dev/null +++ b/hindsight-docs/versioned_docs/version-0.4/cookbook/applications/sanity-blog-memory.md @@ -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 { + 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 diff --git a/hindsight-docs/versioned_docs/version-0.4/cookbook/applications/stancetracker.md b/hindsight-docs/versioned_docs/version-0.4/cookbook/applications/stancetracker.md new file mode 100644 index 00000000..9e6ce781 --- /dev/null +++ b/hindsight-docs/versioned_docs/version-0.4/cookbook/applications/stancetracker.md @@ -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 diff --git a/hindsight-docs/versioned_docs/version-0.4/cookbook/index.mdx b/hindsight-docs/versioned_docs/version-0.4/cookbook/index.mdx index 27e96d04..4d6d367e 100644 --- a/hindsight-docs/versioned_docs/version-0.4/cookbook/index.mdx +++ b/hindsight-docs/versioned_docs/version-0.4/cookbook/index.mdx @@ -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" } ]} /> diff --git a/hindsight-docs/versioned_docs/version-0.4/cookbook/recipes/fitness_tracker.md b/hindsight-docs/versioned_docs/version-0.4/cookbook/recipes/fitness_tracker.md new file mode 100644 index 00000000..a411eede --- /dev/null +++ b/hindsight-docs/versioned_docs/version-0.4/cookbook/recipes/fitness_tracker.md @@ -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.") +``` diff --git a/hindsight-docs/versioned_docs/version-0.4/cookbook/recipes/healthcare_assistant.md b/hindsight-docs/versioned_docs/version-0.4/cookbook/recipes/healthcare_assistant.md new file mode 100644 index 00000000..995f621b --- /dev/null +++ b/hindsight-docs/versioned_docs/version-0.4/cookbook/recipes/healthcare_assistant.md @@ -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.") +``` diff --git a/hindsight-docs/versioned_docs/version-0.4/cookbook/recipes/movie_recommendation.md b/hindsight-docs/versioned_docs/version-0.4/cookbook/recipes/movie_recommendation.md new file mode 100644 index 00000000..1dc3bf4a --- /dev/null +++ b/hindsight-docs/versioned_docs/version-0.4/cookbook/recipes/movie_recommendation.md @@ -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 + +``` diff --git a/hindsight-docs/versioned_docs/version-0.4/cookbook/recipes/personal_assistant.md b/hindsight-docs/versioned_docs/version-0.4/cookbook/recipes/personal_assistant.md new file mode 100644 index 00000000..ecc520d6 --- /dev/null +++ b/hindsight-docs/versioned_docs/version-0.4/cookbook/recipes/personal_assistant.md @@ -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.") +``` diff --git a/hindsight-docs/versioned_docs/version-0.4/cookbook/recipes/personalized_search.md b/hindsight-docs/versioned_docs/version-0.4/cookbook/recipes/personalized_search.md new file mode 100644 index 00000000..61ac26f5 --- /dev/null +++ b/hindsight-docs/versioned_docs/version-0.4/cookbook/recipes/personalized_search.md @@ -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.") +``` diff --git a/hindsight-docs/versioned_docs/version-0.4/cookbook/recipes/quickstart.md b/hindsight-docs/versioned_docs/version-0.4/cookbook/recipes/quickstart.md index affb8392..b219fe9a 100644 --- a/hindsight-docs/versioned_docs/version-0.4/cookbook/recipes/quickstart.md +++ b/hindsight-docs/versioned_docs/version-0.4/cookbook/recipes/quickstart.md @@ -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 diff --git a/hindsight-docs/versioned_docs/version-0.4/cookbook/recipes/study_buddy.md b/hindsight-docs/versioned_docs/version-0.4/cookbook/recipes/study_buddy.md new file mode 100644 index 00000000..3174c210 --- /dev/null +++ b/hindsight-docs/versioned_docs/version-0.4/cookbook/recipes/study_buddy.md @@ -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.") +``` diff --git a/hindsight-docs/versioned_docs/version-0.4/developer/models.md b/hindsight-docs/versioned_docs/version-0.4/developer/models.md index e9a60907..cbb94bc5 100644 --- a/hindsight-docs/versioned_docs/version-0.4/developer/models.md +++ b/hindsight-docs/versioned_docs/version-0.4/developer/models.md @@ -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 diff --git a/hindsight-docs/versioned_sidebars/version-0.4-sidebars.json b/hindsight-docs/versioned_sidebars/version-0.4-sidebars.json index 78d8ec66..eb6fea7f 100644 --- a/hindsight-docs/versioned_sidebars/version-0.4-sidebars.json +++ b/hindsight-docs/versioned_sidebars/version-0.4-sidebars.json @@ -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" } ] }