doc: release notes for 0.4.0 (#217)
* doc: release notes for 0.4.0 * doc: release notes for 0.4.0 * doc: release notes for 0.4.0 * doc: release notes for 0.4.0
This commit is contained in:
parent
1bf90358c3
commit
20f2b92069
52 changed files with 8189 additions and 235 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -50,4 +50,5 @@ hindsight-clients/rust/target
|
|||
.claude
|
||||
whats-next.md
|
||||
TASK.md
|
||||
CHANGELOG.md
|
||||
# Changelog is now tracked in hindsight-docs/src/pages/changelog.md
|
||||
# CHANGELOG.md
|
||||
|
|
@ -25,7 +25,7 @@ GITHUB_REPO = "vectorize-io/hindsight"
|
|||
GITHUB_RELEASES_URL = f"https://github.com/{GITHUB_REPO}/releases"
|
||||
GITHUB_COMMIT_URL = f"https://github.com/{GITHUB_REPO}/commit"
|
||||
REPO_PATH = Path(__file__).parent.parent.parent
|
||||
CHANGELOG_PATH = REPO_PATH / "hindsight-docs" / "docs" / "changelog" / "index.md"
|
||||
CHANGELOG_PATH = REPO_PATH / "hindsight-docs" / "src" / "pages" / "changelog.md"
|
||||
|
||||
|
||||
class ChangelogEntry(BaseModel):
|
||||
|
|
@ -238,7 +238,7 @@ def read_existing_changelog() -> tuple[str, str]:
|
|||
"""Read existing changelog and split into header and content."""
|
||||
if not CHANGELOG_PATH.exists():
|
||||
header = """---
|
||||
sidebar_position: 1
|
||||
hide_table_of_contents: true
|
||||
---
|
||||
|
||||
# Changelog
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ slug: learning-capabilities
|
|||
title: "Agent memory that learns: observations and mental models"
|
||||
authors: [hindsight]
|
||||
image: /img/reflect-operation.webp
|
||||
hide_table_of_contents: false
|
||||
hide_table_of_contents: true
|
||||
---
|
||||
|
||||
Today we're releasing Hindsight 0.4.0, which introduces two powerful learning capabilities for AI agents: **Observations** for automatic knowledge consolidation, and **Mental Models** for user-curated summaries.
|
||||
|
|
@ -220,8 +220,7 @@ const config: Config = {
|
|||
className: 'navbar-item-blog',
|
||||
},
|
||||
{
|
||||
type: 'doc',
|
||||
docId: 'changelog/index',
|
||||
to: '/changelog',
|
||||
position: 'left',
|
||||
label: 'Changelog',
|
||||
className: 'navbar-item-changelog',
|
||||
|
|
|
|||
|
|
@ -246,13 +246,6 @@ const sidebars: SidebarsConfig = {
|
|||
],
|
||||
},
|
||||
],
|
||||
changelogSidebar: [
|
||||
{
|
||||
type: 'doc',
|
||||
id: 'changelog/index',
|
||||
label: 'Changelog',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default sidebars;
|
||||
|
|
|
|||
|
|
@ -511,6 +511,17 @@ div[class*="codeBlockContent"] .prism-code {
|
|||
max-width: 100%;
|
||||
}
|
||||
|
||||
/* Force blog posts to be wider - aggressive override */
|
||||
body[class*="blog"] .container,
|
||||
body[class*="blog"] main .container {
|
||||
max-width: 100% !important;
|
||||
}
|
||||
|
||||
body[class*="blog"] article {
|
||||
max-width: 1200px !important;
|
||||
margin: 0 auto !important;
|
||||
}
|
||||
|
||||
/* Page title with gradient */
|
||||
article h1,
|
||||
.markdown h1,
|
||||
|
|
@ -1249,25 +1260,17 @@ ul[class*="suggestion"] {
|
|||
|
||||
/* ===== Blog Styling ===== */
|
||||
|
||||
/* Hide TOC sidebar on blog post pages */
|
||||
.blog-post-page .col--3,
|
||||
.blog-post-page [class*="tableOfContents"],
|
||||
.blog-post-page aside[class*="toc"] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Make blog post content full width when TOC is hidden */
|
||||
.blog-post-page .col--9 {
|
||||
--ifm-col-width: 100%;
|
||||
max-width: 100%;
|
||||
flex-basis: 100%;
|
||||
}
|
||||
|
||||
/* Hide author avatar/icon on blog posts */
|
||||
[class*="blogPostAuthor"] img,
|
||||
[class*="authorImage"],
|
||||
.avatar__photo {
|
||||
display: none !important;
|
||||
/* Blog author text visible in light mode */
|
||||
[class*="blogPostAuthor"],
|
||||
[class*="blogPostAuthor"] *,
|
||||
.avatar__name,
|
||||
.avatar__name a,
|
||||
.avatar__subtitle,
|
||||
[class*="authorName"],
|
||||
[class*="blogPostData"] a,
|
||||
[class*="blogPostInfo"] a {
|
||||
color: #1e293b !important;
|
||||
-webkit-text-fill-color: #1e293b !important;
|
||||
}
|
||||
|
||||
/* Blog author text visible in dark mode */
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
sidebar_position: 1
|
||||
hide_table_of_contents: true
|
||||
---
|
||||
|
||||
# Changelog
|
||||
|
|
@ -8,7 +8,28 @@ This changelog highlights user-facing changes only. Internal maintenance, CI/CD,
|
|||
|
||||
For full release details, see [GitHub Releases](https://github.com/vectorize-io/hindsight/releases).
|
||||
|
||||
## [0.3.0](https://github.com/vectorize-io/hindsight/releases/tag/v0.3.0)
|
||||
## [0.4.0](https://github.com/vectorize-io/hindsight/releases/tag/v0.4.0)
|
||||
|
||||
**Observations**, **Mental Models**, new **Agentic Reflect** and Directives, read the [announcement](/blog/learning-capabilities).
|
||||
|
||||
**Features**
|
||||
|
||||
- Added support for providing a custom prompt for memory extraction. ([`3172e99`](https://github.com/vectorize-io/hindsight/commit/3172e99))
|
||||
- Expanded the LiteLLM integration with async retain/reflect support, cleaner API, and support for tags/mission (including passing API keys correctly). ([`1d4879a`](https://github.com/vectorize-io/hindsight/commit/1d4879a))
|
||||
- Added a new worker service to run background tasks at scale. ([`4c79240`](https://github.com/vectorize-io/hindsight/commit/4c79240))
|
||||
- MCP retain now supports timestamps. ([`b378f68`](https://github.com/vectorize-io/hindsight/commit/b378f68))
|
||||
- Added support for installing skills via `npx add-skill`. ([`ec22317`](https://github.com/vectorize-io/hindsight/commit/ec22317))
|
||||
|
||||
**Improvements**
|
||||
|
||||
- CLI retain-files now accepts more file types. ([`1eeced3`](https://github.com/vectorize-io/hindsight/commit/1eeced3))
|
||||
|
||||
**Bug Fixes**
|
||||
|
||||
- Fixed a macOS crash in the embed daemon caused by an XPC connection issue. ([`e5fc6ee`](https://github.com/vectorize-io/hindsight/commit/e5fc6ee))
|
||||
- Fixed occasional extraction in the wrong language. ([`87d4a36`](https://github.com/vectorize-io/hindsight/commit/87d4a36))
|
||||
- Fixed PyTorch model initialization issues that could cause startup failures (meta tensor/init problems). ([`ddaa5f5`](https://github.com/vectorize-io/hindsight/commit/ddaa5f5))
|
||||
|
||||
|
||||
**Features**
|
||||
|
||||
|
|
@ -1,192 +0,0 @@
|
|||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# Changelog
|
||||
|
||||
This changelog highlights user-facing changes only. Internal maintenance, CI/CD, and infrastructure updates are omitted.
|
||||
|
||||
For full release details, see [GitHub Releases](https://github.com/vectorize-io/hindsight/releases).
|
||||
|
||||
## [0.3.0](https://github.com/vectorize-io/hindsight/releases/tag/v0.3.0)
|
||||
|
||||
**Features**
|
||||
|
||||
- Add memory tags so you can label and filter memories during recall/reflect. ([`20c8f8b`](https://github.com/vectorize-io/hindsight/commit/20c8f8b))
|
||||
- Allow choosing different AI providers/models per operation. ([`e6709d5`](https://github.com/vectorize-io/hindsight/commit/e6709d5))
|
||||
- Add Cohere support for embeddings and reranking. ([`4de0730`](https://github.com/vectorize-io/hindsight/commit/4de0730))
|
||||
- Add configurable embedding dimensions and OpenAI embeddings support. ([`70de23e`](https://github.com/vectorize-io/hindsight/commit/70de23e))
|
||||
- Support custom base URLs for OpenAI-style embeddings and Cohere endpoints. ([`fa53917`](https://github.com/vectorize-io/hindsight/commit/fa53917))
|
||||
- Add LiteLLM gateway support for routing LLM/embedding requests. ([`d47c8a2`](https://github.com/vectorize-io/hindsight/commit/d47c8a2))
|
||||
- Add multilingual content support to improve handling and retrieval across languages. ([`c65c6a9`](https://github.com/vectorize-io/hindsight/commit/c65c6a9))
|
||||
- Add delete memory bank capability. ([`4b82d2d`](https://github.com/vectorize-io/hindsight/commit/4b82d2d))
|
||||
- Add backup/restore tooling for memory banks. ([`67b273d`](https://github.com/vectorize-io/hindsight/commit/67b273d))
|
||||
|
||||
**Improvements**
|
||||
|
||||
- Add retention modes to control how memories are extracted and stored. ([`fb31a35`](https://github.com/vectorize-io/hindsight/commit/fb31a35))
|
||||
- Add offline (optional) database migrations to support restricted/air-gapped deployments. ([`233bd2e`](https://github.com/vectorize-io/hindsight/commit/233bd2e))
|
||||
- Add database connection configuration options for more flexible deployments. ([`33fac2c`](https://github.com/vectorize-io/hindsight/commit/33fac2c))
|
||||
- Load .env automatically on startup to simplify configuration. ([`c06d9b4`](https://github.com/vectorize-io/hindsight/commit/c06d9b4))
|
||||
- Expose an operation ID from retain requests so async/background processing can be tracked. ([`1dacd0e`](https://github.com/vectorize-io/hindsight/commit/1dacd0e))
|
||||
- Add per-request LLM token usage metrics for monitoring and cost tracking. ([`29a542d`](https://github.com/vectorize-io/hindsight/commit/29a542d))
|
||||
- Add LLM call latency metrics for performance monitoring. ([`5e1f13e`](https://github.com/vectorize-io/hindsight/commit/5e1f13e))
|
||||
- Include tenant in metrics labels for better multi-tenant observability. ([`1ffc2a4`](https://github.com/vectorize-io/hindsight/commit/1ffc2a4))
|
||||
- Add async processing option to MCP retain tool for background retention workflows. ([`37fc7fb`](https://github.com/vectorize-io/hindsight/commit/37fc7fb))
|
||||
|
||||
**Bug Fixes**
|
||||
|
||||
- Fix extension loading in multi-worker deployments so all workers load extensions correctly. ([`f5f3fca`](https://github.com/vectorize-io/hindsight/commit/f5f3fca))
|
||||
- Improve recall performance by batching recall queries. ([`5991308`](https://github.com/vectorize-io/hindsight/commit/5991308))
|
||||
- Improve retrieval quality and stability for large memory banks (graph/MPFP retrieval fixes). ([`6232e69`](https://github.com/vectorize-io/hindsight/commit/6232e69))
|
||||
- Fix entities list being limited to 100 entities. ([`26bf571`](https://github.com/vectorize-io/hindsight/commit/26bf571))
|
||||
- Fix UI only showing the first 1000 memories. ([`67c1a42`](https://github.com/vectorize-io/hindsight/commit/67c1a42))
|
||||
- Fix duplicated causal relationships and improve token usage during processing. ([`49e233c`](https://github.com/vectorize-io/hindsight/commit/49e233c))
|
||||
- Improve causal link detection accuracy. ([`2a00df0`](https://github.com/vectorize-io/hindsight/commit/2a00df0))
|
||||
- Make retain max completion tokens configurable to prevent truncation issues. ([`7715a51`](https://github.com/vectorize-io/hindsight/commit/7715a51))
|
||||
- Fix Python SDK not sending the Authorization header, preventing authenticated requests. ([`39e3f7c`](https://github.com/vectorize-io/hindsight/commit/39e3f7c))
|
||||
- Fix stats endpoint missing tenant authentication in multi-tenant setups. ([`d6ff191`](https://github.com/vectorize-io/hindsight/commit/d6ff191))
|
||||
- Fix embedding dimension handling for tenant schemas in multi-tenant databases. ([`6fe9314`](https://github.com/vectorize-io/hindsight/commit/6fe9314))
|
||||
- Fix Groq free-tier compatibility so requests work correctly. ([`d899d18`](https://github.com/vectorize-io/hindsight/commit/d899d18))
|
||||
- Fix security vulnerability (qs / CVE-2025-15284). ([`b3becb6`](https://github.com/vectorize-io/hindsight/commit/b3becb6))
|
||||
- Restore MCP tools for listing and creating memory banks. ([`9fd5679`](https://github.com/vectorize-io/hindsight/commit/9fd5679))
|
||||
|
||||
## [0.2.0](https://github.com/vectorize-io/hindsight/releases/tag/v0.2.0)
|
||||
|
||||
**Features**
|
||||
|
||||
- Add additional model provider support, including Anthropic Claude and LM Studio. ([`787ed60`](https://github.com/vectorize-io/hindsight/commit/787ed60))
|
||||
- Add multi-bank access and new MCP tools for interacting with multiple memory banks via MCP. ([`6b5f593`](https://github.com/vectorize-io/hindsight/commit/6b5f593))
|
||||
- Allow supplying custom entities when retaining memories via the retain endpoint. ([`dd59bc8`](https://github.com/vectorize-io/hindsight/commit/dd59bc8))
|
||||
- Enhance the /reflect endpoint with max_tokens control and optional structured output responses. ([`d49e820`](https://github.com/vectorize-io/hindsight/commit/d49e820))
|
||||
|
||||
|
||||
**Improvements**
|
||||
|
||||
- Improve local LLM support for reasoning-capable models and streamline Docker startup for local deployments. ([`eea0f27`](https://github.com/vectorize-io/hindsight/commit/eea0f27))
|
||||
- Support operation validator extensions and return proper HTTP errors when validation fails. ([`ce45d30`](https://github.com/vectorize-io/hindsight/commit/ce45d30))
|
||||
- Add configurable observation thresholds to control when observations are created/updated. ([`54e2df0`](https://github.com/vectorize-io/hindsight/commit/54e2df0))
|
||||
- Improve graph visualization to the control plane for exploring memory relationships. ([`1a62069`](https://github.com/vectorize-io/hindsight/commit/1a62069))
|
||||
|
||||
**Bug Fixes**
|
||||
|
||||
- Fix MCP server lifecycle handling so MCP lifespan is correctly tied to the FastAPI app lifespan. ([`6b78f7d`](https://github.com/vectorize-io/hindsight/commit/6b78f7d))
|
||||
|
||||
## [0.1.15](https://github.com/vectorize-io/hindsight/releases/tag/v0.1.15)
|
||||
|
||||
**Features**
|
||||
|
||||
- Add the ability to delete documents from the web UI. ([`f7ff32d`](https://github.com/vectorize-io/hindsight/commit/f7ff32d))
|
||||
|
||||
**Improvements**
|
||||
|
||||
- Improve the API health check endpoint and update the generated client APIs/types accordingly. ([`e06a612`](https://github.com/vectorize-io/hindsight/commit/e06a612))
|
||||
|
||||
## [0.1.14](https://github.com/vectorize-io/hindsight/releases/tag/v0.1.14)
|
||||
|
||||
**Bug Fixes**
|
||||
|
||||
- Fixes the embedded “get-skill” installer so installing skills works correctly. ([`0b352d1`](https://github.com/vectorize-io/hindsight/commit/0b352d1))
|
||||
|
||||
## [0.1.13](https://github.com/vectorize-io/hindsight/releases/tag/v0.1.13)
|
||||
|
||||
**Improvements**
|
||||
|
||||
- Improve reliability by surfacing task handler failures so retries can occur when processing fails. ([`904ea4d`](https://github.com/vectorize-io/hindsight/commit/904ea4d))
|
||||
- Revamp the hindsight-embed component architecture, including a new daemon/client model and CLI updates for embedding workflows. ([`e6511e7`](https://github.com/vectorize-io/hindsight/commit/e6511e7))
|
||||
|
||||
**Bug Fixes**
|
||||
|
||||
- Fix memory retention so timestamps are correctly taken into account. ([`234d426`](https://github.com/vectorize-io/hindsight/commit/234d426))
|
||||
|
||||
## [0.1.12](https://github.com/vectorize-io/hindsight/releases/tag/v0.1.12)
|
||||
|
||||
**Features**
|
||||
|
||||
- Added an extensions system for plugging in new operations/skills (including built-in tenant support). ([`2a0c490`](https://github.com/vectorize-io/hindsight/commit/2a0c490))
|
||||
- Introduced the hindsight-embed tool and a native agentic skill for embedding/agent workflows. ([`da44a5e`](https://github.com/vectorize-io/hindsight/commit/da44a5e))
|
||||
|
||||
**Improvements**
|
||||
|
||||
- Improved reliability when parsing LLM JSON by retrying on parse errors and adding clearer diagnostics. ([`a831a7b`](https://github.com/vectorize-io/hindsight/commit/a831a7b))
|
||||
|
||||
**Bug Fixes**
|
||||
|
||||
- Fixed structured-output support for Ollama-based LLM providers. ([`32bca12`](https://github.com/vectorize-io/hindsight/commit/32bca12))
|
||||
- Adjusted LLM validation to cap max completion tokens at 100 to prevent validation failures. ([`b94b5cf`](https://github.com/vectorize-io/hindsight/commit/b94b5cf))
|
||||
|
||||
## [0.1.11](https://github.com/vectorize-io/hindsight/releases/tag/v0.1.11)
|
||||
|
||||
**Bug Fixes**
|
||||
|
||||
- Fixed the standalone Docker image and control plane standalone build process so standalone deployments build correctly. ([`2948cb6`](https://github.com/vectorize-io/hindsight/commit/2948cb6))
|
||||
|
||||
## [0.1.10](https://github.com/vectorize-io/hindsight/releases/tag/v0.1.10)
|
||||
|
||||
*This release contains internal maintenance and infrastructure changes only.*
|
||||
|
||||
|
||||
## [0.1.9](https://github.com/vectorize-io/hindsight/releases/tag/v0.1.9)
|
||||
|
||||
**Features**
|
||||
|
||||
- Simplified local MCP installation and added a standalone UI option for easier setup. ([`1c6acc3`](https://github.com/vectorize-io/hindsight/commit/1c6acc3))
|
||||
|
||||
**Bug Fixes**
|
||||
|
||||
- Fixed the standalone Docker image so it builds and starts reliably. ([`b52eb90`](https://github.com/vectorize-io/hindsight/commit/b52eb90))
|
||||
- Improved Docker runtime reliability by adding required system utilities (procps). ([`ae80876`](https://github.com/vectorize-io/hindsight/commit/ae80876))
|
||||
|
||||
## [0.1.8](https://github.com/vectorize-io/hindsight/releases/tag/v0.1.8)
|
||||
|
||||
**Bug Fixes**
|
||||
|
||||
- Fix bank list responses when a bank has no name. ([`04f01ab`](https://github.com/vectorize-io/hindsight/commit/04f01ab))
|
||||
- Fix failures when retaining memories asynchronously. ([`63f5138`](https://github.com/vectorize-io/hindsight/commit/63f5138))
|
||||
- Fix a race condition in the bank selector when switching banks. ([`e468a4e`](https://github.com/vectorize-io/hindsight/commit/e468a4e))
|
||||
|
||||
## [0.1.7](https://github.com/vectorize-io/hindsight/releases/tag/v0.1.7)
|
||||
|
||||
*This release contains internal maintenance and infrastructure changes only.*
|
||||
|
||||
## [0.1.6](https://github.com/vectorize-io/hindsight/releases/tag/v0.1.6)
|
||||
|
||||
**Features**
|
||||
|
||||
- Added support for the Gemini 3 Pro and GPT-5.2 models. ([`bb1f9cb`](https://github.com/vectorize-io/hindsight/commit/bb1f9cb))
|
||||
- Added a local MCP server option for running/connecting to Hindsight via MCP without a separate remote service. ([`7dd6853`](https://github.com/vectorize-io/hindsight/commit/7dd6853))
|
||||
|
||||
**Improvements**
|
||||
|
||||
- Updated the Postgres/pg0 dependency to a newer 0.11.x series for improved compatibility and stability. ([`47be07f`](https://github.com/vectorize-io/hindsight/commit/47be07f))
|
||||
|
||||
## [0.1.5](https://github.com/vectorize-io/hindsight/releases/tag/v0.1.5)
|
||||
|
||||
**Features**
|
||||
|
||||
- Added LiteLLM integration so Hindsight can capture and manage memories from LiteLLM-based LLM calls. ([`dfccbf2`](https://github.com/vectorize-io/hindsight/commit/dfccbf2))
|
||||
- Added an optional graph-based retriever (MPFP) to improve recall by leveraging relationships between memories. ([`7445cef`](https://github.com/vectorize-io/hindsight/commit/7445cef))
|
||||
|
||||
**Improvements**
|
||||
|
||||
- Switched the embedded Postgres layer to pg0-embedded for a smoother local/standalone experience. ([`94c2b85`](https://github.com/vectorize-io/hindsight/commit/94c2b85))
|
||||
|
||||
**Bug Fixes**
|
||||
|
||||
- Fixed repeated retries on 400 errors from the LLM, preventing unnecessary request loops and failures. ([`70983f5`](https://github.com/vectorize-io/hindsight/commit/70983f5))
|
||||
- Fixed recall trace visualization in the control plane so search/recall debugging displays correctly. ([`922164e`](https://github.com/vectorize-io/hindsight/commit/922164e))
|
||||
- Fixed the CLI installer to make installation more reliable. ([`158a6aa`](https://github.com/vectorize-io/hindsight/commit/158a6aa))
|
||||
- Updated Next.js to patch security vulnerabilities (CVE-2025-55184, CVE-2025-55183). ([`f018cc5`](https://github.com/vectorize-io/hindsight/commit/f018cc5))
|
||||
|
||||
## [0.1.3](https://github.com/vectorize-io/hindsight/releases/tag/v0.1.3)
|
||||
|
||||
**Improvements**
|
||||
|
||||
- Improved CLI and UI branding/polish, including new banner/logo assets and updated interface styling. ([`fa554b8`](https://github.com/vectorize-io/hindsight/commit/fa554b8))
|
||||
|
||||
|
||||
## [0.1.2](https://github.com/vectorize-io/hindsight/releases/tag/v0.1.2)
|
||||
|
||||
**Bug Fixes**
|
||||
|
||||
- Fixed the standalone Docker image so it builds/runs correctly. ([`1056a20`](https://github.com/vectorize-io/hindsight/commit/1056a20))
|
||||
|
|
@ -114,7 +114,6 @@ These traits only affect the `reflect` operation, not `recall`.
|
|||
- [**Recall**](/developer/api/recall) — Search and retrieve memories
|
||||
- [**Reflect**](/developer/api/reflect) — Reason with disposition
|
||||
- [**Memory Banks**](/developer/api/memory-banks) — Configure disposition and background
|
||||
- [**Entities**](/developer/api/entities) — Track people, places, and concepts
|
||||
- [**Documents**](/developer/api/documents) — Manage document sources
|
||||
- [**Operations**](/developer/api/operations) — Monitor async tasks
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,315 @@
|
|||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# OpenAI Agent + Hindsight Memory Integration
|
||||
|
||||
|
||||
:::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)
|
||||
:::
|
||||
|
||||
|
||||
A fitness coach example demonstrating how to use **OpenAI Agents** with **Hindsight as a memory backend**.
|
||||
|
||||
## What This Demonstrates
|
||||
|
||||
This example showcases:
|
||||
|
||||
- **OpenAI Assistants** handling conversation logic
|
||||
- **Hindsight** providing sophisticated memory storage & retrieval
|
||||
- **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
|
||||
- **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
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
User: "I ran 5K today, don't like tempo runs"
|
||||
|
|
||||
OpenAI Assistant
|
||||
|
|
||||
Function Call: store_memory(workout + preference)
|
||||
|
|
||||
Hindsight API (stores as world/agent)
|
||||
|
|
||||
OpenAI Assistant: "What should I focus on?"
|
||||
|
|
||||
Function Call: retrieve_memories("workouts and preferences")
|
||||
|
|
||||
Hindsight API (returns workouts + preferences)
|
||||
|
|
||||
OpenAI Assistant (analyzes, gives advice)
|
||||
|
|
||||
Function Call: store_memory(advice as experience)
|
||||
|
|
||||
Hindsight API (stores coach's advice, consolidates into observations)
|
||||
|
|
||||
Personalized Answer
|
||||
```
|
||||
|
||||
## Key Difference from Standard Demo
|
||||
|
||||
| Component | Standard Demo | OpenAI Integration |
|
||||
|-----------|---------------|-------------------|
|
||||
| **Conversation** | Hindsight `/reflect` 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 |
|
||||
| **Best For** | Hindsight-native apps | Integrating memory into existing OpenAI agents |
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Prerequisites
|
||||
|
||||
1. **OpenAI API Key**
|
||||
```bash
|
||||
export OPENAI_API_KEY=your_openai_api_key
|
||||
```
|
||||
|
||||
2. **Hindsight API running**
|
||||
```bash
|
||||
# Follow Hindsight setup instructions to start the API
|
||||
# Default: http://localhost:8888
|
||||
```
|
||||
|
||||
3. **Install dependencies**
|
||||
```bash
|
||||
pip install openai requests
|
||||
```
|
||||
|
||||
### Run the Conversational Demo
|
||||
|
||||
```bash
|
||||
cd openai-fitness-coach
|
||||
export OPENAI_API_KEY=your_key_here
|
||||
python demo_conversational.py
|
||||
```
|
||||
|
||||
The demo showcases:
|
||||
1. **Natural language workout logging** - Tell the coach what you did conversationally
|
||||
2. **Preference learning** - Express likes/dislikes and watch the coach adapt
|
||||
3. **Goal tracking** - Set goals, track progress, achieve milestones
|
||||
4. **Bidirectional memory** - Both your activities AND coach's advice are stored
|
||||
5. **Streaming responses** - See responses appear in real-time
|
||||
6. **7 interactive phases** - From goal setting to achievement recognition
|
||||
|
||||
The demo uses a separate agent (`fitness-coach-demo`) to avoid mixing with real data.
|
||||
|
||||
## Usage
|
||||
|
||||
### Chat with Your Coach
|
||||
|
||||
**Interactive mode:**
|
||||
```bash
|
||||
python openai_coach.py
|
||||
```
|
||||
|
||||
**Single question:**
|
||||
```bash
|
||||
python openai_coach.py "What did I do for training this week?"
|
||||
```
|
||||
|
||||
## How It Works
|
||||
|
||||
### 1. Memory Tools (`memory_tools.py`)
|
||||
|
||||
Defines function tools that the OpenAI Agent can call:
|
||||
|
||||
```python
|
||||
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
|
||||
```
|
||||
|
||||
Each function makes API calls to Hindsight to fetch relevant memories.
|
||||
|
||||
### 2. OpenAI Agent (`openai_coach.py`)
|
||||
|
||||
Creates an OpenAI Assistant with:
|
||||
- Fitness coaching instructions
|
||||
- Access to memory function tools
|
||||
- Conversation management
|
||||
|
||||
When you ask a question:
|
||||
1. User message is sent to OpenAI Assistant
|
||||
2. Assistant decides which memory functions to call
|
||||
3. Functions fetch data from Hindsight
|
||||
4. Assistant generates response using retrieved context
|
||||
|
||||
### 3. Function Calling Flow
|
||||
|
||||
```python
|
||||
# User asks: "What did I run this week?"
|
||||
|
||||
# OpenAI Assistant decides to call:
|
||||
search_workouts(
|
||||
after_date="2024-11-18",
|
||||
workout_type="running"
|
||||
)
|
||||
|
||||
# Function retrieves from Hindsight:
|
||||
{
|
||||
"results": [
|
||||
{"text": "User completed 45-minute cardio workout: running..."},
|
||||
{"text": "User completed 60-minute cardio workout: running..."}
|
||||
]
|
||||
}
|
||||
|
||||
# OpenAI Assistant generates response:
|
||||
"This week you've done two runs: a 45-minute run on Monday
|
||||
and a longer 60-minute run on Wednesday. Great consistency!"
|
||||
```
|
||||
|
||||
## Example Questions
|
||||
|
||||
Try asking:
|
||||
|
||||
```bash
|
||||
python openai_coach.py "What does my training look like this week?"
|
||||
python openai_coach.py "Based on my workouts, should I rest today?"
|
||||
python openai_coach.py "How is my nutrition supporting my goals?"
|
||||
python openai_coach.py "What's my progress toward my goal?"
|
||||
python openai_coach.py "Compare my training this month to last month"
|
||||
```
|
||||
|
||||
The agent will automatically:
|
||||
1. Identify what memories it needs
|
||||
2. Call the appropriate function tools
|
||||
3. Retrieve data from Hindsight
|
||||
4. Generate a personalized response
|
||||
|
||||
## Memory Types Retrieved
|
||||
|
||||
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
|
||||
|
||||
## Customization
|
||||
|
||||
### Add New Function Tools
|
||||
|
||||
Edit `memory_tools.py` to add new capabilities:
|
||||
|
||||
```python
|
||||
def get_weekly_summary(week_offset: int = 0):
|
||||
"""Get a summary of a specific week."""
|
||||
# Implementation
|
||||
pass
|
||||
|
||||
# Add to MEMORY_TOOLS list
|
||||
MEMORY_TOOLS.append({
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "get_weekly_summary",
|
||||
"description": "Get training summary for a specific week",
|
||||
# ... parameters
|
||||
}
|
||||
})
|
||||
|
||||
# Add to FUNCTION_MAP
|
||||
FUNCTION_MAP["get_weekly_summary"] = get_weekly_summary
|
||||
```
|
||||
|
||||
### Modify Assistant Instructions
|
||||
|
||||
Edit `openai_coach.py` to change the coach's personality or behavior:
|
||||
|
||||
```python
|
||||
assistant = client.beta.assistants.create(
|
||||
name="Your Custom Coach",
|
||||
instructions="Your custom instructions here...",
|
||||
model="gpt-4o-mini",
|
||||
tools=MEMORY_TOOLS
|
||||
)
|
||||
```
|
||||
|
||||
## Use Cases
|
||||
|
||||
This pattern works for any application that needs memory:
|
||||
|
||||
1. **Customer Support Agents** - Remember past conversations and issues
|
||||
2. **Personal Assistants** - Remember preferences, schedules, past decisions
|
||||
3. **Educational Tutors** - Track learning progress over time
|
||||
4. **Health Coaches** - Monitor habits, progress, goals (like this example)
|
||||
5. **Sales Assistants** - Remember customer interactions and preferences
|
||||
|
||||
## Integration Pattern
|
||||
|
||||
**To add Hindsight memory to your own OpenAI Agent:**
|
||||
|
||||
1. Define function tools that call Hindsight API
|
||||
2. Register them with your OpenAI Assistant
|
||||
3. Implement function handlers to execute Hindsight queries
|
||||
4. Let OpenAI Assistant decide when to retrieve memories
|
||||
|
||||
The key benefit: **Separation of concerns**
|
||||
- OpenAI = Conversation logic
|
||||
- Hindsight = Memory storage, retrieval, temporal queries, entity linking
|
||||
|
||||
## When to Use This vs. Standard Hindsight
|
||||
|
||||
**Use OpenAI + Hindsight (this example) when:**
|
||||
- You want OpenAI's conversation capabilities
|
||||
- You're already using OpenAI Agents
|
||||
- You want explicit control over when to retrieve memories
|
||||
- You want to combine Hindsight with other OpenAI features
|
||||
|
||||
**Use Hindsight directly when:**
|
||||
- You want a complete memory-first solution
|
||||
- You want automatic memory retrieval and observation consolidation
|
||||
- You want to use different LLM providers (not just OpenAI)
|
||||
- You want the `/reflect` endpoint's integrated approach
|
||||
|
||||
## Learning Points
|
||||
|
||||
After running this demo, you'll understand:
|
||||
|
||||
1. How to add sophisticated memory to any OpenAI Agent
|
||||
2. How function calling bridges LLMs and memory systems
|
||||
3. How temporal-semantic queries work via function tools
|
||||
4. Real-world pattern for LLM + memory integration
|
||||
|
||||
## Core Files
|
||||
|
||||
- `demo_conversational.py` - Conversational demo showcasing preference learning and goal tracking
|
||||
- `openai_coach.py` - OpenAI Assistant wrapper with streaming and memory integration
|
||||
- `memory_tools.py` - Function calling tools that bridge to Hindsight API
|
||||
- `.openai_assistant_id` - Saved assistant ID (auto-generated, gitignored)
|
||||
|
||||
## Common Issues
|
||||
|
||||
**"OPENAI_API_KEY not set"**
|
||||
```bash
|
||||
export OPENAI_API_KEY=your_api_key_here
|
||||
```
|
||||
|
||||
**"Agent not found"**
|
||||
- Make sure the Hindsight fitness-coach agent exists
|
||||
|
||||
**"Connection refused"**
|
||||
- Make sure Hindsight API is running on localhost:8888
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. Run the demo to see it in action
|
||||
2. Try chatting with the coach: `python openai_coach.py`
|
||||
3. Log your own workouts and meals
|
||||
4. Experiment with different questions
|
||||
5. Add custom function tools for your use case
|
||||
|
||||
---
|
||||
|
||||
**Built with:**
|
||||
- OpenAI Assistants API
|
||||
- Hindsight (temporal-semantic memory)
|
||||
- Function calling for integration
|
||||
27
hindsight-docs/versioned_docs/version-0.4/cookbook/index.mdx
Normal file
27
hindsight-docs/versioned_docs/version-0.4/cookbook/index.mdx
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
import RecipeCarousel from '@site/src/components/RecipeCarousel';
|
||||
|
||||
# Cookbook
|
||||
|
||||
Practical patterns, recipes, and complete applications for building with Hindsight.
|
||||
|
||||
<RecipeCarousel
|
||||
title="Recipes"
|
||||
items={[
|
||||
{ title: "Hindsight Quickstart", href: "/cookbook/recipes/quickstart" },
|
||||
{ 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" }
|
||||
]}
|
||||
/>
|
||||
|
||||
<RecipeCarousel
|
||||
title="Applications"
|
||||
items={[
|
||||
{ title: "OpenAI Agent + Hindsight Memory Integration", href: "/cookbook/applications/openai-fitness-coach" }
|
||||
]}
|
||||
/>
|
||||
|
|
@ -0,0 +1,187 @@
|
|||
---
|
||||
sidebar_position: 4
|
||||
---
|
||||
|
||||
# Memory with LiteLLM
|
||||
|
||||
|
||||
:::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/04-litellm-memory-demo.ipynb)
|
||||
:::
|
||||
|
||||
|
||||
This notebook demonstrates how to add persistent memory to any LLM app using the `hindsight-litellm` package. Memory storage and injection happen automatically via LiteLLM callbacks - no manual memory management needed!
|
||||
|
||||
**Key features demonstrated:**
|
||||
1. `configure()` + `enable()` - Set up automatic memory integration
|
||||
2. Automatic storage - Conversations are stored after each LLM call
|
||||
3. Automatic injection - Relevant memories are injected into prompts
|
||||
|
||||
The `hindsight-litellm` package hooks into LiteLLM's callback system to:
|
||||
- Store each conversation after successful LLM responses
|
||||
- Inject relevant memories into the system prompt before LLM calls
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Make sure you have Hindsight running:
|
||||
|
||||
```bash
|
||||
export OPENAI_API_KEY=your-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=o3-mini \
|
||||
-v $HOME/.hindsight-docker:/home/hindsight/.pg0 \
|
||||
ghcr.io/vectorize-io/hindsight:latest
|
||||
```
|
||||
|
||||
- API: http://localhost:8888
|
||||
- UI: http://localhost:9999
|
||||
|
||||
## Installation
|
||||
|
||||
|
||||
```python
|
||||
!pip install hindsight-litellm litellm nest_asyncio python-dotenv -U -q
|
||||
```
|
||||
|
||||
## Setup
|
||||
|
||||
|
||||
```python
|
||||
import os
|
||||
import uuid
|
||||
import time
|
||||
import logging
|
||||
import nest_asyncio
|
||||
from dotenv import load_dotenv
|
||||
|
||||
# Apply nest_asyncio for Jupyter compatibility
|
||||
nest_asyncio.apply()
|
||||
|
||||
# Load environment variables
|
||||
load_dotenv()
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logging.getLogger("LiteLLM").setLevel(logging.WARNING)
|
||||
logging.getLogger("LiteLLM Router").setLevel(logging.WARNING)
|
||||
logging.getLogger("LiteLLM Proxy").setLevel(logging.WARNING)
|
||||
|
||||
# Import hindsight_litellm
|
||||
import hindsight_litellm
|
||||
|
||||
# Configuration
|
||||
HINDSIGHT_API_URL = os.getenv("HINDSIGHT_API_URL", "http://localhost:8888")
|
||||
|
||||
# Check for API key
|
||||
if not os.getenv("OPENAI_API_KEY"):
|
||||
print("Warning: OPENAI_API_KEY not set")
|
||||
```
|
||||
|
||||
## Configure and Enable Automatic Memory
|
||||
|
||||
This is all you need! After this, all LiteLLM calls will automatically:
|
||||
- Have relevant memories injected into the prompt
|
||||
- Store conversations to Hindsight after the response
|
||||
|
||||
|
||||
```python
|
||||
# Generate a unique bank_id for this demo session
|
||||
bank_id = f"demo-{uuid.uuid4().hex[:8]}"
|
||||
print(f"Using bank_id: {bank_id}")
|
||||
|
||||
# Configure and enable hindsight
|
||||
hindsight_litellm.configure(
|
||||
hindsight_api_url=HINDSIGHT_API_URL,
|
||||
bank_id=bank_id,
|
||||
store_conversations=True, # Automatically store conversations
|
||||
inject_memories=True, # Automatically inject relevant memories
|
||||
verbose=True, # Enable logging to debug memory operations
|
||||
)
|
||||
hindsight_litellm.enable()
|
||||
|
||||
print("Hindsight memory integration enabled!")
|
||||
```
|
||||
|
||||
## Conversation 1: User Introduces Themselves
|
||||
|
||||
In this first conversation, the user shares some information about themselves. This will be automatically stored to Hindsight memory.
|
||||
|
||||
|
||||
```python
|
||||
user_message_1 = "Hi! I'm Alex and I work at Google as a software engineer. I love Python and machine learning."
|
||||
print(f"User: {user_message_1}\n")
|
||||
|
||||
# Use hindsight_litellm.completion() directly
|
||||
response_1 = hindsight_litellm.completion(
|
||||
model="gpt-4o-mini",
|
||||
messages=[
|
||||
{"role": "system", "content": "You are a helpful assistant."},
|
||||
{"role": "user", "content": user_message_1}
|
||||
],
|
||||
)
|
||||
|
||||
assistant_response_1 = response_1.choices[0].message.content
|
||||
print(f"Assistant: {assistant_response_1}")
|
||||
print("\n(Conversation automatically stored to Hindsight)")
|
||||
```
|
||||
|
||||
## Wait for Memory Processing
|
||||
|
||||
Hindsight needs a few seconds to process and extract facts from the conversation.
|
||||
|
||||
|
||||
```python
|
||||
print("Waiting 12 seconds for memory processing...")
|
||||
time.sleep(12)
|
||||
print("Done!")
|
||||
```
|
||||
|
||||
## Conversation 2: Test Memory-Augmented Response
|
||||
|
||||
Now we start a fresh conversation and ask what the assistant remembers. The memories from the previous conversation will be automatically injected into the prompt!
|
||||
|
||||
|
||||
```python
|
||||
user_message_2 = "What do you know about me? What programming language should I use for my next project?"
|
||||
print(f"User: {user_message_2}\n")
|
||||
|
||||
# Memories are automatically injected before this call!
|
||||
response_2 = hindsight_litellm.completion(
|
||||
model="gpt-4o-mini",
|
||||
messages=[
|
||||
{"role": "system", "content": "You are a helpful assistant."},
|
||||
{"role": "user", "content": user_message_2}
|
||||
],
|
||||
)
|
||||
|
||||
print(f"Assistant: {response_2.choices[0].message.content}")
|
||||
```
|
||||
|
||||
## Summary
|
||||
|
||||
The assistant should have remembered that Alex:
|
||||
- Works at Google as a software engineer
|
||||
- Loves Python and machine learning
|
||||
|
||||
And it should have recommended Python based on that knowledge!
|
||||
|
||||
|
||||
```python
|
||||
print(f"Memories stored in bank: {bank_id}")
|
||||
print(f"View in UI: http://localhost:9999/banks/{bank_id}")
|
||||
```
|
||||
|
||||
## Cleanup
|
||||
|
||||
|
||||
```python
|
||||
hindsight_litellm.cleanup()
|
||||
|
||||
# Optional: delete the bank
|
||||
import requests
|
||||
response = requests.delete(f"{HINDSIGHT_API_URL}/v1/default/banks/{bank_id}")
|
||||
print(f"Deleted bank: {response.json()}")
|
||||
```
|
||||
|
|
@ -0,0 +1,247 @@
|
|||
---
|
||||
sidebar_position: 2
|
||||
---
|
||||
|
||||
# Per-User 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/02-per-user-memory.ipynb)
|
||||
:::
|
||||
|
||||
|
||||
The simplest pattern: give your agent persistent memory for each user. The agent remembers past conversations, user preferences, and context across sessions.
|
||||
|
||||
## The Problem
|
||||
|
||||
Without memory, every conversation starts from scratch:
|
||||
|
||||
```
|
||||
Session 1: "I prefer dark mode and use Python"
|
||||
Session 2: "What's my preferred language?" → Agent doesn't know
|
||||
```
|
||||
|
||||
## The Solution: One Bank Per User
|
||||
|
||||
```
|
||||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||||
│ User A Bank │ │ User B Bank │ │ User C Bank │
|
||||
│ │ │ │ │ │
|
||||
│ - Conversations│ │ - Conversations│ │ - Conversations│
|
||||
│ - Preferences │ │ - Preferences │ │ - Preferences │
|
||||
│ - Context │ │ - Context │ │ - Context │
|
||||
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
||||
│ │ │
|
||||
100% isolated 100% isolated 100% isolated
|
||||
```
|
||||
|
||||
Each user gets their own memory bank. Complete isolation, simple mental model.
|
||||
|
||||
|
||||
```python
|
||||
!pip install hindsight-client nest_asyncio openai python-dotenv -U
|
||||
```
|
||||
|
||||
## 1. Create a Bank When User Signs Up
|
||||
|
||||
|
||||
```python
|
||||
# Jupyter notebooks already run an asyncio event loop. The hindsight client
|
||||
# uses loop.run_until_complete() internally, but Python doesn't allow nested
|
||||
# event loops by default. nest_asyncio patches this to allow nesting.
|
||||
import nest_asyncio
|
||||
nest_asyncio.apply()
|
||||
|
||||
import os
|
||||
from dotenv import load_dotenv
|
||||
from openai import OpenAI as OpenAIClient
|
||||
|
||||
# Load environment variables from .env file
|
||||
# Copy .env.example to .env and fill in your values
|
||||
load_dotenv()
|
||||
|
||||
# Configuration (override with env vars if set)
|
||||
HINDSIGHT_API_URL = os.getenv("HINDSIGHT_API_URL", "http://localhost:8888")
|
||||
HINDSIGHT_UI_URL = os.getenv("HINDSIGHT_UI_URL", "http://localhost:9999")
|
||||
|
||||
from hindsight_client import Hindsight
|
||||
|
||||
client = Hindsight(base_url=HINDSIGHT_API_URL)
|
||||
llm = OpenAIClient() # Uses OPENAI_API_KEY from .env
|
||||
|
||||
def on_user_signup(user_id: str):
|
||||
client.create_bank(
|
||||
bank_id=f"user-{user_id}",
|
||||
name=f"Memory for {user_id}"
|
||||
)
|
||||
print(f"View bank: {HINDSIGHT_UI_URL}/banks/user-{user_id}?view=documents")
|
||||
```
|
||||
|
||||
## 2. Manage Conversation Sessions
|
||||
|
||||
Use `document_id` to group messages belonging to the same conversation. When you retain with the same `document_id`, Hindsight replaces the previous version (upsert behavior), keeping the memory up-to-date as the conversation evolves.
|
||||
|
||||
|
||||
```python
|
||||
import uuid
|
||||
import json
|
||||
|
||||
class ConversationSession:
|
||||
def __init__(self, user_id: str):
|
||||
self.user_id = user_id
|
||||
self.session_id = str(uuid.uuid4()) # Unique ID for this conversation
|
||||
self.messages = []
|
||||
|
||||
def add_message(self, role: str, content: str):
|
||||
self.messages.append({"role": role, "content": content})
|
||||
|
||||
def save(self, client: Hindsight):
|
||||
"""Save the entire conversation. Replaces previous version if session_id exists."""
|
||||
# Convert messages to string format for retain
|
||||
content = "\n".join([f"{m['role']}: {m['content']}" for m in self.messages])
|
||||
client.retain(
|
||||
bank_id=f"user-{self.user_id}",
|
||||
content=content,
|
||||
document_id=self.session_id # Same ID = upsert (replace old version)
|
||||
)
|
||||
```
|
||||
|
||||
## 3. Recall Context Before Responding
|
||||
|
||||
|
||||
```python
|
||||
def get_context(user_id: str, query: str):
|
||||
result = client.recall(
|
||||
bank_id=f"user-{user_id}",
|
||||
query=query
|
||||
)
|
||||
return result.results
|
||||
```
|
||||
|
||||
## 4. Complete Agent Loop
|
||||
|
||||
|
||||
```python
|
||||
def format_results(results):
|
||||
"""Format recall results for the prompt."""
|
||||
if not results:
|
||||
return "No relevant memories found."
|
||||
return "\n".join([f"- {r.text}" for r in results])
|
||||
|
||||
def format_messages(messages):
|
||||
"""Format conversation messages for the prompt."""
|
||||
return "\n".join([f"{m['role']}: {m['content']}" for m in messages])
|
||||
|
||||
def handle_message(session: ConversationSession, user_message: str):
|
||||
# 1. Add user message to session
|
||||
session.add_message("user", user_message)
|
||||
|
||||
# 2. Recall relevant context from past conversations
|
||||
context = client.recall(
|
||||
bank_id=f"user-{session.user_id}",
|
||||
query=user_message
|
||||
)
|
||||
|
||||
# 3. Build system prompt with memory
|
||||
system_prompt = f"""You are a helpful assistant with memory of past conversations.
|
||||
|
||||
## What you remember about this user
|
||||
{format_results(context.results)}
|
||||
|
||||
Respond helpfully and reference relevant memories when appropriate."""
|
||||
|
||||
# 4. Generate response using OpenAI
|
||||
response = llm.chat.completions.create(
|
||||
model="gpt-4o-mini",
|
||||
messages=[
|
||||
{"role": "system", "content": system_prompt},
|
||||
*[{"role": m["role"], "content": m["content"]} for m in session.messages]
|
||||
]
|
||||
)
|
||||
assistant_response = response.choices[0].message.content
|
||||
|
||||
# 5. Add assistant response to session
|
||||
session.add_message("assistant", assistant_response)
|
||||
|
||||
# 6. Save the updated conversation (upserts based on session_id)
|
||||
session.save(client)
|
||||
|
||||
print(f"User: {user_message}")
|
||||
print(f"Assistant: {assistant_response}\n")
|
||||
|
||||
return assistant_response
|
||||
```
|
||||
|
||||
## 5. Starting a New Conversation
|
||||
|
||||
|
||||
```python
|
||||
# Create the user's bank
|
||||
on_user_signup("alice")
|
||||
|
||||
# Each new conversation gets a new session with a unique ID
|
||||
session = ConversationSession(user_id="alice")
|
||||
|
||||
# Multiple exchanges in the same conversation
|
||||
handle_message(session, "Hi! I'm working on a Python project")
|
||||
handle_message(session, "Can you help me with async/await?")
|
||||
|
||||
# View the stored conversation in the UI.
|
||||
# Each message updates the same document (via document_id), so you'll see
|
||||
# the full conversation history in a single document rather than separate entries.
|
||||
print(f"\nView documents: {HINDSIGHT_UI_URL}/banks/user-alice?view=documents")
|
||||
```
|
||||
|
||||
## How Document ID Works
|
||||
|
||||
The `document_id` parameter is key to managing evolving conversations:
|
||||
|
||||
| Scenario | Behavior |
|
||||
|----------|----------|
|
||||
| First retain with `document_id="session_123"` | Creates new document |
|
||||
| Retain again with same `document_id="session_123"` | **Replaces** previous version (upsert) |
|
||||
| Retain with different `document_id="session_456"` | Creates separate document |
|
||||
| Retain without `document_id` | Creates new document each time |
|
||||
|
||||
This upsert behavior means:
|
||||
- You always retain the **full conversation** state
|
||||
- Facts are re-extracted from the complete conversation
|
||||
- No duplicate or stale facts from old versions
|
||||
- Memory stays consistent as conversations evolve
|
||||
|
||||
## What Gets Remembered
|
||||
|
||||
Hindsight automatically extracts and connects:
|
||||
|
||||
- **Facts**: "User prefers Python", "User is building a CLI tool"
|
||||
- **Entities**: People, projects, technologies mentioned
|
||||
- **Relationships**: How entities relate to each other
|
||||
- **Temporal context**: When things happened
|
||||
|
||||
You don't need to manually extract or structure this - just retain the conversations.
|
||||
|
||||
## When to Use This Pattern
|
||||
|
||||
**Good fit:**
|
||||
- Chatbots and assistants
|
||||
- Personal AI companions
|
||||
- Any 1:1 user-to-agent interaction
|
||||
|
||||
**Consider adding shared knowledge if:**
|
||||
- You have product docs or FAQs to reference
|
||||
- Multiple users need access to the same information
|
||||
- See the Support Agent with Shared Knowledge notebook
|
||||
|
||||
## Cleanup
|
||||
|
||||
Delete the banks created during this notebook:
|
||||
|
||||
|
||||
```python
|
||||
import requests
|
||||
|
||||
# Delete the user-alice bank
|
||||
response = requests.delete(f"{HINDSIGHT_API_URL}/v1/default/banks/user-alice")
|
||||
print(f"Deleted user-alice: {response.json()}")
|
||||
```
|
||||
|
|
@ -0,0 +1,161 @@
|
|||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# Hindsight Quickstart
|
||||
|
||||
|
||||
:::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/01-quickstart.ipynb)
|
||||
:::
|
||||
|
||||
|
||||
This notebook covers the basics of using Hindsight:
|
||||
- **Retain**: Store information in memory
|
||||
- **Recall**: Retrieve memories matching a query
|
||||
- **Reflect**: Generate insights from memories
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Make sure you have Hindsight running. The easiest way is via Docker:
|
||||
|
||||
```bash
|
||||
export OPENAI_API_KEY=your-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=o3-mini \
|
||||
-v $HOME/.hindsight-docker:/home/hindsight/.pg0 \
|
||||
ghcr.io/vectorize-io/hindsight:latest
|
||||
```
|
||||
|
||||
- API: http://localhost:8888
|
||||
- UI: http://localhost:9999
|
||||
|
||||
## Installation
|
||||
|
||||
Install the Hindsight Python client:
|
||||
|
||||
|
||||
```python
|
||||
!pip install hindsight-client nest_asyncio python-dotenv -U
|
||||
```
|
||||
|
||||
## Connect to Hindsight
|
||||
|
||||
|
||||
```python
|
||||
# Jupyter notebooks already run an asyncio event loop. The hindsight client
|
||||
# uses loop.run_until_complete() internally, but Python doesn't allow nested
|
||||
# event loops by default. nest_asyncio patches this to allow nesting.
|
||||
import nest_asyncio
|
||||
nest_asyncio.apply()
|
||||
|
||||
import os
|
||||
from dotenv import load_dotenv
|
||||
|
||||
# Load environment variables from .env file
|
||||
# Copy .env.example to .env and fill in your values
|
||||
load_dotenv()
|
||||
|
||||
# Configuration (override with env vars if set)
|
||||
HINDSIGHT_API_URL = os.getenv("HINDSIGHT_API_URL", "http://localhost:8888")
|
||||
HINDSIGHT_UI_URL = os.getenv("HINDSIGHT_UI_URL", "http://localhost:9999")
|
||||
|
||||
from hindsight_client import Hindsight
|
||||
|
||||
client = Hindsight(base_url=HINDSIGHT_API_URL)
|
||||
```
|
||||
|
||||
## Retain: Store Information
|
||||
|
||||
The `retain` operation is used to push new memories into Hindsight. It tells Hindsight to _retain_ the information you pass in.
|
||||
|
||||
Behind the scenes, the retain operation uses an LLM to extract key facts, temporal data, entities, and relationships.
|
||||
|
||||
|
||||
```python
|
||||
# Simple retain
|
||||
client.retain(
|
||||
bank_id="my-bank",
|
||||
content="Alice works at Google as a software engineer"
|
||||
)
|
||||
|
||||
# View the stored document in the UI:
|
||||
print(f"View documents: {HINDSIGHT_UI_URL}/banks/my-bank?view=documents")
|
||||
```
|
||||
|
||||
|
||||
```python
|
||||
# Retain with context and timestamp
|
||||
client.retain(
|
||||
bank_id="my-bank",
|
||||
content="Alice got promoted to senior engineer",
|
||||
context="career update",
|
||||
timestamp="2025-06-15T10:00:00Z"
|
||||
)
|
||||
```
|
||||
|
||||
## Recall: Retrieve Memories
|
||||
|
||||
The `recall` operation retrieves memories matching a query. It performs 4 retrieval strategies in parallel:
|
||||
- **Semantic**: Vector similarity
|
||||
- **Keyword**: BM25 exact matching
|
||||
- **Graph**: Entity/temporal/causal links
|
||||
- **Temporal**: Time range filtering
|
||||
|
||||
|
||||
```python
|
||||
# Simple recall
|
||||
results = client.recall(bank_id="my-bank", query="What does Alice do?")
|
||||
|
||||
print("Memories:")
|
||||
for r in results.results:
|
||||
print(f" - {r.text}")
|
||||
```
|
||||
|
||||
|
||||
```python
|
||||
# Temporal recall
|
||||
results = client.recall(bank_id="my-bank", query="What happened in June?")
|
||||
|
||||
print("Memories:")
|
||||
for r in results.results:
|
||||
print(f" - {r.text}")
|
||||
```
|
||||
|
||||
## 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.
|
||||
|
||||
Example use cases:
|
||||
- An AI Project Manager reflecting on what risks need to be mitigated
|
||||
- A Sales Agent reflecting on why certain outreach messages have gotten responses
|
||||
- A Support Agent reflecting on opportunities where customers have unanswered questions
|
||||
|
||||
|
||||
```python
|
||||
response = client.reflect(bank_id="my-bank", query="What should I know about Alice?")
|
||||
print(response)
|
||||
```
|
||||
|
||||
## Memory Types
|
||||
|
||||
Hindsight organizes knowledge into facts and consolidated observations:
|
||||
|
||||
- **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")
|
||||
|
||||
## Cleanup
|
||||
|
||||
Delete the bank created during this notebook:
|
||||
|
||||
|
||||
```python
|
||||
import requests
|
||||
|
||||
response = requests.delete(f"{HINDSIGHT_API_URL}/v1/default/banks/my-bank")
|
||||
print(f"Deleted my-bank: {response.json()}")
|
||||
```
|
||||
|
|
@ -0,0 +1,315 @@
|
|||
---
|
||||
sidebar_position: 3
|
||||
---
|
||||
|
||||
# Support Agent with Shared Knowledge
|
||||
|
||||
|
||||
:::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/03-support-agent-shared-knowledge.ipynb)
|
||||
:::
|
||||
|
||||
|
||||
This pattern shows how to build a support agent that combines **per-user memory** with **shared product knowledge** (RAG), giving users personalized support while leveraging a single source of truth for documentation.
|
||||
|
||||
## The Problem
|
||||
|
||||
You're building a support agent that needs to:
|
||||
- Remember each user's history, preferences, and past issues
|
||||
- Access shared product documentation
|
||||
- Keep user data completely isolated from other users
|
||||
|
||||
A naive approach would index product docs into each user's memory bank, but this is expensive and wasteful (N copies for N users).
|
||||
|
||||
## The Solution: Multi-Bank Architecture
|
||||
|
||||
```
|
||||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||||
│ User A Bank │ │ User B Bank │ │ Shared Docs │
|
||||
│ │ │ │ │ Bank │
|
||||
│ - Conversations│ │ - Conversations│ │ │
|
||||
│ - Preferences │ │ - Preferences │ │ - Product docs │
|
||||
│ - Past issues │ │ - Past issues │ │ - FAQs │
|
||||
│ - Solutions │ │ - Solutions │ │ - Guides │
|
||||
└────────┬────────┘ └────────┬────────┘ └────────┬────────┘
|
||||
│ │ │
|
||||
└───────────────────────┴───────────────────────┘
|
||||
│
|
||||
Agent queries
|
||||
multiple banks
|
||||
```
|
||||
|
||||
**Key benefits:**
|
||||
- Product docs indexed once, shared by all users
|
||||
- User memory is 100% isolated
|
||||
- Simple mental model, no complex filtering
|
||||
|
||||
|
||||
```python
|
||||
!pip install hindsight-client nest_asyncio openai python-dotenv -U
|
||||
```
|
||||
|
||||
## 1. Set Up Memory Banks
|
||||
|
||||
Create three types of banks:
|
||||
|
||||
|
||||
```python
|
||||
# Jupyter notebooks already run an asyncio event loop. The hindsight client
|
||||
# uses loop.run_until_complete() internally, but Python doesn't allow nested
|
||||
# event loops by default. nest_asyncio patches this to allow nesting.
|
||||
import nest_asyncio
|
||||
nest_asyncio.apply()
|
||||
|
||||
import os
|
||||
from dotenv import load_dotenv
|
||||
from openai import OpenAI as OpenAIClient
|
||||
|
||||
# Load environment variables from .env file
|
||||
# Copy .env.example to .env and fill in your values
|
||||
load_dotenv()
|
||||
|
||||
# Configuration (override with env vars if set)
|
||||
HINDSIGHT_API_URL = os.getenv("HINDSIGHT_API_URL", "http://localhost:8888")
|
||||
HINDSIGHT_UI_URL = os.getenv("HINDSIGHT_UI_URL", "http://localhost:9999")
|
||||
|
||||
from hindsight_client import Hindsight
|
||||
|
||||
client = Hindsight(base_url=HINDSIGHT_API_URL)
|
||||
llm = OpenAIClient() # Uses OPENAI_API_KEY from .env
|
||||
|
||||
# Shared knowledge bank (created once)
|
||||
shared_bank = client.create_bank(
|
||||
bank_id="product-docs",
|
||||
name="Product Documentation"
|
||||
)
|
||||
|
||||
# Per-user banks (created when user signs up)
|
||||
def create_user_bank(user_id: str):
|
||||
return client.create_bank(
|
||||
bank_id=f"user-{user_id}",
|
||||
name=f"Memory for {user_id}"
|
||||
)
|
||||
```
|
||||
|
||||
## 2. Index Product Documentation
|
||||
|
||||
Index your product docs into the shared bank (do this once, or on doc updates):
|
||||
|
||||
|
||||
```python
|
||||
# Index product documentation - retain each doc separately
|
||||
client.retain(
|
||||
bank_id="product-docs",
|
||||
content="# Pricing Tiers\n\nBasic: $10/mo, Pro: $25/mo, Enterprise: Contact us"
|
||||
)
|
||||
|
||||
client.retain(
|
||||
bank_id="product-docs",
|
||||
content="# Getting Started\n\nTo set up your account, visit the dashboard and click 'New Project'"
|
||||
)
|
||||
|
||||
# View the stored documents in the UI:
|
||||
print(f"View documents: {HINDSIGHT_UI_URL}/banks/product-docs?view=documents")
|
||||
```
|
||||
|
||||
## 3. Store User Conversations
|
||||
|
||||
After each support interaction, retain it in the user's bank:
|
||||
|
||||
|
||||
```python
|
||||
def save_conversation(user_id: str, messages: list):
|
||||
# Convert messages to string format
|
||||
content = "\n".join([f"{m['role']}: {m['content']}" for m in messages])
|
||||
client.retain(
|
||||
bank_id=f"user-{user_id}",
|
||||
content=content
|
||||
)
|
||||
```
|
||||
|
||||
## 4. Query Multiple Banks at Support Time
|
||||
|
||||
When handling a user query, retrieve context from both banks:
|
||||
|
||||
|
||||
```python
|
||||
def get_support_context(user_id: str, query: str):
|
||||
# Get user's personal context
|
||||
user_context = client.recall(
|
||||
bank_id=f"user-{user_id}",
|
||||
query=query
|
||||
)
|
||||
|
||||
# Get relevant product documentation
|
||||
docs_context = client.recall(
|
||||
bank_id="product-docs",
|
||||
query=query
|
||||
)
|
||||
|
||||
return {
|
||||
"user_history": user_context.results,
|
||||
"documentation": docs_context.results
|
||||
}
|
||||
```
|
||||
|
||||
## 5. Build the Agent Prompt
|
||||
|
||||
Combine both contexts in your agent's prompt:
|
||||
|
||||
|
||||
```python
|
||||
def format_results(results):
|
||||
"""Format recall results for the prompt."""
|
||||
if not results:
|
||||
return "No relevant information found."
|
||||
return "\n".join([f"- {r.text}" for r in results])
|
||||
|
||||
def build_prompt(query: str, context: dict) -> str:
|
||||
return f"""You are a helpful support agent.
|
||||
|
||||
## User's History
|
||||
{format_results(context["user_history"])}
|
||||
|
||||
## Product Documentation
|
||||
{format_results(context["documentation"])}
|
||||
|
||||
## Current Question
|
||||
{query}
|
||||
|
||||
Use the user's history to personalize your response and the documentation
|
||||
for accurate product information. If you find a solution, remember it for
|
||||
future reference.
|
||||
"""
|
||||
```
|
||||
|
||||
## Promoting Learnings to Shared Knowledge
|
||||
|
||||
When the agent discovers a solution that's not in the docs, you can optionally promote it to a "learnings" bank:
|
||||
|
||||
```
|
||||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||||
│ User A Bank │ │ Shared Docs │ │ Learnings │
|
||||
│ │ │ Bank │ │ Bank │
|
||||
│ - Conversations│ │ │ │ │
|
||||
│ - Preferences │ │ - Product docs │ │ - Verified │
|
||||
│ - Past issues │ │ - FAQs │ │ solutions │
|
||||
│ - Solutions │ │ - Guides │ │ - Workarounds │
|
||||
└────────┬────────┘ └────────┬────────┘ └────────┬────────┘
|
||||
│ │ │
|
||||
└───────────────────────┴───────────────────────┘
|
||||
│
|
||||
Agent queries
|
||||
all three banks
|
||||
```
|
||||
|
||||
|
||||
```python
|
||||
# Optional: Create a curated learnings bank
|
||||
learnings_bank = client.create_bank(
|
||||
bank_id="support-learnings",
|
||||
name="Curated Support Learnings"
|
||||
)
|
||||
|
||||
# After a successful resolution
|
||||
def promote_learning(insight: str):
|
||||
client.retain(
|
||||
bank_id="support-learnings",
|
||||
content=insight
|
||||
)
|
||||
```
|
||||
|
||||
## Complete Example
|
||||
|
||||
|
||||
```python
|
||||
def format_results(results):
|
||||
if not results:
|
||||
return "No relevant information found."
|
||||
return "\n".join([f"- {r.text}" for r in results])
|
||||
|
||||
def handle_support_request(user_id: str, query: str):
|
||||
# 1. Recall from user's memory
|
||||
user_recall = client.recall(
|
||||
bank_id=f"user-{user_id}",
|
||||
query=query
|
||||
)
|
||||
|
||||
# 2. Recall from shared docs
|
||||
docs_recall = client.recall(
|
||||
bank_id="product-docs",
|
||||
query=query
|
||||
)
|
||||
|
||||
# 3. Recall from learnings (optional)
|
||||
learnings_recall = client.recall(
|
||||
bank_id="support-learnings",
|
||||
query=query
|
||||
)
|
||||
|
||||
# 4. Build system prompt with context
|
||||
system_prompt = f"""You are a helpful support agent. Use the context below to answer the user's question.
|
||||
|
||||
## User's History
|
||||
{format_results(user_recall.results)}
|
||||
|
||||
## Product Documentation
|
||||
{format_results(docs_recall.results)}
|
||||
|
||||
## Known Solutions
|
||||
{format_results(learnings_recall.results)}
|
||||
|
||||
Provide helpful, accurate responses based on the documentation. Reference the user's history when relevant."""
|
||||
|
||||
# 5. Generate response using OpenAI
|
||||
response = llm.chat.completions.create(
|
||||
model="gpt-4o-mini",
|
||||
messages=[
|
||||
{"role": "system", "content": system_prompt},
|
||||
{"role": "user", "content": query}
|
||||
]
|
||||
)
|
||||
assistant_response = response.choices[0].message.content
|
||||
|
||||
# 6. Save the conversation to user's memory
|
||||
conversation = f"user: {query}\nassistant: {assistant_response}"
|
||||
client.retain(
|
||||
bank_id=f"user-{user_id}",
|
||||
content=conversation
|
||||
)
|
||||
|
||||
return assistant_response
|
||||
|
||||
# Test the function
|
||||
create_user_bank("bob")
|
||||
print("User: How do I get started?")
|
||||
result = handle_support_request("bob", "How do I get started?")
|
||||
print(f"Assistant: {result}")
|
||||
print(f"\nView user memory: {HINDSIGHT_UI_URL}/banks/user-bob?view=documents")
|
||||
```
|
||||
|
||||
## When to Use This Pattern
|
||||
|
||||
**Good fit:**
|
||||
- Support agents with shared documentation
|
||||
- Multi-tenant applications with shared reference data
|
||||
- Any scenario needing user isolation + shared knowledge
|
||||
|
||||
**Consider alternatives if:**
|
||||
- You need cross-user learning (users benefiting from other users' solutions)
|
||||
- Entity relationships must span across users and docs
|
||||
|
||||
## Cleanup
|
||||
|
||||
Delete the banks created during this notebook:
|
||||
|
||||
|
||||
```python
|
||||
import requests
|
||||
|
||||
# Delete all banks created in this notebook
|
||||
for bank_id in ["product-docs", "support-learnings", "user-bob"]:
|
||||
response = requests.delete(f"{HINDSIGHT_API_URL}/v1/default/banks/{bank_id}")
|
||||
print(f"Deleted {bank_id}: {response.json()}")
|
||||
```
|
||||
|
|
@ -0,0 +1,372 @@
|
|||
---
|
||||
sidebar_position: 5
|
||||
---
|
||||
|
||||
# Routing Tool Learning
|
||||
|
||||
|
||||
:::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/05-tool-learning-demo.ipynb)
|
||||
:::
|
||||
|
||||
|
||||
This notebook demonstrates how Hindsight helps an LLM learn which tool to use when tool names are ambiguous. Without memory, the LLM might randomly select between similarly-named tools. With Hindsight, it learns from past interactions and consistently makes the correct choice.
|
||||
|
||||
## The Scenario
|
||||
|
||||
We have a task routing system with two tools:
|
||||
- `route_to_channel_alpha` - Routes to processing channel Alpha
|
||||
- `route_to_channel_omega` - Routes to processing channel Omega
|
||||
|
||||
The tool names and descriptions are **intentionally vague**. In reality:
|
||||
- Channel Alpha handles **FINANCIAL/PAYMENT** tasks (refunds, billing, etc.)
|
||||
- Channel Omega handles **TECHNICAL/SUPPORT** tasks (bugs, features, etc.)
|
||||
|
||||
**Without Hindsight:** The LLM guesses randomly based on vague descriptions
|
||||
**With Hindsight:** The LLM learns from feedback which channel handles what
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Make sure you have Hindsight running:
|
||||
|
||||
```bash
|
||||
export OPENAI_API_KEY=your-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=o3-mini \
|
||||
-v $HOME/.hindsight-docker:/home/hindsight/.pg0 \
|
||||
ghcr.io/vectorize-io/hindsight:latest
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
|
||||
```python
|
||||
!pip install hindsight-litellm hindsight-client litellm nest_asyncio python-dotenv -U -q
|
||||
```
|
||||
|
||||
## Setup
|
||||
|
||||
|
||||
```python
|
||||
import os
|
||||
import json
|
||||
import uuid
|
||||
import time
|
||||
import logging
|
||||
import nest_asyncio
|
||||
from typing import Optional
|
||||
from dotenv import load_dotenv
|
||||
|
||||
nest_asyncio.apply()
|
||||
load_dotenv()
|
||||
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logging.getLogger("LiteLLM").setLevel(logging.WARNING)
|
||||
logging.getLogger("LiteLLM Router").setLevel(logging.WARNING)
|
||||
logging.getLogger("httpx").setLevel(logging.WARNING)
|
||||
|
||||
import litellm
|
||||
import hindsight_litellm
|
||||
from hindsight_client import Hindsight
|
||||
|
||||
HINDSIGHT_API_URL = os.getenv("HINDSIGHT_API_URL", "http://localhost:8888")
|
||||
|
||||
if not os.getenv("OPENAI_API_KEY"):
|
||||
print("Warning: OPENAI_API_KEY not set")
|
||||
```
|
||||
|
||||
## Define Tools
|
||||
|
||||
These tool definitions are **intentionally ambiguous** - the descriptions don't reveal which channel handles what type of request.
|
||||
|
||||
|
||||
```python
|
||||
TOOLS = [
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "route_to_channel_alpha",
|
||||
"description": "Routes the customer request to processing channel Alpha. Use this channel for appropriate request types.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"request_summary": {
|
||||
"type": "string",
|
||||
"description": "A brief summary of the customer's request"
|
||||
},
|
||||
"priority": {
|
||||
"type": "string",
|
||||
"enum": ["low", "medium", "high"],
|
||||
"description": "Priority level of the request"
|
||||
}
|
||||
},
|
||||
"required": ["request_summary"]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "route_to_channel_omega",
|
||||
"description": "Routes the customer request to processing channel Omega. Use this channel for appropriate request types.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"request_summary": {
|
||||
"type": "string",
|
||||
"description": "A brief summary of the customer's request"
|
||||
},
|
||||
"priority": {
|
||||
"type": "string",
|
||||
"enum": ["low", "medium", "high"],
|
||||
"description": "Priority level of the request"
|
||||
}
|
||||
},
|
||||
"required": ["request_summary"]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## Test Scenarios
|
||||
|
||||
A mix of financial and technical requests to test routing accuracy.
|
||||
|
||||
|
||||
```python
|
||||
TEST_SCENARIOS = [
|
||||
{
|
||||
"type": "financial",
|
||||
"request": "I was charged twice for my subscription last month. I need a refund for the duplicate charge.",
|
||||
"correct_tool": "route_to_channel_alpha"
|
||||
},
|
||||
{
|
||||
"type": "technical",
|
||||
"request": "The app keeps crashing when I try to upload a file larger than 10MB. This bug is blocking my work.",
|
||||
"correct_tool": "route_to_channel_omega"
|
||||
},
|
||||
{
|
||||
"type": "financial",
|
||||
"request": "My invoice shows an incorrect amount. The billing department needs to fix this.",
|
||||
"correct_tool": "route_to_channel_alpha"
|
||||
},
|
||||
{
|
||||
"type": "technical",
|
||||
"request": "I'd like to request a new feature: the ability to export reports as PDF.",
|
||||
"correct_tool": "route_to_channel_omega"
|
||||
},
|
||||
{
|
||||
"type": "financial",
|
||||
"request": "I need to update my payment method and understand why my last payment failed.",
|
||||
"correct_tool": "route_to_channel_alpha"
|
||||
},
|
||||
]
|
||||
```
|
||||
|
||||
## Helper Functions
|
||||
|
||||
|
||||
```python
|
||||
SYSTEM_PROMPT = """You are a customer service routing agent. Your job is to route customer requests to the appropriate processing channel.
|
||||
|
||||
You have access to two routing channels:
|
||||
- route_to_channel_alpha: Routes to channel Alpha
|
||||
- route_to_channel_omega: Routes to channel Omega
|
||||
|
||||
Analyze the customer's request and route it to the most appropriate channel. You must call one of the routing functions to process the request.
|
||||
|
||||
Important: Base your routing decision on what you know about each channel's purpose. If you have learned from previous interactions which channel handles specific types of requests, use that knowledge."""
|
||||
|
||||
|
||||
def make_routing_request(user_request: str, use_hindsight: bool, bank_id: Optional[str] = None):
|
||||
"""Make a routing request and return the tool called."""
|
||||
messages = [
|
||||
{"role": "system", "content": SYSTEM_PROMPT},
|
||||
{"role": "user", "content": f"Customer Request: {user_request}"}
|
||||
]
|
||||
|
||||
if use_hindsight and bank_id:
|
||||
response = hindsight_litellm.completion(
|
||||
model="gpt-4o-mini",
|
||||
messages=messages,
|
||||
tools=TOOLS,
|
||||
tool_choice="required",
|
||||
temperature=0.0,
|
||||
)
|
||||
else:
|
||||
response = litellm.completion(
|
||||
model="gpt-4o-mini",
|
||||
messages=messages,
|
||||
tools=TOOLS,
|
||||
tool_choice="required",
|
||||
temperature=0.7,
|
||||
)
|
||||
|
||||
if response.choices[0].message.tool_calls:
|
||||
tool_call = response.choices[0].message.tool_calls[0]
|
||||
return tool_call.function.name
|
||||
return None
|
||||
|
||||
|
||||
def store_feedback(bank_id: str, request: str, correct_tool: str, request_type: str):
|
||||
"""Store feedback about which tool was correct for a request type."""
|
||||
client = Hindsight(base_url=HINDSIGHT_API_URL, timeout=60.0)
|
||||
|
||||
feedback_content = f"""ROUTING FEEDBACK:
|
||||
Request type: {request_type}
|
||||
Customer request: "{request}"
|
||||
Correct routing: {correct_tool}
|
||||
|
||||
LEARNED RULE: {request_type.upper()} requests (like refunds, billing, payments, charges, invoices) should ALWAYS be routed to {correct_tool}.
|
||||
This is important institutional knowledge for routing decisions."""
|
||||
|
||||
client.retain(
|
||||
bank_id=bank_id,
|
||||
content=feedback_content,
|
||||
context=f"routing:feedback:{request_type}",
|
||||
metadata={"request_type": request_type, "correct_tool": correct_tool}
|
||||
)
|
||||
```
|
||||
|
||||
## Phase 1: Without Hindsight (No Memory)
|
||||
|
||||
The LLM has no prior knowledge about which channel handles what. With ambiguous tool descriptions, it may route incorrectly.
|
||||
|
||||
|
||||
```python
|
||||
print("=" * 60)
|
||||
print("PHASE 1: WITHOUT HINDSIGHT (No Memory)")
|
||||
print("=" * 60)
|
||||
|
||||
phase1_results = []
|
||||
for i, scenario in enumerate(TEST_SCENARIOS[:3], 1):
|
||||
print(f"\n--- Test {i}: {scenario['type'].upper()} Request ---")
|
||||
print(f"Request: \"{scenario['request'][:60]}...\"")
|
||||
|
||||
tool_name = make_routing_request(scenario['request'], use_hindsight=False)
|
||||
|
||||
is_correct = tool_name == scenario['correct_tool']
|
||||
phase1_results.append(is_correct)
|
||||
|
||||
print(f"LLM chose: {tool_name}")
|
||||
print(f"Correct tool: {scenario['correct_tool']}")
|
||||
print(f"Result: {'✓ CORRECT' if is_correct else '✗ INCORRECT'}")
|
||||
|
||||
phase1_accuracy = sum(phase1_results) / len(phase1_results) * 100
|
||||
print(f"\n>>> Phase 1 Accuracy: {phase1_accuracy:.0f}% ({sum(phase1_results)}/{len(phase1_results)})")
|
||||
```
|
||||
|
||||
## Phase 2: Teaching Phase
|
||||
|
||||
Now we provide feedback about correct routing to build memory. This simulates a human supervisor correcting the AI's routing decisions.
|
||||
|
||||
|
||||
```python
|
||||
bank_id = f"tool-learning-{uuid.uuid4().hex[:8]}"
|
||||
print(f"Using bank_id: {bank_id}")
|
||||
|
||||
# Configure and enable Hindsight
|
||||
hindsight_litellm.configure(
|
||||
hindsight_api_url=HINDSIGHT_API_URL,
|
||||
bank_id=bank_id,
|
||||
store_conversations=True,
|
||||
inject_memories=True,
|
||||
max_memories=10,
|
||||
recall_budget="high",
|
||||
verbose=False,
|
||||
)
|
||||
hindsight_litellm.enable()
|
||||
|
||||
print("\nStoring routing feedback...")
|
||||
|
||||
feedback_examples = [
|
||||
("I need a refund for an incorrect charge on my account.", "route_to_channel_alpha", "financial"),
|
||||
("There's a bug in the system causing data loss.", "route_to_channel_omega", "technical"),
|
||||
("My billing statement has errors that need correction.", "route_to_channel_alpha", "financial"),
|
||||
("I want to request a new feature for the dashboard.", "route_to_channel_omega", "technical"),
|
||||
]
|
||||
|
||||
for request, correct_tool, req_type in feedback_examples:
|
||||
print(f" Storing: {req_type.upper()} → {correct_tool}")
|
||||
store_feedback(bank_id, request, correct_tool, req_type)
|
||||
|
||||
print("\nWaiting 15 seconds for Hindsight to process memories...")
|
||||
time.sleep(15)
|
||||
print("Done!")
|
||||
```
|
||||
|
||||
## Phase 3: With Hindsight (Memory-Augmented)
|
||||
|
||||
The LLM now has access to learned routing knowledge via Hindsight. It should route requests correctly based on past feedback.
|
||||
|
||||
|
||||
```python
|
||||
print("=" * 60)
|
||||
print("PHASE 3: WITH HINDSIGHT (Memory-Augmented)")
|
||||
print("=" * 60)
|
||||
|
||||
phase3_results = []
|
||||
for i, scenario in enumerate(TEST_SCENARIOS, 1):
|
||||
print(f"\n--- Test {i}: {scenario['type'].upper()} Request ---")
|
||||
print(f"Request: \"{scenario['request'][:60]}...\"")
|
||||
|
||||
tool_name = make_routing_request(
|
||||
scenario['request'],
|
||||
use_hindsight=True,
|
||||
bank_id=bank_id
|
||||
)
|
||||
|
||||
is_correct = tool_name == scenario['correct_tool']
|
||||
phase3_results.append(is_correct)
|
||||
|
||||
print(f"LLM chose: {tool_name}")
|
||||
print(f"Correct tool: {scenario['correct_tool']}")
|
||||
print(f"Result: {'✓ CORRECT' if is_correct else '✗ INCORRECT'}")
|
||||
|
||||
phase3_accuracy = sum(phase3_results) / len(phase3_results) * 100
|
||||
print(f"\n>>> Phase 3 Accuracy: {phase3_accuracy:.0f}% ({sum(phase3_results)}/{len(phase3_results)})")
|
||||
```
|
||||
|
||||
## Summary
|
||||
|
||||
|
||||
```python
|
||||
print("=" * 60)
|
||||
print("SUMMARY")
|
||||
print("=" * 60)
|
||||
print(f"\nPhase 1 (No Memory): {phase1_accuracy:.0f}% accuracy")
|
||||
print(f"Phase 3 (With Hindsight): {phase3_accuracy:.0f}% accuracy")
|
||||
|
||||
improvement = phase3_accuracy - phase1_accuracy
|
||||
if improvement > 0:
|
||||
print(f"\n🎉 Improvement: +{improvement:.0f}% accuracy with Hindsight!")
|
||||
elif improvement == 0:
|
||||
print(f"\nNote: Results may vary. Run again to see learning effect.")
|
||||
else:
|
||||
print(f"\nNote: Phase 1 got lucky! Run again to see typical behavior.")
|
||||
|
||||
print(f"\nMemories stored in bank: {bank_id}")
|
||||
print(f"View in UI: http://localhost:9999/banks/{bank_id}")
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("KEY INSIGHT")
|
||||
print("=" * 60)
|
||||
print("Hindsight allows the LLM to learn from experience which tool")
|
||||
print("to use, even when tool names/descriptions are ambiguous.")
|
||||
```
|
||||
|
||||
## Cleanup
|
||||
|
||||
|
||||
```python
|
||||
hindsight_litellm.cleanup()
|
||||
|
||||
# Optional: delete the bank
|
||||
import requests
|
||||
response = requests.delete(f"{HINDSIGHT_API_URL}/v1/default/banks/{bank_id}")
|
||||
print(f"Deleted bank: {response.json()}")
|
||||
```
|
||||
192
hindsight-docs/versioned_docs/version-0.4/developer/admin-cli.md
Normal file
192
hindsight-docs/versioned_docs/version-0.4/developer/admin-cli.md
Normal file
|
|
@ -0,0 +1,192 @@
|
|||
# Admin CLI
|
||||
|
||||
The `hindsight-admin` CLI provides administrative commands for managing your Hindsight deployment, including database migrations, backup, and restore operations.
|
||||
|
||||
## Installation
|
||||
|
||||
The admin CLI is included with the `hindsight-api` package:
|
||||
|
||||
```bash
|
||||
pip install hindsight-api
|
||||
# or
|
||||
uv add hindsight-api
|
||||
```
|
||||
|
||||
## Commands
|
||||
|
||||
### run-db-migration
|
||||
|
||||
Run database migrations to the latest version. This is useful when you want to run migrations separately from API startup (e.g., in CI/CD pipelines or before deploying a new version).
|
||||
|
||||
```bash
|
||||
hindsight-admin run-db-migration [OPTIONS]
|
||||
```
|
||||
|
||||
**Options:**
|
||||
|
||||
| Option | Description | Default |
|
||||
|--------|-------------|---------|
|
||||
| `--schema`, `-s` | Database schema to run migrations on | `public` |
|
||||
|
||||
**Examples:**
|
||||
|
||||
```bash
|
||||
# Run migrations on the default public schema
|
||||
hindsight-admin run-db-migration
|
||||
|
||||
# Run migrations on a specific tenant schema
|
||||
hindsight-admin run-db-migration --schema tenant_acme
|
||||
```
|
||||
|
||||
:::tip Disabling Auto-Migrations
|
||||
To disable automatic migrations on API startup, set `HINDSIGHT_API_RUN_MIGRATIONS_ON_STARTUP=false`. This is useful when you want to run migrations as a separate step in your deployment pipeline.
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
### backup
|
||||
|
||||
Create a backup of all Hindsight data to a zip file.
|
||||
|
||||
```bash
|
||||
hindsight-admin backup OUTPUT [OPTIONS]
|
||||
```
|
||||
|
||||
**Arguments:**
|
||||
|
||||
| Argument | Description |
|
||||
|----------|-------------|
|
||||
| `OUTPUT` | Output file path (will add `.zip` extension if not present) |
|
||||
|
||||
**Options:**
|
||||
|
||||
| Option | Description | Default |
|
||||
|--------|-------------|---------|
|
||||
| `--schema`, `-s` | Database schema to backup | `public` |
|
||||
|
||||
**Examples:**
|
||||
|
||||
```bash
|
||||
# Backup to a file
|
||||
hindsight-admin backup /backups/hindsight-2024-01-15.zip
|
||||
|
||||
# Backup a specific tenant schema
|
||||
hindsight-admin backup /backups/tenant-acme.zip --schema tenant_acme
|
||||
```
|
||||
|
||||
The backup includes:
|
||||
- Memory banks and their configuration
|
||||
- Documents and chunks
|
||||
- Entities and their relationships
|
||||
- Memory units (facts, experiences, observations)
|
||||
- Entity cooccurrences and memory links
|
||||
|
||||
:::note Consistency
|
||||
Backups are created within a database transaction with `REPEATABLE READ` isolation, ensuring a consistent snapshot across all tables.
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
### restore
|
||||
|
||||
Restore data from a backup file. **Warning: This deletes all existing data in the target schema.**
|
||||
|
||||
```bash
|
||||
hindsight-admin restore INPUT [OPTIONS]
|
||||
```
|
||||
|
||||
**Arguments:**
|
||||
|
||||
| Argument | Description |
|
||||
|----------|-------------|
|
||||
| `INPUT` | Input backup file (.zip) |
|
||||
|
||||
**Options:**
|
||||
|
||||
| Option | Description | Default |
|
||||
|--------|-------------|---------|
|
||||
| `--schema`, `-s` | Database schema to restore to | `public` |
|
||||
| `--yes`, `-y` | Skip confirmation prompt | `false` |
|
||||
|
||||
**Examples:**
|
||||
|
||||
```bash
|
||||
# Restore with confirmation prompt
|
||||
hindsight-admin restore /backups/hindsight-2024-01-15.zip
|
||||
|
||||
# Restore without confirmation (for scripts)
|
||||
hindsight-admin restore /backups/hindsight-2024-01-15.zip --yes
|
||||
|
||||
# Restore to a specific tenant schema
|
||||
hindsight-admin restore /backups/tenant-acme.zip --schema tenant_acme --yes
|
||||
```
|
||||
|
||||
:::warning Data Loss
|
||||
Restore will **delete all existing data** in the target schema before importing the backup. Always verify you have a recent backup before performing a restore.
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
### decommission-worker
|
||||
|
||||
Release all tasks owned by a worker, resetting them from "processing" back to "pending" status so they can be picked up by other workers.
|
||||
|
||||
```bash
|
||||
hindsight-admin decommission-worker WORKER_ID [OPTIONS]
|
||||
```
|
||||
|
||||
**Arguments:**
|
||||
|
||||
| Argument | Description |
|
||||
|----------|-------------|
|
||||
| `WORKER_ID` | ID of the worker to decommission |
|
||||
|
||||
**Options:**
|
||||
|
||||
| Option | Description | Default |
|
||||
|--------|-------------|---------|
|
||||
| `--schema`, `-s` | Database schema | `public` |
|
||||
|
||||
**Examples:**
|
||||
|
||||
```bash
|
||||
# Before scaling down - release tasks from workers being removed
|
||||
hindsight-admin decommission-worker hindsight-worker-4
|
||||
hindsight-admin decommission-worker hindsight-worker-3
|
||||
|
||||
# Release tasks from a crashed worker
|
||||
hindsight-admin decommission-worker worker-2
|
||||
|
||||
# For a specific tenant schema
|
||||
hindsight-admin decommission-worker worker-1 --schema tenant_acme
|
||||
```
|
||||
|
||||
**When to Use:**
|
||||
|
||||
- **Scaling down**: Before removing worker replicas in Kubernetes
|
||||
- **Graceful removal**: When taking a worker offline for maintenance
|
||||
- **Crash recovery**: If a worker crashed while processing tasks
|
||||
- **Stuck worker**: When a worker is unresponsive
|
||||
|
||||
:::tip Finding Worker IDs
|
||||
Worker IDs default to the hostname. In Kubernetes StatefulSets, this is the pod name (e.g., `hindsight-worker-0`). You can also set a custom ID with `HINDSIGHT_API_WORKER_ID` or `--worker-id`.
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
## Environment Variables
|
||||
|
||||
The admin CLI uses the same environment variables as the API service. The most important one is:
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| `HINDSIGHT_API_DATABASE_URL` | PostgreSQL connection string | `pg0` (embedded) |
|
||||
|
||||
**Example:**
|
||||
|
||||
```bash
|
||||
# Use a specific database
|
||||
export HINDSIGHT_API_DATABASE_URL=postgresql://user:pass@localhost:5432/hindsight
|
||||
hindsight-admin backup /backups/mybackup.zip
|
||||
```
|
||||
|
||||
|
|
@ -0,0 +1,151 @@
|
|||
---
|
||||
sidebar_position: 8
|
||||
---
|
||||
|
||||
# Documents
|
||||
|
||||
Track and manage document sources in your memory bank. Documents provide traceability — knowing where memories came from.
|
||||
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeSnippet from '@site/src/components/CodeSnippet';
|
||||
|
||||
{/* Import raw source files */}
|
||||
import documentsPy from '!!raw-loader!@site/examples/api/documents.py';
|
||||
import documentsMjs from '!!raw-loader!@site/examples/api/documents.mjs';
|
||||
|
||||
:::tip Prerequisites
|
||||
Make sure you've completed the [Quick Start](./quickstart) and understand [how retain works](./retain).
|
||||
:::
|
||||
|
||||
## What Are Documents?
|
||||
|
||||
Documents are containers for retained content. They help you:
|
||||
|
||||
- **Track sources** — Know which PDF, conversation, or file a memory came from
|
||||
- **Update content** — Re-retain a document to update its facts
|
||||
- **Delete in bulk** — Remove all memories from a document at once
|
||||
- **Organize memories** — Group related facts by source
|
||||
|
||||
## Chunks
|
||||
|
||||
When you retain content, Hindsight splits it into chunks before extracting facts. These chunks are stored alongside the extracted memories, preserving the original text segments.
|
||||
|
||||
**Why chunks matter:**
|
||||
- **Context preservation** — Chunks contain the raw text that generated facts, useful when you need the exact wording
|
||||
- **Richer recall** — Including chunks in recall provides surrounding context for matched facts
|
||||
|
||||
:::tip Include Chunks in Recall
|
||||
Use `include_chunks=True` in your recall calls to get the original text chunks alongside fact results. See [Recall](./recall) for details.
|
||||
:::
|
||||
|
||||
## Retain with Document ID
|
||||
|
||||
Associate retained content with a document:
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={documentsPy} section="document-retain" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={documentsMjs} section="document-retain" language="javascript" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
|
||||
```bash
|
||||
# Retain content with document ID
|
||||
hindsight memory retain my-bank "Meeting notes content..." --doc-id notes-2024-03-15
|
||||
|
||||
# Batch retain from files
|
||||
hindsight memory retain-files my-bank docs/
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## Update Documents
|
||||
|
||||
Re-retaining with the same document_id **replaces** the old content:
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={documentsPy} section="document-update" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={documentsMjs} section="document-update" language="javascript" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
|
||||
```bash
|
||||
# Original
|
||||
hindsight memory retain my-bank "Project deadline: March 31" --doc-id project-plan
|
||||
|
||||
# Update
|
||||
hindsight memory retain my-bank "Project deadline: April 15 (extended)" --doc-id project-plan
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## Get Document
|
||||
|
||||
Retrieve a document's original text and metadata. This is useful for expanding document context after a recall operation returns memories with document references.
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={documentsPy} section="document-get" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={documentsMjs} section="document-get" language="javascript" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
|
||||
```bash
|
||||
hindsight document get my-bank meeting-2024-03-15
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## Delete Document
|
||||
|
||||
Remove a document and all its associated memories:
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={documentsPy} section="document-delete" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={documentsMjs} section="document-delete" language="javascript" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
|
||||
```bash
|
||||
hindsight document delete my-bank meeting-2024-03-15
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
:::warning
|
||||
Deleting a document permanently removes all memories extracted from it. This action cannot be undone.
|
||||
:::
|
||||
|
||||
## Document Response Format
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "meeting-2024-03-15",
|
||||
"bank_id": "my-bank",
|
||||
"original_text": "Alice presented the Q4 roadmap...",
|
||||
"content_hash": "abc123def456",
|
||||
"memory_unit_count": 12,
|
||||
"created_at": "2024-03-15T14:00:00Z",
|
||||
"updated_at": "2024-03-15T14:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [**Operations**](./operations) — Monitor background tasks
|
||||
- [**Memory Banks**](./memory-banks) — Configure bank settings
|
||||
|
|
@ -0,0 +1,141 @@
|
|||
---
|
||||
sidebar_position: 2
|
||||
---
|
||||
|
||||
# Main Methods
|
||||
|
||||
Hindsight provides three core operations: **retain**, **recall**, and **reflect**.
|
||||
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeSnippet from '@site/src/components/CodeSnippet';
|
||||
|
||||
{/* Import raw source files */}
|
||||
import mainMethodsPy from '!!raw-loader!@site/examples/api/main-methods.py';
|
||||
import mainMethodsMjs from '!!raw-loader!@site/examples/api/main-methods.mjs';
|
||||
|
||||
:::tip Prerequisites
|
||||
Make sure you've [installed Hindsight](../installation) and completed the [Quick Start](./quickstart).
|
||||
:::
|
||||
|
||||
## Retain: Store Information
|
||||
|
||||
Store conversations, documents, and facts into a memory bank.
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={mainMethodsPy} section="main-retain" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={mainMethodsMjs} section="main-retain" language="javascript" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
|
||||
```bash
|
||||
# Store a single fact
|
||||
hindsight retain my-bank "Alice joined Google in March 2024 as a Senior ML Engineer"
|
||||
|
||||
# Store from a file
|
||||
hindsight retain my-bank --file conversation.txt --context "Daily standup"
|
||||
|
||||
# Store multiple files
|
||||
hindsight retain my-bank --files docs/*.md
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
**What happens:** Content is processed by an LLM to extract rich facts, identify entities, and build connections in a knowledge graph.
|
||||
|
||||
**See:** [Retain Details](./retain) for advanced options and parameters.
|
||||
|
||||
---
|
||||
|
||||
## Recall: Search Memories
|
||||
|
||||
Search for relevant memories using multi-strategy retrieval.
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={mainMethodsPy} section="main-recall" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={mainMethodsMjs} section="main-recall" language="javascript" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
|
||||
```bash
|
||||
# Basic search
|
||||
hindsight recall my-bank "What does Alice do at Google?"
|
||||
|
||||
# Search with options
|
||||
hindsight recall my-bank "What happened last spring?" \
|
||||
--budget high \
|
||||
--max-tokens 8192 \
|
||||
--fact-type world
|
||||
|
||||
# Verbose output (shows weights and sources)
|
||||
hindsight recall my-bank "Tell me about Alice" -v
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
**What happens:** Four search strategies (semantic, keyword, graph, temporal) run in parallel, results are fused and reranked.
|
||||
|
||||
**See:** [Recall Details](./recall) for tuning quality vs latency.
|
||||
|
||||
---
|
||||
|
||||
## Reflect: Reason with Disposition
|
||||
|
||||
Generate disposition-aware responses using memories and observations.
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={mainMethodsPy} section="main-reflect" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={mainMethodsMjs} section="main-reflect" language="javascript" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
|
||||
```bash
|
||||
# Basic reflect
|
||||
hindsight reflect my-bank "Should we adopt TypeScript for our backend?"
|
||||
|
||||
# Verbose output (shows sources and observations)
|
||||
hindsight reflect my-bank "What are Alice's strengths for the team lead role?" -v
|
||||
|
||||
# With higher reasoning budget
|
||||
hindsight reflect my-bank "Analyze our tech stack" --budget high
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
**What happens:** Memories and observations are recalled, bank disposition is applied, and the LLM reasons through the evidence to generate a response.
|
||||
|
||||
**See:** [Reflect Details](./reflect) for disposition configuration.
|
||||
|
||||
---
|
||||
|
||||
## Comparison
|
||||
|
||||
| Feature | Retain | Recall | Reflect |
|
||||
|---------|--------|--------|---------|
|
||||
| **Purpose** | Store information | Find information | Reason about information |
|
||||
| **Input** | Raw text/documents | Search query | Question/prompt |
|
||||
| **Output** | Memory IDs | Ranked facts + observations | Reasoned response |
|
||||
| **Uses LLM** | Yes (extraction) | No | Yes (generation) |
|
||||
| **Uses observations** | No | Yes | Yes |
|
||||
| **Disposition** | No | No | Yes |
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [**Retain**](./retain) — Advanced options for storing memories
|
||||
- [**Recall**](./recall) — Tuning search quality and performance
|
||||
- [**Reflect**](./reflect) — Configuring disposition
|
||||
- [**Memory Banks**](./memory-banks) — Managing memory bank disposition
|
||||
|
|
@ -0,0 +1,161 @@
|
|||
---
|
||||
sidebar_position: 6
|
||||
---
|
||||
|
||||
# Memory Banks
|
||||
|
||||
Memory banks are isolated containers that store all memory-related data for a specific context or use case.
|
||||
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeSnippet from '@site/src/components/CodeSnippet';
|
||||
|
||||
{/* Import raw source files */}
|
||||
import memoryBanksPy from '!!raw-loader!@site/examples/api/memory-banks.py';
|
||||
import memoryBanksMjs from '!!raw-loader!@site/examples/api/memory-banks.mjs';
|
||||
import directivesPy from '!!raw-loader!@site/examples/api/directives.py';
|
||||
import directivesMjs from '!!raw-loader!@site/examples/api/directives.mjs';
|
||||
|
||||
## What is a Memory Bank?
|
||||
|
||||
A memory bank is a complete, isolated storage unit containing:
|
||||
|
||||
- **Memories** — Facts and information retained from conversations
|
||||
- **Documents** — Files and content indexed for retrieval
|
||||
- **Entities** — People, places, concepts extracted from memories
|
||||
- **Relationships** — Connections between entities in the knowledge graph
|
||||
- **Directives** — Hard rules the agent must follow during reflect operations
|
||||
|
||||
Banks are completely isolated from each other — memories stored in one bank are not visible to another.
|
||||
|
||||
You don't need to pre-create a bank. Hindsight will automatically create it with default settings when you first use it.
|
||||
|
||||
:::tip Prerequisites
|
||||
Make sure you've completed the [Quick Start](./quickstart) to install the client and start the server.
|
||||
:::
|
||||
|
||||
## Creating a Memory Bank
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={memoryBanksPy} section="create-bank" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={memoryBanksMjs} section="create-bank" language="javascript" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
|
||||
```bash
|
||||
# Set mission
|
||||
hindsight bank mission my-bank "I am a research assistant specializing in ML"
|
||||
|
||||
# Set disposition
|
||||
hindsight bank disposition my-bank \
|
||||
--skepticism 4 \
|
||||
--literalism 3 \
|
||||
--empathy 3
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## Mission and Disposition
|
||||
|
||||
Mission and disposition are optional settings that influence how the bank reasons during [reflect](./reflect) operations.
|
||||
|
||||
:::info
|
||||
Mission and disposition only affect the `reflect` operation. They do not impact `retain`, `recall`, or other memory operations.
|
||||
:::
|
||||
|
||||
### Mission
|
||||
|
||||
The mission is a first-person narrative providing context for reasoning:
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={memoryBanksPy} section="bank-mission" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={memoryBanksMjs} section="bank-mission" language="javascript" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### Disposition Traits
|
||||
|
||||
Disposition traits influence how reasoning is performed during reflection. Each trait is scored 1 to 5:
|
||||
|
||||
| Trait | Low (1) | High (5) |
|
||||
|-------|---------|----------|
|
||||
| **Skepticism** | Trusting, accepts information at face value | Skeptical, questions and doubts claims |
|
||||
| **Literalism** | Flexible interpretation, reads between the lines | Literal interpretation, takes things exactly as stated |
|
||||
| **Empathy** | Detached, focuses on facts and logic | Empathetic, considers emotional context |
|
||||
|
||||
## Directives
|
||||
|
||||
Directives are hard rules that the agent must follow during [reflect](./reflect) operations. Unlike disposition traits which influence *how* the agent reasons, directives are explicit instructions that are *always* enforced.
|
||||
|
||||
:::info
|
||||
Directives only affect the `reflect` operation. They are injected into prompts and the agent is required to comply with them in all responses.
|
||||
:::
|
||||
|
||||
### When to Use Directives
|
||||
|
||||
Use directives for rules that must never be violated:
|
||||
|
||||
- **Language/style constraints**: "Always respond in formal English"
|
||||
- **Privacy rules**: "Never share personal data with third parties"
|
||||
- **Domain constraints**: "Prefer conservative investment recommendations"
|
||||
- **Behavioral guardrails**: "Always cite sources when making claims"
|
||||
|
||||
### Creating Directives
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={directivesPy} section="create-directive" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={directivesMjs} section="create-directive" language="javascript" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### Listing Directives
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={directivesPy} section="list-directives" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={directivesMjs} section="list-directives" language="javascript" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### Updating Directives
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={directivesPy} section="update-directive" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={directivesMjs} section="update-directive" language="javascript" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### Deleting Directives
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={directivesPy} section="delete-directive" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={directivesMjs} section="delete-directive" language="javascript" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### Directives vs Disposition
|
||||
|
||||
| Aspect | Directives | Disposition |
|
||||
|--------|------------|-------------|
|
||||
| **Nature** | Hard rules, must be followed | Soft influence on reasoning style |
|
||||
| **Enforcement** | Strict — responses are rejected if violated | Flexible — shapes interpretation |
|
||||
| **Use case** | Compliance, guardrails, constraints | Personality, character, tone |
|
||||
| **Example** | "Never recommend specific stocks" | High skepticism: questions claims |
|
||||
|
|
@ -0,0 +1,262 @@
|
|||
---
|
||||
sidebar_position: 4
|
||||
---
|
||||
|
||||
# Mental Models
|
||||
|
||||
User-curated summaries that provide high-quality, pre-computed answers for common queries.
|
||||
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeSnippet from '@site/src/components/CodeSnippet';
|
||||
|
||||
{/* Import raw source files */}
|
||||
import mentalModelsPy from '!!raw-loader!@site/examples/api/mental-models.py';
|
||||
|
||||
## What Are Mental Models?
|
||||
|
||||
Mental models are **saved reflect responses** that you curate for your memory bank. When you create a mental model, Hindsight runs a reflect operation with your source query and stores the result. During future reflect calls, these pre-computed summaries are checked first — providing faster, more consistent answers.
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
A[Create Mental Model] --> B[Run Reflect]
|
||||
B --> C[Store Result]
|
||||
C --> D[Future Queries]
|
||||
D --> E{Match Found?}
|
||||
E -->|Yes| F[Return Mental Model]
|
||||
E -->|No| G[Run Full Reflect]
|
||||
```
|
||||
|
||||
### Why Use Mental Models?
|
||||
|
||||
| Benefit | Description |
|
||||
|---------|-------------|
|
||||
| **Consistency** | Same answer every time for common questions |
|
||||
| **Speed** | Pre-computed responses are returned instantly |
|
||||
| **Quality** | Manually curated summaries you've reviewed |
|
||||
| **Control** | Define exactly how key topics should be answered |
|
||||
|
||||
### Hierarchical Retrieval
|
||||
|
||||
During reflect, the agent checks sources in priority order:
|
||||
|
||||
1. **Mental Models** — User-curated summaries (highest priority)
|
||||
2. **Observations** — Consolidated knowledge
|
||||
3. **Raw Facts** — Ground truth memories
|
||||
|
||||
Mental models are checked first because they represent your explicitly curated knowledge.
|
||||
|
||||
---
|
||||
|
||||
## Create a Mental Model
|
||||
|
||||
Creating a mental model runs a reflect operation in the background and saves the result:
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={mentalModelsPy} section="create-mental-model" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
|
||||
```bash
|
||||
# Create a mental model (async operation)
|
||||
curl -X POST "http://localhost:8888/v1/default/banks/my-bank/mental-models" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"name": "Team Communication Preferences",
|
||||
"source_query": "How does the team prefer to communicate?",
|
||||
"tags": ["team"]
|
||||
}'
|
||||
|
||||
# Response: {"operation_id": "op-123"}
|
||||
# Use the operations endpoint to check completion
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|----------|-------------|
|
||||
| `name` | string | Yes | Human-readable name for the mental model |
|
||||
| `source_query` | string | Yes | The query to run to generate content |
|
||||
| `tags` | list | No | Tags for filtering during retrieval |
|
||||
| `max_tokens` | int | No | Maximum tokens for the mental model content |
|
||||
| `trigger` | object | No | Trigger settings (see [Automatic Refresh](#automatic-refresh)) |
|
||||
|
||||
---
|
||||
|
||||
## Automatic Refresh
|
||||
|
||||
Mental models can be configured to **automatically refresh** when observations are updated. This keeps them in sync with the latest knowledge without manual intervention.
|
||||
|
||||
### Trigger Settings
|
||||
|
||||
| Setting | Type | Default | Description |
|
||||
|---------|------|---------|-------------|
|
||||
| `refresh_after_consolidation` | bool | false | Automatically refresh after observations consolidation |
|
||||
|
||||
When `refresh_after_consolidation` is enabled, the mental model will be re-generated every time the bank's observations are consolidated — ensuring it always reflects the latest synthesized knowledge.
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={mentalModelsPy} section="create-mental-model-with-trigger" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
|
||||
```bash
|
||||
# Create a mental model with automatic refresh enabled
|
||||
curl -X POST "http://localhost:8888/v1/default/banks/my-bank/mental-models" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"name": "Project Status",
|
||||
"source_query": "What is the current project status?",
|
||||
"trigger": {"refresh_after_consolidation": true}
|
||||
}'
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### When to Use Automatic Refresh
|
||||
|
||||
| Use Case | Automatic Refresh | Why |
|
||||
|----------|-------------------|-----|
|
||||
| **Real-time dashboards** | ✅ Enabled | Status should always be current |
|
||||
| **Policy summaries** | ❌ Disabled | Policies change infrequently, manual refresh preferred |
|
||||
| **User preferences** | ✅ Enabled | Preferences evolve with new interactions |
|
||||
| **FAQ answers** | ❌ Disabled | Answers are curated, should be reviewed before updating |
|
||||
|
||||
:::tip
|
||||
Enable automatic refresh for mental models that need to stay current. Disable it for curated content where you want to review changes before they go live.
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
## List Mental Models
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={mentalModelsPy} section="list-mental-models" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
|
||||
```bash
|
||||
curl "http://localhost:8888/v1/default/banks/my-bank/mental-models"
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
---
|
||||
|
||||
## Get a Mental Model
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={mentalModelsPy} section="get-mental-model" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
|
||||
```bash
|
||||
curl "http://localhost:8888/v1/default/banks/my-bank/mental-models/{mental_model_id}"
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### Response Fields
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `id` | string | Unique mental model ID |
|
||||
| `bank_id` | string | Memory bank ID |
|
||||
| `name` | string | Human-readable name |
|
||||
| `source_query` | string | The query used to generate content |
|
||||
| `content` | string | The generated mental model text |
|
||||
| `tags` | list | Tags for filtering |
|
||||
| `last_refreshed_at` | string | When the mental model was last updated |
|
||||
| `created_at` | string | When the mental model was created |
|
||||
| `reflect_response` | object | Full reflect response including `based_on` facts |
|
||||
|
||||
---
|
||||
|
||||
## Refresh a Mental Model
|
||||
|
||||
Re-run the source query to update the mental model with current knowledge:
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={mentalModelsPy} section="refresh-mental-model" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
|
||||
```bash
|
||||
curl -X POST "http://localhost:8888/v1/default/banks/my-bank/mental-models/{mental_model_id}/refresh"
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
Refreshing is useful when:
|
||||
- New memories have been retained that affect the topic
|
||||
- Observations have been updated
|
||||
- You want to ensure the mental model reflects current knowledge
|
||||
|
||||
---
|
||||
|
||||
## Update a Mental Model
|
||||
|
||||
Update the mental model's name:
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={mentalModelsPy} section="update-mental-model" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
|
||||
```bash
|
||||
curl -X PATCH "http://localhost:8888/v1/default/banks/my-bank/mental-models/{mental_model_id}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"name": "Updated Team Communication Preferences"}'
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
---
|
||||
|
||||
## Delete a Mental Model
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={mentalModelsPy} section="delete-mental-model" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
|
||||
```bash
|
||||
curl -X DELETE "http://localhost:8888/v1/default/banks/my-bank/mental-models/{mental_model_id}"
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
---
|
||||
|
||||
## Use Cases
|
||||
|
||||
| Use Case | Example |
|
||||
|----------|---------|
|
||||
| **FAQ Answers** | Pre-compute answers to common customer questions |
|
||||
| **Onboarding Summaries** | "What should new team members know?" |
|
||||
| **Status Reports** | "What's the current project status?" refreshed weekly |
|
||||
| **Policy Summaries** | "What are our security policies?" |
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [**Reflect**](./reflect) — How the agentic loop uses mental models
|
||||
- [**Observations**](/developer/observations) — How knowledge is consolidated
|
||||
- [**Operations**](./operations) — Track async mental model creation
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
---
|
||||
sidebar_position: 9
|
||||
---
|
||||
|
||||
# Operations
|
||||
|
||||
Background tasks that Hindsight executes asynchronously.
|
||||
|
||||
:::tip Prerequisites
|
||||
Make sure you've completed the [Quick Start](./quickstart) and understand [how retain works](./retain).
|
||||
:::
|
||||
|
||||
## How Operations Work
|
||||
|
||||
Hindsight processes several types of tasks in the background to maintain memory quality and consistency. These operations run automatically—you don't need to trigger them manually.
|
||||
|
||||
By default, all background operations are executed in-process within the API service.
|
||||
|
||||
:::note Kafka Integration
|
||||
Support for external streaming platforms like Kafka for scale-out processing is planned but **not available out of the box** in the current release.
|
||||
:::
|
||||
|
||||
## Operation Types
|
||||
|
||||
| Operation | Trigger | Description |
|
||||
|-----------|---------|-------------|
|
||||
| **batch_retain** | `retain_batch` with `async=True` | Processes large content batches in the background |
|
||||
| **consolidate** | After `retain` | Consolidates new facts into observations |
|
||||
|
||||
## Async Retain Example
|
||||
|
||||
When retaining large batches of memories, use `async=true` to process in the background. The response includes an `operation_id` that you can use to poll for completion.
|
||||
|
||||
### 1. Submit async retain request
|
||||
|
||||
```bash
|
||||
curl -X POST "http://localhost:8000/v1/default/banks/my-bank/memories" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"items": [
|
||||
{"content": "Alice joined Google in 2023"},
|
||||
{"content": "Bob prefers Python over JavaScript"}
|
||||
],
|
||||
"async": true
|
||||
}'
|
||||
```
|
||||
|
||||
Response:
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"bank_id": "my-bank",
|
||||
"items_count": 2,
|
||||
"async": true,
|
||||
"operation_id": "550e8400-e29b-41d4-a716-446655440000"
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Poll for operation status
|
||||
|
||||
```bash
|
||||
curl "http://localhost:8000/v1/default/banks/my-bank/operations"
|
||||
```
|
||||
|
||||
Response:
|
||||
```json
|
||||
{
|
||||
"bank_id": "my-bank",
|
||||
"operations": [
|
||||
{
|
||||
"id": "550e8400-e29b-41d4-a716-446655440000",
|
||||
"task_type": "retain",
|
||||
"items_count": 2,
|
||||
"document_id": null,
|
||||
"created_at": "2024-01-15T10:30:00Z",
|
||||
"status": "completed",
|
||||
"error_message": null
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Operation Status Values
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| `pending` | Operation is queued and waiting to be processed |
|
||||
| `completed` | Operation finished successfully |
|
||||
| `failed` | Operation failed (check `error_message` for details) |
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [**Documents**](./documents) — Track document sources
|
||||
- [**Memory Banks**](./memory-banks) — Configure bank settings
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
---
|
||||
sidebar_position: 0
|
||||
---
|
||||
|
||||
# Quick Start
|
||||
|
||||
Get up and running with Hindsight in 60 seconds.
|
||||
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeSnippet from '@site/src/components/CodeSnippet';
|
||||
|
||||
{/* Import raw source files */}
|
||||
import quickstartPy from '!!raw-loader!@site/examples/api/quickstart.py';
|
||||
import quickstartMjs from '!!raw-loader!@site/examples/api/quickstart.mjs';
|
||||
import quickstartSh from '!!raw-loader!@site/examples/api/quickstart.sh';
|
||||
|
||||
## Start the API Server
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="pip" label="pip (API only)">
|
||||
|
||||
```bash
|
||||
pip install hindsight-api
|
||||
export OPENAI_API_KEY=sk-xxx
|
||||
export HINDSIGHT_API_LLM_API_KEY=$OPENAI_API_KEY
|
||||
|
||||
hindsight-api
|
||||
```
|
||||
|
||||
API available at [http://localhost:8888](http://localhost:8888/docs)
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="docker" label="Docker (Full Experience)">
|
||||
|
||||
```bash
|
||||
|
||||
export OPENAI_API_KEY=sk-xxx
|
||||
|
||||
docker run --rm -it --pull always -p 8888:8888 -p 9999:9999 \
|
||||
-e HINDSIGHT_API_LLM_API_KEY=$OPENAI_API_KEY \
|
||||
-v $HOME/.hindsight-docker:/home/hindsight/.pg0 \
|
||||
ghcr.io/vectorize-io/hindsight:latest
|
||||
```
|
||||
|
||||
- **API**: http://localhost:8888
|
||||
- **Control Plane** (Web UI): http://localhost:9999
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
:::tip LLM Provider
|
||||
Hindsight requires an LLM with structured output support. Recommended: **Groq** with `gpt-oss-20b` for fast, cost-effective inference.
|
||||
See [LLM Providers](/developer/models#llm) for more details.
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
## Use the Client
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python">
|
||||
|
||||
```bash
|
||||
pip install hindsight-client
|
||||
```
|
||||
|
||||
<CodeSnippet code={quickstartPy} section="quickstart-full" language="python" />
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="node" label="Node.js">
|
||||
|
||||
```bash
|
||||
npm install @vectorize-io/hindsight-client
|
||||
```
|
||||
|
||||
<CodeSnippet code={quickstartMjs} section="quickstart-full" language="javascript" />
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
|
||||
```bash
|
||||
curl -fsSL https://hindsight.vectorize.io/get-cli | bash
|
||||
```
|
||||
|
||||
<CodeSnippet code={quickstartSh} section="quickstart-full" language="bash" />
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
---
|
||||
|
||||
## What's Happening
|
||||
|
||||
| Operation | What it does |
|
||||
|-----------|--------------|
|
||||
| **Retain** | Content is processed, facts are extracted, entities are identified and linked in a knowledge graph |
|
||||
| **Recall** | Four search strategies (semantic, keyword, graph, temporal) run in parallel to find relevant memories |
|
||||
| **Reflect** | Retrieved memories are used to generate a disposition-aware response |
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [**Retain**](./retain) — Advanced options for storing memories
|
||||
- [**Recall**](./recall) — Search and retrieval strategies
|
||||
- [**Reflect**](./reflect) — Disposition-aware reasoning
|
||||
- [**Memory Banks**](./memory-banks) — Configure disposition and mission
|
||||
- [**Server Deployment**](/developer/installation) — Docker Compose, Helm, and production setup
|
||||
|
|
@ -0,0 +1,159 @@
|
|||
---
|
||||
sidebar_position: 2
|
||||
---
|
||||
|
||||
# Recall Memories
|
||||
|
||||
Retrieve memories using multi-strategy recall.
|
||||
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeSnippet from '@site/src/components/CodeSnippet';
|
||||
|
||||
{/* Import raw source files */}
|
||||
import recallPy from '!!raw-loader!@site/examples/api/recall.py';
|
||||
import recallMjs from '!!raw-loader!@site/examples/api/recall.mjs';
|
||||
import recallSh from '!!raw-loader!@site/examples/api/recall.sh';
|
||||
|
||||
:::info How Recall Works
|
||||
Learn about the four retrieval strategies (semantic, keyword, graph, temporal) and RRF fusion in the [Recall Architecture](/developer/retrieval) guide.
|
||||
:::
|
||||
|
||||
:::tip Prerequisites
|
||||
Make sure you've completed the [Quick Start](./quickstart) to install the client and start the server.
|
||||
:::
|
||||
|
||||
## Basic Recall
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={recallPy} section="recall-basic" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={recallMjs} section="recall-basic" language="javascript" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
<CodeSnippet code={recallSh} section="recall-basic" language="bash" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## Recall Parameters
|
||||
|
||||
| Parameter | Type | Default | Description |
|
||||
|-----------|------|---------|-------------|
|
||||
| `query` | string | required | Natural language query |
|
||||
| `types` | list | all | Filter: `world`, `experience`, `observation` |
|
||||
| `budget` | string | "mid" | Budget level: `low`, `mid`, `high` |
|
||||
| `max_tokens` | int | 4096 | Token budget for results |
|
||||
| `trace` | bool | false | Enable trace output for debugging |
|
||||
| `include_chunks` | bool | false | Include raw text chunks that generated the memories |
|
||||
| `max_chunk_tokens` | int | 500 | Token budget for chunks |
|
||||
| `tags` | list | None | Filter memories by tags (see [Tag Filtering](#filter-by-tags)) |
|
||||
| `tags_match` | string | "any" | How to match tags: `any`, `all`, `any_strict`, `all_strict` |
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={recallPy} section="recall-with-options" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={recallMjs} section="recall-with-options" language="javascript" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## Filter by Fact Type
|
||||
|
||||
Recall specific memory types:
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={recallPy} section="recall-world-only" language="python" />
|
||||
<CodeSnippet code={recallPy} section="recall-experience-only" language="python" />
|
||||
<CodeSnippet code={recallPy} section="recall-observations-only" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
<CodeSnippet code={recallSh} section="recall-fact-type" language="bash" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
:::tip About Observations
|
||||
Observations are consolidated knowledge synthesized from multiple facts. They capture patterns, preferences, and learnings that the memory bank has built up over time. Observations are automatically created in the background after retain operations.
|
||||
:::
|
||||
|
||||
## Token Budget Management
|
||||
|
||||
Hindsight is built for AI agents, not humans. Traditional retrieval systems return "top-k" results, but agents don't think in terms of result counts—they think in tokens. An agent's context window is measured in tokens, and that's exactly how Hindsight measures results.
|
||||
|
||||
The `max_tokens` parameter lets you control how much of your agent's context budget to spend on memories:
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={recallPy} section="recall-token-budget" language="python" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
This design means you never have to guess whether 10 results or 50 results will fit your context. Just specify the token budget and Hindsight returns as many relevant memories as will fit.
|
||||
|
||||
## Budget Levels
|
||||
|
||||
The `budget` parameter controls graph traversal depth:
|
||||
|
||||
- **"low"**: Fast, shallow retrieval — good for simple lookups
|
||||
- **"mid"**: Balanced — default for most queries
|
||||
- **"high"**: Deep exploration — finds indirect connections
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={recallPy} section="recall-budget-levels" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={recallMjs} section="recall-budget-levels" language="javascript" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## Filter by Tags
|
||||
|
||||
Tags enable **visibility scoping**—filter memories based on tags assigned during [retain](./retain#tagging-memories). This is essential for multi-user agents where each user should only see their own memories.
|
||||
|
||||
### Basic Tag Filtering
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={recallPy} section="recall-with-tags" language="python" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### Tag Match Modes
|
||||
|
||||
The `tags_match` parameter controls how tags are matched:
|
||||
|
||||
| Mode | Behavior | Untagged Memories |
|
||||
|------|----------|-------------------|
|
||||
| `any` | OR: memory has ANY of the specified tags | **Included** |
|
||||
| `all` | AND: memory has ALL of the specified tags | **Included** |
|
||||
| `any_strict` | OR: memory has ANY of the specified tags | **Excluded** |
|
||||
| `all_strict` | AND: memory has ALL of the specified tags | **Excluded** |
|
||||
|
||||
**Strict modes** are useful when you want to ensure only tagged memories are returned:
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={recallPy} section="recall-tags-strict" language="python" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
**AND matching** requires all specified tags to be present:
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={recallPy} section="recall-tags-all" language="python" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### Use Cases
|
||||
|
||||
| Scenario | Tags | Mode | Result |
|
||||
|----------|------|------|--------|
|
||||
| User A's memories only | `["user:alice"]` | `any_strict` | Only memories tagged `user:alice` |
|
||||
| Support + feedback | `["support", "feedback"]` | `any` | Memories with either tag + untagged |
|
||||
| Multi-user room | `["user:alice", "room:general"]` | `all_strict` | Only memories with both tags |
|
||||
| Global + user-specific | `["user:alice"]` | `any` | Alice's memories + shared (untagged) |
|
||||
|
|
@ -0,0 +1,168 @@
|
|||
---
|
||||
sidebar_position: 3
|
||||
---
|
||||
|
||||
# Reflect
|
||||
|
||||
Generate disposition-aware responses using an agentic reasoning loop.
|
||||
|
||||
When you call **reflect**, Hindsight runs an **agentic loop** that:
|
||||
1. **Autonomously searches** for relevant information using multiple tools
|
||||
2. **Applies** the bank's disposition traits to shape the reasoning style
|
||||
3. **Generates** a grounded answer with citations to the sources used
|
||||
|
||||
The agent has access to hierarchical retrieval tools (mental models → observations → raw facts) and decides what information it needs to answer your query.
|
||||
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeSnippet from '@site/src/components/CodeSnippet';
|
||||
|
||||
{/* Import raw source files */}
|
||||
import reflectPy from '!!raw-loader!@site/examples/api/reflect.py';
|
||||
import reflectMjs from '!!raw-loader!@site/examples/api/reflect.mjs';
|
||||
import reflectSh from '!!raw-loader!@site/examples/api/reflect.sh';
|
||||
|
||||
:::info How Reflect Works
|
||||
Learn about disposition-driven reasoning in the [Reflect Architecture](/developer/reflect) guide.
|
||||
:::
|
||||
|
||||
:::tip Prerequisites
|
||||
Make sure you've completed the [Quick Start](./quickstart) to install the client and start the server.
|
||||
:::
|
||||
|
||||
## Basic Usage
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={reflectPy} section="reflect-basic" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={reflectMjs} section="reflect-basic" language="javascript" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
<CodeSnippet code={reflectSh} section="reflect-basic" language="bash" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## Parameters
|
||||
|
||||
| Parameter | Type | Default | Description |
|
||||
|-----------|------|---------|-------------|
|
||||
| `query` | string | required | Question or prompt |
|
||||
| `budget` | string | "low" | Budget level: `low`, `mid`, `high` (see below) |
|
||||
| `max_tokens` | int | 4096 | Maximum tokens for the final response |
|
||||
| `response_schema` | object | None | JSON Schema for [structured output](#structured-output) |
|
||||
| `tags` | list | None | Filter memories by tags during reflection |
|
||||
| `tags_match` | string | "any" | How to match tags: `any`, `all`, `any_strict`, `all_strict` |
|
||||
| `trace` | bool | false | Include detailed agent trace in response |
|
||||
|
||||
### Budget
|
||||
|
||||
The `budget` parameter controls the research depth — how thoroughly the agent explores before answering:
|
||||
|
||||
| Budget | Research Depth | Use Case |
|
||||
|--------|----------------|----------|
|
||||
| `low` | Shallow | Quick answers, simple lookups. Prioritizes speed over completeness. |
|
||||
| `mid` | Moderate | Balanced exploration. Checks multiple sources when warranted. |
|
||||
| `high` | Deep | Comprehensive analysis. Explores all knowledge levels, uses multiple query variations. |
|
||||
|
||||
Use `high` for complex questions that require synthesizing information from multiple sources or verifying facts across different retrieval levels.
|
||||
|
||||
### Max Tokens
|
||||
|
||||
The `max_tokens` parameter limits the length of the final generated response. This does not affect how much the agent can retrieve during the agentic loop — only the final answer length.
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={reflectPy} section="reflect-with-params" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={reflectMjs} section="reflect-with-params" language="javascript" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## Disposition Influence
|
||||
|
||||
The bank's disposition affects reflect responses:
|
||||
|
||||
| Trait | Low (1) | High (5) |
|
||||
|-------|---------|----------|
|
||||
| **Skepticism** | Trusting, accepts claims | Questions and doubts claims |
|
||||
| **Literalism** | Flexible interpretation | Exact, literal interpretation |
|
||||
| **Empathy** | Detached, fact-focused | Considers emotional context |
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={reflectPy} section="reflect-disposition" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={reflectMjs} section="reflect-disposition" language="javascript" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## Citations
|
||||
|
||||
The response includes a `based_on` field that shows which sources were used:
|
||||
|
||||
- `based_on.memories` — Memory facts (world, experience) that were retrieved and cited
|
||||
- `based_on.mental_models` — User-curated mental models that were used
|
||||
- `based_on.directives` — Directives that were enforced
|
||||
|
||||
**Important:** Only IDs that were actually retrieved during the agent loop can be cited. The agent validates citations to prevent hallucinated references.
|
||||
|
||||
This enables:
|
||||
- **Transparency** — users see exactly which sources informed the answer
|
||||
- **Verification** — check if the response is grounded in actual memories
|
||||
- **Debugging** — use `trace=True` for detailed tool call logs
|
||||
|
||||
## Structured Output
|
||||
|
||||
For applications that need to process responses programmatically, you can request structured output by providing a JSON Schema via `response_schema`. When provided, the response includes a `structured_output` field with the LLM response parsed according to the schema. The `text` field will be empty since only a single LLM call is made for efficiency.
|
||||
|
||||
The easiest way to define a schema is using **Pydantic models**:
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={reflectPy} section="reflect-structured-output" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={reflectMjs} section="reflect-structured-output" language="javascript" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
<CodeSnippet code={reflectSh} section="reflect-structured-output" language="bash" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
| Use Case | Why Structured Output Helps |
|
||||
|----------|----------------------------|
|
||||
| **Decision pipelines** | Parse recommendations into workflow systems |
|
||||
| **Dashboards** | Extract confidence scores, risk factors for visualization |
|
||||
| **Multi-agent systems** | Pass structured data between agents |
|
||||
| **Auditing** | Log structured decisions with clear reasoning |
|
||||
|
||||
**Tips:**
|
||||
- Use Pydantic's `model_json_schema()` for type-safe schema generation
|
||||
- Use `model_validate()` to parse the response back into your Pydantic model
|
||||
- Keep schemas focused — extract only what you need
|
||||
- Use `Optional` fields for data that may not always be available
|
||||
|
||||
## Filter by Tags
|
||||
|
||||
Like [recall](./recall#filter-by-tags), reflect supports tag filtering to scope which memories are considered during reasoning. This is essential for multi-user scenarios where reflection should only consider memories relevant to a specific user.
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={reflectPy} section="reflect-with-tags" language="python" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
The `tags_match` parameter works the same as in recall:
|
||||
|
||||
| Mode | Behavior |
|
||||
|------|----------|
|
||||
| `any` | OR matching, includes untagged memories |
|
||||
| `all` | AND matching, includes untagged memories |
|
||||
| `any_strict` | OR matching, excludes untagged memories |
|
||||
| `all_strict` | AND matching, excludes untagged memories |
|
||||
|
||||
See [Retain API](./retain#tagging-memories) for how to tag memories and [Recall API](./recall#filter-by-tags) for more details on tag matching modes.
|
||||
|
|
@ -0,0 +1,178 @@
|
|||
---
|
||||
sidebar_position: 2
|
||||
---
|
||||
|
||||
# Ingest Data
|
||||
|
||||
Store documents, conversations, and raw content into Hindsight to automatically extract and create memories.
|
||||
|
||||
When you **retain** content, Hindsight doesn't just store the raw text—it intelligently analyzes the content to extract meaningful facts, identify entities, and build a connected knowledge graph. This process transforms unstructured information into structured, queryable memories.
|
||||
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeSnippet from '@site/src/components/CodeSnippet';
|
||||
|
||||
{/* Import raw source files */}
|
||||
import retainPy from '!!raw-loader!@site/examples/api/retain.py';
|
||||
import retainMjs from '!!raw-loader!@site/examples/api/retain.mjs';
|
||||
import retainSh from '!!raw-loader!@site/examples/api/retain.sh';
|
||||
|
||||
:::info How Retain Works
|
||||
Learn about fact extraction, entity resolution, and graph construction in the [Retain Architecture](/developer/retain) guide.
|
||||
:::
|
||||
|
||||
:::tip Prerequisites
|
||||
Make sure you've completed the [Quick Start](./quickstart) to install the client and start the server.
|
||||
:::
|
||||
|
||||
## Store a Single Memory
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={retainPy} section="retain-basic" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={retainMjs} section="retain-basic" language="javascript" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
<CodeSnippet code={retainSh} section="retain-basic" language="bash" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## The Importance of Context
|
||||
|
||||
The `context` parameter is crucial for guiding how Hindsight extracts memories from your content. Think of it as providing a lens through which the system interprets the information.
|
||||
|
||||
**Why context matters:**
|
||||
- **Steers memory extraction**: Context tells the memory bank what type of information to focus on and how to interpret ambiguous content
|
||||
- **Improves relevance**: Memories extracted with proper context are more accurately categorized and easier to retrieve
|
||||
- **Disambiguates meaning**: The same sentence can have different implications depending on context (e.g., "the project was terminated" means different things in a career vs. product context)
|
||||
|
||||
## Store with Context and Date
|
||||
|
||||
Always provide context and event dates for optimal memory extraction:
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={retainPy} section="retain-with-context" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={retainMjs} section="retain-with-context" language="javascript" />
|
||||
</TabItem>
|
||||
<TabItem value="cli" label="CLI">
|
||||
<CodeSnippet code={retainSh} section="retain-with-context" language="bash" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
The `timestamp` defaults to the current time if not specified. Providing explicit timestamps enables temporal queries like "What happened last spring?"
|
||||
|
||||
### Response Fields
|
||||
|
||||
The retain response includes:
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `success` | bool | Whether the operation succeeded |
|
||||
| `bank_id` | string | The memory bank ID |
|
||||
| `items_count` | int | Number of items processed |
|
||||
| `async` | bool | Whether processed asynchronously |
|
||||
| `usage` | TokenUsage | Token usage metrics for LLM calls (synchronous only) |
|
||||
|
||||
The `usage` field contains token metrics for cost tracking:
|
||||
- `input_tokens`: Tokens consumed by prompts
|
||||
- `output_tokens`: Tokens generated by the LLM
|
||||
- `total_tokens`: Sum of input and output tokens
|
||||
|
||||
Note: `usage` is only present for synchronous operations. Async operations (`async: true`) do not return usage metrics.
|
||||
|
||||
## Batch Ingestion
|
||||
|
||||
Store multiple items in a single request. **Batch ingestion is the recommended approach** as it significantly improves performance by reducing network overhead and allowing Hindsight to optimize the memory extraction process across related content.
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={retainPy} section="retain-batch" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={retainMjs} section="retain-batch" language="javascript" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
The `document_id` groups related memories for later management.
|
||||
|
||||
## Store from Files
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="cli" label="CLI">
|
||||
|
||||
```bash
|
||||
# Single file
|
||||
hindsight memory retain-files my-bank document.txt
|
||||
|
||||
# Directory (recursive by default)
|
||||
hindsight memory retain-files my-bank ./documents/
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
|
||||
## Async Ingestion
|
||||
|
||||
For large batches, use async ingestion to avoid blocking:
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={retainPy} section="retain-async" language="python" />
|
||||
</TabItem>
|
||||
<TabItem value="node" label="Node.js">
|
||||
<CodeSnippet code={retainMjs} section="retain-async" language="javascript" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## Tagging Memories
|
||||
|
||||
Tags enable **visibility scoping**—useful when one memory bank serves multiple users but each should only see relevant memories. For example, an agent that chats with multiple users can tag memories by user ID and filter during recall.
|
||||
|
||||
### Tag Individual Items
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={retainPy} section="retain-with-tags" language="python" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### Apply Tags to All Items in a Batch
|
||||
|
||||
Use `document_tags` to apply the same tags to all items in a request:
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={retainPy} section="retain-with-document-tags" language="python" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
When both `document_tags` and item-level `tags` are provided, they are merged together.
|
||||
|
||||
### Tag Naming Conventions
|
||||
|
||||
Use consistent naming patterns for tags:
|
||||
|
||||
| Pattern | Example | Use Case |
|
||||
|---------|---------|----------|
|
||||
| `user:<id>` | `user:alice` | Multi-user agent filtering |
|
||||
| `session:<id>` | `session:123` | Session-based scoping |
|
||||
| `room:<id>` | `room:general` | Chat room isolation |
|
||||
| `topic:<name>` | `topic:feedback` | Topic categorization |
|
||||
|
||||
### Listing Tags
|
||||
|
||||
Use the list tags API to discover existing tags, useful for UI autocomplete or wildcard expansion:
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="python" label="Python">
|
||||
<CodeSnippet code={retainPy} section="retain-list-tags" language="python" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
See [Recall API](./recall#filter-by-tags) for filtering memories by tags during retrieval.
|
||||
|
|
@ -0,0 +1,455 @@
|
|||
# Configuration
|
||||
|
||||
Complete reference for configuring Hindsight services through environment variables.
|
||||
|
||||
Hindsight has two services, each with its own configuration prefix:
|
||||
|
||||
| Service | Prefix | Description |
|
||||
|---------|--------|-------------|
|
||||
| **API Service** | `HINDSIGHT_API_*` | Core memory engine |
|
||||
| **Control Plane** | `HINDSIGHT_CP_*` | Web UI |
|
||||
|
||||
---
|
||||
|
||||
## API Service
|
||||
|
||||
The API service handles all memory operations (retain, recall, reflect).
|
||||
|
||||
### Database
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| `HINDSIGHT_API_DATABASE_URL` | PostgreSQL connection string | `pg0` (embedded) |
|
||||
| `HINDSIGHT_API_RUN_MIGRATIONS_ON_STARTUP` | Run database migrations on API startup | `true` |
|
||||
|
||||
If not provided, the server uses embedded `pg0` — convenient for development but not recommended for production.
|
||||
|
||||
### Database Connection Pool
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| `HINDSIGHT_API_DB_POOL_MIN_SIZE` | Minimum connections in the pool | `5` |
|
||||
| `HINDSIGHT_API_DB_POOL_MAX_SIZE` | Maximum connections in the pool | `100` |
|
||||
| `HINDSIGHT_API_DB_COMMAND_TIMEOUT` | PostgreSQL command timeout in seconds | `60` |
|
||||
| `HINDSIGHT_API_DB_ACQUIRE_TIMEOUT` | Connection acquisition timeout in seconds | `30` |
|
||||
|
||||
For high-concurrency workloads, increase `DB_POOL_MAX_SIZE`. Each concurrent recall/think operation can use 2-4 connections.
|
||||
|
||||
To run migrations manually (e.g., before starting the API), use the admin CLI:
|
||||
|
||||
```bash
|
||||
hindsight-admin run-db-migration
|
||||
# Or for a specific schema:
|
||||
hindsight-admin run-db-migration --schema tenant_acme
|
||||
```
|
||||
|
||||
### LLM Provider
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| `HINDSIGHT_API_LLM_PROVIDER` | Provider: `openai`, `anthropic`, `gemini`, `groq`, `ollama`, `lmstudio` | `openai` |
|
||||
| `HINDSIGHT_API_LLM_API_KEY` | API key for LLM provider | - |
|
||||
| `HINDSIGHT_API_LLM_MODEL` | Model name | `gpt-5-mini` |
|
||||
| `HINDSIGHT_API_LLM_BASE_URL` | Custom LLM endpoint | Provider default |
|
||||
| `HINDSIGHT_API_LLM_MAX_CONCURRENT` | Max concurrent LLM requests | `32` |
|
||||
| `HINDSIGHT_API_LLM_TIMEOUT` | LLM request timeout in seconds | `120` |
|
||||
| `HINDSIGHT_API_LLM_GROQ_SERVICE_TIER` | Groq service tier: `on_demand`, `flex`, `auto` | `auto` |
|
||||
|
||||
**Provider Examples**
|
||||
|
||||
```bash
|
||||
# Groq (recommended for fast inference)
|
||||
export HINDSIGHT_API_LLM_PROVIDER=groq
|
||||
export HINDSIGHT_API_LLM_API_KEY=gsk_xxxxxxxxxxxx
|
||||
export HINDSIGHT_API_LLM_MODEL=openai/gpt-oss-20b
|
||||
# For free tier users: override to on_demand if you get service_tier errors
|
||||
# export HINDSIGHT_API_LLM_GROQ_SERVICE_TIER=on_demand
|
||||
|
||||
# OpenAI
|
||||
export HINDSIGHT_API_LLM_PROVIDER=openai
|
||||
export HINDSIGHT_API_LLM_API_KEY=sk-xxxxxxxxxxxx
|
||||
export HINDSIGHT_API_LLM_MODEL=gpt-4o
|
||||
|
||||
# Gemini
|
||||
export HINDSIGHT_API_LLM_PROVIDER=gemini
|
||||
export HINDSIGHT_API_LLM_API_KEY=xxxxxxxxxxxx
|
||||
export HINDSIGHT_API_LLM_MODEL=gemini-2.0-flash
|
||||
|
||||
# Anthropic
|
||||
export HINDSIGHT_API_LLM_PROVIDER=anthropic
|
||||
export HINDSIGHT_API_LLM_API_KEY=sk-ant-xxxxxxxxxxxx
|
||||
export HINDSIGHT_API_LLM_MODEL=claude-sonnet-4-20250514
|
||||
|
||||
# Ollama (local, no API key)
|
||||
export HINDSIGHT_API_LLM_PROVIDER=ollama
|
||||
export HINDSIGHT_API_LLM_BASE_URL=http://localhost:11434/v1
|
||||
export HINDSIGHT_API_LLM_MODEL=llama3
|
||||
|
||||
# LM Studio (local, no API key)
|
||||
export HINDSIGHT_API_LLM_PROVIDER=lmstudio
|
||||
export HINDSIGHT_API_LLM_BASE_URL=http://localhost:1234/v1
|
||||
export HINDSIGHT_API_LLM_MODEL=your-local-model
|
||||
|
||||
# OpenAI-compatible endpoint
|
||||
export HINDSIGHT_API_LLM_PROVIDER=openai
|
||||
export HINDSIGHT_API_LLM_BASE_URL=https://your-endpoint.com/v1
|
||||
export HINDSIGHT_API_LLM_API_KEY=your-api-key
|
||||
export HINDSIGHT_API_LLM_MODEL=your-model-name
|
||||
```
|
||||
|
||||
### Per-Operation LLM Configuration
|
||||
|
||||
Different memory operations have different requirements. **Retain** (fact extraction) benefits from models with strong structured output capabilities, while **Reflect** (reasoning/response generation) can use lighter, faster models. Configure separate LLM models for each operation to optimize for cost and performance.
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| `HINDSIGHT_API_RETAIN_LLM_PROVIDER` | LLM provider for retain operations | Falls back to `HINDSIGHT_API_LLM_PROVIDER` |
|
||||
| `HINDSIGHT_API_RETAIN_LLM_API_KEY` | API key for retain LLM | Falls back to `HINDSIGHT_API_LLM_API_KEY` |
|
||||
| `HINDSIGHT_API_RETAIN_LLM_MODEL` | Model for retain operations | Falls back to `HINDSIGHT_API_LLM_MODEL` |
|
||||
| `HINDSIGHT_API_RETAIN_LLM_BASE_URL` | Base URL for retain LLM | Falls back to `HINDSIGHT_API_LLM_BASE_URL` |
|
||||
| `HINDSIGHT_API_REFLECT_LLM_PROVIDER` | LLM provider for reflect operations | Falls back to `HINDSIGHT_API_LLM_PROVIDER` |
|
||||
| `HINDSIGHT_API_REFLECT_LLM_API_KEY` | API key for reflect LLM | Falls back to `HINDSIGHT_API_LLM_API_KEY` |
|
||||
| `HINDSIGHT_API_REFLECT_LLM_MODEL` | Model for reflect operations | Falls back to `HINDSIGHT_API_LLM_MODEL` |
|
||||
| `HINDSIGHT_API_REFLECT_LLM_BASE_URL` | Base URL for reflect LLM | Falls back to `HINDSIGHT_API_LLM_BASE_URL` |
|
||||
| `HINDSIGHT_API_CONSOLIDATION_LLM_PROVIDER` | LLM provider for observation consolidation | Falls back to `HINDSIGHT_API_LLM_PROVIDER` |
|
||||
| `HINDSIGHT_API_CONSOLIDATION_LLM_API_KEY` | API key for consolidation LLM | Falls back to `HINDSIGHT_API_LLM_API_KEY` |
|
||||
| `HINDSIGHT_API_CONSOLIDATION_LLM_MODEL` | Model for consolidation operations | Falls back to `HINDSIGHT_API_LLM_MODEL` |
|
||||
| `HINDSIGHT_API_CONSOLIDATION_LLM_BASE_URL` | Base URL for consolidation LLM | Falls back to `HINDSIGHT_API_LLM_BASE_URL` |
|
||||
|
||||
:::tip When to Use Per-Operation Config
|
||||
- **Retain**: Use models with strong structured output (e.g., GPT-4o, Claude) for accurate fact extraction
|
||||
- **Reflect**: Use faster/cheaper models (e.g., GPT-4o-mini, Groq) for reasoning and response generation
|
||||
- **Recall**: Does not use LLM (pure retrieval), so no configuration needed
|
||||
:::
|
||||
|
||||
**Example: Separate Models for Retain and Reflect**
|
||||
|
||||
```bash
|
||||
# Default LLM (used as fallback)
|
||||
export HINDSIGHT_API_LLM_PROVIDER=openai
|
||||
export HINDSIGHT_API_LLM_API_KEY=sk-xxxxxxxxxxxx
|
||||
export HINDSIGHT_API_LLM_MODEL=gpt-4o
|
||||
|
||||
# Use GPT-4o for retain (strong structured output)
|
||||
export HINDSIGHT_API_RETAIN_LLM_MODEL=gpt-4o
|
||||
|
||||
# Use faster/cheaper model for reflect
|
||||
export HINDSIGHT_API_REFLECT_LLM_PROVIDER=groq
|
||||
export HINDSIGHT_API_REFLECT_LLM_API_KEY=gsk_xxxxxxxxxxxx
|
||||
export HINDSIGHT_API_REFLECT_LLM_MODEL=llama-3.3-70b-versatile
|
||||
```
|
||||
|
||||
### Embeddings
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| `HINDSIGHT_API_EMBEDDINGS_PROVIDER` | Provider: `local`, `tei`, `openai`, `cohere`, or `litellm` | `local` |
|
||||
| `HINDSIGHT_API_EMBEDDINGS_LOCAL_MODEL` | Model for local provider | `BAAI/bge-small-en-v1.5` |
|
||||
| `HINDSIGHT_API_EMBEDDINGS_TEI_URL` | TEI server URL | - |
|
||||
| `HINDSIGHT_API_EMBEDDINGS_OPENAI_API_KEY` | OpenAI API key (falls back to `HINDSIGHT_API_LLM_API_KEY`) | - |
|
||||
| `HINDSIGHT_API_EMBEDDINGS_OPENAI_MODEL` | OpenAI embedding model | `text-embedding-3-small` |
|
||||
| `HINDSIGHT_API_EMBEDDINGS_OPENAI_BASE_URL` | Custom base URL for OpenAI-compatible API (e.g., Azure OpenAI) | - |
|
||||
| `HINDSIGHT_API_COHERE_API_KEY` | Cohere API key (shared for embeddings and reranker) | - |
|
||||
| `HINDSIGHT_API_EMBEDDINGS_COHERE_MODEL` | Cohere embedding model | `embed-english-v3.0` |
|
||||
| `HINDSIGHT_API_EMBEDDINGS_COHERE_BASE_URL` | Custom base URL for Cohere-compatible API (e.g., Azure-hosted) | - |
|
||||
| `HINDSIGHT_API_LITELLM_API_BASE` | LiteLLM proxy base URL (shared for embeddings and reranker) | `http://localhost:4000` |
|
||||
| `HINDSIGHT_API_LITELLM_API_KEY` | LiteLLM proxy API key (optional, depends on proxy config) | - |
|
||||
| `HINDSIGHT_API_EMBEDDINGS_LITELLM_MODEL` | LiteLLM embedding model (use provider prefix, e.g., `cohere/embed-english-v3.0`) | `text-embedding-3-small` |
|
||||
|
||||
```bash
|
||||
# Local (default) - uses SentenceTransformers
|
||||
export HINDSIGHT_API_EMBEDDINGS_PROVIDER=local
|
||||
export HINDSIGHT_API_EMBEDDINGS_LOCAL_MODEL=BAAI/bge-small-en-v1.5
|
||||
|
||||
# OpenAI - cloud-based embeddings
|
||||
export HINDSIGHT_API_EMBEDDINGS_PROVIDER=openai
|
||||
export HINDSIGHT_API_EMBEDDINGS_OPENAI_API_KEY=sk-xxxxxxxxxxxx # or reuses HINDSIGHT_API_LLM_API_KEY
|
||||
export HINDSIGHT_API_EMBEDDINGS_OPENAI_MODEL=text-embedding-3-small # 1536 dimensions
|
||||
|
||||
# Azure OpenAI - embeddings via Azure endpoint
|
||||
export HINDSIGHT_API_EMBEDDINGS_PROVIDER=openai
|
||||
export HINDSIGHT_API_EMBEDDINGS_OPENAI_API_KEY=your-azure-api-key
|
||||
export HINDSIGHT_API_EMBEDDINGS_OPENAI_MODEL=text-embedding-3-small
|
||||
export HINDSIGHT_API_EMBEDDINGS_OPENAI_BASE_URL=https://your-resource.openai.azure.com/openai/deployments/your-deployment
|
||||
|
||||
# TEI - HuggingFace Text Embeddings Inference (recommended for production)
|
||||
export HINDSIGHT_API_EMBEDDINGS_PROVIDER=tei
|
||||
export HINDSIGHT_API_EMBEDDINGS_TEI_URL=http://localhost:8080
|
||||
|
||||
# Cohere - cloud-based embeddings
|
||||
export HINDSIGHT_API_EMBEDDINGS_PROVIDER=cohere
|
||||
export HINDSIGHT_API_COHERE_API_KEY=your-api-key
|
||||
export HINDSIGHT_API_EMBEDDINGS_COHERE_MODEL=embed-english-v3.0 # 1024 dimensions
|
||||
|
||||
# Azure-hosted Cohere - embeddings via custom endpoint
|
||||
export HINDSIGHT_API_EMBEDDINGS_PROVIDER=cohere
|
||||
export HINDSIGHT_API_COHERE_API_KEY=your-azure-api-key
|
||||
export HINDSIGHT_API_EMBEDDINGS_COHERE_MODEL=embed-english-v3.0
|
||||
export HINDSIGHT_API_EMBEDDINGS_COHERE_BASE_URL=https://your-azure-cohere-endpoint.com
|
||||
|
||||
# LiteLLM proxy - unified gateway for multiple providers
|
||||
export HINDSIGHT_API_EMBEDDINGS_PROVIDER=litellm
|
||||
export HINDSIGHT_API_LITELLM_API_BASE=http://localhost:4000
|
||||
export HINDSIGHT_API_LITELLM_API_KEY=your-litellm-key # optional
|
||||
export HINDSIGHT_API_EMBEDDINGS_LITELLM_MODEL=text-embedding-3-small # or cohere/embed-english-v3.0
|
||||
```
|
||||
|
||||
#### Embedding Dimensions
|
||||
|
||||
Hindsight automatically detects the embedding dimension from the model at startup and adjusts the database schema accordingly. The default model (`BAAI/bge-small-en-v1.5`) produces 384-dimensional vectors, while OpenAI models produce 1536 or 3072 dimensions.
|
||||
|
||||
:::warning Dimension Changes
|
||||
Once memories are stored, you cannot change the embedding dimension without losing data. If you need to switch to a model with different dimensions:
|
||||
|
||||
1. **Empty database**: The schema is adjusted automatically on startup
|
||||
2. **Existing data**: Either delete all memories first, or use a model with matching dimensions
|
||||
|
||||
Supported OpenAI embedding dimensions:
|
||||
- `text-embedding-3-small`: 1536 dimensions
|
||||
- `text-embedding-3-large`: 3072 dimensions
|
||||
- `text-embedding-ada-002`: 1536 dimensions (legacy)
|
||||
:::
|
||||
|
||||
### Reranker
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| `HINDSIGHT_API_RERANKER_PROVIDER` | Provider: `local`, `tei`, `cohere`, `flashrank`, `litellm`, or `rrf` | `local` |
|
||||
| `HINDSIGHT_API_RERANKER_LOCAL_MODEL` | Model for local provider | `cross-encoder/ms-marco-MiniLM-L-6-v2` |
|
||||
| `HINDSIGHT_API_RERANKER_LOCAL_MAX_CONCURRENT` | Max concurrent local reranking (prevents CPU thrashing under load) | `4` |
|
||||
| `HINDSIGHT_API_RERANKER_TEI_URL` | TEI server URL | - |
|
||||
| `HINDSIGHT_API_RERANKER_TEI_BATCH_SIZE` | Batch size for TEI reranking | `128` |
|
||||
| `HINDSIGHT_API_RERANKER_TEI_MAX_CONCURRENT` | Max concurrent TEI reranking requests | `8` |
|
||||
| `HINDSIGHT_API_RERANKER_COHERE_MODEL` | Cohere rerank model | `rerank-english-v3.0` |
|
||||
| `HINDSIGHT_API_RERANKER_COHERE_BASE_URL` | Custom base URL for Cohere-compatible API (e.g., Azure-hosted) | - |
|
||||
| `HINDSIGHT_API_RERANKER_LITELLM_MODEL` | LiteLLM rerank model (use provider prefix, e.g., `cohere/rerank-english-v3.0`) | `cohere/rerank-english-v3.0` |
|
||||
| `HINDSIGHT_API_RERANKER_FLASHRANK_MODEL` | FlashRank model for fast CPU-based reranking | `ms-marco-MiniLM-L-12-v2` |
|
||||
| `HINDSIGHT_API_RERANKER_FLASHRANK_CACHE_DIR` | Cache directory for FlashRank models | System default |
|
||||
|
||||
```bash
|
||||
# Local (default) - uses SentenceTransformers CrossEncoder
|
||||
export HINDSIGHT_API_RERANKER_PROVIDER=local
|
||||
export HINDSIGHT_API_RERANKER_LOCAL_MODEL=cross-encoder/ms-marco-MiniLM-L-6-v2
|
||||
|
||||
# TEI - for high-performance inference
|
||||
export HINDSIGHT_API_RERANKER_PROVIDER=tei
|
||||
export HINDSIGHT_API_RERANKER_TEI_URL=http://localhost:8081
|
||||
|
||||
# Cohere - cloud-based reranking
|
||||
export HINDSIGHT_API_RERANKER_PROVIDER=cohere
|
||||
export HINDSIGHT_API_COHERE_API_KEY=your-api-key # shared with embeddings
|
||||
export HINDSIGHT_API_RERANKER_COHERE_MODEL=rerank-english-v3.0
|
||||
|
||||
# Azure-hosted Cohere - reranking via custom endpoint
|
||||
export HINDSIGHT_API_RERANKER_PROVIDER=cohere
|
||||
export HINDSIGHT_API_COHERE_API_KEY=your-azure-api-key
|
||||
export HINDSIGHT_API_RERANKER_COHERE_MODEL=rerank-english-v3.0
|
||||
export HINDSIGHT_API_RERANKER_COHERE_BASE_URL=https://your-azure-cohere-endpoint.com
|
||||
|
||||
# LiteLLM proxy - unified gateway for multiple reranking providers
|
||||
export HINDSIGHT_API_RERANKER_PROVIDER=litellm
|
||||
export HINDSIGHT_API_LITELLM_API_BASE=http://localhost:4000
|
||||
export HINDSIGHT_API_LITELLM_API_KEY=your-litellm-key # optional
|
||||
export HINDSIGHT_API_RERANKER_LITELLM_MODEL=cohere/rerank-english-v3.0 # or voyage/rerank-2, together_ai/...
|
||||
```
|
||||
|
||||
LiteLLM supports multiple reranking providers via the `/rerank` endpoint:
|
||||
- Cohere (`cohere/rerank-english-v3.0`, `cohere/rerank-multilingual-v3.0`)
|
||||
- Together AI (`together_ai/...`)
|
||||
- Voyage AI (`voyage/rerank-2`)
|
||||
- Jina AI (`jina_ai/...`)
|
||||
- AWS Bedrock (`bedrock/...`)
|
||||
|
||||
### Authentication
|
||||
|
||||
By default, Hindsight runs without authentication. For production deployments, enable API key authentication using the built-in tenant extension:
|
||||
|
||||
```bash
|
||||
# Enable the built-in API key authentication
|
||||
export HINDSIGHT_API_TENANT_EXTENSION=hindsight_api.extensions.builtin.tenant:ApiKeyTenantExtension
|
||||
export HINDSIGHT_API_TENANT_API_KEY=your-secret-api-key
|
||||
```
|
||||
|
||||
When enabled, all requests must include the API key in the `Authorization` header:
|
||||
|
||||
```bash
|
||||
curl -H "Authorization: Bearer your-secret-api-key" \
|
||||
http://localhost:8888/v1/default/banks
|
||||
```
|
||||
|
||||
Requests without a valid API key receive a `401 Unauthorized` response.
|
||||
|
||||
:::tip Custom Authentication
|
||||
For advanced authentication (JWT, OAuth, multi-tenant schemas), implement a custom `TenantExtension`. See the [Extensions documentation](./extensions.md) for details.
|
||||
:::
|
||||
|
||||
### Server
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| `HINDSIGHT_API_HOST` | Bind address | `0.0.0.0` |
|
||||
| `HINDSIGHT_API_PORT` | Server port | `8888` |
|
||||
| `HINDSIGHT_API_WORKERS` | Number of uvicorn worker processes | `1` |
|
||||
| `HINDSIGHT_API_LOG_LEVEL` | Log level: `debug`, `info`, `warning`, `error` | `info` |
|
||||
| `HINDSIGHT_API_LOG_FORMAT` | Log format: `text` or `json` (structured logging for cloud platforms) | `text` |
|
||||
| `HINDSIGHT_API_MCP_ENABLED` | Enable MCP server at `/mcp/{bank_id}/` | `true` |
|
||||
|
||||
### Retrieval
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| `HINDSIGHT_API_GRAPH_RETRIEVER` | Graph retrieval algorithm: `link_expansion`, `mpfp`, or `bfs` | `link_expansion` |
|
||||
| `HINDSIGHT_API_RECALL_MAX_CONCURRENT` | Max concurrent recall operations per worker (backpressure) | `32` |
|
||||
| `HINDSIGHT_API_RECALL_CONNECTION_BUDGET` | Max concurrent DB connections per recall operation | `4` |
|
||||
| `HINDSIGHT_API_RERANKER_MAX_CANDIDATES` | Max candidates to rerank per recall (RRF pre-filters the rest) | `300` |
|
||||
| `HINDSIGHT_API_MPFP_TOP_K_NEIGHBORS` | Fan-out limit per node in MPFP graph traversal | `20` |
|
||||
| `HINDSIGHT_API_MENTAL_MODEL_REFRESH_CONCURRENCY` | Max concurrent mental model refreshes | `8` |
|
||||
|
||||
#### Graph Retrieval Algorithms
|
||||
|
||||
- **`link_expansion`** (default): Fast, simple graph expansion from semantic seeds via entity co-occurrence and causal links. Target latency under 100ms. Recommended for most use cases.
|
||||
- **`mpfp`**: Multi-Path Fact Propagation - iterative graph traversal with activation spreading. More thorough but slower.
|
||||
- **`bfs`**: Breadth-first search from seed facts. Simple but less effective for large graphs.
|
||||
|
||||
### Retain
|
||||
|
||||
Controls the retain (memory ingestion) pipeline.
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| `HINDSIGHT_API_RETAIN_MAX_COMPLETION_TOKENS` | Max completion tokens for fact extraction LLM calls | `64000` |
|
||||
| `HINDSIGHT_API_RETAIN_CHUNK_SIZE` | Max characters per chunk for fact extraction. Larger chunks extract fewer LLM calls but may lose context. | `3000` |
|
||||
| `HINDSIGHT_API_RETAIN_EXTRACTION_MODE` | Fact extraction mode: `concise`, `verbose`, or `custom` | `concise` |
|
||||
| `HINDSIGHT_API_RETAIN_CUSTOM_INSTRUCTIONS` | Custom extraction guidelines (only used when mode is `custom`) | - |
|
||||
| `HINDSIGHT_API_RETAIN_EXTRACT_CAUSAL_LINKS` | Extract causal relationships between facts | `true` |
|
||||
|
||||
#### Extraction Modes
|
||||
|
||||
The extraction mode controls how aggressively facts are extracted from content:
|
||||
|
||||
- **`concise`** (default): Selective extraction that focuses on significant, long-term valuable facts. Filters out greetings, filler, and trivial information. Produces fewer but higher-quality facts with better performance.
|
||||
|
||||
- **`verbose`**: Detailed extraction that captures every piece of information with maximum verbosity. Produces more facts with extensive detail but slower performance and higher token usage.
|
||||
|
||||
- **`custom`**: Inject your own extraction guidelines while keeping the structural parts of the prompt (output format, coreference resolution, temporal handling, etc.) intact. Useful for A/B testing different extraction strategies or domain-specific customization.
|
||||
|
||||
**Example: Custom Extraction Mode**
|
||||
|
||||
```bash
|
||||
# Set mode to custom
|
||||
export HINDSIGHT_API_RETAIN_EXTRACTION_MODE=custom
|
||||
|
||||
# Define custom guidelines (multi-line is fine)
|
||||
export HINDSIGHT_API_RETAIN_CUSTOM_INSTRUCTIONS="ONLY extract facts that are:
|
||||
✅ Technical decisions and their rationale
|
||||
✅ Architecture patterns and design choices
|
||||
✅ Performance metrics and benchmarks
|
||||
✅ Code reviews and feedback
|
||||
|
||||
DO NOT extract:
|
||||
❌ Generic greetings or pleasantries
|
||||
❌ Process chatter (\"let me check\", \"one moment\")
|
||||
❌ Repeated information already captured
|
||||
|
||||
CONSOLIDATE related technical discussions into ONE fact when possible.
|
||||
|
||||
Ask yourself: 'Would this technical context be useful in 6 months?' If no, skip it."
|
||||
```
|
||||
|
||||
### Observations (Experimental)
|
||||
|
||||
Observations are consolidated knowledge synthesized from facts.
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| `HINDSIGHT_API_ENABLE_OBSERVATIONS` | Enable observation consolidation | `true` |
|
||||
| `HINDSIGHT_API_CONSOLIDATION_BATCH_SIZE` | Memories to load per batch (internal optimization) | `50` |
|
||||
| `HINDSIGHT_API_RETAIN_OBSERVATIONS_ASYNC` | Run observation generation asynchronously (after retain completes) | `false` |
|
||||
|
||||
### Reflect
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| `HINDSIGHT_API_REFLECT_MAX_ITERATIONS` | Max tool call iterations before forcing a response | `10` |
|
||||
|
||||
### Local MCP Server
|
||||
|
||||
Configuration for the local MCP server (`hindsight-local-mcp` command).
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| `HINDSIGHT_API_MCP_LOCAL_BANK_ID` | Memory bank ID for local MCP | `mcp` |
|
||||
| `HINDSIGHT_API_MCP_INSTRUCTIONS` | Additional instructions appended to retain/recall tool descriptions | - |
|
||||
|
||||
```bash
|
||||
# Example: instruct MCP to also store assistant actions
|
||||
export HINDSIGHT_API_MCP_INSTRUCTIONS="Also store every action you take, including tool calls and decisions made."
|
||||
```
|
||||
|
||||
### Distributed Workers
|
||||
|
||||
Configuration for background task processing. By default, the API processes tasks internally. For high-throughput deployments, run dedicated workers. See [Services - Worker Service](./services#worker-service) for details.
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| `HINDSIGHT_API_WORKER_ENABLED` | Enable internal worker in API process | `true` |
|
||||
| `HINDSIGHT_API_WORKER_ID` | Unique worker identifier | hostname |
|
||||
| `HINDSIGHT_API_WORKER_POLL_INTERVAL_MS` | Database polling interval in milliseconds | `500` |
|
||||
| `HINDSIGHT_API_WORKER_BATCH_SIZE` | Tasks to claim per poll cycle | `10` |
|
||||
| `HINDSIGHT_API_WORKER_MAX_RETRIES` | Max retries before marking task failed | `3` |
|
||||
| `HINDSIGHT_API_WORKER_HTTP_PORT` | HTTP port for worker metrics/health (worker CLI only) | `8889` |
|
||||
|
||||
### Performance Optimization
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| `HINDSIGHT_API_SKIP_LLM_VERIFICATION` | Skip LLM connection check on startup | `false` |
|
||||
| `HINDSIGHT_API_LAZY_RERANKER` | Lazy-load reranker model (faster startup) | `false` |
|
||||
|
||||
### Programmatic Configuration
|
||||
|
||||
You can also configure the API programmatically using `MemoryEngine.from_env()`:
|
||||
|
||||
```python
|
||||
from hindsight_api import MemoryEngine
|
||||
|
||||
memory = MemoryEngine.from_env()
|
||||
await memory.initialize()
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Control Plane
|
||||
|
||||
The Control Plane is the web UI for managing memory banks.
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| `HINDSIGHT_CP_DATAPLANE_API_URL` | URL of the API service | `http://localhost:8888` |
|
||||
|
||||
```bash
|
||||
# Point Control Plane to a remote API service
|
||||
export HINDSIGHT_CP_DATAPLANE_API_URL=http://api.example.com:8888
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Example .env File
|
||||
|
||||
```bash
|
||||
# API Service
|
||||
HINDSIGHT_API_DATABASE_URL=postgresql://hindsight:hindsight_dev@localhost:5432/hindsight
|
||||
HINDSIGHT_API_LLM_PROVIDER=groq
|
||||
HINDSIGHT_API_LLM_API_KEY=gsk_xxxxxxxxxxxx
|
||||
|
||||
# Authentication (optional, recommended for production)
|
||||
# HINDSIGHT_API_TENANT_EXTENSION=hindsight_api.extensions.builtin.tenant:ApiKeyTenantExtension
|
||||
# HINDSIGHT_API_TENANT_API_KEY=your-secret-api-key
|
||||
|
||||
# Control Plane
|
||||
HINDSIGHT_CP_DATAPLANE_API_URL=http://localhost:8888
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
For configuration issues not covered here, please [open an issue](https://github.com/vectorize-io/hindsight/issues) on GitHub.
|
||||
|
|
@ -0,0 +1,149 @@
|
|||
---
|
||||
sidebar_position: 7
|
||||
---
|
||||
|
||||
# Development Guide
|
||||
|
||||
Guide to setting up a local development environment for contributing to Hindsight.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Python 3.11+
|
||||
- [uv](https://docs.astral.sh/uv/) - Fast Python package manager
|
||||
- Docker and Docker Compose
|
||||
- An LLM API key (OpenAI, Groq, or Ollama)
|
||||
|
||||
## Local Development Setup
|
||||
|
||||
### 1. Clone the Repository
|
||||
|
||||
```bash
|
||||
git clone https://github.com/vectorize-io/hindsight.git
|
||||
cd hindsight
|
||||
```
|
||||
|
||||
### 2. Install Dependencies
|
||||
|
||||
```bash
|
||||
uv sync
|
||||
```
|
||||
|
||||
### 3. Start PostgreSQL
|
||||
|
||||
Start only the database via Docker:
|
||||
|
||||
```bash
|
||||
cd docker && docker-compose up -d postgres
|
||||
```
|
||||
|
||||
### 4. Configure Environment
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
Edit `.env` with your LLM API key:
|
||||
|
||||
```bash
|
||||
# Database (connects to Docker postgres)
|
||||
HINDSIGHT_API_DATABASE_URL=postgresql://hindsight:hindsight_dev@localhost:5432/hindsight
|
||||
|
||||
# LLM Provider (choose one)
|
||||
HINDSIGHT_API_LLM_PROVIDER=groq
|
||||
HINDSIGHT_API_LLM_API_KEY=gsk_xxxxxxxxxxxx
|
||||
HINDSIGHT_API_LLM_MODEL=llama-3.1-70b-versatile
|
||||
```
|
||||
|
||||
### 5. Start the API Server
|
||||
|
||||
```bash
|
||||
./scripts/start-server.sh --env local
|
||||
```
|
||||
|
||||
The server will be available at http://localhost:8888.
|
||||
|
||||
## Running Tests
|
||||
|
||||
```bash
|
||||
# Run all tests
|
||||
uv run pytest
|
||||
|
||||
# Run specific test file
|
||||
uv run pytest tests/test_retrieval.py
|
||||
|
||||
# Run with verbose output
|
||||
uv run pytest -v
|
||||
```
|
||||
|
||||
## Code Generation
|
||||
|
||||
### Regenerate API Clients
|
||||
|
||||
When you modify the OpenAPI spec, regenerate the clients:
|
||||
|
||||
```bash
|
||||
./scripts/generate-clients.sh
|
||||
```
|
||||
|
||||
This generates:
|
||||
- Python client in `hindsight-clients/python/`
|
||||
- TypeScript client in `hindsight-clients/typescript/`
|
||||
|
||||
### Export OpenAPI Schema
|
||||
|
||||
```bash
|
||||
./scripts/export-openapi.sh
|
||||
```
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
hindsight/
|
||||
├── hindsight-api/ # Main API server
|
||||
│ ├── hindsight_api/
|
||||
│ │ ├── api/ # HTTP endpoints
|
||||
│ │ ├── engine/ # Memory engine, retrieval, reasoning
|
||||
│ │ └── web/ # Server entry point
|
||||
│ └── tests/
|
||||
├── hindsight-clients/ # Generated SDK clients
|
||||
│ ├── python/
|
||||
│ └── typescript/
|
||||
├── hindsight-control-plane/ # Admin UI (Next.js)
|
||||
├── docker/ # Docker Compose setup
|
||||
└── scripts/ # Development scripts
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
1. Create a feature branch from `main`
|
||||
2. Make your changes
|
||||
3. Run tests: `uv run pytest`
|
||||
4. Submit a pull request
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Database Connection Issues
|
||||
|
||||
Ensure PostgreSQL is running:
|
||||
|
||||
```bash
|
||||
docker-compose ps
|
||||
```
|
||||
|
||||
Check database connectivity:
|
||||
|
||||
```bash
|
||||
psql postgresql://hindsight:hindsight_dev@localhost:5432/hindsight
|
||||
```
|
||||
|
||||
### ML Model Download
|
||||
|
||||
On first run, Hindsight downloads embedding and reranking models. This may take a few minutes. Models are cached in `~/.cache/huggingface/`.
|
||||
|
||||
### Port Conflicts
|
||||
|
||||
If port 8888 is in use:
|
||||
|
||||
```bash
|
||||
HINDSIGHT_API_PORT=8889 ./scripts/start-server.sh --env local
|
||||
```
|
||||
|
|
@ -0,0 +1,226 @@
|
|||
# Extensions
|
||||
|
||||
Extensions allow you to customize and extend Hindsight behavior without modifying core code. They enable multi-tenancy, custom authentication, additional HTTP endpoints, and operation hooks.
|
||||
|
||||
---
|
||||
|
||||
## Available Extensions
|
||||
|
||||
### TenantExtension
|
||||
|
||||
Handles multi-tenancy and API key authentication. Validates incoming requests and determines which PostgreSQL schema to use for database operations, enabling tenant isolation at the database level.
|
||||
|
||||
**Built-in: ApiKeyTenantExtension**
|
||||
|
||||
A simple implementation that validates API keys against an environment variable and uses the `public` schema for all authenticated requests.
|
||||
|
||||
```bash
|
||||
HINDSIGHT_API_TENANT_EXTENSION=hindsight_api.extensions.builtin.tenant:ApiKeyTenantExtension
|
||||
HINDSIGHT_API_TENANT_API_KEY=your-secret-key
|
||||
```
|
||||
|
||||
For multi-tenant setups with separate schemas per tenant (e.g., JWT-based auth with per-tenant schemas), implement a custom `TenantExtension`.
|
||||
|
||||
---
|
||||
|
||||
### HttpExtension
|
||||
|
||||
Adds custom HTTP endpoints under the `/ext/` path prefix. Useful for adding domain-specific APIs that integrate with Hindsight's memory engine.
|
||||
|
||||
**No built-in implementation** - implement your own to add custom endpoints.
|
||||
|
||||
```bash
|
||||
HINDSIGHT_API_HTTP_EXTENSION=mypackage.ext:MyHttpExtension
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### OperationValidatorExtension
|
||||
|
||||
Hooks into retain/recall/reflect operations for validation and monitoring. Use cases include:
|
||||
- Rate limiting and quota enforcement
|
||||
- Permission checks and content filtering
|
||||
- Audit logging and usage tracking
|
||||
- Custom metrics collection
|
||||
|
||||
**No built-in implementation** - implement your own based on your requirements.
|
||||
|
||||
```bash
|
||||
HINDSIGHT_API_OPERATION_VALIDATOR_EXTENSION=mypackage.validators:MyValidator
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Writing Custom Extensions
|
||||
|
||||
### Extension Basics
|
||||
|
||||
Extensions are Python classes loaded via environment variables:
|
||||
|
||||
```bash
|
||||
HINDSIGHT_API_<TYPE>_EXTENSION=mypackage.module:MyExtensionClass
|
||||
```
|
||||
|
||||
Configuration is passed via prefixed environment variables:
|
||||
|
||||
```bash
|
||||
HINDSIGHT_API_<TYPE>_SOME_CONFIG=value
|
||||
# Extension receives: {"some_config": "value"}
|
||||
```
|
||||
|
||||
All extensions support lifecycle hooks:
|
||||
- `on_startup()` - Called when the application starts
|
||||
- `on_shutdown()` - Called when the application shuts down
|
||||
|
||||
Extensions have access to an `ExtensionContext` that provides:
|
||||
- `run_migration(schema)` - Run database migrations for a schema
|
||||
- `get_memory_engine()` - Get the MemoryEngine interface
|
||||
|
||||
### Example: Custom TenantExtension with JWT
|
||||
|
||||
```python
|
||||
import jwt
|
||||
from hindsight_api.extensions import TenantExtension, TenantContext, AuthenticationError
|
||||
|
||||
class JwtTenantExtension(TenantExtension):
|
||||
def __init__(self, config: dict[str, str]):
|
||||
super().__init__(config)
|
||||
self.jwt_secret = config.get("jwt_secret")
|
||||
if not self.jwt_secret:
|
||||
raise ValueError("HINDSIGHT_API_TENANT_JWT_SECRET is required")
|
||||
|
||||
async def authenticate(self, context: RequestContext) -> TenantContext:
|
||||
token = context.api_key
|
||||
if not token:
|
||||
raise AuthenticationError("Bearer token required")
|
||||
|
||||
try:
|
||||
payload = jwt.decode(token, self.jwt_secret, algorithms=["HS256"])
|
||||
tenant_id = payload.get("tenant_id")
|
||||
if not tenant_id:
|
||||
raise AuthenticationError("Missing tenant_id in token")
|
||||
return TenantContext(schema_name=f"tenant_{tenant_id}")
|
||||
except jwt.InvalidTokenError as e:
|
||||
raise AuthenticationError(str(e))
|
||||
```
|
||||
|
||||
### Example: Custom HttpExtension
|
||||
|
||||
```python
|
||||
from fastapi import APIRouter
|
||||
from hindsight_api.extensions import HttpExtension
|
||||
|
||||
class MyHttpExtension(HttpExtension):
|
||||
def get_router(self, memory: MemoryEngine) -> APIRouter:
|
||||
router = APIRouter()
|
||||
|
||||
@router.get("/hello")
|
||||
async def hello():
|
||||
return {"message": "Hello from extension!"}
|
||||
|
||||
@router.post("/custom/{bank_id}/action")
|
||||
async def custom_action(bank_id: str):
|
||||
# Access memory engine for database operations
|
||||
pool = await memory._get_pool()
|
||||
# ... custom logic
|
||||
return {"status": "ok"}
|
||||
|
||||
return router
|
||||
```
|
||||
|
||||
Routes are available at `/ext/hello`, `/ext/custom/{bank_id}/action`, etc.
|
||||
|
||||
### Example: Custom OperationValidatorExtension
|
||||
|
||||
```python
|
||||
from hindsight_api.extensions import (
|
||||
OperationValidatorExtension,
|
||||
ValidationResult,
|
||||
RetainContext,
|
||||
RecallContext,
|
||||
ReflectContext,
|
||||
RetainResult,
|
||||
)
|
||||
|
||||
class MyValidator(OperationValidatorExtension):
|
||||
# Pre-operation validation (required)
|
||||
async def validate_retain(self, ctx: RetainContext) -> ValidationResult:
|
||||
# Implement your validation logic
|
||||
return ValidationResult.accept()
|
||||
# Or reject: return ValidationResult.reject("Reason")
|
||||
|
||||
async def validate_recall(self, ctx: RecallContext) -> ValidationResult:
|
||||
return ValidationResult.accept()
|
||||
|
||||
async def validate_reflect(self, ctx: ReflectContext) -> ValidationResult:
|
||||
return ValidationResult.accept()
|
||||
|
||||
# Post-operation hooks (optional)
|
||||
async def on_retain_complete(self, result: RetainResult) -> None:
|
||||
# Log usage, update metrics, send notifications, etc.
|
||||
pass
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Deploying Custom Extensions
|
||||
|
||||
### With Docker
|
||||
|
||||
Mount your extension package as a volume and set the environment variable:
|
||||
|
||||
```yaml
|
||||
# docker-compose.yml
|
||||
services:
|
||||
hindsight-api:
|
||||
image: vectorize/hindsight-api:latest
|
||||
volumes:
|
||||
- ./my_extensions:/app/my_extensions
|
||||
environment:
|
||||
- HINDSIGHT_API_TENANT_EXTENSION=my_extensions.auth:JwtTenantExtension
|
||||
- HINDSIGHT_API_TENANT_JWT_SECRET=${JWT_SECRET}
|
||||
- PYTHONPATH=/app
|
||||
```
|
||||
|
||||
Or build a custom image with your extensions:
|
||||
|
||||
```dockerfile
|
||||
FROM vectorize/hindsight-api:latest
|
||||
COPY my_extensions /app/my_extensions
|
||||
ENV PYTHONPATH=/app
|
||||
```
|
||||
|
||||
### Bare Metal
|
||||
|
||||
Install your extension package in the same Python environment as Hindsight:
|
||||
|
||||
```bash
|
||||
# Install Hindsight
|
||||
pip install hindsight-api
|
||||
|
||||
# Install your extension package
|
||||
pip install ./my-extensions
|
||||
# or
|
||||
pip install my-extensions-package
|
||||
|
||||
# Configure
|
||||
export HINDSIGHT_API_TENANT_EXTENSION=my_extensions.auth:JwtTenantExtension
|
||||
export HINDSIGHT_API_TENANT_JWT_SECRET=your-secret
|
||||
|
||||
# Run
|
||||
hindsight-api
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Contributing Extensions
|
||||
|
||||
Custom extensions that solve common use cases are welcome contributions to the Hindsight project. If you've built an extension for:
|
||||
|
||||
- Authentication providers (OAuth, SAML, API gateways)
|
||||
- Rate limiting or quota management
|
||||
- Audit logging integrations
|
||||
- Metrics exporters (Datadog, New Relic, etc.)
|
||||
- Custom HTTP endpoints for specific platforms
|
||||
|
||||
Consider contributing it to the `hindsight_api.extensions.builtin` package. Open an issue or pull request on [GitHub](https://github.com/vectorize-io/hindsight) to discuss your extension.
|
||||
138
hindsight-docs/versioned_docs/version-0.4/developer/index.md
Normal file
138
hindsight-docs/versioned_docs/version-0.4/developer/index.md
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
---
|
||||
sidebar_position: 1
|
||||
slug: /
|
||||
---
|
||||
|
||||
# Overview
|
||||
|
||||
## Why Hindsight?
|
||||
|
||||
AI agents forget everything between sessions. Every conversation starts from zero—no context about who you are, what you've discussed, or what the assistant has learned. This isn't just an implementation detail; it fundamentally limits what AI Agents can do.
|
||||
|
||||
**The problem is harder than it looks:**
|
||||
|
||||
- **Simple vector search isn't enough** — "What did Alice do last spring?" requires temporal reasoning, not just semantic similarity
|
||||
- **Facts get disconnected** — Knowing "Alice works at Google" and "Google is in Mountain View" should let you answer "Where does Alice work?" even if you never stored that directly
|
||||
- **AI Agents need to consolidate knowledge** — A coding assistant that remembers "the user prefers functional programming" should consolidate this into an observation and weigh it when making recommendations
|
||||
- **Context matters** — The same information means different things to different memory banks with different personalities
|
||||
|
||||
Hindsight solves these problems with a memory system designed specifically for AI agents.
|
||||
|
||||
## What Hindsight Does
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
subgraph app["<b>Your Application</b>"]
|
||||
Agent[AI Agent]
|
||||
end
|
||||
|
||||
subgraph hindsight["<b>Hindsight</b>"]
|
||||
API[API Server]
|
||||
|
||||
subgraph bank["<b>Memory Bank</b>"]
|
||||
direction TB
|
||||
MentalModels[Mental Models]
|
||||
Observations[Observations]
|
||||
MemEnt[Memories & Entities]
|
||||
Chunks[Chunks]
|
||||
Documents[Documents]
|
||||
|
||||
MentalModels --> Observations --> MemEnt --> Chunks --> Documents
|
||||
end
|
||||
end
|
||||
|
||||
Agent -->|retain| API
|
||||
Agent -->|recall| API
|
||||
Agent -->|reflect| API
|
||||
|
||||
API --> bank
|
||||
```
|
||||
|
||||
**Your AI agent** stores information via `retain()`, searches with `recall()`, and reasons with `reflect()` — all interactions with its dedicated **memory bank**
|
||||
|
||||
## Key Components
|
||||
|
||||
### Memory Types
|
||||
|
||||
Hindsight organizes knowledge into a hierarchy of facts and consolidated knowledge:
|
||||
|
||||
| Type | What it stores | Example |
|
||||
|------|----------------|---------|
|
||||
| **Mental Model** | User-curated summaries for common queries | "Team communication best practices" |
|
||||
| **Observation** | Automatically consolidated knowledge from facts | "User was a React enthusiast but has now switched to Vue" (captures history) |
|
||||
| **World Fact** | Objective facts received | "Alice works at Google" |
|
||||
| **Experience Fact** | Bank's own actions and interactions | "I recommended Python to Bob" |
|
||||
|
||||
During reflect, the agent checks sources in priority order: **Mental Models → Observations → Raw Facts**.
|
||||
|
||||
### Multi-Strategy Retrieval (TEMPR)
|
||||
|
||||
Four search strategies run in parallel:
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
Q[Query] --> S[Semantic]
|
||||
Q --> K[Keyword]
|
||||
Q --> G[Graph]
|
||||
Q --> T[Temporal]
|
||||
|
||||
S --> RRF[RRF Fusion]
|
||||
K --> RRF
|
||||
G --> RRF
|
||||
T --> RRF
|
||||
|
||||
RRF --> CE[Cross-Encoder]
|
||||
CE --> R[Results]
|
||||
```
|
||||
|
||||
| Strategy | Best for |
|
||||
|----------|----------|
|
||||
| **Semantic** | Conceptual similarity, paraphrasing |
|
||||
| **Keyword (BM25)** | Names, technical terms, exact matches |
|
||||
| **Graph** | Related entities, indirect connections |
|
||||
| **Temporal** | "last spring", "in June", time ranges |
|
||||
|
||||
### Observation Consolidation
|
||||
|
||||
After memories are retained, Hindsight automatically consolidates related facts into **observations** — synthesized knowledge representations that capture patterns and learnings:
|
||||
|
||||
- **Automatic synthesis**: New facts are analyzed and consolidated into existing or new observations
|
||||
- **Evidence tracking**: Each observation tracks which facts support it
|
||||
- **Continuous refinement**: Observations evolve as new evidence arrives
|
||||
|
||||
### Mission, Directives & Disposition
|
||||
|
||||
Memory banks can be configured to shape how the agent reasons during `reflect`:
|
||||
|
||||
| Configuration | Purpose | Example |
|
||||
|---------------|---------|---------|
|
||||
| **Mission** | Natural language identity for the bank | "I am a research assistant specializing in ML. I prefer simplicity over cutting-edge." |
|
||||
| **Directives** | Hard rules the agent must follow | "Never recommend specific stocks", "Always cite sources" |
|
||||
| **Disposition** | Soft traits that influence reasoning style | Skepticism, literalism, empathy (1-5 scale) |
|
||||
|
||||
The **mission** tells Hindsight what knowledge to prioritize and provides context for reasoning. **Directives** are guardrails and compliance rules that must never be violated. **Disposition traits** subtly influence interpretation style.
|
||||
|
||||
These settings only affect the `reflect` operation, not `recall`.
|
||||
|
||||
## Next Steps
|
||||
|
||||
### Getting Started
|
||||
- [**Quick Start**](/developer/api/quickstart) — Install and get up and running in 60 seconds
|
||||
- [**RAG vs Hindsight**](/developer/rag-vs-hindsight) — See how Hindsight differs from traditional RAG with real examples
|
||||
|
||||
### Core Concepts
|
||||
- [**Retain**](/developer/retain) — How memories are stored with multi-dimensional facts
|
||||
- [**Recall**](/developer/retrieval) — How TEMPR's 4-way search retrieves memories
|
||||
- [**Reflect**](/developer/reflect) — How mission, directives, and disposition shape reasoning
|
||||
|
||||
### API Methods
|
||||
- [**Retain**](/developer/api/retain) — Store information in memory banks
|
||||
- [**Recall**](/developer/api/recall) — Search and retrieve memories
|
||||
- [**Reflect**](/developer/api/reflect) — Agentic reasoning with memory
|
||||
- [**Mental Models**](/developer/api/mental-models) — User-curated summaries for common queries
|
||||
- [**Memory Banks**](/developer/api/memory-banks) — Configure mission, directives, and disposition
|
||||
- [**Documents**](/developer/api/documents) — Manage document sources
|
||||
- [**Operations**](/developer/api/operations) — Monitor async tasks
|
||||
|
||||
### Deployment
|
||||
- [**Server Setup**](/developer/installation) — Deploy with Docker Compose, Helm, or pip
|
||||
|
|
@ -0,0 +1,184 @@
|
|||
# Installation
|
||||
|
||||
Hindsight can be deployed in several ways depending on your infrastructure and requirements.
|
||||
|
||||
:::tip Don't want to manage infrastructure?
|
||||
**[Hindsight Cloud](https://vectorize.io/hindsight/cloud)** is a fully managed service that handles all infrastructure, scaling, and maintenance. We're onboarding design partners now — [request early access](https://vectorize.io/hindsight/cloud).
|
||||
:::
|
||||
|
||||
## Prerequisites
|
||||
|
||||
### PostgreSQL with pgvector
|
||||
|
||||
Hindsight requires PostgreSQL with the **pgvector** extension for vector similarity search.
|
||||
|
||||
**By default**, Hindsight uses **pg0** — an embedded PostgreSQL that runs locally on your machine. This is convenient for development but **not recommended for production**.
|
||||
|
||||
**For production**, use an external PostgreSQL with pgvector:
|
||||
- **Supabase** — Managed PostgreSQL with pgvector built-in
|
||||
- **Neon** — Serverless PostgreSQL with pgvector
|
||||
- **AWS RDS** / **Cloud SQL** / **Azure** — With pgvector extension enabled
|
||||
- **Self-hosted** — PostgreSQL 14+ with pgvector installed
|
||||
|
||||
### LLM Provider
|
||||
|
||||
You need an LLM API key for fact extraction, entity resolution, and answer generation:
|
||||
|
||||
- **Groq** (recommended): Fast inference with `gpt-oss-20b`
|
||||
- **OpenAI**: GPT-4o, GPT-4o-mini
|
||||
- **Ollama**: Run models locally
|
||||
|
||||
See [Models](./models) for detailed comparison and configuration.
|
||||
|
||||
---
|
||||
|
||||
## Docker
|
||||
|
||||
**Best for**: Quick start, development, small deployments
|
||||
|
||||
Run everything in one container with embedded PostgreSQL:
|
||||
|
||||
```bash
|
||||
export OPENAI_API_KEY=sk-xxx
|
||||
|
||||
docker run --rm -it --pull always -p 8888:8888 -p 9999:9999 \
|
||||
-e HINDSIGHT_API_LLM_API_KEY=$OPENAI_API_KEY \
|
||||
-v $HOME/.hindsight-docker:/home/hindsight/.pg0 \
|
||||
ghcr.io/vectorize-io/hindsight:latest
|
||||
```
|
||||
|
||||
- **API Server**: http://localhost:8888
|
||||
- **Control Plane** (Web UI): http://localhost:9999
|
||||
|
||||
---
|
||||
|
||||
## Helm / Kubernetes
|
||||
|
||||
**Best for**: Production deployments, auto-scaling, cloud environments
|
||||
|
||||
```bash
|
||||
# Install with built-in PostgreSQL
|
||||
helm install hindsight oci://ghcr.io/vectorize-io/charts/hindsight \
|
||||
--set api.llm.provider=groq \
|
||||
--set api.llm.apiKey=gsk_xxxxxxxxxxxx \
|
||||
--set postgresql.enabled=true
|
||||
|
||||
# Or use external PostgreSQL
|
||||
helm install hindsight oci://ghcr.io/vectorize-io/charts/hindsight \
|
||||
--set api.llm.provider=groq \
|
||||
--set api.llm.apiKey=gsk_xxxxxxxxxxxx \
|
||||
--set postgresql.enabled=false \
|
||||
--set api.database.url=postgresql://user:pass@postgres.example.com:5432/hindsight
|
||||
|
||||
# Install a specific version
|
||||
helm install hindsight oci://ghcr.io/vectorize-io/charts/hindsight --version 0.1.3
|
||||
|
||||
# Upgrade to latest
|
||||
helm upgrade hindsight oci://ghcr.io/vectorize-io/charts/hindsight
|
||||
```
|
||||
|
||||
**Requirements**:
|
||||
- Kubernetes cluster (GKE, EKS, AKS, or self-hosted)
|
||||
- Helm 3.8+
|
||||
|
||||
### Distributed Workers
|
||||
|
||||
For high-throughput deployments, enable dedicated worker pods to scale task processing independently:
|
||||
|
||||
```bash
|
||||
helm install hindsight oci://ghcr.io/vectorize-io/charts/hindsight \
|
||||
--set worker.enabled=true \
|
||||
--set worker.replicaCount=3
|
||||
```
|
||||
|
||||
See [Services - Worker Service](./services#worker-service) for configuration details and architecture.
|
||||
|
||||
See the [Helm chart values.yaml](https://github.com/vectorize-io/hindsight/tree/main/helm/hindsight/values.yaml) for all chart options.
|
||||
|
||||
---
|
||||
|
||||
## Bare Metal (pip)
|
||||
|
||||
**Best for**: Custom deployments, integration into existing Python applications
|
||||
|
||||
### Install
|
||||
|
||||
```bash
|
||||
pip install hindsight-all
|
||||
```
|
||||
|
||||
### Run with Embedded Database
|
||||
|
||||
For development and testing, Hindsight can run with an embedded PostgreSQL (pg0):
|
||||
|
||||
```bash
|
||||
export HINDSIGHT_API_LLM_PROVIDER=groq
|
||||
export HINDSIGHT_API_LLM_API_KEY=gsk_xxxxxxxxxxxx
|
||||
|
||||
hindsight-api
|
||||
```
|
||||
|
||||
This creates a database in `~/.hindsight/data/` and starts the API on http://localhost:8888.
|
||||
|
||||
### Run with External PostgreSQL
|
||||
|
||||
For production, connect to your own PostgreSQL instance:
|
||||
|
||||
```bash
|
||||
export HINDSIGHT_API_DATABASE_URL=postgresql://user:pass@localhost:5432/hindsight
|
||||
export HINDSIGHT_API_LLM_PROVIDER=groq
|
||||
export HINDSIGHT_API_LLM_API_KEY=gsk_xxxxxxxxxxxx
|
||||
|
||||
hindsight-api
|
||||
```
|
||||
|
||||
**Note**: The database must exist and have pgvector enabled (`CREATE EXTENSION vector;`).
|
||||
|
||||
### CLI Options
|
||||
|
||||
```bash
|
||||
hindsight-api --port 9000 # Custom port (default: 8888)
|
||||
hindsight-api --host 127.0.0.1 # Bind to localhost only
|
||||
hindsight-api --workers 4 # Multiple worker processes
|
||||
hindsight-api --log-level debug # Verbose logging
|
||||
```
|
||||
|
||||
### Control Plane
|
||||
|
||||
The Control Plane (Web UI) can be run standalone using npx:
|
||||
|
||||
```bash
|
||||
npx @vectorize-io/hindsight-control-plane --api-url http://localhost:8888
|
||||
```
|
||||
|
||||
This connects to your running API server and provides a visual interface for managing memory banks, exploring entities, and testing queries.
|
||||
|
||||
#### Options
|
||||
|
||||
| Option | Environment Variable | Default | Description |
|
||||
|--------|---------------------|---------|-------------|
|
||||
| `-p, --port` | `PORT` | 9999 | Port to listen on |
|
||||
| `-H, --hostname` | `HOSTNAME` | 0.0.0.0 | Hostname to bind to |
|
||||
| `-a, --api-url` | `HINDSIGHT_CP_DATAPLANE_API_URL` | http://localhost:8888 | Hindsight API URL |
|
||||
|
||||
#### Examples
|
||||
|
||||
```bash
|
||||
# Run on custom port
|
||||
npx @vectorize-io/hindsight-control-plane --port 9999 --api-url http://localhost:8888
|
||||
|
||||
# Using environment variables
|
||||
export HINDSIGHT_CP_DATAPLANE_API_URL=http://api.example.com
|
||||
npx @vectorize-io/hindsight-control-plane
|
||||
|
||||
# Production deployment
|
||||
PORT=80 HINDSIGHT_CP_DATAPLANE_API_URL=https://api.hindsight.io npx @vectorize-io/hindsight-control-plane
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [Configuration](./configuration.md) — Environment variables and settings
|
||||
- [Models](./models.md) — ML models and providers
|
||||
- [Monitoring](./monitoring.md) — Metrics and observability
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
---
|
||||
sidebar_position: 5
|
||||
---
|
||||
|
||||
# MCP Server
|
||||
|
||||
Hindsight includes a built-in [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) server that allows AI assistants to store and retrieve memories directly.
|
||||
|
||||
## Access
|
||||
|
||||
The MCP server is **enabled by default** and mounted at `/mcp` on the API server. Each memory bank has its own MCP endpoint:
|
||||
|
||||
```
|
||||
http://localhost:8888/mcp/{bank_id}/
|
||||
```
|
||||
|
||||
For example, to connect to the memory bank `alice`:
|
||||
```
|
||||
http://localhost:8888/mcp/alice/
|
||||
```
|
||||
|
||||
To disable the MCP server, set the environment variable:
|
||||
|
||||
```bash
|
||||
export HINDSIGHT_API_MCP_ENABLED=false
|
||||
```
|
||||
|
||||
## Per-Bank Endpoints
|
||||
|
||||
Unlike traditional MCP servers where tools require explicit identifiers, Hindsight uses **per-bank endpoints**. The `bank_id` is part of the URL path, so tools don't need to specify which bank to use—it's implicit from the connection.
|
||||
|
||||
This design:
|
||||
- **Simplifies tool usage** — no need to pass `bank_id` with every call
|
||||
- **Enforces isolation** — each MCP connection is scoped to a single bank
|
||||
- **Enables multi-tenant setups** — connect different users to different endpoints
|
||||
|
||||
---
|
||||
|
||||
## Available Tools
|
||||
|
||||
### retain
|
||||
|
||||
Store information to long-term memory.
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|----------|-------------|
|
||||
| `content` | string | Yes | The fact or memory to store |
|
||||
| `context` | string | No | Category for the memory (default: `general`) |
|
||||
|
||||
**Example:**
|
||||
```json
|
||||
{
|
||||
"name": "retain",
|
||||
"arguments": {
|
||||
"content": "User prefers Python over JavaScript for backend development",
|
||||
"context": "programming_preferences"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**When to use:**
|
||||
- User shares personal facts, preferences, or interests
|
||||
- Important events or milestones are mentioned
|
||||
- Decisions, opinions, or goals are stated
|
||||
- Work context or project details are discussed
|
||||
|
||||
---
|
||||
|
||||
### recall
|
||||
|
||||
Search memories to provide personalized responses.
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|----------|-------------|
|
||||
| `query` | string | Yes | Natural language search query |
|
||||
| `max_results` | integer | No | Maximum results to return (default: 10) |
|
||||
|
||||
**Example:**
|
||||
```json
|
||||
{
|
||||
"name": "recall",
|
||||
"arguments": {
|
||||
"query": "What are the user's programming language preferences?"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"id": "fact_abc123",
|
||||
"text": "User prefers Python over JavaScript for backend development",
|
||||
"type": "world",
|
||||
"context": "programming_preferences",
|
||||
"event_date": null
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**When to use:**
|
||||
- Start of conversation to recall relevant context
|
||||
- Before making recommendations
|
||||
- When user asks about something they may have mentioned before
|
||||
- To provide continuity across conversations
|
||||
|
||||
---
|
||||
|
||||
## Integration with AI Assistants
|
||||
|
||||
The MCP server can be used with any MCP-compatible AI assistant.
|
||||
|
||||
### Claude Desktop Configuration
|
||||
|
||||
To connect Claude Desktop to a specific memory bank:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"hindsight-alice": {
|
||||
"url": "http://localhost:8888/mcp/alice/"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Each user can have their own MCP server configuration pointing to their personal memory bank.
|
||||
237
hindsight-docs/versioned_docs/version-0.4/developer/models.md
Normal file
237
hindsight-docs/versioned_docs/version-0.4/developer/models.md
Normal file
|
|
@ -0,0 +1,237 @@
|
|||
# Models
|
||||
|
||||
Hindsight uses several machine learning models for different tasks.
|
||||
|
||||
## Overview
|
||||
|
||||
| Model Type | Purpose | Default | Configurable |
|
||||
|------------|---------|---------|--------------|
|
||||
| **LLM** | Fact extraction, reasoning, generation | Provider-specific | Yes |
|
||||
| **Embedding** | Vector representations for semantic search | `BAAI/bge-small-en-v1.5` | Yes |
|
||||
| **Cross-Encoder** | Reranking search results | `cross-encoder/ms-marco-MiniLM-L-6-v2` | Yes |
|
||||
|
||||
All local models (embedding, cross-encoder) are automatically downloaded from HuggingFace on first run.
|
||||
|
||||
---
|
||||
|
||||
## LLM
|
||||
|
||||
Used for fact extraction, entity resolution, mental model consolidation, and answer synthesis.
|
||||
|
||||
**Supported providers:** OpenAI, Anthropic, Gemini, Groq, Ollama, LM Studio, and **any OpenAI-compatible API**
|
||||
|
||||
:::tip OpenAI-Compatible Providers
|
||||
Hindsight works with any provider that exposes an OpenAI-compatible API (e.g., Azure OpenAI). Simply set `HINDSIGHT_API_LLM_PROVIDER=openai` and configure `HINDSIGHT_API_LLM_BASE_URL` to point to your provider's endpoint.
|
||||
|
||||
See [Configuration](./configuration#llm-provider) for setup examples.
|
||||
:::
|
||||
|
||||
### Tested Models
|
||||
|
||||
The following models have been tested and verified to work correctly with Hindsight:
|
||||
|
||||
| Provider | Model |
|
||||
|----------|-------|
|
||||
| **OpenAI** | `gpt-5.2` |
|
||||
| **OpenAI** | `gpt-5` |
|
||||
| **OpenAI** | `gpt-5-mini` |
|
||||
| **OpenAI** | `gpt-5-nano` |
|
||||
| **OpenAI** | `gpt-4.1-mini` |
|
||||
| **OpenAI** | `gpt-4.1-nano` |
|
||||
| **OpenAI** | `gpt-4o-mini` |
|
||||
| **Anthropic** | `claude-sonnet-4-20250514` |
|
||||
| **Anthropic** | `claude-3-5-sonnet-20241022` |
|
||||
| **Gemini** | `gemini-3-pro-preview` |
|
||||
| **Gemini** | `gemini-2.5-flash` |
|
||||
| **Gemini** | `gemini-2.5-flash-lite` |
|
||||
| **Groq** | `openai/gpt-oss-120b` |
|
||||
| **Groq** | `openai/gpt-oss-20b` |
|
||||
|
||||
### Using Other Models
|
||||
|
||||
Other LLM models not listed above may work with Hindsight, but they must support **at least 65,000 output tokens** to ensure reliable fact extraction. If you need support for a specific model that doesn't meet this requirement, please [open an issue](https://github.com/hindsight-ai/hindsight/issues) to request an exception.
|
||||
|
||||
### Configuration
|
||||
|
||||
```bash
|
||||
# Groq (recommended)
|
||||
export HINDSIGHT_API_LLM_PROVIDER=groq
|
||||
export HINDSIGHT_API_LLM_API_KEY=gsk_xxxxxxxxxxxx
|
||||
export HINDSIGHT_API_LLM_MODEL=openai/gpt-oss-20b
|
||||
|
||||
# OpenAI
|
||||
export HINDSIGHT_API_LLM_PROVIDER=openai
|
||||
export HINDSIGHT_API_LLM_API_KEY=sk-xxxxxxxxxxxx
|
||||
export HINDSIGHT_API_LLM_MODEL=gpt-4o
|
||||
|
||||
# Gemini
|
||||
export HINDSIGHT_API_LLM_PROVIDER=gemini
|
||||
export HINDSIGHT_API_LLM_API_KEY=xxxxxxxxxxxx
|
||||
export HINDSIGHT_API_LLM_MODEL=gemini-2.0-flash
|
||||
|
||||
# Anthropic
|
||||
export HINDSIGHT_API_LLM_PROVIDER=anthropic
|
||||
export HINDSIGHT_API_LLM_API_KEY=sk-ant-xxxxxxxxxxxx
|
||||
export HINDSIGHT_API_LLM_MODEL=claude-sonnet-4-20250514
|
||||
|
||||
# Ollama (local)
|
||||
export HINDSIGHT_API_LLM_PROVIDER=ollama
|
||||
export HINDSIGHT_API_LLM_BASE_URL=http://localhost:11434/v1
|
||||
export HINDSIGHT_API_LLM_MODEL=llama3
|
||||
|
||||
# LM Studio (local)
|
||||
export HINDSIGHT_API_LLM_PROVIDER=lmstudio
|
||||
export HINDSIGHT_API_LLM_BASE_URL=http://localhost:1234/v1
|
||||
export HINDSIGHT_API_LLM_MODEL=your-local-model
|
||||
```
|
||||
|
||||
**Note:** The LLM is the primary bottleneck for retain operations. See [Performance](./performance) for optimization strategies.
|
||||
|
||||
---
|
||||
|
||||
## Embedding Model
|
||||
|
||||
Converts text into dense vector representations for semantic similarity search.
|
||||
|
||||
**Default:** `BAAI/bge-small-en-v1.5` (384 dimensions, ~130MB)
|
||||
|
||||
### Supported Providers
|
||||
|
||||
| Provider | Description | Best For |
|
||||
|----------|-------------|----------|
|
||||
| `local` | SentenceTransformers (default) | Development, low latency |
|
||||
| `openai` | OpenAI embeddings API | Production, high quality |
|
||||
| `cohere` | Cohere embeddings API | Production, multilingual |
|
||||
| `tei` | HuggingFace Text Embeddings Inference | Production, self-hosted |
|
||||
| `litellm` | LiteLLM proxy (unified gateway) | Multi-provider setups |
|
||||
|
||||
### Local Models
|
||||
|
||||
| Model | Dimensions | Use Case |
|
||||
|-------|------------|----------|
|
||||
| `BAAI/bge-small-en-v1.5` | 384 | Default, fast, good quality |
|
||||
| `sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2` | 384 | Multilingual (50+ languages) |
|
||||
|
||||
### OpenAI Models
|
||||
|
||||
| Model | Dimensions | Use Case |
|
||||
|-------|------------|----------|
|
||||
| `text-embedding-3-small` | 1536 | Default OpenAI, cost-effective |
|
||||
| `text-embedding-3-large` | 3072 | Higher quality, more expensive |
|
||||
| `text-embedding-ada-002` | 1536 | Legacy model |
|
||||
|
||||
### Cohere Models
|
||||
|
||||
| Model | Dimensions | Use Case |
|
||||
|-------|------------|----------|
|
||||
| `embed-english-v3.0` | 1024 | English text |
|
||||
| `embed-multilingual-v3.0` | 1024 | 100+ languages |
|
||||
|
||||
:::warning Embedding Dimensions
|
||||
Hindsight automatically detects the embedding dimension at startup and adjusts the database schema. Once memories are stored, you cannot change dimensions without losing data.
|
||||
:::
|
||||
|
||||
**Configuration Examples:**
|
||||
|
||||
```bash
|
||||
# Local provider (default)
|
||||
export HINDSIGHT_API_EMBEDDINGS_PROVIDER=local
|
||||
export HINDSIGHT_API_EMBEDDINGS_LOCAL_MODEL=BAAI/bge-small-en-v1.5
|
||||
|
||||
# OpenAI
|
||||
export HINDSIGHT_API_EMBEDDINGS_PROVIDER=openai
|
||||
export HINDSIGHT_API_EMBEDDINGS_OPENAI_API_KEY=sk-xxxxxxxxxxxx
|
||||
export HINDSIGHT_API_EMBEDDINGS_OPENAI_MODEL=text-embedding-3-small
|
||||
|
||||
# Cohere
|
||||
export HINDSIGHT_API_EMBEDDINGS_PROVIDER=cohere
|
||||
export HINDSIGHT_API_COHERE_API_KEY=your-api-key
|
||||
export HINDSIGHT_API_EMBEDDINGS_COHERE_MODEL=embed-english-v3.0
|
||||
|
||||
# TEI (self-hosted)
|
||||
export HINDSIGHT_API_EMBEDDINGS_PROVIDER=tei
|
||||
export HINDSIGHT_API_EMBEDDINGS_TEI_URL=http://localhost:8080
|
||||
|
||||
# LiteLLM proxy
|
||||
export HINDSIGHT_API_EMBEDDINGS_PROVIDER=litellm
|
||||
export HINDSIGHT_API_LITELLM_API_BASE=http://localhost:4000
|
||||
export HINDSIGHT_API_EMBEDDINGS_LITELLM_MODEL=text-embedding-3-small
|
||||
```
|
||||
|
||||
See [Configuration](./configuration#embeddings) for all options including Azure OpenAI and custom endpoints.
|
||||
|
||||
---
|
||||
|
||||
## Cross-Encoder (Reranker)
|
||||
|
||||
Reranks initial search results to improve precision.
|
||||
|
||||
**Default:** `cross-encoder/ms-marco-MiniLM-L-6-v2` (~85MB)
|
||||
|
||||
### Supported Providers
|
||||
|
||||
| Provider | Description | Best For |
|
||||
|----------|-------------|----------|
|
||||
| `local` | SentenceTransformers CrossEncoder (default) | Development, low latency |
|
||||
| `cohere` | Cohere rerank API | Production, high quality |
|
||||
| `tei` | HuggingFace Text Embeddings Inference | Production, self-hosted |
|
||||
| `flashrank` | FlashRank (lightweight, fast) | Resource-constrained environments |
|
||||
| `litellm` | LiteLLM proxy (unified gateway) | Multi-provider setups |
|
||||
| `rrf` | RRF-only (no neural reranking) | Testing, minimal resources |
|
||||
|
||||
### Local Models
|
||||
|
||||
| Model | Use Case |
|
||||
|-------|----------|
|
||||
| `cross-encoder/ms-marco-MiniLM-L-6-v2` | Default, fast |
|
||||
| `cross-encoder/ms-marco-MiniLM-L-12-v2` | Higher accuracy |
|
||||
| `cross-encoder/mmarco-mMiniLMv2-L12-H384-v1` | Multilingual |
|
||||
|
||||
### Cohere Models
|
||||
|
||||
| Model | Use Case |
|
||||
|-------|----------|
|
||||
| `rerank-english-v3.0` | English text |
|
||||
| `rerank-multilingual-v3.0` | 100+ languages |
|
||||
|
||||
### LiteLLM Supported Providers
|
||||
|
||||
LiteLLM supports multiple reranking providers via the `/rerank` endpoint:
|
||||
|
||||
| Provider | Model Example |
|
||||
|----------|---------------|
|
||||
| Cohere | `cohere/rerank-english-v3.0` |
|
||||
| Together AI | `together_ai/...` |
|
||||
| Voyage AI | `voyage/rerank-2` |
|
||||
| Jina AI | `jina_ai/...` |
|
||||
| AWS Bedrock | `bedrock/...` |
|
||||
|
||||
**Configuration Examples:**
|
||||
|
||||
```bash
|
||||
# Local provider (default)
|
||||
export HINDSIGHT_API_RERANKER_PROVIDER=local
|
||||
export HINDSIGHT_API_RERANKER_LOCAL_MODEL=cross-encoder/ms-marco-MiniLM-L-6-v2
|
||||
|
||||
# Cohere
|
||||
export HINDSIGHT_API_RERANKER_PROVIDER=cohere
|
||||
export HINDSIGHT_API_COHERE_API_KEY=your-api-key
|
||||
export HINDSIGHT_API_RERANKER_COHERE_MODEL=rerank-english-v3.0
|
||||
|
||||
# TEI (self-hosted)
|
||||
export HINDSIGHT_API_RERANKER_PROVIDER=tei
|
||||
export HINDSIGHT_API_RERANKER_TEI_URL=http://localhost:8081
|
||||
|
||||
# FlashRank (lightweight)
|
||||
export HINDSIGHT_API_RERANKER_PROVIDER=flashrank
|
||||
|
||||
# LiteLLM proxy
|
||||
export HINDSIGHT_API_RERANKER_PROVIDER=litellm
|
||||
export HINDSIGHT_API_LITELLM_API_BASE=http://localhost:4000
|
||||
export HINDSIGHT_API_RERANKER_LITELLM_MODEL=cohere/rerank-english-v3.0
|
||||
|
||||
# RRF-only (no neural reranking)
|
||||
export HINDSIGHT_API_RERANKER_PROVIDER=rrf
|
||||
```
|
||||
|
||||
See [Configuration](./configuration#reranker) for all options including Azure-hosted endpoints and batch settings.
|
||||
|
|
@ -0,0 +1,199 @@
|
|||
# Monitoring
|
||||
|
||||
Hindsight provides comprehensive monitoring through Prometheus metrics and pre-built Grafana dashboards.
|
||||
|
||||
## Local Development
|
||||
|
||||
For local metrics visualization, a convenience script downloads and runs Prometheus and Grafana:
|
||||
|
||||
```bash
|
||||
./scripts/dev/start-monitoring.sh
|
||||
```
|
||||
|
||||
This will start:
|
||||
- **Grafana**: http://localhost:8890 (anonymous access enabled)
|
||||
- **Prometheus**: http://localhost:8889
|
||||
- **API Metrics**: http://localhost:8888/metrics
|
||||
|
||||
:::note Production Deployment
|
||||
The local monitoring script is for development only. In production, you need to install and configure Prometheus and Grafana separately, then point Prometheus to scrape your Hindsight API's `/metrics` endpoint.
|
||||
:::
|
||||
|
||||
## Grafana Dashboards
|
||||
|
||||
Pre-built dashboards are available in [`monitoring/grafana/dashboards/`](https://github.com/anthropics/hindsight/tree/main/monitoring/grafana/dashboards). Import these JSON files into your Grafana instance:
|
||||
|
||||
| Dashboard | Description |
|
||||
|-----------|-------------|
|
||||
| **Hindsight Operations** | Operation rates, latency percentiles, per-bank metrics |
|
||||
| **Hindsight LLM Metrics** | LLM calls, token usage, latency by scope/provider |
|
||||
| **Hindsight API Service** | HTTP requests, error rates, DB pool, process metrics |
|
||||
|
||||
The dashboards are automatically provisioned when using the monitoring stack script.
|
||||
|
||||
## Metrics Endpoint
|
||||
|
||||
Hindsight exposes Prometheus metrics at `/metrics`:
|
||||
|
||||
```bash
|
||||
curl http://localhost:8888/metrics
|
||||
```
|
||||
|
||||
## Available Metrics
|
||||
|
||||
### Operation Metrics
|
||||
|
||||
| Metric | Type | Labels | Description |
|
||||
|--------|------|--------|-------------|
|
||||
| `hindsight.operation.duration` | Histogram | operation, bank_id, source, budget, max_tokens, success | Duration of operations in seconds |
|
||||
| `hindsight.operation.total` | Counter | operation, bank_id, source, budget, max_tokens, success | Total number of operations executed |
|
||||
|
||||
**Labels:**
|
||||
- `operation`: Operation type (`retain`, `recall`, `reflect`)
|
||||
- `bank_id`: Memory bank identifier
|
||||
- `source`: Where the operation was triggered from (`api`, `reflect`, `internal`)
|
||||
- `budget`: Budget level if specified (`low`, `mid`, `high`)
|
||||
- `max_tokens`: Max tokens if specified
|
||||
- `success`: Whether the operation succeeded (`true`, `false`)
|
||||
|
||||
The `source` label allows distinguishing between:
|
||||
- `api`: Direct API calls from clients
|
||||
- `reflect`: Internal recall calls made during reflect operations
|
||||
- `internal`: Other internal operations
|
||||
|
||||
### LLM Metrics
|
||||
|
||||
| Metric | Type | Labels | Description |
|
||||
|--------|------|--------|-------------|
|
||||
| `hindsight.llm.duration` | Histogram | provider, model, scope, success | Duration of LLM API calls in seconds |
|
||||
| `hindsight.llm.calls.total` | Counter | provider, model, scope, success | Total number of LLM API calls |
|
||||
| `hindsight.llm.tokens.input` | Counter | provider, model, scope, success, token_bucket | Input tokens for LLM calls |
|
||||
| `hindsight.llm.tokens.output` | Counter | provider, model, scope, success, token_bucket | Output tokens from LLM calls |
|
||||
|
||||
**Labels:**
|
||||
- `provider`: LLM provider (`openai`, `anthropic`, `gemini`, `groq`, `ollama`, `lmstudio`)
|
||||
- `model`: Model name (e.g., `gpt-4`, `claude-3-sonnet`)
|
||||
- `scope`: What the LLM call is for (`memory`, `reflect`, `consolidation`, `answer`)
|
||||
- `success`: Whether the call succeeded (`true`, `false`)
|
||||
- `token_bucket`: Token count bucket for cardinality control (`0-100`, `100-500`, `500-1k`, `1k-5k`, `5k-10k`, `10k-50k`, `50k+`)
|
||||
|
||||
### HTTP Request Metrics
|
||||
|
||||
| Metric | Type | Labels | Description |
|
||||
|--------|------|--------|-------------|
|
||||
| `hindsight.http.duration` | Histogram | method, endpoint, status_code, status_class | Duration of HTTP requests in seconds |
|
||||
| `hindsight.http.requests.total` | Counter | method, endpoint, status_code, status_class | Total number of HTTP requests |
|
||||
| `hindsight.http.requests.in_progress` | UpDownCounter | method, endpoint | Number of HTTP requests currently being processed |
|
||||
|
||||
**Labels:**
|
||||
- `method`: HTTP method (`GET`, `POST`, `PUT`, `DELETE`)
|
||||
- `endpoint`: Request path (normalized to reduce cardinality - UUIDs replaced with `{id}`)
|
||||
- `status_code`: HTTP status code (`200`, `400`, `500`, etc.)
|
||||
- `status_class`: Status code class (`2xx`, `4xx`, `5xx`)
|
||||
|
||||
### Database Pool Metrics
|
||||
|
||||
| Metric | Type | Labels | Description |
|
||||
|--------|------|--------|-------------|
|
||||
| `hindsight.db.pool.size` | Gauge | - | Current number of connections in the pool |
|
||||
| `hindsight.db.pool.idle` | Gauge | - | Number of idle connections in the pool |
|
||||
| `hindsight.db.pool.min` | Gauge | - | Minimum pool size |
|
||||
| `hindsight.db.pool.max` | Gauge | - | Maximum pool size |
|
||||
|
||||
### Process Metrics
|
||||
|
||||
| Metric | Type | Labels | Description |
|
||||
|--------|------|--------|-------------|
|
||||
| `hindsight.process.cpu.seconds` | Gauge | type | Process CPU time in seconds |
|
||||
| `hindsight.process.memory.bytes` | Gauge | type | Process memory usage in bytes |
|
||||
| `hindsight.process.open_fds` | Gauge | - | Number of open file descriptors |
|
||||
| `hindsight.process.threads` | Gauge | - | Number of active threads |
|
||||
|
||||
**Labels:**
|
||||
- `type` (CPU): `user` or `system`
|
||||
- `type` (Memory): `rss_max` (maximum resident set size)
|
||||
|
||||
### Histogram Buckets
|
||||
|
||||
Custom bucket boundaries are configured for better percentile accuracy:
|
||||
|
||||
**Operation Duration Buckets (seconds):**
|
||||
```
|
||||
0.1, 0.25, 0.5, 0.75, 1.0, 2.0, 3.0, 5.0, 7.5, 10.0, 15.0, 20.0, 30.0, 60.0, 120.0
|
||||
```
|
||||
|
||||
**LLM Duration Buckets (seconds):**
|
||||
```
|
||||
0.1, 0.25, 0.5, 1.0, 2.0, 3.0, 5.0, 10.0, 15.0, 30.0, 60.0, 120.0
|
||||
```
|
||||
|
||||
**HTTP Duration Buckets (seconds):**
|
||||
```
|
||||
0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0, 10.0, 30.0
|
||||
```
|
||||
|
||||
## Prometheus Configuration
|
||||
|
||||
```yaml
|
||||
scrape_configs:
|
||||
- job_name: 'hindsight'
|
||||
static_configs:
|
||||
- targets: ['localhost:8888']
|
||||
```
|
||||
|
||||
## Example Queries
|
||||
|
||||
### Average operation latency by type
|
||||
```promql
|
||||
rate(hindsight_operation_duration_sum[5m]) / rate(hindsight_operation_duration_count[5m])
|
||||
```
|
||||
|
||||
### LLM calls per minute by provider
|
||||
```promql
|
||||
rate(hindsight_llm_calls_total[1m]) * 60
|
||||
```
|
||||
|
||||
### P95 LLM latency
|
||||
```promql
|
||||
histogram_quantile(0.95, rate(hindsight_llm_duration_bucket[5m]))
|
||||
```
|
||||
|
||||
### Total tokens consumed by model
|
||||
```promql
|
||||
sum by (model) (hindsight_llm_tokens_input_total + hindsight_llm_tokens_output_total)
|
||||
```
|
||||
|
||||
### Internal vs API recall operations
|
||||
```promql
|
||||
sum by (source) (rate(hindsight_operation_total{operation="recall"}[5m]))
|
||||
```
|
||||
|
||||
### HTTP requests per second by endpoint
|
||||
```promql
|
||||
sum by (endpoint) (rate(hindsight_http_requests_total[1m]))
|
||||
```
|
||||
|
||||
### HTTP error rate (5xx)
|
||||
```promql
|
||||
sum(rate(hindsight_http_requests_total{status_class="5xx"}[5m])) / sum(rate(hindsight_http_requests_total[5m]))
|
||||
```
|
||||
|
||||
### P95 HTTP latency
|
||||
```promql
|
||||
histogram_quantile(0.95, sum by (le) (rate(hindsight_http_duration_seconds_bucket[5m])))
|
||||
```
|
||||
|
||||
### Database pool utilization
|
||||
```promql
|
||||
hindsight_db_pool_size / hindsight_db_pool_max
|
||||
```
|
||||
|
||||
### Active database connections
|
||||
```promql
|
||||
hindsight_db_pool_size - hindsight_db_pool_idle
|
||||
```
|
||||
|
||||
### CPU usage rate
|
||||
```promql
|
||||
rate(hindsight_process_cpu_seconds{type="user"}[1m])
|
||||
```
|
||||
|
|
@ -0,0 +1,217 @@
|
|||
---
|
||||
sidebar_position: 5
|
||||
---
|
||||
|
||||
# Multilingual Support
|
||||
|
||||
Hindsight automatically detects the language of your input and responds in the same language. This means facts, entities, and reflect responses are preserved in their original language without translation to English.
|
||||
|
||||
## How It Works
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
A[Chinese Input] --> B[Language Detection]
|
||||
B --> C[Extract Facts in Chinese]
|
||||
C --> D[Chinese Entities]
|
||||
D --> E[Chinese Response]
|
||||
```
|
||||
|
||||
When you retain content or reflect on a query, Hindsight:
|
||||
|
||||
1. **Detects the input language** automatically from the content
|
||||
2. **Extracts facts in the original language** - preserving nuance and meaning
|
||||
3. **Stores entities in their native script** - 张伟 stays 张伟, not "Zhang Wei"
|
||||
4. **Responds in the same language** - queries in Chinese get Chinese answers
|
||||
|
||||
---
|
||||
|
||||
## Retain with Non-English Content
|
||||
|
||||
When you retain content in any language, Hindsight extracts and stores facts in that same language.
|
||||
|
||||
### Example: Chinese Content
|
||||
|
||||
```python
|
||||
from hindsight import Hindsight
|
||||
|
||||
hindsight = Hindsight()
|
||||
|
||||
# Retain Chinese content
|
||||
hindsight.retain(
|
||||
bank_id="user-123",
|
||||
content="""
|
||||
张伟是一位资深软件工程师,在腾讯工作了五年。
|
||||
他专门研究分布式系统,并领导了公司微服务架构的开发。
|
||||
""",
|
||||
context="团队概述"
|
||||
)
|
||||
|
||||
# Query in Chinese - get Chinese results
|
||||
results = hindsight.recall(
|
||||
bank_id="user-123",
|
||||
query="告诉我关于张伟的信息"
|
||||
)
|
||||
|
||||
# Facts are returned in Chinese:
|
||||
# - 张伟是一位资深软件工程师,在腾讯工作了五年
|
||||
# - 张伟专门研究分布式系统,并领导了公司微服务架构的开发
|
||||
```
|
||||
|
||||
### Example: Japanese Content
|
||||
|
||||
```python
|
||||
hindsight.retain(
|
||||
bank_id="user-123",
|
||||
content="""
|
||||
田中さんはソフトウェアエンジニアで、東京のスタートアップで働いています。
|
||||
彼女はPythonとTypeScriptが得意で、毎日コードレビューをしています。
|
||||
""",
|
||||
context="チームプロフィール"
|
||||
)
|
||||
|
||||
# Query in Japanese
|
||||
results = hindsight.recall(
|
||||
bank_id="user-123",
|
||||
query="田中さんについて教えてください"
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Reflect with Non-English Queries
|
||||
|
||||
The `reflect` operation also respects the input language, generating thoughtful responses in the same language as the query.
|
||||
|
||||
### Example: Chinese Reflection
|
||||
|
||||
```python
|
||||
# Store facts about team members (in Chinese)
|
||||
hindsight.retain(
|
||||
bank_id="team-eval",
|
||||
content="张伟是一位优秀的软件工程师,完成了五个重大项目。他总是按时交付,代码整洁有良好的文档。",
|
||||
context="绩效评估"
|
||||
)
|
||||
|
||||
hindsight.retain(
|
||||
bank_id="team-eval",
|
||||
content="李明最近加入团队。他错过了第一个截止日期,代码有很多bug。",
|
||||
context="绩效评估"
|
||||
)
|
||||
|
||||
# Reflect in Chinese
|
||||
result = hindsight.reflect(
|
||||
bank_id="team-eval",
|
||||
query="谁是更可靠的工程师?"
|
||||
)
|
||||
|
||||
# Response is in Chinese:
|
||||
# "我认为张伟更可靠。张伟完成了五个重大项目,按时交付,代码质量高..."
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Mixed Language Content
|
||||
|
||||
Hindsight handles mixed-language content gracefully, preserving both languages where appropriate.
|
||||
|
||||
### Example: Chinese Text with English Company Names
|
||||
|
||||
```python
|
||||
hindsight.retain(
|
||||
bank_id="user-123",
|
||||
content="""
|
||||
王芳在Google北京办公室工作,她是一名高级产品经理。
|
||||
之前她在Microsoft和Amazon工作过。
|
||||
她负责管理YouTube在中国市场的推广策略。
|
||||
""",
|
||||
context="员工资料"
|
||||
)
|
||||
|
||||
# Facts preserve both languages:
|
||||
# - 王芳在Google北京办公室工作,担任高级产品经理
|
||||
# - 王芳曾在Microsoft和Amazon工作过
|
||||
# - 王芳负责管理YouTube在中国市场的推广策略
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Supported Languages
|
||||
|
||||
**Hindsight's multilingual support depends entirely on your LLM's language capabilities.** Hindsight instructs the LLM to detect the input language and respond in that same language. If your LLM supports a language, Hindsight will work with it.
|
||||
|
||||
Most modern LLMs (GPT-4, Claude, Gemini, Llama 3, etc.) support dozens of languages including:
|
||||
|
||||
- **East Asian**: Chinese (Simplified/Traditional), Japanese, Korean
|
||||
- **European**: Spanish, French, German, Italian, Portuguese, Dutch, Polish, Russian
|
||||
- **Middle Eastern**: Arabic, Hebrew, Turkish
|
||||
- **South Asian**: Hindi, Bengali, Tamil
|
||||
- **Southeast Asian**: Thai, Vietnamese, Indonesian
|
||||
|
||||
**To verify support for your target language**, test your LLM directly with content in that language. If the LLM can understand and generate text in the language, Hindsight will preserve it correctly.
|
||||
|
||||
---
|
||||
|
||||
## Configuring for Multilingual Use
|
||||
|
||||
For optimal multilingual performance, you should configure all three components of the pipeline:
|
||||
|
||||
### 1. LLM (Required)
|
||||
Your LLM must support the target languages. Most modern LLMs do, but verify with your specific model.
|
||||
|
||||
### 2. Embedding Model (Recommended)
|
||||
The default embedding model (`BAAI/bge-small-en-v1.5`) is **English-only**. For multilingual content, use a multilingual embedding model:
|
||||
|
||||
```bash
|
||||
# In your .env file
|
||||
HINDSIGHT_API_EMBEDDINGS_LOCAL_MODEL=BAAI/bge-m3
|
||||
```
|
||||
|
||||
**Recommended multilingual embedding models:**
|
||||
| Model | Languages | Notes |
|
||||
|-------|-----------|-------|
|
||||
| `BAAI/bge-m3` | 100+ | Best overall multilingual performance |
|
||||
| `intfloat/multilingual-e5-large` | 100+ | Good alternative |
|
||||
| `sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2` | 50+ | Lighter weight |
|
||||
|
||||
### 3. Reranker Model (Recommended)
|
||||
The default reranker (`cross-encoder/ms-marco-MiniLM-L-6-v2`) is **English-only**. For multilingual content, use a multilingual reranker:
|
||||
|
||||
```bash
|
||||
# In your .env file
|
||||
HINDSIGHT_API_RERANKER_LOCAL_MODEL=BAAI/bge-reranker-v2-m3
|
||||
```
|
||||
|
||||
**Recommended multilingual reranker models:**
|
||||
| Model | Languages | Notes |
|
||||
|-------|-----------|-------|
|
||||
| `BAAI/bge-reranker-v2-m3` | 100+ | Best multilingual reranking |
|
||||
| `cross-encoder/mmarco-mMiniLMv2-L12-H384-v1` | 14 | Lighter alternative |
|
||||
|
||||
---
|
||||
|
||||
## Best Practices
|
||||
|
||||
### 1. Use Multilingual Models for Non-English Content
|
||||
If you primarily work with non-English content, configure multilingual embedding and reranker models. English-only models will still store your content correctly, but semantic search quality will be degraded.
|
||||
|
||||
### 2. Keep Content in One Language Per Retain Call
|
||||
While mixed content works, keeping each `retain` call in a single language produces more consistent results.
|
||||
|
||||
### 3. Query in the Same Language as Your Content
|
||||
For best results, query using the same language as your stored content. Cross-language queries (e.g., English query for Chinese content) may work but results can vary depending on your embedding model.
|
||||
|
||||
---
|
||||
|
||||
## Technical Details
|
||||
|
||||
Multilingual support is implemented through LLM prompt instructions rather than external language detection libraries. This approach:
|
||||
|
||||
- **Requires no additional dependencies**
|
||||
- **Works with any LLM** that supports multiple languages
|
||||
- **Handles edge cases** like mixed-language content naturally
|
||||
- **Preserves semantic meaning** better than rule-based translation
|
||||
|
||||
The LLM is instructed to:
|
||||
1. Detect the input language
|
||||
2. Extract all facts, entities, and descriptions in that same language
|
||||
3. Never translate to English unless the input is in English
|
||||
|
|
@ -0,0 +1,168 @@
|
|||
---
|
||||
sidebar_position: 5
|
||||
---
|
||||
|
||||
import CodeSnippet from '@site/src/components/CodeSnippet';
|
||||
import recallPy from '!!raw-loader!@site/examples/api/recall.py';
|
||||
import memoryBanksPy from '!!raw-loader!@site/examples/api/memory-banks.py';
|
||||
|
||||
# Observations: Knowledge Consolidation
|
||||
|
||||
After memories are retained, Hindsight automatically consolidates related facts into **observations** — synthesized knowledge representations that capture patterns and learnings.
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
A[New Facts] --> B[Consolidation Engine]
|
||||
B --> C{Existing Observation?}
|
||||
C -->|Yes| D[Refine Observation]
|
||||
C -->|No| E[Create Observation]
|
||||
D --> F[Observations]
|
||||
E --> F
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## What Are Observations?
|
||||
|
||||
Observations are **consolidated knowledge** synthesized from multiple facts. Unlike raw facts which are individual pieces of information, observations represent patterns, preferences, and learnings that emerge from accumulated evidence.
|
||||
|
||||
| Raw Facts | Observation |
|
||||
|-----------|--------------|
|
||||
| "Alice prefers Python" | "Alice is a Python-focused developer who values readability and simplicity" |
|
||||
| "Alice dislikes verbose code" | |
|
||||
| "Alice recommends type hints" | |
|
||||
|
||||
Observations provide:
|
||||
- **Synthesis**: Patterns that emerge from multiple facts
|
||||
- **Context**: Richer understanding than individual facts
|
||||
- **Efficiency**: Condensed knowledge for faster retrieval
|
||||
|
||||
---
|
||||
|
||||
## How Consolidation Works
|
||||
|
||||
### Automatic Background Processing
|
||||
|
||||
After `retain()` completes, the consolidation engine runs automatically:
|
||||
|
||||
1. **New facts analyzed** — Each new fact is compared against existing observations
|
||||
2. **Pattern detection** — Related facts are grouped and synthesized
|
||||
3. **Observation creation/update** — New observations are created or existing ones refined
|
||||
4. **Evidence tracking** — Each observation maintains references to supporting facts
|
||||
|
||||
### Evidence-Based Evolution
|
||||
|
||||
Observations evolve as new evidence arrives:
|
||||
|
||||
| Event | What the bank learns | Observation state |
|
||||
|-------|---------------------|----------------|
|
||||
| **Day 1** | "Redis is open source under BSD license" | "Redis is excellent for caching — fast, reliable, and OSS-friendly" (2 supporting facts) |
|
||||
| **Day 2** | "Redis has great community support" | Observation reinforced (3 supporting facts) |
|
||||
| **Day 30** | "Redis changed license to SSPL" | Observation refined: "Redis is technically strong, but has license concerns for cloud" |
|
||||
| **Day 45** | "Valkey forked Redis under BSD" | New observation: "Consider Valkey for new projects requiring true OSS" |
|
||||
|
||||
### Handling Contradictory Evidence
|
||||
|
||||
What happens when a new fact contradicts an existing observation?
|
||||
|
||||
The consolidation engine doesn't blindly overwrite — it **reconciles** the contradiction by capturing the evolution:
|
||||
|
||||
**Example: User preference changes**
|
||||
|
||||
| Time | Fact | Observation |
|
||||
|------|------|--------------|
|
||||
| Week 1 | "User says they love React" | "User prefers React for frontend development" |
|
||||
| Week 2 | "User praises React's component model" | "User is enthusiastic about React, particularly its component model" |
|
||||
| Week 3 | "User says they've switched to Vue and won't use React anymore" | "User was previously a React enthusiast who appreciated its component model, but has now switched to Vue and no longer uses React" |
|
||||
|
||||
Notice how the final observation captures the **full journey** — not just "User prefers Vue" but the complete evolution of their preference. This nuanced understanding means:
|
||||
|
||||
- Your agent won't recommend React tutorials to someone who explicitly moved away from it
|
||||
- Your agent understands *why* this matters (they were enthusiastic before, so this is a deliberate choice)
|
||||
- Your agent can reference this history when relevant ("I know you used to work with React...")
|
||||
|
||||
The system:
|
||||
1. **Detects the conflict** — New fact contradicts existing observation
|
||||
2. **Preserves history** — Incorporates the previous understanding into the new observation
|
||||
3. **Creates nuanced observation** — Synthesizes a richer understanding that captures the change
|
||||
4. **Updates freshness** — Marks the observation as recently updated
|
||||
|
||||
**Example: Correcting misinformation**
|
||||
|
||||
| Time | Fact | Observation |
|
||||
|------|------|--------------|
|
||||
| Day 1 | "Alice works at Google" | "Alice is a Google employee" |
|
||||
| Day 10 | "Alice actually works at Meta, not Google" | "Alice works at Meta (previously thought to work at Google)" |
|
||||
|
||||
When a fact explicitly corrects previous information, the observation is updated to reflect the correction while noting the previous understanding. The raw facts are always preserved, so you can trace back to see what was originally stated and when it was corrected.
|
||||
|
||||
---
|
||||
|
||||
## Observations in Retrieval
|
||||
|
||||
Observations are automatically included in both `recall()` and `reflect()` operations:
|
||||
|
||||
### In Recall
|
||||
|
||||
Observations are returned alongside raw facts, filtered by the `types` parameter:
|
||||
|
||||
<CodeSnippet code={recallPy} section="recall-with-observations" language="python" />
|
||||
|
||||
### In Reflect
|
||||
|
||||
The reflect agent uses **hierarchical retrieval**:
|
||||
|
||||
1. **[Mental Models](/developer/api/mental-models)** — User-curated summaries (highest priority)
|
||||
2. **Observations** — Consolidated knowledge with freshness awareness
|
||||
3. **Raw Facts** — Ground truth for verification
|
||||
|
||||
The agent automatically queries observations and uses them to inform its reasoning.
|
||||
|
||||
---
|
||||
|
||||
## Freshness Awareness
|
||||
|
||||
Observations track when they were last updated. During reflect, the agent considers freshness:
|
||||
|
||||
- **Fresh observations**: Used directly for reasoning
|
||||
- **Stale observations**: Agent verifies against current facts before relying on them
|
||||
|
||||
This ensures responses stay accurate even as the underlying data changes.
|
||||
|
||||
---
|
||||
|
||||
## Mission-Oriented Consolidation
|
||||
|
||||
The bank's **mission** directly influences what knowledge gets consolidated into observations. When you set a mission on your memory bank, the consolidation engine focuses on extracting knowledge that serves that mission.
|
||||
|
||||
**Example:**
|
||||
|
||||
<CodeSnippet code={memoryBanksPy} section="bank-support-agent" language="python" />
|
||||
|
||||
With this mission, the consolidation engine will:
|
||||
- **Prioritize** customer preferences, issue patterns, and communication styles
|
||||
- **Skip** ephemeral details that don't serve support goals
|
||||
- **Synthesize** observations focused on helping customers
|
||||
|
||||
Without a mission, the engine performs general-purpose consolidation. With a mission, it becomes focused and efficient — extracting only knowledge that matters for your use case.
|
||||
|
||||
| Mission | Observations Focus |
|
||||
|---------|-------------------|
|
||||
| *Customer support agent* | Customer preferences, issue patterns, resolution history |
|
||||
| *Code review assistant* | Coding patterns, team conventions, common mistakes |
|
||||
| *Research assistant* | Topic expertise, source reliability, methodology preferences |
|
||||
|
||||
---
|
||||
|
||||
## Configuration
|
||||
|
||||
Observation consolidation runs automatically. You can monitor consolidation via the [Operations API](./api/operations).
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [**Retain**](./retain) — How facts are stored and trigger consolidation
|
||||
- [**Recall**](./retrieval) — How observations are retrieved
|
||||
- [**Reflect**](./reflect) — How the agentic loop uses observations
|
||||
- [**Mental Models**](./api/mental-models) — User-curated summaries for common queries
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
# Performance
|
||||
|
||||
Hindsight is designed for high-performance semantic memory operations at scale. This page covers performance characteristics, optimization strategies, and best practices.
|
||||
|
||||
## Overview
|
||||
|
||||
Hindsight's performance is optimized across three key operations:
|
||||
|
||||
- **Retain (Ingestion)**: Batch processing with async operations for large-scale memory storage
|
||||
- **Recall (Search)**: Sub-second semantic search with configurable thinking budgets
|
||||
- **Reflect (Reasoning)**: Disposition-aware answer generation with controllable compute
|
||||
|
||||
## Design Philosophy: Optimized for Fast Reads
|
||||
|
||||
Hindsight is **architected from the ground up to prioritize read performance over write performance**. This design decision reflects the typical usage pattern of memory systems: memories are written once but read many times.
|
||||
|
||||
The system makes deliberate trade-offs to ensure **sub-second recall operations**:
|
||||
|
||||
- **Pre-computed embeddings**: All memory embeddings are generated and indexed during retention
|
||||
- **Optimized vector search**: HNSW indexes enable fast approximate nearest neighbor search
|
||||
- **Fact extraction at write time**: Complex LLM-based fact extraction happens during retention, not retrieval
|
||||
- **Structured memory graphs**: Relationships and temporal information are resolved upfront
|
||||
|
||||
This means **Recall (search) operations are blazingly fast** because all the heavy lifting has already been done.
|
||||
|
||||
### Performance Comparison
|
||||
|
||||
| Operation | Typical Latency | Primary Bottleneck | Optimization Strategy |
|
||||
|-----------|----------------|-------------------|----------------------------------|
|
||||
| **Recall** | 100-600ms | Re-ranker (on CPU) | Use GPU for re-ranking, or reduce budget |
|
||||
| **Reflect** | 800-3000ms | LLM generation | Use faster LLM |
|
||||
| **Retain** | 500ms-2000ms per batch | **LLM fact extraction** | Use high-throughput LLM provider |
|
||||
|
||||
Hindsight is designed to ensure your **application's read path (recall/reflect) is always fast**, even if it means spending more time upfront during writes. This is the right trade-off for memory systems where:
|
||||
|
||||
- Memories are retained in background processes or during low-traffic periods
|
||||
- Memories are queried frequently in user-facing, latency-sensitive contexts
|
||||
- The ratio of reads to writes is high (typically 10:1 or higher)
|
||||
|
||||
---
|
||||
|
||||
## Retain Performance
|
||||
|
||||
**Retain (write) operations are inherently slower** because they involve LLM-based fact extraction, entity recognition, temporal reasoning, relationship mapping, and embedding generation. **The LLM is the primary bottleneck for write latency.**
|
||||
|
||||
### Hindsight Doesn't Need a Smart Model
|
||||
|
||||
The fact extraction process is structured and well-defined, so smaller, faster models work extremely well. Our recommended model is `gpt-oss-20b` (available via Groq and other providers).
|
||||
|
||||
To maximize retention throughput:
|
||||
|
||||
1. **Use high-throughput LLM providers**: Choose providers with high requests-per-minute (RPM) limits and low latency
|
||||
- **Fast**: [Groq](https://groq.com) with `gpt-oss-20b` or other openai-oss models, self-hosted models on GPU clusters (vLLM, TGI)
|
||||
- **Slow**: Standard cloud LLM providers with rate limits
|
||||
|
||||
2. **Batch your operations**: Group related content into batch requests. The only limit is the HTTP payload size — Hindsight automatically splits large batches into smaller, optimized chunks under the hood, so you don't have to worry about it.
|
||||
|
||||
3. **Use async mode for large datasets**: Queue operations in the background
|
||||
|
||||
4. **Parallel processing**: For very large datasets, use multiple concurrent retention requests with different `document_id` values
|
||||
|
||||
### Throughput
|
||||
|
||||
Factors affecting throughput:
|
||||
- Document size and complexity
|
||||
- LLM provider rate limits (for fact extraction)
|
||||
- Database write performance
|
||||
- Available CPU/memory resources
|
||||
|
||||
---
|
||||
|
||||
## Recall Performance
|
||||
|
||||
### Budget
|
||||
|
||||
The `budget` parameter controls the search depth and quality. Choose based on query complexity — comprehensive questions that need thorough analysis benefit from higher budgets:
|
||||
|
||||
| Budget | Use Case |
|
||||
|--------|----------|
|
||||
| `low` | Quick lookups, real-time chat |
|
||||
| `mid` | Standard queries, balanced performance |
|
||||
| `high` | Comprehensive questions, thorough analysis |
|
||||
|
||||
### Optimization
|
||||
|
||||
1. **Appropriate budgets**: Use lower budgets for simple queries, higher for comprehensive reasoning
|
||||
2. **Limit result tokens**: Set `max_tokens` to control response size (default: 4096)
|
||||
3. **Include chunks**: Use `include_chunks` to retrieve the raw text that generated memories when you need additional context
|
||||
|
||||
### Database Performance
|
||||
|
||||
Hindsight uses PostgreSQL with pgvector for efficient vector search:
|
||||
|
||||
- **Index type**: HNSW for approximate nearest neighbor search
|
||||
- **Typical query time**: 10-50ms for vector search on 100K+ facts
|
||||
- **Scalability**: Tested with millions of facts per bank
|
||||
|
||||
## Reflect Performance
|
||||
|
||||
### Performance Characteristics
|
||||
|
||||
| Component | Latency | Description |
|
||||
|-----------|----------------|-------------|
|
||||
| Memory search | 100-600ms | Based on budget (low/mid/high) |
|
||||
| LLM generation | 500-2000ms | Depends on provider and response length |
|
||||
| **Total** | **600-2600ms** | Typical end-to-end latency |
|
||||
|
||||
### Optimization Strategies
|
||||
|
||||
1. **Budget selection**: Use lower budgets when context is sufficient
|
||||
2. **Context provision**: Provide relevant `context` to reduce recall requirements and steer towards more focused answers
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Operations
|
||||
- **Use appropriate budgets**: Don't over-provision for simple queries; use higher budgets for comprehensive reasoning
|
||||
- **Batch retain operations**: Group related content together for better efficiency
|
||||
- **Cache frequent queries**: Cache at the application level for repeated queries
|
||||
- **Profile with trace**: Use the `trace` parameter to identify slow operations
|
||||
|
||||
### Scaling
|
||||
- **Horizontal scaling**: Deploy multiple API instances behind a load balancer with shared PostgreSQL
|
||||
- **Concurrency**: 100+ simultaneous requests supported; memory search scales with CPU cores
|
||||
- **LLM rate limits**: Distribute load across multiple API keys/providers (typically 60-500 RPM per key)
|
||||
|
||||
### Cost Optimization
|
||||
- **Use efficient models**: `gpt-oss-20b` via Groq for retain — Hindsight doesn't need frontier models
|
||||
- **Control token budgets**: Limit `max_tokens` for recall, use lower budgets when possible
|
||||
- **Optimize chunks**: Larger chunks (1000-2000 tokens) are more efficient than many small ones
|
||||
|
||||
### Monitoring
|
||||
- **Prometheus metrics**: Available at `/metrics` — track latency percentiles, throughput, and error rates
|
||||
- **Key metrics**: `hindsight_recall_duration_seconds`, `hindsight_reflect_duration_seconds`, `hindsight_retain_items_total`
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
---
|
||||
sidebar_position: 2
|
||||
---
|
||||
|
||||
# RAG vs Memory
|
||||
|
||||
Traditional RAG (Retrieval-Augmented Generation) retrieves documents similar to a query. Hindsight provides structured memory with temporal reasoning, entity understanding, and belief formation.
|
||||
|
||||
## Capability Comparison
|
||||
|
||||
| Capability | RAG | Hindsight |
|
||||
|------------|-----|-----------|
|
||||
| **Search strategy** | Semantic similarity only | Semantic + keyword + graph + temporal |
|
||||
| **Multi-hop reasoning** | Limited to retrieved chunks | Graph traversal across entity relationships |
|
||||
| **Temporal queries** | Keyword matching ("spring") | Date parsing and range filtering |
|
||||
| **Entity understanding** | None | Entity resolution, co-occurrence tracking |
|
||||
| **Knowledge consolidation** | Stateless | Mental models that synthesize and evolve |
|
||||
| **Disposition** | None | 3 traits (skepticism, literalism, empathy) influence interpretation |
|
||||
|
||||
## Architecture Comparison
|
||||
|
||||
### RAG
|
||||
|
||||
| Step | Operation |
|
||||
|------|-----------|
|
||||
| 1 | Embed query |
|
||||
| 2 | Vector similarity search |
|
||||
| 3 | Return top-k chunks |
|
||||
| 4 | Generate response |
|
||||
|
||||
Single retrieval strategy. No state between queries.
|
||||
|
||||
### Hindsight
|
||||
|
||||
| Step | Operation |
|
||||
|------|-----------|
|
||||
| 1 | Parse query (extract temporal expressions, entities) |
|
||||
| 2 | Execute 4 parallel retrievals: semantic, BM25, graph, temporal |
|
||||
| 3 | Fuse results with RRF |
|
||||
| 4 | Rerank with cross-encoder |
|
||||
| 5 | Apply disposition traits |
|
||||
| 6 | Generate response |
|
||||
|
||||
Multiple retrieval strategies. Persistent state across sessions.
|
||||
|
||||
## Example Scenarios
|
||||
|
||||
### Multi-Hop Reasoning
|
||||
|
||||
**Stored facts:**
|
||||
- "Alice is the tech lead on Project Atlas"
|
||||
- "Project Atlas uses Kubernetes"
|
||||
- "Kubernetes cluster had an outage Tuesday"
|
||||
|
||||
**Query:** "Was Alice affected by recent issues?"
|
||||
|
||||
| System | Result |
|
||||
|--------|--------|
|
||||
| RAG | Retrieves facts about Alice only (no semantic similarity to "issues") |
|
||||
| Hindsight | Traverses Alice → Project Atlas → Kubernetes → outage via entity links |
|
||||
|
||||
### Temporal Queries
|
||||
|
||||
**Stored facts with timestamps:**
|
||||
- March: "Alice started microservices migration"
|
||||
- April: "Alice completed auth service"
|
||||
- October: "Alice focusing on performance"
|
||||
|
||||
**Query:** "What did Alice do last spring?"
|
||||
|
||||
| System | Result |
|
||||
|--------|--------|
|
||||
| RAG | Returns all Alice facts regardless of date |
|
||||
| Hindsight | Parses "last spring" → March-May, filters to that range |
|
||||
|
||||
### Entity Understanding
|
||||
|
||||
**Stored facts about a user across sessions:**
|
||||
- "Pro subscription"
|
||||
- "Mobile app crashes in settings"
|
||||
- "Switched to annual billing"
|
||||
- "Desktop app working fine"
|
||||
|
||||
**Query:** "What do you know about my account?"
|
||||
|
||||
| System | Result |
|
||||
|--------|--------|
|
||||
| RAG | Lists disconnected facts |
|
||||
| Hindsight | Returns connected facts via entity graph: subscription status, billing, known issues |
|
||||
|
||||
### Knowledge Evolution
|
||||
|
||||
**Week 1:** User struggles with async Python, succeeds with threads
|
||||
**Week 3:** User asks about asyncio, implements async database calls
|
||||
|
||||
| System | Behavior |
|
||||
|--------|----------|
|
||||
| RAG | No memory of progression |
|
||||
| Hindsight | Consolidates mental model "user prefers sync" → refines to "user growing comfortable with async" |
|
||||
|
||||
## When to Use Each
|
||||
|
||||
| Use Case | Recommended |
|
||||
|----------|-------------|
|
||||
| Document Q&A over static corpus | RAG |
|
||||
| Search with no temporal requirements | RAG |
|
||||
| AI assistants with persistent memory | Hindsight |
|
||||
| Applications requiring entity tracking | Hindsight |
|
||||
| Systems needing consistent disposition | Hindsight |
|
||||
| Temporal queries ("last month", "in 2023") | Hindsight |
|
||||
240
hindsight-docs/versioned_docs/version-0.4/developer/reflect.mdx
Normal file
240
hindsight-docs/versioned_docs/version-0.4/developer/reflect.mdx
Normal file
|
|
@ -0,0 +1,240 @@
|
|||
---
|
||||
sidebar_position: 4
|
||||
---
|
||||
|
||||
import CodeSnippet from '@site/src/components/CodeSnippet';
|
||||
import memoryBanksPy from '!!raw-loader!@site/examples/api/memory-banks.py';
|
||||
|
||||
# Reflect: Agentic Reasoning with Disposition
|
||||
|
||||
When you call `reflect()`, Hindsight runs an **agentic loop** that autonomously gathers evidence and reasons through the lens of the bank's disposition to generate contextual responses.
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph agent["Reflect Agent Loop"]
|
||||
A[Query] --> B{Need more info?}
|
||||
B -->|Yes| C[Call Tools]
|
||||
C --> D[search_mental_models]
|
||||
C --> E[search_observations]
|
||||
C --> F[recall]
|
||||
C --> G[expand]
|
||||
D --> B
|
||||
E --> B
|
||||
F --> B
|
||||
G --> B
|
||||
B -->|No| H[Generate Response]
|
||||
end
|
||||
H --> I[Response + Citations]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## How It Works
|
||||
|
||||
Unlike simple retrieval, reflect is an **agentic system** that:
|
||||
|
||||
1. **Autonomously gathers evidence** — The agent decides what information it needs and calls appropriate tools
|
||||
2. **Uses hierarchical retrieval** — Checks mental models first, then observations, then raw facts
|
||||
3. **Applies disposition** — Shapes reasoning based on the bank's personality traits
|
||||
4. **Enforces directives** — Hard rules that must be followed in all responses
|
||||
5. **Cites sources** — Returns which memories and observations were used
|
||||
|
||||
### The Agentic Loop
|
||||
|
||||
The reflect agent runs in a loop with access to these tools:
|
||||
|
||||
| Tool | Purpose | Priority |
|
||||
|------|---------|----------|
|
||||
| `search_mental_models` | User-curated summaries | Highest (check first) |
|
||||
| `search_observations` | Consolidated knowledge | High |
|
||||
| `recall` | Raw facts (ground truth) | Fallback |
|
||||
| `expand` | Get more context for a memory | As needed |
|
||||
| `done` | Complete with final answer | When ready |
|
||||
|
||||
The agent:
|
||||
- **Must gather evidence** before answering (guardrail prevents empty responses)
|
||||
- **Runs up to 10 iterations** to find relevant information
|
||||
- **Validates citations** — only IDs that were actually retrieved can be cited
|
||||
|
||||
### Hierarchical Retrieval Strategy
|
||||
|
||||
The agent uses a smart retrieval hierarchy:
|
||||
|
||||
1. **[Mental Models](/developer/api/mental-models)** — User-curated summaries you've pre-computed for common queries
|
||||
2. **[Observations](/developer/observations)** — Consolidated knowledge with freshness awareness
|
||||
3. **Raw Facts** — Ground truth for verification when observations are stale
|
||||
|
||||
**Mental models** are saved reflect responses that you create for frequently asked questions. They're checked first because they represent explicitly curated knowledge. See the [Mental Models API](/developer/api/mental-models) for how to create and manage them.
|
||||
|
||||
If an observation is marked as **stale**, the agent automatically verifies it against current facts.
|
||||
|
||||
---
|
||||
|
||||
## Why Reflect?
|
||||
|
||||
Most AI systems can retrieve facts, but they can't **reason** about them in a consistent way.
|
||||
|
||||
### The Problem
|
||||
|
||||
Without reflect:
|
||||
- **No consistent character**: Same question gets different answers each time
|
||||
- **No knowledge synthesis**: System never connects related facts
|
||||
- **No reasoning context**: Responses don't reflect accumulated knowledge
|
||||
- **Generic responses**: Every AI sounds the same
|
||||
|
||||
### The Value
|
||||
|
||||
With reflect:
|
||||
- **Consistent character**: A "detail-oriented, cautious" bank emphasizes risks and thorough planning
|
||||
- **Evolving knowledge**: Observations strengthen and adapt as evidence accumulates
|
||||
- **Contextual reasoning**: "Based on what I know about your team's remote work success..."
|
||||
- **Differentiated behavior**: Support bots sound diplomatic, code reviewers sound direct
|
||||
|
||||
### When to Use Reflect
|
||||
|
||||
| Use `recall()` when... | Use `reflect()` when... |
|
||||
|------------------------|-------------------------|
|
||||
| You need raw facts | You need reasoned interpretation |
|
||||
| You're building your own reasoning | You want disposition-consistent responses |
|
||||
| You need maximum control | You want the bank to "think" for itself |
|
||||
| Simple fact lookup | Forming recommendations |
|
||||
|
||||
**Example:**
|
||||
- `recall("Alice")` → Returns all Alice facts and relevant mental models
|
||||
- `reflect("Should we hire Alice?")` → Agent gathers evidence about Alice, reasons about fit, returns answer with citations
|
||||
|
||||
---
|
||||
|
||||
## Disposition Traits
|
||||
|
||||
When you create a memory bank, you can configure its disposition using three traits. These traits influence how the bank interprets information and reasons during `reflect()`:
|
||||
|
||||
| Trait | Scale | Low (1) | High (5) |
|
||||
|-------|-------|---------|----------|
|
||||
| **Skepticism** | 1-5 | Trusting, accepts information at face value | Skeptical, questions and doubts claims |
|
||||
| **Literalism** | 1-5 | Flexible interpretation, reads between the lines | Literal interpretation, takes things at face value |
|
||||
| **Empathy** | 1-5 | Detached, focuses on facts | Empathetic, considers emotional context |
|
||||
|
||||
### Mission: Natural Language Identity
|
||||
|
||||
Beyond numeric traits, you can provide a natural language **mission** that describes the bank's identity:
|
||||
|
||||
<CodeSnippet code={memoryBanksPy} section="bank-with-disposition" language="python" />
|
||||
|
||||
The mission tells Hindsight what knowledge to prioritize and shapes how disposition traits are applied:
|
||||
- "keep track of system designs" → focuses consolidation on architectural decisions
|
||||
- "prefer simplicity over cutting-edge" + high skepticism → questions complex solutions
|
||||
- Explicit guidance → consistent memory focus across conversations
|
||||
|
||||
---
|
||||
|
||||
## Disposition Shapes Reasoning
|
||||
|
||||
Two banks with different dispositions, given identical facts about remote work:
|
||||
|
||||
**Bank A** (low skepticism, high empathy):
|
||||
> "Remote work enables flexibility and work-life balance. The team seems happier and more productive when they can choose their environment."
|
||||
|
||||
**Bank B** (high skepticism, low empathy):
|
||||
> "Remote work claims need verification. What are the actual productivity metrics? The anecdotal benefits may not translate to measurable outcomes."
|
||||
|
||||
**Same facts → Different conclusions** because disposition shapes interpretation.
|
||||
|
||||
---
|
||||
|
||||
## Disposition Presets by Use Case
|
||||
|
||||
Different use cases benefit from different disposition configurations:
|
||||
|
||||
| Use Case | Recommended Traits | Why |
|
||||
|----------|-------------------|-----|
|
||||
| **Customer Support** | skepticism: 2, literalism: 2, empathy: 5 | Trusting, flexible, understanding |
|
||||
| **Code Review** | skepticism: 4, literalism: 5, empathy: 2 | Questions assumptions, precise, direct |
|
||||
| **Legal Analysis** | skepticism: 5, literalism: 5, empathy: 2 | Highly skeptical, exact interpretation |
|
||||
| **Therapist/Coach** | skepticism: 2, literalism: 2, empathy: 5 | Supportive, reads between lines |
|
||||
| **Research Assistant** | skepticism: 4, literalism: 3, empathy: 3 | Questions claims, balanced interpretation |
|
||||
|
||||
---
|
||||
|
||||
## Directives: Hard Rules
|
||||
|
||||
While disposition traits *influence* reasoning style, **directives** are hard rules that the agent *must* follow. Directives are injected into the prompt and enforced in every response.
|
||||
|
||||
### When to Use Directives
|
||||
|
||||
Use directives for constraints that must never be violated:
|
||||
|
||||
- **Compliance rules**: "Never recommend specific stocks or financial products"
|
||||
- **Privacy constraints**: "Never share personal data with third parties"
|
||||
- **Style requirements**: "Always respond in formal English"
|
||||
- **Domain guardrails**: "Always cite sources when making factual claims"
|
||||
|
||||
### Directives vs Disposition
|
||||
|
||||
| Aspect | Disposition | Directives |
|
||||
|--------|-------------|------------|
|
||||
| **Nature** | Soft influence | Hard rules |
|
||||
| **Effect** | Shapes interpretation and tone | Must be followed exactly |
|
||||
| **Violation** | Acceptable (it's a tendency) | Not acceptable |
|
||||
| **Example** | High skepticism → questions claims | "Never make medical diagnoses" |
|
||||
|
||||
:::tip
|
||||
Use disposition for personality and character. Use directives for compliance and guardrails.
|
||||
:::
|
||||
|
||||
See [Memory Banks: Directives](/developer/api/memory-banks#directives) for how to create and manage directives.
|
||||
|
||||
---
|
||||
|
||||
## What You Get from Reflect
|
||||
|
||||
When you call `reflect()`:
|
||||
|
||||
**Returns:**
|
||||
- **Response text** — Disposition-influenced answer from the agent
|
||||
- **based_on** — Evidence used: memories, mental models, and directives that grounded the response
|
||||
- **trace** — Tool calls, LLM calls, and observations accessed (when `include.tool_calls=True`)
|
||||
- **structured_output** — Parsed response if `response_schema` was provided
|
||||
- **usage** — Token usage metrics
|
||||
|
||||
**Example:**
|
||||
```json
|
||||
{
|
||||
"text": "Based on Alice's ML expertise and her work at Google, she'd be an excellent fit for the research team lead position...",
|
||||
"based_on": {
|
||||
"memories": [
|
||||
{"id": "mem-123", "text": "Alice has 5 years of ML experience", "type": "world"},
|
||||
{"id": "mem-456", "text": "Alice worked at Google on search ranking", "type": "experience"}
|
||||
],
|
||||
"mental_models": [],
|
||||
"directives": [
|
||||
{"id": "dir-001", "name": "Formal Language", "rules": ["Always respond in formal English"]}
|
||||
]
|
||||
},
|
||||
"usage": {"input_tokens": 1500, "output_tokens": 500, "total_tokens": 2000}
|
||||
}
|
||||
```
|
||||
|
||||
The agent automatically gathers evidence, validates citations, and generates a grounded response.
|
||||
|
||||
---
|
||||
|
||||
## Why Disposition Matters
|
||||
|
||||
Without disposition, all AI assistants sound the same. With disposition:
|
||||
|
||||
- **Customer support bots** can be diplomatic and empathetic
|
||||
- **Code review assistants** can be direct and thorough
|
||||
- **Creative assistants** can be open to unconventional ideas
|
||||
- **Risk analysts** can be appropriately cautious
|
||||
|
||||
Disposition creates **consistent character** across conversations while observations **evolve with evidence**.
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [**Observations**](./observations) — How knowledge is consolidated
|
||||
- [**Retain**](./retain) — How rich facts are stored
|
||||
- [**Recall**](./retrieval) — How multi-strategy search works
|
||||
- [**Reflect API**](./api/reflect) — Code examples and parameters
|
||||
199
hindsight-docs/versioned_docs/version-0.4/developer/retain.md
Normal file
199
hindsight-docs/versioned_docs/version-0.4/developer/retain.md
Normal file
|
|
@ -0,0 +1,199 @@
|
|||
---
|
||||
sidebar_position: 2
|
||||
---
|
||||
|
||||
# Retain: How Hindsight Stores Memories
|
||||
|
||||
When you call `retain()`, Hindsight transforms conversations and documents into structured, searchable memories that preserve meaning and context.
|
||||
|
||||
## What Retain Does
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
A[Your Content] --> B[Extract Facts]
|
||||
B --> C[Identify Entities]
|
||||
C --> D[Build Connections]
|
||||
D --> E[Memory Bank]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Rich Fact Extraction
|
||||
|
||||
Hindsight doesn't just store what was said — it captures **why**, **how**, and **what it means**.
|
||||
|
||||
### What Gets Captured
|
||||
|
||||
When you retain "Alice joined Google last spring and was thrilled about the research opportunities", Hindsight extracts:
|
||||
|
||||
**The core facts:**
|
||||
- Alice joined Google
|
||||
- This happened last spring
|
||||
|
||||
**The emotions and meaning:**
|
||||
- She was thrilled
|
||||
- It represented an important opportunity
|
||||
|
||||
**The reasoning:**
|
||||
- She chose it for the research opportunities
|
||||
|
||||
This rich extraction means you can later ask "Why did Alice join Google?" and get a meaningful answer, not just "she joined Google."
|
||||
|
||||
### Preserving Context
|
||||
|
||||
Traditional systems fragment information:
|
||||
- "Bob suggested Summer Vibes"
|
||||
- "Alice wanted something unique"
|
||||
- "They chose Beach Beats"
|
||||
|
||||
Hindsight preserves the full narrative:
|
||||
- "Alice and Bob discussed naming their summer party playlist. Bob suggested 'Summer Vibes' because it's catchy, but Alice wanted something unique. They ultimately decided on 'Beach Beats' for its playful tone."
|
||||
|
||||
This means search results include the full context, not disconnected fragments.
|
||||
|
||||
---
|
||||
|
||||
## Two Types of Facts
|
||||
|
||||
Hindsight distinguishes between **world** facts (about others) and **experience** (conversations and events):
|
||||
|
||||
| Type | Description | Example |
|
||||
|-----------------|-----------------------------------|---------|
|
||||
| **world** | Facts about people, places, things | "Alice works at Google" |
|
||||
| **experience** | Conversations and events | "I recommended Python to Alice" |
|
||||
|
||||
|
||||
**Note:** Observations are consolidated automatically in the background after `retain()` operations complete. This consolidation process synthesizes patterns from new facts into the bank's knowledge base.
|
||||
|
||||
---
|
||||
|
||||
## Entity Recognition
|
||||
|
||||
Hindsight automatically identifies and tracks **entities** — the people, organizations, and concepts that matter.
|
||||
|
||||
### What Gets Recognized
|
||||
|
||||
- **People:** "Alice", "Dr. Smith", "Bob Chen"
|
||||
- **Organizations:** "Google", "MIT", "OpenAI"
|
||||
- **Places:** "Paris", "Central Park", "California"
|
||||
- **Products & Concepts:** "Python", "TensorFlow", "machine learning"
|
||||
|
||||
### Entity Resolution
|
||||
|
||||
The same entity mentioned different ways gets unified:
|
||||
- "Alice" + "Alice Chen" + "Alice C." → one person
|
||||
- "Bob" + "Robert Chen" → one person (nickname resolution)
|
||||
|
||||
**Why it matters:** You can ask "What do I know about Alice?" and get everything, even if she was mentioned as "Alice Chen" in some conversations.
|
||||
|
||||
### Context-Aware Disambiguation
|
||||
|
||||
If "Alice" appears with "Google" and "Stanford" multiple times, a new "Alice" mentioning those is likely the same person. Hindsight uses co-occurrence patterns to disambiguate common names.
|
||||
|
||||
---
|
||||
|
||||
## Building Connections
|
||||
|
||||
Memories aren't isolated — Hindsight creates a **knowledge graph** with four types of connections:
|
||||
|
||||
### Entity Connections
|
||||
|
||||
All facts mentioning the same entity are linked together.
|
||||
|
||||
**Enables:** "Tell me everything about Alice" → retrieves all Alice-related facts
|
||||
|
||||
### Time-Based Connections
|
||||
|
||||
Facts close in time are connected, with stronger links for closer dates.
|
||||
|
||||
**Enables:** "What else happened around then?" → finds contextually related events
|
||||
|
||||
### Meaning-Based Connections
|
||||
|
||||
Semantically similar facts are linked, even if they use different words.
|
||||
|
||||
**Enables:** "Tell me about similar topics" → finds thematically related information
|
||||
|
||||
### Causal Connections
|
||||
|
||||
Cause-effect relationships are explicitly tracked.
|
||||
|
||||
**Enables:** "Why did this happen?" → trace reasoning chains
|
||||
**Example:** "Alice felt burned out" ← caused by ← "She worked 80-hour weeks"
|
||||
|
||||
---
|
||||
|
||||
## Understanding Time
|
||||
|
||||
Hindsight tracks **two temporal dimensions**:
|
||||
|
||||
### When It Happened
|
||||
|
||||
For events (meetings, trips, milestones), Hindsight records when they occurred.
|
||||
- "Alice got married in June 2024" → occurred in June 2024
|
||||
|
||||
For general facts (preferences, characteristics), there's no specific occurrence time.
|
||||
- "Alice prefers Python" → ongoing preference
|
||||
|
||||
### When You Learned It
|
||||
|
||||
Hindsight also tracks when you told it each fact.
|
||||
|
||||
**Why both?**
|
||||
|
||||
Imagine in January 2025, someone tells you "Alice got married in June 2024":
|
||||
- **Historical queries** work: "What did Alice do in 2024?" → finds the marriage
|
||||
- **Recency ranking** works: Recent mentions get priority in search
|
||||
- **Temporal reasoning** works: "What happened before her marriage?" → finds earlier events
|
||||
|
||||
Without this distinction, old information would either be unsearchable by date or treated as irrelevant.
|
||||
|
||||
---
|
||||
|
||||
## Tagging Memories
|
||||
|
||||
Tags enable visibility scoping—useful when one memory bank serves multiple users but each should only see relevant memories.
|
||||
|
||||
- **Item tags**: Tag individual memories with specific scopes
|
||||
- **Document tags**: Apply tags to all items in a batch
|
||||
- **Tag filtering**: Filter during recall/reflect by tags
|
||||
|
||||
See [Retain API](./api/retain) for code examples and [Recall API](./api/recall) for filtering options.
|
||||
|
||||
---
|
||||
|
||||
## What You Get
|
||||
|
||||
After `retain()` completes:
|
||||
|
||||
- **Structured facts** that preserve meaning, emotions, and reasoning
|
||||
- **Unified entities** that resolve different name variations
|
||||
- **Knowledge graph** with entity, temporal, semantic, and causal links
|
||||
- **Temporal grounding** for both historical and recency-based queries
|
||||
- **Optional tags** for filtering during recall
|
||||
|
||||
All stored in your isolated **memory bank**, ready for `recall()` and `reflect()`.
|
||||
|
||||
---
|
||||
|
||||
## Observation Consolidation
|
||||
|
||||
After `retain()` completes, Hindsight automatically triggers **observation consolidation** in the background. This process:
|
||||
|
||||
1. Analyzes new facts against existing observations
|
||||
2. Creates new observations when patterns emerge
|
||||
3. Refines existing observations with new evidence
|
||||
4. Tracks which facts support each observation
|
||||
|
||||
This happens asynchronously — your `retain()` call returns immediately while consolidation runs in the background.
|
||||
|
||||
See [Observations](./observations) for details on how consolidation works.
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [**Observations**](./observations) — How knowledge is consolidated after retain
|
||||
- [**Recall**](./retrieval) — How multi-strategy search retrieves relevant memories
|
||||
- [**Reflect**](./reflect) — How the agentic loop uses observations
|
||||
- [**Retain API**](./api/retain) — Code examples and parameters
|
||||
226
hindsight-docs/versioned_docs/version-0.4/developer/retrieval.md
Normal file
226
hindsight-docs/versioned_docs/version-0.4/developer/retrieval.md
Normal file
|
|
@ -0,0 +1,226 @@
|
|||
---
|
||||
sidebar_position: 3
|
||||
---
|
||||
|
||||
# Recall: How Hindsight Retrieves Memories
|
||||
|
||||
When you call `recall()`, Hindsight uses multiple search strategies in parallel to find the most relevant memories, regardless of how you phrase your query.
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
Q[Query] --> S[Semantic]
|
||||
Q --> K[Keyword]
|
||||
Q --> G[Graph]
|
||||
Q --> T[Temporal]
|
||||
|
||||
S --> RRF[RRF Fusion]
|
||||
K --> RRF
|
||||
G --> RRF
|
||||
T --> RRF
|
||||
|
||||
RRF --> CE[Cross-Encoder]
|
||||
CE --> R[Results]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## The Challenge of Memory Recall
|
||||
|
||||
Different queries need different search approaches:
|
||||
|
||||
- **"Alice works at Google"** → needs exact name matching
|
||||
- **"Where does Alice work?"** → needs semantic understanding
|
||||
- **"What did Alice do last spring?"** → needs temporal reasoning
|
||||
- **"Why did Alice leave?"** → needs causal relationship tracing
|
||||
|
||||
No single search method handles all these well. Hindsight solves this with **TEMPR** — four complementary strategies that run in parallel.
|
||||
|
||||
---
|
||||
|
||||
## Four Search Strategies
|
||||
|
||||
### Semantic Search
|
||||
|
||||
**What it does:** Understands the *meaning* behind words, not just the words themselves.
|
||||
|
||||
**Best for:**
|
||||
- Conceptual matches: "Alice's job" → "Alice works as a software engineer"
|
||||
- Paraphrasing: "Bob's expertise" → "Bob specializes in machine learning"
|
||||
- Synonyms: "meeting" matches "conference", "discussion", "gathering"
|
||||
|
||||
**Why it matters:** You can ask questions naturally without matching exact keywords.
|
||||
|
||||
---
|
||||
|
||||
### Keyword Search
|
||||
|
||||
**What it does:** Finds exact terms and names, even when they're spelled uniquely.
|
||||
|
||||
**Best for:**
|
||||
- Proper nouns: "Google", "Alice Chen", "MIT"
|
||||
- Technical terms: "PostgreSQL", "HNSW", "TensorFlow"
|
||||
- Unique identifiers: URLs, product names, specific phrases
|
||||
|
||||
**Why it matters:** Ensures you never miss results that mention specific names or terms, even if they're semantically distant from your query.
|
||||
|
||||
---
|
||||
|
||||
### Graph Traversal
|
||||
|
||||
**What it does:** Follows connections between entities to find indirectly related information.
|
||||
|
||||
**Best for:**
|
||||
- Indirect relationships: "What does Alice do?" → Alice → Google → Google's products
|
||||
- Entity exploration: "Bob's colleagues" → Bob → co-workers → shared projects
|
||||
- Multi-hop reasoning: "Alice's team's achievements"
|
||||
|
||||
**Why it matters:** Retrieves facts that aren't semantically or lexically similar but are **structurally connected** through the knowledge graph.
|
||||
|
||||
**Example:** Even if Alice and her manager are never mentioned together, graph traversal can find the manager through shared projects or team relationships.
|
||||
|
||||
---
|
||||
|
||||
### Temporal Search
|
||||
|
||||
**What it does:** Understands time expressions and filters by when events occurred.
|
||||
|
||||
**Best for:**
|
||||
- Historical queries: "What did Alice do in 2023?"
|
||||
- Time ranges: "What happened last spring?"
|
||||
- Relative time: "What did Bob work on last year?"
|
||||
- Before/after: "What happened before Alice joined Google?"
|
||||
|
||||
**How it works:** Combines semantic understanding with time filtering to find events within specific periods.
|
||||
|
||||
**Why it matters:** Enables precise historical queries without losing old information.
|
||||
|
||||
---
|
||||
|
||||
## Result Fusion
|
||||
|
||||
After the four strategies run, results are **fused together**:
|
||||
|
||||
- Memories appearing in **multiple strategies** rank higher (consensus)
|
||||
- **Rank matters more than score** (robust across different scoring systems)
|
||||
- Final results are **re-ranked** using a neural model that considers query-memory interaction
|
||||
|
||||
**Why fusion matters:** A fact that's both semantically similar AND mentions the right entity will rank higher than one that's only semantically similar.
|
||||
|
||||
---
|
||||
|
||||
## Why Multiple Strategies?
|
||||
|
||||
Consider the query: **"What did Alice say about Python last spring?"**
|
||||
|
||||
- **Semantic** finds facts about Alice's views on programming
|
||||
- **Keyword** ensures "Python" is actually mentioned
|
||||
- **Graph** connects Alice → programming languages → related entities
|
||||
- **Temporal** filters to "last spring" timeframe
|
||||
|
||||
The **fusion** of all four gives you exactly what you're looking for, even though no single strategy would suffice.
|
||||
|
||||
---
|
||||
|
||||
## Token Budget Management
|
||||
|
||||
Hindsight is built for AI agents, not humans. Traditional search systems return "top-k" results, but agents don't think in terms of result counts—they think in tokens. An agent's context window is measured in tokens, and that's exactly how Hindsight measures results.
|
||||
|
||||
**How it works:**
|
||||
- Top-ranked memories selected first
|
||||
- Stops when token budget is exhausted
|
||||
- You specify context budget, Hindsight fills it with the most relevant memories
|
||||
|
||||
**Parameters you control:**
|
||||
- `max_tokens`: How much memory content to return (default: 4096 tokens)
|
||||
- `budget`: Search depth level (low, mid, high)
|
||||
- `types`: Filter by world, experience, observation, or all
|
||||
- `tags`: Filter memories by visibility tags
|
||||
- `tags_match`: How to match tags (see [Recall API](./api/recall) for all options)
|
||||
|
||||
### Expanding Context: Chunks
|
||||
|
||||
Memories are distilled facts—concise but sometimes missing nuance. When your agent needs deeper context, you can optionally retrieve the source material:
|
||||
|
||||
**Chunks** return the raw text that generated each memory—useful when the distilled fact loses important nuance:
|
||||
|
||||
```
|
||||
Memory: "Alice prefers Python over JavaScript"
|
||||
Chunk: "Alice mentioned she prefers Python over JavaScript, mainly because
|
||||
of its data science ecosystem, though she admits JS is better for
|
||||
frontend work and she's been learning TypeScript lately."
|
||||
```
|
||||
|
||||
Use `include_chunks=True` with `max_chunk_tokens` to control the token budget for chunks. This is useful when generating responses that need verbatim quotes or when context matters (e.g., "What exactly did Alice say about the project?").
|
||||
|
||||
---
|
||||
|
||||
## Tuning Recall: Quality vs Latency
|
||||
|
||||
Different use cases require different trade-offs between **recall quality** and **response speed**. Two parameters control this:
|
||||
|
||||
### Budget: Search Depth
|
||||
|
||||
Controls how thoroughly Hindsight explores the memory bank—affecting graph traversal depth, candidate pool size, and cross-encoder re-ranking:
|
||||
|
||||
| Budget | Best For | Trade-off |
|
||||
|--------|----------|-----------|
|
||||
| **low** | Quick lookups, simple queries | Fast, may miss indirect connections |
|
||||
| **mid** | Most queries, balanced | Good coverage, reasonable speed |
|
||||
| **high** | Complex queries requiring deep exploration | Thorough, slower |
|
||||
|
||||
**Example:** "What did Alice's manager's team work on?" benefits from high budget to traverse multiple hops (Alice → manager → team → projects) and evaluate more candidates.
|
||||
|
||||
### Max Tokens: Context Window Size
|
||||
|
||||
Controls how much memory content to return:
|
||||
|
||||
| Max Tokens | ~Pages of Text | Best For | Trade-off |
|
||||
|------------|----------------|----------|-----------|
|
||||
| **2048** | ~2 pages | Focused answers, fast LLM | Fewer memories, faster |
|
||||
| **4096** (default) | ~4 pages | Balanced context | Good coverage, standard |
|
||||
| **8192** | ~8 pages | Comprehensive context | More memories, slower LLM |
|
||||
|
||||
**Example:** "Summarize everything about Alice" benefits from higher max_tokens to include more facts.
|
||||
|
||||
### Two Independent Dimensions
|
||||
|
||||
Budget and max_tokens control different aspects of recall:
|
||||
|
||||
| Parameter | What it controls | Latency impact | Example |
|
||||
|-----------|------------------|----------------|---------|
|
||||
| **Budget** | How thoroughly to explore memories | Search time | High budget finds Alice → manager → team → projects |
|
||||
| **Max Tokens** | How much context to return | LLM processing time | High tokens returns more memories to the agent |
|
||||
|
||||
**They're independent.** Common combinations:
|
||||
|
||||
| Budget | Max Tokens | Use Case |
|
||||
|--------|------------|----------|
|
||||
| high | low | Deep search, return only the best results |
|
||||
| low | high | Quick search, return everything found |
|
||||
| high | high | Comprehensive research queries |
|
||||
| low | low | Fast chatbot responses |
|
||||
|
||||
### Recommended Configurations
|
||||
|
||||
| Use Case | Budget | Max Tokens | Why |
|
||||
|----------|--------|------------|-----|
|
||||
| **Chatbot replies** | low | 2048 | Fast responses, focused context |
|
||||
| **Document Q&A** | mid | 4096 | Balanced coverage and speed |
|
||||
| **Research queries** | high | 8192 | Comprehensive, multi-hop reasoning |
|
||||
| **Real-time search** | low | 2048 | Minimize latency |
|
||||
|
||||
---
|
||||
|
||||
## Graph Retrieval Algorithms
|
||||
|
||||
Hindsight supports multiple graph traversal algorithms. The default (`link_expansion`) is optimized for fast retrieval with target latency under 100ms.
|
||||
|
||||
See [Configuration → Retrieval](./configuration#retrieval) for available algorithms and how to configure them.
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [**Retain**](./retain) — How memories are stored with rich context
|
||||
- [**Reflect**](./reflect) — How disposition influences reasoning
|
||||
- [**Recall API**](./api/recall) — Code examples, parameters, and tag filtering
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
# Services
|
||||
|
||||
Hindsight consists of three services that can run together or separately depending on your deployment needs.
|
||||
|
||||
## API Service
|
||||
|
||||
The core memory engine. Handles all memory operations:
|
||||
|
||||
- **Retain**: Ingests content, extracts facts, builds knowledge graph
|
||||
- **Recall**: Semantic search across memories
|
||||
- **Reflect**: Disposition-aware answer generation
|
||||
|
||||
```bash
|
||||
hindsight-api # Default port: 8888
|
||||
```
|
||||
|
||||
The API service is stateless and can be horizontally scaled behind a load balancer. All state is stored in PostgreSQL.
|
||||
|
||||
By default, the API also processes background tasks (mental model consolidation) internally. For high-throughput deployments, you can disable this and run dedicated workers instead.
|
||||
|
||||
## Worker Service
|
||||
|
||||
Dedicated task processor for background operations. Uses the **same package and Docker image** as the API service, just with a different entry point.
|
||||
|
||||
```bash
|
||||
hindsight-worker # Default metrics port: 8889
|
||||
```
|
||||
|
||||
Workers use PostgreSQL as a task broker, polling for pending tasks. Multiple workers can run simultaneously without conflicts.
|
||||
|
||||
| Deployment | Internal Worker | Dedicated Workers |
|
||||
|------------|-----------------|-------------------|
|
||||
| **Development** | ✅ Simple, all-in-one | ❌ Overkill |
|
||||
| **Small production** | ✅ Less infrastructure | ❌ Overkill |
|
||||
| **High throughput** | ❌ API bottleneck | ✅ Scale independently |
|
||||
| **Long-running tasks** | ❌ Blocks API resources | ✅ Isolated processing |
|
||||
|
||||
To use dedicated workers, disable the internal worker in the API and start worker processes:
|
||||
|
||||
```bash
|
||||
# Disable internal worker in API
|
||||
HINDSIGHT_API_WORKER_ENABLED=false hindsight-api
|
||||
|
||||
# Start dedicated workers (run multiple instances)
|
||||
hindsight-worker --worker-id worker-1
|
||||
hindsight-worker --worker-id worker-2
|
||||
```
|
||||
|
||||
Each worker exposes `/health` and `/metrics` endpoints for monitoring.
|
||||
|
||||
Before scaling down or removing workers, release their tasks with `hindsight-admin decommission-worker <worker-id>`.
|
||||
|
||||
See [Configuration - Distributed Workers](./configuration#distributed-workers) for all worker settings and [Installation - Helm](./installation#distributed-workers) for Kubernetes deployment.
|
||||
|
||||
## Control Plane
|
||||
|
||||
Web UI for managing and exploring your memory banks:
|
||||
|
||||
- Browse agents and memory banks
|
||||
- Explore entities and relationships
|
||||
- View ingestion history and operations
|
||||
- Test recall queries interactively
|
||||
|
||||
The Control Plane connects to the API service and provides a visual interface for development and debugging.
|
||||
|
||||
For bare metal deployments, you can run the Control Plane standalone using npx. See [Installation - Bare Metal](./installation#control-plane) for details.
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
# Storage
|
||||
|
||||
Hindsight uses PostgreSQL as its sole storage backend.
|
||||
|
||||
## Why PostgreSQL?
|
||||
|
||||
PostgreSQL provides all capabilities required for a semantic memory system in a single database:
|
||||
|
||||
| Capability | Implementation |
|
||||
|------------|----------------|
|
||||
| Vector search | pgvector extension with HNSW indexes |
|
||||
| Full-text search | Built-in tsvector with GIN indexes |
|
||||
| Relational data | Native PostgreSQL |
|
||||
| JSON documents | JSONB with indexing |
|
||||
| Graph queries | Recursive CTEs |
|
||||
|
||||
### Reduced System Dependencies
|
||||
|
||||
Building exclusively for PostgreSQL simplifies deployment and operations:
|
||||
|
||||
- Single connection string to configure
|
||||
- Single backup and restore strategy
|
||||
- Single monitoring target
|
||||
- ACID transactions across all data types
|
||||
- Single upgrade path
|
||||
|
||||
### No Storage Abstraction
|
||||
|
||||
Hindsight does not abstract storage behind a generic interface. This is a deliberate trade-off.
|
||||
|
||||
We believe PostgreSQL is becoming the standard database API. Its popularity, extension ecosystem, and modularity mean that PostgreSQL-compatible interfaces are appearing everywhere—from serverless offerings to distributed databases. Building for PostgreSQL today means compatibility with a growing ecosystem tomorrow.
|
||||
|
||||
Supporting multiple databases would increase flexibility but conflict with our core goals: Hindsight is fully open source and designed to be as simple as possible to run and use. Adding database abstractions introduces complexity in code, testing, documentation, and operations—complexity that we pass on to users.
|
||||
|
||||
By committing to PostgreSQL, we keep the system simple:
|
||||
- One set of deployment instructions
|
||||
- One set of performance characteristics to understand
|
||||
- One codebase optimized for one backend
|
||||
- No configuration decisions about which database to use
|
||||
|
||||
## Development with pg0
|
||||
|
||||
For local development, Hindsight uses **[pg0](https://github.com/vectorize-io/pg0)**—an embedded PostgreSQL distribution.
|
||||
|
||||
### What is pg0?
|
||||
|
||||
pg0 is a single binary containing:
|
||||
- PostgreSQL server
|
||||
- pgvector extension (pre-installed)
|
||||
- Automatic initialization
|
||||
|
||||
### Behavior
|
||||
|
||||
When no `DATABASE_URL` is configured, Hindsight:
|
||||
1. Starts an embedded PostgreSQL instance on port 5555
|
||||
2. Initializes the schema
|
||||
3. Stores data in `~/.hindsight/pg0/`
|
||||
|
||||
### Environments
|
||||
|
||||
| Environment | Database | Configuration |
|
||||
|-------------|----------|---------------|
|
||||
| Development | pg0 (embedded) | Automatic |
|
||||
| Production | PostgreSQL 15+ | `DATABASE_URL` environment variable |
|
||||
|
||||
## Requirements
|
||||
|
||||
- PostgreSQL 15 or later
|
||||
- pgvector 0.5.0 or later
|
||||
|
||||
Any PostgreSQL instance that satisfies these requirements should work. If you encounter issues with a specific setup, [open a GitHub issue](https://github.com/hindsight-ai/hindsight/issues).
|
||||
|
||||
### Tested Managed Services
|
||||
|
||||
- AWS RDS (PostgreSQL 15+)
|
||||
- Google Cloud SQL
|
||||
- Azure Database for PostgreSQL
|
||||
- Supabase
|
||||
- Neon
|
||||
244
hindsight-docs/versioned_docs/version-0.4/sdks/cli.md
Normal file
244
hindsight-docs/versioned_docs/version-0.4/sdks/cli.md
Normal file
|
|
@ -0,0 +1,244 @@
|
|||
---
|
||||
sidebar_position: 3
|
||||
---
|
||||
|
||||
# CLI Reference
|
||||
|
||||
The Hindsight CLI provides command-line access to memory operations and bank management. All commands follow the [OpenAPI specification](/api-reference), so you can use `--help` on any command to see all available options.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
curl -fsSL https://hindsight.vectorize.io/get-cli | bash
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
Configure the API URL:
|
||||
|
||||
```bash
|
||||
# Interactive configuration
|
||||
hindsight configure
|
||||
|
||||
# Or set directly
|
||||
hindsight configure --api-url http://localhost:8888
|
||||
|
||||
# With API key for authentication
|
||||
hindsight configure --api-url http://localhost:8888 --api-key your-api-key
|
||||
|
||||
# Or use environment variables (highest priority)
|
||||
export HINDSIGHT_API_URL=http://localhost:8888
|
||||
export HINDSIGHT_API_KEY=your-api-key
|
||||
```
|
||||
|
||||
## Core Commands
|
||||
|
||||
### Retain (Store Memory)
|
||||
|
||||
Store a single memory:
|
||||
|
||||
```bash
|
||||
hindsight memory retain <bank_id> "Alice works at Google as a software engineer"
|
||||
|
||||
# With context
|
||||
hindsight memory retain <bank_id> "Bob loves hiking" --context "hobby discussion"
|
||||
|
||||
# Queue for background processing
|
||||
hindsight memory retain <bank_id> "Meeting notes" --async
|
||||
```
|
||||
|
||||
### Retain Files
|
||||
|
||||
Bulk import from files:
|
||||
|
||||
```bash
|
||||
# Single file
|
||||
hindsight memory retain-files <bank_id> notes.txt
|
||||
|
||||
# Directory (recursive by default)
|
||||
hindsight memory retain-files <bank_id> ./documents/
|
||||
|
||||
# With context
|
||||
hindsight memory retain-files <bank_id> meeting-notes.txt --context "team meeting"
|
||||
|
||||
# Background processing
|
||||
hindsight memory retain-files <bank_id> ./data/ --async
|
||||
```
|
||||
|
||||
### Recall (Search)
|
||||
|
||||
Search memories using semantic similarity:
|
||||
|
||||
```bash
|
||||
hindsight memory recall <bank_id> "What does Alice do?"
|
||||
|
||||
# With options
|
||||
hindsight memory recall <bank_id> "hiking recommendations" \
|
||||
--budget high \
|
||||
--max-tokens 8192
|
||||
|
||||
# Filter by fact type
|
||||
hindsight memory recall <bank_id> "query" --fact-type world,observation
|
||||
|
||||
# Show trace information
|
||||
hindsight memory recall <bank_id> "query" --trace
|
||||
```
|
||||
|
||||
### Reflect (Generate Response)
|
||||
|
||||
Generate a response using memories and bank disposition:
|
||||
|
||||
```bash
|
||||
hindsight memory reflect <bank_id> "What do you know about Alice?"
|
||||
|
||||
# With additional context
|
||||
hindsight memory reflect <bank_id> "Should I learn Python?" --context "career advice"
|
||||
|
||||
# Higher budget for complex questions
|
||||
hindsight memory reflect <bank_id> "Summarize my week" --budget high
|
||||
```
|
||||
|
||||
## Bank Management
|
||||
|
||||
### List Banks
|
||||
|
||||
```bash
|
||||
hindsight bank list
|
||||
```
|
||||
|
||||
### View Disposition
|
||||
|
||||
```bash
|
||||
hindsight bank disposition <bank_id>
|
||||
```
|
||||
|
||||
### View Statistics
|
||||
|
||||
```bash
|
||||
hindsight bank stats <bank_id>
|
||||
```
|
||||
|
||||
### Set Bank Name
|
||||
|
||||
```bash
|
||||
hindsight bank name <bank_id> "My Assistant"
|
||||
```
|
||||
|
||||
### Set Mission
|
||||
|
||||
```bash
|
||||
hindsight bank mission <bank_id> "I am a helpful AI assistant interested in technology"
|
||||
```
|
||||
|
||||
## Document Management
|
||||
|
||||
```bash
|
||||
# List documents
|
||||
hindsight document list <bank_id>
|
||||
|
||||
# Get document details
|
||||
hindsight document get <bank_id> <document_id>
|
||||
|
||||
# Delete document and its memories
|
||||
hindsight document delete <bank_id> <document_id>
|
||||
```
|
||||
|
||||
## Entity Management
|
||||
|
||||
```bash
|
||||
# List entities
|
||||
hindsight entity list <bank_id>
|
||||
|
||||
# Get entity details
|
||||
hindsight entity get <bank_id> <entity_id>
|
||||
```
|
||||
|
||||
## Output Formats
|
||||
|
||||
```bash
|
||||
# Pretty (default)
|
||||
hindsight memory recall <bank_id> "query"
|
||||
|
||||
# JSON
|
||||
hindsight memory recall <bank_id> "query" -o json
|
||||
|
||||
# YAML
|
||||
hindsight memory recall <bank_id> "query" -o yaml
|
||||
```
|
||||
|
||||
## Global Options
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `-v, --verbose` | Show detailed output including request/response |
|
||||
| `-o, --output <format>` | Output format: pretty, json, yaml |
|
||||
| `--help` | Show help |
|
||||
| `--version` | Show version |
|
||||
|
||||
## Control Plane UI
|
||||
|
||||
Launch the web-based Control Plane UI directly from the CLI:
|
||||
|
||||
```bash
|
||||
hindsight ui
|
||||
```
|
||||
|
||||
This runs the Control Plane locally on port 9999 using the API URL from your configuration. The UI provides:
|
||||
|
||||
- **Memory bank management** — Browse and manage all your banks
|
||||
- **Entity explorer** — Visualize the knowledge graph
|
||||
- **Query testing** — Interactive recall and reflect testing
|
||||
- **Operation history** — View ingestion and processing logs
|
||||
|
||||
:::tip
|
||||
The UI command requires Node.js to be installed. It automatically downloads and runs the `@vectorize-io/hindsight-control-plane` package via npx.
|
||||
:::
|
||||
|
||||
## Interactive Explorer
|
||||
|
||||
Launch the TUI explorer for visual navigation of your memory banks:
|
||||
|
||||
```bash
|
||||
hindsight explore
|
||||
```
|
||||
|
||||
The explorer provides an interactive terminal interface to:
|
||||
|
||||
- **Browse memory banks** — View all banks and their statistics
|
||||
- **Search memories** — Run recall queries with real-time results
|
||||
- **Inspect entities** — Explore the knowledge graph and entity relationships
|
||||
- **View facts** — Browse world facts, experiences, and observations
|
||||
- **Navigate documents** — See source documents and their extracted memories
|
||||
|
||||
### Keyboard Shortcuts
|
||||
|
||||
| Key | Action |
|
||||
|-----|--------|
|
||||
| `↑/↓` | Navigate items |
|
||||
| `Enter` | Select / Expand |
|
||||
| `Tab` | Switch panels |
|
||||
| `/` | Search |
|
||||
| `q` | Quit |
|
||||
|
||||
<!-- Screenshot placeholder: explore command TUI -->
|
||||
|
||||
## Example Workflow
|
||||
|
||||
```bash
|
||||
# Configure API URL
|
||||
hindsight configure --api-url http://localhost:8888
|
||||
|
||||
# Store some memories
|
||||
hindsight memory retain demo "Alice works at Google"
|
||||
hindsight memory retain demo "Bob is a data scientist"
|
||||
hindsight memory retain demo "Alice and Bob are colleagues"
|
||||
|
||||
# Search memories
|
||||
hindsight memory recall demo "Who works with Alice?"
|
||||
|
||||
# Generate a response
|
||||
hindsight memory reflect demo "What do you know about the team?"
|
||||
|
||||
# Check bank disposition
|
||||
hindsight bank disposition demo
|
||||
```
|
||||
|
|
@ -0,0 +1,345 @@
|
|||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# LiteLLM
|
||||
|
||||
Universal LLM memory integration via [LiteLLM](https://github.com/BerriAI/litellm). Add persistent memory to any LLM application with just a few lines of code.
|
||||
|
||||
## Features
|
||||
|
||||
- **Universal LLM Support** - Works with 100+ LLM providers via LiteLLM (OpenAI, Anthropic, Groq, Azure, AWS Bedrock, Google Vertex AI, and more)
|
||||
- **Simple Integration** - Just configure, enable, and use `hindsight_litellm.completion()`
|
||||
- **Automatic Memory Injection** - Relevant memories are injected into prompts before LLM calls
|
||||
- **Automatic Conversation Storage** - Conversations are stored to Hindsight for future recall
|
||||
- **Two Memory Modes** - Choose between `reflect` (synthesized context) or `recall` (raw memory retrieval)
|
||||
- **Direct Memory APIs** - Query, synthesize, and store memories manually
|
||||
- **Native Client Wrappers** - Alternative wrappers for OpenAI and Anthropic SDKs
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
pip install hindsight-litellm
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
||||
```python
|
||||
import hindsight_litellm
|
||||
|
||||
# Configure and enable memory integration
|
||||
hindsight_litellm.configure(
|
||||
hindsight_api_url="http://localhost:8888",
|
||||
bank_id="my-agent",
|
||||
)
|
||||
hindsight_litellm.enable()
|
||||
|
||||
# Use the convenience wrapper - memory is automatically injected and stored
|
||||
response = hindsight_litellm.completion(
|
||||
model="gpt-4o-mini",
|
||||
messages=[{"role": "user", "content": "What did we discuss about AI?"}]
|
||||
)
|
||||
```
|
||||
|
||||
## How It Works
|
||||
|
||||
When you call `completion()`, the following happens automatically:
|
||||
|
||||
1. **Memory Retrieval** - Hindsight is queried for relevant memories based on the conversation
|
||||
2. **Prompt Injection** - Memories are injected into the system message
|
||||
3. **LLM Call** - The enriched prompt is sent to the LLM
|
||||
4. **Conversation Storage** - The conversation is stored to Hindsight for future recall
|
||||
5. **Response Returned** - You receive the response as normal
|
||||
|
||||
## Configuration Options
|
||||
|
||||
```python
|
||||
hindsight_litellm.configure(
|
||||
# Required
|
||||
hindsight_api_url="http://localhost:8888", # Hindsight API server URL
|
||||
bank_id="my-agent", # Memory bank ID
|
||||
|
||||
api_key="your-api-key", # Optional API key for authentication
|
||||
|
||||
# Optional - Memory behavior
|
||||
store_conversations=True, # Store conversations after LLM calls
|
||||
inject_memories=True, # Inject relevant memories into prompts
|
||||
use_reflect=False, # Use reflect API (synthesized) vs recall (raw memories)
|
||||
reflect_include_facts=False, # Include source facts with reflect responses
|
||||
max_memories=None, # Maximum memories to inject (None = unlimited)
|
||||
max_memory_tokens=4096, # Maximum tokens for memory context
|
||||
recall_budget="mid", # Recall budget: "low", "mid", "high"
|
||||
fact_types=["world", "agent"], # Filter fact types to inject
|
||||
|
||||
# Optional - Bank Configuration
|
||||
bank_name="My Agent", # Human-readable display name for the memory bank
|
||||
mission="This agent...", # Instructions guiding what Hindsight should remember
|
||||
|
||||
# Optional - Advanced
|
||||
injection_mode="system_message", # or "prepend_user"
|
||||
excluded_models=["gpt-3.5*"], # Exclude certain models
|
||||
verbose=True, # Enable verbose logging and debug info
|
||||
)
|
||||
```
|
||||
|
||||
### Bank Configuration
|
||||
|
||||
The `mission` and `bank_name` parameters configure the memory bank itself. When provided, `configure()` will automatically create or update the bank with these settings.
|
||||
|
||||
```python
|
||||
hindsight_litellm.configure(
|
||||
hindsight_api_url="http://localhost:8888",
|
||||
bank_id="support-router",
|
||||
bank_name="Customer Support Router",
|
||||
mission="""You're a customer support router - keep track of which types of issues
|
||||
should go to which teams (billing, technical, sales), customer preferences for
|
||||
communication channels, and past issue resolutions.""",
|
||||
)
|
||||
```
|
||||
|
||||
### Memory Modes: Reflect vs Recall
|
||||
|
||||
- **Recall mode** (`use_reflect=False`, default): Retrieves raw memory facts and injects them as a numbered list. Best when you need precise, individual memories.
|
||||
- **Reflect mode** (`use_reflect=True`): Synthesizes memories into a coherent context paragraph. Best for natural, conversational memory context.
|
||||
|
||||
```python
|
||||
# Recall mode - raw memories
|
||||
hindsight_litellm.configure(
|
||||
bank_id="my-agent",
|
||||
use_reflect=False, # Default
|
||||
)
|
||||
# Injects: "1. [WORLD] User prefers Python\n2. [MENTAL MODEL] User prefers simple code..."
|
||||
|
||||
# Reflect mode - synthesized context
|
||||
hindsight_litellm.configure(
|
||||
bank_id="my-agent",
|
||||
use_reflect=True,
|
||||
)
|
||||
# Injects: "Based on previous conversations, the user is a Python developer who..."
|
||||
```
|
||||
|
||||
## Multi-Provider Support
|
||||
|
||||
Works with any LiteLLM-supported provider:
|
||||
|
||||
```python
|
||||
import hindsight_litellm
|
||||
|
||||
hindsight_litellm.configure(
|
||||
hindsight_api_url="http://localhost:8888",
|
||||
bank_id="my-agent",
|
||||
)
|
||||
hindsight_litellm.enable()
|
||||
|
||||
# OpenAI
|
||||
hindsight_litellm.completion(model="gpt-4o", messages=[...])
|
||||
|
||||
# Anthropic
|
||||
hindsight_litellm.completion(model="claude-3-5-sonnet-20241022", messages=[...])
|
||||
|
||||
# Groq
|
||||
hindsight_litellm.completion(model="groq/llama-3.1-70b-versatile", messages=[...])
|
||||
|
||||
# Azure OpenAI
|
||||
hindsight_litellm.completion(model="azure/gpt-4", messages=[...])
|
||||
|
||||
# AWS Bedrock
|
||||
hindsight_litellm.completion(model="bedrock/anthropic.claude-3", messages=[...])
|
||||
|
||||
# Google Vertex AI
|
||||
hindsight_litellm.completion(model="vertex_ai/gemini-pro", messages=[...])
|
||||
```
|
||||
|
||||
## Direct Memory APIs
|
||||
|
||||
### Recall - Query raw memories
|
||||
|
||||
```python
|
||||
from hindsight_litellm import configure, recall
|
||||
|
||||
configure(bank_id="my-agent", hindsight_api_url="http://localhost:8888")
|
||||
|
||||
memories = recall("what projects am I working on?", budget="mid")
|
||||
for m in memories:
|
||||
print(f"- [{m.fact_type}] {m.text}")
|
||||
```
|
||||
|
||||
### Reflect - Get synthesized context
|
||||
|
||||
```python
|
||||
from hindsight_litellm import configure, reflect
|
||||
|
||||
configure(bank_id="my-agent", hindsight_api_url="http://localhost:8888")
|
||||
|
||||
result = reflect("what do you know about the user's preferences?")
|
||||
print(result.text)
|
||||
```
|
||||
|
||||
### Retain - Store memories
|
||||
|
||||
```python
|
||||
from hindsight_litellm import configure, retain
|
||||
|
||||
configure(bank_id="my-agent", hindsight_api_url="http://localhost:8888")
|
||||
|
||||
result = retain(
|
||||
content="User mentioned they're working on a machine learning project",
|
||||
context="Discussion about current projects",
|
||||
)
|
||||
```
|
||||
|
||||
### Async APIs
|
||||
|
||||
```python
|
||||
from hindsight_litellm import arecall, areflect, aretain
|
||||
|
||||
# Async versions of all memory APIs
|
||||
memories = await arecall("what do you know about me?")
|
||||
context = await areflect("summarize user preferences")
|
||||
result = await aretain(content="New information to remember")
|
||||
```
|
||||
|
||||
## Native Client Wrappers
|
||||
|
||||
Alternative to LiteLLM callbacks for direct SDK integration.
|
||||
|
||||
### OpenAI Wrapper
|
||||
|
||||
```python
|
||||
from openai import OpenAI
|
||||
from hindsight_litellm import wrap_openai
|
||||
|
||||
client = OpenAI()
|
||||
wrapped = wrap_openai(
|
||||
client,
|
||||
bank_id="my-agent",
|
||||
hindsight_api_url="http://localhost:8888",
|
||||
)
|
||||
|
||||
response = wrapped.chat.completions.create(
|
||||
model="gpt-4",
|
||||
messages=[{"role": "user", "content": "What do you know about me?"}]
|
||||
)
|
||||
```
|
||||
|
||||
### Anthropic Wrapper
|
||||
|
||||
```python
|
||||
from anthropic import Anthropic
|
||||
from hindsight_litellm import wrap_anthropic
|
||||
|
||||
client = Anthropic()
|
||||
wrapped = wrap_anthropic(
|
||||
client,
|
||||
bank_id="my-agent",
|
||||
hindsight_api_url="http://localhost:8888",
|
||||
)
|
||||
|
||||
response = wrapped.messages.create(
|
||||
model="claude-3-5-sonnet-20241022",
|
||||
max_tokens=1024,
|
||||
messages=[{"role": "user", "content": "Hello!"}]
|
||||
)
|
||||
```
|
||||
|
||||
## Debug Mode
|
||||
|
||||
When `verbose=True`, you can inspect exactly what memories are being injected:
|
||||
|
||||
```python
|
||||
from hindsight_litellm import configure, enable, completion, get_last_injection_debug
|
||||
|
||||
configure(
|
||||
bank_id="my-agent",
|
||||
hindsight_api_url="http://localhost:8888",
|
||||
verbose=True,
|
||||
)
|
||||
enable()
|
||||
|
||||
response = completion(
|
||||
model="gpt-4o-mini",
|
||||
messages=[{"role": "user", "content": "What's my favorite color?"}]
|
||||
)
|
||||
|
||||
# Inspect what was injected
|
||||
debug = get_last_injection_debug()
|
||||
if debug:
|
||||
print(f"Mode: {debug.mode}") # "reflect" or "recall"
|
||||
print(f"Injected: {debug.injected}") # True/False
|
||||
print(f"Results: {debug.results_count}")
|
||||
print(f"Memory context:\n{debug.memory_context}")
|
||||
```
|
||||
|
||||
## Context Manager
|
||||
|
||||
```python
|
||||
from hindsight_litellm import hindsight_memory
|
||||
import litellm
|
||||
|
||||
with hindsight_memory(bank_id="user-123"):
|
||||
response = litellm.completion(model="gpt-4", messages=[...])
|
||||
# Memory integration automatically disabled after context
|
||||
```
|
||||
|
||||
## Disabling and Cleanup
|
||||
|
||||
```python
|
||||
from hindsight_litellm import disable, cleanup
|
||||
|
||||
# Temporarily disable memory integration
|
||||
disable()
|
||||
|
||||
# Clean up all resources (call when shutting down)
|
||||
cleanup()
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### Main Functions
|
||||
|
||||
| Function | Description |
|
||||
|----------|-------------|
|
||||
| `configure(...)` | Configure global Hindsight settings |
|
||||
| `enable()` | Enable memory integration with LiteLLM |
|
||||
| `disable()` | Disable memory integration |
|
||||
| `is_enabled()` | Check if memory integration is enabled |
|
||||
| `cleanup()` | Clean up all resources |
|
||||
|
||||
### Configuration Functions
|
||||
|
||||
| Function | Description |
|
||||
|----------|-------------|
|
||||
| `get_config()` | Get current configuration |
|
||||
| `is_configured()` | Check if Hindsight is configured |
|
||||
| `reset_config()` | Reset configuration to defaults |
|
||||
|
||||
### Memory Functions
|
||||
|
||||
| Function | Description |
|
||||
|----------|-------------|
|
||||
| `recall(query, ...)` | Synchronously query raw memories |
|
||||
| `arecall(query, ...)` | Asynchronously query raw memories |
|
||||
| `reflect(query, ...)` | Synchronously get synthesized memory context |
|
||||
| `areflect(query, ...)` | Asynchronously get synthesized memory context |
|
||||
| `retain(content, ...)` | Synchronously store a memory |
|
||||
| `aretain(content, ...)` | Asynchronously store a memory |
|
||||
|
||||
### Debug Functions
|
||||
|
||||
| Function | Description |
|
||||
|----------|-------------|
|
||||
| `get_last_injection_debug()` | Get debug info from last memory injection |
|
||||
| `clear_injection_debug()` | Clear stored debug info |
|
||||
|
||||
### Client Wrappers
|
||||
|
||||
| Function | Description |
|
||||
|----------|-------------|
|
||||
| `wrap_openai(client, ...)` | Wrap OpenAI client with memory |
|
||||
| `wrap_anthropic(client, ...)` | Wrap Anthropic client with memory |
|
||||
|
||||
## Requirements
|
||||
|
||||
- Python >= 3.10
|
||||
- litellm >= 1.40.0
|
||||
- A running Hindsight API server
|
||||
|
|
@ -0,0 +1,193 @@
|
|||
---
|
||||
sidebar_position: 2
|
||||
---
|
||||
|
||||
# Local MCP Server
|
||||
|
||||
Hindsight provides a fully local MCP server that runs entirely on your machine with an embedded PostgreSQL database. No external server or database setup required.
|
||||
|
||||
This is ideal for:
|
||||
- **Personal use with Claude Desktop** — Give Claude long-term memory across conversations
|
||||
- **Development and testing** — Quick setup without infrastructure
|
||||
- **Privacy-focused setups** — All data stays on your machine
|
||||
|
||||
## Quick Install
|
||||
|
||||
```bash
|
||||
curl -fsSL https://hindsight.vectorize.io/get-mcp | bash -s -- \
|
||||
--app claude-desktop \
|
||||
--set HINDSIGHT_API_LLM_API_KEY=sk-...
|
||||
```
|
||||
|
||||
This script will:
|
||||
1. Install [uv](https://docs.astral.sh/uv/) if not already installed
|
||||
2. Configure Claude Desktop to use the Hindsight MCP server
|
||||
3. Set the provided environment variables in the MCP configuration
|
||||
|
||||
:::info Other MCP Applications
|
||||
The quick install script currently supports Claude Desktop only. For other MCP-compatible applications (Cursor, Cline, etc.), follow the [Manual Configuration](#manual-configuration) steps below.
|
||||
:::
|
||||
|
||||
## Manual Configuration
|
||||
|
||||
Add the following to your MCP client's configuration. For Claude Desktop:
|
||||
|
||||
- **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
||||
- **Linux**: `~/.config/Claude/claude_desktop_config.json`
|
||||
|
||||
For other MCP clients, refer to their documentation for the configuration file location.
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"hindsight": {
|
||||
"command": "uvx",
|
||||
"args": ["--from", "hindsight-api", "hindsight-local-mcp"],
|
||||
"env": {
|
||||
"HINDSIGHT_API_LLM_API_KEY": "sk-..."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### With Custom Bank ID
|
||||
|
||||
By default, memories are stored in a bank called `mcp`. To use a different bank:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"hindsight": {
|
||||
"command": "uvx",
|
||||
"args": ["--from", "hindsight-api", "hindsight-local-mcp"],
|
||||
"env": {
|
||||
"HINDSIGHT_API_LLM_API_KEY": "sk-...",
|
||||
"HINDSIGHT_API_MCP_LOCAL_BANK_ID": "my-personal-memory"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Environment Variables
|
||||
|
||||
All standard [Hindsight configuration variables](/developer/configuration) are supported.
|
||||
|
||||
### Local MCP Specific
|
||||
|
||||
| Variable | Required | Default | Description |
|
||||
|----------|----------|---------|-------------|
|
||||
| `HINDSIGHT_API_MCP_LOCAL_BANK_ID` | No | `mcp` | Memory bank ID to use |
|
||||
| `HINDSIGHT_API_MCP_INSTRUCTIONS` | No | - | Additional instructions appended to both `retain` and `recall` tools |
|
||||
|
||||
### Customizing Tool Behavior
|
||||
|
||||
You can customize what gets stored by adding instructions to the tools. Re-run the install script with the additional `--set` flag:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://hindsight.vectorize.io/get-mcp | bash -s -- \
|
||||
--app claude-desktop \
|
||||
--set HINDSIGHT_API_LLM_API_KEY=sk-... \
|
||||
--set HINDSIGHT_API_MCP_INSTRUCTIONS="Also store every action you take, code you write, and files you modify."
|
||||
```
|
||||
|
||||
These instructions are appended to the default tool descriptions, guiding Claude on when and how to use the memory tools.
|
||||
|
||||
## Available Tools
|
||||
|
||||
### retain
|
||||
|
||||
Store information to long-term memory. This is a **fire-and-forget** operation — it returns immediately while processing happens in the background.
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|----------|-------------|
|
||||
| `content` | string | Yes | The fact or memory to store |
|
||||
| `context` | string | No | Category for the memory (default: `general`) |
|
||||
|
||||
**Example:**
|
||||
```json
|
||||
{
|
||||
"name": "retain",
|
||||
"arguments": {
|
||||
"content": "User's favorite color is blue",
|
||||
"context": "preferences"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"status": "accepted",
|
||||
"message": "Memory storage initiated"
|
||||
}
|
||||
```
|
||||
|
||||
### recall
|
||||
|
||||
Search memories to provide personalized responses.
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|----------|-------------|
|
||||
| `query` | string | Yes | Natural language search query |
|
||||
| `max_tokens` | integer | No | Maximum tokens to return (default: 4096) |
|
||||
| `budget` | string | No | Search depth: `low`, `mid`, or `high` (default: `low`) |
|
||||
|
||||
**Example:**
|
||||
```json
|
||||
{
|
||||
"name": "recall",
|
||||
"arguments": {
|
||||
"query": "What are the user's color preferences?",
|
||||
"max_tokens": 2048,
|
||||
"budget": "mid"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## How It Works
|
||||
|
||||
The local MCP server:
|
||||
|
||||
1. **Starts an embedded PostgreSQL** (pg0) on an automatically assigned port
|
||||
2. **Initializes the Hindsight memory engine** with local embeddings
|
||||
3. **Connects via stdio** to Claude Code using the MCP protocol
|
||||
|
||||
Data is persisted in the pg0 data directory (`~/.pg0/hindsight-mcp/`), so your memories survive restarts.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "HINDSIGHT_API_LLM_API_KEY required"
|
||||
|
||||
Make sure you've set the API key in your MCP configuration:
|
||||
|
||||
```json
|
||||
{
|
||||
"env": {
|
||||
"HINDSIGHT_API_LLM_API_KEY": "sk-..."
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Slow startup
|
||||
|
||||
The first startup may take longer as it:
|
||||
- Downloads the embedding model (~100MB)
|
||||
- Initializes the PostgreSQL database
|
||||
|
||||
Subsequent starts are faster.
|
||||
|
||||
### Checking logs
|
||||
|
||||
Set `HINDSIGHT_API_LOG_LEVEL=debug` for verbose output:
|
||||
|
||||
```json
|
||||
{
|
||||
"env": {
|
||||
"HINDSIGHT_API_LOG_LEVEL": "debug"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Logs are written to stderr and visible in Claude Code's MCP server output.
|
||||
|
|
@ -0,0 +1,323 @@
|
|||
---
|
||||
sidebar_position: 3
|
||||
---
|
||||
|
||||
# Skills
|
||||
|
||||
Hindsight provides an Agent Skill that gives AI coding assistants persistent memory across sessions. Skills are reusable prompt templates that agents can load when needed to gain specialized capabilities.
|
||||
|
||||
## Supported Platforms
|
||||
|
||||
| Platform | Skills Directory |
|
||||
|----------|-----------------|
|
||||
| [Claude Code](https://docs.anthropic.com/en/docs/claude-code) | `~/.claude/skills/` |
|
||||
| [OpenCode](https://github.com/opencode-ai/opencode) | `~/.opencode/skills/` |
|
||||
| [Codex CLI](https://github.com/openai/codex) | `~/.codex/skills/` |
|
||||
|
||||
## Deployment Modes
|
||||
|
||||
The skill supports two deployment modes:
|
||||
|
||||
| Mode | Best For | Data Location |
|
||||
|------|----------|---------------|
|
||||
| **Local** | Individual developers | Your machine (`~/.pg0/`) |
|
||||
| **Cloud** | Teams sharing knowledge | Hindsight Cloud |
|
||||
|
||||
## Quick Install
|
||||
|
||||
### Option 1: Interactive Installer (Recommended)
|
||||
|
||||
```bash
|
||||
curl -fsSL https://hindsight.vectorize.io/get-skill | bash
|
||||
```
|
||||
|
||||
The installer will:
|
||||
1. Prompt you to select your AI coding assistant
|
||||
2. Select deployment mode (local or cloud)
|
||||
3. Configure the appropriate settings
|
||||
4. Install the skill to the appropriate directory
|
||||
|
||||
### Install for a Specific Platform
|
||||
|
||||
```bash
|
||||
# Claude Code (interactive mode selection)
|
||||
curl -fsSL https://hindsight.vectorize.io/get-skill | bash -s -- --app claude
|
||||
|
||||
# OpenCode
|
||||
curl -fsSL https://hindsight.vectorize.io/get-skill | bash -s -- --app opencode
|
||||
|
||||
# Codex CLI
|
||||
curl -fsSL https://hindsight.vectorize.io/get-skill | bash -s -- --app codex
|
||||
```
|
||||
|
||||
### Install with Cloud Mode
|
||||
|
||||
```bash
|
||||
# Direct cloud setup (skips interactive prompts for mode)
|
||||
curl -fsSL https://hindsight.vectorize.io/get-skill | bash -s -- --app claude --mode cloud
|
||||
```
|
||||
|
||||
### Option 2: Using add-skill
|
||||
|
||||
If you use [add-skill](https://add-skill.org/) to manage your agent skills:
|
||||
|
||||
```bash
|
||||
# For local mode (individual developers)
|
||||
npx add-skill vectorize-io/hindsight --skill hindsight-local
|
||||
|
||||
# For Hindsight Cloud (teams)
|
||||
npx add-skill vectorize-io/hindsight --skill hindsight-cloud
|
||||
|
||||
# For self-hosted Hindsight servers
|
||||
npx add-skill vectorize-io/hindsight --skill hindsight-self-hosted
|
||||
```
|
||||
|
||||
On first use, the AI will guide you through the remaining setup:
|
||||
- **Local**: Run `uvx hindsight-embed configure` to set up your LLM provider
|
||||
- **Cloud**: Provide your API key and bank ID
|
||||
- **Self-hosted**: Provide your server URL, API key, and bank ID
|
||||
|
||||
## What the Skill Provides
|
||||
|
||||
Once installed, your AI assistant gains the ability to:
|
||||
|
||||
- **Retain** - Store user preferences, learnings, and procedure outcomes
|
||||
- **Recall** - Search for relevant context before starting tasks
|
||||
- **Reflect** - Synthesize memories into contextual answers
|
||||
|
||||
The skill uses the `hindsight-embed` CLI which runs a lightweight local daemon with an embedded database.
|
||||
|
||||
## How Skills Work
|
||||
|
||||
Skills are **model-invoked**, meaning the AI assistant automatically decides when to use them based on the context of your conversation. You don't need to explicitly trigger the skill.
|
||||
|
||||
The assistant will:
|
||||
- **Store** when you share preferences, when tasks succeed/fail, or when learnings emerge
|
||||
- **Recall** before starting non-trivial tasks to get relevant context
|
||||
|
||||
### What Gets Stored
|
||||
|
||||
The skill is optimized to store:
|
||||
|
||||
| Category | Examples |
|
||||
|----------|----------|
|
||||
| **User Preferences** | Coding style, tool preferences, language choices |
|
||||
| **Procedure Outcomes** | Commands that worked, configurations that resolved issues |
|
||||
| **Learnings** | Bug solutions, workarounds, architecture decisions |
|
||||
|
||||
## Architecture
|
||||
|
||||
### Local Mode
|
||||
|
||||
```
|
||||
AI Coding Assistant
|
||||
│
|
||||
▼
|
||||
Hindsight Skill (SKILL.md)
|
||||
│
|
||||
▼
|
||||
hindsight-embed CLI
|
||||
│
|
||||
▼
|
||||
Local Daemon (auto-started)
|
||||
│
|
||||
▼
|
||||
Embedded PostgreSQL (~/.pg0/hindsight-embed/)
|
||||
```
|
||||
|
||||
All data stays on your machine. The daemon auto-starts when needed and shuts down after inactivity.
|
||||
|
||||
### Cloud Mode
|
||||
|
||||
```
|
||||
AI Coding Assistant
|
||||
│
|
||||
▼
|
||||
Hindsight Skill (SKILL.md)
|
||||
│
|
||||
▼
|
||||
hindsight-cli
|
||||
│
|
||||
▼
|
||||
Hindsight Cloud API (https://api.hindsight.vectorize.io)
|
||||
│
|
||||
▼
|
||||
Shared Memory Bank (team-accessible)
|
||||
```
|
||||
|
||||
Data is stored in Hindsight Cloud and shared across your team. All team members with the same bank ID can access shared memories.
|
||||
|
||||
---
|
||||
|
||||
## Local Mode Setup
|
||||
|
||||
The skill uses configuration stored in `~/.hindsight/config.env`. Reconfigure anytime:
|
||||
|
||||
```bash
|
||||
uvx hindsight-embed configure
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Cloud Mode Setup
|
||||
|
||||
Cloud mode connects to [Hindsight Cloud](https://vectorize.io/hindsight/cloud), allowing teams to share memories about a codebase. When one team member learns something, everyone benefits.
|
||||
|
||||
### Prerequisites
|
||||
|
||||
1. A Hindsight Cloud account ([request access](https://vectorize.io/hindsight/cloud))
|
||||
2. An API key from your team admin
|
||||
3. A bank ID for your project (e.g., `team-acme-frontend`)
|
||||
|
||||
### Installation
|
||||
|
||||
Run the installer with cloud mode:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://hindsight.vectorize.io/get-skill | bash -s -- --mode cloud
|
||||
```
|
||||
|
||||
You'll be prompted for:
|
||||
|
||||
| Setting | Description | Example |
|
||||
|---------|-------------|---------|
|
||||
| **Cloud API URL** | Hindsight Cloud endpoint | `https://api.hindsight.vectorize.io` |
|
||||
| **API Key** | Your authentication key | `hs_xxx...` |
|
||||
| **Bank ID** | Shared memory bank for your team | `team-acme-frontend` |
|
||||
|
||||
### Configuration Files
|
||||
|
||||
Cloud mode creates two files:
|
||||
|
||||
**`~/.hindsight/config`** — API connection settings (TOML format):
|
||||
```toml
|
||||
api_url = "https://api.hindsight.vectorize.io"
|
||||
api_key = "hs_xxx..."
|
||||
```
|
||||
|
||||
**`~/.claude/skills/hindsight/SKILL.md`** — Skill definition with your bank ID baked in.
|
||||
|
||||
### Team Setup
|
||||
|
||||
To set up cloud mode for your team:
|
||||
|
||||
1. **Team admin** creates a bank in Hindsight Cloud (e.g., `team-acme-frontend`)
|
||||
2. **Team admin** generates API keys for each team member
|
||||
3. **Each developer** runs the installer with their API key and the shared bank ID
|
||||
4. All team members now share the same memory bank
|
||||
|
||||
### What to Store in Team Banks
|
||||
|
||||
Cloud mode uses a **shared team bank**. Be thoughtful about what goes in:
|
||||
|
||||
| Type | Examples | How to Store |
|
||||
|------|----------|--------------|
|
||||
| **Project conventions** | Linting rules, testing requirements, Node version | `"Project uses ESLint with Airbnb config"` |
|
||||
| **Team knowledge** | Architecture decisions, common pitfalls, domain logic | `"Auth module requires Redis 7+"` |
|
||||
| **Individual preferences** | Personal coding style, communication preferences | `"Alice prefers verbose commit messages"` |
|
||||
|
||||
**Key distinction**: Project conventions apply to everyone. Individual preferences should include the person's name so the AI knows when to apply them.
|
||||
|
||||
### Example Workflow
|
||||
|
||||
```
|
||||
Day 1: Alice discovers a requirement
|
||||
─────────────────────────────────────
|
||||
Alice's AI assistant stores:
|
||||
"The auth module requires Redis 7+ due to HEXPIRE command usage"
|
||||
"Alice prefers explicit error handling over silent failures"
|
||||
|
||||
Day 2: Bob starts working on auth
|
||||
─────────────────────────────────
|
||||
Bob's AI assistant recalls:
|
||||
"The auth module requires Redis 7+ due to HEXPIRE command usage"
|
||||
|
||||
Bob avoids the same issue Alice hit!
|
||||
(Alice's personal preference is stored but won't be applied to Bob)
|
||||
```
|
||||
|
||||
### Testing Cloud Connection
|
||||
|
||||
After installation, verify the connection:
|
||||
|
||||
```bash
|
||||
# Store a test memory
|
||||
hindsight memory retain team-acme-frontend "Alice works at Google as a software engineer"
|
||||
|
||||
# Recall it
|
||||
hindsight memory recall team-acme-frontend "Alice"
|
||||
```
|
||||
|
||||
### Switching Between Banks
|
||||
|
||||
If you work on multiple projects, you can have different skills installed for each AI assistant, or manually switch banks:
|
||||
|
||||
```bash
|
||||
# Environment variable override (temporary)
|
||||
HINDSIGHT_API_URL=https://api.hindsight.vectorize.io \
|
||||
HINDSIGHT_API_KEY=hs_xxx \
|
||||
hindsight memory recall different-bank "query"
|
||||
```
|
||||
|
||||
For permanent multi-bank setups, reinstall the skill with a different bank ID.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Skill not activating
|
||||
|
||||
The skill activates based on its description matching your request. Try being explicit:
|
||||
- "Remember that..." triggers storage
|
||||
- "What do you know about..." triggers recall
|
||||
|
||||
### Local Mode Issues
|
||||
|
||||
**Daemon not starting:**
|
||||
```bash
|
||||
uvx hindsight-embed daemon status
|
||||
uvx hindsight-embed daemon logs
|
||||
```
|
||||
|
||||
**Reconfigure LLM provider:**
|
||||
```bash
|
||||
uvx hindsight-embed configure
|
||||
```
|
||||
|
||||
### Cloud Mode Issues
|
||||
|
||||
**Authentication errors:**
|
||||
```bash
|
||||
# Verify your config
|
||||
cat ~/.hindsight/config
|
||||
|
||||
# Test connection manually
|
||||
hindsight bank list
|
||||
```
|
||||
|
||||
**Wrong bank ID:**
|
||||
|
||||
Check your SKILL.md file to see which bank ID is configured:
|
||||
```bash
|
||||
cat ~/.claude/skills/hindsight/SKILL.md | grep "memory retain"
|
||||
```
|
||||
|
||||
To change the bank ID, reinstall the skill:
|
||||
```bash
|
||||
curl -fsSL https://hindsight.vectorize.io/get-skill | bash -s -- --mode cloud
|
||||
```
|
||||
|
||||
**Network/firewall issues:**
|
||||
```bash
|
||||
# Test connectivity to cloud API
|
||||
curl -I https://api.hindsight.vectorize.io/health
|
||||
```
|
||||
|
||||
## Requirements
|
||||
|
||||
### Local Mode
|
||||
- Python 3.10+ (for `uvx`)
|
||||
- An LLM API key (OpenAI, Anthropic, Groq, etc.)
|
||||
|
||||
### Cloud Mode
|
||||
- Python 3.10+ (for `uvx`)
|
||||
- Hindsight Cloud API key
|
||||
- Network access to `https://api.hindsight.vectorize.io`
|
||||
129
hindsight-docs/versioned_docs/version-0.4/sdks/nodejs.md
Normal file
129
hindsight-docs/versioned_docs/version-0.4/sdks/nodejs.md
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
---
|
||||
sidebar_position: 2
|
||||
---
|
||||
|
||||
# Node.js Client
|
||||
|
||||
Official TypeScript/JavaScript client for the Hindsight API.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm install @vectorize-io/hindsight-client
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
||||
```typescript
|
||||
const { HindsightClient } = require('@vectorize-io/hindsight-client');
|
||||
|
||||
const client = new HindsightClient({ baseUrl: 'http://localhost:8888' });
|
||||
|
||||
// Retain a memory
|
||||
await client.retain('my-bank', 'Alice works at Google');
|
||||
|
||||
// Recall memories
|
||||
const response = await client.recall('my-bank', 'What does Alice do?');
|
||||
for (const r of response.results) {
|
||||
console.log(r.text);
|
||||
}
|
||||
|
||||
// Reflect - generate response with disposition
|
||||
const answer = await client.reflect('my-bank', 'Tell me about Alice');
|
||||
console.log(answer.text);
|
||||
```
|
||||
|
||||
## Client Initialization
|
||||
|
||||
```typescript
|
||||
import { HindsightClient } from '@vectorize-io/hindsight-client';
|
||||
|
||||
const client = new HindsightClient({
|
||||
baseUrl: 'http://localhost:8888',
|
||||
});
|
||||
```
|
||||
|
||||
## Core Operations
|
||||
|
||||
### Retain (Store Memory)
|
||||
|
||||
```typescript
|
||||
// Simple
|
||||
await client.retain('my-bank', 'Alice works at Google');
|
||||
|
||||
// With options
|
||||
await client.retain('my-bank', 'Alice got promoted', {
|
||||
timestamp: new Date('2024-01-15'),
|
||||
context: 'career update',
|
||||
metadata: { source: 'slack' },
|
||||
async: false, // Set true for background processing
|
||||
});
|
||||
```
|
||||
|
||||
### Retain Batch
|
||||
|
||||
```typescript
|
||||
await client.retainBatch('my-bank', [
|
||||
{ content: 'Alice works at Google', context: 'career' },
|
||||
{ content: 'Bob is a data scientist', context: 'career' },
|
||||
], {
|
||||
async: false,
|
||||
});
|
||||
```
|
||||
|
||||
### Recall (Search)
|
||||
|
||||
```typescript
|
||||
// Simple - returns RecallResponse
|
||||
const response = await client.recall('my-bank', 'What does Alice do?');
|
||||
|
||||
for (const r of response.results) {
|
||||
console.log(`${r.text} (type: ${r.type})`);
|
||||
}
|
||||
|
||||
// With options
|
||||
const response = await client.recall('my-bank', 'What does Alice do?', {
|
||||
types: ['world', 'observation'], // Filter by fact type
|
||||
maxTokens: 4096,
|
||||
budget: 'high', // 'low', 'mid', or 'high'
|
||||
});
|
||||
```
|
||||
|
||||
### Reflect (Generate Response)
|
||||
|
||||
```typescript
|
||||
const answer = await client.reflect('my-bank', 'What should I know about Alice?', {
|
||||
budget: 'low', // 'low', 'mid', or 'high'
|
||||
context: 'preparing for a meeting',
|
||||
});
|
||||
|
||||
console.log(answer.text); // Generated response
|
||||
```
|
||||
|
||||
## Bank Management
|
||||
|
||||
### Create Bank
|
||||
|
||||
```typescript
|
||||
await client.createBank('my-bank', {
|
||||
name: 'Assistant',
|
||||
mission: "You're a helpful AI assistant - keep track of user preferences and conversation history.",
|
||||
disposition: {
|
||||
skepticism: 3, // 1-5: trusting to skeptical
|
||||
literalism: 3, // 1-5: flexible to literal
|
||||
empathy: 3, // 1-5: detached to empathetic
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### List Memories
|
||||
|
||||
```typescript
|
||||
const response = await client.listMemories('my-bank', {
|
||||
type: 'world', // Optional filter
|
||||
q: 'Alice', // Optional text search
|
||||
limit: 100,
|
||||
offset: 0,
|
||||
});
|
||||
console.log(response)
|
||||
```
|
||||
259
hindsight-docs/versioned_docs/version-0.4/sdks/python.md
Normal file
259
hindsight-docs/versioned_docs/version-0.4/sdks/python.md
Normal file
|
|
@ -0,0 +1,259 @@
|
|||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# Python Client
|
||||
|
||||
Official Python client for the Hindsight API.
|
||||
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
|
||||
## Installation
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="all-in-one" label="All-in-One (Recommended)">
|
||||
|
||||
The `hindsight-all` package includes embedded PostgreSQL, HTTP API server, and client:
|
||||
|
||||
```bash
|
||||
pip install hindsight-all
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="client-only" label="Client Only">
|
||||
|
||||
If you already have a Hindsight server running:
|
||||
|
||||
```bash
|
||||
pip install hindsight-client
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## Quick Start
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="all-in-one" label="All-in-One">
|
||||
|
||||
```python
|
||||
import os
|
||||
from hindsight import HindsightServer, HindsightClient
|
||||
|
||||
with HindsightServer(
|
||||
llm_provider="openai",
|
||||
llm_model="gpt-4o-mini",
|
||||
llm_api_key=os.environ["OPENAI_API_KEY"]
|
||||
) as server:
|
||||
client = HindsightClient(base_url=server.url)
|
||||
|
||||
# Retain a memory
|
||||
client.retain(bank_id="my-bank", content="Alice works at Google")
|
||||
|
||||
# Recall memories
|
||||
results = client.recall(bank_id="my-bank", query="What does Alice do?")
|
||||
for r in results:
|
||||
print(r.text)
|
||||
|
||||
# Reflect - generate response with disposition
|
||||
answer = client.reflect(bank_id="my-bank", query="Tell me about Alice")
|
||||
print(answer.text)
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="client-only" label="Client Only">
|
||||
|
||||
```python
|
||||
from hindsight_client import Hindsight
|
||||
|
||||
client = Hindsight(base_url="http://localhost:8888")
|
||||
|
||||
# Retain a memory
|
||||
client.retain(bank_id="my-bank", content="Alice works at Google")
|
||||
|
||||
# Recall memories
|
||||
results = client.recall(bank_id="my-bank", query="What does Alice do?")
|
||||
for r in results:
|
||||
print(r.text)
|
||||
|
||||
# Reflect - generate response with disposition
|
||||
answer = client.reflect(bank_id="my-bank", query="Tell me about Alice")
|
||||
print(answer.text)
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## Client Initialization
|
||||
|
||||
```python
|
||||
from hindsight_client import Hindsight
|
||||
|
||||
client = Hindsight(
|
||||
base_url="http://localhost:8888", # Hindsight API URL
|
||||
timeout=30.0, # Request timeout in seconds
|
||||
)
|
||||
```
|
||||
|
||||
## Core Operations
|
||||
|
||||
### Retain (Store Memory)
|
||||
|
||||
```python
|
||||
# Simple
|
||||
client.retain(
|
||||
bank_id="my-bank",
|
||||
content="Alice works at Google as a software engineer",
|
||||
)
|
||||
|
||||
# With options
|
||||
from datetime import datetime
|
||||
|
||||
client.retain(
|
||||
bank_id="my-bank",
|
||||
content="Alice got promoted",
|
||||
context="career update",
|
||||
timestamp=datetime(2024, 1, 15),
|
||||
document_id="conversation_001",
|
||||
metadata={"source": "slack"},
|
||||
)
|
||||
```
|
||||
|
||||
### Retain Batch
|
||||
|
||||
```python
|
||||
client.retain_batch(
|
||||
bank_id="my-bank",
|
||||
items=[
|
||||
{"content": "Alice works at Google", "context": "career"},
|
||||
{"content": "Bob is a data scientist", "context": "career"},
|
||||
],
|
||||
document_id="conversation_001",
|
||||
retain_async=False, # Set True for background processing
|
||||
)
|
||||
```
|
||||
|
||||
### Recall (Search)
|
||||
|
||||
```python
|
||||
# Simple - returns list of RecallResult
|
||||
results = client.recall(
|
||||
bank_id="my-bank",
|
||||
query="What does Alice do?",
|
||||
)
|
||||
|
||||
for r in results.results:
|
||||
print(f"{r.text} (type: {r.type})")
|
||||
|
||||
# With options
|
||||
results = client.recall(
|
||||
bank_id="my-bank",
|
||||
query="What does Alice do?",
|
||||
types=["world", "observation"], # Filter by fact type
|
||||
max_tokens=4096,
|
||||
budget="high", # low, mid, or high
|
||||
)
|
||||
```
|
||||
|
||||
### Recall with Chunks
|
||||
|
||||
```python
|
||||
# Returns RecallResponse with source chunks
|
||||
response = client.recall(
|
||||
bank_id="my-bank",
|
||||
query="What does Alice do?",
|
||||
types=["world", "experience"],
|
||||
budget="mid",
|
||||
max_tokens=4096,
|
||||
include_chunks=True,
|
||||
max_chunk_tokens=500
|
||||
)
|
||||
|
||||
print(f"Found {len(response.results)} memories")
|
||||
for r in response.results:
|
||||
print(f" - {r.text}")
|
||||
if r.chunks:
|
||||
print(f" Source: {r.chunks[0].text[:100]}...")
|
||||
```
|
||||
|
||||
### Reflect (Generate Response)
|
||||
|
||||
```python
|
||||
answer = client.reflect(
|
||||
bank_id="my-bank",
|
||||
query="What should I know about Alice?",
|
||||
budget="low", # low, mid, or high
|
||||
context="preparing for a meeting",
|
||||
)
|
||||
|
||||
print(answer.text) # Generated response
|
||||
```
|
||||
|
||||
## Bank Management
|
||||
|
||||
### Create Bank
|
||||
|
||||
```python
|
||||
client.create_bank(
|
||||
bank_id="my-bank",
|
||||
name="Assistant",
|
||||
mission="You're a helpful AI assistant - keep track of user preferences and conversation history.",
|
||||
disposition={
|
||||
"skepticism": 3, # 1-5: trusting to skeptical
|
||||
"literalism": 3, # 1-5: flexible to literal
|
||||
"empathy": 3, # 1-5: detached to empathetic
|
||||
},
|
||||
)
|
||||
```
|
||||
|
||||
### List Memories
|
||||
|
||||
```python
|
||||
client.list_memories(
|
||||
bank_id="my-bank",
|
||||
type="world", # Optional: filter by type
|
||||
search_query="Alice", # Optional: text search
|
||||
limit=100,
|
||||
offset=0,
|
||||
)
|
||||
```
|
||||
|
||||
## Async Support
|
||||
|
||||
All methods have async versions prefixed with `a`:
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
from hindsight_client import Hindsight
|
||||
|
||||
async def main():
|
||||
client = Hindsight(base_url="http://localhost:8888")
|
||||
|
||||
# Async retain
|
||||
await client.aretain(bank_id="my-bank", content="Hello world")
|
||||
|
||||
# Async recall
|
||||
results = await client.arecall(bank_id="my-bank", query="Hello")
|
||||
for r in results:
|
||||
print(r.text)
|
||||
|
||||
# Async reflect
|
||||
answer = await client.areflect(bank_id="my-bank", query="What did I say?")
|
||||
print(answer.text)
|
||||
|
||||
client.close()
|
||||
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
## Context Manager
|
||||
|
||||
```python
|
||||
from hindsight_client import Hindsight
|
||||
|
||||
with Hindsight(base_url="http://localhost:8888") as client:
|
||||
client.retain(bank_id="my-bank", content="Hello")
|
||||
results = client.recall(bank_id="my-bank", query="Hello")
|
||||
# Client automatically closed
|
||||
```
|
||||
|
|
@ -238,12 +238,5 @@
|
|||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"changelogSidebar": [
|
||||
{
|
||||
"type": "doc",
|
||||
"id": "changelog/index",
|
||||
"label": "Changelog"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
247
hindsight-docs/versioned_sidebars/version-0.4-sidebars.json
Normal file
247
hindsight-docs/versioned_sidebars/version-0.4-sidebars.json
Normal file
|
|
@ -0,0 +1,247 @@
|
|||
{
|
||||
"developerSidebar": [
|
||||
{
|
||||
"type": "category",
|
||||
"label": "Architecture",
|
||||
"collapsible": false,
|
||||
"items": [
|
||||
{
|
||||
"type": "doc",
|
||||
"id": "developer/index",
|
||||
"label": "Overview"
|
||||
},
|
||||
{
|
||||
"type": "doc",
|
||||
"id": "developer/retain",
|
||||
"label": "Retain"
|
||||
},
|
||||
{
|
||||
"type": "doc",
|
||||
"id": "developer/retrieval",
|
||||
"label": "Recall"
|
||||
},
|
||||
{
|
||||
"type": "doc",
|
||||
"id": "developer/reflect",
|
||||
"label": "Reflect"
|
||||
},
|
||||
{
|
||||
"type": "doc",
|
||||
"id": "developer/observations",
|
||||
"label": "Observations"
|
||||
},
|
||||
{
|
||||
"type": "doc",
|
||||
"id": "developer/multilingual",
|
||||
"label": "Multilingual"
|
||||
},
|
||||
{
|
||||
"type": "doc",
|
||||
"id": "developer/performance",
|
||||
"label": "Performance"
|
||||
},
|
||||
{
|
||||
"type": "doc",
|
||||
"id": "developer/storage",
|
||||
"label": "Storage"
|
||||
},
|
||||
{
|
||||
"type": "doc",
|
||||
"id": "developer/rag-vs-hindsight",
|
||||
"label": "RAG vs Memory"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "category",
|
||||
"label": "API",
|
||||
"collapsible": false,
|
||||
"items": [
|
||||
{
|
||||
"type": "doc",
|
||||
"id": "developer/api/quickstart",
|
||||
"label": "Quick Start"
|
||||
},
|
||||
{
|
||||
"type": "doc",
|
||||
"id": "developer/api/retain",
|
||||
"label": "Retain"
|
||||
},
|
||||
{
|
||||
"type": "doc",
|
||||
"id": "developer/api/recall",
|
||||
"label": "Recall"
|
||||
},
|
||||
{
|
||||
"type": "doc",
|
||||
"id": "developer/api/reflect",
|
||||
"label": "Reflect"
|
||||
},
|
||||
{
|
||||
"type": "doc",
|
||||
"id": "developer/api/mental-models",
|
||||
"label": "Mental Models"
|
||||
},
|
||||
{
|
||||
"type": "doc",
|
||||
"id": "developer/api/memory-banks",
|
||||
"label": "Memory Banks"
|
||||
},
|
||||
{
|
||||
"type": "doc",
|
||||
"id": "developer/api/documents",
|
||||
"label": "Documents"
|
||||
},
|
||||
{
|
||||
"type": "doc",
|
||||
"id": "developer/api/operations",
|
||||
"label": "Operations"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "category",
|
||||
"label": "Hosting",
|
||||
"collapsible": false,
|
||||
"items": [
|
||||
{
|
||||
"type": "doc",
|
||||
"id": "developer/installation",
|
||||
"label": "Installation"
|
||||
},
|
||||
{
|
||||
"type": "doc",
|
||||
"id": "developer/services",
|
||||
"label": "Services"
|
||||
},
|
||||
{
|
||||
"type": "doc",
|
||||
"id": "developer/configuration",
|
||||
"label": "Configuration"
|
||||
},
|
||||
{
|
||||
"type": "doc",
|
||||
"id": "developer/admin-cli",
|
||||
"label": "Admin CLI"
|
||||
},
|
||||
{
|
||||
"type": "doc",
|
||||
"id": "developer/extensions",
|
||||
"label": "Extensions"
|
||||
},
|
||||
{
|
||||
"type": "doc",
|
||||
"id": "developer/models",
|
||||
"label": "Models"
|
||||
},
|
||||
{
|
||||
"type": "doc",
|
||||
"id": "developer/monitoring",
|
||||
"label": "Monitoring"
|
||||
},
|
||||
{
|
||||
"type": "doc",
|
||||
"id": "developer/mcp-server",
|
||||
"label": "MCP Server"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"sdksSidebar": [
|
||||
{
|
||||
"type": "category",
|
||||
"label": "Clients",
|
||||
"collapsible": false,
|
||||
"items": [
|
||||
{
|
||||
"type": "doc",
|
||||
"id": "sdks/python",
|
||||
"label": "Python"
|
||||
},
|
||||
{
|
||||
"type": "doc",
|
||||
"id": "sdks/nodejs",
|
||||
"label": "Node.js"
|
||||
},
|
||||
{
|
||||
"type": "doc",
|
||||
"id": "sdks/cli",
|
||||
"label": "CLI"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "category",
|
||||
"label": "Integrations",
|
||||
"collapsible": false,
|
||||
"items": [
|
||||
{
|
||||
"type": "doc",
|
||||
"id": "sdks/integrations/local-mcp",
|
||||
"label": "Local MCP Server"
|
||||
},
|
||||
{
|
||||
"type": "doc",
|
||||
"id": "sdks/integrations/litellm",
|
||||
"label": "LiteLLM"
|
||||
},
|
||||
{
|
||||
"type": "doc",
|
||||
"id": "sdks/integrations/skills",
|
||||
"label": "Skills"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"cookbookSidebar": [
|
||||
{
|
||||
"type": "doc",
|
||||
"id": "cookbook/index",
|
||||
"label": "Overview"
|
||||
},
|
||||
{
|
||||
"type": "category",
|
||||
"label": "Recipes",
|
||||
"collapsible": false,
|
||||
"items": [
|
||||
{
|
||||
"type": "doc",
|
||||
"id": "cookbook/recipes/quickstart",
|
||||
"label": "Hindsight Quickstart"
|
||||
},
|
||||
{
|
||||
"type": "doc",
|
||||
"id": "cookbook/recipes/per-user-memory",
|
||||
"label": "Per-User Memory"
|
||||
},
|
||||
{
|
||||
"type": "doc",
|
||||
"id": "cookbook/recipes/support-agent-shared-knowledge",
|
||||
"label": "Support Agent with Shared Knowledge"
|
||||
},
|
||||
{
|
||||
"type": "doc",
|
||||
"id": "cookbook/recipes/litellm-memory-demo",
|
||||
"label": "Memory with LiteLLM"
|
||||
},
|
||||
{
|
||||
"type": "doc",
|
||||
"id": "cookbook/recipes/tool-learning-demo",
|
||||
"label": "Routing Tool Learning"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "category",
|
||||
"label": "Applications",
|
||||
"collapsible": false,
|
||||
"items": [
|
||||
{
|
||||
"type": "doc",
|
||||
"id": "cookbook/applications/openai-fitness-coach",
|
||||
"label": "OpenAI Agent + Hindsight Memory Integration"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1 +1,4 @@
|
|||
[]
|
||||
[
|
||||
"0.4",
|
||||
"0.3"
|
||||
]
|
||||
Loading…
Reference in a new issue