hindsight-api 0.1.5__py3-none-any.whl → 0.1.7__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 (64) hide show
  1. hindsight_api/__init__.py +10 -9
  2. hindsight_api/alembic/env.py +5 -8
  3. hindsight_api/alembic/versions/5a366d414dce_initial_schema.py +266 -180
  4. hindsight_api/alembic/versions/b7c4d8e9f1a2_add_chunks_table.py +32 -32
  5. hindsight_api/alembic/versions/c8e5f2a3b4d1_add_retain_params_to_documents.py +11 -11
  6. hindsight_api/alembic/versions/d9f6a3b4c5e2_rename_bank_to_interactions.py +7 -12
  7. hindsight_api/alembic/versions/e0a1b2c3d4e5_disposition_to_3_traits.py +23 -15
  8. hindsight_api/alembic/versions/rename_personality_to_disposition.py +30 -21
  9. hindsight_api/api/__init__.py +10 -10
  10. hindsight_api/api/http.py +575 -593
  11. hindsight_api/api/mcp.py +30 -28
  12. hindsight_api/banner.py +13 -6
  13. hindsight_api/config.py +9 -13
  14. hindsight_api/engine/__init__.py +9 -9
  15. hindsight_api/engine/cross_encoder.py +22 -21
  16. hindsight_api/engine/db_utils.py +5 -4
  17. hindsight_api/engine/embeddings.py +22 -21
  18. hindsight_api/engine/entity_resolver.py +81 -75
  19. hindsight_api/engine/llm_wrapper.py +61 -79
  20. hindsight_api/engine/memory_engine.py +603 -625
  21. hindsight_api/engine/query_analyzer.py +100 -97
  22. hindsight_api/engine/response_models.py +105 -106
  23. hindsight_api/engine/retain/__init__.py +9 -16
  24. hindsight_api/engine/retain/bank_utils.py +34 -58
  25. hindsight_api/engine/retain/chunk_storage.py +4 -12
  26. hindsight_api/engine/retain/deduplication.py +9 -28
  27. hindsight_api/engine/retain/embedding_processing.py +4 -11
  28. hindsight_api/engine/retain/embedding_utils.py +3 -4
  29. hindsight_api/engine/retain/entity_processing.py +7 -17
  30. hindsight_api/engine/retain/fact_extraction.py +155 -165
  31. hindsight_api/engine/retain/fact_storage.py +11 -23
  32. hindsight_api/engine/retain/link_creation.py +11 -39
  33. hindsight_api/engine/retain/link_utils.py +166 -95
  34. hindsight_api/engine/retain/observation_regeneration.py +39 -52
  35. hindsight_api/engine/retain/orchestrator.py +72 -62
  36. hindsight_api/engine/retain/types.py +49 -43
  37. hindsight_api/engine/search/__init__.py +5 -5
  38. hindsight_api/engine/search/fusion.py +6 -15
  39. hindsight_api/engine/search/graph_retrieval.py +22 -23
  40. hindsight_api/engine/search/mpfp_retrieval.py +76 -92
  41. hindsight_api/engine/search/observation_utils.py +9 -16
  42. hindsight_api/engine/search/reranking.py +4 -7
  43. hindsight_api/engine/search/retrieval.py +87 -66
  44. hindsight_api/engine/search/scoring.py +5 -7
  45. hindsight_api/engine/search/temporal_extraction.py +8 -11
  46. hindsight_api/engine/search/think_utils.py +115 -39
  47. hindsight_api/engine/search/trace.py +68 -39
  48. hindsight_api/engine/search/tracer.py +44 -35
  49. hindsight_api/engine/search/types.py +20 -17
  50. hindsight_api/engine/task_backend.py +21 -26
  51. hindsight_api/engine/utils.py +25 -10
  52. hindsight_api/main.py +21 -40
  53. hindsight_api/mcp_local.py +190 -0
  54. hindsight_api/metrics.py +44 -30
  55. hindsight_api/migrations.py +10 -8
  56. hindsight_api/models.py +60 -72
  57. hindsight_api/pg0.py +22 -23
  58. hindsight_api/server.py +3 -6
  59. hindsight_api-0.1.7.dist-info/METADATA +178 -0
  60. hindsight_api-0.1.7.dist-info/RECORD +64 -0
  61. {hindsight_api-0.1.5.dist-info → hindsight_api-0.1.7.dist-info}/entry_points.txt +1 -0
  62. hindsight_api-0.1.5.dist-info/METADATA +0 -42
  63. hindsight_api-0.1.5.dist-info/RECORD +0 -63
  64. {hindsight_api-0.1.5.dist-info → hindsight_api-0.1.7.dist-info}/WHEEL +0 -0
