From d405b4feed8218b892b6ab0a900285082f347800 Mon Sep 17 00:00:00 2001 From: DK09876 Date: Fri, 19 Dec 2025 12:17:59 -0700 Subject: [PATCH] ci: finalize test for the documentation code (#57) * Fix main-methods.py: entities is a dict, use .items() and .canonical_name * Migrate docs to use CodeSnippet components - Convert quickstart.md, retain.md, recall.md, reflect.md, memory-banks.md to .mdx - Use CodeSnippet to pull code from validated example scripts - Add missing 'name' parameter to create_bank calls - Fix main-methods.py entities iteration (dict not list) - Remove retain-new.mdx demo file * Migrate existing docs to match testing pattern with code snippet and add CLI tests to the CI * Fix doc-id issue + add main-method tests * CLI fixes * Update openAPI json * Fix rust build issues * increase sleep time for Hindsight to process the document * Added a polling sleep instead of fixed * Delete immediately fails, so create the doc a earlier in the test to get the doc ready * Add debug logs * Remove debug logs --- .github/workflows/test.yml | 27 ++ hindsight-cli/src/commands/explore.rs | 2 +- .../docs/developer/api/documents.md | 238 ------------- .../docs/developer/api/documents.mdx | 128 +++++++ .../docs/developer/api/main-methods.md | 315 ------------------ .../docs/developer/api/main-methods.mdx | 141 ++++++++ .../api/{memory-banks.md => memory-banks.mdx} | 63 +--- .../api/{opinions.md => opinions.mdx} | 96 ++---- .../api/{quickstart.md => quickstart.mdx} | 47 +-- .../developer/api/{recall.md => recall.mdx} | 167 ++-------- .../developer/api/{reflect.md => reflect.mdx} | 134 +------- .../docs/developer/api/retain-new.mdx | 71 ---- .../developer/api/{retain.md => retain.mdx} | 124 ++----- hindsight-docs/docs/sdks/cli.md | 8 +- hindsight-docs/examples/api/cli-reference.sh | 19 +- hindsight-docs/examples/api/main-methods.mjs | 133 ++++++++ hindsight-docs/examples/api/main-methods.py | 59 +++- hindsight-docs/examples/api/memory-banks.mjs | 1 + hindsight-docs/examples/api/memory-banks.py | 1 + hindsight-docs/examples/api/opinions.mjs | 99 ++++++ hindsight-docs/examples/api/opinions.py | 2 + hindsight-docs/examples/api/reflect.mjs | 1 + hindsight-docs/examples/api/reflect.py | 1 + hindsight-docs/openapi.json | 26 +- hindsight-docs/static/openapi.json | 26 +- openapi.json | 26 +- 26 files changed, 768 insertions(+), 1187 deletions(-) delete mode 100644 hindsight-docs/docs/developer/api/documents.md create mode 100644 hindsight-docs/docs/developer/api/documents.mdx delete mode 100644 hindsight-docs/docs/developer/api/main-methods.md create mode 100644 hindsight-docs/docs/developer/api/main-methods.mdx rename hindsight-docs/docs/developer/api/{memory-banks.md => memory-banks.mdx} (64%) rename hindsight-docs/docs/developer/api/{opinions.md => opinions.mdx} (58%) rename hindsight-docs/docs/developer/api/{quickstart.md => quickstart.mdx} (66%) rename hindsight-docs/docs/developer/api/{recall.md => recall.mdx} (52%) rename hindsight-docs/docs/developer/api/{reflect.md => reflect.mdx} (57%) delete mode 100644 hindsight-docs/docs/developer/api/retain-new.mdx rename hindsight-docs/docs/developer/api/{retain.md => retain.mdx} (54%) create mode 100644 hindsight-docs/examples/api/main-methods.mjs create mode 100644 hindsight-docs/examples/api/opinions.mjs diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a48c7f3a..545f377c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -173,6 +173,13 @@ jobs: working-directory: hindsight-cli run: cargo build --release + - name: Upload CLI artifact + uses: actions/upload-artifact@v4 + with: + name: hindsight-cli + path: hindsight-cli/target/release/hindsight + retention-days: 1 + lint-helm-chart: runs-on: ubuntu-latest @@ -558,6 +565,7 @@ jobs: test-doc-examples: runs-on: ubuntu-latest + needs: build-rust-cli env: HINDSIGHT_API_LLM_PROVIDER: groq HINDSIGHT_API_LLM_API_KEY: ${{ secrets.GROQ_API_KEY }} @@ -569,6 +577,15 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Download CLI artifact + uses: actions/download-artifact@v4 + with: + name: hindsight-cli + path: /usr/local/bin + + - name: Make CLI executable + run: chmod +x /usr/local/bin/hindsight + - name: Install uv uses: astral-sh/setup-uv@v5 with: @@ -642,6 +659,16 @@ jobs: node "$f" done + - name: Configure CLI + run: hindsight configure --api-url http://localhost:8888 + + - name: Run CLI doc examples + run: | + for f in hindsight-docs/examples/api/*.sh; do + echo "Running $f..." + bash "$f" + done + - name: Show API server logs if: always() run: | diff --git a/hindsight-cli/src/commands/explore.rs b/hindsight-cli/src/commands/explore.rs index e477d599..1d2d42ce 100644 --- a/hindsight-cli/src/commands/explore.rs +++ b/hindsight-cli/src/commands/explore.rs @@ -944,7 +944,7 @@ fn render_banks(f: &mut Frame, app: &mut App, area: Rect) { .banks .iter() .map(|bank| { - let name = if bank.name.is_empty() { "Unnamed" } else { &bank.name }; + let name = bank.name.as_deref().filter(|s| !s.is_empty()).unwrap_or("Unnamed"); let content = format!("{} - {}", bank.bank_id, name); ListItem::new(content).style(Style::default().fg(Color::White)) }) diff --git a/hindsight-docs/docs/developer/api/documents.md b/hindsight-docs/docs/developer/api/documents.md deleted file mode 100644 index 3f52cc80..00000000 --- a/hindsight-docs/docs/developer/api/documents.md +++ /dev/null @@ -1,238 +0,0 @@ ---- -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'; - -:::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: - - - - -```python -from hindsight_client import Hindsight - -client = Hindsight(base_url="http://localhost:8888") - -# Retain with document ID -client.retain( - bank_id="my-bank", - content="Alice presented the Q4 roadmap...", - document_id="meeting-2024-03-15" -) - -# Batch retain for a document -client.retain_batch( - bank_id="my-bank", - items=[ - {"content": "Item 1: Product launch delayed to Q2"}, - {"content": "Item 2: New hiring targets announced"}, - {"content": "Item 3: Budget approved for ML team"} - ], - document_id="meeting-2024-03-15" -) - -# From file -with open("notes.txt") as f: - client.retain( - bank_id="my-bank", - content=f.read(), - document_id="notes-2024-03-15" - ) -``` - - - - -```typescript -import { HindsightClient } from '@vectorize-io/hindsight-client'; - -const client = new HindsightClient({ baseUrl: 'http://localhost:8888' }); - -// Retain with document ID -await client.retain('my-bank', 'Alice presented the Q4 roadmap...', { - document_id: 'meeting-2024-03-15' -}); - -// Batch retain -await client.retainBatch('my-bank', [ - { content: 'Item 1: Product launch delayed to Q2' }, - { content: 'Item 2: New hiring targets announced' }, - { content: 'Item 3: Budget approved for ML team' } -], { documentId: 'meeting-2024-03-15' }); -``` - - - - -```bash -# Retain file with document ID -hindsight retain my-bank --file notes.txt --document-id notes-2024-03-15 - -# Batch retain directory -hindsight retain my-bank --files docs/*.md --document-id project-docs -``` - - - - -## Update Documents - -Re-retaining with the same document_id **replaces** the old content: - - - - -```python -# Original -client.retain( - bank_id="my-bank", - content="Project deadline: March 31", - document_id="project-plan" -) - -# Update (deletes old facts, creates new ones) -client.retain( - bank_id="my-bank", - content="Project deadline: April 15 (extended)", - document_id="project-plan" -) -``` - - - - -```typescript -// Original -await client.retain('my-bank', 'Project deadline: March 31', { - document_id: 'project-plan' -}); - -// Update -await client.retain('my-bank', 'Project deadline: April 15 (extended)', { - document_id: 'project-plan' -}); -``` - - - - -```bash -# Original -hindsight retain my-bank "Project deadline: March 31" --document-id project-plan - -# Update -hindsight retain my-bank "Project deadline: April 15 (extended)" --document-id project-plan -``` - - - - -## 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. - - - - -```python -from hindsight_client_api import ApiClient, Configuration -from hindsight_client_api.api import DefaultApi - -config = Configuration(host="http://localhost:8888") -api_client = ApiClient(config) -api = DefaultApi(api_client) - -# Get document to expand context from recall results -doc = api.get_document( - bank_id="my-bank", - document_id="meeting-2024-03-15" -) - -print(f"Document: {doc.id}") -print(f"Original text: {doc.original_text}") -print(f"Memory count: {doc.memory_unit_count}") -print(f"Created: {doc.created_at}") -``` - - - - -```typescript -import { sdk, createClient, createConfig } from '@vectorize-io/hindsight-client'; - -const apiClient = createClient(createConfig({ baseUrl: 'http://localhost:8888' })); - -// Get document to expand context from recall results -const { data: doc } = await sdk.getDocument({ - client: apiClient, - path: { bank_id: 'my-bank', document_id: 'meeting-2024-03-15' } -}); - -console.log(`Document: ${doc.id}`); -console.log(`Original text: ${doc.original_text}`); -console.log(`Memory count: ${doc.memory_unit_count}`); -console.log(`Created: ${doc.created_at}`); -``` - - - - -```bash -hindsight documents get my-bank meeting-2024-03-15 -``` - - - - -## 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 - -- [**Entities**](./entities) — Track people, places, and concepts -- [**Operations**](./operations) — Monitor background tasks -- [**Memory Banks**](./memory-banks) — Configure bank settings diff --git a/hindsight-docs/docs/developer/api/documents.mdx b/hindsight-docs/docs/developer/api/documents.mdx new file mode 100644 index 00000000..bf5bc90c --- /dev/null +++ b/hindsight-docs/docs/developer/api/documents.mdx @@ -0,0 +1,128 @@ +--- +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: + + + + + + + + + + +```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/ +``` + + + + +## Update Documents + +Re-retaining with the same document_id **replaces** the old content: + + + + + + + + + + +```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 +``` + + + + +## 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. + + + + + + + + + + +```bash +hindsight document get my-bank meeting-2024-03-15 +``` + + + + +## 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 + +- [**Entities**](./entities) — Track people, places, and concepts +- [**Operations**](./operations) — Monitor background tasks +- [**Memory Banks**](./memory-banks) — Configure bank settings diff --git a/hindsight-docs/docs/developer/api/main-methods.md b/hindsight-docs/docs/developer/api/main-methods.md deleted file mode 100644 index a1fe19b4..00000000 --- a/hindsight-docs/docs/developer/api/main-methods.md +++ /dev/null @@ -1,315 +0,0 @@ ---- -sidebar_position: 2 ---- - -# Main Methods - -Hindsight provides three core operations: **retain**, **recall**, and **reflect**. - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -:::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. - - - - -```python -# Store a single fact -client.retain( - bank_id="my-bank", - content="Alice joined Google in March 2024 as a Senior ML Engineer" -) - -# Store a conversation -conversation = """ -User: What did you work on today? -Assistant: I reviewed the new ML pipeline architecture. -User: How did it look? -Assistant: Promising, but needs better error handling. -""" - -client.retain( - bank_id="my-bank", - content=conversation, - context="Daily standup conversation" -) - -# Batch retain multiple items -client.retain_batch( - bank_id="my-bank", - contents=[ - {"content": "Bob prefers Python for data science"}, - {"content": "Alice recommends using pytest for testing"}, - {"content": "The team uses GitHub for code reviews"} - ] -) -``` - - - - -```javascript -// Store a single fact -await client.retain({ - bankId: 'my-bank', - content: 'Alice joined Google in March 2024 as a Senior ML Engineer' -}); - -// Store a conversation -await client.retain({ - bankId: 'my-bank', - content: ` -User: What did you work on today? -Assistant: I reviewed the new ML pipeline architecture. -User: How did it look? -Assistant: Promising, but needs better error handling. - `, - context: 'Daily standup conversation' -}); - -// Batch retain -await client.retainBatch({ - bankId: 'my-bank', - contents: [ - { content: 'Bob prefers Python for data science' }, - { content: 'Alice recommends using pytest for testing' }, - { content: 'The team uses GitHub for code reviews' } - ] -}); -``` - - - - -```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 -``` - - - - -**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. - - - - -```python -# Basic search -results = client.recall( - bank_id="my-bank", - query="What does Alice do at Google?" -) - -for result in results: - print(f"[{result['weight']:.2f}] {result['text']}") - -# Search with options -results = client.recall( - bank_id="my-bank", - query="What happened last spring?", - budget="high", # More thorough graph traversal - max_tokens=8192, # Return more context - fact_type="world" # Only world facts -) - -# Include entity information -results = client.recall( - bank_id="my-bank", - query="Tell me about Alice", - include_entities=True, - max_entity_tokens=500 -) - -# Check entity details -for entity in results["entities"]: - print(f"Entity: {entity['name']}") - print(f"Observations: {entity['observations']}") -``` - - - - -```javascript -// Basic search -const results = await client.recall({ - bankId: 'my-bank', - query: 'What does Alice do at Google?' -}); - -results.forEach(r => { - console.log(`[${r.weight.toFixed(2)}] ${r.text}`); -}); - -// Search with options -const detailedResults = await client.recall({ - bankId: 'my-bank', - query: 'What happened last spring?', - budget: 'high', - maxTokens: 8192, - factType: 'world' -}); - -// Include entity information -const withEntities = await client.recall({ - bankId: 'my-bank', - query: 'Tell me about Alice', - includeEntities: true, - maxEntityTokens: 500 -}); -``` - - - - -```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 -``` - - - - -**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 that form opinions based on evidence. - - - - -```python -# Basic reflect -response = client.reflect( - bank_id="my-bank", - query="Should we adopt TypeScript for our backend?" -) - -print(response["text"]) -print("\nBased on:", len(response["based_on"]["world"]), "facts") -print("New opinions:", len(response["new_opinions"])) - -# Reflect with options -response = client.reflect( - bank_id="my-bank", - query="What are Alice's strengths for the team lead role?", - budget="high", # More thorough reasoning - include_entities=True -) - -# Access formed opinions -for opinion in response["new_opinions"]: - print(f"Opinion: {opinion['text']}") - print(f"Confidence: {opinion['confidence']}") - -# See which facts influenced the response -for fact in response["based_on"]["world"]: - print(f"[{fact['weight']:.2f}] {fact['text']}") -``` - - - - -```javascript -// Basic reflect -const response = await client.reflect({ - bankId: 'my-bank', - query: 'Should we adopt TypeScript for our backend?' -}); - -console.log(response.text); -console.log(`\nBased on: ${response.basedOn.world.length} facts`); -console.log(`New opinions: ${response.newOpinions.length}`); - -// Reflect with options -const detailed = await client.reflect({ - bankId: 'my-bank', - query: "What are Alice's strengths for the team lead role?", - budget: 'high', - includeEntities: true -}); - -// Access formed opinions -detailed.newOpinions.forEach(op => { - console.log(`Opinion: ${op.text}`); - console.log(`Confidence: ${op.confidence}`); -}); -``` - - - - -```bash -# Basic reflect -hindsight reflect my-bank "Should we adopt TypeScript for our backend?" - -# Verbose output (shows sources and opinions) -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 -``` - - - - -**What happens:** Memories are recalled, bank disposition is loaded, LLM reasons through evidence, new opinions are formed and stored. - -**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 | Reasoned response + opinions | -| **Uses LLM** | Yes (extraction) | No | Yes (generation) | -| **Forms opinions** | No | No | 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 and opinions -- [**Memory Banks**](./memory-banks) — Managing memory bank disposition diff --git a/hindsight-docs/docs/developer/api/main-methods.mdx b/hindsight-docs/docs/developer/api/main-methods.mdx new file mode 100644 index 00000000..9b2fac62 --- /dev/null +++ b/hindsight-docs/docs/developer/api/main-methods.mdx @@ -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. + + + + + + + + + + +```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 +``` + + + + +**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. + + + + + + + + + + +```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 +``` + + + + +**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 that form opinions based on evidence. + + + + + + + + + + +```bash +# Basic reflect +hindsight reflect my-bank "Should we adopt TypeScript for our backend?" + +# Verbose output (shows sources and opinions) +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 +``` + + + + +**What happens:** Memories are recalled, bank disposition is loaded, LLM reasons through evidence, new opinions are formed and stored. + +**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 | Reasoned response + opinions | +| **Uses LLM** | Yes (extraction) | No | Yes (generation) | +| **Forms opinions** | No | No | 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 and opinions +- [**Memory Banks**](./memory-banks) — Managing memory bank disposition diff --git a/hindsight-docs/docs/developer/api/memory-banks.md b/hindsight-docs/docs/developer/api/memory-banks.mdx similarity index 64% rename from hindsight-docs/docs/developer/api/memory-banks.md rename to hindsight-docs/docs/developer/api/memory-banks.mdx index ff805aa9..081de36f 100644 --- a/hindsight-docs/docs/developer/api/memory-banks.md +++ b/hindsight-docs/docs/developer/api/memory-banks.mdx @@ -8,6 +8,11 @@ Memory banks are isolated containers that store all memory-related data for a sp 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'; ## What is a Memory Bank? @@ -30,43 +35,10 @@ Make sure you've completed the [Quick Start](./quickstart) to install the client - -```python -from hindsight_client import Hindsight - -client = Hindsight(base_url="http://localhost:8888") - -client.create_bank( - bank_id="my-bank", - name="Research Assistant", - background="I am a research assistant specializing in machine learning", - disposition={ - "skepticism": 4, - "literalism": 3, - "empathy": 3 - } -) -``` - + - -```typescript -import { HindsightClient } from '@vectorize-io/hindsight-client'; - -const client = new HindsightClient({ baseUrl: 'http://localhost:8888' }); - -await client.createBank('my-bank', { - name: 'Research Assistant', - background: 'I am a research assistant specializing in machine learning', - disposition: { - skepticism: 4, - literalism: 3, - empathy: 3 - } -}); -``` - + @@ -98,27 +70,10 @@ The background is a first-person narrative providing context for opinion formati - -```python -client.create_bank( - bank_id="financial-advisor", - background="""I am a conservative financial advisor with 20 years of experience. - I prioritize capital preservation over aggressive growth. - I have seen multiple market crashes and believe in diversification.""" -) -``` - + - -```typescript -await client.createBank('financial-advisor', { - background: `I am a conservative financial advisor with 20 years of experience. - I prioritize capital preservation over aggressive growth. - I have seen multiple market crashes and believe in diversification.` -}); -``` - + diff --git a/hindsight-docs/docs/developer/api/opinions.md b/hindsight-docs/docs/developer/api/opinions.mdx similarity index 58% rename from hindsight-docs/docs/developer/api/opinions.md rename to hindsight-docs/docs/developer/api/opinions.mdx index 0bfc2248..9f33125c 100644 --- a/hindsight-docs/docs/developer/api/opinions.md +++ b/hindsight-docs/docs/developer/api/opinions.mdx @@ -8,6 +8,11 @@ How memory banks form, store, and evolve beliefs. import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; +import CodeSnippet from '@site/src/components/CodeSnippet'; + +{/* Import raw source files */} +import opinionsPy from '!!raw-loader!@site/examples/api/opinions.py'; +import opinionsMjs from '!!raw-loader!@site/examples/api/opinions.mjs'; :::tip Prerequisites Make sure you've completed the [Quick Start](./quickstart) to install the client and start the server. @@ -41,20 +46,10 @@ graph LR - -```python -# Ask a question that might form an opinion -answer = client.reflect( - bank_id="my-bank", - query="What do you think about functional programming?" -) - -# Check if new opinions were formed -for opinion in answer.get("new_opinions", []): - print(f"New opinion: {opinion['text']}") - print(f"Confidence: {opinion['confidence']}") -``` - + + + + @@ -62,19 +57,10 @@ for opinion in answer.get("new_opinions", []): - -```python -# Search only opinions -opinions = client.recall( - bank_id="my-bank", - query="programming languages", - types=["opinion"] -) - -for op in opinions: - print(f"{op['text']} (confidence: {op['confidence_score']:.2f})") -``` - + + + + @@ -113,39 +99,10 @@ Different dispositions form different opinions from the same facts: - -```python -# Create two memory banks with different dispositions -client.create_bank( - bank_id="open-minded", - disposition={"skepticism": 2, "literalism": 2, "empathy": 4} -) - -client.create_bank( - bank_id="conservative", - disposition={"skepticism": 5, "literalism": 5, "empathy": 2} -) - -# Store the same facts to both -facts = [ - "Rust has better memory safety than C++", - "C++ has a larger ecosystem and more libraries", - "Rust compile times are longer than C++" -] -for fact in facts: - client.retain(bank_id="open-minded", content=fact) - client.retain(bank_id="conservative", content=fact) - -# Ask both the same question -q = "Should we rewrite our C++ codebase in Rust?" - -answer1 = client.reflect(bank_id="open-minded", query=q) -# Likely: "Yes, Rust's safety benefits outweigh migration costs" - -answer2 = client.reflect(bank_id="conservative", query=q) -# Likely: "No, C++'s ecosystem and our team's expertise make it the safer choice" -``` - + + + + @@ -153,17 +110,14 @@ answer2 = client.reflect(bank_id="conservative", query=q) When `reflect` uses opinions, they appear in `based_on`: -```python -answer = client.reflect(bank_id="my-bank", query="What language should I learn?") - -print("World facts used:") -for f in answer.based_on.get("world", []): - print(f" {f['text']}") - -print("\nOpinions used:") -for o in answer.based_on.get("opinion", []): - print(f" {o['text']} (confidence: {o['confidence_score']})") -``` + + + + + + + + ## Confidence Thresholds diff --git a/hindsight-docs/docs/developer/api/quickstart.md b/hindsight-docs/docs/developer/api/quickstart.mdx similarity index 66% rename from hindsight-docs/docs/developer/api/quickstart.md rename to hindsight-docs/docs/developer/api/quickstart.mdx index 2d26668c..d167a931 100644 --- a/hindsight-docs/docs/developer/api/quickstart.md +++ b/hindsight-docs/docs/developer/api/quickstart.mdx @@ -8,6 +8,12 @@ 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 @@ -59,20 +65,7 @@ See [LLM Providers](/developer/models#llm) for more details. pip install hindsight-client ``` -```python -from hindsight_client import Hindsight - -client = Hindsight(base_url="http://localhost:8888") - -# Retain: Store information -client.retain(bank_id="my-bank", content="Alice works at Google as a software engineer") - -# Recall: Search memories -client.recall(bank_id="my-bank", query="What does Alice do?") - -# Reflect: Generate disposition-aware response -client.reflect(bank_id="my-bank", query="Tell me about Alice") -``` + @@ -81,20 +74,7 @@ client.reflect(bank_id="my-bank", query="Tell me about Alice") npm install @vectorize-io/hindsight-client ``` -```javascript -const { HindsightClient } = require('@vectorize-io/hindsight-client'); - -const client = new HindsightClient({ baseUrl: 'http://localhost:8888' }); - -// Retain: Store information -await client.retain('my-bank', 'Alice works at Google as a software engineer'); - -// Recall: Search memories -await client.recall('my-bank', 'What does Alice do?'); - -// Reflect: Generate response -await client.reflect('my-bank', 'Tell me about Alice'); -``` + @@ -103,16 +83,7 @@ await client.reflect('my-bank', 'Tell me about Alice'); curl -fsSL https://hindsight.vectorize.io/get-cli | bash ``` -```bash -# Retain: Store information -hindsight memory retain my-bank "Alice works at Google as a software engineer" - -# Recall: Search memories -hindsight memory recall my-bank "What does Alice do?" - -# Reflect: Generate response -hindsight memory reflect my-bank "Tell me about Alice" -``` + diff --git a/hindsight-docs/docs/developer/api/recall.md b/hindsight-docs/docs/developer/api/recall.mdx similarity index 52% rename from hindsight-docs/docs/developer/api/recall.md rename to hindsight-docs/docs/developer/api/recall.mdx index a060853c..aa8b3d6c 100644 --- a/hindsight-docs/docs/developer/api/recall.md +++ b/hindsight-docs/docs/developer/api/recall.mdx @@ -8,6 +8,12 @@ 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. @@ -21,38 +27,13 @@ Make sure you've completed the [Quick Start](./quickstart) to install the client - -```python -from hindsight_client import Hindsight - -client = Hindsight(base_url="http://localhost:8888") - -response = client.recall(bank_id="my-bank", query="What does Alice do?") -for r in response.results: - print(f"{r.text} (score: {r.weight:.2f})") -``` - + - -```typescript -import { HindsightClient } from '@vectorize-io/hindsight-client'; - -const client = new HindsightClient({ baseUrl: 'http://localhost:8888' }); - -const response = await client.recall('my-bank', 'What does Alice do?'); -for (const r of response.results) { - console.log(`${r.text} (score: ${r.weight})`); -} -``` - + - -```bash -hindsight recall my-bank "What does Alice do?" -``` - + @@ -70,46 +51,10 @@ hindsight recall my-bank "What does Alice do?" - -```python -response = client.recall( - bank_id="my-bank", - query="What does Alice do?", - types=["world", "experience"], - budget="high", - max_tokens=8000, - trace=True, - include_entities=True, - max_entity_tokens=500 -) - -# Access results -for r in response.results: - print(f"{r.text} (score: {r.weight:.2f})") - -# Access entity observations (if include_entities=True) -if response.entities: - for entity in response.entities: - print(f"Entity: {entity.name}") -``` - + - -```typescript -const response = await client.recall('my-bank', 'What does Alice do?', { - types: ['world', 'experience'], - budget: 'high', - maxTokens: 8000, - trace: true -}); - -// Access results -for (const r of response.results) { - console.log(`${r.text} (score: ${r.weight})`); -} -``` - + @@ -119,45 +64,12 @@ Recall specific memory types: - -```python -# Only world facts (objective information) -world_facts = client.recall( - bank_id="my-bank", - query="Where does Alice work?", - types=["world"] -) - -# Only experience (conversations and events) -experience = client.recall( - bank_id="my-bank", - query="What have I recommended?", - types=["experience"] -) - -# Only opinions (formed beliefs) -opinions = client.recall( - bank_id="my-bank", - query="What do I think about Python?", - types=["opinion"] -) - -# World facts and experience (exclude opinions) -facts = client.recall( - bank_id="my-bank", - query="What happened?", - types=["world", "experience"] -) -``` - + + + - -```bash -hindsight recall my-bank "Python" --fact-type opinion -hindsight recall my-bank "Alice" --fact-type world,experience -``` - + @@ -174,13 +86,11 @@ Hindsight is built for AI agents, not humans. Traditional retrieval systems retu The `max_tokens` parameter lets you control how much of your agent's context budget to spend on memories: -```python -# Fill up to 4K tokens of context with relevant memories -results = client.recall(bank_id="my-bank", query="What do I know about Alice?", max_tokens=4096) - -# Smaller budget for quick lookups -results = client.recall(bank_id="my-bank", query="Alice's email", max_tokens=500) -``` + + + + + 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. @@ -193,18 +103,11 @@ Beyond the core memory results, you can optionally retrieve additional context | **Chunks** | `include_chunks`, `max_chunk_tokens` | Raw text chunks that generated the memories | | **Entity Observations** | `include_entities`, `max_entity_tokens` | Related observations about entities mentioned in results | -```python -response = client.recall( - bank_id="my-bank", - query="What does Alice do?", - max_tokens=4096, # Budget for memories - include_entities=True, - max_entity_tokens=1000 # Budget for entity observations -) - -# Access the additional context -entities = response.entities or [] -``` + + + + + This gives your agent richer context while maintaining precise control over total token consumption. @@ -218,25 +121,9 @@ The `budget` parameter controls graph traversal depth: - -```python -# Quick lookup -results = client.recall(bank_id="my-bank", query="Alice's email", budget="low") - -# Deep exploration -results = client.recall(bank_id="my-bank", query="How are Alice and Bob connected?", budget="high") -``` - + - -```typescript -// Quick lookup -const results = await client.recall('my-bank', "Alice's email", { budget: 'low' }); - -// Deep exploration -const deep = await client.recall('my-bank', 'How are Alice and Bob connected?', { budget: 'high' }); -``` - + diff --git a/hindsight-docs/docs/developer/api/reflect.md b/hindsight-docs/docs/developer/api/reflect.mdx similarity index 57% rename from hindsight-docs/docs/developer/api/reflect.md rename to hindsight-docs/docs/developer/api/reflect.mdx index 7ee3f572..c5f771fb 100644 --- a/hindsight-docs/docs/developer/api/reflect.md +++ b/hindsight-docs/docs/developer/api/reflect.mdx @@ -16,6 +16,12 @@ The response includes the generated answer along with the facts that were used, 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 and opinion formation in the [Reflect Architecture](/developer/reflect) guide. @@ -29,33 +35,13 @@ Make sure you've completed the [Quick Start](./quickstart) to install the client - -```python -from hindsight_client import Hindsight - -client = Hindsight(base_url="http://localhost:8888") - -client.reflect(bank_id="my-bank", query="What should I know about Alice?") -``` - + - -```typescript -import { HindsightClient } from '@vectorize-io/hindsight-client'; - -const client = new HindsightClient({ baseUrl: 'http://localhost:8888' }); - -await client.reflect('my-bank', 'What should I know about Alice?'); -``` - + - -```bash -hindsight memory think my-bank "What should I know about Alice?" -``` - + @@ -69,26 +55,10 @@ hindsight memory think my-bank "What should I know about Alice?" - -```python -response = client.reflect( - bank_id="my-bank", - query="What do you think about remote work?", - budget="mid", - context="We're considering a hybrid work policy" -) -``` - + - -```typescript -const response = await client.reflect('my-bank', 'What do you think about remote work?', { - budget: 'mid', - context: "We're considering a hybrid work policy" -}); -``` - + @@ -103,26 +73,10 @@ The `context` parameter steers how the reflection is performed without impacting - -```python -# Context is passed to the LLM to help it understand the situation -response = client.reflect( - bank_id="my-bank", - query="What do you think about the proposal?", - context="We're in a budget review meeting discussing Q4 spending" -) -``` - + - -```typescript -// Context helps the LLM understand the current situation -const response = await client.reflect('my-bank', 'What do you think about the proposal?', { - context: "We're in a budget review meeting discussing Q4 spending" -}); -``` - + @@ -149,45 +103,10 @@ The bank's disposition affects reflect responses: - -```python -# Create a bank with specific disposition -client.create_bank( - bank_id="cautious-advisor", - background="I am a risk-aware financial advisor", - disposition={ - "skepticism": 5, # Very skeptical of claims - "literalism": 4, # Focuses on exact requirements - "empathy": 2 # Prioritizes facts over feelings - } -) - -# Reflect responses will reflect this disposition -response = client.reflect( - bank_id="cautious-advisor", - query="Should I invest in crypto?" -) -# Response will likely emphasize risks and caution -``` - + - -```typescript -// Create a bank with specific disposition -await client.createBank('cautious-advisor', { - background: 'I am a risk-aware financial advisor', - disposition: { - skepticism: 5, - literalism: 4, - empathy: 2 - } -}); - -// Reflect responses will reflect this disposition -const response = await client.reflect('cautious-advisor', 'Should I invest in crypto?'); -``` - + @@ -197,29 +116,10 @@ The `based_on` field shows which memories informed the response: - -```python -response = client.reflect(bank_id="my-bank", query="Tell me about Alice") - -print("Response:", response.text) -print("\nBased on:") -for fact in response.based_on or []: - print(f" - [{fact.type}] {fact.text}") -``` - + - -```typescript -const response = await client.reflect('my-bank', 'Tell me about Alice'); - -console.log('Response:', response.text); -console.log('\nBased on:'); -for (const fact of response.based_on || []) { - console.log(` - [${fact.type}] ${fact.text}`); -} -``` - + diff --git a/hindsight-docs/docs/developer/api/retain-new.mdx b/hindsight-docs/docs/developer/api/retain-new.mdx deleted file mode 100644 index 8d0b94c8..00000000 --- a/hindsight-docs/docs/developer/api/retain-new.mdx +++ /dev/null @@ -1,71 +0,0 @@ ---- -sidebar_position: 2 ---- - -# Ingest Data (New Format) - -This is a demo of the new code snippet approach. Code examples are pulled from executable script files. - -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'; - -:::tip How This Works -The code examples below are extracted from actual runnable script files in `examples/api/`. -When CI runs these scripts, it validates the documentation is correct. -::: - -## Store a Single Memory - - - - - - - - - - - - - -## Store with Context - - - - - - - - - - - - - -## Batch Ingestion - - - - - - - - - - -## Async Ingestion - - - - - - - - - diff --git a/hindsight-docs/docs/developer/api/retain.md b/hindsight-docs/docs/developer/api/retain.mdx similarity index 54% rename from hindsight-docs/docs/developer/api/retain.md rename to hindsight-docs/docs/developer/api/retain.mdx index c2dd7d4c..f3cf9bad 100644 --- a/hindsight-docs/docs/developer/api/retain.md +++ b/hindsight-docs/docs/developer/api/retain.mdx @@ -10,6 +10,12 @@ When you **retain** content, Hindsight doesn't just store the raw text—it inte 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. @@ -23,36 +29,13 @@ Make sure you've completed the [Quick Start](./quickstart) to install the client - -```python -from hindsight_client import Hindsight - -client = Hindsight(base_url="http://localhost:8888") - -client.retain( - bank_id="my-bank", - content="Alice works at Google as a software engineer" -) -``` - + - -```typescript -import { HindsightClient } from '@vectorize-io/hindsight-client'; - -const client = new HindsightClient({ baseUrl: 'http://localhost:8888' }); - -await client.retain('my-bank', 'Alice works at Google as a software engineer'); -``` - + - -```bash -hindsight memory put my-bank "Alice works at Google as a software engineer" -``` - + @@ -71,35 +54,13 @@ Always provide context and event dates for optimal memory extraction: - -```python -client.retain( - bank_id="my-bank", - content="Alice got promoted to senior engineer", - context="career update", - timestamp="2024-03-15T10:00:00Z" -) -``` - + - -```typescript -await client.retain('my-bank', 'Alice got promoted to senior engineer', { - context: 'career update', - timestamp: '2024-03-15T10:00:00Z' -}); -``` - + - -```bash -hindsight memory put my-bank "Alice got promoted" \ - --context "career update" \ - --event-date "2024-03-15" -``` - + @@ -111,30 +72,10 @@ Store multiple items in a single request. **Batch ingestion is the recommended a - -```python -client.retain_batch( - bank_id="my-bank", - items=[ - {"content": "Alice works at Google", "context": "career"}, - {"content": "Bob is a data scientist at Meta", "context": "career"}, - {"content": "Alice and Bob are friends", "context": "relationship"} - ], - document_id="conversation_001" -) -``` - + - -```typescript -await client.retainBatch('my-bank', [ - { content: 'Alice works at Google', context: 'career' }, - { content: 'Bob is a data scientist at Meta', context: 'career' }, - { content: 'Alice and Bob are friends', context: 'relationship' } -], { documentId: 'conversation_001' }); -``` - + @@ -147,13 +88,10 @@ The `document_id` groups related memories for later management. ```bash # Single file -hindsight memory put-files my-bank document.txt +hindsight memory retain-files my-bank document.txt -# Multiple files -hindsight memory put-files my-bank doc1.txt doc2.md notes.txt - -# With document ID -hindsight memory put-files my-bank report.pdf --document-id "q4-report" +# Directory (recursive by default) +hindsight memory retain-files my-bank ./documents/ ``` @@ -166,33 +104,9 @@ For large batches, use async ingestion to avoid blocking: - -```python -# Start async ingestion (returns immediately) -result = client.retain_batch( - bank_id="my-bank", - items=[...large batch...], - document_id="large-doc", - retain_async=True -) - -# Check if it was processed asynchronously -print(result.var_async) # True -``` - + - -```typescript -// Start async ingestion (returns immediately) -const result = await client.retainBatch('my-bank', largeItems, { - documentId: 'large-doc', - async: true -}); - -console.log(result.async); // true -``` - + - diff --git a/hindsight-docs/docs/sdks/cli.md b/hindsight-docs/docs/sdks/cli.md index 25469d25..325ffc1d 100644 --- a/hindsight-docs/docs/sdks/cli.md +++ b/hindsight-docs/docs/sdks/cli.md @@ -102,10 +102,10 @@ hindsight memory reflect "Summarize my week" --budget high hindsight bank list ``` -### View Profile +### View Disposition ```bash -hindsight bank profile +hindsight bank disposition ``` ### View Statistics @@ -241,6 +241,6 @@ hindsight memory recall demo "Who works with Alice?" # Generate a response hindsight memory reflect demo "What do you know about the team?" -# Check bank profile -hindsight bank profile demo +# Check bank disposition +hindsight bank disposition demo ``` diff --git a/hindsight-docs/examples/api/cli-reference.sh b/hindsight-docs/examples/api/cli-reference.sh index 36d7b4f2..7126ef27 100755 --- a/hindsight-docs/examples/api/cli-reference.sh +++ b/hindsight-docs/examples/api/cli-reference.sh @@ -15,12 +15,14 @@ DOC_ID="test-document-001" hindsight configure --api-url "$HINDSIGHT_URL" # Create test data with a known document ID -hindsight memory retain "$BANK_ID" "Alice works at Google as a software engineer" --document-id "$DOC_ID" -hindsight memory retain "$BANK_ID" "Bob is a data scientist who collaborates with Alice" --document-id "$DOC_ID" +hindsight memory retain "$BANK_ID" "Alice works at Google as a software engineer" --doc-id "$DOC_ID" +hindsight memory retain "$BANK_ID" "Bob is a data scientist who collaborates with Alice" --doc-id "$DOC_ID" hindsight memory retain "$BANK_ID" "Alice and Bob work on machine learning projects" +# Create document for delete test early so it has time to index +hindsight memory retain "$BANK_ID" "Carol is a project manager who coordinates the engineering team" --doc-id "temp-doc-to-delete" -# Wait a moment for processing -sleep 2 +# Wait for memories to be indexed (LLM processing takes time) +sleep 5 # ============================================================================= # Configuration (cli.md - Configuration section) @@ -96,9 +98,9 @@ hindsight bank list # [/docs:cli-bank-list] -# [docs:cli-bank-profile] -hindsight bank profile $BANK_ID -# [/docs:cli-bank-profile] +# [docs:cli-bank-disposition] +hindsight bank disposition $BANK_ID +# [/docs:cli-bank-disposition] # [docs:cli-bank-stats] @@ -136,9 +138,6 @@ hindsight document get $BANK_ID $DOC_ID # [docs:cli-document-delete] -# Create a temp document to delete -hindsight memory retain $BANK_ID "Temporary content" --document-id "temp-doc-to-delete" -sleep 1 hindsight document delete $BANK_ID temp-doc-to-delete # [/docs:cli-document-delete] diff --git a/hindsight-docs/examples/api/main-methods.mjs b/hindsight-docs/examples/api/main-methods.mjs new file mode 100644 index 00000000..3eb1bdf4 --- /dev/null +++ b/hindsight-docs/examples/api/main-methods.mjs @@ -0,0 +1,133 @@ +#!/usr/bin/env node +/** + * Main Methods overview examples for Hindsight (Node.js) + * Run: node examples/api/main-methods.mjs + */ +import { HindsightClient } from '@vectorize-io/hindsight-client'; + +const HINDSIGHT_URL = process.env.HINDSIGHT_API_URL || 'http://localhost:8888'; + +// ============================================================================= +// Setup (not shown in docs) +// ============================================================================= +const client = new HindsightClient({ baseUrl: HINDSIGHT_URL }); + +// ============================================================================= +// Doc Examples - Retain Section +// ============================================================================= + +// [docs:main-retain] +// Store a single fact +await client.retain('my-bank', 'Alice joined Google in March 2024 as a Senior ML Engineer'); + +// Store a conversation +const conversation = ` +User: What did you work on today? +Assistant: I reviewed the new ML pipeline architecture. +User: How did it look? +Assistant: Promising, but needs better error handling. +`; + +await client.retain('my-bank', conversation, { + context: 'Daily standup conversation' +}); + +// Batch retain multiple items +await client.retainBatch('my-bank', [ + { content: 'Bob prefers Python for data science' }, + { content: 'Alice recommends using pytest for testing' }, + { content: 'The team uses GitHub for code reviews' } +]); +// [/docs:main-retain] + + +// ============================================================================= +// Doc Examples - Recall Section +// ============================================================================= + +// [docs:main-recall] +// Basic search +const results = await client.recall('my-bank', 'What does Alice do at Google?'); + +for (const result of results.results) { + console.log(`- ${result.text}`); +} + +// Search with options +const filteredResults = await client.recall('my-bank', 'What happened last spring?', { + budget: 'high', + maxTokens: 8192, + types: ['world'] +}); + +// Include entity information +const entityResults = await client.recall('my-bank', 'Tell me about Alice', { + includeEntities: true, + maxEntityTokens: 500 +}); + +// Check entity details +for (const [entityId, entity] of Object.entries(entityResults.entities || {})) { + console.log(`Entity: ${entity.canonical_name}`); + console.log(`Observations: ${entity.observations}`); +} +// [/docs:main-recall] + + +// ============================================================================= +// Doc Examples - Reflect Section +// ============================================================================= + +// [docs:main-reflect] +// Basic reflect +const response = await client.reflect('my-bank', 'Should we adopt TypeScript for our backend?'); + +console.log(response.text); +console.log('\nBased on:', (response.based_on || []).length, 'facts'); + +// Reflect with options +const detailedResponse = await client.reflect('my-bank', "What are Alice's strengths for the team lead role?", { + budget: 'high' +}); + +// See which facts influenced the response +for (const fact of detailedResponse.based_on || []) { + console.log(`- ${fact.text}`); +} +// [/docs:main-reflect] + + +// ============================================================================= +// Doc Examples - List Memories Section +// ============================================================================= + +// [docs:main-list-memories] +// List all memories in a bank +const memories = await client.listMemories('my-bank', { + limit: 10 +}); + +for (const memory of memories.items) { + console.log(`- [${memory.fact_type}] ${memory.text}`); +} + +// Filter by type +const worldFacts = await client.listMemories('my-bank', { + type: 'world', + limit: 5 +}); + +// Search within memories +const searchResults = await client.listMemories('my-bank', { + q: 'Alice', + limit: 10 +}); +// [/docs:main-list-memories] + + +// ============================================================================= +// Cleanup (not shown in docs) +// ============================================================================= +await fetch(`${HINDSIGHT_URL}/v1/default/banks/my-bank`, { method: 'DELETE' }); + +console.log('main-methods.mjs: All examples passed'); diff --git a/hindsight-docs/examples/api/main-methods.py b/hindsight-docs/examples/api/main-methods.py index fed8f864..76038841 100644 --- a/hindsight-docs/examples/api/main-methods.py +++ b/hindsight-docs/examples/api/main-methods.py @@ -84,8 +84,8 @@ results = client.recall( ) # Check entity details -for entity in results.entities or []: - print(f"Entity: {entity.name}") +for entity_id, entity in (results.entities or {}).items(): + print(f"Entity: {entity.canonical_name}") print(f"Observations: {entity.observations}") # [/docs:main-recall] @@ -117,6 +117,61 @@ for fact in response.based_on or []: # [/docs:main-reflect] +# ============================================================================= +# Doc Examples - List Memories Section +# ============================================================================= + +# [docs:main-list-memories] +# List all memories in a bank +memories = client.list_memories( + bank_id="my-bank", + limit=10 +) + +for memory in memories.items: + print(f"- [{memory['fact_type']}] {memory['text']}") + +# Filter by type +world_facts = client.list_memories( + bank_id="my-bank", + type="world", + limit=5 +) + +# Search within memories +search_results = client.list_memories( + bank_id="my-bank", + search_query="Alice", + limit=10 +) +# [/docs:main-list-memories] + + +# ============================================================================= +# Doc Examples - Async Methods Section +# ============================================================================= + +# [docs:main-async] +import asyncio + +async def async_example(): + # Create a fresh client for async operations + async_client = Hindsight(base_url=HINDSIGHT_URL) + + # All sync methods have async versions prefixed with 'a' + await async_client.aretain(bank_id="my-bank", content="Async memory") + + results = await async_client.arecall(bank_id="my-bank", query="Async") + for r in results: + print(f"- {r.text}") + + response = await async_client.areflect(bank_id="my-bank", query="What was stored?") + print(response.text) + +asyncio.run(async_example()) +# [/docs:main-async] + + # ============================================================================= # Cleanup (not shown in docs) # ============================================================================= diff --git a/hindsight-docs/examples/api/memory-banks.mjs b/hindsight-docs/examples/api/memory-banks.mjs index 6051dda0..e6b2740a 100644 --- a/hindsight-docs/examples/api/memory-banks.mjs +++ b/hindsight-docs/examples/api/memory-banks.mjs @@ -31,6 +31,7 @@ await client.createBank('my-bank', { // [docs:bank-background] await client.createBank('financial-advisor', { + name: 'Financial Advisor', background: `I am a conservative financial advisor with 20 years of experience. I prioritize capital preservation over aggressive growth. I have seen multiple market crashes and believe in diversification.` diff --git a/hindsight-docs/examples/api/memory-banks.py b/hindsight-docs/examples/api/memory-banks.py index ba3b61f9..46eadf0c 100644 --- a/hindsight-docs/examples/api/memory-banks.py +++ b/hindsight-docs/examples/api/memory-banks.py @@ -36,6 +36,7 @@ client.create_bank( # [docs:bank-background] client.create_bank( bank_id="financial-advisor", + name="Financial Advisor", background="""I am a conservative financial advisor with 20 years of experience. I prioritize capital preservation over aggressive growth. I have seen multiple market crashes and believe in diversification.""" diff --git a/hindsight-docs/examples/api/opinions.mjs b/hindsight-docs/examples/api/opinions.mjs new file mode 100644 index 00000000..99a523c4 --- /dev/null +++ b/hindsight-docs/examples/api/opinions.mjs @@ -0,0 +1,99 @@ +#!/usr/bin/env node +/** + * Opinions API examples for Hindsight (Node.js) + * Run: node examples/api/opinions.mjs + */ +import { HindsightClient } from '@vectorize-io/hindsight-client'; + +const HINDSIGHT_URL = process.env.HINDSIGHT_API_URL || 'http://localhost:8888'; + +// ============================================================================= +// Setup (not shown in docs) +// ============================================================================= +const client = new HindsightClient({ baseUrl: HINDSIGHT_URL }); + +// Seed some data about programming languages +await client.retain('my-bank', 'Python is widely used for data science and machine learning'); +await client.retain('my-bank', 'Functional programming emphasizes immutability and pure functions'); +await client.retain('my-bank', 'Rust has better memory safety than C++'); +await client.retain('my-bank', 'C++ has a larger ecosystem and more libraries'); + +// ============================================================================= +// Doc Examples +// ============================================================================= + +// [docs:opinion-form] +// Ask a question - the system may form opinions based on stored facts +const answer = await client.reflect('my-bank', 'What do you think about functional programming?'); + +console.log(answer.text); +// [/docs:opinion-form] + + +// [docs:opinion-search] +// Search for facts about a topic +const results = await client.recall('my-bank', 'programming languages'); + +for (const result of results.results) { + console.log(`- ${result.text}`); +} +// [/docs:opinion-search] + + +// [docs:opinion-disposition] +// Create two memory banks with different dispositions +await client.createBank('open-minded', { + name: 'Open Minded', + disposition: { skepticism: 2, literalism: 2, empathy: 4 } +}); + +await client.createBank('conservative', { + name: 'Conservative', + disposition: { skepticism: 5, literalism: 5, empathy: 2 } +}); + +// Store the same facts to both +const facts = [ + 'Rust has better memory safety than C++', + 'C++ has a larger ecosystem and more libraries', + 'Rust compile times are longer than C++' +]; +for (const fact of facts) { + await client.retain('open-minded', fact); + await client.retain('conservative', fact); +} + +// Ask both the same question - different dispositions lead to different responses +const q = 'Should we rewrite our C++ codebase in Rust?'; + +const answer1 = await client.reflect('open-minded', q); +console.log('Open-minded response:', answer1.text.slice(0, 100), '...'); + +const answer2 = await client.reflect('conservative', q); +console.log('Conservative response:', answer2.text.slice(0, 100), '...'); +// [/docs:opinion-disposition] + + +// [docs:opinion-in-reflect] +const reflectAnswer = await client.reflect('my-bank', 'What language should I learn?'); + +console.log('Response:', reflectAnswer.text); + +// See which facts influenced the response +if (reflectAnswer.based_on) { + console.log('\nBased on these facts:'); + for (const fact of reflectAnswer.based_on) { + console.log(` - ${fact.text}`); + } +} +// [/docs:opinion-in-reflect] + + +// ============================================================================= +// Cleanup (not shown in docs) +// ============================================================================= +await fetch(`${HINDSIGHT_URL}/v1/default/banks/my-bank`, { method: 'DELETE' }); +await fetch(`${HINDSIGHT_URL}/v1/default/banks/open-minded`, { method: 'DELETE' }); +await fetch(`${HINDSIGHT_URL}/v1/default/banks/conservative`, { method: 'DELETE' }); + +console.log('opinions.mjs: All examples passed'); diff --git a/hindsight-docs/examples/api/opinions.py b/hindsight-docs/examples/api/opinions.py index 848977e3..4cb817c8 100644 --- a/hindsight-docs/examples/api/opinions.py +++ b/hindsight-docs/examples/api/opinions.py @@ -52,11 +52,13 @@ for result in results.results: # Create two memory banks with different dispositions client.create_bank( bank_id="open-minded", + name="Open Minded", disposition={"skepticism": 2, "literalism": 2, "empathy": 4} ) client.create_bank( bank_id="conservative", + name="Conservative", disposition={"skepticism": 5, "literalism": 5, "empathy": 2} ) diff --git a/hindsight-docs/examples/api/reflect.mjs b/hindsight-docs/examples/api/reflect.mjs index 695c61fe..e2469aff 100644 --- a/hindsight-docs/examples/api/reflect.mjs +++ b/hindsight-docs/examples/api/reflect.mjs @@ -45,6 +45,7 @@ const contextResponse = await client.reflect('my-bank', 'What do you think about // [docs:reflect-disposition] // Create a bank with specific disposition await client.createBank('cautious-advisor', { + name: 'Cautious Advisor', background: 'I am a risk-aware financial advisor', disposition: { skepticism: 5, diff --git a/hindsight-docs/examples/api/reflect.py b/hindsight-docs/examples/api/reflect.py index 1487263c..d6750a78 100644 --- a/hindsight-docs/examples/api/reflect.py +++ b/hindsight-docs/examples/api/reflect.py @@ -53,6 +53,7 @@ response = client.reflect( # Create a bank with specific disposition client.create_bank( bank_id="cautious-advisor", + name="Cautious Advisor", background="I am a risk-aware financial advisor", disposition={ "skepticism": 5, # Very skeptical of claims diff --git a/hindsight-docs/openapi.json b/hindsight-docs/openapi.json index 25311251..fe0f2ec3 100644 --- a/hindsight-docs/openapi.json +++ b/hindsight-docs/openapi.json @@ -1268,14 +1268,28 @@ "title": "Bank Id" }, "name": { - "type": "string", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], "title": "Name" }, "disposition": { "$ref": "#/components/schemas/DispositionTraits" }, "background": { - "type": "string", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], "title": "Background" }, "created_at": { @@ -1304,9 +1318,7 @@ "type": "object", "required": [ "bank_id", - "name", - "disposition", - "background" + "disposition" ], "title": "BankListItem", "description": "Bank list item with profile summary." @@ -1566,9 +1578,9 @@ "title": "DeleteResponse", "description": "Response model for delete operations.", "example": { - "success": true, + "deleted_count": 10, "message": "Deleted successfully", - "deleted_count": 10 + "success": true } }, "DispositionTraits": { diff --git a/hindsight-docs/static/openapi.json b/hindsight-docs/static/openapi.json index 25311251..fe0f2ec3 100644 --- a/hindsight-docs/static/openapi.json +++ b/hindsight-docs/static/openapi.json @@ -1268,14 +1268,28 @@ "title": "Bank Id" }, "name": { - "type": "string", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], "title": "Name" }, "disposition": { "$ref": "#/components/schemas/DispositionTraits" }, "background": { - "type": "string", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], "title": "Background" }, "created_at": { @@ -1304,9 +1318,7 @@ "type": "object", "required": [ "bank_id", - "name", - "disposition", - "background" + "disposition" ], "title": "BankListItem", "description": "Bank list item with profile summary." @@ -1566,9 +1578,9 @@ "title": "DeleteResponse", "description": "Response model for delete operations.", "example": { - "success": true, + "deleted_count": 10, "message": "Deleted successfully", - "deleted_count": 10 + "success": true } }, "DispositionTraits": { diff --git a/openapi.json b/openapi.json index 25311251..fe0f2ec3 100644 --- a/openapi.json +++ b/openapi.json @@ -1268,14 +1268,28 @@ "title": "Bank Id" }, "name": { - "type": "string", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], "title": "Name" }, "disposition": { "$ref": "#/components/schemas/DispositionTraits" }, "background": { - "type": "string", + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], "title": "Background" }, "created_at": { @@ -1304,9 +1318,7 @@ "type": "object", "required": [ "bank_id", - "name", - "disposition", - "background" + "disposition" ], "title": "BankListItem", "description": "Bank list item with profile summary." @@ -1566,9 +1578,9 @@ "title": "DeleteResponse", "description": "Response model for delete operations.", "example": { - "success": true, + "deleted_count": 10, "message": "Deleted successfully", - "deleted_count": 10 + "success": true } }, "DispositionTraits": {