cognee 0.5.1__py3-none-any.whl → 0.5.1.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/api/v1/add/add.py +2 -1
- cognee/api/v1/datasets/routers/get_datasets_router.py +1 -0
- cognee/api/v1/memify/routers/get_memify_router.py +1 -0
- cognee/api/v1/search/search.py +0 -4
- cognee/infrastructure/databases/relational/config.py +16 -1
- cognee/infrastructure/databases/relational/create_relational_engine.py +13 -3
- cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py +24 -2
- cognee/infrastructure/databases/vector/create_vector_engine.py +9 -2
- cognee/infrastructure/llm/LLMGateway.py +0 -13
- cognee/infrastructure/llm/structured_output_framework/litellm_instructor/llm/anthropic/adapter.py +17 -12
- cognee/infrastructure/llm/structured_output_framework/litellm_instructor/llm/gemini/adapter.py +31 -25
- cognee/infrastructure/llm/structured_output_framework/litellm_instructor/llm/generic_llm_api/adapter.py +132 -7
- cognee/infrastructure/llm/structured_output_framework/litellm_instructor/llm/get_llm_client.py +5 -5
- cognee/infrastructure/llm/structured_output_framework/litellm_instructor/llm/llm_interface.py +2 -6
- cognee/infrastructure/llm/structured_output_framework/litellm_instructor/llm/mistral/adapter.py +58 -13
- cognee/infrastructure/llm/structured_output_framework/litellm_instructor/llm/ollama/adapter.py +0 -1
- cognee/infrastructure/llm/structured_output_framework/litellm_instructor/llm/openai/adapter.py +25 -131
- cognee/infrastructure/llm/structured_output_framework/litellm_instructor/llm/types.py +10 -0
- cognee/modules/data/models/Data.py +2 -1
- cognee/modules/retrieval/triplet_retriever.py +1 -1
- cognee/modules/retrieval/utils/brute_force_triplet_search.py +0 -18
- cognee/modules/search/methods/search.py +18 -25
- cognee/tasks/ingestion/data_item.py +8 -0
- cognee/tasks/ingestion/ingest_data.py +12 -1
- cognee/tasks/ingestion/save_data_item_to_storage.py +5 -0
- cognee/tests/integration/retrieval/test_chunks_retriever.py +252 -0
- cognee/tests/integration/retrieval/test_graph_completion_retriever.py +268 -0
- cognee/tests/integration/retrieval/test_graph_completion_retriever_context_extension.py +226 -0
- cognee/tests/integration/retrieval/test_graph_completion_retriever_cot.py +218 -0
- cognee/tests/integration/retrieval/test_rag_completion_retriever.py +254 -0
- cognee/tests/{unit/modules/retrieval/structured_output_test.py → integration/retrieval/test_structured_output.py} +87 -77
- cognee/tests/integration/retrieval/test_summaries_retriever.py +184 -0
- cognee/tests/integration/retrieval/test_temporal_retriever.py +306 -0
- cognee/tests/integration/retrieval/test_triplet_retriever.py +35 -0
- cognee/tests/test_custom_data_label.py +68 -0
- cognee/tests/test_search_db.py +334 -181
- cognee/tests/unit/eval_framework/benchmark_adapters_test.py +25 -0
- cognee/tests/unit/eval_framework/corpus_builder_test.py +33 -4
- cognee/tests/unit/infrastructure/databases/relational/test_RelationalConfig.py +69 -0
- cognee/tests/unit/modules/retrieval/chunks_retriever_test.py +181 -199
- cognee/tests/unit/modules/retrieval/conversation_history_test.py +338 -0
- cognee/tests/unit/modules/retrieval/graph_completion_retriever_context_extension_test.py +454 -162
- cognee/tests/unit/modules/retrieval/graph_completion_retriever_cot_test.py +674 -156
- cognee/tests/unit/modules/retrieval/graph_completion_retriever_test.py +625 -200
- cognee/tests/unit/modules/retrieval/rag_completion_retriever_test.py +319 -203
- cognee/tests/unit/modules/retrieval/summaries_retriever_test.py +189 -155
- cognee/tests/unit/modules/retrieval/temporal_retriever_test.py +539 -58
- cognee/tests/unit/modules/retrieval/test_brute_force_triplet_search.py +218 -9
- cognee/tests/unit/modules/retrieval/test_completion.py +343 -0
- cognee/tests/unit/modules/retrieval/test_graph_summary_completion_retriever.py +157 -0
- cognee/tests/unit/modules/retrieval/test_user_qa_feedback.py +312 -0
- cognee/tests/unit/modules/retrieval/triplet_retriever_test.py +246 -0
- {cognee-0.5.1.dist-info → cognee-0.5.1.dev0.dist-info}/METADATA +1 -1
- {cognee-0.5.1.dist-info → cognee-0.5.1.dev0.dist-info}/RECORD +58 -45
- cognee/tests/unit/modules/search/test_search.py +0 -100
- {cognee-0.5.1.dist-info → cognee-0.5.1.dev0.dist-info}/WHEEL +0 -0
- {cognee-0.5.1.dist-info → cognee-0.5.1.dev0.dist-info}/entry_points.txt +0 -0
- {cognee-0.5.1.dist-info → cognee-0.5.1.dev0.dist-info}/licenses/LICENSE +0 -0
- {cognee-0.5.1.dist-info → cognee-0.5.1.dev0.dist-info}/licenses/NOTICE.md +0 -0
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import pytest
|
|
3
|
+
import pathlib
|
|
4
|
+
import pytest_asyncio
|
|
5
|
+
from typing import List
|
|
6
|
+
import cognee
|
|
7
|
+
|
|
8
|
+
from cognee.low_level import setup
|
|
9
|
+
from cognee.tasks.storage import add_data_points
|
|
10
|
+
from cognee.infrastructure.databases.vector import get_vector_engine
|
|
11
|
+
from cognee.modules.chunking.models import DocumentChunk
|
|
12
|
+
from cognee.modules.data.processing.document_types import TextDocument
|
|
13
|
+
from cognee.modules.retrieval.exceptions.exceptions import NoDataError
|
|
14
|
+
from cognee.modules.retrieval.chunks_retriever import ChunksRetriever
|
|
15
|
+
from cognee.infrastructure.engine import DataPoint
|
|
16
|
+
from cognee.modules.data.processing.document_types import Document
|
|
17
|
+
from cognee.modules.engine.models import Entity
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class DocumentChunkWithEntities(DataPoint):
|
|
21
|
+
text: str
|
|
22
|
+
chunk_size: int
|
|
23
|
+
chunk_index: int
|
|
24
|
+
cut_type: str
|
|
25
|
+
is_part_of: Document
|
|
26
|
+
contains: List[Entity] = None
|
|
27
|
+
|
|
28
|
+
metadata: dict = {"index_fields": ["text"]}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@pytest_asyncio.fixture
|
|
32
|
+
async def setup_test_environment_with_chunks_simple():
|
|
33
|
+
"""Set up a clean test environment with simple chunks."""
|
|
34
|
+
base_dir = pathlib.Path(__file__).parent.parent.parent.parent
|
|
35
|
+
system_directory_path = str(base_dir / ".cognee_system/test_chunks_retriever_context_simple")
|
|
36
|
+
data_directory_path = str(base_dir / ".data_storage/test_chunks_retriever_context_simple")
|
|
37
|
+
|
|
38
|
+
cognee.config.system_root_directory(system_directory_path)
|
|
39
|
+
cognee.config.data_root_directory(data_directory_path)
|
|
40
|
+
|
|
41
|
+
await cognee.prune.prune_data()
|
|
42
|
+
await cognee.prune.prune_system(metadata=True)
|
|
43
|
+
await setup()
|
|
44
|
+
|
|
45
|
+
document = TextDocument(
|
|
46
|
+
name="Steve Rodger's career",
|
|
47
|
+
raw_data_location="somewhere",
|
|
48
|
+
external_metadata="",
|
|
49
|
+
mime_type="text/plain",
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
chunk1 = DocumentChunk(
|
|
53
|
+
text="Steve Rodger",
|
|
54
|
+
chunk_size=2,
|
|
55
|
+
chunk_index=0,
|
|
56
|
+
cut_type="sentence_end",
|
|
57
|
+
is_part_of=document,
|
|
58
|
+
contains=[],
|
|
59
|
+
)
|
|
60
|
+
chunk2 = DocumentChunk(
|
|
61
|
+
text="Mike Broski",
|
|
62
|
+
chunk_size=2,
|
|
63
|
+
chunk_index=1,
|
|
64
|
+
cut_type="sentence_end",
|
|
65
|
+
is_part_of=document,
|
|
66
|
+
contains=[],
|
|
67
|
+
)
|
|
68
|
+
chunk3 = DocumentChunk(
|
|
69
|
+
text="Christina Mayer",
|
|
70
|
+
chunk_size=2,
|
|
71
|
+
chunk_index=2,
|
|
72
|
+
cut_type="sentence_end",
|
|
73
|
+
is_part_of=document,
|
|
74
|
+
contains=[],
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
entities = [chunk1, chunk2, chunk3]
|
|
78
|
+
|
|
79
|
+
await add_data_points(entities)
|
|
80
|
+
|
|
81
|
+
yield
|
|
82
|
+
|
|
83
|
+
try:
|
|
84
|
+
await cognee.prune.prune_data()
|
|
85
|
+
await cognee.prune.prune_system(metadata=True)
|
|
86
|
+
except Exception:
|
|
87
|
+
pass
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
@pytest_asyncio.fixture
|
|
91
|
+
async def setup_test_environment_with_chunks_complex():
|
|
92
|
+
"""Set up a clean test environment with complex chunks."""
|
|
93
|
+
base_dir = pathlib.Path(__file__).parent.parent.parent.parent
|
|
94
|
+
system_directory_path = str(base_dir / ".cognee_system/test_chunks_retriever_context_complex")
|
|
95
|
+
data_directory_path = str(base_dir / ".data_storage/test_chunks_retriever_context_complex")
|
|
96
|
+
|
|
97
|
+
cognee.config.system_root_directory(system_directory_path)
|
|
98
|
+
cognee.config.data_root_directory(data_directory_path)
|
|
99
|
+
|
|
100
|
+
await cognee.prune.prune_data()
|
|
101
|
+
await cognee.prune.prune_system(metadata=True)
|
|
102
|
+
await setup()
|
|
103
|
+
|
|
104
|
+
document1 = TextDocument(
|
|
105
|
+
name="Employee List",
|
|
106
|
+
raw_data_location="somewhere",
|
|
107
|
+
external_metadata="",
|
|
108
|
+
mime_type="text/plain",
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
document2 = TextDocument(
|
|
112
|
+
name="Car List",
|
|
113
|
+
raw_data_location="somewhere",
|
|
114
|
+
external_metadata="",
|
|
115
|
+
mime_type="text/plain",
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
chunk1 = DocumentChunk(
|
|
119
|
+
text="Steve Rodger",
|
|
120
|
+
chunk_size=2,
|
|
121
|
+
chunk_index=0,
|
|
122
|
+
cut_type="sentence_end",
|
|
123
|
+
is_part_of=document1,
|
|
124
|
+
contains=[],
|
|
125
|
+
)
|
|
126
|
+
chunk2 = DocumentChunk(
|
|
127
|
+
text="Mike Broski",
|
|
128
|
+
chunk_size=2,
|
|
129
|
+
chunk_index=1,
|
|
130
|
+
cut_type="sentence_end",
|
|
131
|
+
is_part_of=document1,
|
|
132
|
+
contains=[],
|
|
133
|
+
)
|
|
134
|
+
chunk3 = DocumentChunk(
|
|
135
|
+
text="Christina Mayer",
|
|
136
|
+
chunk_size=2,
|
|
137
|
+
chunk_index=2,
|
|
138
|
+
cut_type="sentence_end",
|
|
139
|
+
is_part_of=document1,
|
|
140
|
+
contains=[],
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
chunk4 = DocumentChunk(
|
|
144
|
+
text="Range Rover",
|
|
145
|
+
chunk_size=2,
|
|
146
|
+
chunk_index=0,
|
|
147
|
+
cut_type="sentence_end",
|
|
148
|
+
is_part_of=document2,
|
|
149
|
+
contains=[],
|
|
150
|
+
)
|
|
151
|
+
chunk5 = DocumentChunk(
|
|
152
|
+
text="Hyundai",
|
|
153
|
+
chunk_size=2,
|
|
154
|
+
chunk_index=1,
|
|
155
|
+
cut_type="sentence_end",
|
|
156
|
+
is_part_of=document2,
|
|
157
|
+
contains=[],
|
|
158
|
+
)
|
|
159
|
+
chunk6 = DocumentChunk(
|
|
160
|
+
text="Chrysler",
|
|
161
|
+
chunk_size=2,
|
|
162
|
+
chunk_index=2,
|
|
163
|
+
cut_type="sentence_end",
|
|
164
|
+
is_part_of=document2,
|
|
165
|
+
contains=[],
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
entities = [chunk1, chunk2, chunk3, chunk4, chunk5, chunk6]
|
|
169
|
+
|
|
170
|
+
await add_data_points(entities)
|
|
171
|
+
|
|
172
|
+
yield
|
|
173
|
+
|
|
174
|
+
try:
|
|
175
|
+
await cognee.prune.prune_data()
|
|
176
|
+
await cognee.prune.prune_system(metadata=True)
|
|
177
|
+
except Exception:
|
|
178
|
+
pass
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
@pytest_asyncio.fixture
|
|
182
|
+
async def setup_test_environment_empty():
|
|
183
|
+
"""Set up a clean test environment without chunks."""
|
|
184
|
+
base_dir = pathlib.Path(__file__).parent.parent.parent.parent
|
|
185
|
+
system_directory_path = str(base_dir / ".cognee_system/test_chunks_retriever_context_empty")
|
|
186
|
+
data_directory_path = str(base_dir / ".data_storage/test_chunks_retriever_context_empty")
|
|
187
|
+
|
|
188
|
+
cognee.config.system_root_directory(system_directory_path)
|
|
189
|
+
cognee.config.data_root_directory(data_directory_path)
|
|
190
|
+
|
|
191
|
+
await cognee.prune.prune_data()
|
|
192
|
+
await cognee.prune.prune_system(metadata=True)
|
|
193
|
+
|
|
194
|
+
yield
|
|
195
|
+
|
|
196
|
+
try:
|
|
197
|
+
await cognee.prune.prune_data()
|
|
198
|
+
await cognee.prune.prune_system(metadata=True)
|
|
199
|
+
except Exception:
|
|
200
|
+
pass
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
@pytest.mark.asyncio
|
|
204
|
+
async def test_chunks_retriever_context_multiple_chunks(setup_test_environment_with_chunks_simple):
|
|
205
|
+
"""Integration test: verify ChunksRetriever can retrieve multiple chunks."""
|
|
206
|
+
retriever = ChunksRetriever()
|
|
207
|
+
|
|
208
|
+
context = await retriever.get_context("Steve")
|
|
209
|
+
|
|
210
|
+
assert isinstance(context, list), "Context should be a list"
|
|
211
|
+
assert len(context) > 0, "Context should not be empty"
|
|
212
|
+
assert any(chunk["text"] == "Steve Rodger" for chunk in context), (
|
|
213
|
+
"Failed to get Steve Rodger chunk"
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
@pytest.mark.asyncio
|
|
218
|
+
async def test_chunks_retriever_top_k_limit(setup_test_environment_with_chunks_complex):
|
|
219
|
+
"""Integration test: verify ChunksRetriever respects top_k parameter."""
|
|
220
|
+
retriever = ChunksRetriever(top_k=2)
|
|
221
|
+
|
|
222
|
+
context = await retriever.get_context("Employee")
|
|
223
|
+
|
|
224
|
+
assert isinstance(context, list), "Context should be a list"
|
|
225
|
+
assert len(context) <= 2, "Should respect top_k limit"
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
@pytest.mark.asyncio
|
|
229
|
+
async def test_chunks_retriever_context_complex(setup_test_environment_with_chunks_complex):
|
|
230
|
+
"""Integration test: verify ChunksRetriever can retrieve chunk context (complex)."""
|
|
231
|
+
retriever = ChunksRetriever(top_k=20)
|
|
232
|
+
|
|
233
|
+
context = await retriever.get_context("Christina")
|
|
234
|
+
|
|
235
|
+
assert context[0]["text"] == "Christina Mayer", "Failed to get Christina Mayer"
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
@pytest.mark.asyncio
|
|
239
|
+
async def test_chunks_retriever_context_on_empty_graph(setup_test_environment_empty):
|
|
240
|
+
"""Integration test: verify ChunksRetriever handles empty graph correctly."""
|
|
241
|
+
retriever = ChunksRetriever()
|
|
242
|
+
|
|
243
|
+
with pytest.raises(NoDataError):
|
|
244
|
+
await retriever.get_context("Christina Mayer")
|
|
245
|
+
|
|
246
|
+
vector_engine = get_vector_engine()
|
|
247
|
+
await vector_engine.create_collection(
|
|
248
|
+
"DocumentChunk_text", payload_schema=DocumentChunkWithEntities
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
context = await retriever.get_context("Christina Mayer")
|
|
252
|
+
assert len(context) == 0, "Found chunks when none should exist"
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import pytest
|
|
3
|
+
import pathlib
|
|
4
|
+
import pytest_asyncio
|
|
5
|
+
from typing import Optional, Union
|
|
6
|
+
import cognee
|
|
7
|
+
|
|
8
|
+
from cognee.low_level import setup, DataPoint
|
|
9
|
+
from cognee.modules.graph.utils import resolve_edges_to_text
|
|
10
|
+
from cognee.tasks.storage import add_data_points
|
|
11
|
+
from cognee.modules.retrieval.graph_completion_retriever import GraphCompletionRetriever
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@pytest_asyncio.fixture
|
|
15
|
+
async def setup_test_environment_simple():
|
|
16
|
+
"""Set up a clean test environment with simple graph data."""
|
|
17
|
+
base_dir = pathlib.Path(__file__).parent.parent.parent.parent
|
|
18
|
+
system_directory_path = str(base_dir / ".cognee_system/test_graph_completion_context_simple")
|
|
19
|
+
data_directory_path = str(base_dir / ".data_storage/test_graph_completion_context_simple")
|
|
20
|
+
|
|
21
|
+
cognee.config.system_root_directory(system_directory_path)
|
|
22
|
+
cognee.config.data_root_directory(data_directory_path)
|
|
23
|
+
|
|
24
|
+
await cognee.prune.prune_data()
|
|
25
|
+
await cognee.prune.prune_system(metadata=True)
|
|
26
|
+
await setup()
|
|
27
|
+
|
|
28
|
+
class Company(DataPoint):
|
|
29
|
+
name: str
|
|
30
|
+
description: str
|
|
31
|
+
|
|
32
|
+
class Person(DataPoint):
|
|
33
|
+
name: str
|
|
34
|
+
description: str
|
|
35
|
+
works_for: Company
|
|
36
|
+
|
|
37
|
+
company1 = Company(name="Figma", description="Figma is a company")
|
|
38
|
+
company2 = Company(name="Canva", description="Canvas is a company")
|
|
39
|
+
person1 = Person(
|
|
40
|
+
name="Steve Rodger",
|
|
41
|
+
description="This is description about Steve Rodger",
|
|
42
|
+
works_for=company1,
|
|
43
|
+
)
|
|
44
|
+
person2 = Person(
|
|
45
|
+
name="Ike Loma", description="This is description about Ike Loma", works_for=company1
|
|
46
|
+
)
|
|
47
|
+
person3 = Person(
|
|
48
|
+
name="Jason Statham",
|
|
49
|
+
description="This is description about Jason Statham",
|
|
50
|
+
works_for=company1,
|
|
51
|
+
)
|
|
52
|
+
person4 = Person(
|
|
53
|
+
name="Mike Broski",
|
|
54
|
+
description="This is description about Mike Broski",
|
|
55
|
+
works_for=company2,
|
|
56
|
+
)
|
|
57
|
+
person5 = Person(
|
|
58
|
+
name="Christina Mayer",
|
|
59
|
+
description="This is description about Christina Mayer",
|
|
60
|
+
works_for=company2,
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
entities = [company1, company2, person1, person2, person3, person4, person5]
|
|
64
|
+
|
|
65
|
+
await add_data_points(entities)
|
|
66
|
+
|
|
67
|
+
yield
|
|
68
|
+
|
|
69
|
+
try:
|
|
70
|
+
await cognee.prune.prune_data()
|
|
71
|
+
await cognee.prune.prune_system(metadata=True)
|
|
72
|
+
except Exception:
|
|
73
|
+
pass
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
@pytest_asyncio.fixture
|
|
77
|
+
async def setup_test_environment_complex():
|
|
78
|
+
"""Set up a clean test environment with complex graph data."""
|
|
79
|
+
base_dir = pathlib.Path(__file__).parent.parent.parent.parent
|
|
80
|
+
system_directory_path = str(base_dir / ".cognee_system/test_graph_completion_context_complex")
|
|
81
|
+
data_directory_path = str(base_dir / ".data_storage/test_graph_completion_context_complex")
|
|
82
|
+
|
|
83
|
+
cognee.config.system_root_directory(system_directory_path)
|
|
84
|
+
cognee.config.data_root_directory(data_directory_path)
|
|
85
|
+
|
|
86
|
+
await cognee.prune.prune_data()
|
|
87
|
+
await cognee.prune.prune_system(metadata=True)
|
|
88
|
+
await setup()
|
|
89
|
+
|
|
90
|
+
class Company(DataPoint):
|
|
91
|
+
name: str
|
|
92
|
+
metadata: dict = {"index_fields": ["name"]}
|
|
93
|
+
|
|
94
|
+
class Car(DataPoint):
|
|
95
|
+
brand: str
|
|
96
|
+
model: str
|
|
97
|
+
year: int
|
|
98
|
+
|
|
99
|
+
class Location(DataPoint):
|
|
100
|
+
country: str
|
|
101
|
+
city: str
|
|
102
|
+
|
|
103
|
+
class Home(DataPoint):
|
|
104
|
+
location: Location
|
|
105
|
+
rooms: int
|
|
106
|
+
sqm: int
|
|
107
|
+
|
|
108
|
+
class Person(DataPoint):
|
|
109
|
+
name: str
|
|
110
|
+
works_for: Company
|
|
111
|
+
owns: Optional[list[Union[Car, Home]]] = None
|
|
112
|
+
|
|
113
|
+
company1 = Company(name="Figma")
|
|
114
|
+
company2 = Company(name="Canva")
|
|
115
|
+
|
|
116
|
+
person1 = Person(name="Mike Rodger", works_for=company1)
|
|
117
|
+
person1.owns = [Car(brand="Toyota", model="Camry", year=2020)]
|
|
118
|
+
|
|
119
|
+
person2 = Person(name="Ike Loma", works_for=company1)
|
|
120
|
+
person2.owns = [
|
|
121
|
+
Car(brand="Tesla", model="Model S", year=2021),
|
|
122
|
+
Home(location=Location(country="USA", city="New York"), sqm=80, rooms=4),
|
|
123
|
+
]
|
|
124
|
+
|
|
125
|
+
person3 = Person(name="Jason Statham", works_for=company1)
|
|
126
|
+
|
|
127
|
+
person4 = Person(name="Mike Broski", works_for=company2)
|
|
128
|
+
person4.owns = [Car(brand="Ford", model="Mustang", year=1978)]
|
|
129
|
+
|
|
130
|
+
person5 = Person(name="Christina Mayer", works_for=company2)
|
|
131
|
+
person5.owns = [Car(brand="Honda", model="Civic", year=2023)]
|
|
132
|
+
|
|
133
|
+
entities = [company1, company2, person1, person2, person3, person4, person5]
|
|
134
|
+
|
|
135
|
+
await add_data_points(entities)
|
|
136
|
+
|
|
137
|
+
yield
|
|
138
|
+
|
|
139
|
+
try:
|
|
140
|
+
await cognee.prune.prune_data()
|
|
141
|
+
await cognee.prune.prune_system(metadata=True)
|
|
142
|
+
except Exception:
|
|
143
|
+
pass
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
@pytest_asyncio.fixture
|
|
147
|
+
async def setup_test_environment_empty():
|
|
148
|
+
"""Set up a clean test environment without graph data."""
|
|
149
|
+
base_dir = pathlib.Path(__file__).parent.parent.parent.parent
|
|
150
|
+
system_directory_path = str(
|
|
151
|
+
base_dir / ".cognee_system/test_get_graph_completion_context_on_empty_graph"
|
|
152
|
+
)
|
|
153
|
+
data_directory_path = str(
|
|
154
|
+
base_dir / ".data_storage/test_get_graph_completion_context_on_empty_graph"
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
cognee.config.system_root_directory(system_directory_path)
|
|
158
|
+
cognee.config.data_root_directory(data_directory_path)
|
|
159
|
+
|
|
160
|
+
await cognee.prune.prune_data()
|
|
161
|
+
await cognee.prune.prune_system(metadata=True)
|
|
162
|
+
await setup()
|
|
163
|
+
|
|
164
|
+
yield
|
|
165
|
+
|
|
166
|
+
try:
|
|
167
|
+
await cognee.prune.prune_data()
|
|
168
|
+
await cognee.prune.prune_system(metadata=True)
|
|
169
|
+
except Exception:
|
|
170
|
+
pass
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
@pytest.mark.asyncio
|
|
174
|
+
async def test_graph_completion_context_simple(setup_test_environment_simple):
|
|
175
|
+
"""Integration test: verify GraphCompletionRetriever can retrieve context (simple)."""
|
|
176
|
+
retriever = GraphCompletionRetriever()
|
|
177
|
+
|
|
178
|
+
context = await resolve_edges_to_text(await retriever.get_context("Who works at Canva?"))
|
|
179
|
+
|
|
180
|
+
# Ensure the top-level sections are present
|
|
181
|
+
assert "Nodes:" in context, "Missing 'Nodes:' section in context"
|
|
182
|
+
assert "Connections:" in context, "Missing 'Connections:' section in context"
|
|
183
|
+
|
|
184
|
+
# --- Nodes headers ---
|
|
185
|
+
assert "Node: Steve Rodger" in context, "Missing node header for Steve Rodger"
|
|
186
|
+
assert "Node: Figma" in context, "Missing node header for Figma"
|
|
187
|
+
assert "Node: Ike Loma" in context, "Missing node header for Ike Loma"
|
|
188
|
+
assert "Node: Jason Statham" in context, "Missing node header for Jason Statham"
|
|
189
|
+
assert "Node: Mike Broski" in context, "Missing node header for Mike Broski"
|
|
190
|
+
assert "Node: Canva" in context, "Missing node header for Canva"
|
|
191
|
+
assert "Node: Christina Mayer" in context, "Missing node header for Christina Mayer"
|
|
192
|
+
|
|
193
|
+
# --- Node contents ---
|
|
194
|
+
assert (
|
|
195
|
+
"__node_content_start__\nThis is description about Steve Rodger\n__node_content_end__"
|
|
196
|
+
in context
|
|
197
|
+
), "Description block for Steve Rodger altered"
|
|
198
|
+
assert "__node_content_start__\nFigma is a company\n__node_content_end__" in context, (
|
|
199
|
+
"Description block for Figma altered"
|
|
200
|
+
)
|
|
201
|
+
assert (
|
|
202
|
+
"__node_content_start__\nThis is description about Ike Loma\n__node_content_end__"
|
|
203
|
+
in context
|
|
204
|
+
), "Description block for Ike Loma altered"
|
|
205
|
+
assert (
|
|
206
|
+
"__node_content_start__\nThis is description about Jason Statham\n__node_content_end__"
|
|
207
|
+
in context
|
|
208
|
+
), "Description block for Jason Statham altered"
|
|
209
|
+
assert (
|
|
210
|
+
"__node_content_start__\nThis is description about Mike Broski\n__node_content_end__"
|
|
211
|
+
in context
|
|
212
|
+
), "Description block for Mike Broski altered"
|
|
213
|
+
assert "__node_content_start__\nCanvas is a company\n__node_content_end__" in context, (
|
|
214
|
+
"Description block for Canva altered"
|
|
215
|
+
)
|
|
216
|
+
assert (
|
|
217
|
+
"__node_content_start__\nThis is description about Christina Mayer\n__node_content_end__"
|
|
218
|
+
in context
|
|
219
|
+
), "Description block for Christina Mayer altered"
|
|
220
|
+
|
|
221
|
+
# --- Connections ---
|
|
222
|
+
assert "Steve Rodger --[works_for]--> Figma" in context, (
|
|
223
|
+
"Connection Steve Rodger→Figma missing or changed"
|
|
224
|
+
)
|
|
225
|
+
assert "Ike Loma --[works_for]--> Figma" in context, (
|
|
226
|
+
"Connection Ike Loma→Figma missing or changed"
|
|
227
|
+
)
|
|
228
|
+
assert "Jason Statham --[works_for]--> Figma" in context, (
|
|
229
|
+
"Connection Jason Statham→Figma missing or changed"
|
|
230
|
+
)
|
|
231
|
+
assert "Mike Broski --[works_for]--> Canva" in context, (
|
|
232
|
+
"Connection Mike Broski→Canva missing or changed"
|
|
233
|
+
)
|
|
234
|
+
assert "Christina Mayer --[works_for]--> Canva" in context, (
|
|
235
|
+
"Connection Christina Mayer→Canva missing or changed"
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
@pytest.mark.asyncio
|
|
240
|
+
async def test_graph_completion_context_complex(setup_test_environment_complex):
|
|
241
|
+
"""Integration test: verify GraphCompletionRetriever can retrieve context (complex)."""
|
|
242
|
+
retriever = GraphCompletionRetriever(top_k=20)
|
|
243
|
+
|
|
244
|
+
context = await resolve_edges_to_text(await retriever.get_context("Who works at Figma?"))
|
|
245
|
+
|
|
246
|
+
assert "Mike Rodger --[works_for]--> Figma" in context, "Failed to get Mike Rodger"
|
|
247
|
+
assert "Ike Loma --[works_for]--> Figma" in context, "Failed to get Ike Loma"
|
|
248
|
+
assert "Jason Statham --[works_for]--> Figma" in context, "Failed to get Jason Statham"
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
@pytest.mark.asyncio
|
|
252
|
+
async def test_get_graph_completion_context_on_empty_graph(setup_test_environment_empty):
|
|
253
|
+
"""Integration test: verify GraphCompletionRetriever handles empty graph correctly."""
|
|
254
|
+
retriever = GraphCompletionRetriever()
|
|
255
|
+
|
|
256
|
+
context = await retriever.get_context("Who works at Figma?")
|
|
257
|
+
assert context == [], "Context should be empty on an empty graph"
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
@pytest.mark.asyncio
|
|
261
|
+
async def test_graph_completion_get_triplets_empty(setup_test_environment_empty):
|
|
262
|
+
"""Integration test: verify GraphCompletionRetriever get_triplets handles empty graph."""
|
|
263
|
+
retriever = GraphCompletionRetriever()
|
|
264
|
+
|
|
265
|
+
triplets = await retriever.get_triplets("Who works at Figma?")
|
|
266
|
+
|
|
267
|
+
assert isinstance(triplets, list), "Triplets should be a list"
|
|
268
|
+
assert len(triplets) == 0, "Should return empty list on empty graph"
|