cognee 0.5.1.dev0__py3-none-any.whl → 0.5.2.dev0__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 (238) hide show
  1. cognee/__init__.py +2 -0
  2. cognee/alembic/README +1 -0
  3. cognee/alembic/env.py +107 -0
  4. cognee/alembic/script.py.mako +26 -0
  5. cognee/alembic/versions/1a58b986e6e1_enable_delete_for_old_tutorial_notebooks.py +52 -0
  6. cognee/alembic/versions/1d0bb7fede17_add_pipeline_run_status.py +33 -0
  7. cognee/alembic/versions/1daae0df1866_incremental_loading.py +48 -0
  8. cognee/alembic/versions/211ab850ef3d_add_sync_operations_table.py +118 -0
  9. cognee/alembic/versions/45957f0a9849_add_notebook_table.py +46 -0
  10. cognee/alembic/versions/46a6ce2bd2b2_expand_dataset_database_with_json_.py +333 -0
  11. cognee/alembic/versions/482cd6517ce4_add_default_user.py +30 -0
  12. cognee/alembic/versions/76625596c5c3_expand_dataset_database_for_multi_user.py +98 -0
  13. cognee/alembic/versions/8057ae7329c2_initial_migration.py +25 -0
  14. cognee/alembic/versions/9e7a3cb85175_loader_separation.py +104 -0
  15. cognee/alembic/versions/a1b2c3d4e5f6_add_label_column_to_data.py +38 -0
  16. cognee/alembic/versions/ab7e313804ae_permission_system_rework.py +236 -0
  17. cognee/alembic/versions/b9274c27a25a_kuzu_11_migration.py +75 -0
  18. cognee/alembic/versions/c946955da633_multi_tenant_support.py +137 -0
  19. cognee/alembic/versions/e1ec1dcb50b6_add_last_accessed_to_data.py +51 -0
  20. cognee/alembic/versions/e4ebee1091e7_expand_data_model_info.py +140 -0
  21. cognee/alembic.ini +117 -0
  22. cognee/api/v1/add/routers/get_add_router.py +2 -0
  23. cognee/api/v1/cognify/cognify.py +11 -6
  24. cognee/api/v1/cognify/routers/get_cognify_router.py +8 -0
  25. cognee/api/v1/config/config.py +60 -0
  26. cognee/api/v1/datasets/routers/get_datasets_router.py +45 -3
  27. cognee/api/v1/memify/routers/get_memify_router.py +2 -0
  28. cognee/api/v1/search/routers/get_search_router.py +21 -6
  29. cognee/api/v1/search/search.py +25 -5
  30. cognee/api/v1/sync/routers/get_sync_router.py +3 -3
  31. cognee/cli/commands/add_command.py +1 -1
  32. cognee/cli/commands/cognify_command.py +6 -0
  33. cognee/cli/commands/config_command.py +1 -1
  34. cognee/context_global_variables.py +5 -1
  35. cognee/eval_framework/answer_generation/answer_generation_executor.py +7 -8
  36. cognee/infrastructure/databases/cache/cache_db_interface.py +38 -1
  37. cognee/infrastructure/databases/cache/config.py +6 -0
  38. cognee/infrastructure/databases/cache/fscache/FsCacheAdapter.py +21 -0
  39. cognee/infrastructure/databases/cache/get_cache_engine.py +9 -3
  40. cognee/infrastructure/databases/cache/redis/RedisAdapter.py +60 -1
  41. cognee/infrastructure/databases/dataset_database_handler/supported_dataset_database_handlers.py +7 -0
  42. cognee/infrastructure/databases/graph/get_graph_engine.py +29 -1
  43. cognee/infrastructure/databases/graph/neo4j_driver/Neo4jAuraDevDatasetDatabaseHandler.py +62 -27
  44. cognee/infrastructure/databases/hybrid/neptune_analytics/NeptuneAnalyticsAdapter.py +17 -4
  45. cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py +2 -1
  46. cognee/infrastructure/databases/vector/chromadb/ChromaDBAdapter.py +2 -0
  47. cognee/infrastructure/databases/vector/config.py +6 -0
  48. cognee/infrastructure/databases/vector/create_vector_engine.py +69 -22
  49. cognee/infrastructure/databases/vector/embeddings/LiteLLMEmbeddingEngine.py +64 -9
  50. cognee/infrastructure/databases/vector/embeddings/OllamaEmbeddingEngine.py +13 -2
  51. cognee/infrastructure/databases/vector/lancedb/LanceDBAdapter.py +16 -3
  52. cognee/infrastructure/databases/vector/models/ScoredResult.py +3 -3
  53. cognee/infrastructure/databases/vector/pgvector/PGVectorAdapter.py +16 -3
  54. cognee/infrastructure/databases/vector/pgvector/PGVectorDatasetDatabaseHandler.py +86 -0
  55. cognee/infrastructure/databases/vector/pgvector/create_db_and_tables.py +81 -2
  56. cognee/infrastructure/databases/vector/vector_db_interface.py +8 -0
  57. cognee/infrastructure/files/utils/get_data_file_path.py +33 -27
  58. cognee/infrastructure/llm/prompts/extract_query_time.txt +1 -1
  59. cognee/infrastructure/llm/prompts/generate_event_entity_prompt.txt +1 -1
  60. cognee/infrastructure/llm/prompts/generate_event_graph_prompt.txt +1 -1
  61. cognee/infrastructure/llm/prompts/generate_graph_prompt.txt +2 -2
  62. cognee/infrastructure/llm/prompts/generate_graph_prompt_guided.txt +1 -1
  63. cognee/infrastructure/llm/prompts/generate_graph_prompt_oneshot.txt +2 -2
  64. cognee/infrastructure/llm/prompts/generate_graph_prompt_simple.txt +1 -1
  65. cognee/infrastructure/llm/prompts/generate_graph_prompt_strict.txt +1 -1
  66. cognee/infrastructure/llm/prompts/search_type_selector_prompt.txt +6 -6
  67. cognee/infrastructure/llm/prompts/test.txt +1 -1
  68. cognee/infrastructure/llm/prompts/translate_content.txt +19 -0
  69. cognee/infrastructure/llm/structured_output_framework/litellm_instructor/llm/get_llm_client.py +24 -0
  70. cognee/infrastructure/llm/structured_output_framework/litellm_instructor/llm/llama_cpp/adapter.py +191 -0
  71. cognee/modules/chunking/models/DocumentChunk.py +0 -1
  72. cognee/modules/cognify/config.py +2 -0
  73. cognee/modules/data/models/Data.py +1 -0
  74. cognee/modules/engine/models/Entity.py +0 -1
  75. cognee/modules/engine/operations/setup.py +6 -0
  76. cognee/modules/graph/cognee_graph/CogneeGraph.py +150 -37
  77. cognee/modules/graph/cognee_graph/CogneeGraphElements.py +48 -2
  78. cognee/modules/graph/utils/__init__.py +1 -0
  79. cognee/modules/graph/utils/get_entity_nodes_from_triplets.py +12 -0
  80. cognee/modules/notebooks/methods/__init__.py +1 -0
  81. cognee/modules/notebooks/methods/create_notebook.py +0 -34
  82. cognee/modules/notebooks/methods/create_tutorial_notebooks.py +191 -0
  83. cognee/modules/notebooks/methods/get_notebooks.py +12 -8
  84. cognee/modules/notebooks/tutorials/cognee-basics/cell-1.md +3 -0
  85. cognee/modules/notebooks/tutorials/cognee-basics/cell-2.md +10 -0
  86. cognee/modules/notebooks/tutorials/cognee-basics/cell-3.md +7 -0
  87. cognee/modules/notebooks/tutorials/cognee-basics/cell-4.py +28 -0
  88. cognee/modules/notebooks/tutorials/cognee-basics/cell-5.py +3 -0
  89. cognee/modules/notebooks/tutorials/cognee-basics/cell-6.py +9 -0
  90. cognee/modules/notebooks/tutorials/cognee-basics/cell-7.py +17 -0
  91. cognee/modules/notebooks/tutorials/cognee-basics/config.json +4 -0
  92. cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-1.md +3 -0
  93. cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-10.md +3 -0
  94. cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-11.md +3 -0
  95. cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-12.py +3 -0
  96. cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-13.md +7 -0
  97. cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-14.py +6 -0
  98. cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-15.md +3 -0
  99. cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-16.py +7 -0
  100. cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-2.md +9 -0
  101. cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-3.md +7 -0
  102. cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-4.md +9 -0
  103. cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-5.md +5 -0
  104. cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-6.py +13 -0
  105. cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-7.md +3 -0
  106. cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-8.md +3 -0
  107. cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-9.py +31 -0
  108. cognee/modules/notebooks/tutorials/python-development-with-cognee/config.json +4 -0
  109. cognee/modules/notebooks/tutorials/python-development-with-cognee/data/copilot_conversations.json +107 -0
  110. cognee/modules/notebooks/tutorials/python-development-with-cognee/data/guido_contributions.json +976 -0
  111. cognee/modules/notebooks/tutorials/python-development-with-cognee/data/my_developer_rules.md +79 -0
  112. cognee/modules/notebooks/tutorials/python-development-with-cognee/data/pep_style_guide.md +74 -0
  113. cognee/modules/notebooks/tutorials/python-development-with-cognee/data/zen_principles.md +74 -0
  114. cognee/modules/retrieval/EntityCompletionRetriever.py +51 -38
  115. cognee/modules/retrieval/__init__.py +0 -1
  116. cognee/modules/retrieval/base_retriever.py +66 -10
  117. cognee/modules/retrieval/chunks_retriever.py +57 -49
  118. cognee/modules/retrieval/coding_rules_retriever.py +12 -5
  119. cognee/modules/retrieval/completion_retriever.py +29 -28
  120. cognee/modules/retrieval/cypher_search_retriever.py +25 -20
  121. cognee/modules/retrieval/graph_completion_context_extension_retriever.py +42 -46
  122. cognee/modules/retrieval/graph_completion_cot_retriever.py +68 -51
  123. cognee/modules/retrieval/graph_completion_retriever.py +78 -63
  124. cognee/modules/retrieval/graph_summary_completion_retriever.py +2 -0
  125. cognee/modules/retrieval/lexical_retriever.py +34 -12
  126. cognee/modules/retrieval/natural_language_retriever.py +18 -15
  127. cognee/modules/retrieval/summaries_retriever.py +51 -34
  128. cognee/modules/retrieval/temporal_retriever.py +59 -49
  129. cognee/modules/retrieval/triplet_retriever.py +31 -32
  130. cognee/modules/retrieval/utils/access_tracking.py +88 -0
  131. cognee/modules/retrieval/utils/brute_force_triplet_search.py +99 -85
  132. cognee/modules/retrieval/utils/node_edge_vector_search.py +174 -0
  133. cognee/modules/search/methods/__init__.py +1 -0
  134. cognee/modules/search/methods/get_retriever_output.py +53 -0
  135. cognee/modules/search/methods/get_search_type_retriever_instance.py +252 -0
  136. cognee/modules/search/methods/search.py +90 -215
  137. cognee/modules/search/models/SearchResultPayload.py +67 -0
  138. cognee/modules/search/types/SearchResult.py +1 -8
  139. cognee/modules/search/types/SearchType.py +1 -2
  140. cognee/modules/search/types/__init__.py +1 -1
  141. cognee/modules/search/utils/__init__.py +1 -2
  142. cognee/modules/search/utils/transform_insights_to_graph.py +2 -2
  143. cognee/modules/search/utils/{transform_context_to_graph.py → transform_triplets_to_graph.py} +2 -2
  144. cognee/modules/users/authentication/default/default_transport.py +11 -1
  145. cognee/modules/users/authentication/get_api_auth_backend.py +2 -1
  146. cognee/modules/users/authentication/get_client_auth_backend.py +2 -1
  147. cognee/modules/users/methods/create_user.py +0 -9
  148. cognee/modules/users/permissions/methods/has_user_management_permission.py +29 -0
  149. cognee/modules/visualization/cognee_network_visualization.py +1 -1
  150. cognee/run_migrations.py +48 -0
  151. cognee/shared/exceptions/__init__.py +1 -3
  152. cognee/shared/exceptions/exceptions.py +11 -1
  153. cognee/shared/usage_logger.py +332 -0
  154. cognee/shared/utils.py +12 -5
  155. cognee/tasks/cleanup/cleanup_unused_data.py +172 -0
  156. cognee/tasks/memify/extract_usage_frequency.py +613 -0
  157. cognee/tasks/summarization/models.py +0 -2
  158. cognee/tasks/temporal_graph/__init__.py +0 -1
  159. cognee/tasks/translation/__init__.py +96 -0
  160. cognee/tasks/translation/config.py +110 -0
  161. cognee/tasks/translation/detect_language.py +190 -0
  162. cognee/tasks/translation/exceptions.py +62 -0
  163. cognee/tasks/translation/models.py +72 -0
  164. cognee/tasks/translation/providers/__init__.py +44 -0
  165. cognee/tasks/translation/providers/azure_provider.py +192 -0
  166. cognee/tasks/translation/providers/base.py +85 -0
  167. cognee/tasks/translation/providers/google_provider.py +158 -0
  168. cognee/tasks/translation/providers/llm_provider.py +143 -0
  169. cognee/tasks/translation/translate_content.py +282 -0
  170. cognee/tasks/web_scraper/default_url_crawler.py +6 -2
  171. cognee/tests/cli_tests/cli_unit_tests/test_cli_commands.py +1 -0
  172. cognee/tests/cli_tests/cli_unit_tests/test_cli_edge_cases.py +3 -0
  173. cognee/tests/integration/retrieval/test_brute_force_triplet_search_with_cognify.py +62 -0
  174. cognee/tests/integration/retrieval/test_chunks_retriever.py +115 -16
  175. cognee/tests/integration/retrieval/test_graph_completion_retriever.py +13 -5
  176. cognee/tests/integration/retrieval/test_graph_completion_retriever_context_extension.py +22 -20
  177. cognee/tests/integration/retrieval/test_graph_completion_retriever_cot.py +23 -24
  178. cognee/tests/integration/retrieval/test_rag_completion_retriever.py +70 -5
  179. cognee/tests/integration/retrieval/test_structured_output.py +62 -18
  180. cognee/tests/integration/retrieval/test_summaries_retriever.py +20 -9
  181. cognee/tests/integration/retrieval/test_temporal_retriever.py +38 -8
  182. cognee/tests/integration/retrieval/test_triplet_retriever.py +13 -4
  183. cognee/tests/integration/shared/test_usage_logger_integration.py +255 -0
  184. cognee/tests/tasks/translation/README.md +147 -0
  185. cognee/tests/tasks/translation/__init__.py +1 -0
  186. cognee/tests/tasks/translation/config_test.py +93 -0
  187. cognee/tests/tasks/translation/detect_language_test.py +118 -0
  188. cognee/tests/tasks/translation/providers_test.py +151 -0
  189. cognee/tests/tasks/translation/translate_content_test.py +213 -0
  190. cognee/tests/test_chromadb.py +1 -1
  191. cognee/tests/test_cleanup_unused_data.py +165 -0
  192. cognee/tests/test_delete_by_id.py +6 -6
  193. cognee/tests/test_extract_usage_frequency.py +308 -0
  194. cognee/tests/test_kuzu.py +17 -7
  195. cognee/tests/test_lancedb.py +3 -1
  196. cognee/tests/test_library.py +1 -1
  197. cognee/tests/test_neo4j.py +17 -7
  198. cognee/tests/test_neptune_analytics_vector.py +3 -1
  199. cognee/tests/test_permissions.py +172 -187
  200. cognee/tests/test_pgvector.py +3 -1
  201. cognee/tests/test_relational_db_migration.py +15 -1
  202. cognee/tests/test_remote_kuzu.py +3 -1
  203. cognee/tests/test_s3_file_storage.py +1 -1
  204. cognee/tests/test_search_db.py +97 -110
  205. cognee/tests/test_usage_logger_e2e.py +268 -0
  206. cognee/tests/unit/api/test_get_raw_data_endpoint.py +206 -0
  207. cognee/tests/unit/eval_framework/answer_generation_test.py +4 -3
  208. cognee/tests/unit/infrastructure/databases/cache/test_cache_config.py +2 -0
  209. cognee/tests/unit/modules/graph/cognee_graph_elements_test.py +42 -2
  210. cognee/tests/unit/modules/graph/cognee_graph_test.py +329 -31
  211. cognee/tests/unit/modules/retrieval/chunks_retriever_test.py +31 -59
  212. cognee/tests/unit/modules/retrieval/graph_completion_retriever_context_extension_test.py +70 -33
  213. cognee/tests/unit/modules/retrieval/graph_completion_retriever_cot_test.py +72 -52
  214. cognee/tests/unit/modules/retrieval/graph_completion_retriever_test.py +27 -33
  215. cognee/tests/unit/modules/retrieval/rag_completion_retriever_test.py +28 -15
  216. cognee/tests/unit/modules/retrieval/summaries_retriever_test.py +37 -42
  217. cognee/tests/unit/modules/retrieval/temporal_retriever_test.py +48 -64
  218. cognee/tests/unit/modules/retrieval/test_brute_force_triplet_search.py +263 -24
  219. cognee/tests/unit/modules/retrieval/test_node_edge_vector_search.py +273 -0
  220. cognee/tests/unit/modules/retrieval/triplet_retriever_test.py +30 -16
  221. cognee/tests/unit/modules/search/test_get_search_type_retriever_instance.py +125 -0
  222. cognee/tests/unit/modules/search/test_search.py +176 -0
  223. cognee/tests/unit/modules/search/test_search_prepare_search_result_contract.py +190 -0
  224. cognee/tests/unit/modules/users/test_tutorial_notebook_creation.py +511 -297
  225. cognee/tests/unit/shared/test_usage_logger.py +241 -0
  226. cognee/tests/unit/users/permissions/test_has_user_management_permission.py +46 -0
  227. {cognee-0.5.1.dev0.dist-info → cognee-0.5.2.dev0.dist-info}/METADATA +17 -10
  228. {cognee-0.5.1.dev0.dist-info → cognee-0.5.2.dev0.dist-info}/RECORD +232 -144
  229. cognee/api/.env.example +0 -5
  230. cognee/modules/retrieval/base_graph_retriever.py +0 -24
  231. cognee/modules/search/methods/get_search_type_tools.py +0 -223
  232. cognee/modules/search/methods/no_access_control_search.py +0 -62
  233. cognee/modules/search/utils/prepare_search_result.py +0 -63
  234. cognee/tests/test_feedback_enrichment.py +0 -174
  235. {cognee-0.5.1.dev0.dist-info → cognee-0.5.2.dev0.dist-info}/WHEEL +0 -0
  236. {cognee-0.5.1.dev0.dist-info → cognee-0.5.2.dev0.dist-info}/entry_points.txt +0 -0
  237. {cognee-0.5.1.dev0.dist-info → cognee-0.5.2.dev0.dist-info}/licenses/LICENSE +0 -0
  238. {cognee-0.5.1.dev0.dist-info → cognee-0.5.2.dev0.dist-info}/licenses/NOTICE.md +0 -0
