hindsight-api 0.2.1__py3-none-any.whl → 0.3.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.
Files changed (46) hide show
  1. hindsight_api/admin/__init__.py +1 -0
  2. hindsight_api/admin/cli.py +252 -0
  3. hindsight_api/alembic/versions/f1a2b3c4d5e6_add_memory_links_composite_index.py +44 -0
  4. hindsight_api/alembic/versions/g2a3b4c5d6e7_add_tags_column.py +48 -0
  5. hindsight_api/api/http.py +282 -20
  6. hindsight_api/api/mcp.py +47 -52
  7. hindsight_api/config.py +238 -6
  8. hindsight_api/engine/cross_encoder.py +599 -86
  9. hindsight_api/engine/db_budget.py +284 -0
  10. hindsight_api/engine/db_utils.py +11 -0
  11. hindsight_api/engine/embeddings.py +453 -26
  12. hindsight_api/engine/entity_resolver.py +8 -5
  13. hindsight_api/engine/interface.py +8 -4
  14. hindsight_api/engine/llm_wrapper.py +241 -27
  15. hindsight_api/engine/memory_engine.py +609 -122
  16. hindsight_api/engine/query_analyzer.py +4 -3
  17. hindsight_api/engine/response_models.py +38 -0
  18. hindsight_api/engine/retain/fact_extraction.py +388 -192
  19. hindsight_api/engine/retain/fact_storage.py +34 -8
  20. hindsight_api/engine/retain/link_utils.py +24 -16
  21. hindsight_api/engine/retain/orchestrator.py +52 -17
  22. hindsight_api/engine/retain/types.py +9 -0
  23. hindsight_api/engine/search/graph_retrieval.py +42 -13
  24. hindsight_api/engine/search/link_expansion_retrieval.py +256 -0
  25. hindsight_api/engine/search/mpfp_retrieval.py +362 -117
  26. hindsight_api/engine/search/reranking.py +2 -2
  27. hindsight_api/engine/search/retrieval.py +847 -200
  28. hindsight_api/engine/search/tags.py +172 -0
  29. hindsight_api/engine/search/think_utils.py +1 -1
  30. hindsight_api/engine/search/trace.py +12 -0
  31. hindsight_api/engine/search/tracer.py +24 -1
  32. hindsight_api/engine/search/types.py +21 -0
  33. hindsight_api/engine/task_backend.py +109 -18
  34. hindsight_api/engine/utils.py +1 -1
  35. hindsight_api/extensions/context.py +10 -1
  36. hindsight_api/main.py +56 -4
  37. hindsight_api/metrics.py +433 -48
  38. hindsight_api/migrations.py +141 -1
  39. hindsight_api/models.py +3 -1
  40. hindsight_api/pg0.py +53 -0
  41. hindsight_api/server.py +39 -2
  42. {hindsight_api-0.2.1.dist-info → hindsight_api-0.3.0.dist-info}/METADATA +5 -1
  43. hindsight_api-0.3.0.dist-info/RECORD +82 -0
  44. {hindsight_api-0.2.1.dist-info → hindsight_api-0.3.0.dist-info}/entry_points.txt +1 -0
  45. hindsight_api-0.2.1.dist-info/RECORD +0 -75
  46. {hindsight_api-0.2.1.dist-info → hindsight_api-0.3.0.dist-info}/WHEEL +0 -0
@@ -84,7 +84,7 @@ class DateparserQueryAnalyzer(QueryAnalyzer):
84
84
 
85
85
  Performance:
86
86
  - ~10-50ms per query
87
- - No model loading required
87
+ - No model loading required (lazy import on first use)
88
88
  """
89
89
 
90
90
  def __init__(self):
@@ -112,8 +112,6 @@ class DateparserQueryAnalyzer(QueryAnalyzer):
112
112
  Returns:
113
113
  QueryAnalysis with temporal_constraint if found
114
114
  """
115
- self.load()
116
-
117
115
  if reference_date is None:
118
116
  reference_date = datetime.now()
119
117
 
@@ -123,6 +121,9 @@ class DateparserQueryAnalyzer(QueryAnalyzer):
123
121
  if period_result is not None:
124
122
  return QueryAnalysis(temporal_constraint=period_result)
125
123
 
124
+ # Lazy load dateparser (only imports on first call, then cached)
125
+ self.load()
126
+
126
127
  # Use dateparser's search_dates to find temporal expressions
127
128
  settings = {
128
129
  "RELATIVE_BASE": reference_date,
@@ -14,6 +14,37 @@ from pydantic import BaseModel, ConfigDict, Field
14
14
  VALID_RECALL_FACT_TYPES = frozenset(["world", "experience", "opinion"])
15
15
 
16
16
 
17
+ class TokenUsage(BaseModel):
18
+ """
19
+ Token usage metrics for LLM calls.
20
+
21
+ Tracks input/output tokens for a single request to enable
22
+ per-request cost tracking and monitoring.
23
+ """
24
+
25
+ model_config = ConfigDict(
26
+ json_schema_extra={
27
+ "example": {
28
+ "input_tokens": 1500,
29
+ "output_tokens": 500,
30
+ "total_tokens": 2000,
31
+ }
32
+ }
33
+ )
34
+
35
+ input_tokens: int = Field(default=0, description="Number of input/prompt tokens consumed")
36
+ output_tokens: int = Field(default=0, description="Number of output/completion tokens generated")
37
+ total_tokens: int = Field(default=0, description="Total tokens (input + output)")
38
+
39
+ def __add__(self, other: "TokenUsage") -> "TokenUsage":
40
+ """Allow aggregating token usage from multiple calls."""
41
+ return TokenUsage(
42
+ input_tokens=self.input_tokens + other.input_tokens,
43
+ output_tokens=self.output_tokens + other.output_tokens,
44
+ total_tokens=self.total_tokens + other.total_tokens,
45
+ )
46
+
47
+
17
48
  class DispositionTraits(BaseModel):
18
49
  """
19
50
  Disposition traits for a memory bank.
@@ -54,6 +85,7 @@ class MemoryFact(BaseModel):
54
85
  "metadata": {"source": "slack"},
55
86
  "chunk_id": "bank123_session_abc123_0",
56
87
  "activation": 0.95,
88
+ "tags": ["user_a", "session_123"],
57
89
  }
58
90
  }
59
91
  )
@@ -71,6 +103,7 @@ class MemoryFact(BaseModel):
71
103
  chunk_id: str | None = Field(
72
104
  None, description="ID of the chunk this fact was extracted from (format: bank_id_document_id_chunk_index)"
73
105
  )
106
+ tags: list[str] | None = Field(None, description="Visibility scope tags associated with this fact")
74
107
 
75
108
 
76
109
  class ChunkInfo(BaseModel):
@@ -147,6 +180,7 @@ class ReflectResult(BaseModel):
147
180
  },
148
181
  "new_opinions": ["Machine learning has great potential in healthcare"],
149
182
  "structured_output": {"summary": "ML in healthcare", "confidence": 0.9},
183
+ "usage": {"input_tokens": 1500, "output_tokens": 500, "total_tokens": 2000},
150
184
  }
151
185
  }
152
186
  )
@@ -160,6 +194,10 @@ class ReflectResult(BaseModel):
160
194
  default=None,
161
195
  description="Structured output parsed according to the provided response schema. Only present when response_schema was provided.",
162
196
  )
197
+ usage: TokenUsage | None = Field(
198
+ default=None,
199
+ description="Token usage metrics for the LLM calls made during this reflect operation.",
200
+ )
163
201
 
164
202
 
165
203
  class Opinion(BaseModel):