c889a57b6b
Test Suites / Build CI Environment (push) Has been cancelled
Test Suites / Basic Tests (push) Has been cancelled
Test Suites / End-to-End Tests (push) Has been cancelled
Test Suites / CLI Tests (push) Has been cancelled
Test Suites / Slow End-to-End Tests (push) Has been cancelled
Test Suites / Graph Database Tests (push) Has been cancelled
Test Suites / Vector DB Tests (push) Has been cancelled
Test Suites / Temporal Graph Test (push) Has been cancelled
Test Suites / Search Test on Different DBs (push) Has been cancelled
Test Suites / Example Tests (push) Has been cancelled
Test Suites / Notebook Tests (push) Has been cancelled
Test Suites / OS and Python Tests Ubuntu (push) Has been cancelled
Test Suites / OS and Python Tests Extended (push) Has been cancelled
Test Suites / LLM Test Suite (push) Has been cancelled
Test Suites / S3 File Storage Test (push) Has been cancelled
Test Suites / Run Integration Tests (push) Has been cancelled
Test Suites / MCP Tests (push) Has been cancelled
Test Suites / Docker Compose Test (push) Has been cancelled
Test Suites / Docker CI test (push) Has been cancelled
Test Suites / Relational DB Migration Tests (push) Has been cancelled
Test Suites / Distributed Cognee Test (push) Has been cancelled
Test Suites / DB Examples Tests (push) Has been cancelled
Test Suites / Test Completion Status (push) Has been cancelled
Test Suites / Claude Code Review (push) Has been cancelled
Test Suites / basic checks (push) Has been cancelled
build | Build and Push Cognee MCP Docker Image to dockerhub / docker-build-and-push (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
build | Build and Push Docker Image to dockerhub / docker-build-and-push (push) Has been cancelled
Weighted Edges Tests / Test Weighted Edges Core Functionality (3.11) (push) Has been cancelled
Weighted Edges Tests / Test Weighted Edges Core Functionality (3.12) (push) Has been cancelled
Weighted Edges Tests / Test Weighted Edges with Different Graph Databases (kuzu, kuzu) (push) Has been cancelled
Weighted Edges Tests / Test Weighted Edges with Different Graph Databases (neo4j, neo4j) (push) Has been cancelled
Weighted Edges Tests / Test Weighted Edges Examples (push) Has been cancelled
Weighted Edges Tests / Code Quality for Weighted Edges (push) Has been cancelled
194 lines
7.7 KiB
Python
194 lines
7.7 KiB
Python
"""SDK entry point: push a local dataset's knowledge graph to Cognee Cloud.
|
|
|
|
Bridges ``cognee.export(format="cogx")`` and the remote remember endpoint:
|
|
the dataset's graph is exported to a COGX archive, packed as a tarball, and
|
|
uploaded via :class:`CloudClient`, where the receiving instance imports it
|
|
through :class:`COGXArchiveSource` — preserving the local graph instead of
|
|
re-deriving it from raw files (which is what ``sync`` does).
|
|
|
|
Authentication reuses the ``serve`` stack: run ``cognee-cli serve`` (or
|
|
``await cognee.serve()``) once, and ``push`` picks up the saved credentials.
|
|
"""
|
|
|
|
import os
|
|
import tempfile
|
|
from dataclasses import dataclass
|
|
from pathlib import Path
|
|
from typing import Optional, Union
|
|
from uuid import UUID
|
|
|
|
from cognee.shared.logging_utils import get_logger
|
|
|
|
logger = get_logger("push")
|
|
|
|
|
|
@dataclass
|
|
class PushResult:
|
|
"""Outcome of a ``cognee.push()`` call."""
|
|
|
|
status: str
|
|
dataset_name: str
|
|
target_dataset: str
|
|
num_nodes: int
|
|
num_edges: int
|
|
remote_response: dict
|
|
# Remote migration pipeline run id; poll it when run_in_background=True.
|
|
pipeline_run_id: Optional[str] = None
|
|
|
|
def __repr__(self):
|
|
return (
|
|
f"PushResult(status={self.status!r}, dataset={self.dataset_name!r}, "
|
|
f"target={self.target_dataset!r}, nodes={self.num_nodes}, edges={self.num_edges}"
|
|
+ (f", pipeline_run_id={self.pipeline_run_id!r}" if self.pipeline_run_id else "")
|
|
+ ")"
|
|
)
|
|
|
|
|
|
def _resolve_client(url: Optional[str], api_key: Optional[str]):
|
|
"""Build or reuse a CloudClient. Returns ``(client, created)``.
|
|
|
|
Precedence (matching ``serve()``): explicit ``url`` argument → live
|
|
``serve()`` connection → ``COGNEE_SERVICE_URL`` / ``COGNEE_API_KEY``
|
|
environment variables → saved credentials from ``cognee-cli serve``.
|
|
"""
|
|
from cognee.api.v1.serve.cloud_client import CloudClient
|
|
from cognee.api.v1.serve.credentials import load_credentials
|
|
from cognee.api.v1.serve.state import get_remote_client
|
|
|
|
if url:
|
|
return CloudClient(url, api_key or os.getenv("COGNEE_API_KEY", "")), True
|
|
|
|
client = get_remote_client()
|
|
if client is not None:
|
|
return client, False
|
|
|
|
env_url = os.getenv("COGNEE_SERVICE_URL")
|
|
if env_url:
|
|
return CloudClient(env_url, api_key or os.getenv("COGNEE_API_KEY", "")), True
|
|
|
|
credentials = load_credentials()
|
|
if credentials and credentials.service_url:
|
|
return CloudClient(credentials.service_url, api_key or credentials.api_key), True
|
|
|
|
raise RuntimeError(
|
|
"No Cognee Cloud connection configured. Run `cognee-cli serve` to log in, "
|
|
"pass url/api_key, or set COGNEE_SERVICE_URL and COGNEE_API_KEY."
|
|
)
|
|
|
|
|
|
def _verify_migration_import(response: dict) -> None:
|
|
"""Ensure the remote server actually ran a COGX migration import.
|
|
|
|
Servers that predate COGX archive support accept the upload but ingest the
|
|
tarball as a regular file; their response lacks the ``migration_import``
|
|
item the import path always emits.
|
|
"""
|
|
items = response.get("items") or []
|
|
if not any(isinstance(item, dict) and item.get("kind") == "migration_import" for item in items):
|
|
raise RuntimeError(
|
|
"The remote server did not perform a COGX archive import — it likely runs an "
|
|
"older Cognee version without migration support. The uploaded archive was NOT "
|
|
"imported as a knowledge graph (it may have been ingested as a plain file). "
|
|
"Upgrade the remote instance, or use cognee.sync()/remember() with raw data."
|
|
)
|
|
|
|
|
|
async def push(
|
|
dataset: Union[str, UUID] = "main_dataset",
|
|
*,
|
|
target_dataset: Optional[str] = None,
|
|
mode: str = "preserve",
|
|
run_in_background: bool = False,
|
|
url: Optional[str] = None,
|
|
api_key: Optional[str] = None,
|
|
user=None,
|
|
) -> PushResult:
|
|
"""Upload a local dataset's knowledge graph to a Cognee Cloud instance.
|
|
|
|
Args:
|
|
dataset: Local dataset name or id. Requires read permission.
|
|
target_dataset: Dataset name on the remote instance; defaults to the
|
|
local dataset's name.
|
|
mode: Import fidelity on the remote side —
|
|
``"preserve"`` (default) maps the exported entities and facts
|
|
directly into the remote graph with zero LLM calls;
|
|
``"hybrid"`` also cognifies the raw content;
|
|
``"re-derive"`` ignores the exported graph and rebuilds from
|
|
raw content.
|
|
run_in_background: If True, the remote import is scheduled and the
|
|
call returns once the upload completes; poll the returned
|
|
``pipeline_run_id`` for progress. Recommended for large graphs.
|
|
url: Remote instance URL; falls back to the active ``serve()``
|
|
connection, ``COGNEE_SERVICE_URL``, or saved credentials.
|
|
api_key: API key; falls back like ``url``.
|
|
user: Local user context for the export; defaults to the default user.
|
|
|
|
Returns:
|
|
A :class:`PushResult` with the export counts, the remote pipeline run
|
|
id (when available), and the raw remote remember response.
|
|
"""
|
|
from cognee.api.v1.export.export import export
|
|
from cognee.modules.migration.archive import ARCHIVE_SUFFIX, pack_archive
|
|
from cognee.modules.migration.sources.base import IMPORT_MODES
|
|
from cognee.modules.observability import COGNEE_DATASET_NAME, new_span
|
|
from cognee.shared.utils import send_telemetry
|
|
|
|
if mode not in IMPORT_MODES:
|
|
raise ValueError(f"Unknown push mode {mode!r}. Expected one of {IMPORT_MODES}.")
|
|
|
|
client, created_client = _resolve_client(url, api_key)
|
|
|
|
with new_span("cognee.api.push") as span:
|
|
span.set_attribute(COGNEE_DATASET_NAME, str(dataset))
|
|
send_telemetry(
|
|
"cognee.push",
|
|
user or "sdk",
|
|
additional_properties={"mode": mode, "dataset": str(dataset)},
|
|
)
|
|
try:
|
|
with tempfile.TemporaryDirectory() as temporary_directory:
|
|
archive_dir = Path(temporary_directory) / "cogx"
|
|
result = await export(dataset, format="cogx", destination=archive_dir, user=user)
|
|
|
|
if result.num_nodes == 0:
|
|
raise ValueError(
|
|
f"Dataset {result.dataset_name!r} exported 0 nodes — nothing to push. "
|
|
"Run cognee.cognify() (or cognee.remember()) on the dataset first to "
|
|
"build its knowledge graph."
|
|
)
|
|
|
|
tar_path = Path(temporary_directory) / f"{result.dataset_name}{ARCHIVE_SUFFIX}"
|
|
pack_archive(archive_dir, tar_path)
|
|
|
|
logger.info(
|
|
"Pushing dataset %s (%d nodes, %d edges) to %s",
|
|
result.dataset_name,
|
|
result.num_nodes,
|
|
result.num_edges,
|
|
client.service_url,
|
|
)
|
|
|
|
with open(tar_path, "rb") as archive_file:
|
|
response = await client.remember(
|
|
archive_file,
|
|
dataset_name=target_dataset or result.dataset_name,
|
|
content_type="cogx-archive",
|
|
import_mode=mode,
|
|
run_in_background=run_in_background,
|
|
)
|
|
|
|
_verify_migration_import(response)
|
|
|
|
return PushResult(
|
|
status=str(response.get("status", "unknown")),
|
|
dataset_name=result.dataset_name,
|
|
target_dataset=target_dataset or result.dataset_name,
|
|
num_nodes=result.num_nodes,
|
|
num_edges=result.num_edges,
|
|
remote_response=response,
|
|
pipeline_run_id=response.get("pipeline_run_id"),
|
|
)
|
|
finally:
|
|
if created_client:
|
|
await client.close()
|