@@ -0,0 +1,308 @@
1
+ """
2
+ Test Suite: Usage Frequency Tracking
3
+
4
+ Comprehensive tests for the usage frequency tracking implementation.
5
+ Tests cover extraction logic, adapter integration, edge cases, and end-to-end workflows.
6
+
7
+ Run with:
8
+ pytest test_usage_frequency_comprehensive.py -v
9
+
10
+ Or without pytest:
11
+ python test_usage_frequency_comprehensive.py
12
+ """
13
+
14
+ import asyncio
15
+ import unittest
16
+ from datetime import datetime, timedelta
17
+ from typing import List, Dict
18
+
19
+ # Mock imports for testing without full Cognee setup
20
+ try:
21
+ from cognee.modules.graph.cognee_graph.CogneeGraph import CogneeGraph
22
+ from cognee.modules.graph.cognee_graph.CogneeGraphElements import Node, Edge
23
+ from cognee.tasks.memify.extract_usage_frequency import (
24
+ extract_usage_frequency,
25
+ add_frequency_weights,
26
+ run_usage_frequency_update,
27
+ )
28
+
29
+ COGNEE_AVAILABLE = True
30
+ except ImportError:
31
+ COGNEE_AVAILABLE = False
32
+ print("⚠ Cognee not fully available - some tests will be skipped")
33
+
34
+
35
+ class TestUsageFrequencyExtraction(unittest.TestCase):
36
+ """Test the core frequency extraction logic."""
37
+
38
+ def setUp(self):
39
+ """Set up test fixtures."""
40
+ if not COGNEE_AVAILABLE:
41
+ self.skipTest("Cognee modules not available")
42
+
43
+ def create_mock_graph(self, num_interactions: int = 3, num_elements: int = 5):
44
+ """Create a mock graph with interactions and elements."""
45
+ graph = CogneeGraph()
46
+
47
+ # Create interaction nodes
48
+ current_time = datetime.now()
49
+ for i in range(num_interactions):
50
+ interaction_node = Node(
51
+ id=f"interaction_{i}",
52
+ node_type="CogneeUserInteraction",
53
+ attributes={
54
+ "type": "CogneeUserInteraction",
55
+ "query_text": f"Test query {i}",
56
+ "timestamp": int((current_time - timedelta(hours=i)).timestamp() * 1000),
57
+ },
58
+ )
59
+ graph.add_node(interaction_node)
60
+
61
+ # Create graph element nodes
62
+ for i in range(num_elements):
63
+ element_node = Node(
64
+ id=f"element_{i}",
65
+ node_type="DocumentChunk",
66
+ attributes={"type": "DocumentChunk", "text": f"Element content {i}"},
67
+ )
68
+ graph.add_node(element_node)
69
+
70
+ # Create usage edges (interactions reference elements)
71
+ for i in range(num_interactions):
72
+ # Each interaction uses 2-3 elements
73
+ for j in range(2):
74
+ element_idx = (i + j) % num_elements
75
+ edge = Edge(
76
+ node1=graph.get_node(f"interaction_{i}"),
77
+ node2=graph.get_node(f"element_{element_idx}"),
78
+ edge_type="used_graph_element_to_answer",
79
+ attributes={"relationship_type": "used_graph_element_to_answer"},
80
+ )
81
+ graph.add_edge(edge)
82
+
83
+ return graph
84
+
85
+ async def test_basic_frequency_extraction(self):
86
+ """Test basic frequency extraction with simple graph."""
87
+ graph = self.create_mock_graph(num_interactions=3, num_elements=5)
88
+
89
+ result = await extract_usage_frequency(
90
+ subgraphs=[graph], time_window=timedelta(days=7), min_interaction_threshold=1
91
+ )
92
+
93
+ self.assertIn("node_frequencies", result)
94
+ self.assertIn("total_interactions", result)
95
+ self.assertEqual(result["total_interactions"], 3)
96
+ self.assertGreater(len(result["node_frequencies"]), 0)
97
+
98
+ async def test_time_window_filtering(self):
99
+ """Test that time window correctly filters old interactions."""
100
+ graph = CogneeGraph()
101
+
102
+ current_time = datetime.now()
103
+
104
+ # Add recent interaction (within window)
105
+ recent_node = Node(
106
+ id="recent_interaction",
107
+ node_type="CogneeUserInteraction",
108
+ attributes={
109
+ "type": "CogneeUserInteraction",
110
+ "timestamp": int(current_time.timestamp() * 1000),
111
+ },
112
+ )
113
+ graph.add_node(recent_node)
114
+
115
+ # Add old interaction (outside window)
116
+ old_node = Node(
117
+ id="old_interaction",
118
+ node_type="CogneeUserInteraction",
119
+ attributes={
120
+ "type": "CogneeUserInteraction",
121
+ "timestamp": int((current_time - timedelta(days=10)).timestamp() * 1000),
122
+ },
123
+ )
124
+ graph.add_node(old_node)
125
+
126
+ # Add element
127
+ element = Node(
128
+ id="element_1", node_type="DocumentChunk", attributes={"type": "DocumentChunk"}
129
+ )
130
+ graph.add_node(element)
131
+
132
+ # Add edges
133
+ graph.add_edge(
134
+ Edge(
135
+ node1=recent_node,
136
+ node2=element,
137
+ edge_type="used_graph_element_to_answer",
138
+ attributes={"relationship_type": "used_graph_element_to_answer"},
139
+ )
140
+ )
141
+ graph.add_edge(
142
+ Edge(
143
+ node1=old_node,
144
+ node2=element,
145
+ edge_type="used_graph_element_to_answer",
146
+ attributes={"relationship_type": "used_graph_element_to_answer"},
147
+ )
148
+ )
149
+
150
+ # Extract with 7-day window
151
+ result = await extract_usage_frequency(
152
+ subgraphs=[graph], time_window=timedelta(days=7), min_interaction_threshold=1
153
+ )
154
+
155
+ # Should only count recent interaction
156
+ self.assertEqual(result["interactions_in_window"], 1)
157
+ self.assertEqual(result["total_interactions"], 2)
158
+
159
+ async def test_threshold_filtering(self):
160
+ """Test that minimum threshold filters low-frequency nodes."""
161
+ graph = self.create_mock_graph(num_interactions=5, num_elements=10)
162
+
163
+ # Extract with threshold of 3
164
+ result = await extract_usage_frequency(
165
+ subgraphs=[graph], time_window=timedelta(days=7), min_interaction_threshold=3
166
+ )
167
+
168
+ # Only nodes with 3+ accesses should be included
169
+ for node_id, freq in result["node_frequencies"].items():
170
+ self.assertGreaterEqual(freq, 3)
171
+
172
+ async def test_element_type_tracking(self):
173
+ """Test that element types are properly tracked."""
174
+ graph = CogneeGraph()
175
+
176
+ # Create interaction
177
+ interaction = Node(
178
+ id="interaction_1",
179
+ node_type="CogneeUserInteraction",
180
+ attributes={
181
+ "type": "CogneeUserInteraction",
182
+ "timestamp": int(datetime.now().timestamp() * 1000),
183
+ },
184
+ )
185
+ graph.add_node(interaction)
186
+
187
+ # Create elements of different types
188
+ chunk = Node(id="chunk_1", node_type="DocumentChunk", attributes={"type": "DocumentChunk"})
189
+ entity = Node(id="entity_1", node_type="Entity", attributes={"type": "Entity"})
190
+
191
+ graph.add_node(chunk)
192
+ graph.add_node(entity)
193
+
194
+ # Add edges
195
+ for element in [chunk, entity]:
196
+ graph.add_edge(
197
+ Edge(
198
+ node1=interaction,
199
+ node2=element,
200
+ edge_type="used_graph_element_to_answer",
201
+ attributes={"relationship_type": "used_graph_element_to_answer"},
202
+ )
203
+ )
204
+
205
+ result = await extract_usage_frequency(subgraphs=[graph], time_window=timedelta(days=7))
206
+
207
+ # Check element types were tracked
208
+ self.assertIn("element_type_frequencies", result)
209
+ types = result["element_type_frequencies"]
210
+ self.assertIn("DocumentChunk", types)
211
+ self.assertIn("Entity", types)
212
+
213
+ async def test_empty_graph(self):
214
+ """Test handling of empty graph."""
215
+ graph = CogneeGraph()
216
+
217
+ result = await extract_usage_frequency(subgraphs=[graph], time_window=timedelta(days=7))
218
+
219
+ self.assertEqual(result["total_interactions"], 0)
220
+ self.assertEqual(len(result["node_frequencies"]), 0)
221
+
222
+ async def test_no_interactions_in_window(self):
223
+ """Test handling when all interactions are outside time window."""
224
+ graph = CogneeGraph()
225
+
226
+ # Add old interaction
227
+ old_time = datetime.now() - timedelta(days=30)
228
+ old_interaction = Node(
229
+ id="old_interaction",
230
+ node_type="CogneeUserInteraction",
231
+ attributes={
232
+ "type": "CogneeUserInteraction",
233
+ "timestamp": int(old_time.timestamp() * 1000),
234
+ },
235
+ )
236
+ graph.add_node(old_interaction)
237
+
238
+ result = await extract_usage_frequency(subgraphs=[graph], time_window=timedelta(days=7))
239
+
240
+ self.assertEqual(result["interactions_in_window"], 0)
241
+ self.assertEqual(result["total_interactions"], 1)
242
+
243
+
244
+ class TestIntegration(unittest.TestCase):
245
+ """Integration tests for the complete workflow."""
246
+
247
+ def setUp(self):
248
+ """Set up test fixtures."""
249
+ if not COGNEE_AVAILABLE:
250
+ self.skipTest("Cognee modules not available")
251
+
252
+ async def test_end_to_end_workflow(self):
253
+ """Test the complete end-to-end frequency tracking workflow."""
254
+ # This would require a full Cognee setup with database
255
+ # Skipped in unit tests, run as part of example_usage_frequency_e2e.py
256
+ self.skipTest("E2E test - run example_usage_frequency_e2e.py instead")
257
+
258
+
259
+ # ============================================================================
260
+ # Test Runner
261
+ # ============================================================================
262
+
263
+
264
+ def run_async_test(test_func):
265
+ """Helper to run async test functions."""
266
+ asyncio.run(test_func())
267
+
268
+
269
+ def main():
270
+ """Run all tests."""
271
+ if not COGNEE_AVAILABLE:
272
+ print("⚠ Cognee not available - skipping tests")
273
+ print("Install with: pip install cognee[neo4j]")
274
+ return
275
+
276
+ print("=" * 80)
277
+ print("Running Usage Frequency Tests")
278
+ print("=" * 80)
279
+ print()
280
+
281
+ # Create test suite
282
+ loader = unittest.TestLoader()
283
+ suite = unittest.TestSuite()
284
+
285
+ # Add tests
286
+ suite.addTests(loader.loadTestsFromTestCase(TestUsageFrequencyExtraction))
287
+ suite.addTests(loader.loadTestsFromTestCase(TestIntegration))
288
+
289
+ # Run tests
290
+ runner = unittest.TextTestRunner(verbosity=2)
291
+ result = runner.run(suite)
292
+
293
+ # Summary
294
+ print()
295
+ print("=" * 80)
296
+ print("Test Summary")
297
+ print("=" * 80)
298
+ print(f"Tests run: {result.testsRun}")
299
+ print(f"Successes: {result.testsRun - len(result.failures) - len(result.errors)}")
300
+ print(f"Failures: {len(result.failures)}")
301
+ print(f"Errors: {len(result.errors)}")
302
+ print(f"Skipped: {len(result.skipped)}")
303
+
304
+ return 0 if result.wasSuccessful() else 1
305
+
306
+
307
+ if __name__ == "__main__":
308
+ exit(main())
cognee/tests/test_kuzu.py CHANGED
@@ -70,7 +70,9 @@ async def main():
70
70
  from cognee.infrastructure.databases.vector import get_vector_engine
