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.
- cognee/__init__.py +2 -0
- cognee/alembic/README +1 -0
- cognee/alembic/env.py +107 -0
- cognee/alembic/script.py.mako +26 -0
- cognee/alembic/versions/1a58b986e6e1_enable_delete_for_old_tutorial_notebooks.py +52 -0
- cognee/alembic/versions/1d0bb7fede17_add_pipeline_run_status.py +33 -0
- cognee/alembic/versions/1daae0df1866_incremental_loading.py +48 -0
- cognee/alembic/versions/211ab850ef3d_add_sync_operations_table.py +118 -0
- cognee/alembic/versions/45957f0a9849_add_notebook_table.py +46 -0
- cognee/alembic/versions/46a6ce2bd2b2_expand_dataset_database_with_json_.py +333 -0
- cognee/alembic/versions/482cd6517ce4_add_default_user.py +30 -0
- cognee/alembic/versions/76625596c5c3_expand_dataset_database_for_multi_user.py +98 -0
- cognee/alembic/versions/8057ae7329c2_initial_migration.py +25 -0
- cognee/alembic/versions/9e7a3cb85175_loader_separation.py +104 -0
- cognee/alembic/versions/a1b2c3d4e5f6_add_label_column_to_data.py +38 -0
- cognee/alembic/versions/ab7e313804ae_permission_system_rework.py +236 -0
- cognee/alembic/versions/b9274c27a25a_kuzu_11_migration.py +75 -0
- cognee/alembic/versions/c946955da633_multi_tenant_support.py +137 -0
- cognee/alembic/versions/e1ec1dcb50b6_add_last_accessed_to_data.py +51 -0
- cognee/alembic/versions/e4ebee1091e7_expand_data_model_info.py +140 -0
- cognee/alembic.ini +117 -0
- cognee/api/v1/add/routers/get_add_router.py +2 -0
- cognee/api/v1/cognify/cognify.py +11 -6
- cognee/api/v1/cognify/routers/get_cognify_router.py +8 -0
- cognee/api/v1/config/config.py +60 -0
- cognee/api/v1/datasets/routers/get_datasets_router.py +45 -3
- cognee/api/v1/memify/routers/get_memify_router.py +2 -0
- cognee/api/v1/search/routers/get_search_router.py +21 -6
- cognee/api/v1/search/search.py +25 -5
- cognee/api/v1/sync/routers/get_sync_router.py +3 -3
- cognee/cli/commands/add_command.py +1 -1
- cognee/cli/commands/cognify_command.py +6 -0
- cognee/cli/commands/config_command.py +1 -1
- cognee/context_global_variables.py +5 -1
- cognee/eval_framework/answer_generation/answer_generation_executor.py +7 -8
- cognee/infrastructure/databases/cache/cache_db_interface.py +38 -1
- cognee/infrastructure/databases/cache/config.py +6 -0
- cognee/infrastructure/databases/cache/fscache/FsCacheAdapter.py +21 -0
- cognee/infrastructure/databases/cache/get_cache_engine.py +9 -3
- cognee/infrastructure/databases/cache/redis/RedisAdapter.py +60 -1
- cognee/infrastructure/databases/dataset_database_handler/supported_dataset_database_handlers.py +7 -0
- cognee/infrastructure/databases/graph/get_graph_engine.py +29 -1
- cognee/infrastructure/databases/graph/neo4j_driver/Neo4jAuraDevDatasetDatabaseHandler.py +62 -27
- cognee/infrastructure/databases/hybrid/neptune_analytics/NeptuneAnalyticsAdapter.py +17 -4
- cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py +2 -1
- cognee/infrastructure/databases/vector/chromadb/ChromaDBAdapter.py +2 -0
- cognee/infrastructure/databases/vector/config.py +6 -0
- cognee/infrastructure/databases/vector/create_vector_engine.py +69 -22
- cognee/infrastructure/databases/vector/embeddings/LiteLLMEmbeddingEngine.py +64 -9
- cognee/infrastructure/databases/vector/embeddings/OllamaEmbeddingEngine.py +13 -2
- cognee/infrastructure/databases/vector/lancedb/LanceDBAdapter.py +16 -3
- cognee/infrastructure/databases/vector/models/ScoredResult.py +3 -3
- cognee/infrastructure/databases/vector/pgvector/PGVectorAdapter.py +16 -3
- cognee/infrastructure/databases/vector/pgvector/PGVectorDatasetDatabaseHandler.py +86 -0
- cognee/infrastructure/databases/vector/pgvector/create_db_and_tables.py +81 -2
- cognee/infrastructure/databases/vector/vector_db_interface.py +8 -0
- cognee/infrastructure/files/utils/get_data_file_path.py +33 -27
- cognee/infrastructure/llm/prompts/extract_query_time.txt +1 -1
- cognee/infrastructure/llm/prompts/generate_event_entity_prompt.txt +1 -1
- cognee/infrastructure/llm/prompts/generate_event_graph_prompt.txt +1 -1
- cognee/infrastructure/llm/prompts/generate_graph_prompt.txt +2 -2
- cognee/infrastructure/llm/prompts/generate_graph_prompt_guided.txt +1 -1
- cognee/infrastructure/llm/prompts/generate_graph_prompt_oneshot.txt +2 -2
- cognee/infrastructure/llm/prompts/generate_graph_prompt_simple.txt +1 -1
- cognee/infrastructure/llm/prompts/generate_graph_prompt_strict.txt +1 -1
- cognee/infrastructure/llm/prompts/search_type_selector_prompt.txt +6 -6
- cognee/infrastructure/llm/prompts/test.txt +1 -1
- cognee/infrastructure/llm/prompts/translate_content.txt +19 -0
- cognee/infrastructure/llm/structured_output_framework/litellm_instructor/llm/get_llm_client.py +24 -0
- cognee/infrastructure/llm/structured_output_framework/litellm_instructor/llm/llama_cpp/adapter.py +191 -0
- cognee/modules/chunking/models/DocumentChunk.py +0 -1
- cognee/modules/cognify/config.py +2 -0
- cognee/modules/data/models/Data.py +1 -0
- cognee/modules/engine/models/Entity.py +0 -1
- cognee/modules/engine/operations/setup.py +6 -0
- cognee/modules/graph/cognee_graph/CogneeGraph.py +150 -37
- cognee/modules/graph/cognee_graph/CogneeGraphElements.py +48 -2
- cognee/modules/graph/utils/__init__.py +1 -0
- cognee/modules/graph/utils/get_entity_nodes_from_triplets.py +12 -0
- cognee/modules/notebooks/methods/__init__.py +1 -0
- cognee/modules/notebooks/methods/create_notebook.py +0 -34
- cognee/modules/notebooks/methods/create_tutorial_notebooks.py +191 -0
- cognee/modules/notebooks/methods/get_notebooks.py +12 -8
- cognee/modules/notebooks/tutorials/cognee-basics/cell-1.md +3 -0
- cognee/modules/notebooks/tutorials/cognee-basics/cell-2.md +10 -0
- cognee/modules/notebooks/tutorials/cognee-basics/cell-3.md +7 -0
- cognee/modules/notebooks/tutorials/cognee-basics/cell-4.py +28 -0
- cognee/modules/notebooks/tutorials/cognee-basics/cell-5.py +3 -0
- cognee/modules/notebooks/tutorials/cognee-basics/cell-6.py +9 -0
- cognee/modules/notebooks/tutorials/cognee-basics/cell-7.py +17 -0
- cognee/modules/notebooks/tutorials/cognee-basics/config.json +4 -0
- cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-1.md +3 -0
- cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-10.md +3 -0
- cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-11.md +3 -0
- cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-12.py +3 -0
- cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-13.md +7 -0
- cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-14.py +6 -0
- cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-15.md +3 -0
- cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-16.py +7 -0
- cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-2.md +9 -0
- cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-3.md +7 -0
- cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-4.md +9 -0
- cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-5.md +5 -0
- cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-6.py +13 -0
- cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-7.md +3 -0
- cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-8.md +3 -0
- cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-9.py +31 -0
- cognee/modules/notebooks/tutorials/python-development-with-cognee/config.json +4 -0
- cognee/modules/notebooks/tutorials/python-development-with-cognee/data/copilot_conversations.json +107 -0
- cognee/modules/notebooks/tutorials/python-development-with-cognee/data/guido_contributions.json +976 -0
- cognee/modules/notebooks/tutorials/python-development-with-cognee/data/my_developer_rules.md +79 -0
- cognee/modules/notebooks/tutorials/python-development-with-cognee/data/pep_style_guide.md +74 -0
- cognee/modules/notebooks/tutorials/python-development-with-cognee/data/zen_principles.md +74 -0
- cognee/modules/retrieval/EntityCompletionRetriever.py +51 -38
- cognee/modules/retrieval/__init__.py +0 -1
- cognee/modules/retrieval/base_retriever.py +66 -10
- cognee/modules/retrieval/chunks_retriever.py +57 -49
- cognee/modules/retrieval/coding_rules_retriever.py +12 -5
- cognee/modules/retrieval/completion_retriever.py +29 -28
- cognee/modules/retrieval/cypher_search_retriever.py +25 -20
- cognee/modules/retrieval/graph_completion_context_extension_retriever.py +42 -46
- cognee/modules/retrieval/graph_completion_cot_retriever.py +68 -51
- cognee/modules/retrieval/graph_completion_retriever.py +78 -63
- cognee/modules/retrieval/graph_summary_completion_retriever.py +2 -0
- cognee/modules/retrieval/lexical_retriever.py +34 -12
- cognee/modules/retrieval/natural_language_retriever.py +18 -15
- cognee/modules/retrieval/summaries_retriever.py +51 -34
- cognee/modules/retrieval/temporal_retriever.py +59 -49
- cognee/modules/retrieval/triplet_retriever.py +31 -32
- cognee/modules/retrieval/utils/access_tracking.py +88 -0
- cognee/modules/retrieval/utils/brute_force_triplet_search.py +99 -85
- cognee/modules/retrieval/utils/node_edge_vector_search.py +174 -0
- cognee/modules/search/methods/__init__.py +1 -0
- cognee/modules/search/methods/get_retriever_output.py +53 -0
- cognee/modules/search/methods/get_search_type_retriever_instance.py +252 -0
- cognee/modules/search/methods/search.py +90 -215
- cognee/modules/search/models/SearchResultPayload.py +67 -0
- cognee/modules/search/types/SearchResult.py +1 -8
- cognee/modules/search/types/SearchType.py +1 -2
- cognee/modules/search/types/__init__.py +1 -1
- cognee/modules/search/utils/__init__.py +1 -2
- cognee/modules/search/utils/transform_insights_to_graph.py +2 -2
- cognee/modules/search/utils/{transform_context_to_graph.py → transform_triplets_to_graph.py} +2 -2
- cognee/modules/users/authentication/default/default_transport.py +11 -1
- cognee/modules/users/authentication/get_api_auth_backend.py +2 -1
- cognee/modules/users/authentication/get_client_auth_backend.py +2 -1
- cognee/modules/users/methods/create_user.py +0 -9
- cognee/modules/users/permissions/methods/has_user_management_permission.py +29 -0
- cognee/modules/visualization/cognee_network_visualization.py +1 -1
- cognee/run_migrations.py +48 -0
- cognee/shared/exceptions/__init__.py +1 -3
- cognee/shared/exceptions/exceptions.py +11 -1
- cognee/shared/usage_logger.py +332 -0
- cognee/shared/utils.py +12 -5
- cognee/tasks/cleanup/cleanup_unused_data.py +172 -0
- cognee/tasks/memify/extract_usage_frequency.py +613 -0
- cognee/tasks/summarization/models.py +0 -2
- cognee/tasks/temporal_graph/__init__.py +0 -1
- cognee/tasks/translation/__init__.py +96 -0
- cognee/tasks/translation/config.py +110 -0
- cognee/tasks/translation/detect_language.py +190 -0
- cognee/tasks/translation/exceptions.py +62 -0
- cognee/tasks/translation/models.py +72 -0
- cognee/tasks/translation/providers/__init__.py +44 -0
- cognee/tasks/translation/providers/azure_provider.py +192 -0
- cognee/tasks/translation/providers/base.py +85 -0
- cognee/tasks/translation/providers/google_provider.py +158 -0
- cognee/tasks/translation/providers/llm_provider.py +143 -0
- cognee/tasks/translation/translate_content.py +282 -0
- cognee/tasks/web_scraper/default_url_crawler.py +6 -2
- cognee/tests/cli_tests/cli_unit_tests/test_cli_commands.py +1 -0
- cognee/tests/cli_tests/cli_unit_tests/test_cli_edge_cases.py +3 -0
- cognee/tests/integration/retrieval/test_brute_force_triplet_search_with_cognify.py +62 -0
- cognee/tests/integration/retrieval/test_chunks_retriever.py +115 -16
- cognee/tests/integration/retrieval/test_graph_completion_retriever.py +13 -5
- cognee/tests/integration/retrieval/test_graph_completion_retriever_context_extension.py +22 -20
- cognee/tests/integration/retrieval/test_graph_completion_retriever_cot.py +23 -24
- cognee/tests/integration/retrieval/test_rag_completion_retriever.py +70 -5
- cognee/tests/integration/retrieval/test_structured_output.py +62 -18
- cognee/tests/integration/retrieval/test_summaries_retriever.py +20 -9
- cognee/tests/integration/retrieval/test_temporal_retriever.py +38 -8
- cognee/tests/integration/retrieval/test_triplet_retriever.py +13 -4
- cognee/tests/integration/shared/test_usage_logger_integration.py +255 -0
- cognee/tests/tasks/translation/README.md +147 -0
- cognee/tests/tasks/translation/__init__.py +1 -0
- cognee/tests/tasks/translation/config_test.py +93 -0
- cognee/tests/tasks/translation/detect_language_test.py +118 -0
- cognee/tests/tasks/translation/providers_test.py +151 -0
- cognee/tests/tasks/translation/translate_content_test.py +213 -0
- cognee/tests/test_chromadb.py +1 -1
- cognee/tests/test_cleanup_unused_data.py +165 -0
- cognee/tests/test_delete_by_id.py +6 -6
- cognee/tests/test_extract_usage_frequency.py +308 -0
- cognee/tests/test_kuzu.py +17 -7
- cognee/tests/test_lancedb.py +3 -1
- cognee/tests/test_library.py +1 -1
- cognee/tests/test_neo4j.py +17 -7
- cognee/tests/test_neptune_analytics_vector.py +3 -1
- cognee/tests/test_permissions.py +172 -187
- cognee/tests/test_pgvector.py +3 -1
- cognee/tests/test_relational_db_migration.py +15 -1
- cognee/tests/test_remote_kuzu.py +3 -1
- cognee/tests/test_s3_file_storage.py +1 -1
- cognee/tests/test_search_db.py +97 -110
- cognee/tests/test_usage_logger_e2e.py +268 -0
- cognee/tests/unit/api/test_get_raw_data_endpoint.py +206 -0
- cognee/tests/unit/eval_framework/answer_generation_test.py +4 -3
- cognee/tests/unit/infrastructure/databases/cache/test_cache_config.py +2 -0
- cognee/tests/unit/modules/graph/cognee_graph_elements_test.py +42 -2
- cognee/tests/unit/modules/graph/cognee_graph_test.py +329 -31
- cognee/tests/unit/modules/retrieval/chunks_retriever_test.py +31 -59
- cognee/tests/unit/modules/retrieval/graph_completion_retriever_context_extension_test.py +70 -33
- cognee/tests/unit/modules/retrieval/graph_completion_retriever_cot_test.py +72 -52
- cognee/tests/unit/modules/retrieval/graph_completion_retriever_test.py +27 -33
- cognee/tests/unit/modules/retrieval/rag_completion_retriever_test.py +28 -15
- cognee/tests/unit/modules/retrieval/summaries_retriever_test.py +37 -42
- cognee/tests/unit/modules/retrieval/temporal_retriever_test.py +48 -64
- cognee/tests/unit/modules/retrieval/test_brute_force_triplet_search.py +263 -24
- cognee/tests/unit/modules/retrieval/test_node_edge_vector_search.py +273 -0
- cognee/tests/unit/modules/retrieval/triplet_retriever_test.py +30 -16
- cognee/tests/unit/modules/search/test_get_search_type_retriever_instance.py +125 -0
- cognee/tests/unit/modules/search/test_search.py +176 -0
- cognee/tests/unit/modules/search/test_search_prepare_search_result_contract.py +190 -0
- cognee/tests/unit/modules/users/test_tutorial_notebook_creation.py +511 -297
- cognee/tests/unit/shared/test_usage_logger.py +241 -0
- cognee/tests/unit/users/permissions/test_has_user_management_permission.py +46 -0
- {cognee-0.5.1.dev0.dist-info → cognee-0.5.2.dev0.dist-info}/METADATA +17 -10
- {cognee-0.5.1.dev0.dist-info → cognee-0.5.2.dev0.dist-info}/RECORD +232 -144
- cognee/api/.env.example +0 -5
- cognee/modules/retrieval/base_graph_retriever.py +0 -24
- cognee/modules/search/methods/get_search_type_tools.py +0 -223
- cognee/modules/search/methods/no_access_control_search.py +0 -62
- cognee/modules/search/utils/prepare_search_result.py +0 -63
- cognee/tests/test_feedback_enrichment.py +0 -174
- {cognee-0.5.1.dev0.dist-info → cognee-0.5.2.dev0.dist-info}/WHEEL +0 -0
- {cognee-0.5.1.dev0.dist-info → cognee-0.5.2.dev0.dist-info}/entry_points.txt +0 -0
- {cognee-0.5.1.dev0.dist-info → cognee-0.5.2.dev0.dist-info}/licenses/LICENSE +0 -0
- {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 = (
|
|
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
|
-
|
|
112
|
+
graph_retriever = GraphCompletionRetriever(
|
|
111
113
|
node_type=NodeSet,
|
|
112
114
|
node_name=["first"],
|
|
113
|
-
)
|
|
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
|
-
|
|
121
|
+
graph_retriever = GraphCompletionRetriever(
|
|
116
122
|
node_type=NodeSet,
|
|
117
123
|
node_name=["nonexistent"],
|
|
118
|
-
)
|
|
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,
|
|
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
|
|
cognee/tests/test_lancedb.py
CHANGED
|
@@ -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 = (
|
|
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(
|
cognee/tests/test_library.py
CHANGED
|
@@ -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(
|
cognee/tests/test_neo4j.py
CHANGED
|
@@ -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 = (
|
|
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
|
-
|
|
114
|
+
graph_retriever = GraphCompletionRetriever(
|
|
113
115
|
node_type=NodeSet,
|
|
114
116
|
node_name=["first"],
|
|
115
|
-
)
|
|
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
|
-
|
|
123
|
+
graph_retriever = GraphCompletionRetriever(
|
|
118
124
|
node_type=NodeSet,
|
|
119
125
|
node_name=["nonexistent"],
|
|
120
|
-
)
|
|
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,
|
|
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 = (
|
|
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(
|