diff --git a/hindsight-clients/python/hindsight_client/hindsight_client.py b/hindsight-clients/python/hindsight_client/hindsight_client.py index 19d67138..47cb9e00 100644 --- a/hindsight-clients/python/hindsight_client/hindsight_client.py +++ b/hindsight-clients/python/hindsight_client/hindsight_client.py @@ -115,6 +115,7 @@ class Hindsight: document_id: Optional[str] = None, metadata: Optional[Dict[str, str]] = None, entities: Optional[List[Dict[str, str]]] = None, + tags: Optional[List[str]] = None, ) -> RetainResponse: """ Store a single memory (simplified interface). @@ -127,13 +128,14 @@ class Hindsight: document_id: Optional document ID for grouping metadata: Optional user-defined metadata entities: Optional list of entities [{"text": "...", "type": "..."}] + tags: Optional list of tags for this memory Returns: RetainResponse with success status """ return self.retain_batch( bank_id=bank_id, - items=[{"content": content, "timestamp": timestamp, "context": context, "metadata": metadata, "entities": entities}], + items=[{"content": content, "timestamp": timestamp, "context": context, "metadata": metadata, "entities": entities, "tags": tags}], document_id=document_id, ) @@ -143,15 +145,17 @@ class Hindsight: items: List[Dict[str, Any]], document_id: Optional[str] = None, retain_async: bool = False, + document_tags: Optional[List[str]] = None, ) -> RetainResponse: """ Store multiple memories in batch. Args: bank_id: The memory bank ID - items: List of memory items with 'content' and optional 'timestamp', 'context', 'metadata', 'document_id', 'entities' + items: List of memory items with 'content' and optional 'timestamp', 'context', 'metadata', 'document_id', 'entities', 'tags' document_id: Optional document ID for grouping memories (applied to items that don't have their own) retain_async: If True, process asynchronously in background (default: False) + document_tags: Optional list of tags to apply to all memories in this batch Returns: RetainResponse with success status and item count @@ -175,12 +179,14 @@ class Hindsight: # Use item's document_id if provided, otherwise fall back to batch-level document_id document_id=item.get("document_id") or document_id, entities=entities, + tags=item.get("tags"), ) ) request_obj = retain_request.RetainRequest( items=memory_items, async_=retain_async, + document_tags=document_tags, ) return _run_async(self._memory_api.retain_memories(bank_id, request_obj)) @@ -198,6 +204,8 @@ class Hindsight: max_entity_tokens: int = 500, include_chunks: bool = False, max_chunk_tokens: int = 8192, + tags: Optional[List[str]] = None, + tags_match: str = "any", ) -> RecallResponse: """ Recall memories using semantic similarity. @@ -214,6 +222,9 @@ class Hindsight: max_entity_tokens: Maximum tokens for entity observations (default: 500) include_chunks: Include raw text chunks in results (default: False) max_chunk_tokens: Maximum tokens for chunks (default: 8192) + tags: Optional list of tags to filter memories by + tags_match: How to match tags: 'any' (OR, includes untagged), 'all' (AND, includes untagged), + 'any_strict' (OR, excludes untagged), 'all_strict' (AND, excludes untagged). Default: 'any' Returns: RecallResponse with results, optional entities, optional chunks, and optional trace @@ -233,6 +244,8 @@ class Hindsight: trace=trace, query_timestamp=query_timestamp, include=include_opts, + tags=tags, + tags_match=tags_match, ) return _run_async(self._memory_api.recall_memories(bank_id, request_obj)) @@ -245,6 +258,8 @@ class Hindsight: context: Optional[str] = None, max_tokens: Optional[int] = None, response_schema: Optional[Dict[str, Any]] = None, + tags: Optional[List[str]] = None, + tags_match: str = "any", ) -> ReflectResponse: """ Generate a contextual answer based on bank identity and memories. @@ -258,6 +273,9 @@ class Hindsight: response_schema: Optional JSON Schema for structured output. When provided, the response will include a 'structured_output' field with the LLM response parsed according to this schema. + tags: Optional list of tags to filter memories by + tags_match: How to match tags: 'any' (OR, includes untagged), 'all' (AND, includes untagged), + 'any_strict' (OR, excludes untagged), 'all_strict' (AND, excludes untagged). Default: 'any' Returns: ReflectResponse with answer text, optionally facts used, and optionally @@ -269,6 +287,8 @@ class Hindsight: context=context, max_tokens=max_tokens, response_schema=response_schema, + tags=tags, + tags_match=tags_match, ) return _run_async(self._memory_api.reflect(bank_id, request_obj)) diff --git a/hindsight-clients/typescript/src/index.ts b/hindsight-clients/typescript/src/index.ts index 1f0d445c..3a4db684 100644 --- a/hindsight-clients/typescript/src/index.ts +++ b/hindsight-clients/typescript/src/index.ts @@ -102,6 +102,8 @@ export class HindsightClient { documentId?: string; async?: boolean; entities?: EntityInput[]; + /** Optional list of tags for this memory */ + tags?: string[]; } ): Promise { const item: { @@ -111,6 +113,7 @@ export class HindsightClient { metadata?: Record; document_id?: string; entities?: EntityInput[]; + tags?: string[]; } = { content }; if (options?.timestamp) { item.timestamp = @@ -130,6 +133,9 @@ export class HindsightClient { if (options?.entities) { item.entities = options.entities; } + if (options?.tags) { + item.tags = options.tags; + } const response = await sdk.retainMemories({ client: this.client, @@ -192,6 +198,10 @@ export class HindsightClient { maxEntityTokens?: number; includeChunks?: boolean; maxChunkTokens?: number; + /** Optional list of tags to filter memories by */ + tags?: string[]; + /** How to match tags: 'any' (OR, includes untagged), 'all' (AND, includes untagged), 'any_strict' (OR, excludes untagged), 'all_strict' (AND, excludes untagged). Default: 'any' */ + tagsMatch?: 'any' | 'all' | 'any_strict' | 'all_strict'; } ): Promise { const response = await sdk.recallMemories({ @@ -208,6 +218,8 @@ export class HindsightClient { entities: options?.includeEntities ? { max_tokens: options?.maxEntityTokens ?? 500 } : undefined, chunks: options?.includeChunks ? { max_tokens: options?.maxChunkTokens ?? 8192 } : undefined, }, + tags: options?.tags, + tags_match: options?.tagsMatch, }, }); @@ -220,7 +232,14 @@ export class HindsightClient { async reflect( bankId: string, query: string, - options?: { context?: string; budget?: Budget } + options?: { + context?: string; + budget?: Budget; + /** Optional list of tags to filter memories by */ + tags?: string[]; + /** How to match tags: 'any' (OR, includes untagged), 'all' (AND, includes untagged), 'any_strict' (OR, excludes untagged), 'all_strict' (AND, excludes untagged). Default: 'any' */ + tagsMatch?: 'any' | 'all' | 'any_strict' | 'all_strict'; + } ): Promise { const response = await sdk.reflect({ client: this.client, @@ -229,6 +248,8 @@ export class HindsightClient { query, context: options?.context, budget: options?.budget || 'low', + tags: options?.tags, + tags_match: options?.tagsMatch, }, }); diff --git a/hindsight-docs/docs/developer/api/recall.mdx b/hindsight-docs/docs/developer/api/recall.mdx index aa8b3d6c..eb05b0bb 100644 --- a/hindsight-docs/docs/developer/api/recall.mdx +++ b/hindsight-docs/docs/developer/api/recall.mdx @@ -43,11 +43,13 @@ Make sure you've completed the [Quick Start](./quickstart) to install the client |-----------|------|---------|-------------| | `query` | string | required | Natural language query | | `types` | list | all | Filter: `world`, `experience`, `opinion` | -| `budget` | string | "mid" | Budget level: "low", "mid", "high" | +| `budget` | string | "mid" | Budget level: `low`, `mid`, `high` | | `max_tokens` | int | 4096 | Token budget for results | | `trace` | bool | false | Enable trace output for debugging | | `include_entities` | bool | false | Include entity observations | | `max_entity_tokens` | int | 500 | Token budget for entity observations | +| `tags` | list | None | Filter memories by tags (see [Tag Filtering](#filter-by-tags)) | +| `tags_match` | string | "any" | How to match tags: `any`, `all`, `any_strict`, `all_strict` | @@ -127,3 +129,51 @@ The `budget` parameter controls graph traversal depth: + +## Filter by Tags + +Tags enable **visibility scoping**—filter memories based on tags assigned during [retain](./retain#tagging-memories). This is essential for multi-user agents where each user should only see their own memories. + +### Basic Tag Filtering + + + + + + + +### Tag Match Modes + +The `tags_match` parameter controls how tags are matched: + +| Mode | Behavior | Untagged Memories | +|------|----------|-------------------| +| `any` | OR: memory has ANY of the specified tags | **Included** | +| `all` | AND: memory has ALL of the specified tags | **Included** | +| `any_strict` | OR: memory has ANY of the specified tags | **Excluded** | +| `all_strict` | AND: memory has ALL of the specified tags | **Excluded** | + +**Strict modes** are useful when you want to ensure only tagged memories are returned: + + + + + + + +**AND matching** requires all specified tags to be present: + + + + + + + +### Use Cases + +| Scenario | Tags | Mode | Result | +|----------|------|------|--------| +| User A's memories only | `["user:alice"]` | `any_strict` | Only memories tagged `user:alice` | +| Support + feedback | `["support", "feedback"]` | `any` | Memories with either tag + untagged | +| Multi-user room | `["user:alice", "room:general"]` | `all_strict` | Only memories with both tags | +| Global + user-specific | `["user:alice"]` | `any` | Alice's memories + shared (untagged) | diff --git a/hindsight-docs/docs/developer/api/reflect.mdx b/hindsight-docs/docs/developer/api/reflect.mdx index 9944fe99..59da6400 100644 --- a/hindsight-docs/docs/developer/api/reflect.mdx +++ b/hindsight-docs/docs/developer/api/reflect.mdx @@ -50,10 +50,12 @@ Make sure you've completed the [Quick Start](./quickstart) to install the client | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | `query` | string | required | Question or prompt | -| `budget` | string | "low" | Budget level: "low", "mid", "high" | +| `budget` | string | "low" | Budget level: `low`, `mid`, `high` | | `context` | string | None | Additional context for the query | | `max_tokens` | int | 4096 | Maximum tokens for the response | | `response_schema` | object | None | JSON Schema for [structured output](#structured-output) | +| `tags` | list | None | Filter memories by tags during reflection | +| `tags_match` | string | "any" | How to match tags: `any`, `all`, `any_strict`, `all_strict` | ### Response Fields @@ -247,3 +249,24 @@ hindsight memory reflect hiring-team \ - Use `model_validate()` to parse the response back into your Pydantic model - Keep schemas focused — extract only what you need - Use `Optional` fields for data that may not always be available + +## Filter by Tags + +Like [recall](./recall#filter-by-tags), reflect supports tag filtering to scope which memories are considered during reasoning. This is essential for multi-user scenarios where reflection should only consider memories relevant to a specific user. + + + + + + + +The `tags_match` parameter works the same as in recall: + +| Mode | Behavior | +|------|----------| +| `any` | OR matching, includes untagged memories | +| `all` | AND matching, includes untagged memories | +| `any_strict` | OR matching, excludes untagged memories | +| `all_strict` | AND matching, excludes untagged memories | + +See [Retain API](./retain#tagging-memories) for how to tag memories and [Recall API](./recall#filter-by-tags) for more details on tag matching modes. diff --git a/hindsight-docs/docs/developer/api/retain.mdx b/hindsight-docs/docs/developer/api/retain.mdx index 4116dbfe..132618d8 100644 --- a/hindsight-docs/docs/developer/api/retain.mdx +++ b/hindsight-docs/docs/developer/api/retain.mdx @@ -129,3 +129,55 @@ For large batches, use async ingestion to avoid blocking: + +## Tagging Memories + +Tags enable **visibility scoping**—useful when one memory bank serves multiple users but each should only see relevant memories. For example, an agent that chats with multiple users can tag memories by user ID and filter during recall. + +### Tag Individual Items + + + + + + + +### Apply Tags to All Items in a Batch + +Use `document_tags` to apply the same tags to all items in a request: + + + + + + + +When both `document_tags` and item-level `tags` are provided, they are merged together. + +### Tag Naming Conventions + +Use consistent naming patterns for tags: + +| Pattern | Example | Use Case | +|---------|---------|----------| +| `user:` | `user:alice` | Multi-user agent filtering | +| `session:` | `session:123` | Session-based scoping | +| `room:` | `room:general` | Chat room isolation | +| `topic:` | `topic:feedback` | Topic categorization | + +### Listing Tags + +Use the list tags API to discover existing tags, useful for UI autocomplete or wildcard expansion: + +```python +# List all tags in a bank +tags = client.list_tags(bank_id="my-bank") +for tag in tags.items: + print(f"{tag.tag}: {tag.count} memories") + +# Search with wildcards (* matches any characters) +user_tags = client.list_tags(bank_id="my-bank", q="user:*") +admin_tags = client.list_tags(bank_id="my-bank", q="*-admin") +``` + +See [Recall API](./recall#filter-by-tags) for filtering memories by tags during retrieval. diff --git a/hindsight-docs/docs/developer/models.md b/hindsight-docs/docs/developer/models.md index 698957d5..c56e4947 100644 --- a/hindsight-docs/docs/developer/models.md +++ b/hindsight-docs/docs/developer/models.md @@ -95,29 +95,71 @@ Converts text into dense vector representations for semantic similarity search. **Default:** `BAAI/bge-small-en-v1.5` (384 dimensions, ~130MB) -**Alternatives:** +### Supported Providers -| Model | Use Case | -|-------|----------| -| `BAAI/bge-small-en-v1.5` | Default, fast, good quality | -| `sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2` | Multilingual (50+ languages) | +| Provider | Description | Best For | +|----------|-------------|----------| +| `local` | SentenceTransformers (default) | Development, low latency | +| `openai` | OpenAI embeddings API | Production, high quality | +| `cohere` | Cohere embeddings API | Production, multilingual | +| `tei` | HuggingFace Text Embeddings Inference | Production, self-hosted | +| `litellm` | LiteLLM proxy (unified gateway) | Multi-provider setups | -:::warning -All embedding models must produce **384-dimensional vectors** to match the database schema. +### Local Models + +| Model | Dimensions | Use Case | +|-------|------------|----------| +| `BAAI/bge-small-en-v1.5` | 384 | Default, fast, good quality | +| `sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2` | 384 | Multilingual (50+ languages) | + +### OpenAI Models + +| Model | Dimensions | Use Case | +|-------|------------|----------| +| `text-embedding-3-small` | 1536 | Default OpenAI, cost-effective | +| `text-embedding-3-large` | 3072 | Higher quality, more expensive | +| `text-embedding-ada-002` | 1536 | Legacy model | + +### Cohere Models + +| Model | Dimensions | Use Case | +|-------|------------|----------| +| `embed-english-v3.0` | 1024 | English text | +| `embed-multilingual-v3.0` | 1024 | 100+ languages | + +:::warning Embedding Dimensions +Hindsight automatically detects the embedding dimension at startup and adjusts the database schema. Once memories are stored, you cannot change dimensions without losing data. ::: -**Configuration:** +**Configuration Examples:** ```bash # Local provider (default) export HINDSIGHT_API_EMBEDDINGS_PROVIDER=local export HINDSIGHT_API_EMBEDDINGS_LOCAL_MODEL=BAAI/bge-small-en-v1.5 -# TEI provider (remote) +# OpenAI +export HINDSIGHT_API_EMBEDDINGS_PROVIDER=openai +export HINDSIGHT_API_EMBEDDINGS_OPENAI_API_KEY=sk-xxxxxxxxxxxx +export HINDSIGHT_API_EMBEDDINGS_OPENAI_MODEL=text-embedding-3-small + +# Cohere +export HINDSIGHT_API_EMBEDDINGS_PROVIDER=cohere +export HINDSIGHT_API_COHERE_API_KEY=your-api-key +export HINDSIGHT_API_EMBEDDINGS_COHERE_MODEL=embed-english-v3.0 + +# TEI (self-hosted) export HINDSIGHT_API_EMBEDDINGS_PROVIDER=tei export HINDSIGHT_API_EMBEDDINGS_TEI_URL=http://localhost:8080 + +# LiteLLM proxy +export HINDSIGHT_API_EMBEDDINGS_PROVIDER=litellm +export HINDSIGHT_API_LITELLM_API_BASE=http://localhost:4000 +export HINDSIGHT_API_EMBEDDINGS_LITELLM_MODEL=text-embedding-3-small ``` +See [Configuration](./configuration#embeddings) for all options including Azure OpenAI and custom endpoints. + --- ## Cross-Encoder (Reranker) @@ -126,7 +168,18 @@ Reranks initial search results to improve precision. **Default:** `cross-encoder/ms-marco-MiniLM-L-6-v2` (~85MB) -**Alternatives:** +### Supported Providers + +| Provider | Description | Best For | +|----------|-------------|----------| +| `local` | SentenceTransformers CrossEncoder (default) | Development, low latency | +| `cohere` | Cohere rerank API | Production, high quality | +| `tei` | HuggingFace Text Embeddings Inference | Production, self-hosted | +| `flashrank` | FlashRank (lightweight, fast) | Resource-constrained environments | +| `litellm` | LiteLLM proxy (unified gateway) | Multi-provider setups | +| `rrf` | RRF-only (no neural reranking) | Testing, minimal resources | + +### Local Models | Model | Use Case | |-------|----------| @@ -134,14 +187,51 @@ Reranks initial search results to improve precision. | `cross-encoder/ms-marco-MiniLM-L-12-v2` | Higher accuracy | | `cross-encoder/mmarco-mMiniLMv2-L12-H384-v1` | Multilingual | -**Configuration:** +### Cohere Models + +| Model | Use Case | +|-------|----------| +| `rerank-english-v3.0` | English text | +| `rerank-multilingual-v3.0` | 100+ languages | + +### LiteLLM Supported Providers + +LiteLLM supports multiple reranking providers via the `/rerank` endpoint: + +| Provider | Model Example | +|----------|---------------| +| Cohere | `cohere/rerank-english-v3.0` | +| Together AI | `together_ai/...` | +| Voyage AI | `voyage/rerank-2` | +| Jina AI | `jina_ai/...` | +| AWS Bedrock | `bedrock/...` | + +**Configuration Examples:** ```bash # Local provider (default) export HINDSIGHT_API_RERANKER_PROVIDER=local export HINDSIGHT_API_RERANKER_LOCAL_MODEL=cross-encoder/ms-marco-MiniLM-L-6-v2 -# TEI provider (remote) +# Cohere +export HINDSIGHT_API_RERANKER_PROVIDER=cohere +export HINDSIGHT_API_COHERE_API_KEY=your-api-key +export HINDSIGHT_API_RERANKER_COHERE_MODEL=rerank-english-v3.0 + +# TEI (self-hosted) export HINDSIGHT_API_RERANKER_PROVIDER=tei export HINDSIGHT_API_RERANKER_TEI_URL=http://localhost:8081 + +# FlashRank (lightweight) +export HINDSIGHT_API_RERANKER_PROVIDER=flashrank + +# LiteLLM proxy +export HINDSIGHT_API_RERANKER_PROVIDER=litellm +export HINDSIGHT_API_LITELLM_API_BASE=http://localhost:4000 +export HINDSIGHT_API_RERANKER_LITELLM_MODEL=cohere/rerank-english-v3.0 + +# RRF-only (no neural reranking) +export HINDSIGHT_API_RERANKER_PROVIDER=rrf ``` + +See [Configuration](./configuration#reranker) for all options including Azure-hosted endpoints and batch settings. diff --git a/hindsight-docs/docs/developer/reflect.md b/hindsight-docs/docs/developer/reflect.md index 0d5d4766..8f982feb 100644 --- a/hindsight-docs/docs/developer/reflect.md +++ b/hindsight-docs/docs/developer/reflect.md @@ -183,4 +183,4 @@ Disposition creates **consistent character** across conversations while allowing - [**Retain**](./retain) — How rich facts are stored - [**Recall**](./retrieval) — How multi-strategy search works -- [API Reference: Reflect](./api/reflect) — Code examples and usage +- [**Reflect API**](./api/reflect) — Code examples, parameters, and tag filtering diff --git a/hindsight-docs/docs/developer/retain.md b/hindsight-docs/docs/developer/retain.md index 366aa3c7..1cd97a39 100644 --- a/hindsight-docs/docs/developer/retain.md +++ b/hindsight-docs/docs/developer/retain.md @@ -169,34 +169,13 @@ As facts accumulate about an entity, Hindsight synthesizes **observations** — ## Tagging Memories -You can tag memories for filtering during recall—useful when one memory bank serves multiple users but each user should only see relevant memories. +Tags enable visibility scoping—useful when one memory bank serves multiple users but each should only see relevant memories. -```python -# Tag memories for specific users -client.retain( - bank_id="my-agent", - items=[ - { - "content": "Alice prefers morning meetings", - "tags": ["user_alice"] - } - ] -) +- **Item tags**: Tag individual memories with specific scopes +- **Document tags**: Apply tags to all items in a batch +- **Tag filtering**: Filter during recall/reflect by tags -# Apply tags to all items in a batch -client.retain( - bank_id="my-agent", - document_tags=["session_123", "user_alice"], # Applied to all items - items=[ - {"content": "Alice discussed the project timeline"}, - {"content": "Alice mentioned she needs help with Python"} - ] -) -``` - -During recall, use `tags_match` to control matching: -- `"any"` (default): OR matching - returns memories where **any** tag overlaps -- `"all"`: AND matching - returns memories containing **all** specified tags +See [Retain API](./api/retain) for code examples and [Recall API](./api/recall) for filtering options. --- @@ -219,4 +198,4 @@ All stored in your isolated **memory bank**, ready for `recall()` and `reflect() - [**Recall**](./retrieval) — How multi-strategy search retrieves relevant memories - [**Reflect**](./reflect) — How disposition influences reasoning and opinion formation -- [API Reference](./api/retain) — Code examples for retaining memories +- [**Retain API**](./api/retain) — Code examples and parameters diff --git a/hindsight-docs/docs/developer/retrieval.md b/hindsight-docs/docs/developer/retrieval.md index 891465ef..5a15dee7 100644 --- a/hindsight-docs/docs/developer/retrieval.md +++ b/hindsight-docs/docs/developer/retrieval.md @@ -133,9 +133,9 @@ Hindsight is built for AI agents, not humans. Traditional search systems return **Parameters you control:** - `max_tokens`: How much memory content to return (default: 4096 tokens) - `budget`: Search depth level (low, mid, high) -- `fact_type`: Filter by world, experience, opinion, or all -- `tags`: Filter memories by tags -- `tags_match`: How to match tags - `"any"` for OR (default), `"all"` for AND +- `types`: Filter by world, experience, opinion, or all +- `tags`: Filter memories by visibility tags +- `tags_match`: How to match tags (see [Recall API](./api/recall) for all options) ### Expanding Context: Chunks and Entity Observations @@ -243,3 +243,4 @@ See [Configuration → Retrieval](./configuration#retrieval) for available algor - [**Retain**](./retain) — How memories are stored with rich context - [**Reflect**](./reflect) — How disposition influences reasoning +- [**Recall API**](./api/recall) — Code examples, parameters, and tag filtering diff --git a/hindsight-docs/examples/api/recall.py b/hindsight-docs/examples/api/recall.py index aed8bdfd..71b68f6d 100644 --- a/hindsight-docs/examples/api/recall.py +++ b/hindsight-docs/examples/api/recall.py @@ -116,6 +116,39 @@ results = client.recall(bank_id="my-bank", query="How are Alice and Bob connecte # [/docs:recall-budget-levels] +# [docs:recall-with-tags] +# Filter recall to only memories tagged for a specific user +response = client.recall( + bank_id="my-bank", + query="What feedback did the user give?", + tags=["user:alice"], + tags_match="any" # OR matching, includes untagged (default) +) +# [/docs:recall-with-tags] + + +# [docs:recall-tags-strict] +# Strict mode: only return memories that have matching tags (exclude untagged) +response = client.recall( + bank_id="my-bank", + query="What did the user say?", + tags=["user:alice"], + tags_match="any_strict" # OR matching, excludes untagged memories +) +# [/docs:recall-tags-strict] + + +# [docs:recall-tags-all] +# AND matching: require ALL specified tags to be present +response = client.recall( + bank_id="my-bank", + query="What bugs were reported?", + tags=["user:alice", "bug-report"], + tags_match="all_strict" # Memory must have BOTH tags +) +# [/docs:recall-tags-all] + + # ============================================================================= # Cleanup (not shown in docs) # ============================================================================= diff --git a/hindsight-docs/examples/api/reflect.py b/hindsight-docs/examples/api/reflect.py index d6750a78..748a548d 100644 --- a/hindsight-docs/examples/api/reflect.py +++ b/hindsight-docs/examples/api/reflect.py @@ -81,6 +81,17 @@ for fact in response.based_on or []: # [/docs:reflect-sources] +# [docs:reflect-with-tags] +# Filter reflection to only consider memories for a specific user +response = client.reflect( + bank_id="my-bank", + query="What does this user think about our product?", + tags=["user:alice"], + tags_match="any_strict" # Only use memories tagged for this user +) +# [/docs:reflect-with-tags] + + # ============================================================================= # Cleanup (not shown in docs) # ============================================================================= diff --git a/hindsight-docs/examples/api/retain.py b/hindsight-docs/examples/api/retain.py index 82d11b3b..e7a37511 100644 --- a/hindsight-docs/examples/api/retain.py +++ b/hindsight-docs/examples/api/retain.py @@ -67,6 +67,39 @@ print(result.var_async) # True # [/docs:retain-async] +# [docs:retain-with-tags] +# Tag individual items for visibility scoping +client.retain_batch( + bank_id="my-bank", + items=[ + { + "content": "User Alice said she loves the new dashboard", + "tags": ["user:alice", "feedback"] + }, + { + "content": "User Bob reported a bug in the search feature", + "tags": ["user:bob", "bug-report"] + } + ], + document_id="user_feedback_001" +) +# [/docs:retain-with-tags] + + +# [docs:retain-with-document-tags] +# Apply tags to all items in a batch +client.retain_batch( + bank_id="my-bank", + items=[ + {"content": "Alice mentioned she prefers dark mode"}, + {"content": "Bob asked about keyboard shortcuts"} + ], + document_id="support_session_123", + document_tags=["session:123", "support"] # Applied to all items +) +# [/docs:retain-with-document-tags] + + # ============================================================================= # Cleanup (not shown in docs) # =============================================================================