71
71
 
72
72
  vector_engine = get_vector_engine()
73
- random_node = (await vector_engine.search("Entity_name", "Quantum computer"))[0]
73
+ random_node = (
74
+ await vector_engine.search("Entity_name", "Quantum computer", include_payload=True)
75
+ )[0]
74
76
  random_node_name = random_node.payload["text"]
75
77
 
76
78
  search_results = await cognee.search(
@@ -107,21 +109,29 @@ async def main():
107
109
 
108
110
  await cognee.cognify([dataset_name])
109
111
 
110
- context_nonempty = await GraphCompletionRetriever(
112
+ graph_retriever = GraphCompletionRetriever(
111
113
  node_type=NodeSet,
112
114
  node_name=["first"],
113
- ).get_context("What is in the context?")
115
+ )
116
+ objects = await graph_retriever.get_retrieved_objects("What is in the context?")
117
+ context_nonempty = await graph_retriever.get_context_from_objects(
118
+ "What is in the context?", objects
119
+ )
114
120
 
115
- context_empty = await GraphCompletionRetriever(
121
+ graph_retriever = GraphCompletionRetriever(
116
122
  node_type=NodeSet,
117
123
  node_name=["nonexistent"],
118
- ).get_context("What is in the context?")
124
+ )
125
+ objects = await graph_retriever.get_retrieved_objects("What is in the context?")
126
+ context_empty = await graph_retriever.get_context_from_objects(
127
+ "What is in the context?", objects
128
+ )
119
129
 
120
- assert isinstance(context_nonempty, list) and context_nonempty != [], (
130
+ assert isinstance(context_nonempty, str) and context_nonempty != "", (
121
131
  f"Nodeset_search_test:Expected non-empty string for context_nonempty, got: {context_nonempty!r}"
122
132
  )
123
133
 
124
- assert context_empty == [], (
134
+ assert context_empty == "", (
125
135
  f"Nodeset_search_test:Expected empty string for context_empty, got: {context_empty!r}"
126
136
  )
127
137
 
@@ -149,7 +149,9 @@ async def main():
149
149
  await test_getting_of_documents(dataset_name_1)
150
150
 
151
151
  vector_engine = get_vector_engine()
152
- random_node = (await vector_engine.search("Entity_name", "Quantum computer"))[0]
152
+ random_node = (
153
+ await vector_engine.search("Entity_name", "Quantum computer", include_payload=True)
154
+ )[0]
153
155
  random_node_name = random_node.payload["text"]
154
156
 
155
157
  search_results = await cognee.search(
@@ -48,7 +48,7 @@ async def main():
48
48
  from cognee.infrastructure.databases.vector import get_vector_engine
49
49
 
50
50
  vector_engine = get_vector_engine()
51
- random_node = (await vector_engine.search("Entity_name", "AI"))[0]
51
+ random_node = (await vector_engine.search("Entity_name", "AI", include_payload=True))[0]
52
52
  random_node_name = random_node.payload["text"]
53
53
 
54
54
  search_results = await cognee.search(
@@ -63,7 +63,9 @@ async def main():
63
63
  from cognee.infrastructure.databases.vector import get_vector_engine
64
64
 
65
65
  vector_engine = get_vector_engine()
66
- random_node = (await vector_engine.search("Entity_name", "Quantum computer"))[0]
66
+ random_node = (
67
+ await vector_engine.search("Entity_name", "Quantum computer", include_payload=True)
68
+ )[0]
67
69
  random_node_name = random_node.payload["text"]
68
70
 
69
71
  search_results = await cognee.search(
@@ -109,21 +111,29 @@ async def main():
109
111
 
110
112
  await cognee.cognify([dataset_name])
111
113
 
112
- context_nonempty = await GraphCompletionRetriever(
114
+ graph_retriever = GraphCompletionRetriever(
113
115
  node_type=NodeSet,
114
116
  node_name=["first"],
115
- ).get_context("What is in the context?")
117
+ )
118
+ objects = await graph_retriever.get_retrieved_objects("What is in the context?")
119
+ context_nonempty = await graph_retriever.get_context_from_objects(
120
+ "What is in the context?", objects
121
+ )
116
122
 
117
- context_empty = await GraphCompletionRetriever(
123
+ graph_retriever = GraphCompletionRetriever(
118
124
  node_type=NodeSet,
119
125
  node_name=["nonexistent"],
120
- ).get_context("What is in the context?")
126
+ )
127
+ objects = await graph_retriever.get_retrieved_objects("What is in the context?")
128
+ context_empty = await graph_retriever.get_context_from_objects(
129
+ "What is in the context?", objects
130
+ )
121
131
 
122
- assert isinstance(context_nonempty, list) and context_nonempty != [], (
132
+ assert isinstance(context_nonempty, str) and context_nonempty != "", (
123
133
  f"Nodeset_search_test:Expected non-empty string for context_nonempty, got: {context_nonempty!r}"
124
134
  )
125
135
 
126
- assert context_empty == [], (
136
+ assert context_empty == "", (
127
137
  f"Nodeset_search_test:Expected empty string for context_empty, got: {context_empty!r}"
128
138
  )
129
139
 
@@ -52,7 +52,9 @@ async def main():
52
52
  await cognee.cognify([dataset_name])
53
53
 
54
54
  vector_engine = get_vector_engine()
55
- random_node = (await vector_engine.search("Entity_name", "Quantum computer"))[0]
55
+ random_node = (
56
+ await vector_engine.search("Entity_name", "Quantum computer", include_payload=True)
57
+ )[0]
56
58
  random_node_name = random_node.payload["text"]
57
59
 
58
60
  search_results = await cognee.search(