cognee 0.3.6__py3-none-any.whl → 0.3.7.dev1__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 (182) hide show
  1. cognee/__init__.py +1 -0
  2. cognee/api/health.py +2 -12
  3. cognee/api/v1/add/add.py +46 -6
  4. cognee/api/v1/add/routers/get_add_router.py +11 -2
  5. cognee/api/v1/cognify/cognify.py +29 -9
  6. cognee/api/v1/cognify/routers/get_cognify_router.py +2 -1
  7. cognee/api/v1/datasets/datasets.py +11 -0
  8. cognee/api/v1/datasets/routers/get_datasets_router.py +8 -0
  9. cognee/api/v1/delete/routers/get_delete_router.py +2 -0
  10. cognee/api/v1/memify/routers/get_memify_router.py +2 -1
  11. cognee/api/v1/permissions/routers/get_permissions_router.py +6 -0
  12. cognee/api/v1/responses/default_tools.py +0 -1
  13. cognee/api/v1/responses/dispatch_function.py +1 -1
  14. cognee/api/v1/responses/routers/default_tools.py +0 -1
  15. cognee/api/v1/search/routers/get_search_router.py +3 -3
  16. cognee/api/v1/search/search.py +11 -9
  17. cognee/api/v1/settings/routers/get_settings_router.py +7 -1
  18. cognee/api/v1/sync/routers/get_sync_router.py +3 -0
  19. cognee/api/v1/ui/ui.py +45 -16
  20. cognee/api/v1/update/routers/get_update_router.py +3 -1
  21. cognee/api/v1/update/update.py +3 -3
  22. cognee/api/v1/users/routers/get_visualize_router.py +2 -0
  23. cognee/cli/_cognee.py +61 -10
  24. cognee/cli/commands/add_command.py +3 -3
  25. cognee/cli/commands/cognify_command.py +3 -3
  26. cognee/cli/commands/config_command.py +9 -7
  27. cognee/cli/commands/delete_command.py +3 -3
  28. cognee/cli/commands/search_command.py +3 -7
  29. cognee/cli/config.py +0 -1
  30. cognee/context_global_variables.py +5 -0
  31. cognee/exceptions/exceptions.py +1 -1
  32. cognee/infrastructure/databases/cache/__init__.py +2 -0
  33. cognee/infrastructure/databases/cache/cache_db_interface.py +79 -0
  34. cognee/infrastructure/databases/cache/config.py +44 -0
  35. cognee/infrastructure/databases/cache/get_cache_engine.py +67 -0
  36. cognee/infrastructure/databases/cache/redis/RedisAdapter.py +243 -0
  37. cognee/infrastructure/databases/exceptions/__init__.py +1 -0
  38. cognee/infrastructure/databases/exceptions/exceptions.py +18 -2
  39. cognee/infrastructure/databases/graph/get_graph_engine.py +1 -1
  40. cognee/infrastructure/databases/graph/graph_db_interface.py +5 -0
  41. cognee/infrastructure/databases/graph/kuzu/adapter.py +76 -47
  42. cognee/infrastructure/databases/graph/neo4j_driver/adapter.py +13 -3
  43. cognee/infrastructure/databases/graph/neo4j_driver/deadlock_retry.py +1 -1
  44. cognee/infrastructure/databases/graph/neptune_driver/neptune_utils.py +1 -1
  45. cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py +1 -1
  46. cognee/infrastructure/databases/vector/embeddings/FastembedEmbeddingEngine.py +21 -3
  47. cognee/infrastructure/databases/vector/embeddings/LiteLLMEmbeddingEngine.py +17 -10
  48. cognee/infrastructure/databases/vector/embeddings/OllamaEmbeddingEngine.py +17 -4
  49. cognee/infrastructure/databases/vector/embeddings/config.py +2 -3
  50. cognee/infrastructure/databases/vector/exceptions/exceptions.py +1 -1
  51. cognee/infrastructure/databases/vector/lancedb/LanceDBAdapter.py +0 -1
  52. cognee/infrastructure/files/exceptions.py +1 -1
  53. cognee/infrastructure/files/storage/LocalFileStorage.py +9 -9
  54. cognee/infrastructure/files/storage/S3FileStorage.py +11 -11
  55. cognee/infrastructure/files/utils/guess_file_type.py +6 -0
  56. cognee/infrastructure/llm/prompts/feedback_reaction_prompt.txt +14 -0
  57. cognee/infrastructure/llm/prompts/feedback_report_prompt.txt +13 -0
  58. cognee/infrastructure/llm/prompts/feedback_user_context_prompt.txt +5 -0
  59. cognee/infrastructure/llm/prompts/search_type_selector_prompt.txt +0 -5
  60. cognee/infrastructure/llm/structured_output_framework/litellm_instructor/llm/anthropic/adapter.py +19 -9
  61. cognee/infrastructure/llm/structured_output_framework/litellm_instructor/llm/gemini/adapter.py +17 -5
  62. cognee/infrastructure/llm/structured_output_framework/litellm_instructor/llm/generic_llm_api/adapter.py +17 -5
  63. cognee/infrastructure/llm/structured_output_framework/litellm_instructor/llm/get_llm_client.py +32 -0
  64. cognee/infrastructure/llm/structured_output_framework/litellm_instructor/llm/mistral/__init__.py +0 -0
  65. cognee/infrastructure/llm/structured_output_framework/litellm_instructor/llm/mistral/adapter.py +109 -0
  66. cognee/infrastructure/llm/structured_output_framework/litellm_instructor/llm/ollama/adapter.py +33 -8
  67. cognee/infrastructure/llm/structured_output_framework/litellm_instructor/llm/openai/adapter.py +40 -18
  68. cognee/infrastructure/loaders/LoaderEngine.py +27 -7
  69. cognee/infrastructure/loaders/external/__init__.py +7 -0
  70. cognee/infrastructure/loaders/external/advanced_pdf_loader.py +2 -8
  71. cognee/infrastructure/loaders/external/beautiful_soup_loader.py +310 -0
  72. cognee/infrastructure/loaders/supported_loaders.py +7 -0
  73. cognee/modules/data/exceptions/exceptions.py +1 -1
  74. cognee/modules/data/methods/__init__.py +3 -0
  75. cognee/modules/data/methods/get_dataset_data.py +4 -1
  76. cognee/modules/data/methods/has_dataset_data.py +21 -0
  77. cognee/modules/engine/models/TableRow.py +0 -1
  78. cognee/modules/ingestion/save_data_to_file.py +9 -2
  79. cognee/modules/pipelines/exceptions/exceptions.py +1 -1
  80. cognee/modules/pipelines/operations/pipeline.py +12 -1
  81. cognee/modules/pipelines/operations/run_tasks.py +25 -197
  82. cognee/modules/pipelines/operations/run_tasks_base.py +7 -0
  83. cognee/modules/pipelines/operations/run_tasks_data_item.py +260 -0
  84. cognee/modules/pipelines/operations/run_tasks_distributed.py +121 -38
  85. cognee/modules/pipelines/operations/run_tasks_with_telemetry.py +9 -1
  86. cognee/modules/retrieval/EntityCompletionRetriever.py +48 -8
  87. cognee/modules/retrieval/base_graph_retriever.py +3 -1
  88. cognee/modules/retrieval/base_retriever.py +3 -1
  89. cognee/modules/retrieval/chunks_retriever.py +5 -1
  90. cognee/modules/retrieval/code_retriever.py +20 -2
  91. cognee/modules/retrieval/completion_retriever.py +50 -9
  92. cognee/modules/retrieval/cypher_search_retriever.py +11 -1
  93. cognee/modules/retrieval/graph_completion_context_extension_retriever.py +47 -8
  94. cognee/modules/retrieval/graph_completion_cot_retriever.py +152 -22
  95. cognee/modules/retrieval/graph_completion_retriever.py +54 -10
  96. cognee/modules/retrieval/lexical_retriever.py +20 -2
  97. cognee/modules/retrieval/natural_language_retriever.py +10 -1
  98. cognee/modules/retrieval/summaries_retriever.py +5 -1
  99. cognee/modules/retrieval/temporal_retriever.py +62 -10
  100. cognee/modules/retrieval/user_qa_feedback.py +3 -2
  101. cognee/modules/retrieval/utils/completion.py +30 -4
  102. cognee/modules/retrieval/utils/description_to_codepart_search.py +1 -1
  103. cognee/modules/retrieval/utils/session_cache.py +156 -0
  104. cognee/modules/search/methods/get_search_type_tools.py +0 -5
  105. cognee/modules/search/methods/no_access_control_search.py +12 -1
  106. cognee/modules/search/methods/search.py +51 -5
  107. cognee/modules/search/types/SearchType.py +0 -1
  108. cognee/modules/settings/get_settings.py +23 -0
  109. cognee/modules/users/methods/get_authenticated_user.py +3 -1
  110. cognee/modules/users/methods/get_default_user.py +1 -6
  111. cognee/modules/users/roles/methods/create_role.py +2 -2
  112. cognee/modules/users/tenants/methods/create_tenant.py +2 -2
  113. cognee/shared/exceptions/exceptions.py +1 -1
  114. cognee/shared/logging_utils.py +18 -11
  115. cognee/shared/utils.py +24 -2
  116. cognee/tasks/codingagents/coding_rule_associations.py +1 -2
  117. cognee/tasks/documents/exceptions/exceptions.py +1 -1
  118. cognee/tasks/feedback/__init__.py +13 -0
  119. cognee/tasks/feedback/create_enrichments.py +84 -0
  120. cognee/tasks/feedback/extract_feedback_interactions.py +230 -0
  121. cognee/tasks/feedback/generate_improved_answers.py +130 -0
  122. cognee/tasks/feedback/link_enrichments_to_feedback.py +67 -0
  123. cognee/tasks/feedback/models.py +26 -0
  124. cognee/tasks/graph/extract_graph_from_data.py +2 -0
  125. cognee/tasks/ingestion/data_item_to_text_file.py +3 -3
  126. cognee/tasks/ingestion/ingest_data.py +11 -5
  127. cognee/tasks/ingestion/save_data_item_to_storage.py +12 -1
  128. cognee/tasks/storage/add_data_points.py +3 -10
  129. cognee/tasks/storage/index_data_points.py +19 -14
  130. cognee/tasks/storage/index_graph_edges.py +25 -11
  131. cognee/tasks/web_scraper/__init__.py +34 -0
  132. cognee/tasks/web_scraper/config.py +26 -0
  133. cognee/tasks/web_scraper/default_url_crawler.py +446 -0
  134. cognee/tasks/web_scraper/models.py +46 -0
  135. cognee/tasks/web_scraper/types.py +4 -0
  136. cognee/tasks/web_scraper/utils.py +142 -0
  137. cognee/tasks/web_scraper/web_scraper_task.py +396 -0
  138. cognee/tests/cli_tests/cli_unit_tests/test_cli_utils.py +0 -1
  139. cognee/tests/integration/web_url_crawler/test_default_url_crawler.py +13 -0
  140. cognee/tests/integration/web_url_crawler/test_tavily_crawler.py +19 -0
  141. cognee/tests/integration/web_url_crawler/test_url_adding_e2e.py +344 -0
  142. cognee/tests/subprocesses/reader.py +25 -0
  143. cognee/tests/subprocesses/simple_cognify_1.py +31 -0
  144. cognee/tests/subprocesses/simple_cognify_2.py +31 -0
  145. cognee/tests/subprocesses/writer.py +32 -0
  146. cognee/tests/tasks/descriptive_metrics/metrics_test_utils.py +0 -2
  147. cognee/tests/tasks/descriptive_metrics/neo4j_metrics_test.py +8 -3
  148. cognee/tests/tasks/entity_extraction/entity_extraction_test.py +89 -0
  149. cognee/tests/tasks/web_scraping/web_scraping_test.py +172 -0
  150. cognee/tests/test_add_docling_document.py +56 -0
  151. cognee/tests/test_chromadb.py +7 -11
  152. cognee/tests/test_concurrent_subprocess_access.py +76 -0
  153. cognee/tests/test_conversation_history.py +240 -0
  154. cognee/tests/test_feedback_enrichment.py +174 -0
  155. cognee/tests/test_kuzu.py +27 -15
  156. cognee/tests/test_lancedb.py +7 -11
  157. cognee/tests/test_library.py +32 -2
  158. cognee/tests/test_neo4j.py +24 -16
  159. cognee/tests/test_neptune_analytics_vector.py +7 -11
  160. cognee/tests/test_permissions.py +9 -13
  161. cognee/tests/test_pgvector.py +4 -4
  162. cognee/tests/test_remote_kuzu.py +8 -11
  163. cognee/tests/test_s3_file_storage.py +1 -1
  164. cognee/tests/test_search_db.py +6 -8
  165. cognee/tests/unit/infrastructure/databases/cache/test_cache_config.py +89 -0
  166. cognee/tests/unit/modules/retrieval/conversation_history_test.py +154 -0
  167. cognee/tests/unit/modules/retrieval/graph_completion_retriever_cot_test.py +51 -0
  168. {cognee-0.3.6.dist-info → cognee-0.3.7.dev1.dist-info}/METADATA +21 -6
  169. {cognee-0.3.6.dist-info → cognee-0.3.7.dev1.dist-info}/RECORD +178 -139
  170. {cognee-0.3.6.dist-info → cognee-0.3.7.dev1.dist-info}/entry_points.txt +1 -0
  171. distributed/Dockerfile +0 -3
  172. distributed/entrypoint.py +21 -9
  173. distributed/signal.py +5 -0
  174. distributed/workers/data_point_saving_worker.py +64 -34
  175. distributed/workers/graph_saving_worker.py +71 -47
  176. cognee/infrastructure/databases/graph/memgraph/memgraph_adapter.py +0 -1116
  177. cognee/modules/retrieval/insights_retriever.py +0 -133
  178. cognee/tests/test_memgraph.py +0 -109
  179. cognee/tests/unit/modules/retrieval/insights_retriever_test.py +0 -251
  180. {cognee-0.3.6.dist-info → cognee-0.3.7.dev1.dist-info}/WHEEL +0 -0
  181. {cognee-0.3.6.dist-info → cognee-0.3.7.dev1.dist-info}/licenses/LICENSE +0 -0
  182. {cognee-0.3.6.dist-info → cognee-0.3.7.dev1.dist-info}/licenses/NOTICE.md +0 -0
