Compare commits
21
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e521914f0f | ||
|
|
7cb469ff75 | ||
|
|
9118e7b4cb | ||
|
|
841a66f375 | ||
|
|
eb06adb2be | ||
|
|
3913788fd8 | ||
|
|
6ea02eb023 | ||
|
|
55154384f6 | ||
|
|
19e4e2d635 | ||
|
|
8f2396f04a | ||
|
|
bffc0ee0d0 | ||
|
|
476a62da47 | ||
|
|
5aaa769ab9 | ||
|
|
04f01ab9ab | ||
|
|
63f51385c4 | ||
|
|
e468a4e19f | ||
|
|
c0a0f447b7 | ||
|
|
84927ccc99 | ||
|
|
a6e8944ff0 | ||
|
|
f6d890f6ed | ||
|
|
1fa8d9150c |
+116
-1
@@ -38,6 +38,29 @@ jobs:
|
||||
working-directory: ./${{ matrix.path }}
|
||||
run: uv build
|
||||
|
||||
build-api-python-versions:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ['3.11', '3.12', '3.13']
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@v5
|
||||
with:
|
||||
enable-cache: true
|
||||
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
|
||||
- name: Build hindsight-api
|
||||
working-directory: ./hindsight-api
|
||||
run: uv build
|
||||
|
||||
build-typescript-client:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -472,4 +495,96 @@ jobs:
|
||||
|
||||
- name: Run tests
|
||||
working-directory: ./hindsight-integrations/litellm
|
||||
run: uv run pytest tests -v
|
||||
run: uv run pytest tests -v
|
||||
|
||||
test-doc-examples:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
HINDSIGHT_API_LLM_PROVIDER: groq
|
||||
HINDSIGHT_API_LLM_API_KEY: ${{ secrets.GROQ_API_KEY }}
|
||||
HINDSIGHT_API_LLM_MODEL: openai/gpt-oss-20b
|
||||
HINDSIGHT_API_URL: http://localhost:8888
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
UV_INDEX: pytorch=https://download.pytorch.org/whl/cpu
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@v5
|
||||
with:
|
||||
enable-cache: true
|
||||
prune-cache: false
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version-file: ".python-version"
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: 'npm'
|
||||
cache-dependency-path: package-lock.json
|
||||
|
||||
- name: Build and install API
|
||||
working-directory: ./hindsight-api
|
||||
run: |
|
||||
uv build
|
||||
uv sync --no-install-project --index-strategy unsafe-best-match
|
||||
|
||||
- name: Install Python client dependencies
|
||||
working-directory: ./hindsight-clients/python
|
||||
run: uv sync --extra test --index-strategy unsafe-best-match
|
||||
|
||||
- name: Install TypeScript client
|
||||
run: |
|
||||
npm ci --workspace=hindsight-clients/typescript
|
||||
npm run build --workspace=hindsight-clients/typescript
|
||||
|
||||
- name: Create .env file
|
||||
run: |
|
||||
cat > .env << EOF
|
||||
HINDSIGHT_API_LLM_PROVIDER=${{ env.HINDSIGHT_API_LLM_PROVIDER }}
|
||||
HINDSIGHT_API_LLM_API_KEY=${{ env.HINDSIGHT_API_LLM_API_KEY }}
|
||||
HINDSIGHT_API_LLM_MODEL=${{ env.HINDSIGHT_API_LLM_MODEL }}
|
||||
EOF
|
||||
|
||||
- name: Start API server
|
||||
run: |
|
||||
./scripts/dev/start-api.sh > /tmp/api-server.log 2>&1 &
|
||||
echo "Waiting for API server to be ready..."
|
||||
for i in {1..60}; do
|
||||
if curl -sf http://localhost:8888/health > /dev/null 2>&1; then
|
||||
echo "API server is ready after ${i}s"
|
||||
break
|
||||
fi
|
||||
if [ $i -eq 60 ]; then
|
||||
echo "API server failed to start after 60s"
|
||||
cat /tmp/api-server.log
|
||||
exit 1
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
- name: Run Python doc examples
|
||||
working-directory: ./hindsight-clients/python
|
||||
run: |
|
||||
for f in ../../hindsight-docs/examples/api/*.py; do
|
||||
echo "Running $f..."
|
||||
uv run python "$f"
|
||||
done
|
||||
|
||||
- name: Run Node.js doc examples
|
||||
run: |
|
||||
for f in hindsight-docs/examples/api/*.mjs; do
|
||||
echo "Running $f..."
|
||||
node "$f"
|
||||
done
|
||||
|
||||
- name: Show API server logs
|
||||
if: always()
|
||||
run: |
|
||||
echo "=== API Server Logs ==="
|
||||
cat /tmp/api-server.log || echo "No API server log found"
|
||||
@@ -2,14 +2,13 @@
|
||||
|
||||

|
||||
|
||||
[Documentation](https://vectorize-io.github.io/hindsight) • [Paper](#coming-soon) • [Examples](https://github.com/vectorize-io/hindsight-cookbook)
|
||||
[Documentation](https://hindsight.vectorize.io) • [Paper](https://arxiv.org/abs/2512.12818) • [Cookbook](https://hindsight.vectorize.io/cookbook) • [Hindsight Cloud](https://vectorize.io/hindsight/cloud)
|
||||
|
||||
[](https://github.com/vectorize-io/hindsight/actions/workflows/release.yml)
|
||||
[](https://opensource.org/licenses/MIT)
|
||||
[](https://pypi.org/project/hindsight-api/)
|
||||
[](https://pypi.org/project/hindsight-client/)
|
||||
[](https://www.npmjs.com/package/@vectorize-io/hindsight-client)
|
||||
[](https://join.slack.com/t/hindsight-space/shared_invite/zt-3klo21kua-VUCC_zHP5rIcXFB1_5yw6A)
|
||||
[](https://opensource.org/licenses/MIT)
|
||||

|
||||

|
||||
|
||||
|
||||
</div>
|
||||
@@ -18,7 +17,7 @@
|
||||
|
||||
## What is Hindsight?
|
||||
|
||||
Hindsight™ is an agent memory system built to create smarter agents that learn over time. It eliminates the shortcomings of alternative techniques such as RAG and knowledge graph.
|
||||
Hindsight™ is an agent memory system built to create smarter agents that learn over time. It eliminates the shortcomings of alternative techniques such as RAG and knowledge graph and delivers state-of-the-art performance on long term memory tasks.
|
||||
|
||||
Hindsight addresses common challenges that have frustrated AI engineers building agents to automate tasks and assist users with conversational interfaces. Many of these challenges stem directly from a lack of memory.
|
||||
|
||||
@@ -26,27 +25,48 @@ Hindsight addresses common challenges that have frustrated AI engineers building
|
||||
- **Hallucinations:** Long term memory can be seeded with external knowledge to ground agent behavior in reliable sources to augment training data.
|
||||
- **Cognitive Overload:** As workflows get complex, retrievals, tool calls, user messages and agent responses can grow to fill the context window leading to context rot. Short term memory optimization allows agents to reduce tokens and focus context by removing irrelevant details.
|
||||
|
||||
## How Hindsight Works
|
||||
## How is Hindsight Different From Other Memory Systems?
|
||||
|
||||

|
||||
|
||||
Hindsight organizes memory into four networks to mimic the way human memory works:
|
||||
Most agent memory implementation rely on basic vector search or sometimes use a knowledge graph. Hindsight uses biomimetic data structures to organize agent memories in a way that is more like how human memory works:
|
||||
|
||||
- **World:** Facts about the world ("The stove gets hot")
|
||||
- **Experiences:** Agent's own experiences ("I touched the stove and it really hurt")
|
||||
- **Opinion:** Beliefs with confidence scores ("I shouldn't touch the stove again" - .99 confidence)
|
||||
- **Observation:** Complex mental models derived by reflecting on facts and experiences ("Curling irons, ovens, and fire are also hot. I shouldn't touch those either.")
|
||||
|
||||
Memories in Hindsight are stored in banks (i.e. memory banks). When memories are added to Hindsight, they are pushed into either the world facts or experiences memory pathway. They are then represented as a combination of entities, relationships, and time series with sparse/dense vector representations to aid in later recall.
|
||||
|
||||
Hindsight provides three simple methods to interact with the system:
|
||||
|
||||
- **Retain:** Provide information to Hindsight that you want it to remember
|
||||
- **Recall:** Retrieve memories from Hindsight
|
||||
- **Reflect:** Reflect on memories and experiences to generate new observations and insights from existing memories.
|
||||
|
||||
Memories in Hindsight are stored in banks (e.g. memory banks). When memories are retained, they are transformed to construct a series of search indexes, time series data, and entity/relationship graphs.
|
||||
### Agent Memory That Learns
|
||||
|
||||
A key goal of Hindsight is to build agent memory that enables agents to learn and improve over time. This is the role of the `reflect` operation which provides the agent to form broader opinions and observations over time.
|
||||
|
||||
For example, imagine a product support agent that is helping a user troubleshoot a problem. It uses a `search-documentation` tool it found on an MCP server. Later in the conversation, the agent discovers that the documentation returned from the tool wasn't for the product the user was asking about. The agent now has an experience in its memory bank. And just like humans, we want that agent to learn from its experience.
|
||||
|
||||
As the agent gains more experiences, `reflect` allows the agent to form observations about what worked, what didn't, and what to do differently the next time it encounters a similar task.
|
||||
|
||||
---
|
||||
|
||||
## Memory Performance & Accuracy
|
||||
|
||||
Hindsight has achieved state-of-the-art performance on the LongMemEval benchmark, widely used to assess memory system performance across a variety of conversational
|
||||
AI scenarios. The current reported performance of Hindsight and other agent memory solutions as of December 2025 is shown here:
|
||||
|
||||

|
||||
|
||||
The benchmark performance data for Hindsight and GPT-4o (full context) have been reproduced by research collaborators at the Virginia Tech [Sanghani Center for Artificial Intelligence and Data Analytics](https://sanghani.cs.vt.edu/) and The Washington Post. Other scores are self-reported by software vendors.
|
||||
|
||||
A thorough examination of the techniques implemented in Hindsight and detailed breakdowns of benchmark performance are [available on arXiv](https://arxiv.org/abs/2512.12818). This research is currently being prepared for conference submission and the wider peer review process.
|
||||
|
||||
The benchmark results from this research can be inspected in our [visual benchmark explorer](https://hindsight-benchmarks.vercel.app). As additional improvements are made to Hindsight, new benchmark data will be available for review using this same tool.
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Docker (recommended)
|
||||
@@ -223,6 +243,10 @@ client.reflect(bank_id="my-bank", query="What should I know about Alice?")
|
||||
- [Slack](https://join.slack.com/t/hindsight-space/shared_invite/zt-3klo21kua-VUCC_zHP5rIcXFB1_5yw6A)
|
||||
- [GitHub Issues](https://github.com/vectorize-io/hindsight/issues)
|
||||
|
||||
---
|
||||
## Star History
|
||||
|
||||
[](https://www.star-history.com/#vectorize-io/hindsight&type=date&legend=top-left)
|
||||
---
|
||||
|
||||
## Contributing
|
||||
|
||||
@@ -2,8 +2,8 @@ apiVersion: v2
|
||||
name: hindsight
|
||||
description: Hindsight helm chart
|
||||
type: application
|
||||
version: 0.1.6
|
||||
appVersion: "0.1.6"
|
||||
version: 0.1.8
|
||||
appVersion: "0.1.8"
|
||||
keywords:
|
||||
- ai
|
||||
- memory
|
||||
|
||||
+137
-1
@@ -1 +1,137 @@
|
||||
# Memory
|
||||
# Hindsight API
|
||||
|
||||
**Memory System for AI Agents** — Temporal + Semantic + Entity Memory Architecture using PostgreSQL with pgvector.
|
||||
|
||||
Hindsight gives AI agents persistent memory that works like human memory: it stores facts, tracks entities and relationships, handles temporal reasoning ("what happened last spring?"), and forms opinions based on configurable disposition traits.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
pip install hindsight-api
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Run the Server
|
||||
|
||||
```bash
|
||||
# Set your LLM provider
|
||||
export HINDSIGHT_API_LLM_PROVIDER=openai
|
||||
export HINDSIGHT_API_LLM_API_KEY=sk-xxxxxxxxxxxx
|
||||
|
||||
# Start the server (uses embedded PostgreSQL by default)
|
||||
hindsight-api
|
||||
```
|
||||
|
||||
The server starts at http://localhost:8888 with:
|
||||
- REST API for memory operations
|
||||
- MCP server at `/mcp` for tool-use integration
|
||||
|
||||
### Use the Python API
|
||||
|
||||
```python
|
||||
from hindsight_api import MemoryEngine
|
||||
|
||||
# Create and initialize the memory engine
|
||||
memory = MemoryEngine()
|
||||
await memory.initialize()
|
||||
|
||||
# Create a memory bank for your agent
|
||||
bank = await memory.create_memory_bank(
|
||||
name="my-assistant",
|
||||
background="A helpful coding assistant"
|
||||
)
|
||||
|
||||
# Store a memory
|
||||
await memory.retain(
|
||||
memory_bank_id=bank.id,
|
||||
content="The user prefers Python for data science projects"
|
||||
)
|
||||
|
||||
# Recall memories
|
||||
results = await memory.recall(
|
||||
memory_bank_id=bank.id,
|
||||
query="What programming language does the user prefer?"
|
||||
)
|
||||
|
||||
# Reflect with reasoning
|
||||
response = await memory.reflect(
|
||||
memory_bank_id=bank.id,
|
||||
query="Should I recommend Python or R for this ML project?"
|
||||
)
|
||||
```
|
||||
|
||||
## CLI Options
|
||||
|
||||
```bash
|
||||
hindsight-api --help
|
||||
|
||||
# Common options
|
||||
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
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
Configure via environment variables:
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| `HINDSIGHT_API_DATABASE_URL` | PostgreSQL connection string | `pg0` (embedded) |
|
||||
| `HINDSIGHT_API_LLM_PROVIDER` | `openai`, `groq`, `gemini`, `ollama` | `openai` |
|
||||
| `HINDSIGHT_API_LLM_API_KEY` | API key for LLM provider | - |
|
||||
| `HINDSIGHT_API_LLM_MODEL` | Model name | `gpt-4o-mini` |
|
||||
| `HINDSIGHT_API_HOST` | Server bind address | `0.0.0.0` |
|
||||
| `HINDSIGHT_API_PORT` | Server port | `8888` |
|
||||
|
||||
### Example with External PostgreSQL
|
||||
|
||||
```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
|
||||
```
|
||||
|
||||
## Docker
|
||||
|
||||
```bash
|
||||
docker run --rm -it -p 8888:8888 \
|
||||
-e HINDSIGHT_API_LLM_API_KEY=$OPENAI_API_KEY \
|
||||
-v $HOME/.hindsight-docker:/home/hindsight/.pg0 \
|
||||
ghcr.io/vectorize-io/hindsight:latest
|
||||
```
|
||||
|
||||
## MCP Server
|
||||
|
||||
For local MCP integration without running the full API server:
|
||||
|
||||
```bash
|
||||
hindsight-local-mcp
|
||||
```
|
||||
|
||||
This runs a stdio-based MCP server that can be used directly with MCP-compatible clients.
|
||||
|
||||
## Key Features
|
||||
|
||||
- **Multi-Strategy Retrieval (TEMPR)** — Semantic, keyword, graph, and temporal search combined with RRF fusion
|
||||
- **Entity Graph** — Automatic entity extraction and relationship tracking
|
||||
- **Temporal Reasoning** — Native support for time-based queries
|
||||
- **Disposition Traits** — Configurable skepticism, literalism, and empathy influence opinion formation
|
||||
- **Three Memory Types** — World facts, bank actions, and formed opinions with confidence scores
|
||||
|
||||
## Documentation
|
||||
|
||||
Full documentation: [https://hindsight.vectorize.io](https://hindsight.vectorize.io)
|
||||
|
||||
- [Installation Guide](https://hindsight.vectorize.io/developer/installation)
|
||||
- [Configuration Reference](https://hindsight.vectorize.io/developer/configuration)
|
||||
- [API Reference](https://hindsight.vectorize.io/api-reference)
|
||||
- [Python SDK](https://hindsight.vectorize.io/sdks/python)
|
||||
|
||||
## License
|
||||
|
||||
Apache 2.0
|
||||
|
||||
@@ -506,9 +506,9 @@ class BankListItem(BaseModel):
|
||||
"""Bank list item with profile summary."""
|
||||
|
||||
bank_id: str
|
||||
name: str
|
||||
name: str | None = None
|
||||
disposition: DispositionTraits
|
||||
background: str
|
||||
background: str | None = None
|
||||
created_at: str | None = None
|
||||
updated_at: str | None = None
|
||||
|
||||
@@ -1452,18 +1452,22 @@ def _register_routes(app: FastAPI):
|
||||
bank_id,
|
||||
)
|
||||
|
||||
def parse_metadata(metadata):
|
||||
"""Parse result_metadata which may be a string or dict."""
|
||||
if metadata is None:
|
||||
return {}
|
||||
if isinstance(metadata, str):
|
||||
return json.loads(metadata)
|
||||
return metadata
|
||||
|
||||
return {
|
||||
"bank_id": bank_id,
|
||||
"operations": [
|
||||
{
|
||||
"id": str(row["operation_id"]),
|
||||
"task_type": row["operation_type"],
|
||||
"items_count": row["result_metadata"].get("items_count", 0)
|
||||
if row["result_metadata"]
|
||||
else 0,
|
||||
"document_id": row["result_metadata"].get("document_id")
|
||||
if row["result_metadata"]
|
||||
else None,
|
||||
"items_count": parse_metadata(row["result_metadata"]).get("items_count", 0),
|
||||
"document_id": parse_metadata(row["result_metadata"]).get("document_id"),
|
||||
"created_at": row["created_at"].isoformat(),
|
||||
"status": row["status"],
|
||||
"error_message": row["error_message"],
|
||||
@@ -1499,7 +1503,7 @@ def _register_routes(app: FastAPI):
|
||||
async with acquire_with_retry(pool) as conn:
|
||||
# Check if operation exists and belongs to this memory bank
|
||||
result = await conn.fetchrow(
|
||||
"SELECT bank_id FROM async_operations WHERE id = $1 AND bank_id = $2", op_uuid, bank_id
|
||||
"SELECT bank_id FROM async_operations WHERE operation_id = $1 AND bank_id = $2", op_uuid, bank_id
|
||||
)
|
||||
|
||||
if not result:
|
||||
@@ -1508,7 +1512,7 @@ def _register_routes(app: FastAPI):
|
||||
)
|
||||
|
||||
# Delete the operation
|
||||
await conn.execute("DELETE FROM async_operations WHERE id = $1", op_uuid)
|
||||
await conn.execute("DELETE FROM async_operations WHERE operation_id = $1", op_uuid)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
@@ -1769,13 +1773,13 @@ def _register_routes(app: FastAPI):
|
||||
async with acquire_with_retry(pool) as conn:
|
||||
await conn.execute(
|
||||
"""
|
||||
INSERT INTO async_operations (id, bank_id, task_type, items_count)
|
||||
INSERT INTO async_operations (operation_id, bank_id, operation_type, result_metadata)
|
||||
VALUES ($1, $2, $3, $4)
|
||||
""",
|
||||
operation_id,
|
||||
bank_id,
|
||||
"retain",
|
||||
len(contents),
|
||||
json.dumps({"items_count": len(contents)}),
|
||||
)
|
||||
|
||||
# Submit task to background queue
|
||||
|
||||
@@ -311,7 +311,7 @@ class MemoryEngine:
|
||||
pool = await self._get_pool()
|
||||
async with acquire_with_retry(pool) as conn:
|
||||
result = await conn.fetchrow(
|
||||
"SELECT id FROM async_operations WHERE id = $1", uuid.UUID(operation_id)
|
||||
"SELECT operation_id FROM async_operations WHERE operation_id = $1", uuid.UUID(operation_id)
|
||||
)
|
||||
if not result:
|
||||
# Operation was cancelled, skip processing
|
||||
@@ -369,7 +369,7 @@ class MemoryEngine:
|
||||
try:
|
||||
pool = await self._get_pool()
|
||||
async with acquire_with_retry(pool) as conn:
|
||||
await conn.execute("DELETE FROM async_operations WHERE id = $1", uuid.UUID(operation_id))
|
||||
await conn.execute("DELETE FROM async_operations WHERE operation_id = $1", uuid.UUID(operation_id))
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to delete async operation record {operation_id}: {e}")
|
||||
|
||||
@@ -386,7 +386,7 @@ class MemoryEngine:
|
||||
"""
|
||||
UPDATE async_operations
|
||||
SET status = 'failed', error_message = $2
|
||||
WHERE id = $1
|
||||
WHERE operation_id = $1
|
||||
""",
|
||||
uuid.UUID(operation_id),
|
||||
truncated_error,
|
||||
|
||||
@@ -4,8 +4,8 @@ build-backend = "hatchling.build"
|
||||
|
||||
[project]
|
||||
name = "hindsight-api"
|
||||
version = "0.1.6"
|
||||
description = "Temporal + Semantic + Entity Memory System for AI agents using PostgreSQL"
|
||||
version = "0.1.8"
|
||||
description = "Hindsight: Agent Memory That Works Like Human Memory"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.11"
|
||||
dependencies = [
|
||||
@@ -25,7 +25,7 @@ dependencies = [
|
||||
"greenlet>=3.2.4",
|
||||
"psycopg2-binary>=2.9.11",
|
||||
"transformers>=4.30.0,<4.46.0",
|
||||
"torch>=2.0.0,<2.6.0",
|
||||
"torch>=2.0.0",
|
||||
"tiktoken>=0.12.0",
|
||||
"httpx>=0.27.0",
|
||||
"fastmcp>=2.3.0",
|
||||
|
||||
@@ -426,3 +426,185 @@ async def test_document_deletion(api_client):
|
||||
f"/v1/default/banks/{test_bank_id}/documents/sales-report-q1-2024"
|
||||
)
|
||||
assert response.status_code == 404
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_async_retain(api_client):
|
||||
"""Test asynchronous retain functionality.
|
||||
|
||||
When async=true is passed, the retain endpoint should:
|
||||
1. Return immediately with success and async_=true
|
||||
2. Process the content in the background
|
||||
3. Eventually store the memories
|
||||
"""
|
||||
import asyncio
|
||||
|
||||
test_bank_id = f"async_retain_test_{datetime.now().timestamp()}"
|
||||
|
||||
# Store memory with async=true
|
||||
response = await api_client.post(
|
||||
f"/v1/default/banks/{test_bank_id}/memories",
|
||||
json={
|
||||
"async": True,
|
||||
"items": [
|
||||
{
|
||||
"content": "Alice is a senior engineer at TechCorp. She has been working on the authentication system for 5 years.",
|
||||
"context": "team introduction"
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
assert response.status_code == 200
|
||||
result = response.json()
|
||||
assert result["success"] is True
|
||||
assert result["async"] is True, "Response should indicate async processing"
|
||||
assert result["items_count"] == 1
|
||||
|
||||
# Check operations endpoint to see the pending operation
|
||||
response = await api_client.get(f"/v1/default/banks/{test_bank_id}/operations")
|
||||
assert response.status_code == 200
|
||||
ops_result = response.json()
|
||||
assert "operations" in ops_result
|
||||
|
||||
# Wait for async processing to complete (poll with timeout)
|
||||
max_wait_seconds = 30
|
||||
poll_interval = 0.5
|
||||
elapsed = 0
|
||||
memories_found = False
|
||||
|
||||
while elapsed < max_wait_seconds:
|
||||
# Check if memories are stored
|
||||
response = await api_client.get(
|
||||
f"/v1/default/banks/{test_bank_id}/memories/list",
|
||||
params={"limit": 10}
|
||||
)
|
||||
assert response.status_code == 200
|
||||
items = response.json()["items"]
|
||||
|
||||
if len(items) > 0:
|
||||
memories_found = True
|
||||
break
|
||||
|
||||
await asyncio.sleep(poll_interval)
|
||||
elapsed += poll_interval
|
||||
|
||||
assert memories_found, f"Async retain did not complete within {max_wait_seconds} seconds"
|
||||
|
||||
# Verify we can recall the stored memory
|
||||
response = await api_client.post(
|
||||
f"/v1/default/banks/{test_bank_id}/memories/recall",
|
||||
json={
|
||||
"query": "Who works at TechCorp?",
|
||||
"thinking_budget": 30
|
||||
}
|
||||
)
|
||||
assert response.status_code == 200
|
||||
search_results = response.json()
|
||||
assert len(search_results["results"]) > 0, "Should find the asynchronously stored memory"
|
||||
|
||||
# Verify Alice is mentioned
|
||||
found_alice = any("Alice" in r["text"] for r in search_results["results"])
|
||||
assert found_alice, "Should find Alice in search results"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_async_retain_parallel(api_client):
|
||||
"""Test multiple async retain operations running in parallel.
|
||||
|
||||
Verifies that:
|
||||
1. Multiple async operations can be submitted concurrently
|
||||
2. All operations complete successfully
|
||||
3. The exact number of documents are processed
|
||||
"""
|
||||
import asyncio
|
||||
|
||||
test_bank_id = f"async_parallel_test_{datetime.now().timestamp()}"
|
||||
num_documents = 5
|
||||
|
||||
# Prepare multiple documents to retain
|
||||
documents = [
|
||||
{
|
||||
"content": f"Document {i}: This is test content about Person{i} who works at Company{i}.",
|
||||
"context": f"test document {i}",
|
||||
"document_id": f"doc_{i}"
|
||||
}
|
||||
for i in range(num_documents)
|
||||
]
|
||||
|
||||
# Submit all async retain operations in parallel
|
||||
async def submit_async_retain(doc):
|
||||
return await api_client.post(
|
||||
f"/v1/default/banks/{test_bank_id}/memories",
|
||||
json={
|
||||
"async": True,
|
||||
"items": [doc]
|
||||
}
|
||||
)
|
||||
|
||||
# Run all submissions concurrently
|
||||
responses = await asyncio.gather(*[submit_async_retain(doc) for doc in documents])
|
||||
|
||||
# Verify all submissions succeeded
|
||||
for i, response in enumerate(responses):
|
||||
assert response.status_code == 200, f"Document {i} submission failed"
|
||||
result = response.json()
|
||||
assert result["success"] is True
|
||||
assert result["async"] is True
|
||||
|
||||
# Check operations endpoint - should show pending operations
|
||||
response = await api_client.get(f"/v1/default/banks/{test_bank_id}/operations")
|
||||
assert response.status_code == 200
|
||||
|
||||
# Wait for all async operations to complete (poll with timeout)
|
||||
max_wait_seconds = 60
|
||||
poll_interval = 1.0
|
||||
elapsed = 0
|
||||
all_docs_processed = False
|
||||
|
||||
while elapsed < max_wait_seconds:
|
||||
# Check document count
|
||||
response = await api_client.get(f"/v1/default/banks/{test_bank_id}/documents")
|
||||
assert response.status_code == 200
|
||||
docs = response.json()["items"]
|
||||
|
||||
if len(docs) >= num_documents:
|
||||
all_docs_processed = True
|
||||
break
|
||||
|
||||
await asyncio.sleep(poll_interval)
|
||||
elapsed += poll_interval
|
||||
|
||||
assert all_docs_processed, f"Expected {num_documents} documents, but only {len(docs)} were processed within {max_wait_seconds} seconds"
|
||||
|
||||
# Verify exact document count
|
||||
response = await api_client.get(f"/v1/default/banks/{test_bank_id}/documents")
|
||||
assert response.status_code == 200
|
||||
final_docs = response.json()["items"]
|
||||
assert len(final_docs) == num_documents, f"Expected exactly {num_documents} documents, got {len(final_docs)}"
|
||||
|
||||
# Verify each document exists
|
||||
doc_ids = {doc["id"] for doc in final_docs}
|
||||
for i in range(num_documents):
|
||||
assert f"doc_{i}" in doc_ids, f"Document doc_{i} not found"
|
||||
|
||||
# Verify memories were created for all documents
|
||||
response = await api_client.get(
|
||||
f"/v1/default/banks/{test_bank_id}/memories/list",
|
||||
params={"limit": 100}
|
||||
)
|
||||
assert response.status_code == 200
|
||||
memories = response.json()["items"]
|
||||
assert len(memories) >= num_documents, f"Expected at least {num_documents} memories, got {len(memories)}"
|
||||
|
||||
# Verify we can recall content from different documents
|
||||
for i in [0, num_documents - 1]: # Check first and last
|
||||
response = await api_client.post(
|
||||
f"/v1/default/banks/{test_bank_id}/memories/recall",
|
||||
json={
|
||||
"query": f"Who works at Company{i}?",
|
||||
"thinking_budget": 30
|
||||
}
|
||||
)
|
||||
assert response.status_code == 200
|
||||
results = response.json()["results"]
|
||||
assert len(results) > 0, f"Should find memories for document {i}"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "hindsight-cli"
|
||||
version = "0.1.6"
|
||||
version = "0.1.8"
|
||||
edition = "2021"
|
||||
authors = ["Hindsight Team"]
|
||||
description = "A beautiful CLI for Hindsight - semantic memory system"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "hindsight-client"
|
||||
version = "0.1.6"
|
||||
version = "0.1.8"
|
||||
description = "Python client for Hindsight - Semantic memory system with personality-driven thinking"
|
||||
authors = [
|
||||
{name = "Hindsight Team"}
|
||||
@@ -20,6 +20,7 @@ dependencies = [
|
||||
test = [
|
||||
"pytest>=7.0.0",
|
||||
"pytest-asyncio>=0.21.0",
|
||||
"requests>=2.28.0",
|
||||
]
|
||||
|
||||
[build-system]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vectorize-io/hindsight-client",
|
||||
"version": "0.1.6",
|
||||
"version": "0.1.8",
|
||||
"description": "TypeScript client for Hindsight - Semantic memory system with personality-driven thinking",
|
||||
"main": "./dist/src/index.js",
|
||||
"types": "./dist/src/index.d.ts",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "hindsight-control-plane",
|
||||
"version": "0.1.6",
|
||||
"version": "0.1.8",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useParams, useRouter, useSearchParams } from "next/navigation";
|
||||
import { useEffect } from "react";
|
||||
import { BankSelector } from "@/components/bank-selector";
|
||||
import { Sidebar } from "@/components/sidebar";
|
||||
import { DataView } from "@/components/data-view";
|
||||
@@ -10,7 +9,6 @@ import { EntitiesView } from "@/components/entities-view";
|
||||
import { ThinkView } from "@/components/think-view";
|
||||
import { SearchDebugView } from "@/components/search-debug-view";
|
||||
import { BankProfileView } from "@/components/bank-profile-view";
|
||||
import { useBank } from "@/lib/bank-context";
|
||||
|
||||
type NavItem = "recall" | "reflect" | "data" | "documents" | "entities" | "profile";
|
||||
type DataSubTab = "world" | "experience" | "opinion";
|
||||
@@ -19,19 +17,11 @@ export default function BankPage() {
|
||||
const params = useParams();
|
||||
const router = useRouter();
|
||||
const searchParams = useSearchParams();
|
||||
const { currentBank, setCurrentBank } = useBank();
|
||||
|
||||
const bankId = params.bankId as string;
|
||||
const view = (searchParams.get("view") || "profile") as NavItem;
|
||||
const subTab = (searchParams.get("subTab") || "world") as DataSubTab;
|
||||
|
||||
// Sync URL bank with context
|
||||
useEffect(() => {
|
||||
if (bankId && bankId !== currentBank) {
|
||||
setCurrentBank(bankId);
|
||||
}
|
||||
}, [bankId, currentBank, setCurrentBank]);
|
||||
|
||||
const handleTabChange = (tab: NavItem) => {
|
||||
router.push(`/banks/${bankId}?view=${tab}`);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
# Hindsight Benchmarks
|
||||
|
||||
This directory contains benchmark suites for evaluating Hindsight's memory capabilities.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
1. Set up your environment variables in `.env` at the project root:
|
||||
```bash
|
||||
cp .env.example .env
|
||||
# Edit .env with your API keys
|
||||
```
|
||||
|
||||
2. Make sure you have `uv` installed.
|
||||
|
||||
## Available Benchmarks
|
||||
|
||||
### LoComo
|
||||
|
||||
Tests conversational memory with multi-turn dialogues.
|
||||
|
||||
```bash
|
||||
# Run from project root
|
||||
./scripts/benchmarks/run-locomo.sh
|
||||
|
||||
# With options
|
||||
./scripts/benchmarks/run-locomo.sh --max-conversations 10
|
||||
./scripts/benchmarks/run-locomo.sh --skip-ingestion # Reuse existing data
|
||||
./scripts/benchmarks/run-locomo.sh --use-think # Use think API
|
||||
./scripts/benchmarks/run-locomo.sh --conversation conv-26 # Single conversation
|
||||
```
|
||||
|
||||
**Options:**
|
||||
- `--max-conversations N` - Limit number of conversations
|
||||
- `--max-questions N` - Limit questions per conversation
|
||||
- `--skip-ingestion` - Skip data ingestion, use existing
|
||||
- `--use-think` - Use think API instead of search + LLM
|
||||
- `--conversation NAME` - Run specific conversation only
|
||||
- `--api-url URL` - Custom API URL (default: local memory)
|
||||
- `--only-failed` - Retry only failed questions
|
||||
- `--only-invalid` - Retry only invalid questions
|
||||
|
||||
### LongMemEval
|
||||
|
||||
Tests long-term memory across different categories.
|
||||
|
||||
```bash
|
||||
# Run from project root
|
||||
./scripts/benchmarks/run-longmemeval.sh
|
||||
|
||||
# With options
|
||||
./scripts/benchmarks/run-longmemeval.sh --max-instances 50
|
||||
./scripts/benchmarks/run-longmemeval.sh --category single-session-user
|
||||
./scripts/benchmarks/run-longmemeval.sh --parallel 4 # Faster evaluation
|
||||
```
|
||||
|
||||
**Options:**
|
||||
- `--max-instances N` - Limit total questions
|
||||
- `--max-instances-per-category N` - Limit per category
|
||||
- `--skip-ingestion` - Skip data ingestion
|
||||
- `--category NAME` - Filter by category:
|
||||
- `single-session-user`
|
||||
- `multi-session`
|
||||
- `single-session-preference`
|
||||
- `temporal-reasoning`
|
||||
- `knowledge-update`
|
||||
- `single-session-assistant`
|
||||
- `--parallel N` - Parallel instances (default: 1)
|
||||
- `--only-failed` - Retry failed questions
|
||||
- `--fill` - Resume interrupted runs
|
||||
|
||||
## Visualizer
|
||||
|
||||
View benchmark results in a web UI:
|
||||
|
||||
```bash
|
||||
./scripts/benchmarks/start-visualizer.sh
|
||||
# Opens at http://localhost:8001
|
||||
```
|
||||
|
||||
## Results
|
||||
|
||||
Results are saved in JSON format in each benchmark's `results/` directory.
|
||||
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
||||
|
||||
[project]
|
||||
name = "hindsight-dev"
|
||||
version = "0.1.6"
|
||||
version = "0.1.8"
|
||||
description = "Development utilities for Hindsight"
|
||||
requires-python = ">=3.11"
|
||||
dependencies = [
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
---
|
||||
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
|
||||
|
||||
<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>
|
||||
|
||||
## Store with Context
|
||||
|
||||
<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>
|
||||
|
||||
## Batch Ingestion
|
||||
|
||||
<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>
|
||||
|
||||
## Async Ingestion
|
||||
|
||||
<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>
|
||||
@@ -1,6 +1,10 @@
|
||||
# Installation
|
||||
|
||||
Hindsight can be deployed in three ways depending on your infrastructure and requirements.
|
||||
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
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ This is ideal for:
|
||||
### With uvx (recommended)
|
||||
|
||||
```bash
|
||||
uvx hindsight-api@latest hindsight-local-mcp
|
||||
uvx --from hindsight-api hindsight-local-mcp
|
||||
```
|
||||
|
||||
### With pip
|
||||
@@ -35,7 +35,7 @@ Add to your Claude Code MCP settings (`~/.claude/claude_desktop_config.json`):
|
||||
"mcpServers": {
|
||||
"hindsight": {
|
||||
"command": "uvx",
|
||||
"args": ["hindsight-api@latest", "hindsight-local-mcp"],
|
||||
"args": ["--from", "hindsight-api", "hindsight-local-mcp"],
|
||||
"env": {
|
||||
"HINDSIGHT_API_LLM_API_KEY": "your-openai-key"
|
||||
}
|
||||
@@ -53,7 +53,7 @@ By default, memories are stored in a bank called `mcp`. To use a different bank:
|
||||
"mcpServers": {
|
||||
"hindsight": {
|
||||
"command": "uvx",
|
||||
"args": ["hindsight-api@latest", "hindsight-local-mcp"],
|
||||
"args": ["--from", "hindsight-api", "hindsight-local-mcp"],
|
||||
"env": {
|
||||
"HINDSIGHT_API_LLM_API_KEY": "your-openai-key",
|
||||
"HINDSIGHT_API_MCP_LOCAL_BANK_ID": "my-personal-memory"
|
||||
|
||||
@@ -174,6 +174,12 @@ const config: Config = {
|
||||
label: 'Changelog',
|
||||
className: 'navbar-item-changelog',
|
||||
},
|
||||
{
|
||||
href: 'https://vectorize.io/hindsight/cloud',
|
||||
position: 'right',
|
||||
label: 'Hindsight Cloud',
|
||||
className: 'navbar-item-cloud',
|
||||
},
|
||||
{
|
||||
href: 'https://github.com/vectorize-io/hindsight',
|
||||
position: 'right',
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
# API Documentation Examples
|
||||
|
||||
This directory contains runnable example scripts that serve as the source of truth for code samples in the documentation.
|
||||
|
||||
## How It Works
|
||||
|
||||
1. **Scripts are runnable** - Each file can be executed as a smoke test
|
||||
2. **Markers define sections** - Code between `# [docs:section-name]` and `# [/docs:section-name]` markers is extracted
|
||||
3. **Docs import at build time** - MDX files use `raw-loader` to import scripts, then `CodeSnippet` extracts marked sections
|
||||
|
||||
## File Structure
|
||||
|
||||
| File | Documentation | Description |
|
||||
|------|---------------|-------------|
|
||||
| `quickstart.py/mjs/sh` | quickstart.md | Getting started examples |
|
||||
| `retain.py/mjs/sh` | retain.md | Memory ingestion examples |
|
||||
| `recall.py/mjs/sh` | recall.md | Memory retrieval examples |
|
||||
| `reflect.py/mjs/sh` | reflect.md | AI reflection examples |
|
||||
| `memory-banks.py/mjs` | memory-banks.md | Bank management examples |
|
||||
| `documents.py/mjs` | documents.md | Document CRUD examples |
|
||||
| `opinions.py` | opinions.md | Opinion management examples |
|
||||
| `main-methods.py` | main-methods.md | Core method examples |
|
||||
| `cli-reference.sh` | cli.md | CLI command examples |
|
||||
|
||||
## Running Examples
|
||||
|
||||
```bash
|
||||
# Run all Python examples
|
||||
for f in *.py; do python "$f"; done
|
||||
|
||||
# Run all Node.js examples
|
||||
for f in *.mjs; do node "$f"; done
|
||||
|
||||
# Run all CLI examples
|
||||
for f in *.sh; do bash "$f"; done
|
||||
```
|
||||
|
||||
Requires a running Hindsight server at `http://localhost:8888` (or set `HINDSIGHT_API_URL`).
|
||||
|
||||
## What's NOT Covered
|
||||
|
||||
### 1. OpenAPI Auto-Generated Docs (`/api-reference/*`)
|
||||
|
||||
These pages are generated directly from the OpenAPI specification. The spec itself is the source of truth, and the generated docs reflect it automatically. No manual code examples to validate.
|
||||
|
||||
### 2. Interactive CLI Commands
|
||||
|
||||
| Command | Reason |
|
||||
|---------|--------|
|
||||
| `hindsight configure` | Requires interactive user input (prompts for API URL, credentials) |
|
||||
| `hindsight configure --show` | Displays sensitive configuration, not suitable for automated tests |
|
||||
|
||||
### 3. Installation/Setup Instructions
|
||||
|
||||
Documentation sections covering `pip install`, `npm install`, or system setup are instructions, not executable code samples. These are validated by the CI environment setup itself.
|
||||
|
||||
### 4. Error Handling Examples
|
||||
|
||||
Some docs show error responses (e.g., "what happens when bank doesn't exist"). These require intentionally broken states that would fail smoke tests. Error behavior is covered by unit tests instead.
|
||||
|
||||
## Adding New Examples
|
||||
|
||||
1. Create or edit the appropriate script file
|
||||
2. Add markers around the new code section:
|
||||
```python
|
||||
# [docs:my-new-section]
|
||||
client.some_method(...)
|
||||
# [/docs:my-new-section]
|
||||
```
|
||||
3. Reference in the MDX file:
|
||||
```mdx
|
||||
import myScript from '!!raw-loader!@site/examples/api/my-script.py';
|
||||
<CodeSnippet code={myScript} section="my-new-section" language="python" />
|
||||
```
|
||||
4. Run the script locally to verify it works
|
||||
|
||||
## Marker Format
|
||||
|
||||
- **Python/Bash**: `# [docs:section-name]` / `# [/docs:section-name]`
|
||||
- **JavaScript**: `// [docs:section-name]` / `// [/docs:section-name]`
|
||||
|
||||
Section names should be kebab-case and descriptive (e.g., `retain-with-context`, `recall-basic`).
|
||||
Executable
+209
@@ -0,0 +1,209 @@
|
||||
#!/bin/bash
|
||||
# CLI Reference examples for Hindsight
|
||||
# Tests all documented CLI commands and flags
|
||||
# Run: bash examples/api/cli-reference.sh
|
||||
|
||||
set -e
|
||||
|
||||
HINDSIGHT_URL="${HINDSIGHT_API_URL:-http://localhost:8888}"
|
||||
BANK_ID="cli-test-bank"
|
||||
DOC_ID="test-document-001"
|
||||
|
||||
# =============================================================================
|
||||
# Setup
|
||||
# =============================================================================
|
||||
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 and Bob work on machine learning projects"
|
||||
|
||||
# Wait a moment for processing
|
||||
sleep 2
|
||||
|
||||
# =============================================================================
|
||||
# Configuration (cli.md - Configuration section)
|
||||
# =============================================================================
|
||||
|
||||
# [docs:cli-configure]
|
||||
hindsight configure --api-url http://localhost:8888
|
||||
# [/docs:cli-configure]
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Core Memory Commands (cli.md - Core Commands section)
|
||||
# =============================================================================
|
||||
|
||||
# [docs:cli-retain-basic]
|
||||
hindsight memory retain $BANK_ID "Alice works at Google as a software engineer"
|
||||
# [/docs:cli-retain-basic]
|
||||
|
||||
|
||||
# [docs:cli-retain-context]
|
||||
hindsight memory retain $BANK_ID "Bob loves hiking" --context "hobby discussion"
|
||||
# [/docs:cli-retain-context]
|
||||
|
||||
|
||||
# [docs:cli-retain-async]
|
||||
hindsight memory retain $BANK_ID "Meeting notes" --async
|
||||
# [/docs:cli-retain-async]
|
||||
|
||||
|
||||
# [docs:cli-recall-basic]
|
||||
hindsight memory recall $BANK_ID "What does Alice do?"
|
||||
# [/docs:cli-recall-basic]
|
||||
|
||||
|
||||
# [docs:cli-recall-options]
|
||||
hindsight memory recall $BANK_ID "hiking recommendations" \
|
||||
--budget high \
|
||||
--max-tokens 8192
|
||||
# [/docs:cli-recall-options]
|
||||
|
||||
|
||||
# [docs:cli-recall-fact-type]
|
||||
hindsight memory recall $BANK_ID "query" --fact-type world,opinion
|
||||
# [/docs:cli-recall-fact-type]
|
||||
|
||||
|
||||
# [docs:cli-recall-trace]
|
||||
hindsight memory recall $BANK_ID "query" --trace
|
||||
# [/docs:cli-recall-trace]
|
||||
|
||||
|
||||
# [docs:cli-reflect-basic]
|
||||
hindsight memory reflect $BANK_ID "What do you know about Alice?"
|
||||
# [/docs:cli-reflect-basic]
|
||||
|
||||
|
||||
# [docs:cli-reflect-context]
|
||||
hindsight memory reflect $BANK_ID "Should I learn Python?" --context "career advice"
|
||||
# [/docs:cli-reflect-context]
|
||||
|
||||
|
||||
# [docs:cli-reflect-budget]
|
||||
hindsight memory reflect $BANK_ID "Summarize my week" --budget high
|
||||
# [/docs:cli-reflect-budget]
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Bank Management (cli.md - Bank Management section)
|
||||
# =============================================================================
|
||||
|
||||
# [docs:cli-bank-list]
|
||||
hindsight bank list
|
||||
# [/docs:cli-bank-list]
|
||||
|
||||
|
||||
# [docs:cli-bank-profile]
|
||||
hindsight bank profile $BANK_ID
|
||||
# [/docs:cli-bank-profile]
|
||||
|
||||
|
||||
# [docs:cli-bank-stats]
|
||||
hindsight bank stats $BANK_ID
|
||||
# [/docs:cli-bank-stats]
|
||||
|
||||
|
||||
# [docs:cli-bank-name]
|
||||
hindsight bank name $BANK_ID "My Assistant"
|
||||
# [/docs:cli-bank-name]
|
||||
|
||||
|
||||
# [docs:cli-bank-background]
|
||||
hindsight bank background $BANK_ID "I am a helpful AI assistant interested in technology"
|
||||
# [/docs:cli-bank-background]
|
||||
|
||||
|
||||
# [docs:cli-bank-background-no-disposition]
|
||||
hindsight bank background $BANK_ID "Background text" --no-update-disposition
|
||||
# [/docs:cli-bank-background-no-disposition]
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Document Management (cli.md - Document Management section)
|
||||
# =============================================================================
|
||||
|
||||
# [docs:cli-document-list]
|
||||
hindsight document list $BANK_ID
|
||||
# [/docs:cli-document-list]
|
||||
|
||||
|
||||
# [docs:cli-document-get]
|
||||
hindsight document get $BANK_ID $DOC_ID
|
||||
# [/docs:cli-document-get]
|
||||
|
||||
|
||||
# [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]
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Entity Management (cli.md - Entity Management section)
|
||||
# =============================================================================
|
||||
|
||||
# [docs:cli-entity-list]
|
||||
hindsight entity list $BANK_ID
|
||||
# [/docs:cli-entity-list]
|
||||
|
||||
|
||||
# Get an entity ID from the list output and use it
|
||||
ENTITY_ID=$(hindsight entity list $BANK_ID -o json 2>/dev/null | grep -o '"id":"[^"]*"' | head -1 | cut -d'"' -f4 || echo "")
|
||||
|
||||
if [ -n "$ENTITY_ID" ]; then
|
||||
# [docs:cli-entity-get]
|
||||
hindsight entity get $BANK_ID $ENTITY_ID
|
||||
# [/docs:cli-entity-get]
|
||||
|
||||
# [docs:cli-entity-regenerate]
|
||||
hindsight entity regenerate $BANK_ID $ENTITY_ID
|
||||
# [/docs:cli-entity-regenerate]
|
||||
else
|
||||
echo "No entities found yet, skipping entity get/regenerate"
|
||||
fi
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Output Formats (cli.md - Output Formats section)
|
||||
# =============================================================================
|
||||
|
||||
# [docs:cli-output-json]
|
||||
hindsight memory recall $BANK_ID "query" -o json
|
||||
# [/docs:cli-output-json]
|
||||
|
||||
|
||||
# [docs:cli-output-yaml]
|
||||
hindsight memory recall $BANK_ID "query" -o yaml
|
||||
# [/docs:cli-output-yaml]
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Global Options (cli.md - Global Options section)
|
||||
# =============================================================================
|
||||
|
||||
# [docs:cli-verbose]
|
||||
hindsight memory recall $BANK_ID "Alice" -v
|
||||
# [/docs:cli-verbose]
|
||||
|
||||
|
||||
# [docs:cli-help]
|
||||
hindsight --help
|
||||
# [/docs:cli-help]
|
||||
|
||||
|
||||
# [docs:cli-version]
|
||||
hindsight --version
|
||||
# [/docs:cli-version]
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Cleanup
|
||||
# =============================================================================
|
||||
curl -s -X DELETE "${HINDSIGHT_URL}/v1/default/banks/${BANK_ID}" > /dev/null
|
||||
|
||||
echo "cli-reference.sh: All examples passed"
|
||||
@@ -0,0 +1,68 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Documents API examples for Hindsight (Node.js)
|
||||
* Run: node examples/api/documents.mjs
|
||||
*/
|
||||
import { HindsightClient, sdk, createClient, createConfig } 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
|
||||
// =============================================================================
|
||||
|
||||
// [docs:document-retain]
|
||||
// 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' });
|
||||
// [/docs:document-retain]
|
||||
|
||||
|
||||
// [docs:document-update]
|
||||
// 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'
|
||||
});
|
||||
// [/docs:document-update]
|
||||
|
||||
|
||||
// [docs:document-get]
|
||||
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}`);
|
||||
// [/docs:document-get]
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// Cleanup (not shown in docs)
|
||||
// =============================================================================
|
||||
await fetch(`${HINDSIGHT_URL}/v1/default/banks/my-bank`, { method: 'DELETE' });
|
||||
|
||||
console.log('documents.mjs: All examples passed');
|
||||
@@ -0,0 +1,90 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Documents API examples for Hindsight.
|
||||
Run: python examples/api/documents.py
|
||||
"""
|
||||
import os
|
||||
import requests
|
||||
|
||||
HINDSIGHT_URL = os.getenv("HINDSIGHT_API_URL", "http://localhost:8888")
|
||||
|
||||
# =============================================================================
|
||||
# Setup (not shown in docs)
|
||||
# =============================================================================
|
||||
from hindsight_client import Hindsight
|
||||
|
||||
client = Hindsight(base_url=HINDSIGHT_URL)
|
||||
|
||||
# =============================================================================
|
||||
# Doc Examples
|
||||
# =============================================================================
|
||||
|
||||
# [docs:document-retain]
|
||||
# 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"
|
||||
)
|
||||
# [/docs:document-retain]
|
||||
|
||||
|
||||
# [docs:document-update]
|
||||
# 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"
|
||||
)
|
||||
# [/docs:document-update]
|
||||
|
||||
|
||||
# [docs:document-get]
|
||||
import asyncio
|
||||
from hindsight_client_api import ApiClient, Configuration
|
||||
from hindsight_client_api.api import DefaultApi
|
||||
|
||||
async def get_document_example():
|
||||
config = Configuration(host="http://localhost:8888")
|
||||
api_client = ApiClient(config)
|
||||
api = DefaultApi(api_client)
|
||||
|
||||
# Get document to expand context from recall results
|
||||
doc = await 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}")
|
||||
|
||||
asyncio.run(get_document_example())
|
||||
# [/docs:document-get]
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Cleanup (not shown in docs)
|
||||
# =============================================================================
|
||||
requests.delete(f"{HINDSIGHT_URL}/v1/default/banks/my-bank")
|
||||
|
||||
print("documents.py: All examples passed")
|
||||
@@ -0,0 +1,125 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Main Methods overview examples for Hindsight.
|
||||
Run: python examples/api/main-methods.py
|
||||
"""
|
||||
import os
|
||||
import requests
|
||||
|
||||
HINDSIGHT_URL = os.getenv("HINDSIGHT_API_URL", "http://localhost:8888")
|
||||
|
||||
# =============================================================================
|
||||
# Setup (not shown in docs)
|
||||
# =============================================================================
|
||||
from hindsight_client import Hindsight
|
||||
|
||||
client = Hindsight(base_url=HINDSIGHT_URL)
|
||||
|
||||
# =============================================================================
|
||||
# Doc Examples - Retain Section
|
||||
# =============================================================================
|
||||
|
||||
# [docs:main-retain]
|
||||
# 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",
|
||||
items=[
|
||||
{"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
|
||||
results = client.recall(
|
||||
bank_id="my-bank",
|
||||
query="What does Alice do at Google?"
|
||||
)
|
||||
|
||||
for result in results.results:
|
||||
print(f"- {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
|
||||
types=["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 or []:
|
||||
print(f"Entity: {entity.name}")
|
||||
print(f"Observations: {entity.observations}")
|
||||
# [/docs:main-recall]
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Doc Examples - Reflect Section
|
||||
# =============================================================================
|
||||
|
||||
# [docs:main-reflect]
|
||||
# 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 or []), "facts")
|
||||
|
||||
# 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
|
||||
)
|
||||
|
||||
# See which facts influenced the response
|
||||
for fact in response.based_on or []:
|
||||
print(f"- {fact.text}")
|
||||
# [/docs:main-reflect]
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Cleanup (not shown in docs)
|
||||
# =============================================================================
|
||||
requests.delete(f"{HINDSIGHT_URL}/v1/default/banks/my-bank")
|
||||
|
||||
print("main-methods.py: All examples passed")
|
||||
@@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Memory Banks API examples for Hindsight (Node.js)
|
||||
* Run: node examples/api/memory-banks.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
|
||||
// =============================================================================
|
||||
|
||||
// [docs:create-bank]
|
||||
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
|
||||
}
|
||||
});
|
||||
// [/docs:create-bank]
|
||||
|
||||
|
||||
// [docs:bank-background]
|
||||
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.`
|
||||
});
|
||||
// [/docs:bank-background]
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// Cleanup (not shown in docs)
|
||||
// =============================================================================
|
||||
await fetch(`${HINDSIGHT_URL}/v1/default/banks/my-bank`, { method: 'DELETE' });
|
||||
await fetch(`${HINDSIGHT_URL}/v1/default/banks/financial-advisor`, { method: 'DELETE' });
|
||||
|
||||
console.log('memory-banks.mjs: All examples passed');
|
||||
@@ -0,0 +1,52 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Memory Banks API examples for Hindsight.
|
||||
Run: python examples/api/memory-banks.py
|
||||
"""
|
||||
import os
|
||||
import requests
|
||||
|
||||
HINDSIGHT_URL = os.getenv("HINDSIGHT_API_URL", "http://localhost:8888")
|
||||
|
||||
# =============================================================================
|
||||
# Setup (not shown in docs)
|
||||
# =============================================================================
|
||||
from hindsight_client import Hindsight
|
||||
|
||||
client = Hindsight(base_url=HINDSIGHT_URL)
|
||||
|
||||
# =============================================================================
|
||||
# Doc Examples
|
||||
# =============================================================================
|
||||
|
||||
# [docs:create-bank]
|
||||
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
|
||||
}
|
||||
)
|
||||
# [/docs:create-bank]
|
||||
|
||||
|
||||
# [docs:bank-background]
|
||||
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."""
|
||||
)
|
||||
# [/docs:bank-background]
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Cleanup (not shown in docs)
|
||||
# =============================================================================
|
||||
requests.delete(f"{HINDSIGHT_URL}/v1/default/banks/my-bank")
|
||||
requests.delete(f"{HINDSIGHT_URL}/v1/default/banks/financial-advisor")
|
||||
|
||||
print("memory-banks.py: All examples passed")
|
||||
@@ -0,0 +1,104 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Opinions API examples for Hindsight.
|
||||
Run: python examples/api/opinions.py
|
||||
"""
|
||||
import os
|
||||
import requests
|
||||
|
||||
HINDSIGHT_URL = os.getenv("HINDSIGHT_API_URL", "http://localhost:8888")
|
||||
|
||||
# =============================================================================
|
||||
# Setup (not shown in docs)
|
||||
# =============================================================================
|
||||
from hindsight_client import Hindsight
|
||||
|
||||
client = Hindsight(base_url=HINDSIGHT_URL)
|
||||
|
||||
# Seed some data about programming languages
|
||||
client.retain(bank_id="my-bank", content="Python is widely used for data science and machine learning")
|
||||
client.retain(bank_id="my-bank", content="Functional programming emphasizes immutability and pure functions")
|
||||
client.retain(bank_id="my-bank", content="Rust has better memory safety than C++")
|
||||
client.retain(bank_id="my-bank", content="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
|
||||
answer = client.reflect(
|
||||
bank_id="my-bank",
|
||||
query="What do you think about functional programming?"
|
||||
)
|
||||
|
||||
print(answer.text)
|
||||
# [/docs:opinion-form]
|
||||
|
||||
|
||||
# [docs:opinion-search]
|
||||
# Search for facts about a topic
|
||||
results = client.recall(
|
||||
bank_id="my-bank",
|
||||
query="programming languages"
|
||||
)
|
||||
|
||||
for result in results.results:
|
||||
print(f"- {result.text}")
|
||||
# [/docs:opinion-search]
|
||||
|
||||
|
||||
# [docs:opinion-disposition]
|
||||
# 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 - different dispositions lead to different responses
|
||||
q = "Should we rewrite our C++ codebase in Rust?"
|
||||
|
||||
answer1 = client.reflect(bank_id="open-minded", query=q)
|
||||
print("Open-minded response:", answer1.text[:100], "...")
|
||||
|
||||
answer2 = client.reflect(bank_id="conservative", query=q)
|
||||
print("Conservative response:", answer2.text[:100], "...")
|
||||
# [/docs:opinion-disposition]
|
||||
|
||||
|
||||
# [docs:opinion-in-reflect]
|
||||
answer = client.reflect(bank_id="my-bank", query="What language should I learn?")
|
||||
|
||||
print("Response:", answer.text)
|
||||
|
||||
# See which facts influenced the response
|
||||
if answer.based_on:
|
||||
print("\nBased on these facts:")
|
||||
for fact in answer.based_on:
|
||||
print(f" - {fact.text}")
|
||||
# [/docs:opinion-in-reflect]
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Cleanup (not shown in docs)
|
||||
# =============================================================================
|
||||
requests.delete(f"{HINDSIGHT_URL}/v1/default/banks/my-bank")
|
||||
requests.delete(f"{HINDSIGHT_URL}/v1/default/banks/open-minded")
|
||||
requests.delete(f"{HINDSIGHT_URL}/v1/default/banks/conservative")
|
||||
|
||||
print("opinions.py: All examples passed")
|
||||
@@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Quickstart examples for Hindsight API (Node.js)
|
||||
* Run: node examples/api/quickstart.mjs
|
||||
*/
|
||||
|
||||
const HINDSIGHT_URL = process.env.HINDSIGHT_API_URL || 'http://localhost:8888';
|
||||
|
||||
// =============================================================================
|
||||
// Doc Examples
|
||||
// =============================================================================
|
||||
|
||||
// [docs:quickstart-full]
|
||||
import { HindsightClient } from '@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');
|
||||
// [/docs:quickstart-full]
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// Cleanup (not shown in docs)
|
||||
// =============================================================================
|
||||
await fetch(`${HINDSIGHT_URL}/v1/default/banks/my-bank`, { method: 'DELETE' });
|
||||
|
||||
console.log('quickstart.mjs: All examples passed');
|
||||
@@ -0,0 +1,36 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Quickstart examples for Hindsight API.
|
||||
Run: python examples/api/quickstart.py
|
||||
"""
|
||||
import os
|
||||
import requests
|
||||
|
||||
HINDSIGHT_URL = os.getenv("HINDSIGHT_API_URL", "http://localhost:8888")
|
||||
|
||||
# =============================================================================
|
||||
# Doc Examples
|
||||
# =============================================================================
|
||||
|
||||
# [docs:quickstart-full]
|
||||
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")
|
||||
# [/docs:quickstart-full]
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Cleanup (not shown in docs)
|
||||
# =============================================================================
|
||||
requests.delete(f"{HINDSIGHT_URL}/v1/default/banks/my-bank")
|
||||
|
||||
print("quickstart.py: All examples passed")
|
||||
Executable
+30
@@ -0,0 +1,30 @@
|
||||
#!/bin/bash
|
||||
# Quickstart examples for Hindsight CLI
|
||||
# Run: bash examples/api/quickstart.sh
|
||||
|
||||
set -e
|
||||
|
||||
HINDSIGHT_URL="${HINDSIGHT_API_URL:-http://localhost:8888}"
|
||||
|
||||
# =============================================================================
|
||||
# Doc Examples
|
||||
# =============================================================================
|
||||
|
||||
# [docs:quickstart-full]
|
||||
# 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"
|
||||
# [/docs:quickstart-full]
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Cleanup (not shown in docs)
|
||||
# =============================================================================
|
||||
curl -s -X DELETE "${HINDSIGHT_URL}/v1/default/banks/my-bank" > /dev/null
|
||||
|
||||
echo "quickstart.sh: All examples passed"
|
||||
@@ -0,0 +1,61 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Recall API examples for Hindsight (Node.js)
|
||||
* Run: node examples/api/recall.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 for recall examples
|
||||
await client.retain('my-bank', 'Alice works at Google as a software engineer');
|
||||
await client.retain('my-bank', 'Alice loves hiking on weekends');
|
||||
await client.retain('my-bank', 'Bob is a data scientist who works with Alice');
|
||||
|
||||
// =============================================================================
|
||||
// Doc Examples
|
||||
// =============================================================================
|
||||
|
||||
// [docs:recall-basic]
|
||||
const response = await client.recall('my-bank', 'What does Alice do?');
|
||||
for (const r of response.results) {
|
||||
console.log(`${r.text} (score: ${r.weight})`);
|
||||
}
|
||||
// [/docs:recall-basic]
|
||||
|
||||
|
||||
// [docs:recall-with-options]
|
||||
const detailedResponse = await client.recall('my-bank', 'What does Alice do?', {
|
||||
types: ['world', 'experience'],
|
||||
budget: 'high',
|
||||
maxTokens: 8000,
|
||||
trace: true
|
||||
});
|
||||
|
||||
// Access results
|
||||
for (const r of detailedResponse.results) {
|
||||
console.log(`${r.text} (score: ${r.weight})`);
|
||||
}
|
||||
// [/docs:recall-with-options]
|
||||
|
||||
|
||||
// [docs:recall-budget-levels]
|
||||
// Quick lookup
|
||||
const quickResults = await client.recall('my-bank', "Alice's email", { budget: 'low' });
|
||||
|
||||
// Deep exploration
|
||||
const deepResults = await client.recall('my-bank', 'How are Alice and Bob connected?', { budget: 'high' });
|
||||
// [/docs:recall-budget-levels]
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// Cleanup (not shown in docs)
|
||||
// =============================================================================
|
||||
await fetch(`${HINDSIGHT_URL}/v1/default/banks/my-bank`, { method: 'DELETE' });
|
||||
|
||||
console.log('recall.mjs: All examples passed');
|
||||
@@ -0,0 +1,124 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Recall API examples for Hindsight.
|
||||
Run: python examples/api/recall.py
|
||||
"""
|
||||
import os
|
||||
import requests
|
||||
|
||||
HINDSIGHT_URL = os.getenv("HINDSIGHT_API_URL", "http://localhost:8888")
|
||||
|
||||
# =============================================================================
|
||||
# Setup (not shown in docs)
|
||||
# =============================================================================
|
||||
from hindsight_client import Hindsight
|
||||
|
||||
client = Hindsight(base_url=HINDSIGHT_URL)
|
||||
|
||||
# Seed some data for recall examples
|
||||
client.retain(bank_id="my-bank", content="Alice works at Google as a software engineer")
|
||||
client.retain(bank_id="my-bank", content="Alice loves hiking on weekends")
|
||||
client.retain(bank_id="my-bank", content="Bob is a data scientist who works with Alice")
|
||||
|
||||
# =============================================================================
|
||||
# Doc Examples
|
||||
# =============================================================================
|
||||
|
||||
# [docs:recall-basic]
|
||||
response = client.recall(bank_id="my-bank", query="What does Alice do?")
|
||||
for r in response.results:
|
||||
print(f"- {r.text}")
|
||||
# [/docs:recall-basic]
|
||||
|
||||
|
||||
# [docs:recall-with-options]
|
||||
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}")
|
||||
|
||||
# Access entity observations (if include_entities=True)
|
||||
if response.entities:
|
||||
for entity_id, entity in response.entities.items():
|
||||
print(f"Entity: {entity.canonical_name}")
|
||||
# [/docs:recall-with-options]
|
||||
|
||||
|
||||
# [docs:recall-world-only]
|
||||
# Only world facts (objective information)
|
||||
world_facts = client.recall(
|
||||
bank_id="my-bank",
|
||||
query="Where does Alice work?",
|
||||
types=["world"]
|
||||
)
|
||||
# [/docs:recall-world-only]
|
||||
|
||||
|
||||
# [docs:recall-experience-only]
|
||||
# Only experience (conversations and events)
|
||||
experience = client.recall(
|
||||
bank_id="my-bank",
|
||||
query="What have I recommended?",
|
||||
types=["experience"]
|
||||
)
|
||||
# [/docs:recall-experience-only]
|
||||
|
||||
|
||||
# [docs:recall-opinions-only]
|
||||
# Only opinions (formed beliefs)
|
||||
opinions = client.recall(
|
||||
bank_id="my-bank",
|
||||
query="What do I think about Python?",
|
||||
types=["opinion"]
|
||||
)
|
||||
# [/docs:recall-opinions-only]
|
||||
|
||||
|
||||
# [docs:recall-token-budget]
|
||||
# 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)
|
||||
# [/docs:recall-token-budget]
|
||||
|
||||
|
||||
# [docs:recall-include-entities]
|
||||
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 []
|
||||
# [/docs:recall-include-entities]
|
||||
|
||||
|
||||
# [docs:recall-budget-levels]
|
||||
# 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")
|
||||
# [/docs:recall-budget-levels]
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Cleanup (not shown in docs)
|
||||
# =============================================================================
|
||||
requests.delete(f"{HINDSIGHT_URL}/v1/default/banks/my-bank")
|
||||
|
||||
print("recall.py: All examples passed")
|
||||
Executable
+46
@@ -0,0 +1,46 @@
|
||||
#!/bin/bash
|
||||
# Recall API examples for Hindsight CLI
|
||||
# Run: bash examples/api/recall.sh
|
||||
|
||||
set -e
|
||||
|
||||
HINDSIGHT_URL="${HINDSIGHT_API_URL:-http://localhost:8888}"
|
||||
|
||||
# =============================================================================
|
||||
# Setup (not shown in docs)
|
||||
# =============================================================================
|
||||
hindsight memory retain my-bank "Alice works at Google as a software engineer"
|
||||
hindsight memory retain my-bank "Alice loves hiking on weekends"
|
||||
|
||||
# =============================================================================
|
||||
# Doc Examples
|
||||
# =============================================================================
|
||||
|
||||
# [docs:recall-basic]
|
||||
hindsight memory recall my-bank "What does Alice do?"
|
||||
# [/docs:recall-basic]
|
||||
|
||||
|
||||
# [docs:recall-with-options]
|
||||
hindsight memory recall my-bank "hiking recommendations" \
|
||||
--budget high \
|
||||
--max-tokens 8192
|
||||
# [/docs:recall-with-options]
|
||||
|
||||
|
||||
# [docs:recall-fact-type]
|
||||
hindsight memory recall my-bank "query" --fact-type world,opinion
|
||||
# [/docs:recall-fact-type]
|
||||
|
||||
|
||||
# [docs:recall-trace]
|
||||
hindsight memory recall my-bank "query" --trace
|
||||
# [/docs:recall-trace]
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Cleanup (not shown in docs)
|
||||
# =============================================================================
|
||||
curl -s -X DELETE "${HINDSIGHT_URL}/v1/default/banks/my-bank" > /dev/null
|
||||
|
||||
echo "recall.sh: All examples passed"
|
||||
@@ -0,0 +1,78 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Reflect API examples for Hindsight (Node.js)
|
||||
* Run: node examples/api/reflect.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 for reflect examples
|
||||
await client.retain('my-bank', 'Alice works at Google as a software engineer');
|
||||
await client.retain('my-bank', 'Alice has been working there for 5 years');
|
||||
await client.retain('my-bank', 'Alice recently got promoted to senior engineer');
|
||||
|
||||
// =============================================================================
|
||||
// Doc Examples
|
||||
// =============================================================================
|
||||
|
||||
// [docs:reflect-basic]
|
||||
await client.reflect('my-bank', 'What should I know about Alice?');
|
||||
// [/docs:reflect-basic]
|
||||
|
||||
|
||||
// [docs:reflect-with-params]
|
||||
const response = await client.reflect('my-bank', 'What do you think about remote work?', {
|
||||
budget: 'mid',
|
||||
context: "We're considering a hybrid work policy"
|
||||
});
|
||||
// [/docs:reflect-with-params]
|
||||
|
||||
|
||||
// [docs:reflect-with-context]
|
||||
// Context helps the LLM understand the current situation
|
||||
const contextResponse = await client.reflect('my-bank', 'What do you think about the proposal?', {
|
||||
context: "We're in a budget review meeting discussing Q4 spending"
|
||||
});
|
||||
// [/docs:reflect-with-context]
|
||||
|
||||
|
||||
// [docs:reflect-disposition]
|
||||
// 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 advisorResponse = await client.reflect('cautious-advisor', 'Should I invest in crypto?');
|
||||
// [/docs:reflect-disposition]
|
||||
|
||||
|
||||
// [docs:reflect-sources]
|
||||
const sourcesResponse = await client.reflect('my-bank', 'Tell me about Alice');
|
||||
|
||||
console.log('Response:', sourcesResponse.text);
|
||||
console.log('\nBased on:');
|
||||
for (const fact of sourcesResponse.based_on || []) {
|
||||
console.log(` - [${fact.type}] ${fact.text}`);
|
||||
}
|
||||
// [/docs:reflect-sources]
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// Cleanup (not shown in docs)
|
||||
// =============================================================================
|
||||
await fetch(`${HINDSIGHT_URL}/v1/default/banks/my-bank`, { method: 'DELETE' });
|
||||
await fetch(`${HINDSIGHT_URL}/v1/default/banks/cautious-advisor`, { method: 'DELETE' });
|
||||
|
||||
console.log('reflect.mjs: All examples passed');
|
||||
@@ -0,0 +1,89 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Reflect API examples for Hindsight.
|
||||
Run: python examples/api/reflect.py
|
||||
"""
|
||||
import os
|
||||
import requests
|
||||
|
||||
HINDSIGHT_URL = os.getenv("HINDSIGHT_API_URL", "http://localhost:8888")
|
||||
|
||||
# =============================================================================
|
||||
# Setup (not shown in docs)
|
||||
# =============================================================================
|
||||
from hindsight_client import Hindsight
|
||||
|
||||
client = Hindsight(base_url=HINDSIGHT_URL)
|
||||
|
||||
# Seed some data for reflect examples
|
||||
client.retain(bank_id="my-bank", content="Alice works at Google as a software engineer")
|
||||
client.retain(bank_id="my-bank", content="Alice has been working there for 5 years")
|
||||
client.retain(bank_id="my-bank", content="Alice recently got promoted to senior engineer")
|
||||
|
||||
# =============================================================================
|
||||
# Doc Examples
|
||||
# =============================================================================
|
||||
|
||||
# [docs:reflect-basic]
|
||||
client.reflect(bank_id="my-bank", query="What should I know about Alice?")
|
||||
# [/docs:reflect-basic]
|
||||
|
||||
|
||||
# [docs:reflect-with-params]
|
||||
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"
|
||||
)
|
||||
# [/docs:reflect-with-params]
|
||||
|
||||
|
||||
# [docs:reflect-with-context]
|
||||
# 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"
|
||||
)
|
||||
# [/docs:reflect-with-context]
|
||||
|
||||
|
||||
# [docs:reflect-disposition]
|
||||
# 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
|
||||
# [/docs:reflect-disposition]
|
||||
|
||||
|
||||
# [docs:reflect-sources]
|
||||
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}")
|
||||
# [/docs:reflect-sources]
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Cleanup (not shown in docs)
|
||||
# =============================================================================
|
||||
requests.delete(f"{HINDSIGHT_URL}/v1/default/banks/my-bank")
|
||||
requests.delete(f"{HINDSIGHT_URL}/v1/default/banks/cautious-advisor")
|
||||
|
||||
print("reflect.py: All examples passed")
|
||||
Executable
+39
@@ -0,0 +1,39 @@
|
||||
#!/bin/bash
|
||||
# Reflect API examples for Hindsight CLI
|
||||
# Run: bash examples/api/reflect.sh
|
||||
|
||||
set -e
|
||||
|
||||
HINDSIGHT_URL="${HINDSIGHT_API_URL:-http://localhost:8888}"
|
||||
|
||||
# =============================================================================
|
||||
# Setup (not shown in docs)
|
||||
# =============================================================================
|
||||
hindsight memory retain my-bank "Alice works at Google as a software engineer"
|
||||
hindsight memory retain my-bank "Alice has been working there for 5 years"
|
||||
|
||||
# =============================================================================
|
||||
# Doc Examples
|
||||
# =============================================================================
|
||||
|
||||
# [docs:reflect-basic]
|
||||
hindsight memory reflect my-bank "What do you know about Alice?"
|
||||
# [/docs:reflect-basic]
|
||||
|
||||
|
||||
# [docs:reflect-with-context]
|
||||
hindsight memory reflect my-bank "Should I learn Python?" --context "career advice"
|
||||
# [/docs:reflect-with-context]
|
||||
|
||||
|
||||
# [docs:reflect-high-budget]
|
||||
hindsight memory reflect my-bank "Summarize my week" --budget high
|
||||
# [/docs:reflect-high-budget]
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Cleanup (not shown in docs)
|
||||
# =============================================================================
|
||||
curl -s -X DELETE "${HINDSIGHT_URL}/v1/default/banks/my-bank" > /dev/null
|
||||
|
||||
echo "reflect.sh: All examples passed"
|
||||
@@ -0,0 +1,58 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Retain API examples for Hindsight (Node.js)
|
||||
* Run: node examples/api/retain.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
|
||||
// =============================================================================
|
||||
|
||||
// [docs:retain-basic]
|
||||
await client.retain('my-bank', 'Alice works at Google as a software engineer');
|
||||
// [/docs:retain-basic]
|
||||
|
||||
|
||||
// [docs:retain-with-context]
|
||||
await client.retain('my-bank', 'Alice got promoted to senior engineer', {
|
||||
context: 'career update',
|
||||
timestamp: '2024-03-15T10:00:00Z'
|
||||
});
|
||||
// [/docs:retain-with-context]
|
||||
|
||||
|
||||
// [docs:retain-batch]
|
||||
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' });
|
||||
// [/docs:retain-batch]
|
||||
|
||||
|
||||
// [docs:retain-async]
|
||||
// Start async ingestion (returns immediately)
|
||||
await client.retainBatch('my-bank', [
|
||||
{ content: 'Large batch item 1' },
|
||||
{ content: 'Large batch item 2' },
|
||||
], {
|
||||
documentId: 'large-doc',
|
||||
async: true
|
||||
});
|
||||
// [/docs:retain-async]
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// Cleanup (not shown in docs)
|
||||
// =============================================================================
|
||||
await fetch(`${HINDSIGHT_URL}/v1/default/banks/my-bank`, { method: 'DELETE' });
|
||||
|
||||
console.log('retain.mjs: All examples passed');
|
||||
@@ -0,0 +1,75 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Retain API examples for Hindsight.
|
||||
Run: python examples/api/retain.py
|
||||
"""
|
||||
import os
|
||||
import requests
|
||||
|
||||
HINDSIGHT_URL = os.getenv("HINDSIGHT_API_URL", "http://localhost:8888")
|
||||
|
||||
# =============================================================================
|
||||
# Setup (not shown in docs)
|
||||
# =============================================================================
|
||||
from hindsight_client import Hindsight
|
||||
|
||||
client = Hindsight(base_url=HINDSIGHT_URL)
|
||||
|
||||
# =============================================================================
|
||||
# Doc Examples
|
||||
# =============================================================================
|
||||
|
||||
# [docs:retain-basic]
|
||||
client.retain(
|
||||
bank_id="my-bank",
|
||||
content="Alice works at Google as a software engineer"
|
||||
)
|
||||
# [/docs:retain-basic]
|
||||
|
||||
|
||||
# [docs:retain-with-context]
|
||||
client.retain(
|
||||
bank_id="my-bank",
|
||||
content="Alice got promoted to senior engineer",
|
||||
context="career update",
|
||||
timestamp="2024-03-15T10:00:00Z"
|
||||
)
|
||||
# [/docs:retain-with-context]
|
||||
|
||||
|
||||
# [docs:retain-batch]
|
||||
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"
|
||||
)
|
||||
# [/docs:retain-batch]
|
||||
|
||||
|
||||
# [docs:retain-async]
|
||||
# Start async ingestion (returns immediately)
|
||||
result = client.retain_batch(
|
||||
bank_id="my-bank",
|
||||
items=[
|
||||
{"content": "Large batch item 1"},
|
||||
{"content": "Large batch item 2"},
|
||||
],
|
||||
document_id="large-doc",
|
||||
retain_async=True
|
||||
)
|
||||
|
||||
# Check if it was processed asynchronously
|
||||
print(result.var_async) # True
|
||||
# [/docs:retain-async]
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Cleanup (not shown in docs)
|
||||
# =============================================================================
|
||||
requests.delete(f"{HINDSIGHT_URL}/v1/default/banks/my-bank")
|
||||
|
||||
print("retain.py: All examples passed")
|
||||
Executable
+34
@@ -0,0 +1,34 @@
|
||||
#!/bin/bash
|
||||
# Retain API examples for Hindsight CLI
|
||||
# Run: bash examples/api/retain.sh
|
||||
|
||||
set -e
|
||||
|
||||
HINDSIGHT_URL="${HINDSIGHT_API_URL:-http://localhost:8888}"
|
||||
|
||||
# =============================================================================
|
||||
# Doc Examples
|
||||
# =============================================================================
|
||||
|
||||
# [docs:retain-basic]
|
||||
hindsight memory retain my-bank "Alice works at Google as a software engineer"
|
||||
# [/docs:retain-basic]
|
||||
|
||||
|
||||
# [docs:retain-with-context]
|
||||
hindsight memory retain my-bank "Alice got promoted" \
|
||||
--context "career update"
|
||||
# [/docs:retain-with-context]
|
||||
|
||||
|
||||
# [docs:retain-async]
|
||||
hindsight memory retain my-bank "Meeting notes" --async
|
||||
# [/docs:retain-async]
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Cleanup (not shown in docs)
|
||||
# =============================================================================
|
||||
curl -s -X DELETE "${HINDSIGHT_URL}/v1/default/banks/my-bank" > /dev/null
|
||||
|
||||
echo "retain.sh: All examples passed"
|
||||
Executable
+129
@@ -0,0 +1,129 @@
|
||||
#!/bin/bash
|
||||
# Run all documentation example scripts
|
||||
# Usage: ./examples/run-examples.sh [python|node|cli|all]
|
||||
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
HINDSIGHT_URL="${HINDSIGHT_API_URL:-http://localhost:8888}"
|
||||
|
||||
# Colors for output
|
||||
GREEN='\033[0;32m'
|
||||
RED='\033[0;31m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
passed=0
|
||||
failed=0
|
||||
skipped=0
|
||||
|
||||
run_python_examples() {
|
||||
echo -e "${YELLOW}Running Python examples...${NC}"
|
||||
for f in "$SCRIPT_DIR"/api/*.py; do
|
||||
if [ -f "$f" ]; then
|
||||
echo -n " $(basename "$f"): "
|
||||
if python "$f" 2>&1; then
|
||||
echo -e "${GREEN}PASSED${NC}"
|
||||
((passed++))
|
||||
else
|
||||
echo -e "${RED}FAILED${NC}"
|
||||
((failed++))
|
||||
fi
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
run_node_examples() {
|
||||
echo -e "${YELLOW}Running Node.js examples...${NC}"
|
||||
for f in "$SCRIPT_DIR"/api/*.mjs; do
|
||||
if [ -f "$f" ]; then
|
||||
echo -n " $(basename "$f"): "
|
||||
if node "$f" 2>&1; then
|
||||
echo -e "${GREEN}PASSED${NC}"
|
||||
((passed++))
|
||||
else
|
||||
echo -e "${RED}FAILED${NC}"
|
||||
((failed++))
|
||||
fi
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
run_cli_examples() {
|
||||
echo -e "${YELLOW}Running CLI examples...${NC}"
|
||||
|
||||
# Check if hindsight CLI is available
|
||||
if ! command -v hindsight &> /dev/null; then
|
||||
echo -e " ${YELLOW}SKIPPED (hindsight CLI not installed)${NC}"
|
||||
for f in "$SCRIPT_DIR"/api/*.sh; do
|
||||
if [ -f "$f" ]; then
|
||||
((skipped++))
|
||||
fi
|
||||
done
|
||||
return
|
||||
fi
|
||||
|
||||
for f in "$SCRIPT_DIR"/api/*.sh; do
|
||||
if [ -f "$f" ]; then
|
||||
echo -n " $(basename "$f"): "
|
||||
if bash "$f" 2>&1; then
|
||||
echo -e "${GREEN}PASSED${NC}"
|
||||
((passed++))
|
||||
else
|
||||
echo -e "${RED}FAILED${NC}"
|
||||
((failed++))
|
||||
fi
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Wait for server to be ready
|
||||
wait_for_server() {
|
||||
echo "Waiting for Hindsight server at $HINDSIGHT_URL..."
|
||||
for i in {1..30}; do
|
||||
if curl -s "$HINDSIGHT_URL/health" > /dev/null 2>&1; then
|
||||
echo "Server is ready!"
|
||||
return 0
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
echo "Server not available after 30 seconds"
|
||||
return 1
|
||||
}
|
||||
|
||||
# Main
|
||||
case "${1:-all}" in
|
||||
python)
|
||||
wait_for_server
|
||||
run_python_examples
|
||||
;;
|
||||
node)
|
||||
wait_for_server
|
||||
run_node_examples
|
||||
;;
|
||||
cli)
|
||||
wait_for_server
|
||||
run_cli_examples
|
||||
;;
|
||||
all)
|
||||
wait_for_server
|
||||
run_python_examples
|
||||
echo ""
|
||||
run_node_examples
|
||||
echo ""
|
||||
run_cli_examples
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 [python|node|cli|all]"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
echo ""
|
||||
echo "========================================"
|
||||
echo -e "Results: ${GREEN}$passed passed${NC}, ${RED}$failed failed${NC}, ${YELLOW}$skipped skipped${NC}"
|
||||
echo "========================================"
|
||||
|
||||
if [ $failed -gt 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
@@ -22,6 +22,7 @@
|
||||
"@mdx-js/react": "^3.0.0",
|
||||
"clsx": "^2.0.0",
|
||||
"prism-react-renderer": "^2.3.0",
|
||||
"raw-loader": "^4.0.2",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
"redocusaurus": "^2.5.0"
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
import React from 'react';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
|
||||
interface CodeSnippetProps {
|
||||
/** Raw file content (use raw-loader to import) */
|
||||
code: string;
|
||||
/** Section marker name (e.g., "retain-basic" for [docs:retain-basic]) */
|
||||
section: string;
|
||||
/** Language for syntax highlighting */
|
||||
language: string;
|
||||
/** Optional title for the code block */
|
||||
title?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts a marked section from source code.
|
||||
*
|
||||
* Markers are in the format:
|
||||
* - Start: `# [docs:section-name]` (Python/Bash) or `// [docs:section-name]` (JS/TS)
|
||||
* - End: `# [/docs:section-name]` (Python/Bash) or `// [/docs:section-name]` (JS/TS)
|
||||
*/
|
||||
function extractSection(code: string, section: string): string {
|
||||
// Match both Python/Bash (#) and JS/TS (//) comment styles
|
||||
const startPattern = new RegExp(`(?:#|//)\\s*\\[docs:${section}\\]`);
|
||||
const endPattern = new RegExp(`(?:#|//)\\s*\\[/docs:${section}\\]`);
|
||||
|
||||
const lines = code.split('\n');
|
||||
let inSection = false;
|
||||
const sectionLines: string[] = [];
|
||||
|
||||
for (const line of lines) {
|
||||
if (startPattern.test(line)) {
|
||||
inSection = true;
|
||||
continue;
|
||||
}
|
||||
if (endPattern.test(line)) {
|
||||
inSection = false;
|
||||
continue;
|
||||
}
|
||||
if (inSection) {
|
||||
sectionLines.push(line);
|
||||
}
|
||||
}
|
||||
|
||||
if (sectionLines.length === 0) {
|
||||
console.warn(`CodeSnippet: Section "${section}" not found in code`);
|
||||
return `// Section "${section}" not found`;
|
||||
}
|
||||
|
||||
// Trim leading/trailing empty lines and normalize indentation
|
||||
return trimAndNormalize(sectionLines);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trims leading/trailing empty lines and removes common leading indentation.
|
||||
*/
|
||||
function trimAndNormalize(lines: string[]): string {
|
||||
// Remove leading empty lines
|
||||
while (lines.length > 0 && lines[0].trim() === '') {
|
||||
lines.shift();
|
||||
}
|
||||
// Remove trailing empty lines
|
||||
while (lines.length > 0 && lines[lines.length - 1].trim() === '') {
|
||||
lines.pop();
|
||||
}
|
||||
|
||||
if (lines.length === 0) return '';
|
||||
|
||||
// Find minimum indentation (ignoring empty lines)
|
||||
const nonEmptyLines = lines.filter(l => l.trim() !== '');
|
||||
if (nonEmptyLines.length === 0) return '';
|
||||
|
||||
const minIndent = Math.min(
|
||||
...nonEmptyLines.map(line => {
|
||||
const match = line.match(/^(\s*)/);
|
||||
return match ? match[1].length : 0;
|
||||
})
|
||||
);
|
||||
|
||||
// Remove common indentation
|
||||
return lines
|
||||
.map(line => line.slice(minIndent))
|
||||
.join('\n');
|
||||
}
|
||||
|
||||
/**
|
||||
* CodeSnippet component for embedding code from example files.
|
||||
*
|
||||
* Usage in MDX:
|
||||
* ```mdx
|
||||
* import CodeSnippet from '@site/src/components/CodeSnippet';
|
||||
* import retainPy from '!!raw-loader!@site/examples/api/retain.py';
|
||||
*
|
||||
* <CodeSnippet code={retainPy} section="retain-basic" language="python" />
|
||||
* ```
|
||||
*/
|
||||
export default function CodeSnippet({
|
||||
code,
|
||||
section,
|
||||
language,
|
||||
title
|
||||
}: CodeSnippetProps): React.ReactElement {
|
||||
const extractedCode = extractSection(code, section);
|
||||
|
||||
return (
|
||||
<CodeBlock language={language} title={title}>
|
||||
{extractedCode}
|
||||
</CodeBlock>
|
||||
);
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 102 KiB |
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "hindsight-litellm"
|
||||
version = "0.1.6"
|
||||
version = "0.1.8"
|
||||
description = "Universal LLM memory integration via LiteLLM - works with 100+ providers"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.10"
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
# hindsight-all
|
||||
|
||||
All-in-one package for Hindsight - Semantic memory system with personality-driven thinking for AI agents.
|
||||
All-in-one package for Hindsight - Agent Memory That Works Like Human Memory
|
||||
|
||||
## Quick Start
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@ build-backend = "hatchling.build"
|
||||
|
||||
[project]
|
||||
name = "hindsight-all"
|
||||
version = "0.1.6"
|
||||
description = "All-in-one package for Hindsight - Semantic memory system with personality-driven thinking"
|
||||
version = "0.1.8"
|
||||
description = "Hindsight: Agent Memory That Works Like Human Memory - All-in-One Bundle"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.11"
|
||||
dependencies = [
|
||||
|
||||
Generated
+41
-2
@@ -13,7 +13,7 @@
|
||||
},
|
||||
"hindsight-clients/typescript": {
|
||||
"name": "@vectorize-io/hindsight-client",
|
||||
"version": "0.1.5",
|
||||
"version": "0.1.8",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@hey-api/openapi-ts": "^0.88.0",
|
||||
@@ -25,7 +25,7 @@
|
||||
}
|
||||
},
|
||||
"hindsight-control-plane": {
|
||||
"version": "0.1.5",
|
||||
"version": "0.1.8",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-checkbox": "^1.3.3",
|
||||
@@ -105,6 +105,7 @@
|
||||
"@mdx-js/react": "^3.0.0",
|
||||
"clsx": "^2.0.0",
|
||||
"prism-react-renderer": "^2.3.0",
|
||||
"raw-loader": "^4.0.2",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
"redocusaurus": "^2.5.0"
|
||||
@@ -24244,6 +24245,44 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/raw-loader": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-4.0.2.tgz",
|
||||
"integrity": "sha512-ZnScIV3ag9A4wPX/ZayxL/jZH+euYb6FcUinPcgiQW0+UBtEv0O6Q3lGd3cqJ+GHH+rksEv3Pj99oxJ3u3VIKA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"loader-utils": "^2.0.0",
|
||||
"schema-utils": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10.13.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/webpack"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"webpack": "^4.0.0 || ^5.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/raw-loader/node_modules/schema-utils": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz",
|
||||
"integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/json-schema": "^7.0.8",
|
||||
"ajv": "^6.12.5",
|
||||
"ajv-keywords": "^3.5.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10.13.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/webpack"
|
||||
}
|
||||
},
|
||||
"node_modules/rc": {
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
|
||||
|
||||
@@ -1141,7 +1141,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "hindsight-all"
|
||||
version = "0.1.6"
|
||||
version = "0.1.8"
|
||||
source = { editable = "hindsight" }
|
||||
dependencies = [
|
||||
{ name = "hindsight-api" },
|
||||
@@ -1165,7 +1165,7 @@ provides-extras = ["test"]
|
||||
|
||||
[[package]]
|
||||
name = "hindsight-api"
|
||||
version = "0.1.6"
|
||||
version = "0.1.8"
|
||||
source = { editable = "hindsight-api" }
|
||||
dependencies = [
|
||||
{ name = "alembic" },
|
||||
@@ -1249,7 +1249,7 @@ requires-dist = [
|
||||
{ name = "sentence-transformers", specifier = ">=3.0.0,<3.3.0" },
|
||||
{ name = "sqlalchemy", specifier = ">=2.0.44" },
|
||||
{ name = "tiktoken", specifier = ">=0.12.0" },
|
||||
{ name = "torch", specifier = ">=2.0.0,<2.6.0" },
|
||||
{ name = "torch", specifier = ">=2.0.0" },
|
||||
{ name = "transformers", specifier = ">=4.30.0,<4.46.0" },
|
||||
{ name = "uvicorn", specifier = ">=0.38.0" },
|
||||
{ name = "wsproto", specifier = ">=1.0.0" },
|
||||
@@ -1269,7 +1269,7 @@ dev = [
|
||||
|
||||
[[package]]
|
||||
name = "hindsight-client"
|
||||
version = "0.1.6"
|
||||
version = "0.1.8"
|
||||
source = { editable = "hindsight-clients/python" }
|
||||
dependencies = [
|
||||
{ name = "aiohttp" },
|
||||
@@ -1284,6 +1284,7 @@ dependencies = [
|
||||
test = [
|
||||
{ name = "pytest" },
|
||||
{ name = "pytest-asyncio" },
|
||||
{ name = "requests" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
@@ -1294,6 +1295,7 @@ requires-dist = [
|
||||
{ name = "pytest", marker = "extra == 'test'", specifier = ">=7.0.0" },
|
||||
{ name = "pytest-asyncio", marker = "extra == 'test'", specifier = ">=0.21.0" },
|
||||
{ name = "python-dateutil", specifier = ">=2.8.2" },
|
||||
{ name = "requests", marker = "extra == 'test'", specifier = ">=2.28.0" },
|
||||
{ name = "typing-extensions", specifier = ">=4.7.1" },
|
||||
{ name = "urllib3", specifier = ">=2.1.0,<3.0.0" },
|
||||
]
|
||||
@@ -1301,7 +1303,7 @@ provides-extras = ["test"]
|
||||
|
||||
[[package]]
|
||||
name = "hindsight-dev"
|
||||
version = "0.1.6"
|
||||
version = "0.1.8"
|
||||
source = { editable = "hindsight-dev" }
|
||||
dependencies = [
|
||||
{ name = "hindsight-api" },
|
||||
|
||||
Reference in New Issue
Block a user