cognee 0.5.1__py3-none-any.whl → 0.5.2__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 (265) 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/add.py +2 -1
  23. cognee/api/v1/add/routers/get_add_router.py +2 -0
  24. cognee/api/v1/cognify/cognify.py +11 -6
  25. cognee/api/v1/cognify/routers/get_cognify_router.py +8 -0
  26. cognee/api/v1/config/config.py +60 -0
  27. cognee/api/v1/datasets/routers/get_datasets_router.py +46 -3
  28. cognee/api/v1/memify/routers/get_memify_router.py +3 -0
  29. cognee/api/v1/search/routers/get_search_router.py +21 -6
  30. cognee/api/v1/search/search.py +21 -5
  31. cognee/api/v1/sync/routers/get_sync_router.py +3 -3
  32. cognee/cli/commands/add_command.py +1 -1
  33. cognee/cli/commands/cognify_command.py +6 -0
  34. cognee/cli/commands/config_command.py +1 -1
  35. cognee/context_global_variables.py +5 -1
  36. cognee/eval_framework/answer_generation/answer_generation_executor.py +7 -8
  37. cognee/infrastructure/databases/cache/cache_db_interface.py +38 -1
  38. cognee/infrastructure/databases/cache/config.py +6 -0
  39. cognee/infrastructure/databases/cache/fscache/FsCacheAdapter.py +21 -0
  40. cognee/infrastructure/databases/cache/get_cache_engine.py +9 -3
  41. cognee/infrastructure/databases/cache/redis/RedisAdapter.py +60 -1
  42. cognee/infrastructure/databases/dataset_database_handler/supported_dataset_database_handlers.py +7 -0
  43. cognee/infrastructure/databases/graph/get_graph_engine.py +29 -1
  44. cognee/infrastructure/databases/graph/neo4j_driver/Neo4jAuraDevDatasetDatabaseHandler.py +62 -27
  45. cognee/infrastructure/databases/hybrid/neptune_analytics/NeptuneAnalyticsAdapter.py +17 -4
  46. cognee/infrastructure/databases/relational/config.py +16 -1
  47. cognee/infrastructure/databases/relational/create_relational_engine.py +13 -3
  48. cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py +26 -3
  49. cognee/infrastructure/databases/vector/chromadb/ChromaDBAdapter.py +2 -0
  50. cognee/infrastructure/databases/vector/config.py +6 -0
  51. cognee/infrastructure/databases/vector/create_vector_engine.py +70 -16
  52. cognee/infrastructure/databases/vector/embeddings/LiteLLMEmbeddingEngine.py +64 -9
  53. cognee/infrastructure/databases/vector/embeddings/OllamaEmbeddingEngine.py +13 -2
  54. cognee/infrastructure/databases/vector/lancedb/LanceDBAdapter.py +16 -3
  55. cognee/infrastructure/databases/vector/models/ScoredResult.py +3 -3
  56. cognee/infrastructure/databases/vector/pgvector/PGVectorAdapter.py +16 -3
  57. cognee/infrastructure/databases/vector/pgvector/PGVectorDatasetDatabaseHandler.py +86 -0
  58. cognee/infrastructure/databases/vector/pgvector/create_db_and_tables.py +81 -2
  59. cognee/infrastructure/databases/vector/vector_db_interface.py +8 -0
  60. cognee/infrastructure/files/utils/get_data_file_path.py +33 -27
  61. cognee/infrastructure/llm/LLMGateway.py +0 -13
  62. cognee/infrastructure/llm/prompts/extract_query_time.txt +1 -1
  63. cognee/infrastructure/llm/prompts/generate_event_entity_prompt.txt +1 -1
  64. cognee/infrastructure/llm/prompts/generate_event_graph_prompt.txt +1 -1
  65. cognee/infrastructure/llm/prompts/generate_graph_prompt.txt +2 -2
  66. cognee/infrastructure/llm/prompts/generate_graph_prompt_guided.txt +1 -1
  67. cognee/infrastructure/llm/prompts/generate_graph_prompt_oneshot.txt +2 -2
  68. cognee/infrastructure/llm/prompts/generate_graph_prompt_simple.txt +1 -1
  69. cognee/infrastructure/llm/prompts/generate_graph_prompt_strict.txt +1 -1
  70. cognee/infrastructure/llm/prompts/search_type_selector_prompt.txt +6 -6
  71. cognee/infrastructure/llm/prompts/test.txt +1 -1
  72. cognee/infrastructure/llm/prompts/translate_content.txt +19 -0
  73. cognee/infrastructure/llm/structured_output_framework/litellm_instructor/llm/anthropic/adapter.py +17 -12
  74. cognee/infrastructure/llm/structured_output_framework/litellm_instructor/llm/gemini/adapter.py +31 -25
  75. cognee/infrastructure/llm/structured_output_framework/litellm_instructor/llm/generic_llm_api/adapter.py +132 -7
  76. cognee/infrastructure/llm/structured_output_framework/litellm_instructor/llm/get_llm_client.py +29 -5
  77. cognee/infrastructure/llm/structured_output_framework/litellm_instructor/llm/llama_cpp/adapter.py +191 -0
  78. cognee/infrastructure/llm/structured_output_framework/litellm_instructor/llm/llm_interface.py +2 -6
  79. cognee/infrastructure/llm/structured_output_framework/litellm_instructor/llm/mistral/adapter.py +58 -13
  80. cognee/infrastructure/llm/structured_output_framework/litellm_instructor/llm/ollama/adapter.py +0 -1
  81. cognee/infrastructure/llm/structured_output_framework/litellm_instructor/llm/openai/adapter.py +25 -131
  82. cognee/infrastructure/llm/structured_output_framework/litellm_instructor/llm/types.py +10 -0
  83. cognee/modules/chunking/models/DocumentChunk.py +0 -1
  84. cognee/modules/cognify/config.py +2 -0
  85. cognee/modules/data/models/Data.py +3 -1
  86. cognee/modules/engine/models/Entity.py +0 -1
  87. cognee/modules/engine/operations/setup.py +6 -0
  88. cognee/modules/graph/cognee_graph/CogneeGraph.py +150 -37
  89. cognee/modules/graph/cognee_graph/CogneeGraphElements.py +48 -2
  90. cognee/modules/graph/utils/__init__.py +1 -0
  91. cognee/modules/graph/utils/get_entity_nodes_from_triplets.py +12 -0
  92. cognee/modules/notebooks/methods/__init__.py +1 -0
  93. cognee/modules/notebooks/methods/create_notebook.py +0 -34
  94. cognee/modules/notebooks/methods/create_tutorial_notebooks.py +191 -0
  95. cognee/modules/notebooks/methods/get_notebooks.py +12 -8
  96. cognee/modules/notebooks/tutorials/cognee-basics/cell-1.md +3 -0
  97. cognee/modules/notebooks/tutorials/cognee-basics/cell-2.md +10 -0
  98. cognee/modules/notebooks/tutorials/cognee-basics/cell-3.md +7 -0
  99. cognee/modules/notebooks/tutorials/cognee-basics/cell-4.py +28 -0
  100. cognee/modules/notebooks/tutorials/cognee-basics/cell-5.py +3 -0
  101. cognee/modules/notebooks/tutorials/cognee-basics/cell-6.py +9 -0
  102. cognee/modules/notebooks/tutorials/cognee-basics/cell-7.py +17 -0
  103. cognee/modules/notebooks/tutorials/cognee-basics/config.json +4 -0
  104. cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-1.md +3 -0
  105. cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-10.md +3 -0
  106. cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-11.md +3 -0
  107. cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-12.py +3 -0
  108. cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-13.md +7 -0
  109. cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-14.py +6 -0
  110. cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-15.md +3 -0
  111. cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-16.py +7 -0
  112. cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-2.md +9 -0
  113. cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-3.md +7 -0
  114. cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-4.md +9 -0
  115. cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-5.md +5 -0
  116. cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-6.py +13 -0
  117. cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-7.md +3 -0
  118. cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-8.md +3 -0
  119. cognee/modules/notebooks/tutorials/python-development-with-cognee/cell-9.py +31 -0
  120. cognee/modules/notebooks/tutorials/python-development-with-cognee/config.json +4 -0
  121. cognee/modules/notebooks/tutorials/python-development-with-cognee/data/copilot_conversations.json +107 -0
  122. cognee/modules/notebooks/tutorials/python-development-with-cognee/data/guido_contributions.json +976 -0
  123. cognee/modules/notebooks/tutorials/python-development-with-cognee/data/my_developer_rules.md +79 -0
  124. cognee/modules/notebooks/tutorials/python-development-with-cognee/data/pep_style_guide.md +74 -0
  125. cognee/modules/notebooks/tutorials/python-development-with-cognee/data/zen_principles.md +74 -0
  126. cognee/modules/retrieval/EntityCompletionRetriever.py +51 -38
  127. cognee/modules/retrieval/__init__.py +0 -1
  128. cognee/modules/retrieval/base_retriever.py +66 -10
  129. cognee/modules/retrieval/chunks_retriever.py +57 -49
  130. cognee/modules/retrieval/coding_rules_retriever.py +12 -5
  131. cognee/modules/retrieval/completion_retriever.py +29 -28
  132. cognee/modules/retrieval/cypher_search_retriever.py +25 -20
  133. cognee/modules/retrieval/graph_completion_context_extension_retriever.py +42 -46
  134. cognee/modules/retrieval/graph_completion_cot_retriever.py +68 -51
  135. cognee/modules/retrieval/graph_completion_retriever.py +78 -63
  136. cognee/modules/retrieval/graph_summary_completion_retriever.py +2 -0
  137. cognee/modules/retrieval/lexical_retriever.py +34 -12
  138. cognee/modules/retrieval/natural_language_retriever.py +18 -15
  139. cognee/modules/retrieval/summaries_retriever.py +51 -34
  140. cognee/modules/retrieval/temporal_retriever.py +59 -49
  141. cognee/modules/retrieval/triplet_retriever.py +32 -33
  142. cognee/modules/retrieval/utils/access_tracking.py +88 -0
  143. cognee/modules/retrieval/utils/brute_force_triplet_search.py +99 -103
  144. cognee/modules/retrieval/utils/node_edge_vector_search.py +174 -0
  145. cognee/modules/search/methods/__init__.py +1 -0
  146. cognee/modules/search/methods/get_retriever_output.py +53 -0
  147. cognee/modules/search/methods/get_search_type_retriever_instance.py +252 -0
  148. cognee/modules/search/methods/search.py +90 -222
  149. cognee/modules/search/models/SearchResultPayload.py +67 -0
  150. cognee/modules/search/types/SearchResult.py +1 -8
  151. cognee/modules/search/types/SearchType.py +1 -2
  152. cognee/modules/search/types/__init__.py +1 -1
  153. cognee/modules/search/utils/__init__.py +1 -2
  154. cognee/modules/search/utils/transform_insights_to_graph.py +2 -2
  155. cognee/modules/search/utils/{transform_context_to_graph.py → transform_triplets_to_graph.py} +2 -2
  156. cognee/modules/users/authentication/default/default_transport.py +11 -1
  157. cognee/modules/users/authentication/get_api_auth_backend.py +2 -1
  158. cognee/modules/users/authentication/get_client_auth_backend.py +2 -1
  159. cognee/modules/users/methods/create_user.py +0 -9
  160. cognee/modules/users/permissions/methods/has_user_management_permission.py +29 -0
  161. cognee/modules/visualization/cognee_network_visualization.py +1 -1
  162. cognee/run_migrations.py +48 -0
  163. cognee/shared/exceptions/__init__.py +1 -3
  164. cognee/shared/exceptions/exceptions.py +11 -1
  165. cognee/shared/usage_logger.py +332 -0
  166. cognee/shared/utils.py +12 -5
  167. cognee/tasks/chunks/__init__.py +9 -0
  168. cognee/tasks/cleanup/cleanup_unused_data.py +172 -0
  169. cognee/tasks/graph/__init__.py +7 -0
  170. cognee/tasks/ingestion/data_item.py +8 -0
  171. cognee/tasks/ingestion/ingest_data.py +12 -1
  172. cognee/tasks/ingestion/save_data_item_to_storage.py +5 -0
  173. cognee/tasks/memify/__init__.py +8 -0
  174. cognee/tasks/memify/extract_usage_frequency.py +613 -0
  175. cognee/tasks/summarization/models.py +0 -2
  176. cognee/tasks/temporal_graph/__init__.py +0 -1
  177. cognee/tasks/translation/__init__.py +96 -0
  178. cognee/tasks/translation/config.py +110 -0
  179. cognee/tasks/translation/detect_language.py +190 -0
  180. cognee/tasks/translation/exceptions.py +62 -0
  181. cognee/tasks/translation/models.py +72 -0
  182. cognee/tasks/translation/providers/__init__.py +44 -0
  183. cognee/tasks/translation/providers/azure_provider.py +192 -0
  184. cognee/tasks/translation/providers/base.py +85 -0
  185. cognee/tasks/translation/providers/google_provider.py +158 -0
  186. cognee/tasks/translation/providers/llm_provider.py +143 -0
  187. cognee/tasks/translation/translate_content.py +282 -0
  188. cognee/tasks/web_scraper/default_url_crawler.py +6 -2
  189. cognee/tests/cli_tests/cli_unit_tests/test_cli_commands.py +1 -0
  190. cognee/tests/cli_tests/cli_unit_tests/test_cli_edge_cases.py +3 -0
  191. cognee/tests/integration/retrieval/test_brute_force_triplet_search_with_cognify.py +62 -0
  192. cognee/tests/integration/retrieval/test_chunks_retriever.py +351 -0
  193. cognee/tests/integration/retrieval/test_graph_completion_retriever.py +276 -0
  194. cognee/tests/integration/retrieval/test_graph_completion_retriever_context_extension.py +228 -0
  195. cognee/tests/integration/retrieval/test_graph_completion_retriever_cot.py +217 -0
  196. cognee/tests/integration/retrieval/test_rag_completion_retriever.py +319 -0
  197. cognee/tests/integration/retrieval/test_structured_output.py +258 -0
  198. cognee/tests/integration/retrieval/test_summaries_retriever.py +195 -0
  199. cognee/tests/integration/retrieval/test_temporal_retriever.py +336 -0
  200. cognee/tests/integration/retrieval/test_triplet_retriever.py +45 -1
  201. cognee/tests/integration/shared/test_usage_logger_integration.py +255 -0
  202. cognee/tests/tasks/translation/README.md +147 -0
  203. cognee/tests/tasks/translation/__init__.py +1 -0
  204. cognee/tests/tasks/translation/config_test.py +93 -0
  205. cognee/tests/tasks/translation/detect_language_test.py +118 -0
  206. cognee/tests/tasks/translation/providers_test.py +151 -0
  207. cognee/tests/tasks/translation/translate_content_test.py +213 -0
  208. cognee/tests/test_chromadb.py +1 -1
  209. cognee/tests/test_cleanup_unused_data.py +165 -0
  210. cognee/tests/test_custom_data_label.py +68 -0
  211. cognee/tests/test_delete_by_id.py +6 -6
  212. cognee/tests/test_extract_usage_frequency.py +308 -0
  213. cognee/tests/test_kuzu.py +17 -7
  214. cognee/tests/test_lancedb.py +3 -1
  215. cognee/tests/test_library.py +1 -1
  216. cognee/tests/test_neo4j.py +17 -7
  217. cognee/tests/test_neptune_analytics_vector.py +3 -1
  218. cognee/tests/test_permissions.py +172 -187
  219. cognee/tests/test_pgvector.py +3 -1
  220. cognee/tests/test_relational_db_migration.py +15 -1
  221. cognee/tests/test_remote_kuzu.py +3 -1
  222. cognee/tests/test_s3_file_storage.py +1 -1
  223. cognee/tests/test_search_db.py +345 -205
  224. cognee/tests/test_usage_logger_e2e.py +268 -0
  225. cognee/tests/unit/api/test_get_raw_data_endpoint.py +206 -0
  226. cognee/tests/unit/eval_framework/answer_generation_test.py +4 -3
  227. cognee/tests/unit/eval_framework/benchmark_adapters_test.py +25 -0
  228. cognee/tests/unit/eval_framework/corpus_builder_test.py +33 -4
  229. cognee/tests/unit/infrastructure/databases/cache/test_cache_config.py +2 -0
  230. cognee/tests/unit/infrastructure/databases/relational/test_RelationalConfig.py +69 -0
  231. cognee/tests/unit/modules/graph/cognee_graph_elements_test.py +42 -2
  232. cognee/tests/unit/modules/graph/cognee_graph_test.py +329 -31
  233. cognee/tests/unit/modules/retrieval/chunks_retriever_test.py +122 -168
  234. cognee/tests/unit/modules/retrieval/conversation_history_test.py +338 -0
  235. cognee/tests/unit/modules/retrieval/graph_completion_retriever_context_extension_test.py +486 -157
  236. cognee/tests/unit/modules/retrieval/graph_completion_retriever_cot_test.py +693 -155
  237. cognee/tests/unit/modules/retrieval/graph_completion_retriever_test.py +619 -200
  238. cognee/tests/unit/modules/retrieval/rag_completion_retriever_test.py +300 -171
  239. cognee/tests/unit/modules/retrieval/summaries_retriever_test.py +184 -155
  240. cognee/tests/unit/modules/retrieval/temporal_retriever_test.py +544 -79
  241. cognee/tests/unit/modules/retrieval/test_brute_force_triplet_search.py +476 -28
  242. cognee/tests/unit/modules/retrieval/test_completion.py +343 -0
  243. cognee/tests/unit/modules/retrieval/test_graph_summary_completion_retriever.py +157 -0
  244. cognee/tests/unit/modules/retrieval/test_node_edge_vector_search.py +273 -0
  245. cognee/tests/unit/modules/retrieval/test_user_qa_feedback.py +312 -0
  246. cognee/tests/unit/modules/retrieval/triplet_retriever_test.py +267 -7
  247. cognee/tests/unit/modules/search/test_get_search_type_retriever_instance.py +125 -0
  248. cognee/tests/unit/modules/search/test_search.py +96 -20
  249. cognee/tests/unit/modules/search/test_search_prepare_search_result_contract.py +190 -0
  250. cognee/tests/unit/modules/users/test_tutorial_notebook_creation.py +511 -297
  251. cognee/tests/unit/shared/test_usage_logger.py +241 -0
  252. cognee/tests/unit/users/permissions/test_has_user_management_permission.py +46 -0
  253. {cognee-0.5.1.dist-info → cognee-0.5.2.dist-info}/METADATA +22 -17
  254. {cognee-0.5.1.dist-info → cognee-0.5.2.dist-info}/RECORD +258 -157
  255. cognee/api/.env.example +0 -5
  256. cognee/modules/retrieval/base_graph_retriever.py +0 -24
  257. cognee/modules/search/methods/get_search_type_tools.py +0 -223
  258. cognee/modules/search/methods/no_access_control_search.py +0 -62
  259. cognee/modules/search/utils/prepare_search_result.py +0 -63
  260. cognee/tests/test_feedback_enrichment.py +0 -174
  261. cognee/tests/unit/modules/retrieval/structured_output_test.py +0 -204
  262. {cognee-0.5.1.dist-info → cognee-0.5.2.dist-info}/WHEEL +0 -0
  263. {cognee-0.5.1.dist-info → cognee-0.5.2.dist-info}/entry_points.txt +0 -0
  264. {cognee-0.5.1.dist-info → cognee-0.5.2.dist-info}/licenses/LICENSE +0 -0
  265. {cognee-0.5.1.dist-info → cognee-0.5.2.dist-info}/licenses/NOTICE.md +0 -0