@@ -12,6 +12,7 @@ from cognee.modules.sync.methods import get_running_sync_operations_for_user, ge
12
12
  from cognee.shared.utils import send_telemetry
13
13
  from cognee.shared.logging_utils import get_logger
14
14
  from cognee.api.v1.sync import SyncResponse
15
+ from cognee import __version__ as cognee_version
15
16
  from cognee.context_global_variables import set_database_global_context_variables
16
17
 
17
18
  logger = get_logger()
@@ -99,6 +100,7 @@ def get_sync_router() -> APIRouter:
99
100
  user.id,
100
101
  additional_properties={
101
102
  "endpoint": "POST /v1/sync",
103
+ "cognee_version": cognee_version,
102
104
  "dataset_ids": [str(id) for id in request.dataset_ids]
103
105
  if request.dataset_ids
104
106
  else "*",
@@ -205,6 +207,7 @@ def get_sync_router() -> APIRouter:
205
207
  user.id,
206
208
  additional_properties={
207
209
  "endpoint": "GET /v1/sync/status",
210
+ "cognee_version": cognee_version,
208
211
  },
209
212
  )
210
213
 
cognee/api/v1/ui/ui.py CHANGED
@@ -502,22 +502,46 @@ def start_ui(
502
502
 
503
503
  if start_mcp:
504
504
  logger.info("Starting Cognee MCP server with Docker...")
505
- cwd = os.getcwd()
506
- env_file = os.path.join(cwd, ".env")
507
505
  try:
506
+ image = "cognee/cognee-mcp:main"
507
+ subprocess.run(["docker", "pull", image], check=True)
508
+
509
+ import uuid
510
+
511
+ container_name = f"cognee-mcp-{uuid.uuid4().hex[:8]}"
512
+
513
+ docker_cmd = [
514
+ "docker",
515
+ "run",
516
+ "--name",
517
+ container_name,
518
+ "-p",
519
+ f"{mcp_port}:8000",
520
+ "--rm",
521
+ "-e",
522
+ "TRANSPORT_MODE=sse",
523
+ ]
524
+
525
+ if start_backend:
526
+ docker_cmd.extend(
527
+ [
528
+ "-e",
529
+ f"API_URL=http://localhost:{backend_port}",
530
+ ]
531
+ )
532
+ logger.info(
533
+ f"Configuring MCP to connect to backend API at http://localhost:{backend_port}"
534
+ )
535
+ logger.info("(localhost will be auto-converted to host.docker.internal)")
536
+ else:
537
+ cwd = os.getcwd()
538
+ env_file = os.path.join(cwd, ".env")
539
+ docker_cmd.extend(["--env-file", env_file])
540
+
541
+ docker_cmd.append(image)
542
+
508
543
  mcp_process = subprocess.Popen(
509
- [
510
- "docker",
511
- "run",
512
- "-p",
513
- f"{mcp_port}:8000",
514
- "--rm",
515
- "--env-file",
516
- env_file,
517
- "-e",
518
- "TRANSPORT_MODE=sse",
519
- "cognee/cognee-mcp:main",
520
- ],
544
+ docker_cmd,
521
545
  stdout=subprocess.PIPE,
522
546
  stderr=subprocess.PIPE,
523
547
  preexec_fn=os.setsid if hasattr(os, "setsid") else None,
@@ -526,8 +550,13 @@ def start_ui(
526
550
  _stream_process_output(mcp_process, "stdout", "[MCP]", "\033[34m") # Blue
527
551
  _stream_process_output(mcp_process, "stderr", "[MCP]", "\033[34m") # Blue
528
552
 
529
- pid_callback(mcp_process.pid)
530
- logger.info(f"✓ Cognee MCP server starting on http://127.0.0.1:{mcp_port}/sse")
553
+ # Pass both PID and container name using a tuple
554
+ pid_callback((mcp_process.pid, container_name))
555
+
556
+ mode_info = "API mode" if start_backend else "direct mode"
557
+ logger.info(
558
+ f"✓ Cognee MCP server starting on http://127.0.0.1:{mcp_port}/sse ({mode_info})"
559
+ )
531
560
  except Exception as e:
532
561
  logger.error(f"Failed to start MCP server with Docker: {str(e)}")
533
562
  # Start backend server if requested
@@ -9,6 +9,7 @@ from cognee.shared.logging_utils import get_logger
9
9
  from cognee.modules.users.models import User
10
10
  from cognee.modules.users.methods import get_authenticated_user
11
11
  from cognee.shared.utils import send_telemetry
12
+ from cognee import __version__ as cognee_version
12
13
  from cognee.modules.pipelines.models.PipelineRunInfo import (
13
14
  PipelineRunErrored,
14
15
  )
@@ -64,6 +65,7 @@ def get_update_router() -> APIRouter:
64
65
  "dataset_id": str(dataset_id),
65
66
  "data_id": str(data_id),
66
67
  "node_set": str(node_set),
68
+ "cognee_version": cognee_version,
67
69
  },
68
70
  )
69
71
 
@@ -75,7 +77,7 @@ def get_update_router() -> APIRouter:
75
77
  data=data,
76
78
  dataset_id=dataset_id,
77
79
  user=user,
78
- node_set=node_set,
80
+ node_set=node_set if node_set else None,
79
81
  )
