hindsight-api 0.3.0__py3-none-any.whl → 0.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- hindsight_api/admin/cli.py +59 -0
- hindsight_api/alembic/versions/h3c4d5e6f7g8_mental_models_v4.py +112 -0
- hindsight_api/alembic/versions/i4d5e6f7g8h9_delete_opinions.py +41 -0
- hindsight_api/alembic/versions/j5e6f7g8h9i0_mental_model_versions.py +95 -0
- hindsight_api/alembic/versions/k6f7g8h9i0j1_add_directive_subtype.py +58 -0
- hindsight_api/alembic/versions/l7g8h9i0j1k2_add_worker_columns.py +109 -0
- hindsight_api/alembic/versions/m8h9i0j1k2l3_mental_model_id_to_text.py +41 -0
- hindsight_api/alembic/versions/n9i0j1k2l3m4_learnings_and_pinned_reflections.py +134 -0
- hindsight_api/alembic/versions/o0j1k2l3m4n5_migrate_mental_models_data.py +113 -0
- hindsight_api/alembic/versions/p1k2l3m4n5o6_new_knowledge_architecture.py +194 -0
- hindsight_api/alembic/versions/q2l3m4n5o6p7_fix_mental_model_fact_type.py +50 -0
- hindsight_api/alembic/versions/r3m4n5o6p7q8_add_reflect_response_to_reflections.py +47 -0
- hindsight_api/alembic/versions/s4n5o6p7q8r9_add_consolidated_at_to_memory_units.py +53 -0
- hindsight_api/alembic/versions/t5o6p7q8r9s0_rename_mental_models_to_observations.py +134 -0
- hindsight_api/alembic/versions/u6p7q8r9s0t1_mental_models_text_id.py +41 -0
- hindsight_api/alembic/versions/v7q8r9s0t1u2_add_max_tokens_to_mental_models.py +50 -0
- hindsight_api/api/http.py +1119 -93
- hindsight_api/api/mcp.py +11 -191
- hindsight_api/config.py +145 -45
- hindsight_api/engine/consolidation/__init__.py +5 -0
- hindsight_api/engine/consolidation/consolidator.py +859 -0
- hindsight_api/engine/consolidation/prompts.py +69 -0
- hindsight_api/engine/cross_encoder.py +114 -9
- hindsight_api/engine/directives/__init__.py +5 -0
- hindsight_api/engine/directives/models.py +37 -0
- hindsight_api/engine/embeddings.py +102 -5
- hindsight_api/engine/interface.py +32 -13
- hindsight_api/engine/llm_wrapper.py +505 -43
- hindsight_api/engine/memory_engine.py +2090 -1089
- hindsight_api/engine/mental_models/__init__.py +14 -0
- hindsight_api/engine/mental_models/models.py +53 -0
- hindsight_api/engine/reflect/__init__.py +18 -0
- hindsight_api/engine/reflect/agent.py +933 -0
- hindsight_api/engine/reflect/models.py +109 -0
- hindsight_api/engine/reflect/observations.py +186 -0
- hindsight_api/engine/reflect/prompts.py +483 -0
- hindsight_api/engine/reflect/tools.py +437 -0
- hindsight_api/engine/reflect/tools_schema.py +250 -0
- hindsight_api/engine/response_models.py +130 -4
- hindsight_api/engine/retain/bank_utils.py +79 -201
- hindsight_api/engine/retain/fact_extraction.py +81 -48
- hindsight_api/engine/retain/fact_storage.py +5 -8
- hindsight_api/engine/retain/link_utils.py +5 -8
- hindsight_api/engine/retain/orchestrator.py +1 -55
- hindsight_api/engine/retain/types.py +2 -2
- hindsight_api/engine/search/graph_retrieval.py +2 -2
- hindsight_api/engine/search/link_expansion_retrieval.py +164 -29
- hindsight_api/engine/search/mpfp_retrieval.py +1 -1
- hindsight_api/engine/search/retrieval.py +14 -14
- hindsight_api/engine/search/think_utils.py +41 -140
- hindsight_api/engine/search/trace.py +0 -1
- hindsight_api/engine/search/tracer.py +2 -5
- hindsight_api/engine/search/types.py +0 -3
- hindsight_api/engine/task_backend.py +112 -196
- hindsight_api/engine/utils.py +0 -151
- hindsight_api/extensions/__init__.py +10 -1
- hindsight_api/extensions/builtin/tenant.py +5 -1
- hindsight_api/extensions/operation_validator.py +81 -4
- hindsight_api/extensions/tenant.py +26 -0
- hindsight_api/main.py +16 -5
- hindsight_api/mcp_local.py +12 -53
- hindsight_api/mcp_tools.py +494 -0
- hindsight_api/models.py +0 -2
- hindsight_api/worker/__init__.py +11 -0
- hindsight_api/worker/main.py +296 -0
- hindsight_api/worker/poller.py +486 -0
- {hindsight_api-0.3.0.dist-info → hindsight_api-0.4.0.dist-info}/METADATA +12 -6
- hindsight_api-0.4.0.dist-info/RECORD +112 -0
- {hindsight_api-0.3.0.dist-info → hindsight_api-0.4.0.dist-info}/entry_points.txt +1 -0
- hindsight_api/engine/retain/observation_regeneration.py +0 -254
- hindsight_api/engine/search/observation_utils.py +0 -125
- hindsight_api/engine/search/scoring.py +0 -159
- hindsight_api-0.3.0.dist-info/RECORD +0 -82
- {hindsight_api-0.3.0.dist-info → hindsight_api-0.4.0.dist-info}/WHEEL +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""Operation Validator Extension for validating retain/recall/reflect operations."""
|
|
1
|
+
"""Operation Validator Extension for validating retain/recall/reflect/consolidate operations."""
|
|
2
2
|
|
|
3
3
|
from abc import ABC, abstractmethod
|
|
4
4
|
from dataclasses import dataclass, field
|
|
@@ -97,6 +97,19 @@ class ReflectContext:
|
|
|
97
97
|
context: str | None = None
|
|
98
98
|
|
|
99
99
|
|
|
100
|
+
# =============================================================================
|
|
101
|
+
# Consolidation Pre-operation Context
|
|
102
|
+
# =============================================================================
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
@dataclass
|
|
106
|
+
class ConsolidateContext:
|
|
107
|
+
"""Context for a consolidation operation validation (pre-operation)."""
|
|
108
|
+
|
|
109
|
+
bank_id: str
|
|
110
|
+
request_context: "RequestContext"
|
|
111
|
+
|
|
112
|
+
|
|
100
113
|
# =============================================================================
|
|
101
114
|
# Post-operation Contexts (includes results)
|
|
102
115
|
# =============================================================================
|
|
@@ -164,9 +177,28 @@ class ReflectResultContext:
|
|
|
164
177
|
error: str | None = None
|
|
165
178
|
|
|
166
179
|
|
|
180
|
+
# =============================================================================
|
|
181
|
+
# Consolidation Post-operation Context
|
|
182
|
+
# =============================================================================
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
@dataclass
|
|
186
|
+
class ConsolidateResult:
|
|
187
|
+
"""Result context for post-consolidation hook."""
|
|
188
|
+
|
|
189
|
+
bank_id: str
|
|
190
|
+
request_context: "RequestContext"
|
|
191
|
+
# Result
|
|
192
|
+
processed: int = 0
|
|
193
|
+
created: int = 0
|
|
194
|
+
updated: int = 0
|
|
195
|
+
success: bool = True
|
|
196
|
+
error: str | None = None
|
|
197
|
+
|
|
198
|
+
|
|
167
199
|
class OperationValidatorExtension(Extension, ABC):
|
|
168
200
|
"""
|
|
169
|
-
Validates and hooks into retain/recall/reflect operations.
|
|
201
|
+
Validates and hooks into retain/recall/reflect/consolidate operations.
|
|
170
202
|
|
|
171
203
|
This extension allows implementing custom logic such as:
|
|
172
204
|
- Rate limiting (pre-operation)
|
|
@@ -185,9 +217,13 @@ class OperationValidatorExtension(Extension, ABC):
|
|
|
185
217
|
-> config = {"max_requests": "100"}
|
|
186
218
|
|
|
187
219
|
Hook execution order:
|
|
188
|
-
1.
|
|
220
|
+
1. validate_* (pre-operation)
|
|
189
221
|
2. [operation executes]
|
|
190
|
-
3.
|
|
222
|
+
3. on_*_complete (post-operation)
|
|
223
|
+
|
|
224
|
+
Supported operations:
|
|
225
|
+
- retain, recall, reflect (core memory operations)
|
|
226
|
+
- consolidate (mental models consolidation)
|
|
191
227
|
"""
|
|
192
228
|
|
|
193
229
|
# =========================================================================
|
|
@@ -325,3 +361,44 @@ class OperationValidatorExtension(Extension, ABC):
|
|
|
325
361
|
- error: Error message (if failed)
|
|
326
362
|
"""
|
|
327
363
|
pass
|
|
364
|
+
|
|
365
|
+
# =========================================================================
|
|
366
|
+
# Consolidation - Pre-operation validation hook (optional - override to implement)
|
|
367
|
+
# =========================================================================
|
|
368
|
+
|
|
369
|
+
async def validate_consolidate(self, ctx: ConsolidateContext) -> ValidationResult:
|
|
370
|
+
"""
|
|
371
|
+
Validate a consolidation operation before execution.
|
|
372
|
+
|
|
373
|
+
Override to implement custom validation logic for consolidation.
|
|
374
|
+
|
|
375
|
+
Args:
|
|
376
|
+
ctx: Context containing:
|
|
377
|
+
- bank_id: Bank identifier
|
|
378
|
+
- request_context: Request context with auth info
|
|
379
|
+
|
|
380
|
+
Returns:
|
|
381
|
+
ValidationResult indicating whether the operation is allowed.
|
|
382
|
+
"""
|
|
383
|
+
return ValidationResult.accept()
|
|
384
|
+
|
|
385
|
+
# =========================================================================
|
|
386
|
+
# Consolidation - Post-operation hook (optional - override to implement)
|
|
387
|
+
# =========================================================================
|
|
388
|
+
|
|
389
|
+
async def on_consolidate_complete(self, result: ConsolidateResult) -> None:
|
|
390
|
+
"""
|
|
391
|
+
Called after a consolidation operation completes (success or failure).
|
|
392
|
+
|
|
393
|
+
Override to implement post-operation logic such as usage tracking or audit logging.
|
|
394
|
+
|
|
395
|
+
Args:
|
|
396
|
+
result: Result context containing:
|
|
397
|
+
- bank_id: Bank identifier
|
|
398
|
+
- processed: Number of memories processed
|
|
399
|
+
- created: Number of mental models created
|
|
400
|
+
- updated: Number of mental models updated
|
|
401
|
+
- success: Whether the operation succeeded
|
|
402
|
+
- error: Error message (if failed)
|
|
403
|
+
"""
|
|
404
|
+
pass
|
|
@@ -28,6 +28,18 @@ class TenantContext:
|
|
|
28
28
|
schema_name: str
|
|
29
29
|
|
|
30
30
|
|
|
31
|
+
@dataclass
|
|
32
|
+
class Tenant:
|
|
33
|
+
"""
|
|
34
|
+
Represents a tenant for worker discovery.
|
|
35
|
+
|
|
36
|
+
Used by list_tenants() to return tenant information including
|
|
37
|
+
the PostgreSQL schema name for database operations.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
schema: str
|
|
41
|
+
|
|
42
|
+
|
|
31
43
|
class TenantExtension(Extension, ABC):
|
|
32
44
|
"""
|
|
33
45
|
Extension for multi-tenancy and API key authentication.
|
|
@@ -61,3 +73,17 @@ class TenantExtension(Extension, ABC):
|
|
|
61
73
|
AuthenticationError: If authentication fails.
|
|
62
74
|
"""
|
|
63
75
|
...
|
|
76
|
+
|
|
77
|
+
@abstractmethod
|
|
78
|
+
async def list_tenants(self) -> list[Tenant]:
|
|
79
|
+
"""
|
|
80
|
+
List all tenants that should be processed by workers.
|
|
81
|
+
|
|
82
|
+
This method is used by the worker to discover all tenants that need
|
|
83
|
+
task polling. Workers will poll for pending tasks in each tenant's schema.
|
|
84
|
+
|
|
85
|
+
Returns:
|
|
86
|
+
List of Tenant objects containing schema information.
|
|
87
|
+
For single-tenant setups, return [Tenant(schema="public")].
|
|
88
|
+
"""
|
|
89
|
+
...
|
hindsight_api/main.py
CHANGED
|
@@ -184,6 +184,10 @@ def main():
|
|
|
184
184
|
reflect_llm_api_key=config.reflect_llm_api_key,
|
|
185
185
|
reflect_llm_model=config.reflect_llm_model,
|
|
186
186
|
reflect_llm_base_url=config.reflect_llm_base_url,
|
|
187
|
+
consolidation_llm_provider=config.consolidation_llm_provider,
|
|
188
|
+
consolidation_llm_api_key=config.consolidation_llm_api_key,
|
|
189
|
+
consolidation_llm_model=config.consolidation_llm_model,
|
|
190
|
+
consolidation_llm_base_url=config.consolidation_llm_base_url,
|
|
187
191
|
embeddings_provider=config.embeddings_provider,
|
|
188
192
|
embeddings_local_model=config.embeddings_local_model,
|
|
189
193
|
embeddings_tei_url=config.embeddings_tei_url,
|
|
@@ -199,18 +203,20 @@ def main():
|
|
|
199
203
|
host=args.host,
|
|
200
204
|
port=args.port,
|
|
201
205
|
log_level=args.log_level,
|
|
206
|
+
log_format=config.log_format,
|
|
202
207
|
mcp_enabled=config.mcp_enabled,
|
|
203
208
|
graph_retriever=config.graph_retriever,
|
|
204
209
|
mpfp_top_k_neighbors=config.mpfp_top_k_neighbors,
|
|
205
210
|
recall_max_concurrent=config.recall_max_concurrent,
|
|
206
211
|
recall_connection_budget=config.recall_connection_budget,
|
|
207
|
-
observation_min_facts=config.observation_min_facts,
|
|
208
|
-
observation_top_entities=config.observation_top_entities,
|
|
209
212
|
retain_max_completion_tokens=config.retain_max_completion_tokens,
|
|
210
213
|
retain_chunk_size=config.retain_chunk_size,
|
|
211
214
|
retain_extract_causal_links=config.retain_extract_causal_links,
|
|
212
215
|
retain_extraction_mode=config.retain_extraction_mode,
|
|
216
|
+
retain_custom_instructions=config.retain_custom_instructions,
|
|
213
217
|
retain_observations_async=config.retain_observations_async,
|
|
218
|
+
enable_observations=config.enable_observations,
|
|
219
|
+
consolidation_batch_size=config.consolidation_batch_size,
|
|
214
220
|
skip_llm_verification=config.skip_llm_verification,
|
|
215
221
|
lazy_reranker=config.lazy_reranker,
|
|
216
222
|
run_migrations_on_startup=config.run_migrations_on_startup,
|
|
@@ -218,9 +224,14 @@ def main():
|
|
|
218
224
|
db_pool_max_size=config.db_pool_max_size,
|
|
219
225
|
db_command_timeout=config.db_command_timeout,
|
|
220
226
|
db_acquire_timeout=config.db_acquire_timeout,
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
227
|
+
worker_enabled=config.worker_enabled,
|
|
228
|
+
worker_id=config.worker_id,
|
|
229
|
+
worker_poll_interval_ms=config.worker_poll_interval_ms,
|
|
230
|
+
worker_max_retries=config.worker_max_retries,
|
|
231
|
+
worker_batch_size=config.worker_batch_size,
|
|
232
|
+
worker_http_port=config.worker_http_port,
|
|
233
|
+
reflect_max_iterations=config.reflect_max_iterations,
|
|
234
|
+
mental_model_refresh_concurrency=config.mental_model_refresh_concurrency,
|
|
224
235
|
)
|
|
225
236
|
config.configure_logging()
|
|
226
237
|
if not args.daemon:
|
hindsight_api/mcp_local.py
CHANGED
|
@@ -44,7 +44,6 @@ import os
|
|
|
44
44
|
import sys
|
|
45
45
|
|
|
46
46
|
from mcp.server.fastmcp import FastMCP
|
|
47
|
-
from mcp.types import Icon
|
|
48
47
|
|
|
49
48
|
from hindsight_api.config import (
|
|
50
49
|
DEFAULT_MCP_LOCAL_BANK_ID,
|
|
@@ -53,6 +52,7 @@ from hindsight_api.config import (
|
|
|
53
52
|
ENV_MCP_INSTRUCTIONS,
|
|
54
53
|
ENV_MCP_LOCAL_BANK_ID,
|
|
55
54
|
)
|
|
55
|
+
from hindsight_api.mcp_tools import MCPToolsConfig, register_mcp_tools
|
|
56
56
|
|
|
57
57
|
# Configure logging - default to warning to avoid polluting stderr during MCP init
|
|
58
58
|
# MCP clients interpret stderr output as errors, so we suppress INFO logs by default
|
|
@@ -85,9 +85,6 @@ def create_local_mcp_server(bank_id: str, memory=None) -> FastMCP:
|
|
|
85
85
|
"""
|
|
86
86
|
# Import here to avoid slow startup if just checking --help
|
|
87
87
|
from hindsight_api import MemoryEngine
|
|
88
|
-
from hindsight_api.engine.memory_engine import Budget
|
|
89
|
-
from hindsight_api.engine.response_models import VALID_RECALL_FACT_TYPES
|
|
90
|
-
from hindsight_api.models import RequestContext
|
|
91
88
|
|
|
92
89
|
# Create memory engine with pg0 embedded database if not provided
|
|
93
90
|
if memory is None:
|
|
@@ -105,55 +102,17 @@ def create_local_mcp_server(bank_id: str, memory=None) -> FastMCP:
|
|
|
105
102
|
|
|
106
103
|
mcp = FastMCP("hindsight")
|
|
107
104
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
await memory.retain_batch_async(
|
|
120
|
-
bank_id=bank_id,
|
|
121
|
-
contents=[{"content": content, "context": context}],
|
|
122
|
-
request_context=RequestContext(),
|
|
123
|
-
)
|
|
124
|
-
except Exception as e:
|
|
125
|
-
logger.error(f"Error storing memory: {e}", exc_info=True)
|
|
126
|
-
|
|
127
|
-
# Fire and forget - don't block on memory storage
|
|
128
|
-
asyncio.create_task(_retain())
|
|
129
|
-
return {"status": "accepted", "message": "Memory storage initiated"}
|
|
130
|
-
|
|
131
|
-
@mcp.tool(description=recall_description)
|
|
132
|
-
async def recall(query: str, max_tokens: int = 4096, budget: str = "low") -> dict:
|
|
133
|
-
"""
|
|
134
|
-
Args:
|
|
135
|
-
query: Natural language search query (e.g., "user's food preferences", "what projects is user working on")
|
|
136
|
-
max_tokens: Maximum tokens to return in results (default: 4096)
|
|
137
|
-
budget: Search budget level - "low", "mid", or "high" (default: "low")
|
|
138
|
-
"""
|
|
139
|
-
try:
|
|
140
|
-
# Map string budget to enum
|
|
141
|
-
budget_map = {"low": Budget.LOW, "mid": Budget.MID, "high": Budget.HIGH}
|
|
142
|
-
budget_enum = budget_map.get(budget.lower(), Budget.LOW)
|
|
143
|
-
|
|
144
|
-
search_result = await memory.recall_async(
|
|
145
|
-
bank_id=bank_id,
|
|
146
|
-
query=query,
|
|
147
|
-
fact_type=list(VALID_RECALL_FACT_TYPES),
|
|
148
|
-
budget=budget_enum,
|
|
149
|
-
max_tokens=max_tokens,
|
|
150
|
-
request_context=RequestContext(),
|
|
151
|
-
)
|
|
152
|
-
|
|
153
|
-
return search_result.model_dump()
|
|
154
|
-
except Exception as e:
|
|
155
|
-
logger.error(f"Error searching: {e}", exc_info=True)
|
|
156
|
-
return {"error": str(e), "results": []}
|
|
105
|
+
# Configure and register tools using shared module
|
|
106
|
+
config = MCPToolsConfig(
|
|
107
|
+
bank_id_resolver=lambda: bank_id,
|
|
108
|
+
include_bank_id_param=False, # Local MCP uses fixed bank_id
|
|
109
|
+
tools={"retain", "recall"}, # Local MCP only has retain and recall
|
|
110
|
+
retain_description=retain_description,
|
|
111
|
+
recall_description=recall_description,
|
|
112
|
+
retain_fire_and_forget=True, # Local MCP uses fire-and-forget pattern
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
register_mcp_tools(mcp, memory, config)
|
|
157
116
|
|
|
158
117
|
return mcp
|
|
159
118
|
|