@@ -3,10 +3,9 @@ Fact storage for retain pipeline.
3
3
 
4
4
  Handles insertion of facts into the database.
5
5
  """
6
- import logging
6
+
7
7
  import json
8
- from typing import List, Optional
9
- from uuid import UUID
8
+ import logging
10
9
 
11
10
  from .types import ProcessedFact
12
11
 
@@ -14,11 +13,8 @@ logger = logging.getLogger(__name__)
14
13
 
15
14
 
16
15
  async def insert_facts_batch(
17
- conn,
18
- bank_id: str,
19
- facts: List[ProcessedFact],
20
- document_id: Optional[str] = None
21
- ) -> List[str]:
16
+ conn, bank_id: str, facts: list[ProcessedFact], document_id: str | None = None
17
+ ) -> list[str]:
22
18
  """
23
19
  Insert facts into the database in batch.
24
20
 
@@ -62,7 +58,7 @@ async def insert_facts_batch(
62
58
  contexts.append(fact.context)
63
59
  fact_types.append(fact.fact_type)
64
60
  # confidence_score is only for opinion facts
65
- confidence_scores.append(1.0 if fact.fact_type == 'opinion' else None)
61
+ confidence_scores.append(1.0 if fact.fact_type == "opinion" else None)
66
62
  access_counts.append(0) # Initial access count
67
63
  metadata_jsons.append(json.dumps(fact.metadata))
68
64
  chunk_ids.append(fact.chunk_id)
@@ -93,10 +89,10 @@ async def insert_facts_batch(
93
89
  access_counts,
94
90
  metadata_jsons,
95
91
  chunk_ids,
96
- document_ids
92
+ document_ids,
97
93
  )
98
94
 
99
- unit_ids = [str(row['id']) for row in results]
95
+ unit_ids = [str(row["id"]) for row in results]
100
96
  return unit_ids
101
97
 
102
98
 
@@ -119,17 +115,12 @@ async def ensure_bank_exists(conn, bank_id: str) -> None:
119
115
  """,
120
116
  bank_id,
121
117
  '{"skepticism": 3, "literalism": 3, "empathy": 3}',
122
- ""
118
+ "",
123
119
  )
124
120
 
125
121
 
126
122
  async def handle_document_tracking(
127
- conn,
128
- bank_id: str,
129
- document_id: str,
130
- combined_content: str,
131
- is_first_batch: bool,
132
- retain_params: Optional[dict] = None
123
+ conn, bank_id: str, document_id: str, combined_content: str, is_first_batch: bool, retain_params: dict | None = None
133
124
  ) -> None:
134
125
  """
135
126
  Handle document tracking in the database.
@@ -150,10 +141,7 @@ async def handle_document_tracking(
150
141
  # Always delete old document first if it exists (cascades to units and links)
151
142
  # Only delete on the first batch to avoid deleting data we just inserted
152
143
  if is_first_batch:
153
- await conn.fetchval(
154
- "DELETE FROM documents WHERE id = $1 AND bank_id = $2 RETURNING id",
155
- document_id, bank_id
156
- )
144
+ await conn.fetchval("DELETE FROM documents WHERE id = $1 AND bank_id = $2 RETURNING id", document_id, bank_id)
157
145
 
158
146
  # Insert document (or update if exists from concurrent operations)
159
147
  await conn.execute(
@@ -172,5 +160,5 @@ async def handle_document_tracking(
172
160
  combined_content,
173
161
  content_hash,
174
162
  json.dumps({}), # Empty metadata dict
175
- json.dumps(retain_params) if retain_params else None
163
+ json.dumps(retain_params) if retain_params else None,
176
164
  )
@@ -3,20 +3,16 @@ Link creation for retain pipeline.
3
3
 
4
4
  Handles creation of temporal, semantic, and causal links between facts.
5
5
  """
6
+
6
7
  import logging
7
- from typing import List
8
8
 
9
- from .types import ProcessedFact, CausalRelation
10
9
  from . import link_utils
10
+ from .types import ProcessedFact
11
11
 
12
12
  logger = logging.getLogger(__name__)
13
13
 
14
14
 
15
- async def create_temporal_links_batch(
16
- conn,
17
- bank_id: str,
18
- unit_ids: List[str]
19
- ) -> int:
15
+ async def create_temporal_links_batch(conn, bank_id: str, unit_ids: list[str]) -> int:
20
16
  """
21
17
  Create temporal links between facts.
22
18
 
@@ -33,20 +29,10 @@ async def create_temporal_links_batch(
33
29
  if not unit_ids:
34
30
  return 0
35
31
 
36
- return await link_utils.create_temporal_links_batch_per_fact(
37
- conn,
38
- bank_id,
39
- unit_ids,
40
- log_buffer=[]
41
- )
32
+ return await link_utils.create_temporal_links_batch_per_fact(conn, bank_id, unit_ids, log_buffer=[])
42
33
 
43
34
 
44
- async def create_semantic_links_batch(
45
- conn,
46
- bank_id: str,
47
- unit_ids: List[str],
48
- embeddings: List[List[float]]
49
- ) -> int:
35
+ async def create_semantic_links_batch(conn, bank_id: str, unit_ids: list[str], embeddings: list[list[float]]) -> int:
50
36
  """
51
37
  Create semantic links between facts.
52
38
 
@@ -67,20 +53,10 @@ async def create_semantic_links_batch(
67
53
  if len(unit_ids) != len(embeddings):
68
54
  raise ValueError(f"Mismatch between unit_ids ({len(unit_ids)}) and embeddings ({len(embeddings)})")
69
55
 
70
- return await link_utils.create_semantic_links_batch(
71
- conn,
72
- bank_id,
73
- unit_ids,
74
- embeddings,
75
- log_buffer=[]
76
- )
56
+ return await link_utils.create_semantic_links_batch(conn, bank_id, unit_ids, embeddings, log_buffer=[])
77
57
 
78
58
 
79
- async def create_causal_links_batch(
80
- conn,
81
- unit_ids: List[str],
82
- facts: List[ProcessedFact]
83
- ) -> int:
59
+ async def create_causal_links_batch(conn, unit_ids: list[str], facts: list[ProcessedFact]) -> int:
84
60
  """
85
61
  Create causal links between facts.
86
62
 
@@ -108,9 +84,9 @@ async def create_causal_links_batch(
108
84
  # Convert CausalRelation objects to dicts
109
85
  relations_dicts = [
110
86
  {
111
- 'relation_type': rel.relation_type,
112
- 'target_fact_index': rel.target_fact_index,
113
- 'strength': rel.strength
87
+ "relation_type": rel.relation_type,
88
+ "target_fact_index": rel.target_fact_index,
89
+ "strength": rel.strength,
114
90
  }
115
91
  for rel in fact.causal_relations
116
92
  ]
@@ -118,10 +94,6 @@ async def create_causal_links_batch(
118
94
  else:
119
95
  causal_relations_per_fact.append([])
120
96
 
121
- link_count = await link_utils.create_causal_links_batch(
122
- conn,
123
- unit_ids,
124
- causal_relations_per_fact
125
- )
97
+ link_count = await link_utils.create_causal_links_batch(conn, unit_ids, causal_relations_per_fact)
126
98
 
127
99
  return link_count