@@ -0,0 +1,255 @@
1
+ """Integration tests for usage logger with real Redis components."""
2
+
3
+ import os
4
+ import pytest
5
+ import asyncio
6
+ from datetime import datetime, timezone
7
+ from types import SimpleNamespace
8
+ from uuid import UUID
9
+ from unittest.mock import patch
10
+
11
+ from cognee.shared.usage_logger import log_usage
12
+ from cognee.infrastructure.databases.cache.config import get_cache_config
13
+ from cognee.infrastructure.databases.cache.get_cache_engine import (
14
+ get_cache_engine,
15
+ create_cache_engine,
16
+ )
17
+
18
+
19
+ @pytest.fixture
20
+ def usage_logging_config():
21
+ """Fixture to enable usage logging via environment variables."""
22
+ original_env = os.environ.copy()
23
+ os.environ["USAGE_LOGGING"] = "true"
24
+ os.environ["CACHE_BACKEND"] = "redis"
25
+ os.environ["CACHE_HOST"] = "localhost"
26
+ os.environ["CACHE_PORT"] = "6379"
27
+ get_cache_config.cache_clear()
28
+ create_cache_engine.cache_clear()
29
+ yield
30
+ os.environ.clear()
31
+ os.environ.update(original_env)
32
+ get_cache_config.cache_clear()
33
+ create_cache_engine.cache_clear()
34
+
35
+
36
+ @pytest.fixture
37
+ def usage_logging_disabled():
38
+ """Fixture to disable usage logging via environment variables."""
39
+ original_env = os.environ.copy()
40
+ os.environ["USAGE_LOGGING"] = "false"
41
+ os.environ["CACHE_BACKEND"] = "redis"
42
+ get_cache_config.cache_clear()
43
+ create_cache_engine.cache_clear()
44
+ yield
45
+ os.environ.clear()
46
+ os.environ.update(original_env)
47
+ get_cache_config.cache_clear()
48
+ create_cache_engine.cache_clear()
49
+
50
+
51
+ @pytest.fixture
52
+ def redis_adapter():
53
+ """Real RedisAdapter instance for testing."""
54
+ from cognee.infrastructure.databases.cache.redis.RedisAdapter import RedisAdapter
55
+
56
+ try:
57
+ yield RedisAdapter(host="localhost", port=6379, log_key="test_usage_logs")
58
+ except Exception as e:
59
+ pytest.skip(f"Redis not available: {e}")
60
+
61
+
62
+ @pytest.fixture
63
+ def test_user():
64
+ """Test user object."""
65
+ return SimpleNamespace(id="test-user-123")
66
+
67
+
68
+ class TestDecoratorBehavior:
69
+ """Test decorator behavior with real components."""
70
+
71
+ @pytest.mark.asyncio
72
+ async def test_decorator_configuration(
73
+ self, usage_logging_disabled, usage_logging_config, redis_adapter
74
+ ):
75
+ """Test decorator skips when disabled and logs when enabled."""
76
+ # Test disabled
77
+ call_count = 0
78
+
79
+ @log_usage(function_name="test_func", log_type="test")
80
+ async def test_func():
81
+ nonlocal call_count
82
+ call_count += 1
83
+ return "result"
84
+
85
+ assert await test_func() == "result"
86
+ assert call_count == 1
87
+
88
+ # Test enabled with cache engine None
89
+ with patch("cognee.shared.usage_logger.get_cache_engine") as mock_get:
90
+ mock_get.return_value = None
91
+ assert await test_func() == "result"
92
+
93
+ @pytest.mark.asyncio
94
+ async def test_decorator_logging(self, usage_logging_config, redis_adapter, test_user):
95
+ """Test decorator logs to Redis with correct structure."""
96
+
97
+ @log_usage(function_name="test_func", log_type="test")
98
+ async def test_func(param1: str, param2: int = 42, user=None):
99
+ await asyncio.sleep(0.01)
100
+ return {"result": f"{param1}_{param2}"}
101
+
102
+ with patch("cognee.shared.usage_logger.get_cache_engine") as mock_get:
103
+ mock_get.return_value = redis_adapter
104
+
105
+ result = await test_func("value1", user=test_user)
106
+ assert result == {"result": "value1_42"}
107
+
108
+ logs = await redis_adapter.get_usage_logs("test-user-123", limit=10)
109
+ log = logs[0]
110
+ assert log["function_name"] == "test_func"
111
+ assert log["type"] == "test"
112
+ assert log["user_id"] == "test-user-123"
113
+ assert log["parameters"]["param1"] == "value1"
114
+ assert log["parameters"]["param2"] == 42
115
+ assert log["success"] is True
116
+ assert all(
117
+ field in log
118
+ for field in [
119
+ "timestamp",
120
+ "result",
121
+ "error",
122
+ "duration_ms",
123
+ "start_time",
124
+ "end_time",
125
+ "metadata",
126
+ ]
127
+ )
128
+ assert "cognee_version" in log["metadata"]
129
+
130
+ @pytest.mark.asyncio
131
+ async def test_multiple_calls(self, usage_logging_config, redis_adapter, test_user):
132
+ """Test multiple consecutive calls are all logged."""
133
+
134
+ @log_usage(function_name="multi_test", log_type="test")
135
+ async def multi_func(call_num: int, user=None):
136
+ return {"call": call_num}
137
+
138
+ with patch("cognee.shared.usage_logger.get_cache_engine") as mock_get:
139
+ mock_get.return_value = redis_adapter
140
+
141
+ for i in range(3):
142
+ await multi_func(i, user=test_user)
143
+
144
+ logs = await redis_adapter.get_usage_logs("test-user-123", limit=10)
145
+ assert len(logs) >= 3
146
+ call_nums = {log["parameters"]["call_num"] for log in logs[:3]}
147
+ assert call_nums == {0, 1, 2}
148
+
149
+
150
+ class TestRealRedisIntegration:
151
+ """Test real Redis integration."""
152
+
153
+ @pytest.mark.asyncio
154
+ async def test_redis_storage_retrieval_and_ttl(
155
+ self, usage_logging_config, redis_adapter, test_user
156
+ ):
157
+ """Test logs are stored, retrieved with correct order/limits, and TTL is set."""
158
+
159
+ @log_usage(function_name="redis_test", log_type="test")
160
+ async def redis_func(data: str, user=None):
161
+ return {"processed": data}
162
+
163
+ @log_usage(function_name="order_test", log_type="test")
164
+ async def order_func(num: int, user=None):
165
+ return {"num": num}
166
+
167
+ with patch("cognee.shared.usage_logger.get_cache_engine") as mock_get:
168
+ mock_get.return_value = redis_adapter
169
+
170
+ # Storage
171
+ await redis_func("test_data", user=test_user)
172
+ logs = await redis_adapter.get_usage_logs("test-user-123", limit=10)
173
+ assert logs[0]["function_name"] == "redis_test"
174
+ assert logs[0]["parameters"]["data"] == "test_data"
175
+
176
+ # Order (most recent first)
177
+ for i in range(3):
178
+ await order_func(i, user=test_user)
179
+ await asyncio.sleep(0.01)
180
+
181
+ logs = await redis_adapter.get_usage_logs("test-user-123", limit=10)
182
+ assert [log["parameters"]["num"] for log in logs[:3]] == [2, 1, 0]
183
+
184
+ # Limit
185
+ assert len(await redis_adapter.get_usage_logs("test-user-123", limit=2)) == 2
186
+
187
+ # TTL
188
+ ttl = await redis_adapter.async_redis.ttl("test_usage_logs:test-user-123")
189
+ assert 0 < ttl <= 604800
190
+
191
+
192
+ class TestEdgeCases:
193
+ """Test edge cases in integration tests."""
194
+
195
+ @pytest.mark.asyncio
196
+ async def test_edge_cases(self, usage_logging_config, redis_adapter, test_user):
197
+ """Test no params, defaults, complex structures, exceptions, None, circular refs."""
198
+
199
+ @log_usage(function_name="no_params", log_type="test")
200
+ async def no_params_func(user=None):
201
+ return "result"
202
+
203
+ @log_usage(function_name="defaults_only", log_type="test")
204
+ async def defaults_only_func(param1: str = "default1", param2: int = 42, user=None):
205
+ return {"param1": param1, "param2": param2}
206
+
207
+ @log_usage(function_name="complex_test", log_type="test")
208
+ async def complex_func(user=None):
209
+ return {
210
+ "nested": {
211
+ "list": [1, 2, 3],
212
+ "uuid": UUID("123e4567-e89b-12d3-a456-426614174000"),
213
+ "datetime": datetime(2024, 1, 15, tzinfo=timezone.utc),
214
+ }
215
+ }
216
+
217
+ @log_usage(function_name="exception_test", log_type="test")
218
+ async def exception_func(user=None):
219
+ raise RuntimeError("Test exception")
220
+
221
+ @log_usage(function_name="none_test", log_type="test")
222
+ async def none_func(user=None):
223
+ return None
224
+
225
+ with patch("cognee.shared.usage_logger.get_cache_engine") as mock_get:
226
+ mock_get.return_value = redis_adapter
227
+
228
+ # No parameters
229
+ await no_params_func(user=test_user)
230
+ logs = await redis_adapter.get_usage_logs("test-user-123", limit=10)
231
+ assert logs[0]["parameters"] == {}
232
+
233
+ # Default parameters
234
+ await defaults_only_func(user=test_user)
235
+ logs = await redis_adapter.get_usage_logs("test-user-123", limit=10)
236
+ assert logs[0]["parameters"]["param1"] == "default1"
237
+ assert logs[0]["parameters"]["param2"] == 42
238
+
239
+ # Complex nested structures
240
+ await complex_func(user=test_user)
241
+ logs = await redis_adapter.get_usage_logs("test-user-123", limit=10)
242
+ assert isinstance(logs[0]["result"]["nested"]["uuid"], str)
243
+ assert isinstance(logs[0]["result"]["nested"]["datetime"], str)
244
+
245
+ # Exception handling
246
+ with pytest.raises(RuntimeError):
247
+ await exception_func(user=test_user)
248
+ logs = await redis_adapter.get_usage_logs("test-user-123", limit=10)
249
+ assert logs[0]["success"] is False
250
+ assert "Test exception" in logs[0]["error"]
251
+
252
+ # None return value
253
+ assert await none_func(user=test_user) is None
254
+ logs = await redis_adapter.get_usage_logs("test-user-123", limit=10)
255
+ assert logs[0]["result"] is None
@@ -0,0 +1,147 @@
1
+ # Translation Task Tests
2
+
3
+ Unit and integration tests for the multilingual content translation feature.
4
+
5
+ ## Test Files
6
+
7
+ - **config_test.py** - Tests for translation configuration
8
+ - Default configuration
9
+ - Provider type validation
10
+ - Confidence threshold bounds
11
+ - Multiple provider API keys
12
+
13
+ - **detect_language_test.py** - Tests for language detection functionality
14
+ - English, Spanish, French, German, Chinese detection
15
+ - Confidence thresholds
16
+ - Edge cases (empty text, short text, mixed languages)
17
+
18
+ - **providers_test.py** - Tests for translation provider implementations
19
+ - LLM provider basic translation
20
+ - Auto-detection of source language
21
+ - Batch translation
22
+ - Special characters and formatting preservation
23
+ - Error handling
24
+
25
+ - **translate_content_test.py** - Tests for the main translate_content task
26
+ - Basic translation workflow
27
+ - Original text preservation
28
+ - Multiple chunks processing
29
+ - Language metadata creation
30
+ - Skip translation for target language
31
+ - Confidence threshold customization
32
+
33
+ ## Running Tests
34
+
35
+ ### Run all translation tests
36
+ ```bash
37
+ uv run pytest cognee/tests/tasks/translation/ -v
38
+ ```
39
+
40
+ ### Run specific test file
41
+ ```bash
42
+ uv run pytest cognee/tests/tasks/translation/detect_language_test.py -v
43
+ ```
44
+
45
+ ### Run tests directly (without pytest)
46
+ ```bash
47
+ uv run python cognee/tests/tasks/translation/config_test.py
48
+ uv run python cognee/tests/tasks/translation/detect_language_test.py
49
+ uv run python cognee/tests/tasks/translation/providers_test.py
50
+ uv run python cognee/tests/tasks/translation/translate_content_test.py
51
+ uv run python cognee/tests/tasks/translation/integration_test.py
52
+ ```
53
+
54
+ ### Run all tests at once
55
+ ```bash
56
+ for f in cognee/tests/tasks/translation/*_test.py; do uv run python "$f"; done
57
+ ```
58
+
59
+ ### Run with coverage
60
+ ```bash
61
+ uv run pytest cognee/tests/tasks/translation/ --cov=cognee.tasks.translation --cov-report=html
62
+ ```
63
+
64
+ ## Prerequisites
65
+
66
+ - LLM API key set in environment: `LLM_API_KEY=your_key`
67
+ - Tests will be skipped if no API key is available
68
+
69
+ **Note:** The translation feature uses the same LLM model configured for other cognee tasks (via `LLM_MODEL` and `LLM_PROVIDER` environment variables). This means any LLM provider supported by cognee (OpenAI, Azure, Anthropic, Ollama, etc.) can be used for translation.
70
+
71
+ ## Usage Example
72
+
73
+ ```python
74
+ import cognee
75
+ from cognee.tasks.translation import translate_text
76
+
77
+ # Configure translation (optional - defaults to LLM provider)
78
+ cognee.config.set_translation_config(
79
+ provider="llm", # Uses configured LLM (default)
80
+ target_language="en", # Target language code
81
+ confidence_threshold=0.7 # Minimum confidence for language detection
82
+ )
83
+
84
+ # Translate text directly
85
+ result = await translate_text(
86
+ text="Bonjour le monde",
87
+ target_language="en"
88
+ )
89
+ print(result.translated_text) # "Hello world"
90
+ ```
91
+
92
+ ### Alternative Translation Providers
93
+
94
+ ```python
95
+ # Use Google Cloud Translate (requires GOOGLE_TRANSLATE_API_KEY)
96
+ cognee.config.set_translation_provider("google")
97
+
98
+ # Use Azure Translator (requires AZURE_TRANSLATOR_KEY and AZURE_TRANSLATOR_REGION)
99
+ cognee.config.set_translation_provider("azure")
100
+ ```
101
+
102
+ ## Test Summary
103
+
104
+ | Test File | Tests | Description |
105
+ |-----------|-------|-------------|
106
+ | config_test.py | 4 | Configuration validation |
107
+ | detect_language_test.py | 10 | Language detection |
108
+ | providers_test.py | 9 | Translation providers |
109
+ | translate_content_test.py | 9 | Content translation task |
110
+ | integration_test.py | 2 | Standalone translation tests |
111
+ | **Total** | **34** | |
112
+
113
+ ## Test Categories
114
+
115
+ ### Configuration (4 tests)
116
+ - ✅ Default configuration values
117
+ - ✅ Provider type literal validation
118
+ - ✅ Confidence threshold bounds
119
+ - ✅ Multiple provider API keys
120
+
121
+ ### Language Detection (10 tests)
122
+ - ✅ Multiple language detection (EN, ES, FR, DE, ZH)
123
+ - ✅ Confidence scoring
124
+ - ✅ Target language matching
125
+ - ✅ Short and empty text handling
126
+ - ✅ Mixed language detection
127
+
128
+ ### Translation Providers (9 tests)
129
+ - ✅ Provider factory function
130
+ - ✅ LLM translation
131
+ - ✅ Batch operations
132
+ - ✅ Auto source language detection
133
+ - ✅ Long text handling
134
+ - ✅ Special characters preservation
135
+ - ✅ Error handling
136
+
137
+ ### Content Translation (9 tests)
138
+ - ✅ DocumentChunk processing
139
+ - ✅ Metadata creation (LanguageMetadata, TranslatedContent)
140
+ - ✅ Original text preservation
141
+ - ✅ Multiple chunk handling
142
+ - ✅ Empty text/list handling
143
+ - ✅ Confidence threshold customization
144
+
145
+ ### Integration (2 tests)
146
+ - ✅ Direct translate_text function
147
+ - ✅ Language detection functionality
@@ -0,0 +1 @@
1
+ """Translation task tests"""
@@ -0,0 +1,93 @@
1
+ """
2
+ Unit tests for translation configuration
3
+ """
4
+
5
+ from typing import get_args
6
+
7
+ from pydantic import ValidationError
8
+
9
+ from cognee.tasks.translation.config import (
10
+ get_translation_config,
11
+ TranslationConfig,
12
+ TranslationProviderType,
13
+ )
14
+
15
+
16
+ def test_default_translation_config():
17
+ """Test default translation configuration"""
18
+ config = get_translation_config()
19
+
20
+ assert isinstance(config, TranslationConfig), "Config should be TranslationConfig instance"
21
+ assert config.translation_provider in [
22
+ "llm",
23
+ "google",
24
+ "azure",
25
+ ], f"Invalid provider: {config.translation_provider}"
26
+ assert 0.0 <= config.confidence_threshold <= 1.0, (
27
+ f"Confidence threshold {config.confidence_threshold} out of bounds [0.0, 1.0]"
28
+ )
29
+
30
+
31
+ def test_translation_provider_type_literal():
32
+ """Test TranslationProviderType Literal type values"""
33
+ # Get the allowed values from the Literal type
34
+ allowed_values = get_args(TranslationProviderType)
35
+
36
+ assert "llm" in allowed_values, "llm should be an allowed provider"
37
+ assert "google" in allowed_values, "google should be an allowed provider"
38
+ assert "azure" in allowed_values, "azure should be an allowed provider"
39
+ assert len(allowed_values) == 3, f"Expected 3 providers, got {len(allowed_values)}"
40
+
41
+
42
+ def test_confidence_threshold_bounds():
43
+ """Test confidence threshold validation"""
44
+ config = TranslationConfig(translation_provider="llm", confidence_threshold=0.9)
45
+
46
+ assert 0.0 <= config.confidence_threshold <= 1.0, (
47
+ f"Confidence threshold {config.confidence_threshold} out of bounds [0.0, 1.0]"
48
+ )
49
+
50
+
51
+ def test_confidence_threshold_validation():
52
+ """Test that invalid confidence thresholds are rejected or clamped"""
53
+ # Test boundary values - these should work
54
+ config_min = TranslationConfig(translation_provider="llm", confidence_threshold=0.0)
55
+ assert config_min.confidence_threshold == 0.0, "Minimum bound (0.0) should be valid"
56
+
57
+ config_max = TranslationConfig(translation_provider="llm", confidence_threshold=1.0)
58
+ assert config_max.confidence_threshold == 1.0, "Maximum bound (1.0) should be valid"
59
+
60
+ # Test invalid values - these should either raise ValidationError or be clamped
61
+ try:
62
+ config_invalid_low = TranslationConfig(
63
+ translation_provider="llm", confidence_threshold=-0.1
64
+ )
65
+ # If no error, verify it was clamped to valid range
66
+ assert 0.0 <= config_invalid_low.confidence_threshold <= 1.0, (
67
+ f"Invalid low value should be clamped, got {config_invalid_low.confidence_threshold}"
68
+ )
69
+ except ValidationError:
70
+ pass # Expected validation error
71
+
72
+ try:
73
+ config_invalid_high = TranslationConfig(
74
+ translation_provider="llm", confidence_threshold=1.5
75
+ )
76
+ # If no error, verify it was clamped to valid range
77
+ assert 0.0 <= config_invalid_high.confidence_threshold <= 1.0, (
78
+ f"Invalid high value should be clamped, got {config_invalid_high.confidence_threshold}"
79
+ )
80
+ except ValidationError:
81
+ pass # Expected validation error
82
+
83
+
84
+ def test_multiple_provider_keys():
85
+ """Test configuration with multiple provider API keys"""
86
+ config = TranslationConfig(
87
+ translation_provider="llm",
88
+ google_translate_api_key="google_key",
89
+ azure_translator_key="azure_key",
90
+ )
91
+
92
+ assert config.google_translate_api_key == "google_key", "Google API key not set correctly"
93
+ assert config.azure_translator_key == "azure_key", "Azure API key not set correctly"
@@ -0,0 +1,118 @@
1
+ """
2
+ Unit tests for language detection functionality
3
+ """
4
+
5
+ import pytest
6
+ from cognee.tasks.translation.detect_language import (
7
+ detect_language_async,
8
+ LanguageDetectionResult,
9
+ )
10
+ from cognee.tasks.translation.exceptions import LanguageDetectionError
11
+
12
+
13
+ @pytest.mark.asyncio
14
+ async def test_detect_english():
15
+ """Test detection of English text"""
16
+ result = await detect_language_async("Hello world, this is a test.", target_language="en")
17
+
18
+ assert result.language_code == "en"
19
+ assert result.requires_translation is False
20
+ assert result.confidence > 0.9
21
+ assert result.language_name == "English"
22
+
23
+
24
+ @pytest.mark.asyncio
25
+ async def test_detect_spanish():
26
+ """Test detection of Spanish text"""
27
+ result = await detect_language_async("Hola mundo, esta es una prueba.", target_language="en")
28
+
29
+ assert result.language_code == "es"
30
+ assert result.requires_translation is True
31
+ assert result.confidence > 0.9
32
+ assert result.language_name == "Spanish"
33
+
34
+
35
+ @pytest.mark.asyncio
36
+ async def test_detect_french():
37
+ """Test detection of French text"""
38
+ result = await detect_language_async(
39
+ "Bonjour le monde, ceci est un test.", target_language="en"
40
+ )
41
+
42
+ assert result.language_code == "fr"
43
+ assert result.requires_translation is True
44
+ assert result.confidence > 0.9
45
+ assert result.language_name == "French"
46
+
47
+
48
+ @pytest.mark.asyncio
49
+ async def test_detect_german():
50
+ """Test detection of German text"""
51
+ result = await detect_language_async("Hallo Welt, das ist ein Test.", target_language="en")
52
+
53
+ assert result.language_code == "de"
54
+ assert result.requires_translation is True
55
+ assert result.confidence > 0.9
56
+
57
+
58
+ @pytest.mark.asyncio
59
+ async def test_detect_chinese():
60
+ """Test detection of Chinese text"""
61
+ result = await detect_language_async("你好世界,这是一个测试。", target_language="en")
62
+
63
+ assert result.language_code.startswith("zh"), f"Expected Chinese, got {result.language_code}"
64
+ assert result.requires_translation is True
65
+ assert result.confidence > 0.9
66
+
67
+
68
+ @pytest.mark.asyncio
69
+ async def test_already_target_language():
70
+ """Test when text is already in target language"""
71
+ result = await detect_language_async("This text is already in English.", target_language="en")
72
+
73
+ assert result.requires_translation is False
74
+
75
+
76
+ @pytest.mark.asyncio
77
+ async def test_short_text():
78
+ """Test detection with very short text"""
79
+ result = await detect_language_async("Hi", target_language="es")
80
+
81
+ # Short text may return 'unknown' if langdetect can't reliably detect
82
+ assert result.language_code in ["en", "unknown"]
83
+ assert result.character_count == 2
84
+
85
+
86
+ @pytest.mark.asyncio
87
+ async def test_empty_text():
88
+ """Test detection with empty text - returns unknown by default"""
89
+ result = await detect_language_async("", target_language="en")
90
+
91
+ # With skip_detection_for_short_text=True (default), returns unknown
92
+ assert result.language_code == "unknown"
93
+ assert result.language_name == "Unknown"
94
+ assert result.confidence == 0.0
95
+ assert result.requires_translation is False
96
+ assert result.character_count == 0
97
+
98
+
99
+ @pytest.mark.asyncio
100
+ async def test_confidence_threshold():
101
+ """Test detection respects confidence threshold"""
102
+ result = await detect_language_async(
103
+ "Hello world", target_language="es", confidence_threshold=0.5
104
+ )
105
+
106
+ assert result.confidence >= 0.5
107
+
108
+
109
+ @pytest.mark.asyncio
110
+ async def test_mixed_language_text():
111
+ """Test detection with mixed language text (predominantly one language)"""
112
+ # Predominantly Spanish with English word
113
+ result = await detect_language_async(
114
+ "La inteligencia artificial es muy importante en technology moderna.", target_language="en"
115
+ )
116
+
117
+ assert result.language_code == "es" # Should detect as Spanish
118
+ assert result.requires_translation is True