80
82
 
81
83
  # If any cognify run errored return JSONResponse with proper error status code
@@ -1,5 +1,5 @@
1
1
  from uuid import UUID
2
- from typing import Union, BinaryIO, List, Optional
2
+ from typing import Union, BinaryIO, List, Optional, Any
3
3
 
4
4
  from cognee.modules.users.models import User
5
5
  from cognee.api.v1.delete import delete
@@ -10,12 +10,12 @@ from cognee.api.v1.cognify import cognify
10
10
  async def update(
11
11
  data_id: UUID,
12
12
  data: Union[BinaryIO, list[BinaryIO], str, list[str]],
13
+ dataset_id: UUID,
13
14
  user: User = None,
14
15
  node_set: Optional[List[str]] = None,
15
- dataset_id: Optional[UUID] = None,
16
16
  vector_db_config: dict = None,
17
17
  graph_db_config: dict = None,
18
- preferred_loaders: List[str] = None,
18
+ preferred_loaders: dict[str, dict[str, Any]] = None,
19
19
  incremental_loading: bool = True,
20
20
  ):
21
21
  """
@@ -8,6 +8,7 @@ from cognee.modules.users.models import User
8
8
 
9
9
  from cognee.context_global_variables import set_database_global_context_variables
10
10
  from cognee.shared.utils import send_telemetry
11
+ from cognee import __version__ as cognee_version
11
12
 
12
13
  logger = get_logger()
13
14
 
@@ -46,6 +47,7 @@ def get_visualize_router() -> APIRouter:
46
47
  additional_properties={
47
48
  "endpoint": "GET /v1/visualize",
48
49
  "dataset_id": str(dataset_id),
50
+ "cognee_version": cognee_version,
49
51
  },
50
52
  )
51
53
 
cognee/cli/_cognee.py CHANGED
@@ -175,19 +175,59 @@ def main() -> int:
175
175
  # Handle UI flag
176
176
  if hasattr(args, "start_ui") and args.start_ui:
177
177
  spawned_pids = []
178
+ docker_container = None
178
179
 
179
180
  def signal_handler(signum, frame):
180
181
  """Handle Ctrl+C and other termination signals"""
181
- nonlocal spawned_pids
182
- fmt.echo("\nShutting down UI server...")
182
+ nonlocal spawned_pids, docker_container
183
183
 
184
+ try:
185
+ fmt.echo("\nShutting down UI server...")
186
+ except (BrokenPipeError, OSError):
187
+ pass
188
+
189
+ # First, stop Docker container if running
190
+ if docker_container:
191
+ try:
192
+ result = subprocess.run(
193
+ ["docker", "stop", docker_container],
194
+ capture_output=True,
195
+ timeout=10,
196
+ check=False,
197
+ )
198
+ try:
199
+ if result.returncode == 0:
200
+ fmt.success(f"✓ Docker container {docker_container} stopped.")
201
+ else:
202
+ fmt.warning(
203
+ f"Could not stop container {docker_container}: {result.stderr.decode()}"
204
+ )
205
+ except (BrokenPipeError, OSError):
206
+ pass
207
+ except subprocess.TimeoutExpired:
208
+ try:
209
+ fmt.warning(
210
+ f"Timeout stopping container {docker_container}, forcing removal..."
211
+ )
212
+ except (BrokenPipeError, OSError):
213
+ pass
214
+ subprocess.run(
215
+ ["docker", "rm", "-f", docker_container], capture_output=True, check=False
216
+ )
217
+ except Exception:
218
+ pass
219
+
220
+ # Then, stop regular processes
184
221
  for pid in spawned_pids:
185
222
  try:
186
223
  if hasattr(os, "killpg"):
187
224
  # Unix-like systems: Use process groups
188
225
  pgid = os.getpgid(pid)
189
226
  os.killpg(pgid, signal.SIGTERM)
190
- fmt.success(f"✓ Process group {pgid} (PID {pid}) terminated.")
227
+ try:
228
+ fmt.success(f"✓ Process group {pgid} (PID {pid}) terminated.")
229
+ except (BrokenPipeError, OSError):
230
+ pass
191
231
  else:
192
232
  # Windows: Use taskkill to terminate process and its children
193
233
  subprocess.run(
@@ -195,24 +235,35 @@ def main() -> int:
195
235
  capture_output=True,
196
236
  check=False,
197
237
  )
198
- fmt.success(f"✓ Process {pid} and its children terminated.")
199
- except (OSError, ProcessLookupError, subprocess.SubprocessError) as e:
200
- fmt.warning(f"Could not terminate process {pid}: {e}")
238
+ try:
239
+ fmt.success(f"✓ Process {pid} and its children terminated.")
240
+ except (BrokenPipeError, OSError):
241
+ pass
242
+ except (OSError, ProcessLookupError, subprocess.SubprocessError):
243
+ pass
201
244
 
202
245
  sys.exit(0)
203
246
 
204
247
  signal.signal(signal.SIGINT, signal_handler) # Ctrl+C
205
248
  signal.signal(signal.SIGTERM, signal_handler) # Termination request
249
+ if hasattr(signal, "SIGHUP"):
250
+ signal.signal(signal.SIGHUP, signal_handler)
206
251
 
207
252
  try:
208
253
  from cognee import start_ui
209
254
 
210
255
  fmt.echo("Starting cognee UI...")
211
256
 
212
- # Callback to capture PIDs of all spawned processes
213
- def pid_callback(pid):
214
- nonlocal spawned_pids
215
- spawned_pids.append(pid)
257
+ # Callback to capture PIDs and Docker container of all spawned processes
258
+ def pid_callback(pid_or_tuple):
259
+ nonlocal spawned_pids, docker_container
260
+ # Handle both regular PIDs and (PID, container_name) tuples
261
+ if isinstance(pid_or_tuple, tuple):
262
+ pid, container_name = pid_or_tuple
263
+ spawned_pids.append(pid)
264
+ docker_container = container_name
265
+ else:
266
+ spawned_pids.append(pid_or_tuple)
216
267
 
217
268
  frontend_port = 3000
218
269
  start_backend, backend_port = True, 8000
@@ -70,11 +70,11 @@ After adding data, use `cognee cognify` to process it into knowledge graphs.
70
70
  await cognee.add(data=data_to_add, dataset_name=args.dataset_name)
71
71
  fmt.success(f"Successfully added data to dataset '{args.dataset_name}'")
72
72
  except Exception as e:
73
- raise CliCommandInnerException(f"Failed to add data: {str(e)}")
73
+ raise CliCommandInnerException(f"Failed to add data: {str(e)}") from e
74
74
 
75
75
  asyncio.run(run_add())
76
76
 
77
77
  except Exception as e:
78
78
  if isinstance(e, CliCommandInnerException):
79
- raise CliCommandException(str(e), error_code=1)
80
- raise CliCommandException(f"Error adding data: {str(e)}", error_code=1)
79
+ raise CliCommandException(str(e), error_code=1) from e
80
+ raise CliCommandException(f"Failed to add data: {str(e)}", error_code=1) from e
@@ -107,7 +107,7 @@ After successful cognify processing, use `cognee search` to query the knowledge
107
107
  )
108
108
  return result
109
109
  except Exception as e:
110
- raise CliCommandInnerException(f"Failed to cognify: {str(e)}")
110
+ raise CliCommandInnerException(f"Failed to cognify: {str(e)}") from e
111
111
 
112
112
  result = asyncio.run(run_cognify())
113
113
 
@@ -124,5 +124,5 @@ After successful cognify processing, use `cognee search` to query the knowledge
124
124
 
125
125
  except Exception as e:
126
126
  if isinstance(e, CliCommandInnerException):
127
- raise CliCommandException(str(e), error_code=1)
128
- raise CliCommandException(f"Error during cognification: {str(e)}", error_code=1)
127
+ raise CliCommandException(str(e), error_code=1) from e
128
+ raise CliCommandException(f"Error during cognification: {str(e)}", error_code=1) from e
@@ -79,8 +79,10 @@ Configuration changes will affect how cognee processes and stores data.
79
79
 
80
80
  except Exception as e:
81
81
  if isinstance(e, CliCommandInnerException):
82
- raise CliCommandException(str(e), error_code=1)
83
- raise CliCommandException(f"Error managing configuration: {str(e)}", error_code=1)
82
+ raise CliCommandException(str(e), error_code=1) from e
83
+ raise CliCommandException(
84
+ f"Error managing configuration: {str(e)}", error_code=1
85
+ ) from e
84
86
 
85
87
  def _handle_get(self, args: argparse.Namespace) -> None:
86
88
  try:
@@ -122,7 +124,7 @@ Configuration changes will affect how cognee processes and stores data.
122
124
  fmt.note("Configuration viewing not fully implemented yet")
123
125
 
124
126
  except Exception as e:
125
- raise CliCommandInnerException(f"Failed to get configuration: {str(e)}")
127
+ raise CliCommandInnerException(f"Failed to get configuration: {str(e)}") from e
126
128
 
127
129
  def _handle_set(self, args: argparse.Namespace) -> None:
128
130
  try:
@@ -141,7 +143,7 @@ Configuration changes will affect how cognee processes and stores data.
141
143
  fmt.error(f"Failed to set configuration key '{args.key}'")
142
144
 
143
145
  except Exception as e:
144
- raise CliCommandInnerException(f"Failed to set configuration: {str(e)}")
146
+ raise CliCommandInnerException(f"Failed to set configuration: {str(e)}") from e
145
147
 
146
148
  def _handle_unset(self, args: argparse.Namespace) -> None:
147
149
  try:
@@ -189,7 +191,7 @@ Configuration changes will affect how cognee processes and stores data.
189
191
  fmt.note("Use 'cognee config list' to see all available configuration options")
190
192
 
191
193
  except Exception as e:
192
- raise CliCommandInnerException(f"Failed to unset configuration: {str(e)}")
194
+ raise CliCommandInnerException(f"Failed to unset configuration: {str(e)}") from e
193
195
 
194
196
  def _handle_list(self, args: argparse.Namespace) -> None:
195
197
  try:
@@ -209,7 +211,7 @@ Configuration changes will affect how cognee processes and stores data.
209
211
  fmt.echo(" cognee config reset - Reset all to defaults")
210
212
 
211
213
  except Exception as e:
212
- raise CliCommandInnerException(f"Failed to list configuration: {str(e)}")
214
+ raise CliCommandInnerException(f"Failed to list configuration: {str(e)}") from e
213
215
 
214
216
  def _handle_reset(self, args: argparse.Namespace) -> None:
215
217
  try:
@@ -222,4 +224,4 @@ Configuration changes will affect how cognee processes and stores data.
222
224
  fmt.echo("This would reset all settings to their default values")
223
225
 
224
226
  except Exception as e:
225
- raise CliCommandInnerException(f"Failed to reset configuration: {str(e)}")
227
+ raise CliCommandInnerException(f"Failed to reset configuration: {str(e)}") from e
@@ -100,7 +100,7 @@ Be careful with deletion operations as they are irreversible.
100
100
  else:
101
101
  await cognee.delete(dataset_name=args.dataset_name, user_id=args.user_id)
102
102
  except Exception as e:
103
- raise CliCommandInnerException(f"Failed to delete: {str(e)}")
103
+ raise CliCommandInnerException(f"Failed to delete: {str(e)}") from e
104
104
 
105
105
  asyncio.run(run_delete())
106
106
  # This success message may be inaccurate due to the underlying bug, but we leave it for now.
@@ -108,5 +108,5 @@ Be careful with deletion operations as they are irreversible.
108
108
 
109
109
  except Exception as e:
110
110
  if isinstance(e, CliCommandInnerException):
111
- raise CliCommandException(str(e), error_code=1)
112
- raise CliCommandException(f"Error deleting data: {str(e)}", error_code=1)
111
+ raise CliCommandException(str(e), error_code=1) from e
112
+ raise CliCommandException(f"Error deleting data: {str(e)}", error_code=1) from e
@@ -31,10 +31,6 @@ Search Types & Use Cases:
31
31
  Traditional RAG using document chunks without graph structure.
32
32
  Best for: Direct document retrieval, specific fact-finding.
33
33
 
34
- **INSIGHTS**:
35
- Structured entity relationships and semantic connections.
36
- Best for: Understanding concept relationships, knowledge mapping.
37
-
38
34
  **CHUNKS**:
39
35
  Raw text segments that match the query semantically.
40
36
  Best for: Finding specific passages, citations, exact content.
@@ -108,7 +104,7 @@ Search Types & Use Cases:
108
104
  )
109
105
  return results
110
106
  except Exception as e:
111
- raise CliCommandInnerException(f"Failed to search: {str(e)}")
107
+ raise CliCommandInnerException(f"Failed to search: {str(e)}") from e
112
108
 
113
109
  results = asyncio.run(run_search())
114
110
 
@@ -145,5 +141,5 @@ Search Types & Use Cases:
145
141
 
146
142
  except Exception as e:
147
143
  if isinstance(e, CliCommandInnerException):
148
- raise CliCommandException(str(e), error_code=1)
149
- raise CliCommandException(f"Error searching: {str(e)}", error_code=1)
144
+ raise CliCommandException(str(e), error_code=1) from e
145
+ raise CliCommandException(f"Error searching: {str(e)}", error_code=1) from e
cognee/cli/config.py CHANGED
@@ -19,7 +19,6 @@ COMMAND_DESCRIPTIONS = {
19
19
  SEARCH_TYPE_CHOICES = [
20
20
  "GRAPH_COMPLETION",
21
21
  "RAG_COMPLETION",
22
- "INSIGHTS",
23
22
  "CHUNKS",
24
23
  "SUMMARIES",
25
24
  "CODE",
@@ -12,6 +12,11 @@ from cognee.modules.users.methods import get_user
12
12
  # for different async tasks, threads and processes
13
13
  vector_db_config = ContextVar("vector_db_config", default=None)
14
14
  graph_db_config = ContextVar("graph_db_config", default=None)
15
+ session_user = ContextVar("session_user", default=None)
16
+
17
+
18
+ async def set_session_user_context_variable(user):
19
+ session_user.set(user)
15
20
 
16
21
 
17
22
  async def set_database_global_context_variables(dataset: Union[str, UUID], user_id: UUID):
@@ -56,7 +56,7 @@ class CogneeValidationError(CogneeApiError):
56
56
  self,
57
57
  message: str = "A validation error occurred.",
58
58
  name: str = "CogneeValidationError",
59
- status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
59
+ status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
60
60
  log=True,
61
61
  log_level="ERROR",
62
62
  ):
@@ -0,0 +1,2 @@
1
+ from .get_cache_engine import get_cache_engine
2
+ from .config import get_cache_config
@@ -0,0 +1,79 @@
1
+ from abc import ABC, abstractmethod
2
+ from contextlib import contextmanager
3
+
4
+
5
+ class CacheDBInterface(ABC):
6
+ """
7
+ Abstract base class for distributed cache coordination systems (e.g., Redis, Memcached).
8
+ Provides a common interface for lock acquisition, release, and context-managed locking.
9
+ """
10
+
11
+ def __init__(self, host: str, port: int, lock_key: str):
12
+ self.host = host
13
+ self.port = port
14
+ self.lock_key = lock_key
15
+ self.lock = None
16
+
17
+ @abstractmethod
18
+ def acquire_lock(self):
19
+ """
20
+ Acquire a lock on the given key.
21
+ Must be implemented by subclasses.
22
+ """
23
+ pass
24
+
25
+ @abstractmethod
26
+ def release_lock(self):
27
+ """
28
+ Release the lock if it is held.
29
+ Must be implemented by subclasses.
30
+ """
31
+ pass
32
+
33
+ @contextmanager
34
+ def hold_lock(self):
35
+ """
36
+ Context manager for safely acquiring and releasing the lock.
37
+ """
38
+ self.acquire()
39
+ try:
40
+ yield
41
+ finally:
42
+ self.release()
43
+
44
+ @abstractmethod
45
+ async def add_qa(
46
+ self,
47
+ user_id: str,
48
+ session_id: str,
49
+ question: str,
50
+ context: str,
51
+ answer: str,
52
+ ttl: int | None = 86400,
53
+ ):
54
+ """
55
+ Add a Q/A/context triplet to a cache session.
56
+ """
57
+
58
+ pass
59
+
60
+ @abstractmethod
61
+ async def get_latest_qa(self, user_id: str, session_id: str, last_n: int = 5):
62
+ """
63
+ Retrieve the most recent Q/A/context triplets for a session.
64
+ """
65
+ pass
66
+
67
+ @abstractmethod
68
+ async def get_all_qas(self, user_id: str, session_id: str):
69
+ """
70
+ Retrieve all Q/A/context triplets for the given session.
71
+ """
72
+ pass
73
+
74
+ @abstractmethod
75
+ async def close(self):
76
+ """
77
+ Gracefully close any async connections.
78
+ """
79
+ pass
@@ -0,0 +1,44 @@
1
+ from pydantic_settings import BaseSettings, SettingsConfigDict
2
+ from functools import lru_cache
3
+ from typing import Optional
4
+
5
+
6
+ class CacheConfig(BaseSettings):
7
+ """
8
+ Configuration for distributed cache systems (e.g., Redis), used for locking or coordination.
9
+
10
+ Attributes:
11
+ - shared_kuzu_lock: Shared kuzu lock logic on/off.
12
+ - cache_host: Hostname of the cache service.
13
+ - cache_port: Port number for the cache service.
14
+ - agentic_lock_expire: Automatic lock expiration time (in seconds).
15
+ - agentic_lock_timeout: Maximum time (in seconds) to wait for the lock release.
16
+ """
17
+
18
+ caching: bool = False
19
+ shared_kuzu_lock: bool = False
20
+ cache_host: str = "localhost"
21
+ cache_port: int = 6379
22
+ cache_username: Optional[str] = None
23
+ cache_password: Optional[str] = None
24
+ agentic_lock_expire: int = 240
25
+ agentic_lock_timeout: int = 300
26
+
27
+ model_config = SettingsConfigDict(env_file=".env", extra="allow")
28
+
29
+ def to_dict(self) -> dict:
30
+ return {
31
+ "caching": self.caching,
32
+ "shared_kuzu_lock": self.shared_kuzu_lock,
33
+ "cache_host": self.cache_host,
34
+ "cache_port": self.cache_port,
35
+ "cache_username": self.cache_username,
36
+ "cache_password": self.cache_password,
37
+ "agentic_lock_expire": self.agentic_lock_expire,
38
+ "agentic_lock_timeout": self.agentic_lock_timeout,
39
+ }
40
+
41
+
42
+ @lru_cache
43
+ def get_cache_config():
44
+ return CacheConfig()
@@ -0,0 +1,67 @@
1
+ """Factory to get the appropriate cache coordination engine (e.g., Redis)."""
2
+
3
+ from functools import lru_cache
4
+ from typing import Optional
5
+ from cognee.infrastructure.databases.cache.config import get_cache_config
6
+ from cognee.infrastructure.databases.cache.cache_db_interface import CacheDBInterface
7
+
8
+ config = get_cache_config()
9
+
10
+
11
+ @lru_cache
12
+ def create_cache_engine(
13
+ cache_host: str,
14
+ cache_port: int,
15
+ cache_username: str,
16
+ cache_password: str,
17
+ lock_key: str,
18
+ agentic_lock_expire: int = 240,
19
+ agentic_lock_timeout: int = 300,
20
+ ):
21
+ """
22
+ Factory function to instantiate a cache coordination backend (currently Redis).
23
+
24
+ Parameters:
25
+ -----------
26
+ - cache_host: Hostname or IP of the cache server.
27
+ - cache_port: Port number to connect to.
28
+ - cache_username: Username to authenticate with.
29
+ - cache_password: Password to authenticate with.
30
+ - lock_key: Identifier used for the locking resource.
31
+ - agentic_lock_expire: Duration to hold the lock after acquisition.
32
+ - agentic_lock_timeout: Max time to wait for the lock before failing.
33
+
34
+ Returns:
35
+ --------
36
+ - CacheDBInterface: An instance of the appropriate cache adapter. :TODO: Now we support only Redis. later if we add more here we can split the logic
37
+ """
38
+ if config.caching:
39
+ from cognee.infrastructure.databases.cache.redis.RedisAdapter import RedisAdapter
40
+
41
+ return RedisAdapter(
42
+ host=cache_host,
43
+ port=cache_port,
44
+ username=cache_username,
45
+ password=cache_password,
46
+ lock_name=lock_key,
47
+ timeout=agentic_lock_expire,
48
+ blocking_timeout=agentic_lock_timeout,
49
+ )
50
+ else:
51
+ return None
52
+
53
+
54
+ def get_cache_engine(lock_key: Optional[str] = None) -> CacheDBInterface:
55
+ """
56
+ Returns a cache adapter instance using current context configuration.
57
+ """
58
+
59
+ return create_cache_engine(
60
+ cache_host=config.cache_host,
61
+ cache_port=config.cache_port,
62
+ cache_username=config.cache_username,
63
+ cache_password=config.cache_password,
64
+ lock_key=lock_key,
65
+ agentic_lock_expire=config.agentic_lock_expire,
66
+ agentic_lock_timeout=config.agentic_lock_timeout,
67
+ )