cognee 1.2.2.dev2__py3-none-any.whl → 1.2.2.dev3__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/memify_pipelines/persist_agent_trace_feedbacks_in_knowledge_graph.py +1 -0
- cognee/memify_pipelines/persist_sessions_in_knowledge_graph.py +2 -1
- cognee/modules/migration/import_source.py +0 -10
- cognee/modules/migration/loader.py +6 -8
- cognee/modules/migration/snapshot.py +8 -42
- cognee/tasks/memify/cognify_session.py +13 -3
- cognee/tests/unit/memify_pipelines/test_persist_agent_trace_feedbacks_pipeline.py +1 -0
- cognee/tests/unit/migration/test_import_source.py +1 -43
- cognee/tests/unit/migration/test_snapshot.py +0 -53
- cognee/tests/unit/modules/memify_tasks/test_cognify_session.py +33 -4
- {cognee-1.2.2.dev2.dist-info → cognee-1.2.2.dev3.dist-info}/METADATA +1 -1
- {cognee-1.2.2.dev2.dist-info → cognee-1.2.2.dev3.dist-info}/RECORD +16 -18
- cognee/tests/test_cogx_roundtrip.py +0 -174
- cognee/tests/unit/migration/test_provenance_ctx.py +0 -75
- {cognee-1.2.2.dev2.dist-info → cognee-1.2.2.dev3.dist-info}/WHEEL +0 -0
- {cognee-1.2.2.dev2.dist-info → cognee-1.2.2.dev3.dist-info}/entry_points.txt +0 -0
- {cognee-1.2.2.dev2.dist-info → cognee-1.2.2.dev3.dist-info}/licenses/LICENSE +0 -0
- {cognee-1.2.2.dev2.dist-info → cognee-1.2.2.dev3.dist-info}/licenses/NOTICE.md +0 -0
|
@@ -52,13 +52,14 @@ async def persist_sessions_in_knowledge_graph_pipeline(
|
|
|
52
52
|
extraction_tasks = [Task(extract_user_sessions, session_ids=session_ids)]
|
|
53
53
|
|
|
54
54
|
enrichment_tasks = [
|
|
55
|
-
Task(cognify_session, dataset_id=dataset_to_write[0].id),
|
|
55
|
+
Task(cognify_session, dataset_id=dataset_to_write[0].id, user=user),
|
|
56
56
|
]
|
|
57
57
|
|
|
58
58
|
result = await memify(
|
|
59
59
|
extraction_tasks=extraction_tasks,
|
|
60
60
|
enrichment_tasks=enrichment_tasks,
|
|
61
61
|
dataset=dataset_to_write[0].id,
|
|
62
|
+
user=user,
|
|
62
63
|
data=[{}],
|
|
63
64
|
run_in_background=run_in_background,
|
|
64
65
|
)
|
|
@@ -77,16 +77,6 @@ async def import_memory_source(
|
|
|
77
77
|
external_id, node ids from entity names) make re-running an interrupted
|
|
78
78
|
or repeated import safe.
|
|
79
79
|
"""
|
|
80
|
-
from cognee.modules.migrations.startup import run_migrations_and_block
|
|
81
|
-
|
|
82
|
-
# Imports are writes, so they take the same migration gate as
|
|
83
|
-
# remember()/cognify() (the remember() MemorySource dispatch happens
|
|
84
|
-
# before its own gate). This also records the data-migration revision —
|
|
85
|
-
# stamping a fresh store at head — BEFORE the imported rows arrive;
|
|
86
|
-
# without it the populated store has no recorded revision and the first
|
|
87
|
-
# migration-aware startup replays the entire data chain over it.
|
|
88
|
-
await run_migrations_and_block(dataset_name, user)
|
|
89
|
-
|
|
90
80
|
node_set = node_set or [f"import:{source.source_system}"]
|
|
91
81
|
|
|
92
82
|
if source.mode == "preserve" and getattr(source, "replayable", False):
|
|
@@ -11,7 +11,6 @@ Two targets, selected by the source's import mode:
|
|
|
11
11
|
the source (``valid_at``/``invalid_at``) is preserved as edge properties.
|
|
12
12
|
"""
|
|
13
13
|
|
|
14
|
-
import dataclasses
|
|
15
14
|
from dataclasses import dataclass, field
|
|
16
15
|
from datetime import datetime
|
|
17
16
|
from types import SimpleNamespace
|
|
@@ -428,12 +427,6 @@ def _provenance_ctx(ctx):
|
|
|
428
427
|
add_data_points stamps ledger provenance from ``ctx.data_item.id``, which
|
|
429
428
|
exists on Data ORM records but not on raw ingestion DataItems. Substitute
|
|
430
429
|
the DataItem's deterministic ``data_id`` so provenance still lands.
|
|
431
|
-
|
|
432
|
-
Only ``data_item`` is replaced; every other PipelineContext field is
|
|
433
|
-
carried over via ``dataclasses.replace`` so consumers that read ctx
|
|
434
|
-
attributes (e.g. ``add_data_points`` reads ``ctx.pipeline_run_id``) never
|
|
435
|
-
see a field-stripped context — a hand-copied field list here silently
|
|
436
|
-
drops any parameter later added to PipelineContext.
|
|
437
430
|
"""
|
|
438
431
|
if ctx is None:
|
|
439
432
|
return None
|
|
@@ -441,7 +434,12 @@ def _provenance_ctx(ctx):
|
|
|
441
434
|
if data_item is None or hasattr(data_item, "id"):
|
|
442
435
|
return ctx
|
|
443
436
|
data_id = getattr(data_item, "data_id", None)
|
|
444
|
-
return
|
|
437
|
+
return SimpleNamespace(
|
|
438
|
+
user=getattr(ctx, "user", None),
|
|
439
|
+
dataset=getattr(ctx, "dataset", None),
|
|
440
|
+
data_item=SimpleNamespace(id=data_id) if data_id else None,
|
|
441
|
+
extras=getattr(ctx, "extras", None),
|
|
442
|
+
)
|
|
445
443
|
|
|
446
444
|
|
|
447
445
|
# Edge batches can run larger than node batches: edges are small tuples and
|
|
@@ -19,7 +19,7 @@ so no property is lost.
|
|
|
19
19
|
"""
|
|
20
20
|
|
|
21
21
|
import json
|
|
22
|
-
from typing import Any, Dict,
|
|
22
|
+
from typing import Any, Dict, List, Optional, Type, Union
|
|
23
23
|
|
|
24
24
|
from pydantic import BaseModel, ConfigDict, Field, SerializeAsAny, create_model, field_validator
|
|
25
25
|
|
|
@@ -59,41 +59,13 @@ class _DynamicDataPoint(DataPoint):
|
|
|
59
59
|
model_config = ConfigDict(arbitrary_types_allowed=True, extra="allow")
|
|
60
60
|
|
|
61
61
|
|
|
62
|
-
_dynamic_models: Dict[
|
|
62
|
+
_dynamic_models: Dict[str, Type[DataPoint]] = {}
|
|
63
63
|
|
|
64
64
|
|
|
65
|
-
def _dynamic_model(
|
|
66
|
-
type_name:
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
) -> Type[DataPoint]:
|
|
70
|
-
"""A DataPoint subclass named ``type_name`` that DECLARES the record's
|
|
71
|
-
properties as fields and bakes ``index_fields`` into the CLASS-level
|
|
72
|
-
metadata default.
|
|
73
|
-
|
|
74
|
-
Instance-level state is not enough on either count: downstream model
|
|
75
|
-
machinery only sees declared fields. ``get_graph_from_model`` iterates
|
|
76
|
-
declared fields when collecting node properties (``extra="allow"`` values
|
|
77
|
-
are silently dropped — imported DocumentChunk text never reached storage),
|
|
78
|
-
and rebuilds nodes through ``copy_model``, which re-applies class field
|
|
79
|
-
defaults (a plain DataPoint metadata default of ``index_fields: []``
|
|
80
|
-
dropped the embeddable-field markers, so nothing was vector-indexed).
|
|
81
|
-
"""
|
|
82
|
-
extra_fields = tuple(
|
|
83
|
-
sorted(
|
|
84
|
-
name
|
|
85
|
-
for name in (property_names or ())
|
|
86
|
-
if name != "metadata" and name not in DataPoint.model_fields
|
|
87
|
-
)
|
|
88
|
-
)
|
|
89
|
-
key = (type_name, extra_fields, tuple(index_fields or ()))
|
|
90
|
-
if key not in _dynamic_models:
|
|
91
|
-
field_definitions: Dict[str, Any] = {name: (Any, None) for name in extra_fields}
|
|
92
|
-
field_definitions["metadata"] = (dict, {"index_fields": list(index_fields or [])})
|
|
93
|
-
_dynamic_models[key] = create_model(
|
|
94
|
-
type_name, __base__=_DynamicDataPoint, **field_definitions
|
|
95
|
-
)
|
|
96
|
-
return _dynamic_models[key]
|
|
65
|
+
def _dynamic_model(type_name: str) -> Type[DataPoint]:
|
|
66
|
+
if type_name not in _dynamic_models:
|
|
67
|
+
_dynamic_models[type_name] = create_model(type_name, __base__=_DynamicDataPoint)
|
|
68
|
+
return _dynamic_models[type_name]
|
|
97
69
|
|
|
98
70
|
|
|
99
71
|
def _clean_properties(properties: Dict[str, Any]) -> Dict[str, Any]:
|
|
@@ -129,20 +101,14 @@ def rehydrate_node(
|
|
|
129
101
|
except Exception: # noqa: BLE001 — fall back to a dynamic model
|
|
130
102
|
pass
|
|
131
103
|
|
|
132
|
-
# Carry the record's properties and embeddable fields onto the dynamic
|
|
133
|
-
# CLASS so they survive downstream field iteration and copy_model
|
|
134
|
-
# rebuilds (see _dynamic_model).
|
|
135
|
-
metadata = props.get("metadata")
|
|
136
|
-
index_fields = metadata.get("index_fields") if isinstance(metadata, dict) else None
|
|
137
|
-
|
|
138
104
|
try:
|
|
139
105
|
# Created lazily: only when the registered class is absent or fails.
|
|
140
|
-
return _dynamic_model(type_name
|
|
106
|
+
return _dynamic_model(type_name)(**props)
|
|
141
107
|
except Exception: # noqa: BLE001 — final fallback below
|
|
142
108
|
pass
|
|
143
109
|
|
|
144
110
|
base_safe = {key: value for key, value in props.items() if key in _BASE_FIELDS}
|
|
145
|
-
return _dynamic_model(type_name
|
|
111
|
+
return _dynamic_model(type_name)(**base_safe)
|
|
146
112
|
|
|
147
113
|
|
|
148
114
|
class GraphEdge(BaseModel):
|
|
@@ -5,11 +5,16 @@ import cognee
|
|
|
5
5
|
|
|
6
6
|
from cognee.exceptions import CogneeValidationError, CogneeSystemError
|
|
7
7
|
from cognee.shared.logging_utils import get_logger
|
|
8
|
+
from cognee.modules.users.models import User
|
|
8
9
|
|
|
9
10
|
logger = get_logger("cognify_session")
|
|
10
11
|
|
|
11
12
|
|
|
12
|
-
async def cognify_session(
|
|
13
|
+
async def cognify_session(
|
|
14
|
+
data: str,
|
|
15
|
+
dataset_id: Optional[UUID | str] = None,
|
|
16
|
+
user: Optional[User] = None,
|
|
17
|
+
) -> None:
|
|
13
18
|
"""
|
|
14
19
|
Process and cognify session data into the knowledge graph.
|
|
15
20
|
|
|
@@ -32,9 +37,14 @@ async def cognify_session(data: str, dataset_id: Optional[UUID | str] = None) ->
|
|
|
32
37
|
|
|
33
38
|
logger.info("Processing session data for cognification")
|
|
34
39
|
|
|
35
|
-
await cognee.add(
|
|
40
|
+
await cognee.add(
|
|
41
|
+
data,
|
|
42
|
+
dataset_id=dataset_id,
|
|
43
|
+
node_set=["user_sessions_from_cache"],
|
|
44
|
+
user=user,
|
|
45
|
+
)
|
|
36
46
|
logger.debug("Session data added to cognee with node_set: user_sessions")
|
|
37
|
-
await cognee.cognify(datasets=[dataset_id])
|
|
47
|
+
await cognee.cognify(datasets=[dataset_id], user=user)
|
|
38
48
|
logger.info("Session data successfully cognified")
|
|
39
49
|
|
|
40
50
|
except CogneeValidationError:
|
|
@@ -48,6 +48,7 @@ async def test_persist_agent_trace_feedbacks_pipeline_wires_memify_tasks():
|
|
|
48
48
|
|
|
49
49
|
memify_kwargs = memify_mock.call_args.kwargs
|
|
50
50
|
assert memify_kwargs["dataset"] == "dataset-1"
|
|
51
|
+
assert memify_kwargs["user"] == user
|
|
51
52
|
assert memify_kwargs["data"] == [{}]
|
|
52
53
|
assert len(memify_kwargs["extraction_tasks"]) == 1
|
|
53
54
|
assert len(memify_kwargs["enrichment_tasks"]) == 1
|
|
@@ -22,7 +22,6 @@ from cognee.modules.migration.sources.base import MemorySource
|
|
|
22
22
|
# fails here because package __init__ files rebind submodule names to
|
|
23
23
|
# same-named functions (e.g. ``cognee.api.v1.remember.remember``).
|
|
24
24
|
add_module = importlib.import_module("cognee.api.v1.add")
|
|
25
|
-
migrations_startup_module = importlib.import_module("cognee.modules.migrations.startup")
|
|
26
25
|
pipeline_module = importlib.import_module("cognee.modules.run_custom_pipeline")
|
|
27
26
|
remember_module = importlib.import_module("cognee.api.v1.remember.remember")
|
|
28
27
|
serve_state = importlib.import_module("cognee.api.v1.serve.state")
|
|
@@ -76,13 +75,7 @@ def install_sinks(monkeypatch):
|
|
|
76
75
|
``add_data_points`` sink. It returns a run-info dict so pipeline_run_id
|
|
77
76
|
propagation can be asserted.
|
|
78
77
|
"""
|
|
79
|
-
sinks = SimpleNamespace(
|
|
80
|
-
pipeline_calls=[],
|
|
81
|
-
add_calls=[],
|
|
82
|
-
remember_calls=[],
|
|
83
|
-
graph_flushes=[],
|
|
84
|
-
migration_gate_calls=[],
|
|
85
|
-
)
|
|
78
|
+
sinks = SimpleNamespace(pipeline_calls=[], add_calls=[], remember_calls=[], graph_flushes=[])
|
|
86
79
|
|
|
87
80
|
async def fake_run_custom_pipeline(**kwargs):
|
|
88
81
|
sinks.pipeline_calls.append(kwargs)
|
|
@@ -105,24 +98,10 @@ def install_sinks(monkeypatch):
|
|
|
105
98
|
result.items_processed = len(data)
|
|
106
99
|
return result
|
|
107
100
|
|
|
108
|
-
async def fake_run_migrations_and_block(datasets, user):
|
|
109
|
-
# writes_before_gate lets tests assert the gate fired before any
|
|
110
|
-
# imported data was stored (stamping must precede the rows).
|
|
111
|
-
sinks.migration_gate_calls.append(
|
|
112
|
-
{
|
|
113
|
-
"datasets": datasets,
|
|
114
|
-
"user": user,
|
|
115
|
-
"writes_before_gate": len(sinks.add_calls) + len(sinks.graph_flushes),
|
|
116
|
-
}
|
|
117
|
-
)
|
|
118
|
-
|
|
119
101
|
monkeypatch.setattr(pipeline_module, "run_custom_pipeline", fake_run_custom_pipeline)
|
|
120
102
|
monkeypatch.setattr(storage_module, "add_data_points", fake_add_data_points)
|
|
121
103
|
monkeypatch.setattr(add_module, "add", fake_add)
|
|
122
104
|
monkeypatch.setattr(remember_module, "remember", fake_remember)
|
|
123
|
-
monkeypatch.setattr(
|
|
124
|
-
migrations_startup_module, "run_migrations_and_block", fake_run_migrations_and_block
|
|
125
|
-
)
|
|
126
105
|
return sinks
|
|
127
106
|
|
|
128
107
|
|
|
@@ -341,27 +320,6 @@ class TestSkippedFacts:
|
|
|
341
320
|
assert _flushed_edges(sinks) == []
|
|
342
321
|
|
|
343
322
|
|
|
344
|
-
class TestMigrationGate:
|
|
345
|
-
"""import_memory_source must take the run_migrations_and_block gate.
|
|
346
|
-
|
|
347
|
-
The gate stamps a fresh store's migration revision at head BEFORE the
|
|
348
|
-
imported rows arrive; skipping it leaves the populated store with no
|
|
349
|
-
recorded revision, so the first migration-aware startup replays the whole
|
|
350
|
-
data-migration chain over the freshly imported data.
|
|
351
|
-
"""
|
|
352
|
-
|
|
353
|
-
@pytest.mark.parametrize("mode", ["preserve", "re-derive", "hybrid"])
|
|
354
|
-
def test_gate_fires_once_before_any_write(self, monkeypatch, mode):
|
|
355
|
-
sinks = install_sinks(monkeypatch)
|
|
356
|
-
source = FakeSource(_sample_records(), mode=mode)
|
|
357
|
-
|
|
358
|
-
asyncio.run(import_memory_source(source, dataset_name="ds"))
|
|
359
|
-
|
|
360
|
-
(gate_call,) = sinks.migration_gate_calls
|
|
361
|
-
assert gate_call["datasets"] == "ds"
|
|
362
|
-
assert gate_call["writes_before_gate"] == 0
|
|
363
|
-
|
|
364
|
-
|
|
365
323
|
class TestRememberDispatch:
|
|
366
324
|
"""remember() routing for MemorySource inputs (guards, kwargs forwarding)."""
|
|
367
325
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
"""Unit tests for the Pydantic-native export (GraphSnapshot). Pure: no DB, no LLM."""
|
|
2
2
|
|
|
3
|
-
import asyncio
|
|
4
3
|
from uuid import uuid4
|
|
5
4
|
|
|
6
5
|
from cognee.infrastructure.engine import DataPoint
|
|
@@ -69,58 +68,6 @@ class TestRehydrateNode:
|
|
|
69
68
|
assert isinstance(node, Entity)
|
|
70
69
|
assert node.metadata["index_fields"] == ["name"]
|
|
71
70
|
|
|
72
|
-
def test_dynamic_model_bakes_index_fields_into_class_default(self):
|
|
73
|
-
node = rehydrate_node(
|
|
74
|
-
{
|
|
75
|
-
"id": str(uuid4()),
|
|
76
|
-
"type": "AlienChunk",
|
|
77
|
-
"text": "Zorg lives on Mars.",
|
|
78
|
-
"metadata": {"index_fields": ["text"]},
|
|
79
|
-
}
|
|
80
|
-
)
|
|
81
|
-
# The CLASS default must carry index_fields, not just the instance:
|
|
82
|
-
# get_graph_from_model rebuilds nodes via copy_model from class field
|
|
83
|
-
# defaults, so instance-only metadata never reaches the vector index.
|
|
84
|
-
assert type(node).model_fields["metadata"].default["index_fields"] == ["text"]
|
|
85
|
-
|
|
86
|
-
def test_index_fields_and_text_survive_graph_extraction(self):
|
|
87
|
-
"""Regression: imported DocumentChunk raw nodes fail real-class
|
|
88
|
-
validation (flat properties lack the required relation fields) and
|
|
89
|
-
fall back to a dynamic model. Downstream model machinery only sees
|
|
90
|
-
DECLARED fields, so the dynamic class must declare the record's
|
|
91
|
-
properties AND carry index_fields as its class metadata default —
|
|
92
|
-
otherwise get_graph_from_model drops the chunk's text (extra="allow"
|
|
93
|
-
values are not iterated) and/or its embeddable-field markers
|
|
94
|
-
(copy_model re-applies class defaults), the restored archive has no
|
|
95
|
-
DocumentChunk_text collection, and hybrid retrieval fails with
|
|
96
|
-
NoDataError."""
|
|
97
|
-
from cognee.modules.graph.utils import get_graph_from_model
|
|
98
|
-
|
|
99
|
-
node = rehydrate_node(
|
|
100
|
-
{
|
|
101
|
-
"id": str(uuid4()),
|
|
102
|
-
"type": "DocumentChunk",
|
|
103
|
-
"text": "Alice lives in Berlin.",
|
|
104
|
-
"chunk_index": 0,
|
|
105
|
-
"metadata": {"index_fields": ["text"]},
|
|
106
|
-
}
|
|
107
|
-
)
|
|
108
|
-
assert node.metadata["index_fields"] == ["text"]
|
|
109
|
-
assert node.text == "Alice lives in Berlin."
|
|
110
|
-
|
|
111
|
-
nodes, _ = asyncio.run(
|
|
112
|
-
get_graph_from_model(node, added_nodes={}, added_edges={}, visited_properties={})
|
|
113
|
-
)
|
|
114
|
-
(extracted,) = nodes
|
|
115
|
-
assert extracted.metadata["index_fields"] == ["text"], (
|
|
116
|
-
"index_fields lost during graph extraction — imported chunk text "
|
|
117
|
-
"will not be vector-indexed"
|
|
118
|
-
)
|
|
119
|
-
assert getattr(extracted, "text", None) == "Alice lives in Berlin.", (
|
|
120
|
-
"chunk text lost during graph extraction — undeclared extra fields "
|
|
121
|
-
"are dropped, so the imported chunk stores and indexes as empty"
|
|
122
|
-
)
|
|
123
|
-
|
|
124
71
|
|
|
125
72
|
class TestGraphSnapshot:
|
|
126
73
|
def _snapshot(self, link_relations=False):
|
|
@@ -19,9 +19,12 @@ async def test_cognify_session_success():
|
|
|
19
19
|
await cognify_session(session_data, dataset_id="123")
|
|
20
20
|
|
|
21
21
|
mock_add.assert_called_once_with(
|
|
22
|
-
session_data,
|
|
22
|
+
session_data,
|
|
23
|
+
dataset_id="123",
|
|
24
|
+
node_set=["user_sessions_from_cache"],
|
|
25
|
+
user=None,
|
|
23
26
|
)
|
|
24
|
-
mock_cognify.
|
|
27
|
+
mock_cognify.assert_called_once_with(datasets=["123"], user=None)
|
|
25
28
|
|
|
26
29
|
|
|
27
30
|
@pytest.mark.asyncio
|
|
@@ -106,6 +109,32 @@ async def test_cognify_session_with_special_characters():
|
|
|
106
109
|
await cognify_session(session_data, dataset_id="123")
|
|
107
110
|
|
|
108
111
|
mock_add.assert_called_once_with(
|
|
109
|
-
session_data,
|
|
112
|
+
session_data,
|
|
113
|
+
dataset_id="123",
|
|
114
|
+
node_set=["user_sessions_from_cache"],
|
|
115
|
+
user=None,
|
|
110
116
|
)
|
|
111
|
-
mock_cognify.
|
|
117
|
+
mock_cognify.assert_called_once_with(datasets=["123"], user=None)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
@pytest.mark.asyncio
|
|
121
|
+
async def test_cognify_session_passes_user_to_add_and_cognify():
|
|
122
|
+
"""Test user is forwarded to cognee.add/cognee.cognify."""
|
|
123
|
+
session_data = (
|
|
124
|
+
"Session ID: test_session\n\nQuestion: What is AI?\n\nAnswer: AI is artificial intelligence"
|
|
125
|
+
)
|
|
126
|
+
user = object()
|
|
127
|
+
|
|
128
|
+
with (
|
|
129
|
+
patch("cognee.add", new_callable=AsyncMock) as mock_add,
|
|
130
|
+
patch("cognee.cognify", new_callable=AsyncMock) as mock_cognify,
|
|
131
|
+
):
|
|
132
|
+
await cognify_session(session_data, dataset_id="123", user=user)
|
|
133
|
+
|
|
134
|
+
mock_add.assert_called_once_with(
|
|
135
|
+
session_data,
|
|
136
|
+
dataset_id="123",
|
|
137
|
+
node_set=["user_sessions_from_cache"],
|
|
138
|
+
user=user,
|
|
139
|
+
)
|
|
140
|
+
mock_cognify.assert_called_once_with(datasets=["123"], user=user)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cognee
|
|
3
|
-
Version: 1.2.2.
|
|
3
|
+
Version: 1.2.2.dev3
|
|
4
4
|
Summary: Cognee - is a library for enriching LLM context with a semantic layer for better understanding and reasoning.
|
|
5
5
|
Project-URL: Homepage, https://www.cognee.ai
|
|
6
6
|
Project-URL: Repository, https://github.com/topoteretes/cognee
|
|
@@ -602,8 +602,8 @@ cognee/memify_pipelines/consolidate_entity_descriptions.py,sha256=E3lNaVSQBZG9gm
|
|
|
602
602
|
cognee/memify_pipelines/create_triplet_embeddings.py,sha256=oniU5JUClgpmxgR860nOX0Wu7TjlXNXE9zH2OnSlD_E,1730
|
|
603
603
|
cognee/memify_pipelines/global_context_index.py,sha256=-fi--mYVazD_Kzjbek_IE-q7GRquP77pmnaqbRpMMEk,2700
|
|
604
604
|
cognee/memify_pipelines/memify_default_tasks.py,sha256=SmXqkQCufI8zYdx239-ncjNQqZE-E10AIGbajPMPln8,908
|
|
605
|
-
cognee/memify_pipelines/persist_agent_trace_feedbacks_in_knowledge_graph.py,sha256=
|
|
606
|
-
cognee/memify_pipelines/persist_sessions_in_knowledge_graph.py,sha256=
|
|
605
|
+
cognee/memify_pipelines/persist_agent_trace_feedbacks_in_knowledge_graph.py,sha256=5i35i9KTpOCMYuxncqXDId6rDcNnmv1BTSN7hipTHNQ,3620
|
|
606
|
+
cognee/memify_pipelines/persist_sessions_in_knowledge_graph.py,sha256=gtpqVR6qb4FKl6gG4C0Q3av3h3e1GjYlEjkdnfX_q2c,2503
|
|
607
607
|
cognee/memory/__init__.py,sha256=LOsCYZ0aMKAb0wdpe1aUBdu4RoTjKy_4_XLNCULW_Iw,298
|
|
608
608
|
cognee/memory/entries.py,sha256=obAHjOybB3Hqr-y37_9ZKa9KMycBLqjieIfsdzWKIfA,5872
|
|
609
609
|
cognee/migration/__init__.py,sha256=KIgvAJwxU9AnthJmwIxw_qvz-KDHteHpWf7ZXyv9i_4,1946
|
|
@@ -785,9 +785,9 @@ cognee/modules/migration/archive.py,sha256=ptBMXeJiWQwas2n0Yf-tD2cdqVfU_WaBxw9sa
|
|
|
785
785
|
cognee/modules/migration/cogx.py,sha256=Z_phNpzX3p9upeKxevtRE_RjLht1Ly9jYw6koYkfPXU,11079
|
|
786
786
|
cognee/modules/migration/export.py,sha256=v-GPc1oT41cmXpuU_vqOCX0Us_9sWQZFoVwMTNyLOCQ,8210
|
|
787
787
|
cognee/modules/migration/formats.py,sha256=-o2hqVwSHXz2O7d_bsxdACZjTd-h8goKoLQ_UqFBcSw,5785
|
|
788
|
-
cognee/modules/migration/import_source.py,sha256=
|
|
789
|
-
cognee/modules/migration/loader.py,sha256=
|
|
790
|
-
cognee/modules/migration/snapshot.py,sha256=
|
|
788
|
+
cognee/modules/migration/import_source.py,sha256=Ndy_wJsyP4ZMHtdAKkjD1sIP4GMlkMbz4dlsld1MOHU,10907
|
|
789
|
+
cognee/modules/migration/loader.py,sha256=IXyH0svZm8VoURymfZCQ-3WZdqPGNPzBQ-y6UjNenpk,23699
|
|
790
|
+
cognee/modules/migration/snapshot.py,sha256=wYOSuX_N9R3AF5NaHUyX4YbgXil2y7bhJWS3A0srAU4,9084
|
|
791
791
|
cognee/modules/migration/sources/__init__.py,sha256=HofNJVBO45VaaEWHnC_I7lV5XFtsMLqbm_bpiD3-0Ck,348
|
|
792
792
|
cognee/modules/migration/sources/base.py,sha256=WXhgaRX9M7GCvLmyzvWkREgGCvTliJwk_DGK7LjicVE,2135
|
|
793
793
|
cognee/modules/migration/sources/cogx_archive.py,sha256=x4wz5E-Gim7_vLkB9JFJ9NiZB_JIFKt5ISA1VZNToGs,1569
|
|
@@ -1179,7 +1179,7 @@ cognee/tasks/memify/__init__.py,sha256=Bpkm0TdrCnhY76b1orosMVfA3H7a5Dn-mIxIVodNb
|
|
|
1179
1179
|
cognee/tasks/memify/apply_feedback_weights.py,sha256=vlAQUb0Xb4egS3Bf-EyWnxwfhsZP-WPAO14nBwNT_Gw,7717
|
|
1180
1180
|
cognee/tasks/memify/apply_frequency_weights.py,sha256=CZb5ITSIBkgRoQuaYq8yletm6vEsDLKiUGZ9Ng3y8O8,6570
|
|
1181
1181
|
cognee/tasks/memify/cognify_agent_trace_feedback.py,sha256=fS7upXpo_-N_l5x0nl9mKiDElMww5yvH1iO5fPh75OA,2005
|
|
1182
|
-
cognee/tasks/memify/cognify_session.py,sha256=
|
|
1182
|
+
cognee/tasks/memify/cognify_session.py,sha256=z4zj88E0mEV7LCjbFDXh3AdLnaEazmgaWSXHoHVl0RM,1857
|
|
1183
1183
|
cognee/tasks/memify/extract_agent_trace_feedbacks.py,sha256=V7_ZscgwlCZh07cthAXdOy1EEG4gsk0xDAOIpEOEG14,5226
|
|
1184
1184
|
cognee/tasks/memify/extract_feedback_qas.py,sha256=VANI24LkOfFxvES8B9bHXuWiUD8OaAW00JHFBIdI9Vc,3218
|
|
1185
1185
|
cognee/tasks/memify/extract_subgraph.py,sha256=Al1A5d3bhmd-rd9T9is_ppTfK9JsTb3Es9mBWTiJjB8,220
|
|
@@ -1261,7 +1261,6 @@ cognee/tests/test_advanced_pdf_loader.py,sha256=0Jdg4ZZ67_3dg5Z0bCYzubHSLYDQtNgH
|
|
|
1261
1261
|
cognee/tests/test_agent_memory_e2e.py,sha256=I1d52atkk0r0dycBG_FTu7_gOyQL-tYt067dW-GTQF0,6681
|
|
1262
1262
|
cognee/tests/test_chunk_associations.py,sha256=OnsX3a9pLV_Yaj7Xyb297mOciihEz3TFK5uwhbjh_80,8182
|
|
1263
1263
|
cognee/tests/test_cognee_server_start.py,sha256=nld8SkG4WHUPiHVz6872ImWmcERcUnNN_-6Gf8fUj0E,7572
|
|
1264
|
-
cognee/tests/test_cogx_roundtrip.py,sha256=K0kiGxZ1COFsytTS5zfhymMwClWCUTOQK7VTsWOZxgk,7522
|
|
1265
1264
|
cognee/tests/test_concurrent_cognify_e2e.py,sha256=tdmp0QA6uatFd5YL0bBahk8GWq-GG8LKrhiDfrP4jWQ,5682
|
|
1266
1265
|
cognee/tests/test_concurrent_subprocess_access.py,sha256=xh72FclRY1LnwUbpmIQTzvK7Yayoov6oewWmHivPTxE,3041
|
|
1267
1266
|
cognee/tests/test_conversation_history.py,sha256=80be_RWiT4acwZ6agSQY2ch69hmJ8MN-RSeL2qIx0pM,18186
|
|
@@ -1540,14 +1539,13 @@ cognee/tests/unit/interfaces/graph/get_graph_from_model_unit_test.py,sha256=IZQ7
|
|
|
1540
1539
|
cognee/tests/unit/interfaces/graph/test_expand_with_nodes_and_edges.py,sha256=h3ZRdvtfdJA77aC_Cz7UCXMWXuGXxeLtVwk4CnVD1uc,6429
|
|
1541
1540
|
cognee/tests/unit/interfaces/graph/test_weighted_edges.py,sha256=Xi-iVyhVJ4YzAgG-eGvx9kZLtwCMhq2Ca43xNkaO_K4,13315
|
|
1542
1541
|
cognee/tests/unit/memify_pipelines/test_apply_feedback_weights_pipeline.py,sha256=B96e_wv7TBbLANknkgR7Wu26-TwxQrYDgWg6bFWQNeI,3248
|
|
1543
|
-
cognee/tests/unit/memify_pipelines/test_persist_agent_trace_feedbacks_pipeline.py,sha256=
|
|
1542
|
+
cognee/tests/unit/memify_pipelines/test_persist_agent_trace_feedbacks_pipeline.py,sha256=T01IppNOKbRL9apCxb5eQEjdzt3Zy0Py8ppOGqF9iNc,2630
|
|
1544
1543
|
cognee/tests/unit/migration/test_export_roundtrip.py,sha256=CSB9G_KtHMEbDWa8UR6oU0hi3jy5G2Qv3WGc1cs5Vtw,18167
|
|
1545
|
-
cognee/tests/unit/migration/test_import_source.py,sha256=
|
|
1544
|
+
cognee/tests/unit/migration/test_import_source.py,sha256=ZyuY4AjHugKEa6T4vWu4Vh_RtwcHH7JwnFxHTrtUPxw,15932
|
|
1546
1545
|
cognee/tests/unit/migration/test_migration.py,sha256=5tqGzk01dsfhGxDDRzyumQ2fotbiKW7XWfjonrMUy3M,19833
|
|
1547
|
-
cognee/tests/unit/migration/test_provenance_ctx.py,sha256=GHiAA8NLs2JWaeztyFJuaeeuo9NScgzUNtQGX5wguuA,3057
|
|
1548
1546
|
cognee/tests/unit/migration/test_push.py,sha256=GYRZXhAKHsyWSNLYa23PDCM9qX5BoXlRY9EWRe-8TwY,16905
|
|
1549
1547
|
cognee/tests/unit/migration/test_remember_router_cogx.py,sha256=Q72DFoaW9gjdGZI07EXSgU_pQlhnr0-5LlDx1TY_h-A,12156
|
|
1550
|
-
cognee/tests/unit/migration/test_snapshot.py,sha256=
|
|
1548
|
+
cognee/tests/unit/migration/test_snapshot.py,sha256=tdzSUAHq187ZaN8gMBlF2WBe9ABv6kBw6VYu6Os4sHU,4898
|
|
1551
1549
|
cognee/tests/unit/modules/agent_memory/test_agent_memory.py,sha256=AGgsjsS1BTvdJbgX6M4peNgkbMBbRSHGH2BRD2sLuXc,40791
|
|
1552
1550
|
cognee/tests/unit/modules/agents/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
1553
1551
|
cognee/tests/unit/modules/agents/conftest.py,sha256=5QcS2mitl-wl1ytZVm1_T7SAofrPhgBbs4P3I95nLJE,1027
|
|
@@ -1570,7 +1568,7 @@ cognee/tests/unit/modules/graph/test_resolve_edges_to_text.py,sha256=Pz4CTFHEE8R
|
|
|
1570
1568
|
cognee/tests/unit/modules/graph/test_retrieve_existing_edges.py,sha256=VIolEF-RdQ_9kqOed8XQ5Irl6NH2MreIXPxA1uG7SeI,3004
|
|
1571
1569
|
cognee/tests/unit/modules/memify_tasks/test_apply_feedback_weights.py,sha256=tISeQ7T_6sokaVpvWb6aEec3Hgg6bHPsMYSArqlYpow,9874
|
|
1572
1570
|
cognee/tests/unit/modules/memify_tasks/test_cognify_agent_trace_feedback.py,sha256=pF1ELFjcHgCIxHnV4hVdUEy9lvWTICap6v93zuMV6DI,2753
|
|
1573
|
-
cognee/tests/unit/modules/memify_tasks/test_cognify_session.py,sha256=
|
|
1571
|
+
cognee/tests/unit/modules/memify_tasks/test_cognify_session.py,sha256=rp_uRURlfujpY6e2Mo61X2kj-VFAfqVUDrHdAAXNLzI,4783
|
|
1574
1572
|
cognee/tests/unit/modules/memify_tasks/test_extract_agent_trace_feedbacks.py,sha256=XOvmx3dSCgSfDldFOjGlds9mPPk074QcYTXmj5m_HxU,13729
|
|
1575
1573
|
cognee/tests/unit/modules/memify_tasks/test_extract_feedback_qas.py,sha256=CZdduhZCXczui7XNk2Y0R2a9gDSX-SvfnKOdMTzkUpo,6320
|
|
1576
1574
|
cognee/tests/unit/modules/memify_tasks/test_extract_user_sessions.py,sha256=6WLyquWcVWeRVCoUk2i6uwpFk-xl-0s_WMruQYijzas,7542
|
|
@@ -1713,9 +1711,9 @@ distributed/workers/data_point_saving_worker.py,sha256=kmaQy2A2J7W3k9Gd5lyoiT0XY
|
|
|
1713
1711
|
distributed/workers/graph_saving_worker.py,sha256=KVds58rBh-m3TnOyouE4cqSDnzIHNRqw-Td06abOGS0,4961
|
|
1714
1712
|
kuzu/__init__.py,sha256=NqYsYyycqMZOUte0_3r_eO5VJGe_BCNdOdLPpJTvgdk,224
|
|
1715
1713
|
kuzu/database.py,sha256=JfHFK1YAFKrnSId0p_5sqFwhX2IWfKo0MFNEPPNeQ9k,154
|
|
1716
|
-
cognee-1.2.2.
|
|
1717
|
-
cognee-1.2.2.
|
|
1718
|
-
cognee-1.2.2.
|
|
1719
|
-
cognee-1.2.2.
|
|
1720
|
-
cognee-1.2.2.
|
|
1721
|
-
cognee-1.2.2.
|
|
1714
|
+
cognee-1.2.2.dev3.dist-info/METADATA,sha256=XMMcyeQT0DAv0pnHBXUlg-TKN6SGk4-fK6j31Cf2T9E,26799
|
|
1715
|
+
cognee-1.2.2.dev3.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
|
|
1716
|
+
cognee-1.2.2.dev3.dist-info/entry_points.txt,sha256=GCCTsNg8gzOJkolq7dR7OK1VlIAO202dGDnMI8nm8oQ,55
|
|
1717
|
+
cognee-1.2.2.dev3.dist-info/licenses/LICENSE,sha256=pHHjSQj1DD8SDppW88MMs04TPk7eAanL1c5xj8NY7NQ,11344
|
|
1718
|
+
cognee-1.2.2.dev3.dist-info/licenses/NOTICE.md,sha256=6L3saP3kSpcingOxDh-SGjMS8GY79Rlh2dBNLaO0o5c,339
|
|
1719
|
+
cognee-1.2.2.dev3.dist-info/RECORD,,
|
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
"""E2E: export a cognified dataset as a COGX archive, restore it into a fresh
|
|
2
|
-
store, and search the restored knowledge graph.
|
|
3
|
-
|
|
4
|
-
This is the Cognee-to-Cognee instance-migration path (the local half of
|
|
5
|
-
push/pull): ``cognee.export(format="cogx")`` on the source machine,
|
|
6
|
-
``cognee.remember(COGXArchiveSource(...))`` on the target. The test covers
|
|
7
|
-
the full system contract:
|
|
8
|
-
|
|
9
|
-
- the preserve-mode import survives the pipeline context adaptation
|
|
10
|
-
(regression: ``ctx.pipeline_run_id`` was dropped, crashing every import),
|
|
11
|
-
- the import stamps the fresh store's migration revision at head BEFORE the
|
|
12
|
-
rows arrive (regression: an unstamped store replayed the entire
|
|
13
|
-
data-migration chain on the first server start after a restore),
|
|
14
|
-
- the restored graph is populated and answerable via search.
|
|
15
|
-
|
|
16
|
-
The test runs in multi-user mode (backend access control enabled — pinned
|
|
17
|
-
below): each dataset_database row must be head-stamped when the import
|
|
18
|
-
creates it.
|
|
19
|
-
"""
|
|
20
|
-
|
|
21
|
-
import asyncio
|
|
22
|
-
import os
|
|
23
|
-
import pathlib
|
|
24
|
-
import tempfile
|
|
25
|
-
|
|
26
|
-
import cognee
|
|
27
|
-
from cognee.modules.migration.sources.cogx_archive import COGXArchiveSource
|
|
28
|
-
from cognee.modules.search.types import SearchType
|
|
29
|
-
from cognee.shared.logging_utils import get_logger
|
|
30
|
-
|
|
31
|
-
logger = get_logger()
|
|
32
|
-
|
|
33
|
-
TEXT = """The Aurora Skyline Hotel is a boutique hotel in Berlin founded by Clara Novak in 2015.
|
|
34
|
-
The hotel is known for its rooftop observatory and partners with the Berlin Astronomy Club.
|
|
35
|
-
Clara Novak previously managed the Lindenhof Resort in Munich before moving to Berlin.
|
|
36
|
-
"""
|
|
37
|
-
|
|
38
|
-
QUERY = "Who founded the Aurora Skyline Hotel and what is the hotel known for?"
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
async def _wipe_store():
|
|
42
|
-
"""Reset to an empty store, as on a machine that never ran Cognee."""
|
|
43
|
-
await cognee.prune.prune_data()
|
|
44
|
-
await cognee.prune.prune_system(metadata=True)
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
async def _assert_revision_at_head():
|
|
48
|
-
"""The restored store's data-migration bookkeeping must be stamped at head.
|
|
49
|
-
|
|
50
|
-
Without the stamp the store is indistinguishable from a pre-migration one,
|
|
51
|
-
and the first migration-aware startup replays the whole chain over the
|
|
52
|
-
imported data. In multi-user mode the stamp lives on the per-dataset
|
|
53
|
-
``dataset_database`` rows, head-stamped when the import creates them.
|
|
54
|
-
"""
|
|
55
|
-
from cognee.modules.data.methods.get_dataset_databases import get_dataset_databases
|
|
56
|
-
from cognee.modules.migrations.migration import head_revision
|
|
57
|
-
from cognee.modules.migrations.registry import MIGRATIONS
|
|
58
|
-
|
|
59
|
-
head = head_revision(MIGRATIONS)
|
|
60
|
-
|
|
61
|
-
rows = await get_dataset_databases()
|
|
62
|
-
assert rows, "Import created no dataset_database bookkeeping row for the fresh store."
|
|
63
|
-
for row in rows:
|
|
64
|
-
assert row.migration_revision == head, (
|
|
65
|
-
f"Imported dataset {row.dataset_id} is stamped at {row.migration_revision!r}, "
|
|
66
|
-
f"expected head {head!r} — the first startup would replay the migration chain."
|
|
67
|
-
)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
async def main():
|
|
71
|
-
# Disable session-turn gating so searches return direct retrieval results
|
|
72
|
-
# (same rationale as test_library.py).
|
|
73
|
-
os.environ["AUTO_FEEDBACK"] = "False"
|
|
74
|
-
|
|
75
|
-
# This test runs in multi-user mode: the stamp assertion reads the
|
|
76
|
-
# per-dataset bookkeeping rows that mode maintains. The flag is read
|
|
77
|
-
# dynamically, so setting it here wins over any ambient .env.
|
|
78
|
-
os.environ["ENABLE_BACKEND_ACCESS_CONTROL"] = "true"
|
|
79
|
-
|
|
80
|
-
data_directory_path = str(
|
|
81
|
-
pathlib.Path(
|
|
82
|
-
os.path.join(pathlib.Path(__file__).parent, ".data_storage/test_cogx_roundtrip")
|
|
83
|
-
).resolve()
|
|
84
|
-
)
|
|
85
|
-
cognee.config.data_root_directory(data_directory_path)
|
|
86
|
-
cognee_directory_path = str(
|
|
87
|
-
pathlib.Path(
|
|
88
|
-
os.path.join(pathlib.Path(__file__).parent, ".cognee_system/test_cogx_roundtrip")
|
|
89
|
-
).resolve()
|
|
90
|
-
)
|
|
91
|
-
cognee.config.system_root_directory(cognee_directory_path)
|
|
92
|
-
|
|
93
|
-
dataset_name = "hotel_knowledge"
|
|
94
|
-
|
|
95
|
-
with tempfile.TemporaryDirectory() as temporary_directory:
|
|
96
|
-
# The archive must live OUTSIDE the data/system roots so wiping the
|
|
97
|
-
# store between phases cannot delete it (it is the "file shipped to
|
|
98
|
-
# the other machine").
|
|
99
|
-
archive_dir = pathlib.Path(temporary_directory) / "hotel_cogx"
|
|
100
|
-
|
|
101
|
-
# --- Phase 1: source instance — build a graph and export it. -------
|
|
102
|
-
await _wipe_store()
|
|
103
|
-
|
|
104
|
-
await cognee.add([TEXT], dataset_name)
|
|
105
|
-
await cognee.cognify([dataset_name])
|
|
106
|
-
|
|
107
|
-
source_results = await cognee.search(
|
|
108
|
-
query_type=SearchType.GRAPH_COMPLETION, query_text=QUERY, datasets=[dataset_name]
|
|
109
|
-
)
|
|
110
|
-
assert len(source_results) != 0, "Search on the source instance returned nothing."
|
|
111
|
-
logger.info("Source search results: %s", source_results)
|
|
112
|
-
|
|
113
|
-
export_result = await cognee.export(dataset_name, format="cogx", destination=archive_dir)
|
|
114
|
-
assert export_result.num_nodes > 0, "Export produced an empty archive (0 nodes)."
|
|
115
|
-
assert export_result.num_edges > 0, "Export produced an archive with 0 edges."
|
|
116
|
-
logger.info(
|
|
117
|
-
"Exported %d nodes, %d edges to %s",
|
|
118
|
-
export_result.num_nodes,
|
|
119
|
-
export_result.num_edges,
|
|
120
|
-
export_result.destination,
|
|
121
|
-
)
|
|
122
|
-
|
|
123
|
-
# --- Phase 2: target instance — restore into a fresh store. --------
|
|
124
|
-
await _wipe_store()
|
|
125
|
-
|
|
126
|
-
# run_migrations is once-per-process; on a real restore the import
|
|
127
|
-
# runs in a brand-new process on the target machine. Reset the guard
|
|
128
|
-
# so the import's migration gate treats the wiped store as exactly
|
|
129
|
-
# that: a fresh instance.
|
|
130
|
-
import cognee.modules.migrations.startup as migrations_startup
|
|
131
|
-
|
|
132
|
-
migrations_startup._startup_migrations_done = False
|
|
133
|
-
|
|
134
|
-
import_result = await cognee.remember(
|
|
135
|
-
COGXArchiveSource(archive_dir), dataset_name=dataset_name
|
|
136
|
-
)
|
|
137
|
-
assert import_result.status == "completed", (
|
|
138
|
-
f"Import did not complete: {import_result.status!r}"
|
|
139
|
-
)
|
|
140
|
-
assert import_result.items_processed > 0, "Import processed nothing."
|
|
141
|
-
|
|
142
|
-
(import_summary,) = [
|
|
143
|
-
item for item in import_result.items if item.get("kind") == "migration_import"
|
|
144
|
-
]
|
|
145
|
-
assert import_summary["graph_nodes"] > 0, "Import restored no graph nodes."
|
|
146
|
-
assert import_summary["graph_edges"] > 0, "Import restored no graph edges."
|
|
147
|
-
logger.info("Import summary: %s", import_summary)
|
|
148
|
-
|
|
149
|
-
await _assert_revision_at_head()
|
|
150
|
-
|
|
151
|
-
# --- Phase 3: the restored graph answers searches. ------------------
|
|
152
|
-
restored_results = await cognee.search(
|
|
153
|
-
query_type=SearchType.GRAPH_COMPLETION, query_text=QUERY, datasets=[dataset_name]
|
|
154
|
-
)
|
|
155
|
-
assert len(restored_results) != 0, "Search on the restored instance returned nothing."
|
|
156
|
-
logger.info("Restored search results: %s", restored_results)
|
|
157
|
-
|
|
158
|
-
# Chunk-level retrieval needs the imported DocumentChunk text to be
|
|
159
|
-
# vector-indexed (regression: rehydrated raw nodes lost their
|
|
160
|
-
# index_fields, so restored archives had no DocumentChunk_text
|
|
161
|
-
# collection and chunk/hybrid retrieval failed with NoDataError).
|
|
162
|
-
chunk_results = await cognee.search(
|
|
163
|
-
query_type=SearchType.CHUNKS, query_text="rooftop observatory", datasets=[dataset_name]
|
|
164
|
-
)
|
|
165
|
-
assert len(chunk_results) != 0, (
|
|
166
|
-
"Chunk search on the restored instance returned nothing — imported "
|
|
167
|
-
"DocumentChunk text was not vector-indexed."
|
|
168
|
-
)
|
|
169
|
-
|
|
170
|
-
print("COGX roundtrip e2e passed: export -> fresh store -> import -> search.")
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
if __name__ == "__main__":
|
|
174
|
-
asyncio.run(main())
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
"""Drift guard between PipelineContext and the COGX import ctx adaptation.
|
|
2
|
-
|
|
3
|
-
The COGX import path adapts the pipeline context before handing it to
|
|
4
|
-
``add_data_points`` (``_provenance_ctx`` in ``cognee/modules/migration/loader.py``).
|
|
5
|
-
A hand-copied field list there silently drops any parameter later added to
|
|
6
|
-
``PipelineContext`` — exactly how ``ctx.pipeline_run_id`` was lost, crashing
|
|
7
|
-
every preserve-mode import with AttributeError because ``add_data_points``
|
|
8
|
-
reads it unconditionally.
|
|
9
|
-
|
|
10
|
-
These tests introspect ``dataclasses.fields(PipelineContext)``, so they fail
|
|
11
|
-
for ANY field that does not survive the adaptation — adding a new parameter
|
|
12
|
-
to PipelineContext without carrying it through the cogx import path breaks
|
|
13
|
-
them by construction. Pure: no databases, no LLM calls, no network.
|
|
14
|
-
"""
|
|
15
|
-
|
|
16
|
-
import dataclasses
|
|
17
|
-
from types import SimpleNamespace
|
|
18
|
-
from uuid import uuid4
|
|
19
|
-
|
|
20
|
-
from cognee.modules.migration.loader import _provenance_ctx
|
|
21
|
-
from cognee.modules.pipelines.models.PipelineContext import PipelineContext
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
def _full_context() -> PipelineContext:
|
|
25
|
-
"""A PipelineContext with every field set to a distinct sentinel.
|
|
26
|
-
|
|
27
|
-
``data_item`` is DataItem-shaped (has ``data_id``, no ``id``) so
|
|
28
|
-
``_provenance_ctx`` takes its substitution path instead of returning the
|
|
29
|
-
context unchanged. Sentinels are per-field strings, so a swapped or
|
|
30
|
-
defaulted field cannot pass equality by accident.
|
|
31
|
-
"""
|
|
32
|
-
ctx = PipelineContext()
|
|
33
|
-
for context_field in dataclasses.fields(PipelineContext):
|
|
34
|
-
setattr(ctx, context_field.name, f"sentinel:{context_field.name}")
|
|
35
|
-
ctx.data_item = SimpleNamespace(data_id=uuid4())
|
|
36
|
-
return ctx
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
def test_every_pipeline_context_field_survives_adaptation():
|
|
40
|
-
ctx = _full_context()
|
|
41
|
-
|
|
42
|
-
adapted = _provenance_ctx(ctx)
|
|
43
|
-
|
|
44
|
-
assert adapted is not ctx, "expected the data_item substitution path, not the pass-through"
|
|
45
|
-
for context_field in dataclasses.fields(PipelineContext):
|
|
46
|
-
assert hasattr(adapted, context_field.name), (
|
|
47
|
-
f"PipelineContext.{context_field.name} does not survive the COGX import "
|
|
48
|
-
"ctx adaptation (_provenance_ctx in cognee/modules/migration/loader.py). "
|
|
49
|
-
"If you added a parameter to PipelineContext, the cogx import path must "
|
|
50
|
-
"carry it: task consumers such as add_data_points read ctx attributes "
|
|
51
|
-
"unconditionally (this is how pipeline_run_id regressed)."
|
|
52
|
-
)
|
|
53
|
-
if context_field.name == "data_item":
|
|
54
|
-
continue
|
|
55
|
-
assert getattr(adapted, context_field.name) == getattr(ctx, context_field.name), (
|
|
56
|
-
f"PipelineContext.{context_field.name} changed value across _provenance_ctx"
|
|
57
|
-
)
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
def test_data_item_id_substituted_from_data_id():
|
|
61
|
-
ctx = _full_context()
|
|
62
|
-
|
|
63
|
-
adapted = _provenance_ctx(ctx)
|
|
64
|
-
|
|
65
|
-
assert adapted.data_item.id == ctx.data_item.data_id
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
def test_passthrough_when_data_item_already_has_id():
|
|
69
|
-
ctx = PipelineContext(data_item=SimpleNamespace(id=uuid4()))
|
|
70
|
-
|
|
71
|
-
assert _provenance_ctx(ctx) is ctx
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
def test_none_ctx_stays_none():
|
|
75
|
-
assert _provenance_ctx(None) is None
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|