chore: import upstream snapshot with attribution
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
@@ -0,0 +1,114 @@
|
||||
# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json
|
||||
# .coderabbit.yaml
|
||||
language: en
|
||||
early_access: false
|
||||
enable_free_tier: true
|
||||
reviews:
|
||||
profile: chill
|
||||
instructions: >-
|
||||
# Code Review Instructions
|
||||
|
||||
- Ensure the code follows best practices and coding standards.
|
||||
- For **Python** code, follow
|
||||
[PEP 20](https://www.python.org/dev/peps/pep-0020/) and
|
||||
[CEP-8](https://gist.github.com/reactive-firewall/b7ee98df9e636a51806e62ef9c4ab161)
|
||||
standards.
|
||||
|
||||
# Documentation Review Instructions
|
||||
- Verify that documentation and comments are clear and comprehensive.
|
||||
- Verify that documentation and comments are free of spelling mistakes.
|
||||
|
||||
# Test Code Review Instructions
|
||||
- Ensure that test code is automated, comprehensive, and follows testing best practices.
|
||||
- Verify that all critical functionality is covered by tests.
|
||||
- Ensure that test code follow
|
||||
[CEP-8](https://gist.github.com/reactive-firewall/d840ee9990e65f302ce2a8d78ebe73f6)
|
||||
|
||||
# Misc.
|
||||
- Confirm that the code meets the project's requirements and objectives.
|
||||
- Confirm that copyright years are up-to date whenever a file is changed.
|
||||
request_changes_workflow: false
|
||||
high_level_summary: true
|
||||
high_level_summary_placeholder: '@coderabbitai summary'
|
||||
auto_title_placeholder: '@coderabbitai'
|
||||
review_status: true
|
||||
poem: false
|
||||
collapse_walkthrough: false
|
||||
sequence_diagrams: false
|
||||
changed_files_summary: true
|
||||
path_filters: ['!*.xc*/**', '!node_modules/**', '!dist/**', '!build/**', '!.git/**', '!venv/**', '!__pycache__/**']
|
||||
path_instructions:
|
||||
- path: README.md
|
||||
instructions: >-
|
||||
1. Consider the file 'README.md' the overview/introduction of the project.
|
||||
Also consider the 'README.md' file the first place to look for project documentation.
|
||||
|
||||
2. When reviewing the file 'README.md' it should be linted with help
|
||||
from the tools `markdownlint` and `languagetool`, pointing out any issues.
|
||||
|
||||
3. You may assume the file 'README.md' will contain GitHub flavor Markdown.
|
||||
- path: '**/*.py'
|
||||
instructions: >-
|
||||
When reviewing Python code for this project:
|
||||
|
||||
1. Prioritize portability over clarity, especially when dealing with cross-Python compatibility. However, with the priority in mind, do still consider improvements to clarity when relevant.
|
||||
|
||||
2. As a general guideline, consider the code style advocated in the PEP 8 standard (excluding the use of spaces for indentation) and evaluate suggested changes for code style compliance.
|
||||
|
||||
3. As a style convention, consider the code style advocated in [CEP-8](https://gist.github.com/reactive-firewall/b7ee98df9e636a51806e62ef9c4ab161) and evaluate suggested changes for code style compliance.
|
||||
|
||||
4. As a general guideline, try to provide any relevant, official, and supporting documentation links to any tool's suggestions in review comments. This guideline is important for posterity.
|
||||
|
||||
5. As a general rule, undocumented function definitions and class definitions in the project's Python code are assumed incomplete. Please consider suggesting a short summary of the code for any of these incomplete definitions as docstrings when reviewing.
|
||||
- path: cognee/tests/*
|
||||
instructions: >-
|
||||
When reviewing test code:
|
||||
|
||||
1. Prioritize portability over clarity, especially when dealing with cross-Python compatibility. However, with the priority in mind, do still consider improvements to clarity when relevant.
|
||||
|
||||
2. As a general guideline, consider the code style advocated in the PEP 8 standard (excluding the use of spaces for indentation) and evaluate suggested changes for code style compliance.
|
||||
|
||||
3. As a style convention, consider the code style advocated in [CEP-8](https://gist.github.com/reactive-firewall/b7ee98df9e636a51806e62ef9c4ab161) and evaluate suggested changes for code style compliance, pointing out any violations discovered.
|
||||
|
||||
4. As a general guideline, try to provide any relevant, official, and supporting documentation links to any tool's suggestions in review comments. This guideline is important for posterity.
|
||||
|
||||
5. As a project rule, Python source files with names prefixed by the string "test_" and located in the project's "tests" directory are the project's unit-testing code. It is safe, albeit a heuristic, to assume these are considered part of the project's minimal acceptance testing unless a justifying exception to this assumption is documented.
|
||||
|
||||
6. As a project rule, any files without extensions and with names prefixed by either the string "check_" or the string "test_", and located in the project's "tests" directory, are the project's non-unit test code. "Non-unit test" in this context refers to any type of testing other than unit testing, such as (but not limited to) functional testing, style linting, regression testing, etc. It can also be assumed that non-unit testing code is usually written as Bash shell scripts.
|
||||
- path: requirements.txt
|
||||
instructions: >-
|
||||
* The project's own Python dependencies are recorded in 'requirements.txt' for production code.
|
||||
|
||||
* The project's testing-specific Python dependencies are recorded in 'tests/requirements.txt' and are used for testing the project.
|
||||
|
||||
* The project's documentation-specific Python dependencies are recorded in 'docs/requirements.txt' and are used only for generating Python-focused documentation for the project. 'docs/requirements.txt' may be absent if not applicable.
|
||||
|
||||
Consider these 'requirements.txt' files the records of truth regarding project dependencies.
|
||||
- path: .github/**
|
||||
instructions: >-
|
||||
* When the project is hosted on GitHub: All GitHub-specific configurations, templates, and tools should be found in the '.github' directory tree.
|
||||
|
||||
* 'actionlint' erroneously generates false positives when dealing with GitHub's `${{ ... }}` syntax in conditionals.
|
||||
|
||||
* 'actionlint' erroneously generates incorrect solutions when suggesting the removal of valid `${{ ... }}` syntax.
|
||||
abort_on_close: true
|
||||
auto_review:
|
||||
enabled: true
|
||||
auto_incremental_review: true
|
||||
ignore_title_keywords: []
|
||||
labels: []
|
||||
drafts: false
|
||||
base_branches:
|
||||
- dev
|
||||
- main
|
||||
tools:
|
||||
shellcheck:
|
||||
enabled: true
|
||||
ruff:
|
||||
enabled: true
|
||||
markdownlint:
|
||||
enabled: true
|
||||
yamllint:
|
||||
enabled: true
|
||||
chat:
|
||||
auto_reply: true
|
||||
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"name": "Cognee Development",
|
||||
"image": "ghcr.io/astral-sh/uv:python3.12-bookworm",
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/git:1": {},
|
||||
"ghcr.io/devcontainers/features/docker-in-docker:2": {}
|
||||
},
|
||||
"postCreateCommand": "uv sync && cp cognee/.env.template cognee/.env && echo 'Set LLM_API_KEY in cognee/.env to get started'",
|
||||
"forwardPorts": [8000, 3000],
|
||||
"portsAttributes": {
|
||||
"8000": {"label": "Cognee API", "onAutoForward": "notify"},
|
||||
"3000": {"label": "Cognee UI", "onAutoForward": "notify"}
|
||||
},
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": [
|
||||
"ms-python.python",
|
||||
"ms-python.vscode-pylance",
|
||||
"charliermarsh.ruff"
|
||||
],
|
||||
"settings": {
|
||||
"python.defaultInterpreterPath": ".venv/bin/python"
|
||||
}
|
||||
}
|
||||
},
|
||||
"remoteEnv": {
|
||||
"PYTHONPATH": "/workspaces/cognee"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
bin
|
||||
dist
|
||||
docs
|
||||
evals
|
||||
tests
|
||||
tools
|
||||
assets
|
||||
notebooks
|
||||
cognee-frontend
|
||||
|
||||
examples/python/.dlt
|
||||
.venv
|
||||
.github
|
||||
|
||||
.idea
|
||||
.vscode
|
||||
@@ -0,0 +1,4 @@
|
||||
*
|
||||
!pyproject.toml
|
||||
!uv.lock
|
||||
!README.md
|
||||
@@ -0,0 +1,11 @@
|
||||
# Deprecated: use .env.template as the canonical environment template.
|
||||
#
|
||||
# To configure Cognee, copy .env.template to .env and fill in the values you need:
|
||||
#
|
||||
# cp .env.template .env
|
||||
#
|
||||
# This file is kept for backwards compatibility with older setup instructions.
|
||||
|
||||
LLM_API_KEY="your_api_key"
|
||||
LLM_MODEL="openai/gpt-5-mini"
|
||||
LLM_PROVIDER="openai"
|
||||
@@ -0,0 +1,629 @@
|
||||
###############################################################################
|
||||
# TIER 1 — QUICK START
|
||||
# Set this one variable and you're done. Everything else has working defaults.
|
||||
# Default databases (SQLite, LanceDB, KuzuDB) are file-based, no setup needed.
|
||||
###############################################################################
|
||||
LLM_API_KEY="your_api_key"
|
||||
|
||||
|
||||
###############################################################################
|
||||
# TIER 2 — COMMON OVERRIDES (uncomment to customize)
|
||||
# Most users only need a few of these.
|
||||
###############################################################################
|
||||
|
||||
# -- LLM Provider & Model ----------------------------------------------------
|
||||
#LLM_MODEL="openai/gpt-5-mini"
|
||||
#LLM_PROVIDER="openai"
|
||||
#LLM_ENDPOINT=""
|
||||
|
||||
# -- Embedding Provider -------------------------------------------------------
|
||||
#EMBEDDING_PROVIDER="openai"
|
||||
#EMBEDDING_MODEL="openai/text-embedding-3-large"
|
||||
#EMBEDDING_DIMENSIONS=3072
|
||||
|
||||
# -- Tokenizer (chunk sizing) -------------------------------------------------
|
||||
# The tokenizer used to count tokens for chunking is auto-selected to match the
|
||||
# embedding model: openai/gemini use TikToken, mistral uses the Mistral
|
||||
# tokenizer, and fastembed / openai-compatible models use the embedding model's
|
||||
# own HuggingFace tokenizer. cognee warns (and falls back to TikToken) when it
|
||||
# cannot match one, since a mismatched tokenizer mis-sizes chunks and skews the
|
||||
# --dry-run estimate. For providers whose model id is not a HuggingFace repo
|
||||
# (e.g. Ollama), set HUGGINGFACE_TOKENIZER to a tokenizer matching your model:
|
||||
#HUGGINGFACE_TOKENIZER="Salesforce/SFR-Embedding-Mistral"
|
||||
|
||||
# -- Database Providers (switch from file-based defaults) ---------------------
|
||||
#DB_PROVIDER="postgres"
|
||||
#DB_HOST=127.0.0.1
|
||||
#DB_PORT=5432
|
||||
#DB_USERNAME=cognee
|
||||
#DB_PASSWORD=cognee
|
||||
#DB_NAME=cognee_db
|
||||
|
||||
#GRAPH_DATABASE_PROVIDER="neo4j"
|
||||
#VECTOR_DB_PROVIDER="lancedb"
|
||||
|
||||
|
||||
###############################################################################
|
||||
# TIER 3 — ADVANCED (grouped by subsystem)
|
||||
# Most users never need to change anything below this line.
|
||||
###############################################################################
|
||||
|
||||
################################################################################
|
||||
# LLM — Advanced Settings
|
||||
# Tune these when switching providers, adjusting structured output, or
|
||||
# rate-limiting LLM calls.
|
||||
################################################################################
|
||||
|
||||
# Structured output framework: "instructor" (default, via litellm) or "baml"
|
||||
STRUCTURED_OUTPUT_FRAMEWORK="instructor"
|
||||
|
||||
# Instructor's mode determines how structured data is extracted from LLM responses.
|
||||
# Each LLM has its own default (e.g. gpt-5 models use "json_schema_mode").
|
||||
#LLM_INSTRUCTOR_MODE=""
|
||||
|
||||
# Cognee uses this to determine optimal chunk size (not forwarded in LLM calls).
|
||||
#LLM_MAX_COMPLETION_TOKENS="16384"
|
||||
|
||||
# LLM API version (needed for Azure OpenAI)
|
||||
#LLM_API_VERSION=""
|
||||
|
||||
# Extra kwargs passed to every LLM completion call (JSON string).
|
||||
# Examples: LLM_ARGS='{"max_tokens": 16384, "temperature": 0.7}'
|
||||
#LLM_ARGS='{}'
|
||||
|
||||
# LLM rate limiting
|
||||
#LLM_RATE_LIMIT_ENABLED=true
|
||||
#LLM_RATE_LIMIT_REQUESTS=60
|
||||
#LLM_RATE_LIMIT_INTERVAL=60
|
||||
|
||||
# Per-stage model routing (optional). Unset means the stage uses the base LLM_* config above.
|
||||
# Route a cheap or local model to extraction (it runs per chunk and dominates token use),
|
||||
# and keep a stronger model for summarization and query-time reasoning.
|
||||
#LLM_EXTRACTION_MODEL="ollama_chat/llama3.1"
|
||||
#LLM_EXTRACTION_PROVIDER="ollama"
|
||||
#LLM_EXTRACTION_ENDPOINT="http://localhost:11434"
|
||||
#LLM_EXTRACTION_API_KEY=""
|
||||
#LLM_SUMMARIZATION_MODEL="openai/gpt-5-mini"
|
||||
#LLM_SUMMARIZATION_PROVIDER="openai"
|
||||
#LLM_QUERY_MODEL="openai/gpt-5-mini"
|
||||
#LLM_QUERY_PROVIDER="openai"
|
||||
|
||||
################################################################################
|
||||
# Embedding — Advanced Settings
|
||||
# Tune these when using non-default embedding providers.
|
||||
################################################################################
|
||||
|
||||
#EMBEDDING_ENDPOINT=""
|
||||
#EMBEDDING_API_VERSION=""
|
||||
#EMBEDDING_MAX_COMPLETION_TOKENS=8191
|
||||
#EMBEDDING_BATCH_SIZE=36
|
||||
# If not provided, LLM_API_KEY is used for embeddings too.
|
||||
#EMBEDDING_API_KEY="your_api_key"
|
||||
|
||||
################################################################################
|
||||
# BAML Structured Output
|
||||
# Only needed when STRUCTURED_OUTPUT_FRAMEWORK="baml".
|
||||
################################################################################
|
||||
|
||||
#BAML_LLM_PROVIDER=openai
|
||||
#BAML_LLM_MODEL="gpt-5-mini"
|
||||
#BAML_LLM_ENDPOINT=""
|
||||
#BAML_LLM_API_KEY="your_api_key"
|
||||
#BAML_LLM_API_VERSION=""
|
||||
|
||||
################################################################################
|
||||
# Root Directories
|
||||
# Override where Cognee stores files and databases (default: .venv).
|
||||
################################################################################
|
||||
|
||||
#DATA_ROOT_DIRECTORY='/Users/<user>/Desktop/cognee/.cognee_data/'
|
||||
#SYSTEM_ROOT_DIRECTORY='/Users/<user>/Desktop/cognee/.cognee_system/'
|
||||
|
||||
################################################################################
|
||||
# Storage Backend
|
||||
# Switch from local filesystem to S3.
|
||||
################################################################################
|
||||
|
||||
#STORAGE_BACKEND="local"
|
||||
#STORAGE_BACKEND="s3"
|
||||
#STORAGE_BUCKET_NAME="your-bucket-name"
|
||||
#AWS_REGION="us-east-1"
|
||||
#AWS_ACCESS_KEY_ID="your-access-key"
|
||||
#AWS_SECRET_ACCESS_KEY="your-secret-key"
|
||||
#DATA_ROOT_DIRECTORY="s3://your-bucket/cognee/data"
|
||||
#SYSTEM_ROOT_DIRECTORY="s3://your-bucket/cognee/system"
|
||||
#CACHE_ROOT_DIRECTORY="s3://your-bucket/cognee/cache"
|
||||
|
||||
################################################################################
|
||||
# Relational Database — Advanced
|
||||
# Connection tuning, pool sizes, SSL.
|
||||
################################################################################
|
||||
|
||||
DB_PROVIDER="sqlite"
|
||||
DB_NAME=cognee_db
|
||||
|
||||
# Custom connection arguments (JSON). Useful for SSL, timeouts.
|
||||
#DATABASE_CONNECT_ARGS='{"sslmode": "require", "connect_timeout": 10}'
|
||||
|
||||
# Connection pool tuning (JSON).
|
||||
#POOL_ARGS='{"pool_size": 5, "max_overflow": 10, "pool_recycle": -1, "pool_timeout": 30}'
|
||||
|
||||
################################################################################
|
||||
# Graph Database — Advanced
|
||||
# Provider-specific connection details.
|
||||
################################################################################
|
||||
|
||||
GRAPH_DATABASE_PROVIDER="kuzu"
|
||||
# Handler for multi-user access control (per-dataset DB creation).
|
||||
GRAPH_DATASET_DATABASE_HANDLER="kuzu"
|
||||
|
||||
# Remote Kuzu
|
||||
#GRAPH_DATABASE_PROVIDER="kuzu-remote"
|
||||
#GRAPH_DATABASE_URL="http://localhost:8000"
|
||||
#GRAPH_DATABASE_USERNAME=XXX
|
||||
#GRAPH_DATABASE_PASSWORD=YYY
|
||||
|
||||
# Neo4j
|
||||
#GRAPH_DATABASE_PROVIDER="neo4j"
|
||||
#GRAPH_DATABASE_URL=bolt://localhost:7687
|
||||
#GRAPH_DATABASE_NAME="neo4j"
|
||||
#GRAPH_DATABASE_USERNAME=neo4j
|
||||
#GRAPH_DATABASE_PASSWORD=pleaseletmein
|
||||
|
||||
################################################################################
|
||||
# Vector Database — Advanced
|
||||
# Provider-specific connection details.
|
||||
################################################################################
|
||||
|
||||
# Supported (built-in): pgvector | lancedb
|
||||
# Community adapters (separate packages): qdrant | weaviate | milvus | chromadb
|
||||
VECTOR_DB_PROVIDER="lancedb"
|
||||
#VECTOR_DB_URL=
|
||||
#VECTOR_DB_KEY=
|
||||
# Handler for multi-user access control (per-dataset DB creation).
|
||||
VECTOR_DATASET_DATABASE_HANDLER="lancedb"
|
||||
|
||||
# Connection pool tuning for PGVector per-dataset engines (JSON).
|
||||
# When ENABLE_BACKEND_ACCESS_CONTROL=true each dataset gets its own engine; this controls
|
||||
# its pool size independently from POOL_ARGS (default: pool_size=2, max_overflow=2).
|
||||
#VECTOR_POOL_ARGS='{"pool_size": 2, "max_overflow": 5, "pool_recycle": 1800}'
|
||||
|
||||
################################################################################
|
||||
# Ontology Resolver
|
||||
# Use when grounding extraction against an OWL ontology.
|
||||
################################################################################
|
||||
|
||||
#ONTOLOGY_RESOLVER=rdflib
|
||||
#MATCHING_STRATEGY=fuzzy
|
||||
#ONTOLOGY_FILE_PATH=YOUR_FULL_FILE_PATH
|
||||
|
||||
################################################################################
|
||||
# Database Adapter Caching
|
||||
# Max graph / vector / relational engine instances held in the LRU cache
|
||||
# (one per unique connection key, e.g. per dataset in multi-tenant mode).
|
||||
# In subprocess mode, this also caps how many child processes (Kuzu/LanceDB
|
||||
# workers) can be alive at once — eviction shuts down the subprocess.
|
||||
# Also the default for DATASET_QUEUE_MAX_CONCURRENT when that is unset.
|
||||
# Engines of datasets currently admitted by the dataset queue are pinned and
|
||||
# never evicted by capacity pressure; when every entry is pinned the cache
|
||||
# briefly exceeds this size (bounded by DATASET_QUEUE_MAX_CONCURRENT).
|
||||
# Lower values save memory; raise when running many datasets concurrently.
|
||||
################################################################################
|
||||
|
||||
#DATABASE_MAX_LRU_CACHE_SIZE=6
|
||||
|
||||
################################################################################
|
||||
# Dataset Queue
|
||||
# Semaphore-backed queue that limits how many datasets can be processed at
|
||||
# once (cognify, search, etc.). Prevents resource exhaustion when many
|
||||
# datasets run in parallel. When the limit is reached, new datasets wait
|
||||
# until a slot is freed.
|
||||
################################################################################
|
||||
|
||||
#DATASET_QUEUE_ENABLED=true
|
||||
# Max concurrent dataset slots. Defaults to DATABASE_MAX_LRU_CACHE_SIZE.
|
||||
#DATASET_QUEUE_MAX_CONCURRENT=6
|
||||
|
||||
################################################################################
|
||||
# Translation
|
||||
# Use when ingesting non-English content.
|
||||
################################################################################
|
||||
|
||||
TRANSLATION_PROVIDER="llm"
|
||||
TARGET_LANGUAGE="en"
|
||||
CONFIDENCE_THRESHOLD=0.8
|
||||
#GOOGLE_TRANSLATE_API_KEY="your-google-api-key"
|
||||
#GOOGLE_PROJECT_ID="your-google-project-id"
|
||||
#AZURE_TRANSLATOR_KEY="your-azure-translator-key"
|
||||
#AZURE_TRANSLATOR_REGION="westeurope"
|
||||
#AZURE_TRANSLATOR_ENDPOINT="https://api.cognitive.microsofttranslator.com"
|
||||
#TRANSLATION_BATCH_SIZE=10
|
||||
#TRANSLATION_MAX_RETRIES=3
|
||||
#TRANSLATION_TIMEOUT_SECONDS=30
|
||||
|
||||
################################################################################
|
||||
# Data Migrations (graph/vector revision chain)
|
||||
################################################################################
|
||||
|
||||
# Cognee runs its data migrations automatically on startup (FastAPI lifespan,
|
||||
# first remember()/cognify() call in an SDK process). Set to false to disable
|
||||
# ALL automatic runs and migrate explicitly via `cognee-cli upgrade` instead
|
||||
# (e.g. operator-driven deployments, or tests on deliberately old-format data).
|
||||
#ENABLE_AUTO_MIGRATIONS=true
|
||||
|
||||
################################################################################
|
||||
# Migration (Relational -> Graph)
|
||||
################################################################################
|
||||
|
||||
MIGRATION_DB_PATH="/path/to/migration/directory"
|
||||
MIGRATION_DB_NAME="migration_database.sqlite"
|
||||
MIGRATION_DB_PROVIDER="sqlite"
|
||||
#MIGRATION_DB_USERNAME=cognee
|
||||
#MIGRATION_DB_PASSWORD=cognee
|
||||
#MIGRATION_DB_HOST="127.0.0.1"
|
||||
#MIGRATION_DB_PORT=5432
|
||||
|
||||
################################################################################
|
||||
# Security
|
||||
################################################################################
|
||||
|
||||
# -- JWT Authentication -------------------------------------------------------
|
||||
# Secret used to sign and verify JWT tokens. Must be the same across all instances
|
||||
# (e.g. all Kubernetes pods) for tokens issued by one instance to be accepted by another.
|
||||
# Change this to a long random string in production. Never commit the real value to git.
|
||||
FASTAPI_USERS_JWT_SECRET="super_secret"
|
||||
|
||||
# How long a JWT token remains valid, in seconds. After expiry the user must log in again.
|
||||
# The same lifetime applies to both cookie and bearer token auth.
|
||||
# Default: 3600 (1 hour)
|
||||
JWT_LIFETIME_SECONDS=3600
|
||||
|
||||
# -- API Key Authentication ---------------------------------------------------
|
||||
# When HASH_API_KEY=true, API keys are hashed with SHA-256 before being stored in the database.
|
||||
# This means the raw key is shown to the user only once at creation time and cannot be recovered.
|
||||
#
|
||||
# ⚠️ Migration note: if you enable this on a running system that already has API keys stored
|
||||
# in plaintext, those existing keys will stop working immediately because the lookup will
|
||||
# hash the incoming value and find no match. You must either:
|
||||
# 1. Delete and re-issue all existing API keys, or
|
||||
# 2. Write a one-off migration to SHA-256 hash the existing api_key column values.
|
||||
#
|
||||
# Default: false (keys are stored in plaintext)
|
||||
HASH_API_KEY="False"
|
||||
|
||||
# When set to false don't allow adding of local system files to Cognee. Should be set to False when Cognee is used as a backend.
|
||||
ACCEPT_LOCAL_FILE_PATH=True
|
||||
ALLOW_HTTP_REQUESTS=True
|
||||
ALLOW_CYPHER_QUERY=True
|
||||
RAISE_INCREMENTAL_LOADING_ERRORS=True
|
||||
|
||||
# Authentication & access control.
|
||||
#
|
||||
# ENABLE_BACKEND_ACCESS_CONTROL is the canonical posture switch:
|
||||
# true (default) - multi-tenant mode: per-user/dataset isolated DBs AND
|
||||
# API endpoints require an authenticated user.
|
||||
# false - single-user mode: shared DB AND auth requirement off.
|
||||
#
|
||||
# REQUIRE_AUTHENTICATION is an explicit override on the auth requirement only:
|
||||
# unset (default) - follow ENABLE_BACKEND_ACCESS_CONTROL.
|
||||
# true - force auth on (sane for single-user behind a token).
|
||||
# false - force auth off — IGNORED if ENABLE_BACKEND_ACCESS_CONTROL
|
||||
# is true (multi-tenant always requires auth; a warning is
|
||||
# logged at startup).
|
||||
#
|
||||
# Startup logs an "auth posture: ..." line with the resolved decision so you
|
||||
# can verify what's actually in effect.
|
||||
REQUIRE_AUTHENTICATION=False
|
||||
|
||||
# Set this variable to True to enforce usage of backend access control for Cognee
|
||||
# Note: This is only currently supported by the following databases:
|
||||
# Relational: SQLite, Postgres
|
||||
# Vector: LanceDB, pgvector
|
||||
# Graph: KuzuDB, neo4j_aura_dev
|
||||
#
|
||||
# It enforces creation of databases per Cognee user + dataset. Does not work with some graph and database providers.
|
||||
# Disable mode when using not supported graph/vector databases.
|
||||
ENABLE_BACKEND_ACCESS_CONTROL=True
|
||||
|
||||
################################################################################
|
||||
# Cloud Sync
|
||||
################################################################################
|
||||
|
||||
COGNEE_CLOUD_API_URL="http://localhost:8001"
|
||||
COGNEE_CLOUD_AUTH_TOKEN="your-api-key"
|
||||
|
||||
################################################################################
|
||||
# UI
|
||||
################################################################################
|
||||
|
||||
UI_APP_URL=http://localhost:3000
|
||||
|
||||
################################################################################
|
||||
# DLT Ingestion
|
||||
################################################################################
|
||||
|
||||
#DLT_MAX_ROWS_PER_TABLE=50
|
||||
|
||||
################################################################################
|
||||
# Dev / Debug
|
||||
################################################################################
|
||||
|
||||
ENV="local"
|
||||
#ENABLE_LAST_ACCESSED="false"
|
||||
TOKENIZERS_PARALLELISM="false"
|
||||
|
||||
# -- Search History ------------------------------------------------------------
|
||||
# Set to false to disable search query/result logging (recommended for daemons)
|
||||
#COGNEE_LOG_SEARCH_HISTORY="true"
|
||||
|
||||
# LITELLM Logging Level. Set to quiet down logging
|
||||
LITELLM_LOG="ERROR"
|
||||
#TELEMETRY_DISABLED=1
|
||||
#DEFAULT_USER_EMAIL=""
|
||||
#DEFAULT_USER_PASSWORD=""
|
||||
|
||||
# -- Cognee Logging -----------------------------------------------------------
|
||||
# Console log level: DEBUG, INFO, WARNING, ERROR, CRITICAL (default: INFO)
|
||||
#LOG_LEVEL="INFO"
|
||||
# Set to false to disable file logging entirely (console-only)
|
||||
#COGNEE_LOG_FILE="true"
|
||||
# Override the log directory (default: ~/.cognee/logs)
|
||||
#COGNEE_LOGS_DIR="/var/log/cognee"
|
||||
# Max size per log file before rotation, in bytes (default: 50 MB)
|
||||
#COGNEE_LOG_MAX_BYTES=52428800
|
||||
# Number of rotated log files to keep (default: 5 → 300 MB total cap)
|
||||
#COGNEE_LOG_BACKUP_COUNT=5
|
||||
|
||||
################################################################################
|
||||
# AWS
|
||||
################################################################################
|
||||
|
||||
#AWS_REGION=""
|
||||
#AWS_ENDPOINT_URL=""
|
||||
#AWS_ACCESS_KEY_ID=""
|
||||
#AWS_SECRET_ACCESS_KEY=""
|
||||
#AWS_SESSION_TOKEN=""
|
||||
|
||||
################################################################################
|
||||
# Web Scraper
|
||||
################################################################################
|
||||
|
||||
WEB_SCRAPER_TIMEOUT=15.0
|
||||
WEB_SCRAPER_MAX_DELAY=10.0
|
||||
|
||||
################################################################################
|
||||
# OpenTelemetry / Tracing
|
||||
################################################################################
|
||||
|
||||
# -- To export traces to an OTLP-compatible backend (Dash0, Grafana, Jaeger, etc.),
|
||||
# set the endpoint and optional auth headers: ---------------------
|
||||
# COGNEE_TRACING_ENABLED=true
|
||||
# OTEL_EXPORTER_OTLP_ENDPOINT="https://ingress.eu-west.dash0.com:4317"
|
||||
# OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer <your-token>"
|
||||
|
||||
# Override the service name reported in traces (default: "cognee")
|
||||
# OTEL_SERVICE_NAME="cognee"
|
||||
|
||||
# Add extra resource attributes (useful for Kubernetes, multi-instance deployments)
|
||||
# OTEL_RESOURCE_ATTRIBUTES="service.namespace=my-team,service.version=1.0"
|
||||
|
||||
# Session cache settings
|
||||
# To switch to Redis caching check our documentation page sessions-and-caching
|
||||
# CACHING=true
|
||||
# Backends: sqlite (default), postgres, redis, fs, tapes
|
||||
# CACHE_BACKEND=sqlite
|
||||
# CACHE_BACKEND=postgres
|
||||
# Optional explicit SQLAlchemy async URL for the sqlite/postgres backends.
|
||||
# sqlite default: cache.db next to the relational SQLite database.
|
||||
# postgres default: falls back to DB_* settings when DB_PROVIDER=postgres.
|
||||
# CACHE_DB_URL=sqlite+aiosqlite:///path/to/databases/cache.db
|
||||
# CACHE_DB_URL=postgresql+asyncpg://cognee:cognee@localhost:5432/cognee_db
|
||||
# Minimum seconds between global TTL purge sweeps (sqlite/postgres backends)
|
||||
# CACHE_PURGE_INTERVAL_SECONDS=900
|
||||
|
||||
|
||||
################################################################################
|
||||
# ADDITIONAL MANAGED SETTINGS (previously undocumented)
|
||||
# These are all read by Cognee's config classes (pydantic BaseSettings) but
|
||||
# were missing from this template. Defaults shown; uncomment to override.
|
||||
################################################################################
|
||||
|
||||
# -- LLM tuning ---------------------------------------------------------------
|
||||
#LLM_TEMPERATURE=0.0
|
||||
#LLM_STREAMING=false
|
||||
# Optional fallback model used when the primary completion fails.
|
||||
#FALLBACK_MODEL=""
|
||||
#FALLBACK_API_KEY=""
|
||||
#FALLBACK_ENDPOINT=""
|
||||
# Audio transcription model.
|
||||
#TRANSCRIPTION_MODEL="whisper-1"
|
||||
|
||||
# -- Embedding rate limiting (mirrors the LLM_RATE_LIMIT_* knobs) -------------
|
||||
#EMBEDDING_RATE_LIMIT_ENABLED=false
|
||||
#EMBEDDING_RATE_LIMIT_REQUESTS=60
|
||||
#EMBEDDING_RATE_LIMIT_INTERVAL=60
|
||||
#EMBEDDING_RATE_LIMIT_TOKENS=0
|
||||
# Token-based LLM limit (0 = disabled; requests/interval already documented above).
|
||||
#LLM_RATE_LIMIT_TOKENS=0
|
||||
|
||||
# -- Chunking -----------------------------------------------------------------
|
||||
#CHUNK_SIZE=1500
|
||||
#CHUNK_OVERLAP=10
|
||||
#CHUNK_STRATEGY="paragraph"
|
||||
|
||||
# -- Triplet embedding (extra triplet-level vectors during cognify) -----------
|
||||
#TRIPLET_EMBEDDING=false
|
||||
|
||||
# -- Session cache (Redis backend + session/usage tuning) ---------------------
|
||||
# Used when CACHE_BACKEND=redis; also the host/port for a remote cache.
|
||||
#CACHE_HOST="localhost"
|
||||
#CACHE_PORT=6379
|
||||
#CACHE_USERNAME=""
|
||||
#CACHE_PASSWORD=""
|
||||
# Session lifetime in the cache (default 7 days) and per-turn context cap.
|
||||
#SESSION_TTL_SECONDS=604800
|
||||
#MAX_SESSION_CONTEXT_CHARS=
|
||||
# Self-improvement: absorb per-turn feedback/guidance automatically (default on).
|
||||
#AUTO_FEEDBACK=true
|
||||
# Per-process LLM usage logging into the cache.
|
||||
#USAGE_LOGGING=false
|
||||
#USAGE_LOGGING_TTL=604800
|
||||
# Cross-process locks for file-based embedded graph backends.
|
||||
#SHARED_KUZU_LOCK=false
|
||||
#SHARED_LADYBUG_LOCK=false
|
||||
|
||||
# -- Graph database — advanced connection / Kuzu tuning -----------------------
|
||||
#GRAPH_DATABASE_HOST=""
|
||||
#GRAPH_DATABASE_PORT=
|
||||
#GRAPH_DATABASE_KEY=""
|
||||
#GRAPH_DATABASE_ALLOW_ANONYMOUS=false
|
||||
# Run the embedded graph engine (Kuzu/Ladybug) in a worker subprocess.
|
||||
#GRAPH_DATABASE_SUBPROCESS_ENABLED=true
|
||||
# Kuzu performance tuning (0/auto by default).
|
||||
#KUZU_NUM_THREADS=0
|
||||
#KUZU_BUFFER_POOL_SIZE=
|
||||
#KUZU_MAX_DB_SIZE=
|
||||
|
||||
# -- Vector database — advanced connection ------------------------------------
|
||||
#VECTOR_DB_HOST=""
|
||||
#VECTOR_DB_PORT=1234
|
||||
#VECTOR_DB_NAME=""
|
||||
#VECTOR_DB_USERNAME=""
|
||||
#VECTOR_DB_PASSWORD=""
|
||||
#VECTOR_DB_SUBPROCESS_ENABLED=true
|
||||
|
||||
# -- Database subprocess workers — advanced tuning ----------------------------
|
||||
# The embedded DB engines (Kuzu/Ladybug graph, LanceDB vector) run their native
|
||||
# client in a dedicated worker process. These knobs tune that harness.
|
||||
# Per-RPC deadline guarding against a hung native call (seconds; <=0 disables).
|
||||
#SUBPROCESS_CALL_TIMEOUT=300
|
||||
# How many times a failed subprocess RPC is retried (respawning the worker).
|
||||
#SUBPROCESS_MAX_RETRIES=2
|
||||
# Backstop for the brief window where one graph worker is still releasing a
|
||||
# file lock while another opens the same DB path: the worker retries the open
|
||||
# this many times, with exponential backoff starting at this many seconds
|
||||
# (per-attempt backoff is capped internally).
|
||||
#SUBPROCESS_OPEN_LOCK_RETRIES=10
|
||||
#SUBPROCESS_OPEN_LOCK_BACKOFF=0.1
|
||||
|
||||
# -- AWS / Bedrock extras (in addition to the AWS section above) --------------
|
||||
#AWS_PROFILE_NAME=""
|
||||
#AWS_BEDROCK_RUNTIME_ENDPOINT=""
|
||||
|
||||
# -- Local llama.cpp provider -------------------------------------------------
|
||||
#LLAMA_CPP_MODEL_PATH=""
|
||||
#LLAMA_CPP_N_CTX=2048
|
||||
#LLAMA_CPP_N_GPU_LAYERS=0
|
||||
#LLAMA_CPP_CHAT_FORMAT="chatml"
|
||||
|
||||
# -- Security: additional auth-token secrets ----------------------------------
|
||||
# Like FASTAPI_USERS_JWT_SECRET above, these default to the INSECURE value
|
||||
# "super_secret". Override BOTH with long random strings in production.
|
||||
#FASTAPI_USERS_VERIFICATION_TOKEN_SECRET="change_me_in_production"
|
||||
#FASTAPI_USERS_RESET_PASSWORD_TOKEN_SECRET="change_me_in_production"
|
||||
|
||||
|
||||
################################################################################
|
||||
# Docker / MCP Runtime
|
||||
# Configure the cognee API image (cognee/cognee) and the MCP image
|
||||
# (cognee/cognee-mcp) when running `docker run` / `docker compose`.
|
||||
# Unless noted "read by the app", these are consumed by the container
|
||||
# entrypoints/compose and have defaults baked into the images — set them only
|
||||
# to override. (docker-compose.yml already sets sensible values for most.)
|
||||
################################################################################
|
||||
|
||||
# -- API server (cognee/cognee image) ----------------------------------------
|
||||
# CORS allow-list for the FastAPI server: comma-separated origins. Read by the
|
||||
# app (cognee/api/client.py). Default '*' (all origins) — set explicit domains
|
||||
# in production.
|
||||
#CORS_ALLOWED_ORIGINS="https://yourdomain.com,https://another.com"
|
||||
# Server bind/port inside the container (entrypoint defaults shown).
|
||||
#HTTP_PORT=8000
|
||||
#BIND_ADDRESS=0.0.0.0
|
||||
|
||||
# -- MCP server (cognee/cognee-mcp image) -------------------------------------
|
||||
# Transport the MCP container serves. The Docker image reads TRANSPORT_MODE;
|
||||
# the direct `cognee-mcp` CLI uses --transport instead.
|
||||
#TRANSPORT_MODE=stdio # stdio | sse | http
|
||||
# Comma-separated optional extras to pip-install at container startup.
|
||||
#EXTRAS=aws,postgres
|
||||
# MCP "API mode": point the MCP server at an already-running cognee API server.
|
||||
#API_URL=http://localhost:8000
|
||||
#API_TOKEN=""
|
||||
# MCP "Cloud mode": point the MCP server at a managed Cognee Cloud instance.
|
||||
# These are the canonical cloud-connection variables, shared across serve(),
|
||||
# push(), the MCP server, and sync. COGNEE_CLOUD_API_URL / COGNEE_CLOUD_AUTH_TOKEN
|
||||
# (above) remain as deprecated fallbacks.
|
||||
#COGNEE_SERVICE_URL=""
|
||||
#COGNEE_API_KEY=""
|
||||
|
||||
# -- Debug (both images) ------------------------------------------------------
|
||||
# DEBUG=true together with ENV in {dev,local} starts the container under
|
||||
# debugpy, listening on DEBUG_PORT. ENV is the canonical environment variable
|
||||
# (set it in the Dev/Debug section above); ENVIRONMENT is a deprecated alias
|
||||
# still accepted by the container entrypoints.
|
||||
#DEBUG=false
|
||||
#DEBUG_PORT=5678
|
||||
|
||||
# -- Frontend (cognee-frontend image / compose `ui` profile) ------------------
|
||||
#NEXT_PUBLIC_BACKEND_API_URL=http://localhost:8000
|
||||
|
||||
|
||||
###############################################################################
|
||||
# TIER 4 — EXAMPLE PROVIDER OVERRIDES (commented out)
|
||||
# Uncomment + fill values to switch providers.
|
||||
###############################################################################
|
||||
|
||||
########## Azure OpenAI (API key auth) ########################################
|
||||
#LLM_PROVIDER="azure"
|
||||
#LLM_MODEL="azure/gpt-5-mini"
|
||||
#LLM_ENDPOINT="https://YOUR-RESOURCE.openai.azure.com"
|
||||
#LLM_API_KEY="your-azure-api-key"
|
||||
#LLM_API_VERSION="2024-12-01-preview"
|
||||
#LLM_MAX_COMPLETION_TOKENS="16384"
|
||||
|
||||
########## Azure OpenAI (managed identity / DefaultAzureCredential) ###########
|
||||
# Uses DefaultAzureCredential - no API key needed (for Azure VMs, App Service, etc.)
|
||||
# Requires: pip install azure-identity
|
||||
#LLM_PROVIDER="azure"
|
||||
#LLM_MODEL="azure/gpt-5-mini"
|
||||
#LLM_ENDPOINT="https://YOUR-RESOURCE.openai.azure.com"
|
||||
#LLM_API_VERSION="2024-12-01-preview"
|
||||
#LLM_AZURE_USE_MANAGED_IDENTITY=true
|
||||
|
||||
#EMBEDDING_MODEL="azure/text-embedding-3-large"
|
||||
#EMBEDDING_ENDPOINT="https://YOUR-RESOURCE.openai.azure.com/openai/deployments/text-embedding-3-large"
|
||||
#EMBEDDING_API_KEY="your-azure-api-key"
|
||||
#EMBEDDING_API_VERSION="2024-12-01-preview"
|
||||
#EMBEDDING_DIMENSIONS=3072
|
||||
#EMBEDDING_MAX_COMPLETION_TOKENS=8191
|
||||
|
||||
########## Local LLM via Ollama ###############################################
|
||||
#LLM_API_KEY ="ollama"
|
||||
#LLM_MODEL="llama3.1:8b"
|
||||
#LLM_PROVIDER="ollama"
|
||||
#LLM_ENDPOINT="http://localhost:11434/v1"
|
||||
#EMBEDDING_PROVIDER="ollama"
|
||||
#EMBEDDING_MODEL="nomic-embed-text:latest"
|
||||
#EMBEDDING_ENDPOINT="http://localhost:11434/api/embed"
|
||||
#EMBEDDING_DIMENSIONS=768
|
||||
#HUGGINGFACE_TOKENIZER="nomic-ai/nomic-embed-text-v1.5"
|
||||
|
||||
########## OpenRouter (also free) #############################################
|
||||
#LLM_API_KEY="<<go-get-one-yourself"
|
||||
#LLM_PROVIDER="custom"
|
||||
#LLM_MODEL="openrouter/google/gemini-2.0-flash-lite-preview-02-05:free"
|
||||
#LLM_ENDPOINT="https://openrouter.ai/api/v1"
|
||||
|
||||
########## DeepInfra ##########################################################
|
||||
#LLM_API_KEY="<<>>"
|
||||
#LLM_PROVIDER="custom"
|
||||
#LLM_MODEL="deepinfra/meta-llama/Meta-Llama-3-8B-Instruct"
|
||||
#LLM_ENDPOINT="https://api.deepinfra.com/v1/openai"
|
||||
#EMBEDDING_PROVIDER="openai"
|
||||
#EMBEDDING_API_KEY="<<>>"
|
||||
#EMBEDDING_MODEL="deepinfra/BAAI/bge-base-en-v1.5"
|
||||
#EMBEDDING_ENDPOINT=""
|
||||
#EMBEDDING_API_VERSION=""
|
||||
#EMBEDDING_DIMENSIONS=3072
|
||||
#EMBEDDING_MAX_COMPLETION_TOKENS=8191
|
||||
@@ -0,0 +1,5 @@
|
||||
# ignore jupyter notebooks in the language bar on github
|
||||
notebooks/** linguist-vendored
|
||||
|
||||
# Ensure shell scripts always use LF line endings (fixes Docker on Windows)
|
||||
*.sh text eol=lf
|
||||
@@ -0,0 +1,26 @@
|
||||
# .gitguardian.yml
|
||||
version: 2
|
||||
|
||||
secret:
|
||||
# Ignore specific file paths from scanning
|
||||
ignored-paths:
|
||||
- ".env.template"
|
||||
- ".github/workflows/*.yml"
|
||||
- "examples/**"
|
||||
- "tests/**"
|
||||
- "docker-compose.yml"
|
||||
- "deployment/helm/docker-compose-helm.yml"
|
||||
|
||||
# Ignore specific detector types (test/CI credentials, not real secrets)
|
||||
ignored-detectors:
|
||||
- generic_password
|
||||
- generic_high_entropy_secret
|
||||
|
||||
# Ignore specific known false-positive matches
|
||||
ignored-matches:
|
||||
- name: "CI test postgres credentials in e2e_tests.yml"
|
||||
match: "cognee"
|
||||
- name: "CI test postgres credentials in search_db_tests.yml"
|
||||
match: "cognee"
|
||||
- name: "Docker compose neo4j test password"
|
||||
match: "pleaseletmein"
|
||||
@@ -0,0 +1,71 @@
|
||||
# Code owners for the cognee repository.
|
||||
#
|
||||
# GitHub auto-requests reviews from these owners when a PR touches their paths.
|
||||
# Order matters: the LAST matching pattern wins. Keep most-specific rules at the
|
||||
# bottom.
|
||||
#
|
||||
# To update this file, please confirm the change with the affected owners
|
||||
# before merging. Tracking ticket: COG-4900.
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Default fallback — picked when no other rule matches.
|
||||
# -----------------------------------------------------------------------------
|
||||
* @Vasilije1990
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Public API surface (V1 + V2)
|
||||
# -----------------------------------------------------------------------------
|
||||
/cognee/api/v1/ @dexters1 @Vasilije1990
|
||||
/cognee/api/v1/cognify/ @dexters1
|
||||
/cognee/api/v1/remember/ @dexters1 @Vasilije1990
|
||||
/cognee/api/v1/recall/ @dexters1 @Vasilije1990
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Retrieval / memory tasks (V2 memory + agentic retrievers)
|
||||
# -----------------------------------------------------------------------------
|
||||
/cognee/modules/retrieval/ @hajdul88 @lxobr
|
||||
/cognee/tasks/memify/ @lxobr @hajdul88
|
||||
/cognee/tasks/temporal_awareness/ @lxobr @hajdul88
|
||||
/cognee/tasks/temporal_graph/ @lxobr @hajdul88
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Pipelines & tasks (the cognify ECL pipeline + composable tasks)
|
||||
# -----------------------------------------------------------------------------
|
||||
/cognee/pipelines/ @Vasilije1990
|
||||
/cognee/tasks/ @Vasilije1990 @siillee
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Infrastructure adapters
|
||||
# -----------------------------------------------------------------------------
|
||||
/cognee/infrastructure/databases/vector/ @siillee @dexters1
|
||||
/cognee/infrastructure/databases/graph/ @siillee
|
||||
/cognee/infrastructure/databases/graph/ladybug/ @siillee @hajdul88
|
||||
/cognee/infrastructure/databases/cache/ @Vasilije1990
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# MCP server
|
||||
# -----------------------------------------------------------------------------
|
||||
/cognee-mcp/ @Vasilije1990 @dexters1
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Frontend (Next.js UI)
|
||||
# -----------------------------------------------------------------------------
|
||||
/cognee-frontend/ @LStromann
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Build, packaging, CI
|
||||
# -----------------------------------------------------------------------------
|
||||
/Dockerfile @Vasilije1990
|
||||
/distributed/Dockerfile @Vasilije1990
|
||||
/.github/workflows/ @dexters1 @siillee
|
||||
/.github/actions/ @dexters1
|
||||
/pyproject.toml @Vasilije1990 @dexters1
|
||||
/uv.lock @Vasilije1990 @dexters1
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Contributor experience (this file, CONTRIBUTING.md, AGENTS.md, CLAUDE.md)
|
||||
# -----------------------------------------------------------------------------
|
||||
/.github/CODEOWNERS @Vasilije1990
|
||||
/CONTRIBUTING.md @Vasilije1990
|
||||
/AGENTS.md @Vasilije1990
|
||||
/CLAUDE.md @Vasilije1990
|
||||
@@ -0,0 +1,97 @@
|
||||
name: 🐛 Bug Report
|
||||
description: Report a bug or unexpected behavior
|
||||
title: "[Bug]: "
|
||||
labels: ["bug", "needs-triage"]
|
||||
assignees: []
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to fill out this bug report! Please provide a clear and detailed description.
|
||||
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Bug Description
|
||||
description: Please provide a clear and concise description of the bug. What happened vs what you expected?
|
||||
placeholder: Describe the bug in detail...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: reproduction
|
||||
attributes:
|
||||
label: Steps to Reproduce
|
||||
description: Please provide detailed steps to reproduce the issue
|
||||
placeholder: |
|
||||
1. Go to...
|
||||
2. Click on...
|
||||
3. See error...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: expected
|
||||
attributes:
|
||||
label: Expected Behavior
|
||||
description: What did you expect to happen?
|
||||
placeholder: Describe what you expected...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: actual
|
||||
attributes:
|
||||
label: Actual Behavior
|
||||
description: What actually happened?
|
||||
placeholder: Describe what actually happened...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: environment
|
||||
attributes:
|
||||
label: Environment
|
||||
description: Please provide your environment details
|
||||
placeholder: |
|
||||
- OS: [e.g. macOS 13.0, Ubuntu 20.04]
|
||||
- Python version: [e.g. 3.9.0]
|
||||
- Cognee version: [e.g. 0.1.0]
|
||||
- LLM Provider: [e.g. OpenAI, Ollama]
|
||||
- Database: [e.g. Neo4j]
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Logs/Error Messages
|
||||
description: Please include any relevant logs or error messages
|
||||
placeholder: Paste logs here...
|
||||
render: shell
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: additional
|
||||
attributes:
|
||||
label: Additional Context
|
||||
description: Add any other context about the problem here
|
||||
placeholder: Any additional information...
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: checkboxes
|
||||
id: checklist
|
||||
attributes:
|
||||
label: Pre-submission Checklist
|
||||
description: Please confirm the following before submitting
|
||||
options:
|
||||
- label: I have searched existing issues to ensure this bug hasn't been reported already
|
||||
required: true
|
||||
- label: I have provided a clear and detailed description of the bug
|
||||
required: true
|
||||
- label: I have included steps to reproduce the issue
|
||||
required: true
|
||||
- label: I have included my environment details
|
||||
required: true
|
||||
@@ -0,0 +1,8 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: 💬 Discord Community
|
||||
url: https://discord.gg/NQtRemgQVD
|
||||
about: Join our Discord community for questions, discussions, and support
|
||||
- name: 📖 Documentation
|
||||
url: https://docs.cognee.ai
|
||||
about: Check our documentation for guides and API references
|
||||
@@ -0,0 +1,73 @@
|
||||
name: 📚 Documentation Issue
|
||||
description: Report an issue with documentation or suggest documentation improvements
|
||||
title: "[Docs]: "
|
||||
labels: ["documentation", "needs-triage"]
|
||||
assignees: []
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for helping improve our documentation! Please provide details about the documentation issue or improvement.
|
||||
|
||||
- type: dropdown
|
||||
id: doc-type
|
||||
attributes:
|
||||
label: Documentation Type
|
||||
description: What type of documentation issue is this?
|
||||
options:
|
||||
- Missing documentation
|
||||
- Incorrect documentation
|
||||
- Unclear documentation
|
||||
- Documentation improvement
|
||||
- New documentation request
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: location
|
||||
attributes:
|
||||
label: Documentation Location
|
||||
description: Where is the documentation issue located? (URL, file path, section, etc.)
|
||||
placeholder: https://cognee.ai/docs/... or specific file/section
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: issue
|
||||
attributes:
|
||||
label: Issue Description
|
||||
description: Please describe the documentation issue or improvement needed
|
||||
placeholder: The documentation is unclear about...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: suggestion
|
||||
attributes:
|
||||
label: Suggested Improvement
|
||||
description: How would you improve this documentation?
|
||||
placeholder: I suggest changing this to...
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: additional
|
||||
attributes:
|
||||
label: Additional Context
|
||||
description: Add any other context about the documentation issue
|
||||
placeholder: Additional context...
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: checkboxes
|
||||
id: checklist
|
||||
attributes:
|
||||
label: Pre-submission Checklist
|
||||
description: Please confirm the following before submitting
|
||||
options:
|
||||
- label: I have searched existing issues to ensure this documentation issue hasn't been reported already
|
||||
required: true
|
||||
- label: I have provided a clear description of the documentation issue
|
||||
required: true
|
||||
- label: I have specified the location of the documentation issue
|
||||
required: true
|
||||
@@ -0,0 +1,77 @@
|
||||
name: 🚀 Feature Request
|
||||
description: Suggest a new feature or enhancement
|
||||
title: "[Feature]: "
|
||||
labels: ["enhancement", "needs-triage"]
|
||||
assignees: []
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for suggesting a new feature! Please provide a clear and detailed description of your idea.
|
||||
|
||||
- type: textarea
|
||||
id: problem
|
||||
attributes:
|
||||
label: Problem Statement
|
||||
description: Is your feature request related to a problem? Please describe the problem you're trying to solve.
|
||||
placeholder: I'm always frustrated when...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: solution
|
||||
attributes:
|
||||
label: Proposed Solution
|
||||
description: Describe the solution you'd like to see implemented
|
||||
placeholder: I would like to see...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: alternatives
|
||||
attributes:
|
||||
label: Alternatives Considered
|
||||
description: Describe any alternative solutions or features you've considered
|
||||
placeholder: I have also considered...
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: use-case
|
||||
attributes:
|
||||
label: Use Case
|
||||
description: Describe your specific use case and how this feature would help
|
||||
placeholder: This feature would help me...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: implementation
|
||||
attributes:
|
||||
label: Implementation Ideas
|
||||
description: If you have ideas about how this could be implemented, please share them
|
||||
placeholder: This could be implemented by...
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: additional
|
||||
attributes:
|
||||
label: Additional Context
|
||||
description: Add any other context, screenshots, or examples about the feature request
|
||||
placeholder: Additional context...
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: checkboxes
|
||||
id: checklist
|
||||
attributes:
|
||||
label: Pre-submission Checklist
|
||||
description: Please confirm the following before submitting
|
||||
options:
|
||||
- label: I have searched existing issues to ensure this feature hasn't been requested already
|
||||
required: true
|
||||
- label: I have provided a clear problem statement and proposed solution
|
||||
required: true
|
||||
- label: I have described my specific use case
|
||||
required: true
|
||||
@@ -0,0 +1,97 @@
|
||||
# Workflow Migration to Test Suites
|
||||
|
||||
This document explains how to ensure all test workflows are only run through the central test-suites.yml workflow.
|
||||
|
||||
## Why Migrate to Test Suites?
|
||||
|
||||
1. **Prevent Duplicate Runs**: Avoid running the same tests multiple times
|
||||
2. **Sequential Execution**: Ensure tests run in the correct order
|
||||
3. **Centralized Control**: Manage all tests from a single place
|
||||
4. **Resource Efficiency**: Run tests only when needed
|
||||
|
||||
## Automated Migration
|
||||
|
||||
We've provided a script to automatically convert individual workflows to only run when called by the test-suites.yml file:
|
||||
|
||||
```bash
|
||||
# Make the script executable
|
||||
chmod +x .github/workflows/disable_independent_workflows.sh
|
||||
|
||||
# Run the script
|
||||
.github/workflows/disable_independent_workflows.sh
|
||||
```
|
||||
|
||||
## Manual Migration
|
||||
|
||||
For each workflow file that should only run through test-suites.yml:
|
||||
|
||||
1. Open the workflow file
|
||||
2. Find the `on:` section, which typically looks like:
|
||||
```yaml
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
types: [labeled, synchronize]
|
||||
```
|
||||
|
||||
3. Replace it with:
|
||||
```yaml
|
||||
on:
|
||||
workflow_call:
|
||||
secrets:
|
||||
inherit: true
|
||||
```
|
||||
|
||||
4. Save the file
|
||||
|
||||
## Verification
|
||||
|
||||
After modifying the workflows, verify that:
|
||||
|
||||
1. The workflows no longer trigger on pushes or PRs
|
||||
2. The workflows still run correctly when called by test-suites.yml
|
||||
3. No tests are left out of the test-suites.yml orchestrator
|
||||
|
||||
## Example Conversion
|
||||
|
||||
**Before:**
|
||||
```yaml
|
||||
name: test | chromadb
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
types: [labeled, synchronize]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
run_chromadb_integration_test:
|
||||
name: chromadb test
|
||||
runs-on: ubuntu-22.04
|
||||
# ...rest of workflow...
|
||||
```
|
||||
|
||||
**After:**
|
||||
```yaml
|
||||
name: test | chromadb
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
secrets:
|
||||
inherit: true
|
||||
|
||||
jobs:
|
||||
run_chromadb_integration_test:
|
||||
name: chromadb test
|
||||
runs-on: ubuntu-22.04
|
||||
# ...rest of workflow...
|
||||
```
|
||||
|
||||
## Special Cases
|
||||
|
||||
- **CI/CD Workflows**: Don't modify workflows for CI/CD pipelines like cd.yaml and cd_prd.yaml
|
||||
- **Shared Workflows**: Keep reusable_*.yml workflows as they are, since they're already designed to be called by other workflows
|
||||
- **Infrastructure Workflows**: Don't modify workflows that handle infrastructure or deployments
|
||||
@@ -0,0 +1,80 @@
|
||||
name: cognee-setup
|
||||
description: "Sets up Python, installs uv, and installs dependencies for Cognee."
|
||||
|
||||
inputs:
|
||||
python-version:
|
||||
description: "Which Python version to use"
|
||||
required: false
|
||||
default: "3.11.x"
|
||||
extra-dependencies:
|
||||
description: "Additional extra dependencies to install (space-separated)"
|
||||
required: false
|
||||
default: ""
|
||||
rebuild-lockfile:
|
||||
description: "Whether to rebuild the uv lockfile"
|
||||
required: false
|
||||
default: "false"
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
|
||||
- name: Detect CI container
|
||||
id: detect-env
|
||||
shell: bash
|
||||
run: |
|
||||
if [ -f "/app/.anon_id" ] && command -v uv &> /dev/null && [ -d "/app/.venv" ]; then
|
||||
echo "in-container=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "in-container=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
- name: Set up Python
|
||||
if: steps.detect-env.outputs.in-container != 'true'
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ inputs.python-version }}
|
||||
|
||||
- name: Install uv
|
||||
if: steps.detect-env.outputs.in-container != 'true'
|
||||
uses: astral-sh/setup-uv@v4
|
||||
with:
|
||||
enable-cache: true
|
||||
|
||||
- name: Rebuild uv lockfile
|
||||
if: ${{ inputs.rebuild-lockfile == 'true' }}
|
||||
shell: bash
|
||||
run: |
|
||||
rm uv.lock
|
||||
uv lock
|
||||
|
||||
- name: Install dependencies (bare runner)
|
||||
if: steps.detect-env.outputs.in-container != 'true'
|
||||
shell: bash
|
||||
run: |
|
||||
EXTRA_ARGS=""
|
||||
if [ -n "${{ inputs.extra-dependencies }}" ]; then
|
||||
IFS=' ' read -r -a deps <<< "${{ inputs.extra-dependencies }}"
|
||||
for extra in "${deps[@]}"; do
|
||||
EXTRA_ARGS="$EXTRA_ARGS --extra $extra"
|
||||
done
|
||||
fi
|
||||
uv sync --extra api --extra docs --extra evals --extra codegraph --extra ollama --extra dev --extra neo4j --extra redis --extra tracing $EXTRA_ARGS
|
||||
|
||||
- name: Install dependencies (container - link project only)
|
||||
if: steps.detect-env.outputs.in-container == 'true'
|
||||
shell: bash
|
||||
env:
|
||||
UV_PROJECT_ENVIRONMENT: /app/.venv
|
||||
run: |
|
||||
# Persist for all subsequent steps so uv run uses /app/.venv
|
||||
echo "UV_PROJECT_ENVIRONMENT=/app/.venv" >> "$GITHUB_ENV"
|
||||
# Install project into the pre-built venv; --inexact keeps pre-installed extras intact
|
||||
uv sync --frozen --inexact
|
||||
# Prevent uv run from re-syncing and stripping extras
|
||||
echo "UV_NO_SYNC=true" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Add telemetry identifier for telemetry test and in case telemetry is enabled by accident
|
||||
shell: bash
|
||||
run: |
|
||||
echo "test-machine" > .anon_id
|
||||
@@ -0,0 +1,35 @@
|
||||
name: 'Build Docker images for Cognee'
|
||||
description: 'Build cognee-related Docker images and push to the Docker registry (AWS ECR)'
|
||||
inputs:
|
||||
stage:
|
||||
description: 'The stage of the pipeline, such as "dev" or "prd", for the Cognee app'
|
||||
required: true
|
||||
aws_account_id:
|
||||
description: 'The AWS account ID for the Cognee app'
|
||||
required: true
|
||||
should_publish:
|
||||
description: 'Whether to publish the Cognee Docker image to AWS ECR; should be either "true" or "false"'
|
||||
required: true
|
||||
ecr_image_repo_name:
|
||||
description: 'The Docker image ECR repository name for the Cognee app, such as "workflows"'
|
||||
required: true
|
||||
dockerfile_location:
|
||||
description: 'The directory location of the Dockerfile for the Cognee app'
|
||||
required: true
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Build PromethAI App Docker image
|
||||
shell: bash
|
||||
env:
|
||||
STAGE: ${{ inputs.stage }}
|
||||
run: |
|
||||
export SHA_SHORT="$(git rev-parse --short HEAD)"
|
||||
export CUR_DATE="$(date +%Y%m%d%H%M%S)"
|
||||
export VERSION="${{ inputs.stage }}-$CUR_DATE-$SHA_SHORT"
|
||||
export STAGE="${{ inputs.stage }}"
|
||||
export APP_DIR="$PWD/${{ inputs.dockerfile_location }}"
|
||||
image_name="${{ inputs.ecr_image_repo_name }}" version="$VERSION" account="${{ inputs.aws_account_id }}" app_dir="$APP_DIR" publish="${{ inputs.should_publish }}" ./bin/dockerize
|
||||
echo "Docker tag is: $VERSION"
|
||||
echo $VERSION > /tmp/.DOCKER_IMAGE_VERSION
|
||||
@@ -0,0 +1,55 @@
|
||||
name: install_cognee
|
||||
description: "Installs Cognee from local source or PyPI depending on specified version"
|
||||
|
||||
inputs:
|
||||
python-version:
|
||||
description: "Which Python version to use"
|
||||
required: false
|
||||
default: "3.11.x"
|
||||
cognee_version:
|
||||
description: "Pypi-compatible version of cognee to use. For example, 0.5.2.dev0. `local` (default) - Installing Cognee from local source"
|
||||
required: false
|
||||
default: "local"
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
|
||||
- name: Detect CI container
|
||||
id: detect-env
|
||||
shell: bash
|
||||
run: |
|
||||
if [ -f "/app/.anon_id" ] && command -v uv &> /dev/null && [ -d "/app/.venv" ]; then
|
||||
echo "in-container=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "in-container=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
- name: Set up Python
|
||||
if: steps.detect-env.outputs.in-container != 'true'
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ inputs.python-version }}
|
||||
|
||||
- name: Install uv
|
||||
if: steps.detect-env.outputs.in-container != 'true'
|
||||
uses: astral-sh/setup-uv@v4
|
||||
with:
|
||||
enable-cache: true
|
||||
|
||||
- name: (Re)Install Cognee
|
||||
shell: bash
|
||||
working-directory: cognee-mcp
|
||||
env:
|
||||
VIRTUAL_ENV: ${{ steps.detect-env.outputs.in-container == 'true' && '/app/.venv' || '' }}
|
||||
run: |
|
||||
uv pip uninstall cognee
|
||||
if [ "${{ inputs.cognee_version }}" = "local" ]; then
|
||||
echo "Installing Cognee from local source ..."
|
||||
uv pip install --force-reinstall -e ../
|
||||
else
|
||||
echo "Installing Cognee version ${{ inputs.cognee_version }} from PyPI..."
|
||||
uv pip install --force-reinstall "cognee==${{ inputs.cognee_version }}"
|
||||
fi
|
||||
echo "Installed Cognee version:"
|
||||
uv pip show cognee | grep Version
|
||||
@@ -0,0 +1,67 @@
|
||||
name: 'Setup Neo4j with Graph Data Science'
|
||||
description: 'Sets up a Neo4j instance with APOC and Graph Data Science plugins for testing'
|
||||
inputs:
|
||||
neo4j-version:
|
||||
description: 'Neo4j version to use'
|
||||
required: false
|
||||
default: '5.21'
|
||||
neo4j-password:
|
||||
description: 'Password for Neo4j'
|
||||
required: false
|
||||
default: 'cognee_test_password'
|
||||
outputs:
|
||||
neo4j-url:
|
||||
description: 'Neo4j connection URL'
|
||||
value: 'bolt://localhost:7687'
|
||||
neo4j-username:
|
||||
description: 'Neo4j username'
|
||||
value: 'neo4j'
|
||||
neo4j-password:
|
||||
description: 'Neo4j password'
|
||||
value: ${{ inputs.neo4j-password }}
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- name: Start Neo4j with GDS
|
||||
shell: bash
|
||||
run: |
|
||||
docker run -d \
|
||||
--name neo4j-test \
|
||||
-p 7474:7474 -p 7687:7687 \
|
||||
-e NEO4J_AUTH="neo4j/${{ inputs.neo4j-password }}" \
|
||||
-e NEO4J_PLUGINS='["apoc", "graph-data-science"]' \
|
||||
-e NEO4J_dbms_security_procedures_unrestricted="apoc.*,gds.*" \
|
||||
-e NEO4J_apoc_export_file_enabled=true \
|
||||
-e NEO4J_apoc_import_file_enabled=true \
|
||||
neo4j:${{ inputs.neo4j-version }}
|
||||
|
||||
- name: Wait for Neo4j to be ready
|
||||
shell: bash
|
||||
run: |
|
||||
echo "Waiting for Neo4j to start..."
|
||||
timeout=60
|
||||
counter=0
|
||||
|
||||
while [ $counter -lt $timeout ]; do
|
||||
if docker exec neo4j-test cypher-shell -u neo4j -p "${{ inputs.neo4j-password }}" "RETURN 1" > /dev/null 2>&1; then
|
||||
echo "Neo4j is ready!"
|
||||
break
|
||||
fi
|
||||
echo "Waiting... ($counter/$timeout)"
|
||||
sleep 2
|
||||
counter=$((counter + 2))
|
||||
done
|
||||
|
||||
if [ $counter -ge $timeout ]; then
|
||||
echo "Neo4j failed to start within $timeout seconds"
|
||||
docker logs neo4j-test
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Verify GDS is available
|
||||
shell: bash
|
||||
run: |
|
||||
echo "Verifying Graph Data Science library is available..."
|
||||
docker exec neo4j-test cypher-shell -u neo4j -p "${{ inputs.neo4j-password }}" \
|
||||
"CALL gds.version() YIELD gdsVersion RETURN gdsVersion"
|
||||
echo "GDS verification complete!"
|
||||
@@ -0,0 +1,11 @@
|
||||
# Core team GitHub logins (one per line). Lines may begin with @; case-insensitive.
|
||||
borisarzentar
|
||||
daukadolt
|
||||
dexters1
|
||||
hajdul88
|
||||
hande-k
|
||||
lxobr
|
||||
pazone
|
||||
siillee
|
||||
vasilije1990
|
||||
NMZivkovic
|
||||
@@ -0,0 +1,33 @@
|
||||
## How to make a release
|
||||
|
||||
### Dev release
|
||||
|
||||
#### Prepare release
|
||||
1. Set the project version that will be released in [pyproject.toml](https://github.com/topoteretes/cognee/blob/dev/pyproject.toml#L4)
|
||||
2. Update `uv.lock` with `uv lock` lock command
|
||||
3. Update `poetry.lock` by deleting the `poetry.lock` file first and then running the `poetry lock` command. This is required to update the `poetry.lock` file with the new version of the dependencies, otherwise it does not properly update and mostly uses the cached dependency versions in the existing `poetry.lock` file.
|
||||
4. Create a PR with the changes mentioned above to `dev` and merge it.
|
||||
|
||||
#### Perform Release
|
||||
1. Go to [Release action](https://github.com/topoteretes/cognee/actions/workflows/release.yml)
|
||||
2. Select `dev` branch and run the workflow.
|
||||
3. Watch the logs and make sure that everything goes well
|
||||
|
||||
### Main release
|
||||
|
||||
#### Prepare release
|
||||
1. Set the project version that will be released in [pyproject.toml](https://github.com/topoteretes/cognee/blob/dev/pyproject.toml#L4)
|
||||
2. Update `uv.lock` with `uv lock` lock command
|
||||
3. Update `poetry.lock` by deleting the `poetry.lock` file first and then running the `poetry lock` command. This is required to update the `poetry.lock` file with the new version of the dependencies, otherwise it does not properly update and mostly uses the cached dependency versions in the existing `poetry.lock` file.
|
||||
4. Create a PR with the changes mentioned above to `main` and merge it.
|
||||
|
||||
#### Perform Release
|
||||
1. Go to [Release action](https://github.com/topoteretes/cognee/actions/workflows/release.yml)
|
||||
2. Select `main` branch and run the workflow.
|
||||
3. Watch the logs and make sure that everything goes well
|
||||
|
||||
### Release validation
|
||||
|
||||
1. Make sure that the correct image is published to [Docker Hub](https://hub.docker.com/r/cognee/cognee)
|
||||
2. Python package is published to [PyPi](https://pypi.org/project/cognee/)
|
||||
3. Find the created github release in [GitHub releases](https://github.com/topoteretes/cognee/releases). Edit/prettify the release notes if required.
|
||||
@@ -0,0 +1,34 @@
|
||||
You are a documentation improvement agent for the Cognee project.
|
||||
|
||||
Update the existing Cognee documentation to reflect this merged PR. Your job is to document the actual behavior and API changes introduced by this PR, not to make adjacent or generic documentation improvements.
|
||||
|
||||
## Required inputs
|
||||
|
||||
Read these first:
|
||||
|
||||
- Documentation scope plan
|
||||
- Branch notes
|
||||
- Documentation assessment
|
||||
|
||||
## Available resources
|
||||
|
||||
- **Documentation repo** (`./docs-repo`): Contains the documentation pages. Use existing `.md` and `.mdx` pages as the primary targets for edits. Read `./docs-repo/docs.json` only if the scope plan requires navigation context.
|
||||
- **Cognee source code** (current workspace root): Use the source code to verify actual implementation details, defaults, supported options, function signatures, env vars, and behavior.
|
||||
|
||||
## Editing rules
|
||||
|
||||
1. Follow the documentation scope plan.
|
||||
2. If the scope plan says `Docs Needed` is `false`, make no documentation edits and print the reason.
|
||||
3. Inspect only the source files listed in the scope plan unless they are insufficient to verify a specific planned edit.
|
||||
4. Edit only docs files listed in the scope plan unless they are clearly the wrong target; if so, choose the smallest better existing docs target.
|
||||
5. Document only user-facing behavior, public API changes, examples, or developer-facing semantics that actually changed in this PR.
|
||||
6. If a proposed docs edit cannot be traced back to a concrete source diff in this PR, do not make that edit.
|
||||
7. Do not present pre-existing behavior as if this PR introduced it.
|
||||
8. Do not make unrelated cleanup edits, style edits, or generic improvements.
|
||||
9. Edit at most 3 documentation files unless the scope plan explicitly justifies more.
|
||||
10. Prefer updating existing pages over creating new ones.
|
||||
11. Do not edit `docs.json` unless the scope plan says a new docs page is strictly required.
|
||||
12. Only edit documentation files inside `./docs-repo`. Do NOT modify the source repository files, workflow files, or non-documentation assets.
|
||||
13. Do NOT create git commits.
|
||||
|
||||
When done, print a short summary of what you changed and which existing documentation pages you updated.
|
||||
@@ -0,0 +1,46 @@
|
||||
You are a documentation scope planner for the Cognee project.
|
||||
|
||||
Analyze this merged PR and produce a small documentation edit plan. Do not edit documentation files.
|
||||
|
||||
## Available resources
|
||||
|
||||
- **Documentation repo** (`./docs-repo`): Contains the documentation pages. Use existing `.md` and `.mdx` pages as the primary targets for edits. Read `./docs-repo/docs.json` if it exists to understand the documentation structure.
|
||||
- **Cognee source code** (current workspace root): Use the source code to verify actual implementation details, defaults, supported options, function signatures, env vars, and behavior.
|
||||
- **Prepared documentation edit scope**: Curated source files, docs candidates, documentation signals, assessment summary, and out-of-scope files produced by the workflow.
|
||||
|
||||
## Planning task
|
||||
|
||||
1. Read the prepared documentation edit scope first.
|
||||
2. Use the prepared scope as your primary evidence. Do not re-classify the full PR changed-file list.
|
||||
3. Read only the source files listed in `Source Files To Inspect` unless one listed file is insufficient to verify a specific planned edit.
|
||||
4. Read only the documentation files listed in `Candidate Documentation Files` unless they are clearly the wrong target.
|
||||
5. Do not run shell commands or inspect the full diff. If the prepared scope is still too broad, produce a conservative small plan instead of exploring further.
|
||||
6. Treat files listed in `Out Of Scope Files` as skipped unless one is explicitly needed to verify a planned edit.
|
||||
7. Identify the smallest docs edit surface that could cover the public-facing changes.
|
||||
|
||||
Write the final plan to the scope plan output path provided by the workflow prompt.
|
||||
|
||||
The plan must be Markdown with these exact sections:
|
||||
|
||||
# Documentation Scope Plan
|
||||
|
||||
## Docs Needed
|
||||
`true` or `false`
|
||||
|
||||
## Reason
|
||||
One concise paragraph.
|
||||
|
||||
## Documentation-Worthy Changes
|
||||
Bullets. Each bullet must name the change, the source files proving it, and the recommended docs page type.
|
||||
|
||||
## Files To Edit
|
||||
Bullets of existing docs files to edit. Use paths relative to `docs-repo`. Leave empty if none.
|
||||
|
||||
## Source Files To Inspect During Editing
|
||||
Bullets of source files the editing step should inspect. Keep this list short and exclude tests/assets/lockfiles.
|
||||
|
||||
## Out Of Scope
|
||||
Bullets for changes intentionally skipped.
|
||||
|
||||
Do not edit files inside `./docs-repo`.
|
||||
Do not create commits.
|
||||
@@ -0,0 +1,38 @@
|
||||
<!-- .github/pull_request_template.md -->
|
||||
|
||||
## Description
|
||||
<!--
|
||||
Please provide a clear, human-generated description of the changes in this PR.
|
||||
DO NOT use AI-generated descriptions. We want to understand your thought process and reasoning.
|
||||
-->
|
||||
|
||||
## Acceptance Criteria
|
||||
<!--
|
||||
* Key requirements to the new feature or modification;
|
||||
* Proof that the changes work and meet the requirements;
|
||||
-->
|
||||
|
||||
## Type of Change
|
||||
<!-- Please check the relevant option -->
|
||||
- [ ] Bug fix (non-breaking change that fixes an issue)
|
||||
- [ ] New feature (non-breaking change that adds functionality)
|
||||
- [ ] Code refactoring
|
||||
- [ ] Other (please specify):
|
||||
|
||||
## Screenshots
|
||||
<!-- ADD SCREENSHOT OF LOCAL TESTS PASSING-->
|
||||
|
||||
## Pre-submission Checklist
|
||||
<!-- Please check all boxes that apply before submitting your PR -->
|
||||
- [ ] **I have tested my changes thoroughly before submitting this PR** (See `CONTRIBUTING.md`)
|
||||
- [ ] **This PR contains minimal changes necessary to address the issue/feature**
|
||||
- [ ] My code follows the project's coding standards and style guidelines
|
||||
- [ ] I have added tests that prove my fix is effective or that my feature works
|
||||
- [ ] I have added necessary documentation (if applicable)
|
||||
- [ ] All new and existing tests pass
|
||||
- [ ] I have searched existing PRs to ensure this change hasn't been submitted already
|
||||
- [ ] I have linked any relevant issues in the description
|
||||
- [ ] My commits have clear and descriptive messages
|
||||
|
||||
## DCO Affirmation
|
||||
I affirm that all code in every commit of this pull request conforms to the terms of the Topoteretes Developer Certificate of Origin.
|
||||
@@ -0,0 +1,20 @@
|
||||
name-template: 'v$NEXT_PATCH_VERSION'
|
||||
tag-template: 'v$NEXT_PATCH_VERSION'
|
||||
|
||||
categories:
|
||||
- title: 'Features'
|
||||
labels: ['feature', 'enhancement']
|
||||
- title: 'Bug Fixes'
|
||||
labels: ['bug', 'fix']
|
||||
- title: 'Maintenance'
|
||||
labels: ['chore', 'refactor', 'ci']
|
||||
|
||||
change-template: '- $TITLE (#$NUMBER) @$AUTHOR'
|
||||
template: |
|
||||
## What’s Changed
|
||||
|
||||
$CHANGES
|
||||
|
||||
## Contributors
|
||||
|
||||
$CONTRIBUTORS
|
||||
@@ -0,0 +1,291 @@
|
||||
name: Reusable Adapter Caching Tests
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: read
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
databases:
|
||||
required: false
|
||||
type: string
|
||||
default: "all"
|
||||
description: "Which provider combos to test (comma-separated list or 'all')"
|
||||
python-version:
|
||||
required: false
|
||||
type: string
|
||||
default: '3.11.x'
|
||||
description: "Python version to test"
|
||||
ci-image:
|
||||
required: false
|
||||
type: string
|
||||
default: ''
|
||||
description: "Container image for CI (empty string means no container)"
|
||||
secrets:
|
||||
LLM_MODEL:
|
||||
required: true
|
||||
LLM_ENDPOINT:
|
||||
required: true
|
||||
LLM_API_KEY:
|
||||
required: true
|
||||
LLM_ARGS:
|
||||
required: false
|
||||
LLM_API_VERSION:
|
||||
required: true
|
||||
EMBEDDING_MODEL:
|
||||
required: true
|
||||
EMBEDDING_API_KEY:
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
run-ladybug-lance-sqlite-caching:
|
||||
name: Adapter caching — Ladybug + LanceDB + Sqlite
|
||||
runs-on: ubuntu-22.04
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
if: ${{ inputs.databases == 'all' || contains(inputs.databases, 'ladybug/lance/sqlite') }}
|
||||
steps:
|
||||
- name: Check out
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: ${{ inputs.python-version }}
|
||||
|
||||
- name: Run adapter caching test
|
||||
env:
|
||||
ENV: 'dev'
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
GRAPH_DATABASE_PROVIDER: 'ladybug'
|
||||
VECTOR_DB_PROVIDER: 'lancedb'
|
||||
DB_PROVIDER: 'sqlite'
|
||||
run: uv run python ./cognee/tests/test_adapter_object_caching.py
|
||||
|
||||
run-neo4j-lance-sqlite-caching:
|
||||
name: Adapter caching — Neo4j + LanceDB + Sqlite
|
||||
runs-on: ubuntu-22.04
|
||||
if: ${{ inputs.databases == 'all' || contains(inputs.databases, 'neo4j/lance/sqlite') }}
|
||||
steps:
|
||||
- name: Check out
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: ${{ inputs.python-version }}
|
||||
|
||||
- name: Setup Neo4j with GDS
|
||||
uses: ./.github/actions/setup_neo4j
|
||||
id: neo4j
|
||||
|
||||
- name: Run adapter caching test
|
||||
env:
|
||||
ENV: 'dev'
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
GRAPH_DATABASE_PROVIDER: 'neo4j'
|
||||
VECTOR_DB_PROVIDER: 'lancedb'
|
||||
DB_PROVIDER: 'sqlite'
|
||||
ENABLE_BACKEND_ACCESS_CONTROL: 'false'
|
||||
GRAPH_DATABASE_URL: ${{ steps.neo4j.outputs.neo4j-url }}
|
||||
GRAPH_DATABASE_USERNAME: ${{ steps.neo4j.outputs.neo4j-username }}
|
||||
GRAPH_DATABASE_PASSWORD: ${{ steps.neo4j.outputs.neo4j-password }}
|
||||
run: uv run python ./cognee/tests/test_adapter_object_caching.py
|
||||
|
||||
run-ladybug-pgvector-postgres-caching:
|
||||
name: Adapter caching — Ladybug + PGVector + Postgres
|
||||
runs-on: ubuntu-22.04
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
if: ${{ inputs.databases == 'all' || contains(inputs.databases, 'ladybug/pgvector/postgres') }}
|
||||
services:
|
||||
postgres:
|
||||
image: ghcr.io/topoteretes/pgvector:pg17
|
||||
credentials:
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
env:
|
||||
POSTGRES_USER: cognee
|
||||
POSTGRES_PASSWORD: cognee
|
||||
POSTGRES_DB: cognee_db
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
ports:
|
||||
- 5432:5432
|
||||
steps:
|
||||
- name: Check out
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: ${{ inputs.python-version }}
|
||||
extra-dependencies: "postgres"
|
||||
|
||||
- name: Run adapter caching test
|
||||
env:
|
||||
ENV: 'dev'
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
GRAPH_DATABASE_PROVIDER: 'ladybug'
|
||||
VECTOR_DB_PROVIDER: 'pgvector'
|
||||
ENABLE_BACKEND_ACCESS_CONTROL: 'false'
|
||||
DB_PROVIDER: 'postgres'
|
||||
DB_NAME: 'cognee_db'
|
||||
DB_HOST: ${{ inputs.ci-image != '' && 'postgres' || '127.0.0.1' }}
|
||||
DB_PORT: 5432
|
||||
DB_USERNAME: cognee
|
||||
DB_PASSWORD: cognee
|
||||
run: uv run python ./cognee/tests/test_adapter_object_caching.py
|
||||
|
||||
run-neo4j-pgvector-postgres-caching:
|
||||
name: Adapter caching — Neo4j + PGVector + Postgres
|
||||
runs-on: ubuntu-22.04
|
||||
if: ${{ inputs.databases == 'all' || contains(inputs.databases, 'neo4j/pgvector/postgres') }}
|
||||
services:
|
||||
postgres:
|
||||
image: ghcr.io/topoteretes/pgvector:pg17
|
||||
credentials:
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
env:
|
||||
POSTGRES_USER: cognee
|
||||
POSTGRES_PASSWORD: cognee
|
||||
POSTGRES_DB: cognee_db
|
||||
ports:
|
||||
- 5432:5432
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries=5
|
||||
steps:
|
||||
- name: Check out
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: ${{ inputs.python-version }}
|
||||
extra-dependencies: "postgres"
|
||||
|
||||
- name: Setup Neo4j with GDS
|
||||
uses: ./.github/actions/setup_neo4j
|
||||
id: neo4j
|
||||
|
||||
- name: Run adapter caching test
|
||||
env:
|
||||
ENV: 'dev'
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
GRAPH_DATABASE_PROVIDER: 'neo4j'
|
||||
VECTOR_DB_PROVIDER: 'pgvector'
|
||||
DB_PROVIDER: 'postgres'
|
||||
ENABLE_BACKEND_ACCESS_CONTROL: 'false'
|
||||
GRAPH_DATABASE_URL: ${{ steps.neo4j.outputs.neo4j-url }}
|
||||
GRAPH_DATABASE_USERNAME: ${{ steps.neo4j.outputs.neo4j-username }}
|
||||
GRAPH_DATABASE_PASSWORD: ${{ steps.neo4j.outputs.neo4j-password }}
|
||||
DB_NAME: cognee_db
|
||||
DB_HOST: 127.0.0.1
|
||||
DB_PORT: 5432
|
||||
DB_USERNAME: cognee
|
||||
DB_PASSWORD: cognee
|
||||
run: uv run python ./cognee/tests/test_adapter_object_caching.py
|
||||
|
||||
run-postgres-pgvector-postgres-caching:
|
||||
name: Adapter caching — Postgres graph + PGVector + Postgres (access control)
|
||||
runs-on: ubuntu-22.04
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
if: ${{ inputs.databases == 'all' || contains(inputs.databases, 'postgres/pgvector/postgres') }}
|
||||
services:
|
||||
postgres:
|
||||
image: ghcr.io/topoteretes/pgvector:pg17
|
||||
credentials:
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
env:
|
||||
POSTGRES_USER: cognee
|
||||
POSTGRES_PASSWORD: cognee
|
||||
POSTGRES_DB: cognee_db
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
ports:
|
||||
- 5432:5432
|
||||
steps:
|
||||
- name: Check out
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: ${{ inputs.python-version }}
|
||||
extra-dependencies: "postgres"
|
||||
|
||||
- name: Run adapter caching test
|
||||
env:
|
||||
ENV: 'dev'
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
# Access control mode: every dataset gets its own physical Postgres
|
||||
# database (named after the deterministic dataset id) that is created
|
||||
# on add and dropped on delete — the engine-cache lifecycle across
|
||||
# that drop/recreate boundary is what this job guards.
|
||||
ENABLE_BACKEND_ACCESS_CONTROL: 'true'
|
||||
DB_PROVIDER: 'postgres'
|
||||
DB_NAME: 'cognee_db'
|
||||
DB_HOST: ${{ inputs.ci-image != '' && 'postgres' || '127.0.0.1' }}
|
||||
DB_PORT: 5432
|
||||
DB_USERNAME: cognee
|
||||
DB_PASSWORD: cognee
|
||||
VECTOR_DB_PROVIDER: 'pgvector'
|
||||
VECTOR_DB_NAME: 'cognee_db'
|
||||
VECTOR_DB_HOST: ${{ inputs.ci-image != '' && 'postgres' || '127.0.0.1' }}
|
||||
VECTOR_DB_PORT: 5432
|
||||
VECTOR_DB_USERNAME: cognee
|
||||
VECTOR_DB_PASSWORD: cognee
|
||||
VECTOR_DATASET_DATABASE_HANDLER: 'pgvector'
|
||||
GRAPH_DATABASE_PROVIDER: 'postgres'
|
||||
GRAPH_DATABASE_NAME: 'cognee_db'
|
||||
GRAPH_DATABASE_HOST: ${{ inputs.ci-image != '' && 'postgres' || '127.0.0.1' }}
|
||||
GRAPH_DATABASE_PORT: 5432
|
||||
GRAPH_DATABASE_USERNAME: cognee
|
||||
GRAPH_DATABASE_PASSWORD: cognee
|
||||
GRAPH_DATASET_DATABASE_HANDLER: 'postgres_graph'
|
||||
run: uv run python ./cognee/tests/test_adapter_object_caching.py
|
||||
@@ -0,0 +1,40 @@
|
||||
name: community | DCO Check
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, edited, reopened, synchronize, ready_for_review]
|
||||
|
||||
jobs:
|
||||
check-dco:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Validate Developer Certificate of Origin statement
|
||||
uses: actions/github-script@v8
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
const prUser = context.payload.pull_request.user.login;
|
||||
const prBody = context.payload.pull_request.body || '';
|
||||
const authorAssociation = context.payload.pull_request.author_association;
|
||||
|
||||
// Exact text you require in the PR body
|
||||
const requiredStatement = "I affirm that all code in every commit of this pull request conforms to the terms of the Topoteretes Developer Certificate of Origin";
|
||||
|
||||
// 1. Check if user is an org member via author_association
|
||||
// (available on the PR payload without extra API calls or permissions)
|
||||
// OWNER, MEMBER, and COLLABORATOR are trusted roles.
|
||||
const trustedRoles = ['OWNER', 'MEMBER', 'COLLABORATOR', 'CONTRIBUTOR'];
|
||||
const isTrusted = trustedRoles.includes(authorAssociation);
|
||||
|
||||
if (isTrusted) {
|
||||
console.log(`${prUser} has association '${authorAssociation}'. Skipping DCO check.`);
|
||||
} else {
|
||||
console.log(`${prUser} has association '${authorAssociation}'. Enforcing DCO check.`);
|
||||
|
||||
// 2. If user is not trusted, enforce the DCO statement
|
||||
if (!prBody.includes(requiredStatement)) {
|
||||
core.setFailed(
|
||||
`DCO check failed. The PR body must include the following statement:\n\n${requiredStatement}`
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
name: build test | Docker image
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
env:
|
||||
AWS_ACCOUNT_ID_DEV: "463722570299"
|
||||
COGNEE_SKIP_CONNECTION_TEST: 'true'
|
||||
|
||||
jobs:
|
||||
|
||||
build_docker:
|
||||
name: Build Cognee Backend Docker App Image
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Check out Cognee code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Build Cognee Docker image
|
||||
id: cognee-docker-tag
|
||||
run: |
|
||||
export SHA_SHORT="$(git rev-parse --short HEAD)"
|
||||
export CUR_DATE="$(date +%Y%m%d%H%M%S)"
|
||||
export VERSION="dev-$CUR_DATE-$SHA_SHORT"
|
||||
image_name="cognee" docker_login="false" version="$VERSION" account="${{ env.AWS_ACCOUNT_ID_DEV }}" app_dir="." publish="false" ./bin/dockerize
|
||||
export DOCKER_TAG=$(cat /tmp/.DOCKER_IMAGE_VERSION)
|
||||
echo "Successfully built cognee Docker image. Tag is: $DOCKER_TAG"
|
||||
@@ -0,0 +1,139 @@
|
||||
name: Reusable Basic Tests
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
python-version:
|
||||
required: false
|
||||
type: string
|
||||
default: '3.11.x'
|
||||
ci-image:
|
||||
required: false
|
||||
type: string
|
||||
default: ''
|
||||
secrets:
|
||||
LLM_PROVIDER:
|
||||
required: true
|
||||
LLM_MODEL:
|
||||
required: true
|
||||
LLM_ENDPOINT:
|
||||
required: true
|
||||
LLM_API_KEY:
|
||||
required: true
|
||||
LLM_ARGS:
|
||||
required: false
|
||||
LLM_API_VERSION:
|
||||
required: true
|
||||
EMBEDDING_PROVIDER:
|
||||
required: true
|
||||
EMBEDDING_MODEL:
|
||||
required: true
|
||||
EMBEDDING_API_KEY:
|
||||
required: true
|
||||
|
||||
env:
|
||||
RUNTIME__LOG_LEVEL: ERROR
|
||||
ENV: 'dev'
|
||||
COGNEE_SKIP_CONNECTION_TEST: 'true'
|
||||
|
||||
jobs:
|
||||
unit-tests:
|
||||
name: Run Unit Tests
|
||||
runs-on: ubuntu-22.04
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
env:
|
||||
ENV: 'dev'
|
||||
LLM_PROVIDER: openai
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
|
||||
EMBEDDING_PROVIDER: openai
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: ${{ inputs.python-version }}
|
||||
|
||||
- name: Run Unit Tests
|
||||
run: uv run pytest cognee/tests/unit/ --timeout=300 --timeout-method=thread
|
||||
|
||||
simple-examples:
|
||||
name: Run Simple Examples
|
||||
runs-on: ubuntu-22.04
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
env:
|
||||
ENV: 'dev'
|
||||
LLM_PROVIDER: openai
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
|
||||
EMBEDDING_PROVIDER: openai
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: ${{ inputs.python-version }}
|
||||
|
||||
- name: Run Simple Examples
|
||||
run: uv run python ./examples/demos/simple_cognee_example.py
|
||||
|
||||
simple-examples-baml:
|
||||
name: Run Simple Examples BAML
|
||||
runs-on: ubuntu-22.04
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
env:
|
||||
ENV: 'dev'
|
||||
STRUCTURED_OUTPUT_FRAMEWORK: "BAML"
|
||||
BAML_LLM_PROVIDER: openai
|
||||
BAML_LLM_MODEL: ${{ secrets.OPENAI_MODEL }}
|
||||
BAML_LLM_ENDPOINT: ${{ secrets.OPENAI_ENDPOINT }}
|
||||
BAML_LLM_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
# BAML_LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
|
||||
LLM_PROVIDER: openai
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
|
||||
EMBEDDING_PROVIDER: openai
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: ${{ inputs.python-version }}
|
||||
extra-dependencies: "baml"
|
||||
|
||||
- name: Run Simple Examples
|
||||
run: uv run python ./examples/demos/simple_cognee_example.py
|
||||
@@ -0,0 +1,32 @@
|
||||
name: clean | remove stale PRs
|
||||
|
||||
on:
|
||||
# Run this action periodically (daily at 0:00 UTC).
|
||||
schedule:
|
||||
- cron: "0 0 * * *"
|
||||
# Optionally, also run when pull requests are labeled, unlabeled, synchronized, or reopened
|
||||
# to update the stale timer as needed. Uncomment if desired.
|
||||
# pull_request:
|
||||
# types: [labeled, unlabeled, synchronize, reopened]
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Mark and Close Stale PRs
|
||||
uses: actions/stale@v10
|
||||
with:
|
||||
# Number of days of inactivity before the pull request is marked stale
|
||||
days-before-stale: 60
|
||||
# Number of days of inactivity after being marked stale before the pull request is closed
|
||||
days-before-close: 7
|
||||
# Comment to post when marking as stale
|
||||
stale-pr-message: "This pull request has been automatically marked as stale due to inactivity. It will be closed in 7 days if no further activity occurs."
|
||||
# Comment to post when closing a stale pull request
|
||||
close-pr-message: "This pull request has been closed due to prolonged inactivity."
|
||||
# Labels for stale and closed PRs
|
||||
stale-pr-label: "stale"
|
||||
exempt-pr-labels: "keep-open"
|
||||
@@ -0,0 +1,171 @@
|
||||
name: test | cli
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
python-version:
|
||||
required: false
|
||||
type: string
|
||||
default: '3.11.x'
|
||||
cognee_version:
|
||||
required: false
|
||||
type: string
|
||||
default: "local"
|
||||
description: "Pypi-compatible version of cognee to use. For example, 0.5.2.dev0. `local` (default) - Installing Cognee from local source"
|
||||
ci-image:
|
||||
required: false
|
||||
type: string
|
||||
default: ''
|
||||
secrets:
|
||||
LLM_PROVIDER:
|
||||
required: true
|
||||
LLM_MODEL:
|
||||
required: true
|
||||
LLM_ENDPOINT:
|
||||
required: true
|
||||
LLM_API_KEY:
|
||||
required: true
|
||||
LLM_ARGS:
|
||||
required: false
|
||||
LLM_API_VERSION:
|
||||
required: true
|
||||
EMBEDDING_PROVIDER:
|
||||
required: true
|
||||
EMBEDDING_MODEL:
|
||||
required: true
|
||||
EMBEDDING_API_KEY:
|
||||
required: true
|
||||
|
||||
env:
|
||||
RUNTIME__LOG_LEVEL: ERROR
|
||||
ENV: 'dev'
|
||||
COGNEE_SKIP_CONNECTION_TEST: 'true'
|
||||
|
||||
jobs:
|
||||
cli-unit-tests:
|
||||
name: CLI Unit Tests
|
||||
if: ${{ inputs.cognee_version == 'local' }}
|
||||
runs-on: ubuntu-22.04
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
env:
|
||||
ENV: 'dev'
|
||||
LLM_PROVIDER: openai
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: ${{ inputs.python-version }}
|
||||
|
||||
- name: Run CLI Unit Tests
|
||||
run: uv run pytest cognee/tests/cli_tests/cli_unit_tests/ -v
|
||||
|
||||
cli-integration-tests:
|
||||
name: CLI Integration Tests
|
||||
runs-on: ubuntu-22.04
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
env:
|
||||
ENV: 'dev'
|
||||
LLM_PROVIDER: openai
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: ${{ inputs.python-version }}
|
||||
|
||||
- name: Install Cognee
|
||||
uses: ./.github/actions/install_cognee
|
||||
with:
|
||||
python-version: ${{ inputs.python-version }}
|
||||
cognee_version: ${{ inputs.cognee_version }}
|
||||
|
||||
- name: Run CLI Integration Tests
|
||||
run: uv run pytest cognee/tests/cli_tests/cli_integration_tests/ -v
|
||||
|
||||
cli-functionality-tests:
|
||||
name: CLI Functionality Tests
|
||||
runs-on: ubuntu-22.04
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
env:
|
||||
ENV: 'dev'
|
||||
LLM_PROVIDER: openai
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: ${{ inputs.python-version }}
|
||||
|
||||
- name: Install Cognee
|
||||
uses: ./.github/actions/install_cognee
|
||||
with:
|
||||
python-version: ${{ inputs.python-version }}
|
||||
cognee_version: ${{ inputs.cognee_version }}
|
||||
|
||||
- name: Test CLI Help Commands
|
||||
run: |
|
||||
uv run python -m cognee.cli._cognee --help
|
||||
uv run python -m cognee.cli._cognee --version
|
||||
uv run python -m cognee.cli._cognee add --help
|
||||
uv run python -m cognee.cli._cognee search --help
|
||||
uv run python -m cognee.cli._cognee cognify --help
|
||||
uv run python -m cognee.cli._cognee delete --help
|
||||
uv run python -m cognee.cli._cognee config --help
|
||||
|
||||
- name: Test CLI Config Subcommands
|
||||
run: |
|
||||
uv run python -m cognee.cli._cognee config get --help
|
||||
uv run python -m cognee.cli._cognee config set --help
|
||||
uv run python -m cognee.cli._cognee config list --help
|
||||
uv run python -m cognee.cli._cognee config unset --help
|
||||
uv run python -m cognee.cli._cognee config reset --help
|
||||
|
||||
- name: Test CLI Error Handling
|
||||
run: |
|
||||
# Test invalid command (should fail gracefully)
|
||||
! uv run python -m cognee.cli._cognee invalid_command
|
||||
|
||||
# Test missing required arguments (should fail gracefully)
|
||||
! uv run python -m cognee.cli._cognee search
|
||||
|
||||
# Test invalid search type (should fail gracefully)
|
||||
! uv run python -m cognee.cli._cognee search "test" --query-type INVALID_TYPE
|
||||
|
||||
# Test invalid chunker (should fail gracefully)
|
||||
! uv run python -m cognee.cli._cognee cognify --chunker InvalidChunker
|
||||
@@ -0,0 +1,25 @@
|
||||
name: community | Greetings
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened]
|
||||
pull_request_target:
|
||||
types: [opened]
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
greeting:
|
||||
if: github.actor != 'github-actions[bot]' && github.actor != 'dependabot[bot]' && !contains(github.event.pull_request.body, 'Generated with [Claude Code]')
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/first-interaction@v3
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
pr_message: 'Hello @${{ github.actor }}, thank you for submitting a PR! We will respond as soon as possible.'
|
||||
issue_message: |
|
||||
Hello @${{ github.actor }}, thank you for your interest in our work!
|
||||
|
||||
If this is a bug report, please provide screenshots and **minimum viable code to reproduce your issue**, otherwise we can not help you.
|
||||
@@ -0,0 +1,180 @@
|
||||
name: Community Tests (No Secrets)
|
||||
|
||||
# Runs on ALL pull requests, including forks.
|
||||
# No secrets required — only fully mocked unit tests and code quality checks.
|
||||
# This gives community contributors fast feedback on their changes.
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [ main, dev ]
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: community-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
RUNTIME__LOG_LEVEL: ERROR
|
||||
ENV: 'dev'
|
||||
|
||||
jobs:
|
||||
code-quality:
|
||||
name: Code Quality
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@v7
|
||||
with:
|
||||
enable-cache: true
|
||||
|
||||
- name: Validate uv lockfile
|
||||
run: uv lock --check || { echo "'uv lock --check' failed. Run 'uv lock' and push your changes."; exit 1; }
|
||||
|
||||
- name: Run pre-commit hooks
|
||||
uses: pre-commit/action@v3.0.1
|
||||
|
||||
- name: Install dependencies
|
||||
run: uv sync --extra dev
|
||||
|
||||
- name: Ruff check
|
||||
run: uv run ruff check .
|
||||
|
||||
- name: Ruff format check
|
||||
run: uv run ruff format --check .
|
||||
|
||||
- name: Ty type check
|
||||
run: uv run ty check .
|
||||
|
||||
unit-tests:
|
||||
name: Unit Tests (Mocked, No Secrets)
|
||||
runs-on: ubuntu-22.04
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
python-version: ['3.11.x']
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@v7
|
||||
with:
|
||||
enable-cache: true
|
||||
|
||||
- name: Install dependencies
|
||||
# postgres is needed so the SQL cache adapter tests run instead of skipping.
|
||||
run: uv sync --extra dev --extra postgres
|
||||
|
||||
- name: Run mocked unit tests
|
||||
run: |
|
||||
uv run pytest \
|
||||
cognee/tests/unit/processing/ \
|
||||
cognee/tests/unit/entity_extraction/ \
|
||||
cognee/tests/unit/modules/graph/ \
|
||||
cognee/tests/unit/modules/chunking/ \
|
||||
cognee/tests/unit/modules/data/ \
|
||||
cognee/tests/unit/modules/retrieval/ \
|
||||
--ignore=cognee/tests/unit/modules/retrieval/graph_completion_retriever_cot_test.py \
|
||||
--ignore=cognee/tests/unit/modules/retrieval/temporal_retriever_test.py \
|
||||
--ignore=cognee/tests/unit/modules/retrieval/triplet_retriever_test.py \
|
||||
cognee/tests/unit/modules/search/ \
|
||||
cognee/tests/unit/modules/pipelines/ \
|
||||
cognee/tests/unit/modules/visualization/ \
|
||||
cognee/tests/unit/modules/ontology/ \
|
||||
cognee/tests/unit/modules/observability/ \
|
||||
cognee/tests/unit/modules/users/ \
|
||||
cognee/tests/unit/modules/memify_tasks/ \
|
||||
cognee/tests/unit/interfaces/graph/ \
|
||||
cognee/tests/unit/infrastructure/databases/cache/ \
|
||||
cognee/tests/unit/infrastructure/databases/vector/test_vector_db_config.py \
|
||||
cognee/tests/unit/infrastructure/databases/relational/ \
|
||||
cognee/tests/unit/infrastructure/databases/test_unified_store_engine.py \
|
||||
cognee/tests/unit/infrastructure/session/ \
|
||||
cognee/tests/unit/infrastructure/llm/ \
|
||||
cognee/tests/unit/infrastructure/test_rate_limiting_retry.py \
|
||||
cognee/tests/unit/tasks/storage/test_add_data_points.py \
|
||||
cognee/tests/unit/shared/ \
|
||||
-v --tb=short
|
||||
|
||||
cli-unit-tests:
|
||||
name: CLI Unit Tests (Mocked, No Secrets)
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.11.x'
|
||||
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@v7
|
||||
with:
|
||||
enable-cache: true
|
||||
|
||||
- name: Install dependencies
|
||||
run: uv sync --extra dev
|
||||
|
||||
- name: Run CLI unit tests
|
||||
run: uv run pytest cognee/tests/cli_tests/cli_unit_tests/ -v --tb=short
|
||||
|
||||
telemetry-test:
|
||||
name: Telemetry Test (Mocked, No Secrets)
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.11.x'
|
||||
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@v7
|
||||
with:
|
||||
enable-cache: true
|
||||
|
||||
- name: Install dependencies
|
||||
run: uv sync --extra dev
|
||||
|
||||
- name: Run telemetry test
|
||||
run: uv run pytest cognee/tests/test_telemetry.py -v --tb=short
|
||||
|
||||
notify:
|
||||
name: Community Tests Status
|
||||
needs: [code-quality, unit-tests, cli-unit-tests, telemetry-test]
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ !cancelled() }}
|
||||
steps:
|
||||
- name: Check Status
|
||||
run: |
|
||||
if [[ "${{ needs.code-quality.result }}" == "success" &&
|
||||
"${{ needs.unit-tests.result }}" == "success" &&
|
||||
"${{ needs.cli-unit-tests.result }}" == "success" &&
|
||||
"${{ needs.telemetry-test.result }}" == "success" ]]; then
|
||||
echo "All community tests passed!"
|
||||
else
|
||||
echo "One or more community tests failed."
|
||||
exit 1
|
||||
fi
|
||||
@@ -0,0 +1,165 @@
|
||||
name: Reusable DB Examples Tests
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
databases:
|
||||
required: false
|
||||
type: string
|
||||
default: "all"
|
||||
description: "Which databases to run (comma-separated or 'all')"
|
||||
python-version:
|
||||
required: false
|
||||
type: string
|
||||
default: "3.11.x"
|
||||
ci-image:
|
||||
required: false
|
||||
type: string
|
||||
default: ''
|
||||
secrets:
|
||||
LLM_MODEL:
|
||||
required: true
|
||||
LLM_ENDPOINT:
|
||||
required: true
|
||||
LLM_API_KEY:
|
||||
required: true
|
||||
LLM_ARGS:
|
||||
required: false
|
||||
LLM_API_VERSION:
|
||||
required: true
|
||||
EMBEDDING_MODEL:
|
||||
required: true
|
||||
EMBEDDING_API_KEY:
|
||||
required: true
|
||||
|
||||
POSTGRES_PASSWORD:
|
||||
required: false
|
||||
NEO4J_API_URL:
|
||||
required: false
|
||||
NEO4J_API_KEY:
|
||||
required: false
|
||||
|
||||
|
||||
env:
|
||||
COGNEE_SKIP_CONNECTION_TEST: 'true'
|
||||
|
||||
jobs:
|
||||
run-db-example-neo4j:
|
||||
name: "Neo4j DB Example Test"
|
||||
runs-on: ubuntu-22.04
|
||||
if: ${{ inputs.databases == 'all' || contains(inputs.databases, 'neo4j') }}
|
||||
steps:
|
||||
- name: Check out
|
||||
uses: actions/checkout@master
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: ${{ inputs.python-version }}
|
||||
|
||||
- name: Setup Neo4j with GDS
|
||||
uses: ./.github/actions/setup_neo4j
|
||||
id: neo4j
|
||||
|
||||
- name: Run Neo4j Example
|
||||
env:
|
||||
ENV: 'dev'
|
||||
ENABLE_BACKEND_ACCESS_CONTROL: 'false'
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
GRAPH_DATABASE_PROVIDER: "neo4j"
|
||||
GRAPH_DATABASE_URL: ${{ steps.neo4j.outputs.neo4j-url }}
|
||||
GRAPH_DATABASE_USERNAME: ${{ steps.neo4j.outputs.neo4j-username }}
|
||||
GRAPH_DATABASE_PASSWORD: ${{ steps.neo4j.outputs.neo4j-password }}
|
||||
run: |
|
||||
uv run python examples/database_examples/neo4j_example.py
|
||||
|
||||
run-db-example-ladybug:
|
||||
name: "Ladybug DB Example Test"
|
||||
runs-on: ubuntu-22.04
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
if: ${{ inputs.databases == 'all' || contains(inputs.databases, 'ladybug') || contains(inputs.databases, 'kuzu') }}
|
||||
|
||||
steps:
|
||||
- name: Check out
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: ${{ inputs.python-version }}
|
||||
|
||||
- name: Dependencies already installed
|
||||
run: echo "Dependencies already installed in setup"
|
||||
|
||||
- name: Run Ladybug Example
|
||||
env:
|
||||
ENV: 'dev'
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
GRAPH_DATABASE_PROVIDER: "ladybug"
|
||||
run: |
|
||||
uv run python examples/database_examples/ladybug_example.py
|
||||
|
||||
run-db-example-pgvector:
|
||||
name: "PostgreSQL PGVector DB Example Test"
|
||||
runs-on: ubuntu-22.04
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
if: ${{ inputs.databases == 'all' || contains(inputs.databases, 'postgres') }}
|
||||
services:
|
||||
postgres:
|
||||
image: ghcr.io/topoteretes/pgvector:pg17
|
||||
credentials:
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
env:
|
||||
POSTGRES_USER: cognee
|
||||
POSTGRES_PASSWORD: ${{ secrets.POSTGRES_PASSWORD }}
|
||||
POSTGRES_DB: cognee_db
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
ports:
|
||||
- 5432:5432
|
||||
|
||||
steps:
|
||||
- name: Check out
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: ${{ inputs.python-version }}
|
||||
extra-dependencies: "postgres"
|
||||
|
||||
- name: Run PGVector Example
|
||||
env:
|
||||
ENV: 'dev'
|
||||
ENABLE_BACKEND_ACCESS_CONTROL: 'false'
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
DB_HOST: ${{ inputs.ci-image != '' && 'postgres' || '127.0.0.1' }}
|
||||
run: |
|
||||
uv run python examples/database_examples/pgvector_example.py
|
||||
@@ -0,0 +1,123 @@
|
||||
name: Dev Canary Release
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# Every Monday at 06:00 UTC
|
||||
- cron: "0 6 * * 1"
|
||||
workflow_dispatch:
|
||||
workflow_call:
|
||||
|
||||
concurrency:
|
||||
group: dev-canary-release
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
# ── Gate: run core test suites before publishing ────────────────────
|
||||
test-gate:
|
||||
name: Canary Test Gate
|
||||
uses: ./.github/workflows/basic_tests.yml
|
||||
with:
|
||||
ci-image: ""
|
||||
secrets: inherit
|
||||
|
||||
# ── Compute canary version ──────────────────────────────────────────
|
||||
prepare:
|
||||
name: Prepare Canary Version
|
||||
runs-on: ubuntu-latest
|
||||
needs: test-gate
|
||||
outputs:
|
||||
version: ${{ steps.version.outputs.version }}
|
||||
canary_version: ${{ steps.version.outputs.canary_version }}
|
||||
steps:
|
||||
- name: Check out dev
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: dev
|
||||
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@v7
|
||||
|
||||
- name: Install Python
|
||||
run: uv python install
|
||||
|
||||
- name: Compute canary version
|
||||
id: version
|
||||
run: |
|
||||
BASE_VERSION="$(uv version --short)"
|
||||
# Strip any existing .devN suffix to get the base
|
||||
CLEAN_VERSION="${BASE_VERSION%%\.dev*}"
|
||||
# PEP 440 dev release: 0.5.4.dev20260309
|
||||
CANARY_VERSION="${CLEAN_VERSION}.dev$(date -u +%Y%m%d)"
|
||||
echo "version=${CLEAN_VERSION}" >> "$GITHUB_OUTPUT"
|
||||
echo "canary_version=${CANARY_VERSION}" >> "$GITHUB_OUTPUT"
|
||||
echo "Canary version: ${CANARY_VERSION}"
|
||||
|
||||
# ── Publish to PyPI ─────────────────────────────────────────────────
|
||||
release-pypi:
|
||||
name: Publish Dev Canary to PyPI
|
||||
needs: prepare
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out dev
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: dev
|
||||
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@v7
|
||||
|
||||
- name: Install Python
|
||||
run: uv python install
|
||||
|
||||
- name: Set canary version in pyproject.toml
|
||||
run: uv version "${{ needs.prepare.outputs.canary_version }}"
|
||||
|
||||
- name: Install dependencies
|
||||
run: uv sync --all-extras
|
||||
|
||||
- name: Build distributions
|
||||
run: uv build
|
||||
|
||||
- name: Publish to PyPI
|
||||
env:
|
||||
UV_PUBLISH_TOKEN: ${{ secrets.PYPI_TOKEN }}
|
||||
run: uv publish
|
||||
|
||||
# ── Publish Docker image ────────────────────────────────────────────
|
||||
release-docker:
|
||||
name: Publish Dev Canary Docker Image
|
||||
needs: prepare
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out dev
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: dev
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: |
|
||||
cognee/cognee:dev-canary
|
||||
cognee/cognee:${{ needs.prepare.outputs.canary_version }}
|
||||
labels: |
|
||||
version=${{ needs.prepare.outputs.canary_version }}
|
||||
flavour=dev-canary
|
||||
cache-from: type=registry,ref=cognee/cognee:buildcache
|
||||
cache-to: type=registry,ref=cognee/cognee:buildcache,mode=max
|
||||
@@ -0,0 +1,351 @@
|
||||
name: automation | Draft Docs PRs For Previous Day Dev PRs
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
lookback_days:
|
||||
description: Number of UTC calendar days to look back when scanning merged PRs
|
||||
required: false
|
||||
default: "1"
|
||||
anchor_date:
|
||||
description: Optional UTC date to scan, in YYYY-MM-DD format
|
||||
required: false
|
||||
default: ""
|
||||
schedule:
|
||||
- cron: "59 23 * * *"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
|
||||
env:
|
||||
lookback_days: ${{ github.event.inputs.lookback_days || vars.lookback_days || '1' }}
|
||||
|
||||
jobs:
|
||||
prepare-merged-branches:
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 10
|
||||
outputs:
|
||||
start_date: ${{ steps.prepare.outputs.start_date }}
|
||||
end_date: ${{ steps.prepare.outputs.end_date }}
|
||||
has_merges: ${{ steps.prepare.outputs.has_merges }}
|
||||
merge_summary: ${{ steps.prepare.outputs.merge_summary }}
|
||||
matrix: ${{ steps.prepare.outputs.matrix }}
|
||||
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Fetch latest dev branch
|
||||
run: git fetch origin dev:refs/remotes/origin/dev --no-tags
|
||||
|
||||
- name: Prepare merged PRs
|
||||
id: prepare
|
||||
shell: bash
|
||||
env:
|
||||
INPUT_ANCHOR_DATE: ${{ github.event.inputs.anchor_date || '' }}
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
args=(
|
||||
--branch origin/dev
|
||||
--lookback-days "${lookback_days}"
|
||||
)
|
||||
|
||||
anchor_date="${INPUT_ANCHOR_DATE}"
|
||||
if [ "${{ github.event_name }}" = "schedule" ]; then
|
||||
anchor_date="$(date -u -d 'yesterday' +%F)"
|
||||
fi
|
||||
|
||||
if [ -n "${anchor_date}" ]; then
|
||||
echo "Using anchor date ${anchor_date}"
|
||||
args+=(--anchor-date "${anchor_date}")
|
||||
fi
|
||||
|
||||
python3 tools/prepare_merged_branches.py "${args[@]}"
|
||||
|
||||
create-docs-prs:
|
||||
needs:
|
||||
- prepare-merged-branches
|
||||
if: ${{ needs.prepare-merged-branches.outputs.has_merges == 'true' }}
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 20
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include: ${{ fromJSON(needs.prepare-merged-branches.outputs.matrix) }}
|
||||
|
||||
steps:
|
||||
- name: Check out core repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.10"
|
||||
|
||||
- name: Set up uv
|
||||
uses: astral-sh/setup-uv@v7
|
||||
|
||||
- name: Install workflow dependencies
|
||||
run: uv sync --locked
|
||||
|
||||
- name: Fetch latest dev branch
|
||||
run: git fetch origin dev:refs/remotes/origin/dev --no-tags
|
||||
|
||||
- name: Prepare branch note paths
|
||||
id: branch_paths
|
||||
run: |
|
||||
OUTPUT_DIR="branch-dev-notes/${{ matrix.safe_branch }}-${{ matrix.short_sha }}"
|
||||
mkdir -p "${OUTPUT_DIR}"
|
||||
echo "output_dir=${OUTPUT_DIR}" >> "${GITHUB_OUTPUT}"
|
||||
echo "notes_json=${OUTPUT_DIR}/branch_notes.json" >> "${GITHUB_OUTPUT}"
|
||||
echo "notes_markdown=${OUTPUT_DIR}/branch_notes.md" >> "${GITHUB_OUTPUT}"
|
||||
echo "assessment_json=${OUTPUT_DIR}/docs_assessment.json" >> "${GITHUB_OUTPUT}"
|
||||
echo "assessment_markdown=${OUTPUT_DIR}/docs_assessment.md" >> "${GITHUB_OUTPUT}"
|
||||
echo "docs_edit_scope_json=${OUTPUT_DIR}/docs_edit_scope.json" >> "${GITHUB_OUTPUT}"
|
||||
echo "docs_edit_scope_markdown=${OUTPUT_DIR}/docs_edit_scope.md" >> "${GITHUB_OUTPUT}"
|
||||
echo "docs_scope_plan=${OUTPUT_DIR}/docs_scope_plan.md" >> "${GITHUB_OUTPUT}"
|
||||
|
||||
- name: Generate branch notes
|
||||
env:
|
||||
LLM_API_KEY: ${{ secrets.OPENAI_API_KEY || secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_MODEL: ${{ vars.LLM_MODEL || secrets.LLM_MODEL || 'openai/gpt-4o-mini' }}
|
||||
NOTES_JSON: ${{ steps.branch_paths.outputs.notes_json }}
|
||||
NOTES_MARKDOWN: ${{ steps.branch_paths.outputs.notes_markdown }}
|
||||
PR_NUMBER: ${{ matrix.pr_number }}
|
||||
PR_TITLE: ${{ matrix.pr_title }}
|
||||
PR_BODY_B64: ${{ matrix.pr_body_b64 }}
|
||||
PR_URL: ${{ matrix.pr_url }}
|
||||
run: |
|
||||
uv run python tools/generate_branch_notes.py \
|
||||
--branch-name "${{ matrix.branch_name }}" \
|
||||
--merge-sha "${{ matrix.merge_sha }}" \
|
||||
--first-parent "${{ matrix.first_parent }}" \
|
||||
--second-parent "${{ matrix.second_parent }}" \
|
||||
--pr-number "${PR_NUMBER}" \
|
||||
--pr-title "${PR_TITLE}" \
|
||||
--pr-body-base64 "${PR_BODY_B64}" \
|
||||
--pr-url "${PR_URL}" \
|
||||
--json-output "${NOTES_JSON}" \
|
||||
--markdown-output "${NOTES_MARKDOWN}"
|
||||
|
||||
- name: Assess documentation impact for branch
|
||||
id: assessment
|
||||
env:
|
||||
LLM_API_KEY: ${{ secrets.OPENAI_API_KEY || secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_MODEL: ${{ vars.LLM_MODEL || secrets.LLM_MODEL || 'openai/gpt-4o-mini' }}
|
||||
NOTES_JSON: ${{ steps.branch_paths.outputs.notes_json }}
|
||||
NOTES_MARKDOWN: ${{ steps.branch_paths.outputs.notes_markdown }}
|
||||
ASSESSMENT_JSON: ${{ steps.branch_paths.outputs.assessment_json }}
|
||||
ASSESSMENT_MARKDOWN: ${{ steps.branch_paths.outputs.assessment_markdown }}
|
||||
run: |
|
||||
uv run python tools/assess_branch_notes.py \
|
||||
--notes-json "${NOTES_JSON}" \
|
||||
--notes-markdown "${NOTES_MARKDOWN}" \
|
||||
--json-output "${ASSESSMENT_JSON}" \
|
||||
--markdown-output "${ASSESSMENT_MARKDOWN}"
|
||||
|
||||
python3 tools/write_docs_assessment_outputs.py \
|
||||
--assessment-json "${ASSESSMENT_JSON}" \
|
||||
--branch-slug "${{ matrix.safe_branch }}" \
|
||||
--short-sha "${{ matrix.short_sha }}" \
|
||||
--pr-number "${{ matrix.pr_number }}"
|
||||
|
||||
- name: Check out docs repository
|
||||
if: ${{ steps.assessment.outputs.needs_update == 'true' }}
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
repository: topoteretes/cognee-docs
|
||||
token: ${{ secrets.REPO_DISPATCH_PAT_TOKEN }}
|
||||
ref: main
|
||||
path: docs-repo
|
||||
|
||||
- name: Prepare docs branch
|
||||
if: ${{ steps.assessment.outputs.needs_update == 'true' }}
|
||||
working-directory: docs-repo
|
||||
run: |
|
||||
git fetch origin "${{ steps.assessment.outputs.docs_branch }}" || true
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
if git show-ref --verify --quiet "refs/remotes/origin/${{ steps.assessment.outputs.docs_branch }}"; then
|
||||
git checkout -B "${{ steps.assessment.outputs.docs_branch }}" "origin/${{ steps.assessment.outputs.docs_branch }}"
|
||||
else
|
||||
git checkout -B "${{ steps.assessment.outputs.docs_branch }}"
|
||||
fi
|
||||
|
||||
- name: Prepare docs edit scope
|
||||
if: ${{ steps.assessment.outputs.needs_update == 'true' }}
|
||||
id: docs_scope
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
python3 tools/prepare_docs_edit_scope.py \
|
||||
--repo "${{ github.repository }}" \
|
||||
--pr-number "${{ matrix.pr_number }}" \
|
||||
--docs-root docs-repo \
|
||||
--notes-json "${{ steps.branch_paths.outputs.notes_json }}" \
|
||||
--assessment-json "${{ steps.branch_paths.outputs.assessment_json }}" \
|
||||
--scope-json-output "${{ steps.branch_paths.outputs.docs_edit_scope_json }}" \
|
||||
--scope-markdown-output "${{ steps.branch_paths.outputs.docs_edit_scope_markdown }}"
|
||||
|
||||
- name: Plan docs changes with Claude
|
||||
if: ${{ steps.assessment.outputs.needs_update == 'true' }}
|
||||
id: claude_scope
|
||||
uses: anthropics/claude-code-action@v1
|
||||
with:
|
||||
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
prompt: |
|
||||
Read and follow `.github/prompts/docs_scope_plan.md`.
|
||||
|
||||
- Branch: `${{ matrix.branch_name }}`
|
||||
- PR: `#${{ matrix.pr_number }} ${{ matrix.pr_title }}`
|
||||
- Merge SHA: `${{ matrix.merge_sha }}`
|
||||
- Short SHA: `${{ matrix.short_sha }}`
|
||||
- First parent: `${{ matrix.first_parent }}`
|
||||
- Second parent: `${{ matrix.second_parent }}`
|
||||
- Scope plan output: `./${{ steps.branch_paths.outputs.docs_scope_plan }}`
|
||||
|
||||
- **Prepared documentation edit scope** (`./${{ steps.branch_paths.outputs.docs_edit_scope_markdown }}`): Curated source files, docs candidates, assessment summary, and out-of-scope files.
|
||||
- **Prepared documentation edit scope JSON** (`./${{ steps.branch_paths.outputs.docs_edit_scope_json }}`): Machine-readable copy of the prepared scope.
|
||||
claude_args: "--allowed-tools Read,Write,Glob,Grep --max-turns 35"
|
||||
|
||||
- name: Validate docs scope plan
|
||||
if: ${{ steps.assessment.outputs.needs_update == 'true' }}
|
||||
run: |
|
||||
test -s "${{ steps.branch_paths.outputs.docs_scope_plan }}"
|
||||
if [ -n "$(git -C docs-repo status --short)" ]; then
|
||||
echo "The docs planning step modified docs-repo, but planning must not edit documentation." >&2
|
||||
git -C docs-repo status --short >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Read docs scope plan outputs
|
||||
if: ${{ steps.assessment.outputs.needs_update == 'true' }}
|
||||
id: scope_plan
|
||||
run: |
|
||||
python3 tools/write_docs_scope_plan_outputs.py \
|
||||
--scope-plan "${{ steps.branch_paths.outputs.docs_scope_plan }}"
|
||||
|
||||
- name: Generate docs changes with Claude
|
||||
if: ${{ steps.assessment.outputs.needs_update == 'true' && steps.scope_plan.outputs.docs_needed == 'true' }}
|
||||
id: claude
|
||||
uses: anthropics/claude-code-action@v1
|
||||
with:
|
||||
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
prompt: |
|
||||
Read and follow `.github/prompts/docs_edit.md`.
|
||||
|
||||
- Branch: `${{ matrix.branch_name }}`
|
||||
- PR: `#${{ matrix.pr_number }} ${{ matrix.pr_title }}`
|
||||
- Merge SHA: `${{ matrix.merge_sha }}`
|
||||
- Short SHA: `${{ matrix.short_sha }}`
|
||||
- First parent: `${{ matrix.first_parent }}`
|
||||
- Second parent: `${{ matrix.second_parent }}`
|
||||
|
||||
## Required inputs
|
||||
|
||||
Read these first:
|
||||
|
||||
- **Documentation scope plan** (`./${{ steps.branch_paths.outputs.docs_scope_plan }}`)
|
||||
- **Branch notes** (`./${{ steps.branch_paths.outputs.notes_markdown }}`)
|
||||
- **Documentation assessment** (`./${{ steps.branch_paths.outputs.assessment_markdown }}`)
|
||||
claude_args: "--allowed-tools Read,Edit,Write,Glob,Grep,Bash --max-turns 50"
|
||||
|
||||
- name: Prepare docs PR content
|
||||
if: ${{ steps.assessment.outputs.needs_update == 'true' && steps.scope_plan.outputs.docs_needed == 'true' }}
|
||||
id: pr_content
|
||||
env:
|
||||
NOTES_JSON: ${{ steps.branch_paths.outputs.notes_json }}
|
||||
ASSESSMENT_JSON: ${{ steps.branch_paths.outputs.assessment_json }}
|
||||
BRANCH_NAME: ${{ matrix.branch_name }}
|
||||
SHORT_SHA: ${{ matrix.short_sha }}
|
||||
DEFAULT_PR_TITLE: ${{ steps.assessment.outputs.pr_title }}
|
||||
run: |
|
||||
python3 tools/prepare_docs_pr_content.py \
|
||||
--notes-json "${NOTES_JSON}" \
|
||||
--assessment-json "${ASSESSMENT_JSON}" \
|
||||
--branch-name "${BRANCH_NAME}" \
|
||||
--short-sha "${SHORT_SHA}" \
|
||||
--default-pr-title "${DEFAULT_PR_TITLE}" \
|
||||
--docs-root docs-repo
|
||||
|
||||
- name: Create docs draft commit
|
||||
if: ${{ steps.assessment.outputs.needs_update == 'true' && steps.scope_plan.outputs.docs_needed == 'true' }}
|
||||
id: commit_docs
|
||||
working-directory: docs-repo
|
||||
run: |
|
||||
git add -A
|
||||
|
||||
if git diff --cached --quiet; then
|
||||
echo "changes_made=false" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
git commit -m "${{ steps.pr_content.outputs.pr_title }}"
|
||||
echo "changes_made=true" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Push docs draft branch
|
||||
if: ${{ steps.assessment.outputs.needs_update == 'true' && steps.scope_plan.outputs.docs_needed == 'true' && steps.commit_docs.outputs.changes_made == 'true' }}
|
||||
working-directory: docs-repo
|
||||
run: git push --force-with-lease origin "${{ steps.assessment.outputs.docs_branch }}"
|
||||
|
||||
- name: Create or update docs pull request
|
||||
if: ${{ steps.assessment.outputs.needs_update == 'true' && steps.scope_plan.outputs.docs_needed == 'true' }}
|
||||
id: manage_pr
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.REPO_DISPATCH_PAT_TOKEN }}
|
||||
HEAD_BRANCH: ${{ steps.assessment.outputs.docs_branch }}
|
||||
PR_TITLE: ${{ steps.pr_content.outputs.pr_title }}
|
||||
PR_BODY: ${{ steps.pr_content.outputs.pr_body }}
|
||||
CHANGES_MADE: ${{ steps.commit_docs.outputs.changes_made }}
|
||||
run: |
|
||||
python3 tools/manage_docs_pr.py \
|
||||
--target-repo topoteretes/cognee-docs \
|
||||
--head-branch "${HEAD_BRANCH}" \
|
||||
--pr-title "${PR_TITLE}" \
|
||||
--pr-body "${PR_BODY}" \
|
||||
--changes-made "${CHANGES_MADE}"
|
||||
|
||||
- name: Summarize docs PR result
|
||||
if: ${{ steps.assessment.outputs.needs_update == 'true' && steps.scope_plan.outputs.docs_needed == 'true' }}
|
||||
env:
|
||||
CHANGED_FILES: ${{ steps.pr_content.outputs.changed_files }}
|
||||
run: |
|
||||
{
|
||||
echo "## PR docs review: #${{ matrix.pr_number }} ${{ matrix.pr_title }}"
|
||||
echo
|
||||
echo "- Branch: \`${{ matrix.branch_name }}\`"
|
||||
echo "- Merge commit: \`${{ matrix.merge_sha }}\`"
|
||||
echo "- Needs documentation update: \`${{ steps.assessment.outputs.needs_update }}\`"
|
||||
if [ "${{ steps.assessment.outputs.needs_update }}" = "true" ]; then
|
||||
echo "- Docs branch: \`${{ steps.assessment.outputs.docs_branch }}\`"
|
||||
if [ -n "${CHANGED_FILES}" ]; then
|
||||
echo "- Updated docs files:"
|
||||
printf '%s\n' "${CHANGED_FILES}" | while IFS= read -r changed_file; do
|
||||
[ -n "${changed_file}" ] || continue
|
||||
echo " - \`${changed_file}\`"
|
||||
done
|
||||
else
|
||||
echo "- Updated docs files: none"
|
||||
fi
|
||||
if [ -n "${{ steps.manage_pr.outputs.pr_url }}" ]; then
|
||||
echo "- Pull request: ${{ steps.manage_pr.outputs.pr_url }}"
|
||||
else
|
||||
echo "- Pull request: not created"
|
||||
fi
|
||||
fi
|
||||
echo
|
||||
echo "### Documentation assessment"
|
||||
echo
|
||||
cat "${{ steps.branch_paths.outputs.assessment_markdown }}"
|
||||
} >> "${GITHUB_STEP_SUMMARY}"
|
||||
@@ -0,0 +1,83 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Navigate to the workflows directory
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
# List of workflows that should only be triggered via test-suites.yml
|
||||
WORKFLOWS=(
|
||||
"test_weaviate.yml"
|
||||
"test_kuzu.yml"
|
||||
"test_multimetric_qa_eval_run.yaml"
|
||||
"test_graphrag_vs_rag_notebook.yml"
|
||||
"test_llms.yml"
|
||||
"test_multimedia_example.yaml"
|
||||
"test_deduplication.yml"
|
||||
"test_eval_framework.yml"
|
||||
"test_descriptive_graph_metrics.yml"
|
||||
"test_llama_index_cognee_integration_notebook.yml"
|
||||
"test_cognee_llama_index_notebook.yml"
|
||||
"test_cognee_multimedia_notebook.yml"
|
||||
"test_cognee_server_start.yml"
|
||||
"test_telemetry.yml"
|
||||
"test_neo4j.yml"
|
||||
"test_pgvector.yml"
|
||||
"test_ollama.yml"
|
||||
"test_notebook.yml"
|
||||
"test_simple_example.yml"
|
||||
"test_code_graph_example.yml"
|
||||
)
|
||||
|
||||
for workflow in "${WORKFLOWS[@]}"; do
|
||||
if [ -f "$workflow" ]; then
|
||||
echo "Processing $workflow..."
|
||||
|
||||
# Create a backup
|
||||
cp "$workflow" "${workflow}.bak"
|
||||
|
||||
# Check if the file begins with a workflow_call trigger
|
||||
if grep -q "workflow_call:" "$workflow"; then
|
||||
echo "$workflow already has workflow_call trigger, skipping..."
|
||||
continue
|
||||
fi
|
||||
|
||||
# Get the content after the 'on:' section
|
||||
on_line=$(grep -n "^on:" "$workflow" | cut -d ':' -f1)
|
||||
|
||||
if [ -z "$on_line" ]; then
|
||||
echo "Warning: No 'on:' section found in $workflow, skipping..."
|
||||
continue
|
||||
fi
|
||||
|
||||
# Create a new file with the modified content
|
||||
{
|
||||
# Copy the part before 'on:'
|
||||
head -n $((on_line-1)) "$workflow"
|
||||
|
||||
# Add the new on: section that only includes workflow_call
|
||||
echo "on:"
|
||||
echo " workflow_call:"
|
||||
echo " secrets:"
|
||||
echo " inherit: true"
|
||||
|
||||
# Find where to continue after the original 'on:' section
|
||||
next_section=$(awk "NR > $on_line && /^[a-z]/ {print NR; exit}" "$workflow")
|
||||
|
||||
if [ -z "$next_section" ]; then
|
||||
next_section=$(wc -l < "$workflow")
|
||||
next_section=$((next_section+1))
|
||||
fi
|
||||
|
||||
# Copy the rest of the file starting from the next section
|
||||
tail -n +$next_section "$workflow"
|
||||
} > "${workflow}.new"
|
||||
|
||||
# Replace the original with the new version
|
||||
mv "${workflow}.new" "$workflow"
|
||||
|
||||
echo "Modified $workflow to only run when called from test-suites.yml"
|
||||
else
|
||||
echo "Warning: $workflow not found, skipping..."
|
||||
fi
|
||||
done
|
||||
|
||||
echo "Finished modifying workflows!"
|
||||
@@ -0,0 +1,81 @@
|
||||
name: Distributed Cognee test with modal
|
||||
permissions:
|
||||
contents: read
|
||||
packages: read
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
python-version:
|
||||
required: false
|
||||
type: string
|
||||
default: '3.13.x'
|
||||
ci-image:
|
||||
required: false
|
||||
type: string
|
||||
default: ''
|
||||
secrets:
|
||||
LLM_MODEL:
|
||||
required: true
|
||||
LLM_ENDPOINT:
|
||||
required: true
|
||||
LLM_API_KEY:
|
||||
required: true
|
||||
LLM_ARGS:
|
||||
required: false
|
||||
LLM_API_VERSION:
|
||||
required: true
|
||||
EMBEDDING_MODEL:
|
||||
required: true
|
||||
EMBEDDING_API_KEY:
|
||||
required: true
|
||||
OPENAI_API_KEY:
|
||||
required: true
|
||||
|
||||
env:
|
||||
COGNEE_SKIP_CONNECTION_TEST: 'true'
|
||||
|
||||
jobs:
|
||||
run-server-start-test:
|
||||
name: Distributed Cognee test (Modal)
|
||||
runs-on: ubuntu-22.04
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
steps:
|
||||
- name: Check out
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: '3.13.x'
|
||||
extra-dependencies: "distributed postgres"
|
||||
|
||||
- name: Run Distributed Cognee (Modal)
|
||||
env:
|
||||
ENV: 'dev'
|
||||
ENABLE_BACKEND_ACCESS_CONTROL: 'false'
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
MODAL_TOKEN_ID: ${{ secrets.MODAL_TOKEN_ID }}
|
||||
MODAL_TOKEN_SECRET: ${{ secrets.MODAL_TOKEN_SECRET }}
|
||||
MODAL_SECRET_NAME: ${{ secrets.MODAL_SECRET_NAME }}
|
||||
GRAPH_DATABASE_PROVIDER: "neo4j"
|
||||
GRAPH_DATABASE_URL: ${{ secrets.AZURE_NEO4j_URL }}
|
||||
GRAPH_DATABASE_USERNAME: ${{ secrets.AZURE_NEO4J_USERNAME }}
|
||||
GRAPH_DATABASE_PASSWORD: ${{ secrets.AZURE_NEO4J_PW }}
|
||||
DB_PROVIDER: "postgres"
|
||||
DB_NAME: ${{ secrets.AZURE_POSTGRES_DB_NAME }}
|
||||
DB_HOST: ${{ secrets.AZURE_POSTGRES_HOST }}
|
||||
DB_PORT: ${{ secrets.AZURE_POSTGRES_PORT }}
|
||||
DB_USERNAME: ${{ secrets.AZURE_POSTGRES_USERNAME }}
|
||||
DB_PASSWORD: ${{ secrets.AZURE_POSTGRES_PW }}
|
||||
VECTOR_DB_PROVIDER: "pgvector"
|
||||
COGNEE_DISTRIBUTED: "true"
|
||||
run: uv run modal run ./distributed/entrypoint.py
|
||||
@@ -0,0 +1,108 @@
|
||||
name: test | docker compose
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
env:
|
||||
COGNEE_SKIP_CONNECTION_TEST: 'true'
|
||||
|
||||
jobs:
|
||||
docker-compose-test:
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@master
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Build Docker images
|
||||
env:
|
||||
ENV: dev
|
||||
run: |
|
||||
docker compose -f docker-compose.yml build
|
||||
|
||||
- name: Create container .env
|
||||
# docker-compose.yml bind-mounts ./.env into the container; CI has no
|
||||
# checked-in .env, so provide the runtime credentials the server needs.
|
||||
# Secrets flow through the env block so the script body never renders
|
||||
# secret material (GitHub's log masking then only has exact values to hide).
|
||||
env:
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
run: |
|
||||
printenv | grep -E '^(LLM_|EMBEDDING_)' > .env
|
||||
echo "EMBEDDING_DIMENSIONS=300" >> .env
|
||||
echo "COGNEE_SKIP_CONNECTION_TEST=true" >> .env
|
||||
|
||||
- name: Run Docker Compose
|
||||
env:
|
||||
ENV: dev
|
||||
run: |
|
||||
docker compose -f docker-compose.yml up -d
|
||||
|
||||
- name: Wait for server health
|
||||
run: |
|
||||
for attempt in $(seq 1 60); do
|
||||
if curl -sf http://localhost:8000/health >/dev/null; then
|
||||
echo "server healthy after ~$((attempt * 3))s"
|
||||
exit 0
|
||||
fi
|
||||
if [ "$(docker inspect -f '{{.State.Running}}' cognee 2>/dev/null)" != "true" ]; then
|
||||
echo "cognee container is not running"
|
||||
docker compose -f docker-compose.yml logs cognee | tail -60
|
||||
exit 1
|
||||
fi
|
||||
sleep 3
|
||||
done
|
||||
echo "server did not become healthy in time"
|
||||
docker compose -f docker-compose.yml logs cognee | tail -60
|
||||
exit 1
|
||||
|
||||
- name: Verify remember and recall round-trip
|
||||
run: |
|
||||
TOKEN=$(curl -sf -X POST http://localhost:8000/api/v1/auth/login \
|
||||
-d "username=default_user@example.com&password=default_password" | jq -r .access_token)
|
||||
[ -n "$TOKEN" ] && [ "$TOKEN" != "null" ] || { echo "login failed"; exit 1; }
|
||||
|
||||
FACT="The glassblower Odene Marsk crafted the twin cobalt lanterns of the Vellinge lighthouse in 1931."
|
||||
echo "$FACT" > fact.txt
|
||||
REMEMBERED=$(curl -sf -X POST http://localhost:8000/api/v1/remember \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-F "datasetName=compose_smoke" \
|
||||
-F "data=@fact.txt;type=text/plain")
|
||||
echo "$REMEMBERED" | jq -e '.dataset_id != null' >/dev/null \
|
||||
|| { echo "remember returned no dataset_id"; echo "$REMEMBERED"; exit 1; }
|
||||
echo "remember: ingested into $(echo "$REMEMBERED" | jq -r .dataset_id)"
|
||||
|
||||
# Deterministic check: CHUNKS recall returns the raw stored text, no
|
||||
# LLM involved — the full stored fact must come back verbatim.
|
||||
CHUNKS=$(curl -sf -X POST http://localhost:8000/api/v1/recall \
|
||||
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
|
||||
-d '{"query":"cobalt lanterns lighthouse","searchType":"CHUNKS","datasets":["compose_smoke"]}')
|
||||
echo "$CHUNKS" | grep -qF "$FACT" || { echo "CHUNKS recall missing stored fact"; echo "$CHUNKS"; exit 1; }
|
||||
echo "recall (CHUNKS): stored fact retrieved verbatim"
|
||||
|
||||
# End-to-end answer check: the graph-grounded completion must name the entity.
|
||||
ANSWER=$(curl -sf -X POST http://localhost:8000/api/v1/recall \
|
||||
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
|
||||
-d '{"query":"Who crafted the twin cobalt lanterns of the Vellinge lighthouse, and in which year?","searchType":"GRAPH_COMPLETION","datasets":["compose_smoke"]}')
|
||||
echo "recall (GRAPH_COMPLETION): $ANSWER"
|
||||
echo "$ANSWER" | grep -qi "Marsk" || { echo "graph completion did not mention the remembered entity"; exit 1; }
|
||||
|
||||
- name: Show server logs on failure
|
||||
if: failure()
|
||||
# Filter key-shaped lines: GitHub masks exact secret values, but partial
|
||||
# or transformed echoes (e.g. provider auth errors) would slip through.
|
||||
run: docker compose -f docker-compose.yml logs cognee | grep -viE "api[-_]?key|authorization|bearer" | tail -100
|
||||
|
||||
- name: Shut down Docker Compose
|
||||
if: always()
|
||||
run: |
|
||||
docker compose -f docker-compose.yml down
|
||||
@@ -0,0 +1,65 @@
|
||||
name: build | Build and Push Cognee MCP Docker Image to dockerhub
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
docker-build-and-push:
|
||||
runs-on:
|
||||
group: Default
|
||||
labels:
|
||||
- docker_build_runner
|
||||
|
||||
steps:
|
||||
- name: Check and free disk space before build
|
||||
run: |
|
||||
echo "=== Before cleanup ==="
|
||||
df -h
|
||||
echo "Removing unused preinstalled SDKs to free space..."
|
||||
sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc || true
|
||||
docker system prune -af || true
|
||||
echo "=== After cleanup ==="
|
||||
df -h
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
buildkitd-flags: --root /tmp/buildkit
|
||||
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Extract metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: cognee/cognee-mcp
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=sha,prefix={{branch}}-
|
||||
type=raw,value=latest,enable={{is_default_branch}}
|
||||
|
||||
- name: Build and push
|
||||
id: build
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
file: cognee-mcp/Dockerfile
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=registry,ref=cognee/cognee-mcp:buildcache
|
||||
cache-to: type=registry,ref=cognee/cognee-mcp:buildcache,mode=max
|
||||
|
||||
|
||||
- name: Image digest
|
||||
run: echo ${{ steps.build.outputs.digest }}
|
||||
@@ -0,0 +1,48 @@
|
||||
name: build | Build and Push Docker Image to dockerhub
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
docker-build-and-push:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Extract metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: cognee/cognee
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=sha,prefix={{branch}}-
|
||||
type=raw,value=latest,enable={{is_default_branch}}
|
||||
|
||||
- name: Build and push
|
||||
id: build
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=registry,ref=cognee/cognee:buildcache
|
||||
cache-to: type=registry,ref=cognee/cognee:buildcache,mode=max
|
||||
|
||||
- name: Image digest
|
||||
run: echo ${{ steps.build.outputs.digest }}
|
||||
@@ -0,0 +1,384 @@
|
||||
name: Reusable Examples Tests
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: read
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
ci-image:
|
||||
required: false
|
||||
type: string
|
||||
default: ''
|
||||
|
||||
env:
|
||||
COGNEE_SKIP_CONNECTION_TEST: 'true'
|
||||
|
||||
jobs:
|
||||
test-multimedia-example:
|
||||
name: Run Multimedia Example
|
||||
runs-on: ubuntu-22.04
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: '3.11.x'
|
||||
|
||||
- name: Run Multimedia Example
|
||||
env:
|
||||
ENV: 'dev'
|
||||
LLM_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
run: uv run python ./examples/demos/multimedia_processing/multimedia_audio_image_processing_example.py
|
||||
|
||||
test-eval-example:
|
||||
name: Run Eval Example
|
||||
runs-on: ubuntu-22.04
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: '3.11.x'
|
||||
extra-dependencies: "deepeval"
|
||||
|
||||
- name: Run Evaluation Framework Example
|
||||
env:
|
||||
ENV: 'dev'
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
run: uv run python ./cognee/eval_framework/run_eval.py
|
||||
|
||||
test-descriptive-metrics:
|
||||
name: Run Descriptive Metrics Example
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: '3.11.x'
|
||||
|
||||
- name: Setup Neo4j with GDS
|
||||
uses: ./.github/actions/setup_neo4j
|
||||
id: neo4j
|
||||
|
||||
- name: Run Descriptive Graph Metrics Example
|
||||
env:
|
||||
ENV: 'dev'
|
||||
ENABLE_BACKEND_ACCESS_CONTROL: 'false'
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
GRAPH_DATABASE_PROVIDER: "neo4j"
|
||||
GRAPH_DATABASE_URL: ${{ steps.neo4j.outputs.neo4j-url }}
|
||||
GRAPH_DATABASE_USERNAME: ${{ steps.neo4j.outputs.neo4j-username }}
|
||||
GRAPH_DATABASE_PASSWORD: ${{ steps.neo4j.outputs.neo4j-password }}
|
||||
run: uv run python ./cognee/tests/tasks/descriptive_metrics/neo4j_metrics_test.py
|
||||
|
||||
test-temporal-example:
|
||||
name: Run Temporal Tests
|
||||
runs-on: ubuntu-22.04
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: '3.11.x'
|
||||
|
||||
- name: Run Temporal Example
|
||||
env:
|
||||
ENV: 'dev'
|
||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
run: uv run python ./examples/demos/temporal_awareness_example/temporal_awareness_example.py
|
||||
|
||||
test-ontology-example:
|
||||
name: Run Ontology Tests
|
||||
runs-on: ubuntu-22.04
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: '3.11.x'
|
||||
|
||||
- name: Run Ontology Demo Example
|
||||
env:
|
||||
ENV: 'dev'
|
||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
run: uv run python ./examples/demos/ontology_reference_vocabulary/ontology_as_reference_vocabulary_example.py
|
||||
|
||||
test-feedback-score-shifting-example:
|
||||
name: Run Feedback Score Shifting Example
|
||||
runs-on: ubuntu-22.04
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: '3.11.x'
|
||||
|
||||
- name: Run Feedback Score Shifting Example
|
||||
env:
|
||||
ENV: 'dev'
|
||||
CACHING: 'true'
|
||||
CACHE_BACKEND: 'fs'
|
||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
run: uv run python ./examples/demos/feedback_score_shifting_example.py
|
||||
|
||||
test-agentic-reasoning:
|
||||
name: Run Agentic Reasoning Tests
|
||||
runs-on: ubuntu-22.04
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: '3.11.x'
|
||||
|
||||
- name: Run Agentic Reasoning Example
|
||||
env:
|
||||
ENV: 'dev'
|
||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
run: uv run python ./examples/custom_pipelines/agentic_reasoning_procurement_example.py
|
||||
|
||||
test-memify:
|
||||
name: Run Memify Example
|
||||
runs-on: ubuntu-22.04
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: '3.11.x'
|
||||
|
||||
- name: Run Memify Tests
|
||||
env:
|
||||
ENV: 'dev'
|
||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
run: uv run python ./examples/custom_pipelines/memify_coding_agent_rule_extraction_example.py
|
||||
|
||||
test-custom-pipeline:
|
||||
name: Run Custom Pipeline Example
|
||||
runs-on: ubuntu-22.04
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: '3.11.x'
|
||||
|
||||
- name: Run Custom Pipeline Example
|
||||
env:
|
||||
ENV: 'dev'
|
||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
run: uv run python ./examples/custom_pipelines/custom_cognify_pipeline_example.py
|
||||
|
||||
test-permissions-example:
|
||||
name: Run Permissions Example
|
||||
runs-on: ubuntu-22.04
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: '3.11.x'
|
||||
|
||||
- name: Run Permissions Example
|
||||
env:
|
||||
ENV: 'dev'
|
||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
run: uv run python ./examples/configurations/permissions_example/user_permissions_and_access_control_example.py
|
||||
|
||||
test-s3-permissions-example: # Make sure permission and multi-user mode work with S3 file system
|
||||
name: Run Permissions Example
|
||||
runs-on: ubuntu-22.04
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
services:
|
||||
postgres: # Using postgres to avoid storing and using SQLite from S3
|
||||
image: ghcr.io/topoteretes/pgvector:pg17
|
||||
credentials:
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
env:
|
||||
POSTGRES_USER: cognee
|
||||
POSTGRES_PASSWORD: cognee
|
||||
POSTGRES_DB: cognee_db
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
ports:
|
||||
- 5432:5432
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: '3.11.x'
|
||||
extra-dependencies: "postgres aws"
|
||||
|
||||
- name: Run S3 Permissions Example
|
||||
env:
|
||||
ENV: 'dev'
|
||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
STORAGE_BACKEND: 's3'
|
||||
AWS_REGION: eu-west-1
|
||||
AWS_ENDPOINT_URL: https://s3-eu-west-1.amazonaws.com
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_S3_DEV_USER_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_S3_DEV_USER_SECRET_KEY }}
|
||||
STORAGE_BUCKET_NAME: github-runner-cognee-tests
|
||||
DATA_ROOT_DIRECTORY: "s3://github-runner-cognee-tests/cognee/data"
|
||||
SYSTEM_ROOT_DIRECTORY: "s3://github-runner-cognee-tests/cognee/system"
|
||||
DB_PROVIDER: 'postgres'
|
||||
DB_NAME: 'cognee_db'
|
||||
DB_HOST: ${{ inputs.ci-image != '' && 'postgres' || '127.0.0.1' }}
|
||||
DB_PORT: 5432
|
||||
DB_USERNAME: cognee
|
||||
DB_PASSWORD: cognee
|
||||
run: uv run python ./examples/configurations/permissions_example/user_permissions_and_access_control_example.py
|
||||
|
||||
# Docling test - NO container (runs on macOS, container only works on Linux)
|
||||
test_docling_add:
|
||||
name: Run Add with Docling Test
|
||||
runs-on: macos-15
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: '3.11.x'
|
||||
extra-dependencies: 'docling'
|
||||
|
||||
- name: Run Docling Test
|
||||
env:
|
||||
ENV: 'dev'
|
||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
run: |
|
||||
uv sync --extra docling
|
||||
uv run python ./cognee/tests/test_add_docling_document.py
|
||||
@@ -0,0 +1,225 @@
|
||||
name: Reusable Graph DB Tests
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: read
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
databases:
|
||||
required: false
|
||||
type: string
|
||||
default: "all"
|
||||
description: "Which vector databases to test (comma-separated list or 'all')"
|
||||
python-version:
|
||||
required: false
|
||||
type: string
|
||||
default: "3.11.x"
|
||||
description: "Python version to use for testing"
|
||||
ci-image:
|
||||
required: false
|
||||
type: string
|
||||
default: ''
|
||||
|
||||
env:
|
||||
COGNEE_SKIP_CONNECTION_TEST: 'true'
|
||||
|
||||
jobs:
|
||||
run-kuzu-tests:
|
||||
name: Kuzu Tests
|
||||
runs-on: ubuntu-22.04
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
if: ${{ inputs.databases == 'all' || contains(inputs.databases, 'kuzu') }}
|
||||
steps:
|
||||
- name: Check out
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: ${{ inputs.python-version }}
|
||||
|
||||
- name: Dependencies already installed
|
||||
run: echo "Dependencies already installed in setup"
|
||||
|
||||
- name: Run Kuzu Tests
|
||||
env:
|
||||
ENV: 'dev'
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
run: uv run python ./cognee/tests/test_kuzu.py
|
||||
|
||||
- name: Run Weighted Edges Tests with Kuzu
|
||||
env:
|
||||
ENV: 'dev'
|
||||
GRAPH_DATABASE_PROVIDER: "kuzu"
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
run: uv run pytest cognee/tests/unit/interfaces/graph/test_weighted_edges.py -v
|
||||
|
||||
run-postgres-tests:
|
||||
name: Postgres Graph Tests
|
||||
runs-on: ubuntu-22.04
|
||||
if: ${{ inputs.databases == 'all' || contains(inputs.databases, 'postgres') }}
|
||||
services:
|
||||
postgres:
|
||||
image: ghcr.io/topoteretes/pgvector:pg17
|
||||
credentials:
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
env:
|
||||
POSTGRES_USER: cognee
|
||||
POSTGRES_PASSWORD: cognee
|
||||
POSTGRES_DB: cognee_db
|
||||
ports:
|
||||
- 5432:5432
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
steps:
|
||||
- name: Check out
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: ${{ inputs.python-version }}
|
||||
extra-dependencies: postgres
|
||||
|
||||
- name: Run Postgres Adapter Unit Tests
|
||||
env:
|
||||
DB_PROVIDER: postgres
|
||||
DB_HOST: localhost
|
||||
DB_PORT: 5432
|
||||
DB_USERNAME: cognee
|
||||
DB_PASSWORD: cognee
|
||||
DB_NAME: cognee_db
|
||||
run: uv run pytest cognee/tests/e2e/postgres/test_postgres_adapter.py -v
|
||||
|
||||
- name: Run Postgres Graph E2E Test
|
||||
env:
|
||||
ENV: 'dev'
|
||||
GRAPH_DATABASE_PROVIDER: "postgres"
|
||||
GRAPH_DATABASE_URL: "postgresql+asyncpg://cognee:cognee@localhost:5432/cognee_db"
|
||||
DB_PROVIDER: postgres
|
||||
DB_HOST: localhost
|
||||
DB_PORT: 5432
|
||||
DB_USERNAME: cognee
|
||||
DB_PASSWORD: cognee
|
||||
DB_NAME: cognee_db
|
||||
ENABLE_BACKEND_ACCESS_CONTROL: 'false'
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
run: uv run python ./cognee/tests/e2e/postgres/test_graphdb_postgres.py
|
||||
|
||||
# - name: Run Postgres Hybrid Adapter Tests
|
||||
# env:
|
||||
# ENV: 'dev'
|
||||
# DB_PROVIDER: postgres
|
||||
# DB_HOST: localhost
|
||||
# DB_PORT: 5432
|
||||
# DB_USERNAME: cognee
|
||||
# DB_PASSWORD: cognee
|
||||
# DB_NAME: cognee_db
|
||||
# EMBEDDING_DIMENSIONS: 300
|
||||
# EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
# EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
# run: uv run pytest cognee/tests/e2e/postgres/test_postgres_hybrid_adapter.py -v
|
||||
#
|
||||
# - name: Run Postgres Hybrid E2E Test
|
||||
# env:
|
||||
# ENV: 'dev'
|
||||
# USE_UNIFIED_PROVIDER: "pghybrid"
|
||||
# DB_PROVIDER: postgres
|
||||
# DB_HOST: localhost
|
||||
# DB_PORT: 5432
|
||||
# DB_USERNAME: cognee
|
||||
# DB_PASSWORD: cognee
|
||||
# DB_NAME: cognee_db
|
||||
# ENABLE_BACKEND_ACCESS_CONTROL: 'false'
|
||||
# LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
# LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
# LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
# LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
# LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
# EMBEDDING_DIMENSIONS: 300
|
||||
# EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
# EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
# run: uv run python ./cognee/tests/e2e/postgres/test_pghybrid.py
|
||||
|
||||
run-neo4j-tests:
|
||||
name: Neo4j Tests
|
||||
runs-on: ubuntu-22.04
|
||||
if: ${{ inputs.databases == 'all' || contains(inputs.databases, 'neo4j') }}
|
||||
steps:
|
||||
- name: Check out
|
||||
uses: actions/checkout@master
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: ${{ inputs.python-version }}
|
||||
|
||||
- name: Setup Neo4j with GDS
|
||||
uses: ./.github/actions/setup_neo4j
|
||||
id: neo4j
|
||||
|
||||
- name: Run default Neo4j
|
||||
env:
|
||||
ENV: 'dev'
|
||||
ENABLE_BACKEND_ACCESS_CONTROL: 'false'
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
GRAPH_DATABASE_PROVIDER: "neo4j"
|
||||
GRAPH_DATABASE_URL: ${{ steps.neo4j.outputs.neo4j-url }}
|
||||
GRAPH_DATABASE_USERNAME: ${{ steps.neo4j.outputs.neo4j-username }}
|
||||
GRAPH_DATABASE_PASSWORD: ${{ steps.neo4j.outputs.neo4j-password }}
|
||||
run: uv run python ./cognee/tests/test_neo4j.py
|
||||
|
||||
- name: Run Weighted Edges Tests with Neo4j
|
||||
env:
|
||||
ENV: 'dev'
|
||||
GRAPH_DATABASE_PROVIDER: "neo4j"
|
||||
GRAPH_DATABASE_URL: ${{ secrets.NEO4J_API_URL }}
|
||||
GRAPH_DATABASE_PASSWORD: ${{ secrets.NEO4J_API_KEY }}
|
||||
GRAPH_DATABASE_USERNAME: "neo4j"
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
run: uv run pytest cognee/tests/unit/interfaces/graph/test_weighted_edges.py -v
|
||||
@@ -0,0 +1,192 @@
|
||||
name: Reusable Integration Tests
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: read
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
ci-image:
|
||||
required: false
|
||||
type: string
|
||||
default: ''
|
||||
|
||||
env:
|
||||
COGNEE_SKIP_CONNECTION_TEST: 'true'
|
||||
|
||||
jobs:
|
||||
integration-retrieval:
|
||||
name: Integration - Retrieval (${{ matrix.split-group }}/4)
|
||||
runs-on: ubuntu-22.04
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
split-group: [1, 2, 3, 4]
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
env:
|
||||
ENV: 'dev'
|
||||
LLM_PROVIDER: openai
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: '3.11.x'
|
||||
extra-dependencies: "scraping fastembed"
|
||||
|
||||
- name: Run Retrieval Tests
|
||||
run: uv run pytest cognee/tests/integration/retrieval/ --splits 4 --group ${{ matrix.split-group }}
|
||||
|
||||
integration-documents-tasks:
|
||||
name: Integration - Documents & Tasks (${{ matrix.split-group }}/2)
|
||||
runs-on: ubuntu-22.04
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
split-group: [1, 2]
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
env:
|
||||
ENV: 'dev'
|
||||
LLM_PROVIDER: openai
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: '3.11.x'
|
||||
extra-dependencies: "scraping"
|
||||
|
||||
- name: Run Document & Task Tests
|
||||
run: uv run pytest cognee/tests/integration/documents/ cognee/tests/integration/tasks/ --splits 2 --group ${{ matrix.split-group }}
|
||||
|
||||
integration-infra:
|
||||
name: Integration - Infrastructure (${{ matrix.split-group }}/3)
|
||||
runs-on: ubuntu-22.04
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
split-group: [1, 2, 3]
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
env:
|
||||
ENV: 'dev'
|
||||
LLM_PROVIDER: openai
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: '3.11.x'
|
||||
# fastembed so the embedding tokenizer delegation tests can import
|
||||
# FastembedEmbeddingEngine.
|
||||
extra-dependencies: "scraping fastembed"
|
||||
|
||||
- name: Run Infrastructure Tests
|
||||
run: uv run pytest cognee/tests/integration/infrastructure/ --splits 3 --group ${{ matrix.split-group }}
|
||||
|
||||
integration-web:
|
||||
name: Integration - Web
|
||||
runs-on: ubuntu-22.04
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
env:
|
||||
ENV: 'dev'
|
||||
LLM_PROVIDER: openai
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: '3.11.x'
|
||||
extra-dependencies: "scraping"
|
||||
|
||||
- name: Run Web Integration Tests
|
||||
run: uv run pytest cognee/tests/integration/web_url_crawler/
|
||||
|
||||
integration-other:
|
||||
name: Integration - Deletion & Misc
|
||||
runs-on: ubuntu-22.04
|
||||
services:
|
||||
redis:
|
||||
image: redis:7
|
||||
ports:
|
||||
- 6379:6379
|
||||
options: >-
|
||||
--health-cmd "redis-cli ping"
|
||||
--health-interval 5s
|
||||
--health-timeout 3s
|
||||
--health-retries 5
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
env:
|
||||
ENV: 'dev'
|
||||
LLM_PROVIDER: openai
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
CACHE_HOST: redis
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: '3.11.x'
|
||||
extra-dependencies: "scraping redis"
|
||||
|
||||
- name: Run Deletion & Misc Tests
|
||||
run: uv run pytest cognee/tests/integration/test_delete_edge_cases.py cognee/tests/integration/shared/
|
||||
@@ -0,0 +1,74 @@
|
||||
name: Label PRs from core team
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened, reopened, synchronize, ready_for_review, edited]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
|
||||
jobs:
|
||||
label-core-team:
|
||||
if: ${{ !github.event.pull_request.draft }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out base repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
repository: ${{ github.repository }}
|
||||
ref: ${{ github.event.pull_request.base.ref }}
|
||||
|
||||
- name: Determine if PR author is a core team member
|
||||
id: check_core
|
||||
shell: bash
|
||||
run: |
|
||||
AUTHOR="${{ github.event.pull_request.user.login }}"
|
||||
LIST_FILE=".github/core-team.txt"
|
||||
|
||||
if [ ! -f "$LIST_FILE" ]; then
|
||||
echo "core=false" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Normalize author to lowercase and strip leading '@'
|
||||
AUTHOR_NORM="$(echo "$AUTHOR" | tr '[:upper:]' '[:lower:]' | sed 's/^@//')"
|
||||
|
||||
# Compare against normalized list values (ignore comments/blank lines)
|
||||
if awk -v author="$AUTHOR_NORM" '
|
||||
BEGIN { found=0 }
|
||||
{
|
||||
line=$0
|
||||
sub(/^[ \t]+|[ \t]+$/, "", line)
|
||||
if (line ~ /^#/ || line == "") next
|
||||
sub(/^@/, "", line)
|
||||
line=tolower(line)
|
||||
if (line == author) { found=1; exit }
|
||||
}
|
||||
END { exit(found ? 0 : 1) }
|
||||
' "$LIST_FILE"; then
|
||||
echo "core=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "core=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
- name: Add core-team label
|
||||
if: steps.check_core.outputs.core == 'true'
|
||||
uses: actions/github-script@v8
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
const label = 'core-team';
|
||||
const { owner, repo } = context.repo;
|
||||
const prNumber = context.payload.pull_request.number;
|
||||
try {
|
||||
await github.rest.issues.addLabels({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: prNumber,
|
||||
labels: [label],
|
||||
});
|
||||
core.info(`Label '${label}' added to PR #${prNumber}`);
|
||||
} catch (error) {
|
||||
core.warning(`Failed to add label: ${error.message}`);
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
name: Load tests
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: read
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
workflow_call:
|
||||
inputs:
|
||||
ci-image:
|
||||
required: false
|
||||
type: string
|
||||
default: ''
|
||||
secrets:
|
||||
LLM_MODEL:
|
||||
required: true
|
||||
LLM_ENDPOINT:
|
||||
required: true
|
||||
LLM_API_KEY:
|
||||
required: true
|
||||
LLM_ARGS:
|
||||
required: false
|
||||
LLM_API_VERSION:
|
||||
required: true
|
||||
EMBEDDING_MODEL:
|
||||
required: true
|
||||
EMBEDDING_API_KEY:
|
||||
required: true
|
||||
OPENAI_API_KEY:
|
||||
required: true
|
||||
AWS_ACCESS_KEY_ID:
|
||||
required: true
|
||||
AWS_SECRET_ACCESS_KEY:
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
test-load:
|
||||
name: Test Load
|
||||
runs-on: ubuntu-22.04
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: '3.11.x'
|
||||
extra-dependencies: "aws"
|
||||
|
||||
- name: Verify File Descriptor Limit
|
||||
run: ulimit -n
|
||||
|
||||
- name: Run Load Test
|
||||
env:
|
||||
ENV: 'dev'
|
||||
ENABLE_BACKEND_ACCESS_CONTROL: True
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
STORAGE_BACKEND: s3
|
||||
AWS_REGION: eu-west-1
|
||||
AWS_ENDPOINT_URL: https://s3-eu-west-1.amazonaws.com
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_S3_DEV_USER_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_S3_DEV_USER_SECRET_KEY }}
|
||||
run: uv run python ./cognee/tests/test_load.py
|
||||
@@ -0,0 +1,54 @@
|
||||
name: Mirror external images to GHCR
|
||||
|
||||
# Copies the pinned third-party images CI depends on (pgvector) into GHCR, so the
|
||||
# PR / test hot path never pulls from Docker Hub — which is rate-limited and flaky
|
||||
# from GitHub Actions (intermittent `registry-1.docker.io ... timeout` on service
|
||||
# container setup). The test workflows reference ghcr.io/<owner>/pgvector:pg17.
|
||||
#
|
||||
# Runs weekly for freshness and on-demand. IMPORTANT: run this once (Actions ->
|
||||
# "Mirror external images to GHCR" -> Run workflow) BEFORE the GHCR references go
|
||||
# live, so the image exists. Ensure the resulting GHCR package is accessible to
|
||||
# this repo (public, or repo-linked) so service pulls with GITHUB_TOKEN succeed.
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 6 * * 1" # Mondays 06:00 UTC
|
||||
workflow_dispatch: {}
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
mirror:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
image:
|
||||
- pgvector/pgvector:pg17
|
||||
steps:
|
||||
- name: Log in to Docker Hub (authenticated source pulls)
|
||||
uses: docker/login-action@v3
|
||||
continue-on-error: true # best-effort: fall back to anonymous if unset
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Log in to GHCR
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Mirror ${{ matrix.image }} -> GHCR
|
||||
run: |
|
||||
set -euo pipefail
|
||||
SRC="${{ matrix.image }}"
|
||||
DST="ghcr.io/${{ github.repository_owner }}/${SRC##*/}"
|
||||
echo "Mirroring $SRC -> $DST"
|
||||
docker pull "$SRC"
|
||||
docker tag "$SRC" "$DST"
|
||||
docker push "$DST"
|
||||
echo "Done: $DST"
|
||||
@@ -0,0 +1,246 @@
|
||||
name: Nightly Tests
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 3 * * *'
|
||||
workflow_dispatch:
|
||||
# Note: Run Nightly CI on change to any of the following files.
|
||||
pull_request:
|
||||
paths:
|
||||
- '.github/workflows/nightly_tests.yml'
|
||||
- '.github/workflows/performance_report.yml'
|
||||
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
RUNTIME__LOG_LEVEL: ERROR
|
||||
ENV: 'dev'
|
||||
|
||||
jobs:
|
||||
ollama-tests:
|
||||
name: Ollama Tests
|
||||
uses: ./.github/workflows/test_ollama.yml
|
||||
secrets: inherit
|
||||
|
||||
llamacpp-tests:
|
||||
name: Llama-cpp Tests
|
||||
uses: ./.github/workflows/test_llamacpp.yml
|
||||
secrets: inherit
|
||||
|
||||
# ══ Performance: each caller runs BOTH file_based and postgres backends ════
|
||||
perf-small-llm:
|
||||
name: Performance — 50 Small Documents (real LLM)
|
||||
uses: ./.github/workflows/performance_report.yml
|
||||
with:
|
||||
mode: llm
|
||||
label: 50_small_documents
|
||||
runs: '3'
|
||||
num_memories: '50'
|
||||
memories_key: nightly_ci_artifacts/performance_test_artifacts/memories.json
|
||||
secrets: inherit
|
||||
|
||||
perf-small-mock:
|
||||
name: Performance — 50 Small Documents (mock LLM)
|
||||
uses: ./.github/workflows/performance_report.yml
|
||||
with:
|
||||
mode: mock_llm
|
||||
label: 50_small_documents
|
||||
runs: '3'
|
||||
num_memories: '50'
|
||||
memories_key: nightly_ci_artifacts/performance_test_artifacts/memories.json
|
||||
mock_memories_key: nightly_ci_artifacts/performance_test_artifacts/mock_memories.json
|
||||
secrets: inherit
|
||||
|
||||
perf-wap-llm:
|
||||
name: Performance — War and Peace (real LLM)
|
||||
uses: ./.github/workflows/performance_report.yml
|
||||
with:
|
||||
mode: llm
|
||||
label: war_and_peace
|
||||
runs: '3'
|
||||
memories_key: nightly_ci_artifacts/performance_test_artifacts/war_and_peace.json
|
||||
secrets: inherit
|
||||
|
||||
perf-wap-mock:
|
||||
name: Performance — War and Peace (mock LLM)
|
||||
uses: ./.github/workflows/performance_report.yml
|
||||
with:
|
||||
mode: mock_llm
|
||||
label: war_and_peace
|
||||
runs: '3'
|
||||
memories_key: nightly_ci_artifacts/performance_test_artifacts/war_and_peace.json
|
||||
mock_memories_key: nightly_ci_artifacts/performance_test_artifacts/mock_war_and_peace.json
|
||||
secrets: inherit
|
||||
|
||||
notify:
|
||||
name: Test Completion Status
|
||||
needs: [
|
||||
ollama-tests,
|
||||
llamacpp-tests,
|
||||
perf-small-llm,
|
||||
perf-small-mock,
|
||||
perf-wap-llm,
|
||||
perf-wap-mock,
|
||||
]
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ !cancelled() }}
|
||||
steps:
|
||||
- name: Determine status
|
||||
id: status
|
||||
run: |
|
||||
if [[ "${{ needs.ollama-tests.result }}" == "success" &&
|
||||
"${{ needs.llamacpp-tests.result }}" == "success" &&
|
||||
"${{ needs.perf-small-llm.result }}" == "success" &&
|
||||
"${{ needs.perf-small-mock.result }}" == "success" &&
|
||||
"${{ needs.perf-wap-llm.result }}" == "success" &&
|
||||
"${{ needs.perf-wap-mock.result }}" == "success" ]]; then
|
||||
echo "passed=true" >> "$GITHUB_OUTPUT"
|
||||
echo "emoji=✅" >> "$GITHUB_OUTPUT"
|
||||
echo "summary=All nightly test suites completed successfully!" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "passed=false" >> "$GITHUB_OUTPUT"
|
||||
echo "emoji=❌" >> "$GITHUB_OUTPUT"
|
||||
echo "summary=One or more nightly test suites failed." >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
echo "ran_at=$(date -u '+%Y-%m-%d %H:%M UTC')" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Presign performance report links
|
||||
id: presign
|
||||
env:
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_S3_DEV_USER_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_S3_DEV_USER_SECRET_KEY }}
|
||||
AWS_DEFAULT_REGION: eu-west-1
|
||||
BUCKET: github-runner-cognee-tests
|
||||
# "<slack-output-name> <s3-key>" per line. The key already encodes the
|
||||
# backend (file_based/ or postgres/), so presigning is fully generic.
|
||||
REPORT_KEYS: |
|
||||
url_file_small_llm ${{ needs.perf-small-llm.outputs.file_based_html_key }}
|
||||
url_file_small_mock ${{ needs.perf-small-mock.outputs.file_based_html_key }}
|
||||
url_file_wap_llm ${{ needs.perf-wap-llm.outputs.file_based_html_key }}
|
||||
url_file_wap_mock ${{ needs.perf-wap-mock.outputs.file_based_html_key }}
|
||||
url_pg_small_llm ${{ needs.perf-small-llm.outputs.postgres_html_key }}
|
||||
url_pg_small_mock ${{ needs.perf-small-mock.outputs.postgres_html_key }}
|
||||
url_pg_wap_llm ${{ needs.perf-wap-llm.outputs.postgres_html_key }}
|
||||
url_pg_wap_mock ${{ needs.perf-wap-mock.outputs.postgres_html_key }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# 7 days = 604800s is the maximum lifetime for an IAM-user presigned URL.
|
||||
# Skip empty keys (a failed perf job produces no report).
|
||||
while read -r name key; do
|
||||
[ -n "${key:-}" ] || continue
|
||||
echo "$name=$(aws s3 presign "s3://$BUCKET/$key" --expires-in 604800)" >> "$GITHUB_OUTPUT"
|
||||
done <<< "$REPORT_KEYS"
|
||||
|
||||
- name: Post status to Slack
|
||||
uses: slackapi/slack-github-action@v2.1.0
|
||||
with:
|
||||
method: chat.postMessage
|
||||
token: ${{ secrets.SLACK_NIGHTLY_BOT_TOKEN }}
|
||||
payload: |
|
||||
channel: ${{ secrets.SLACK_NIGHTLY_CHANNEL_ID }}
|
||||
text: "${{ steps.status.outputs.emoji }} Nightly Tests (${{ steps.status.outputs.ran_at }}): ${{ steps.status.outputs.summary }}"
|
||||
blocks:
|
||||
- type: "section"
|
||||
text:
|
||||
type: "mrkdwn"
|
||||
text: |
|
||||
${{ steps.status.outputs.emoji }} *Nightly Tests* — ${{ steps.status.outputs.summary }}
|
||||
*Ran at:* `${{ steps.status.outputs.ran_at }}`
|
||||
*Ollama:* `${{ needs.ollama-tests.result }}` • *Llama-cpp:* `${{ needs.llamacpp-tests.result }}`
|
||||
- type: "section"
|
||||
text:
|
||||
type: "mrkdwn"
|
||||
text: |
|
||||
*📊 File Based — 50 Small Documents — Real LLM* (`${{ needs.perf-small-llm.result }}`) • runs `${{ fromJSON(needs.perf-small-llm.outputs.file_based_metrics || '{}').success }}`
|
||||
add p50 `${{ fromJSON(needs.perf-small-llm.outputs.file_based_metrics || '{}').add.p50 }}s` • p90 `${{ fromJSON(needs.perf-small-llm.outputs.file_based_metrics || '{}').add.p90 }}s` • p99 `${{ fromJSON(needs.perf-small-llm.outputs.file_based_metrics || '{}').add.p99 }}s`
|
||||
cognify p50 `${{ fromJSON(needs.perf-small-llm.outputs.file_based_metrics || '{}').cognify.p50 }}s` • p90 `${{ fromJSON(needs.perf-small-llm.outputs.file_based_metrics || '{}').cognify.p90 }}s` • p99 `${{ fromJSON(needs.perf-small-llm.outputs.file_based_metrics || '{}').cognify.p99 }}s`
|
||||
search p50 `${{ fromJSON(needs.perf-small-llm.outputs.file_based_metrics || '{}').search.p50 }}s` • p90 `${{ fromJSON(needs.perf-small-llm.outputs.file_based_metrics || '{}').search.p90 }}s` • p99 `${{ fromJSON(needs.perf-small-llm.outputs.file_based_metrics || '{}').search.p99 }}s`
|
||||
total p50 `${{ fromJSON(needs.perf-small-llm.outputs.file_based_metrics || '{}').total.p50 }}s` • p90 `${{ fromJSON(needs.perf-small-llm.outputs.file_based_metrics || '{}').total.p90 }}s` • p99 `${{ fromJSON(needs.perf-small-llm.outputs.file_based_metrics || '{}').total.p99 }}s`
|
||||
<${{ steps.presign.outputs.url_file_small_llm }}|HTML report>
|
||||
- type: "section"
|
||||
text:
|
||||
type: "mrkdwn"
|
||||
text: |
|
||||
*📊 File Based — 50 Small Documents — Mock LLM* (`${{ needs.perf-small-mock.result }}`) • runs `${{ fromJSON(needs.perf-small-mock.outputs.file_based_metrics || '{}').success }}`
|
||||
add p50 `${{ fromJSON(needs.perf-small-mock.outputs.file_based_metrics || '{}').add.p50 }}s` • p90 `${{ fromJSON(needs.perf-small-mock.outputs.file_based_metrics || '{}').add.p90 }}s` • p99 `${{ fromJSON(needs.perf-small-mock.outputs.file_based_metrics || '{}').add.p99 }}s`
|
||||
cognify p50 `${{ fromJSON(needs.perf-small-mock.outputs.file_based_metrics || '{}').cognify.p50 }}s` • p90 `${{ fromJSON(needs.perf-small-mock.outputs.file_based_metrics || '{}').cognify.p90 }}s` • p99 `${{ fromJSON(needs.perf-small-mock.outputs.file_based_metrics || '{}').cognify.p99 }}s`
|
||||
search p50 `${{ fromJSON(needs.perf-small-mock.outputs.file_based_metrics || '{}').search.p50 }}s` • p90 `${{ fromJSON(needs.perf-small-mock.outputs.file_based_metrics || '{}').search.p90 }}s` • p99 `${{ fromJSON(needs.perf-small-mock.outputs.file_based_metrics || '{}').search.p99 }}s`
|
||||
total p50 `${{ fromJSON(needs.perf-small-mock.outputs.file_based_metrics || '{}').total.p50 }}s` • p90 `${{ fromJSON(needs.perf-small-mock.outputs.file_based_metrics || '{}').total.p90 }}s` • p99 `${{ fromJSON(needs.perf-small-mock.outputs.file_based_metrics || '{}').total.p99 }}s`
|
||||
<${{ steps.presign.outputs.url_file_small_mock }}|HTML report>
|
||||
- type: "section"
|
||||
text:
|
||||
type: "mrkdwn"
|
||||
text: |
|
||||
*📚 File Based — War and Peace — Real LLM* (`${{ needs.perf-wap-llm.result }}`) • runs `${{ fromJSON(needs.perf-wap-llm.outputs.file_based_metrics || '{}').success }}`
|
||||
add p50 `${{ fromJSON(needs.perf-wap-llm.outputs.file_based_metrics || '{}').add.p50 }}s` • p90 `${{ fromJSON(needs.perf-wap-llm.outputs.file_based_metrics || '{}').add.p90 }}s` • p99 `${{ fromJSON(needs.perf-wap-llm.outputs.file_based_metrics || '{}').add.p99 }}s`
|
||||
cognify p50 `${{ fromJSON(needs.perf-wap-llm.outputs.file_based_metrics || '{}').cognify.p50 }}s` • p90 `${{ fromJSON(needs.perf-wap-llm.outputs.file_based_metrics || '{}').cognify.p90 }}s` • p99 `${{ fromJSON(needs.perf-wap-llm.outputs.file_based_metrics || '{}').cognify.p99 }}s`
|
||||
search p50 `${{ fromJSON(needs.perf-wap-llm.outputs.file_based_metrics || '{}').search.p50 }}s` • p90 `${{ fromJSON(needs.perf-wap-llm.outputs.file_based_metrics || '{}').search.p90 }}s` • p99 `${{ fromJSON(needs.perf-wap-llm.outputs.file_based_metrics || '{}').search.p99 }}s`
|
||||
total p50 `${{ fromJSON(needs.perf-wap-llm.outputs.file_based_metrics || '{}').total.p50 }}s` • p90 `${{ fromJSON(needs.perf-wap-llm.outputs.file_based_metrics || '{}').total.p90 }}s` • p99 `${{ fromJSON(needs.perf-wap-llm.outputs.file_based_metrics || '{}').total.p99 }}s`
|
||||
<${{ steps.presign.outputs.url_file_wap_llm }}|HTML report>
|
||||
- type: "section"
|
||||
text:
|
||||
type: "mrkdwn"
|
||||
text: |
|
||||
*📚 File Based — War and Peace — Mock LLM* (`${{ needs.perf-wap-mock.result }}`) • runs `${{ fromJSON(needs.perf-wap-mock.outputs.file_based_metrics || '{}').success }}`
|
||||
add p50 `${{ fromJSON(needs.perf-wap-mock.outputs.file_based_metrics || '{}').add.p50 }}s` • p90 `${{ fromJSON(needs.perf-wap-mock.outputs.file_based_metrics || '{}').add.p90 }}s` • p99 `${{ fromJSON(needs.perf-wap-mock.outputs.file_based_metrics || '{}').add.p99 }}s`
|
||||
cognify p50 `${{ fromJSON(needs.perf-wap-mock.outputs.file_based_metrics || '{}').cognify.p50 }}s` • p90 `${{ fromJSON(needs.perf-wap-mock.outputs.file_based_metrics || '{}').cognify.p90 }}s` • p99 `${{ fromJSON(needs.perf-wap-mock.outputs.file_based_metrics || '{}').cognify.p99 }}s`
|
||||
search p50 `${{ fromJSON(needs.perf-wap-mock.outputs.file_based_metrics || '{}').search.p50 }}s` • p90 `${{ fromJSON(needs.perf-wap-mock.outputs.file_based_metrics || '{}').search.p90 }}s` • p99 `${{ fromJSON(needs.perf-wap-mock.outputs.file_based_metrics || '{}').search.p99 }}s`
|
||||
total p50 `${{ fromJSON(needs.perf-wap-mock.outputs.file_based_metrics || '{}').total.p50 }}s` • p90 `${{ fromJSON(needs.perf-wap-mock.outputs.file_based_metrics || '{}').total.p90 }}s` • p99 `${{ fromJSON(needs.perf-wap-mock.outputs.file_based_metrics || '{}').total.p99 }}s`
|
||||
<${{ steps.presign.outputs.url_file_wap_mock }}|HTML report>
|
||||
- type: "section"
|
||||
text:
|
||||
type: "mrkdwn"
|
||||
text: |
|
||||
*📊 Full Postgres — 50 Small Documents — Real LLM* (`${{ needs.perf-small-llm.result }}`) • runs `${{ fromJSON(needs.perf-small-llm.outputs.postgres_metrics || '{}').success }}`
|
||||
add p50 `${{ fromJSON(needs.perf-small-llm.outputs.postgres_metrics || '{}').add.p50 }}s` • p90 `${{ fromJSON(needs.perf-small-llm.outputs.postgres_metrics || '{}').add.p90 }}s` • p99 `${{ fromJSON(needs.perf-small-llm.outputs.postgres_metrics || '{}').add.p99 }}s`
|
||||
cognify p50 `${{ fromJSON(needs.perf-small-llm.outputs.postgres_metrics || '{}').cognify.p50 }}s` • p90 `${{ fromJSON(needs.perf-small-llm.outputs.postgres_metrics || '{}').cognify.p90 }}s` • p99 `${{ fromJSON(needs.perf-small-llm.outputs.postgres_metrics || '{}').cognify.p99 }}s`
|
||||
search p50 `${{ fromJSON(needs.perf-small-llm.outputs.postgres_metrics || '{}').search.p50 }}s` • p90 `${{ fromJSON(needs.perf-small-llm.outputs.postgres_metrics || '{}').search.p90 }}s` • p99 `${{ fromJSON(needs.perf-small-llm.outputs.postgres_metrics || '{}').search.p99 }}s`
|
||||
total p50 `${{ fromJSON(needs.perf-small-llm.outputs.postgres_metrics || '{}').total.p50 }}s` • p90 `${{ fromJSON(needs.perf-small-llm.outputs.postgres_metrics || '{}').total.p90 }}s` • p99 `${{ fromJSON(needs.perf-small-llm.outputs.postgres_metrics || '{}').total.p99 }}s`
|
||||
<${{ steps.presign.outputs.url_pg_small_llm }}|HTML report>
|
||||
- type: "section"
|
||||
text:
|
||||
type: "mrkdwn"
|
||||
text: |
|
||||
*📊 Full Postgres — 50 Small Documents — Mock LLM* (`${{ needs.perf-small-mock.result }}`) • runs `${{ fromJSON(needs.perf-small-mock.outputs.postgres_metrics || '{}').success }}`
|
||||
add p50 `${{ fromJSON(needs.perf-small-mock.outputs.postgres_metrics || '{}').add.p50 }}s` • p90 `${{ fromJSON(needs.perf-small-mock.outputs.postgres_metrics || '{}').add.p90 }}s` • p99 `${{ fromJSON(needs.perf-small-mock.outputs.postgres_metrics || '{}').add.p99 }}s`
|
||||
cognify p50 `${{ fromJSON(needs.perf-small-mock.outputs.postgres_metrics || '{}').cognify.p50 }}s` • p90 `${{ fromJSON(needs.perf-small-mock.outputs.postgres_metrics || '{}').cognify.p90 }}s` • p99 `${{ fromJSON(needs.perf-small-mock.outputs.postgres_metrics || '{}').cognify.p99 }}s`
|
||||
search p50 `${{ fromJSON(needs.perf-small-mock.outputs.postgres_metrics || '{}').search.p50 }}s` • p90 `${{ fromJSON(needs.perf-small-mock.outputs.postgres_metrics || '{}').search.p90 }}s` • p99 `${{ fromJSON(needs.perf-small-mock.outputs.postgres_metrics || '{}').search.p99 }}s`
|
||||
total p50 `${{ fromJSON(needs.perf-small-mock.outputs.postgres_metrics || '{}').total.p50 }}s` • p90 `${{ fromJSON(needs.perf-small-mock.outputs.postgres_metrics || '{}').total.p90 }}s` • p99 `${{ fromJSON(needs.perf-small-mock.outputs.postgres_metrics || '{}').total.p99 }}s`
|
||||
<${{ steps.presign.outputs.url_pg_small_mock }}|HTML report>
|
||||
- type: "section"
|
||||
text:
|
||||
type: "mrkdwn"
|
||||
text: |
|
||||
*📚 Full Postgres — War and Peace — Real LLM* (`${{ needs.perf-wap-llm.result }}`) • runs `${{ fromJSON(needs.perf-wap-llm.outputs.postgres_metrics || '{}').success }}`
|
||||
add p50 `${{ fromJSON(needs.perf-wap-llm.outputs.postgres_metrics || '{}').add.p50 }}s` • p90 `${{ fromJSON(needs.perf-wap-llm.outputs.postgres_metrics || '{}').add.p90 }}s` • p99 `${{ fromJSON(needs.perf-wap-llm.outputs.postgres_metrics || '{}').add.p99 }}s`
|
||||
cognify p50 `${{ fromJSON(needs.perf-wap-llm.outputs.postgres_metrics || '{}').cognify.p50 }}s` • p90 `${{ fromJSON(needs.perf-wap-llm.outputs.postgres_metrics || '{}').cognify.p90 }}s` • p99 `${{ fromJSON(needs.perf-wap-llm.outputs.postgres_metrics || '{}').cognify.p99 }}s`
|
||||
search p50 `${{ fromJSON(needs.perf-wap-llm.outputs.postgres_metrics || '{}').search.p50 }}s` • p90 `${{ fromJSON(needs.perf-wap-llm.outputs.postgres_metrics || '{}').search.p90 }}s` • p99 `${{ fromJSON(needs.perf-wap-llm.outputs.postgres_metrics || '{}').search.p99 }}s`
|
||||
total p50 `${{ fromJSON(needs.perf-wap-llm.outputs.postgres_metrics || '{}').total.p50 }}s` • p90 `${{ fromJSON(needs.perf-wap-llm.outputs.postgres_metrics || '{}').total.p90 }}s` • p99 `${{ fromJSON(needs.perf-wap-llm.outputs.postgres_metrics || '{}').total.p99 }}s`
|
||||
<${{ steps.presign.outputs.url_pg_wap_llm }}|HTML report>
|
||||
- type: "section"
|
||||
text:
|
||||
type: "mrkdwn"
|
||||
text: |
|
||||
*📚 Full Postgres — War and Peace — Mock LLM* (`${{ needs.perf-wap-mock.result }}`) • runs `${{ fromJSON(needs.perf-wap-mock.outputs.postgres_metrics || '{}').success }}`
|
||||
add p50 `${{ fromJSON(needs.perf-wap-mock.outputs.postgres_metrics || '{}').add.p50 }}s` • p90 `${{ fromJSON(needs.perf-wap-mock.outputs.postgres_metrics || '{}').add.p90 }}s` • p99 `${{ fromJSON(needs.perf-wap-mock.outputs.postgres_metrics || '{}').add.p99 }}s`
|
||||
cognify p50 `${{ fromJSON(needs.perf-wap-mock.outputs.postgres_metrics || '{}').cognify.p50 }}s` • p90 `${{ fromJSON(needs.perf-wap-mock.outputs.postgres_metrics || '{}').cognify.p90 }}s` • p99 `${{ fromJSON(needs.perf-wap-mock.outputs.postgres_metrics || '{}').cognify.p99 }}s`
|
||||
search p50 `${{ fromJSON(needs.perf-wap-mock.outputs.postgres_metrics || '{}').search.p50 }}s` • p90 `${{ fromJSON(needs.perf-wap-mock.outputs.postgres_metrics || '{}').search.p90 }}s` • p99 `${{ fromJSON(needs.perf-wap-mock.outputs.postgres_metrics || '{}').search.p99 }}s`
|
||||
total p50 `${{ fromJSON(needs.perf-wap-mock.outputs.postgres_metrics || '{}').total.p50 }}s` • p90 `${{ fromJSON(needs.perf-wap-mock.outputs.postgres_metrics || '{}').total.p90 }}s` • p99 `${{ fromJSON(needs.perf-wap-mock.outputs.postgres_metrics || '{}').total.p99 }}s`
|
||||
<${{ steps.presign.outputs.url_pg_wap_mock }}|HTML report>
|
||||
- type: "section"
|
||||
text:
|
||||
type: "mrkdwn"
|
||||
text: |
|
||||
<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View run>
|
||||
|
||||
- name: Fail if any suite failed
|
||||
if: ${{ steps.status.outputs.passed != 'true' }}
|
||||
run: |
|
||||
echo "One or more nightly test suites failed."
|
||||
exit 1
|
||||
@@ -0,0 +1,28 @@
|
||||
name: Reusable Notebook Tests
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
ci-image:
|
||||
required: false
|
||||
type: string
|
||||
default: ''
|
||||
|
||||
env:
|
||||
COGNEE_SKIP_CONNECTION_TEST: 'true'
|
||||
|
||||
jobs:
|
||||
# run-main-notebook:
|
||||
# name: Main Notebook Test
|
||||
# uses: ./.github/workflows/reusable_notebook.yml
|
||||
# with:
|
||||
# notebook-location: notebooks/cognee_demo.ipynb
|
||||
# secrets: inherit
|
||||
|
||||
run-cognee-multimedia:
|
||||
name: Cognee Multimedia Notebook
|
||||
uses: ./.github/workflows/reusable_notebook.yml
|
||||
with:
|
||||
notebook-location: notebooks/cognee_multimedia_demo.ipynb
|
||||
ci-image: ${{ inputs.ci-image }}
|
||||
secrets: inherit
|
||||
@@ -0,0 +1,298 @@
|
||||
name: performance report
|
||||
|
||||
# Reusable workflow: runs the percentile performance report once for a given
|
||||
# dataset + mode, uploads the JSON + HTML artifacts to S3, and exposes the
|
||||
# headline metrics + HTML object key as outputs for the caller (the Slack bot in
|
||||
# nightly_tests.yml).
|
||||
#
|
||||
# Both backends run on every call, as two separate jobs:
|
||||
# - file_based : cognee defaults (SQLite + Kuzu + LanceDB), no services.
|
||||
# - postgres : full Postgres (relational + PGVector + Postgres graph) via a
|
||||
# `services: postgres` container (mirrors e2e_tests.yml).
|
||||
# Each job exposes its own metrics + html_key outputs (file_based_* / postgres_*).
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
mode:
|
||||
description: "Run mode: 'mock_llm' (no API calls) or 'llm' (real LLM)."
|
||||
required: true
|
||||
type: string
|
||||
label:
|
||||
description: "Dataset label, used in the S3 output path and display name."
|
||||
required: true
|
||||
type: string
|
||||
runs:
|
||||
description: "Number of sequential benchmark runs."
|
||||
required: false
|
||||
type: string
|
||||
default: '10'
|
||||
num_memories:
|
||||
description: "If set, forwarded as --num-memories (limit input documents)."
|
||||
required: false
|
||||
type: string
|
||||
default: ''
|
||||
memories_key:
|
||||
description: "S3 object key (under the bucket) downloaded and used as --memories."
|
||||
required: true
|
||||
type: string
|
||||
mock_memories_key:
|
||||
description: "If set, S3 object key downloaded and used as --mock-memories."
|
||||
required: false
|
||||
type: string
|
||||
default: ''
|
||||
outputs:
|
||||
file_based_metrics:
|
||||
description: "File-based run: success + add/cognify/search/total p50/p90/p99."
|
||||
value: ${{ jobs.file_based.outputs.metrics }}
|
||||
file_based_html_key:
|
||||
description: "File-based run: S3 object key of the HTML report."
|
||||
value: ${{ jobs.file_based.outputs.html_key }}
|
||||
postgres_metrics:
|
||||
description: "Postgres run: success + add/cognify/search/total p50/p90/p99."
|
||||
value: ${{ jobs.postgres.outputs.metrics }}
|
||||
postgres_html_key:
|
||||
description: "Postgres run: S3 object key of the HTML report."
|
||||
value: ${{ jobs.postgres.outputs.html_key }}
|
||||
|
||||
env:
|
||||
ENV: 'dev'
|
||||
COGNEE_SKIP_CONNECTION_TEST: 'true'
|
||||
RUNTIME__LOG_LEVEL: ERROR
|
||||
BUCKET: github-runner-cognee-tests
|
||||
|
||||
jobs:
|
||||
# ── File-based backend: SQLite + Kuzu + LanceDB (cognee defaults) ────────────
|
||||
file_based:
|
||||
name: file_based — ${{ inputs.label }} (${{ inputs.mode }})
|
||||
runs-on: ubuntu-22.04
|
||||
outputs:
|
||||
metrics: ${{ steps.parse.outputs.metrics }}
|
||||
html_key: ${{ steps.upload.outputs.html_key }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: '3.11.x'
|
||||
|
||||
- name: Download dataset from S3
|
||||
env:
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_S3_DEV_USER_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_S3_DEV_USER_SECRET_KEY }}
|
||||
AWS_DEFAULT_REGION: eu-west-1
|
||||
MEMORIES_KEY: ${{ inputs.memories_key }}
|
||||
MOCK_MEMORIES_KEY: ${{ inputs.mock_memories_key }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
mkdir -p performance_datasets
|
||||
aws s3 cp "s3://$BUCKET/$MEMORIES_KEY" performance_datasets/memories.json
|
||||
echo "MEMORIES_FILE=$PWD/performance_datasets/memories.json" >> "$GITHUB_ENV"
|
||||
if [ -n "$MOCK_MEMORIES_KEY" ]; then
|
||||
aws s3 cp "s3://$BUCKET/$MOCK_MEMORIES_KEY" performance_datasets/mock_memories.json
|
||||
echo "MOCK_MEMORIES_FILE=$PWD/performance_datasets/mock_memories.json" >> "$GITHUB_ENV"
|
||||
fi
|
||||
|
||||
- name: Run performance report
|
||||
id: run
|
||||
env:
|
||||
PYTHONFAULTHANDLER: 1
|
||||
# LLM + embedding config via the standard CI secrets (see e2e_tests.yml).
|
||||
# Only exercised for mode == 'llm'; the mock run hits no external APIs.
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
TS="$(date -u '+%Y-%m-%d_%H-%M-%SZ')"
|
||||
JSON_PATH="performance_results/file_based/${{ inputs.label }}/${{ inputs.mode }}_${TS}.json"
|
||||
HTML_PATH="performance_results/file_based/${{ inputs.label }}/${{ inputs.mode }}_${TS}.html"
|
||||
mkdir -p "$(dirname "$JSON_PATH")"
|
||||
echo "JSON_PATH=$JSON_PATH" >> "$GITHUB_ENV"
|
||||
echo "HTML_PATH=$HTML_PATH" >> "$GITHUB_ENV"
|
||||
|
||||
ARGS=(--runs "${{ inputs.runs }}" --memories "$MEMORIES_FILE")
|
||||
if [ -n "${MOCK_MEMORIES_FILE:-}" ]; then
|
||||
ARGS+=(--mock-memories "$MOCK_MEMORIES_FILE")
|
||||
fi
|
||||
if [ "${{ inputs.mode }}" = "mock_llm" ]; then
|
||||
ARGS+=(--mock-llm)
|
||||
fi
|
||||
if [ -n "${{ inputs.num_memories }}" ]; then
|
||||
ARGS+=(--num-memories "${{ inputs.num_memories }}")
|
||||
fi
|
||||
|
||||
uv run python cognee/tests/performance/statistics_percentile_report.py \
|
||||
"${ARGS[@]}" \
|
||||
--output "$JSON_PATH" \
|
||||
--html "$HTML_PATH"
|
||||
|
||||
- name: Upload reports to S3
|
||||
id: upload
|
||||
env:
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_S3_DEV_USER_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_S3_DEV_USER_SECRET_KEY }}
|
||||
AWS_DEFAULT_REGION: eu-west-1
|
||||
run: |
|
||||
set -euo pipefail
|
||||
aws s3 cp "$JSON_PATH" "s3://$BUCKET/$JSON_PATH" --content-type application/json
|
||||
aws s3 cp "$HTML_PATH" "s3://$BUCKET/$HTML_PATH" --content-type text/html
|
||||
# Presigning is done by the caller (the Slack job), NOT here: a presigned URL
|
||||
# embeds the AWS access key id, and GitHub scrubs registered secrets from
|
||||
# reusable-workflow outputs — which would blank the link. Pass only the
|
||||
# (non-secret) object key across the boundary.
|
||||
echo "html_key=$HTML_PATH" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Parse headline metrics
|
||||
id: parse
|
||||
run: |
|
||||
set -euo pipefail
|
||||
METRICS="$(jq -c '{
|
||||
success: "\(.succeeded)/\(.num_runs)",
|
||||
add: {p50: .stats.add_time_s.p50, p90: .stats.add_time_s.p90, p99: .stats.add_time_s.p99},
|
||||
cognify: {p50: .stats.cognify_time_s.p50, p90: .stats.cognify_time_s.p90, p99: .stats.cognify_time_s.p99},
|
||||
search: {p50: .stats.search_time.p50, p90: .stats.search_time.p90, p99: .stats.search_time.p99},
|
||||
total: {p50: .stats.total_ingest_time_s.p50, p90: .stats.total_ingest_time_s.p90, p99: .stats.total_ingest_time_s.p99}
|
||||
}' "$JSON_PATH")"
|
||||
echo "metrics=$METRICS" >> "$GITHUB_OUTPUT"
|
||||
|
||||
# ── Postgres backend: Postgres relational + PGVector + Postgres graph ────────
|
||||
postgres:
|
||||
name: postgres — ${{ inputs.label }} (${{ inputs.mode }})
|
||||
runs-on: ubuntu-22.04
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
services:
|
||||
postgres:
|
||||
image: ghcr.io/topoteretes/pgvector:pg17
|
||||
credentials:
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
env:
|
||||
POSTGRES_USER: cognee
|
||||
POSTGRES_PASSWORD: cognee
|
||||
POSTGRES_DB: cognee_db
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
ports:
|
||||
- 5432:5432
|
||||
outputs:
|
||||
metrics: ${{ steps.parse.outputs.metrics }}
|
||||
html_key: ${{ steps.upload.outputs.html_key }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: '3.11.x'
|
||||
extra-dependencies: "postgres"
|
||||
|
||||
- name: Download dataset from S3
|
||||
env:
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_S3_DEV_USER_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_S3_DEV_USER_SECRET_KEY }}
|
||||
AWS_DEFAULT_REGION: eu-west-1
|
||||
MEMORIES_KEY: ${{ inputs.memories_key }}
|
||||
MOCK_MEMORIES_KEY: ${{ inputs.mock_memories_key }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
mkdir -p performance_datasets
|
||||
aws s3 cp "s3://$BUCKET/$MEMORIES_KEY" performance_datasets/memories.json
|
||||
echo "MEMORIES_FILE=$PWD/performance_datasets/memories.json" >> "$GITHUB_ENV"
|
||||
if [ -n "$MOCK_MEMORIES_KEY" ]; then
|
||||
aws s3 cp "s3://$BUCKET/$MOCK_MEMORIES_KEY" performance_datasets/mock_memories.json
|
||||
echo "MOCK_MEMORIES_FILE=$PWD/performance_datasets/mock_memories.json" >> "$GITHUB_ENV"
|
||||
fi
|
||||
|
||||
- name: Run performance report
|
||||
id: run
|
||||
env:
|
||||
PYTHONFAULTHANDLER: 1
|
||||
# LLM + embedding config via the standard CI secrets (see e2e_tests.yml).
|
||||
# Only exercised for mode == 'llm'; the mock run hits no external APIs.
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
# Full Postgres stack (creds match the postgres service above; mirrors e2e_tests.yml).
|
||||
DB_PROVIDER: 'postgres'
|
||||
DB_HOST: '127.0.0.1'
|
||||
DB_PORT: '5432'
|
||||
DB_USERNAME: cognee
|
||||
DB_PASSWORD: cognee
|
||||
DB_NAME: cognee_db
|
||||
VECTOR_DB_PROVIDER: 'pgvector'
|
||||
VECTOR_DB_HOST: '127.0.0.1'
|
||||
VECTOR_DB_PORT: '5432'
|
||||
VECTOR_DB_USERNAME: cognee
|
||||
VECTOR_DB_PASSWORD: cognee
|
||||
VECTOR_DATASET_DATABASE_HANDLER: 'pgvector'
|
||||
GRAPH_DATABASE_PROVIDER: 'postgres'
|
||||
GRAPH_DATABASE_HOST: '127.0.0.1'
|
||||
GRAPH_DATABASE_PORT: '5432'
|
||||
GRAPH_DATABASE_USERNAME: cognee
|
||||
GRAPH_DATABASE_PASSWORD: cognee
|
||||
GRAPH_DATABASE_NAME: cognee_db
|
||||
run: |
|
||||
set -euo pipefail
|
||||
TS="$(date -u '+%Y-%m-%d_%H-%M-%SZ')"
|
||||
JSON_PATH="performance_results/postgres/${{ inputs.label }}/${{ inputs.mode }}_${TS}.json"
|
||||
HTML_PATH="performance_results/postgres/${{ inputs.label }}/${{ inputs.mode }}_${TS}.html"
|
||||
mkdir -p "$(dirname "$JSON_PATH")"
|
||||
echo "JSON_PATH=$JSON_PATH" >> "$GITHUB_ENV"
|
||||
echo "HTML_PATH=$HTML_PATH" >> "$GITHUB_ENV"
|
||||
|
||||
ARGS=(--runs "${{ inputs.runs }}" --memories "$MEMORIES_FILE")
|
||||
if [ -n "${MOCK_MEMORIES_FILE:-}" ]; then
|
||||
ARGS+=(--mock-memories "$MOCK_MEMORIES_FILE")
|
||||
fi
|
||||
if [ "${{ inputs.mode }}" = "mock_llm" ]; then
|
||||
ARGS+=(--mock-llm)
|
||||
fi
|
||||
if [ -n "${{ inputs.num_memories }}" ]; then
|
||||
ARGS+=(--num-memories "${{ inputs.num_memories }}")
|
||||
fi
|
||||
|
||||
uv run python cognee/tests/performance/statistics_percentile_report.py \
|
||||
"${ARGS[@]}" \
|
||||
--output "$JSON_PATH" \
|
||||
--html "$HTML_PATH"
|
||||
|
||||
- name: Upload reports to S3
|
||||
id: upload
|
||||
env:
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_S3_DEV_USER_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_S3_DEV_USER_SECRET_KEY }}
|
||||
AWS_DEFAULT_REGION: eu-west-1
|
||||
run: |
|
||||
set -euo pipefail
|
||||
aws s3 cp "$JSON_PATH" "s3://$BUCKET/$JSON_PATH" --content-type application/json
|
||||
aws s3 cp "$HTML_PATH" "s3://$BUCKET/$HTML_PATH" --content-type text/html
|
||||
# Presigning is done by the caller (the Slack job), NOT here: a presigned URL
|
||||
# embeds the AWS access key id, and GitHub scrubs registered secrets from
|
||||
# reusable-workflow outputs — which would blank the link. Pass only the
|
||||
# (non-secret) object key across the boundary.
|
||||
echo "html_key=$HTML_PATH" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Parse headline metrics
|
||||
id: parse
|
||||
run: |
|
||||
set -euo pipefail
|
||||
METRICS="$(jq -c '{
|
||||
success: "\(.succeeded)/\(.num_runs)",
|
||||
add: {p50: .stats.add_time_s.p50, p90: .stats.add_time_s.p90, p99: .stats.add_time_s.p99},
|
||||
cognify: {p50: .stats.cognify_time_s.p50, p90: .stats.cognify_time_s.p90, p99: .stats.cognify_time_s.p99},
|
||||
search: {p50: .stats.search_time.p50, p90: .stats.search_time.p90, p99: .stats.search_time.p99},
|
||||
total: {p50: .stats.total_ingest_time_s.p50, p90: .stats.total_ingest_time_s.p90, p99: .stats.total_ingest_time_s.p99}
|
||||
}' "$JSON_PATH")"
|
||||
echo "metrics=$METRICS" >> "$GITHUB_OUTPUT"
|
||||
@@ -0,0 +1,44 @@
|
||||
## Reference: https://github.com/amannn/action-semantic-pull-request
|
||||
---
|
||||
name: lint | PR
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- reopened
|
||||
- edited
|
||||
- synchronize
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
pr_title:
|
||||
permissions:
|
||||
pull-requests: write
|
||||
statuses: write
|
||||
name: Validate & Label PR
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: amannn/action-semantic-pull-request@v5
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
# Configure which types are allowed (newline-delimited).
|
||||
# From: https://github.com/commitizen/conventional-commit-types/blob/master/index.json
|
||||
# listing all below
|
||||
types: |
|
||||
chore
|
||||
ci
|
||||
docs
|
||||
feat
|
||||
fix
|
||||
perf
|
||||
refactor
|
||||
revert
|
||||
test
|
||||
break
|
||||
- uses: release-drafter/release-drafter@v6
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -0,0 +1,29 @@
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
COGNEE_SKIP_CONNECTION_TEST: 'true'
|
||||
|
||||
jobs:
|
||||
check-uv-lock:
|
||||
name: Lockfile and Pre-commit Hooks
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@v7
|
||||
with:
|
||||
enable-cache: true
|
||||
|
||||
- name: Validate uv lockfile and project metadata
|
||||
run: uv lock --check || { echo "'uv lock --check' failed."; echo "Run 'uv lock' and push your changes."; exit 1; }
|
||||
|
||||
- name: Run pre-commit hooks
|
||||
uses: pre-commit/action@v3.0.1
|
||||
@@ -0,0 +1,248 @@
|
||||
name: Relational DB Migration Tests
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
python-version:
|
||||
required: false
|
||||
type: string
|
||||
default: '3.11.x'
|
||||
ci-image:
|
||||
required: false
|
||||
type: string
|
||||
default: ''
|
||||
secrets:
|
||||
LLM_PROVIDER:
|
||||
required: true
|
||||
LLM_MODEL:
|
||||
required: true
|
||||
LLM_ENDPOINT:
|
||||
required: true
|
||||
LLM_API_KEY:
|
||||
required: true
|
||||
LLM_ARGS:
|
||||
required: false
|
||||
LLM_API_VERSION:
|
||||
required: true
|
||||
EMBEDDING_PROVIDER:
|
||||
required: true
|
||||
EMBEDDING_MODEL:
|
||||
required: true
|
||||
EMBEDDING_API_KEY:
|
||||
required: true
|
||||
|
||||
env:
|
||||
COGNEE_SKIP_CONNECTION_TEST: 'true'
|
||||
|
||||
jobs:
|
||||
run-relational-db-migration-test-networkx:
|
||||
name: NetworkX Relational DB Migration Test
|
||||
runs-on: ubuntu-22.04
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
services:
|
||||
postgres:
|
||||
image: ghcr.io/topoteretes/pgvector:pg17
|
||||
credentials:
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
env:
|
||||
POSTGRES_USER: cognee
|
||||
POSTGRES_PASSWORD: cognee
|
||||
POSTGRES_DB: test_migration_db
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
ports:
|
||||
- 5432:5432
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: '3.11.x'
|
||||
extra-dependencies: "postgres"
|
||||
|
||||
- name: Install specific db dependency
|
||||
run: echo "Dependencies already installed in setup"
|
||||
|
||||
- name: Run PostgreSQL Script to create test data (Chinook_PostgreSql.sql)
|
||||
env:
|
||||
PGPASSWORD: cognee
|
||||
PG_HOST: ${{ inputs.ci-image != '' && 'postgres' || 'localhost' }}
|
||||
run: |
|
||||
# Wait until the PostgreSQL service is available
|
||||
until pg_isready -h $PG_HOST -p 5432; do
|
||||
echo "Waiting for postgres..."
|
||||
sleep 2
|
||||
done
|
||||
|
||||
# Execute the SQL script against the test_migration_db database
|
||||
psql -h $PG_HOST -U cognee -d test_migration_db -f ./cognee/tests/test_data/Chinook_PostgreSql.sql
|
||||
|
||||
- name: Run relational db test
|
||||
env:
|
||||
ENV: 'dev'
|
||||
LLM_PROVIDER: openai
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
|
||||
EMBEDDING_PROVIDER: openai
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
DB_HOST: ${{ inputs.ci-image != '' && 'postgres' || '127.0.0.1' }}
|
||||
run: uv run python ./cognee/tests/test_relational_db_migration.py
|
||||
|
||||
run-relational-db-migration-test-kuzu:
|
||||
name: Kuzu Relational DB Migration Test
|
||||
runs-on: ubuntu-22.04
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
services:
|
||||
postgres:
|
||||
image: ghcr.io/topoteretes/pgvector:pg17
|
||||
credentials:
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
env:
|
||||
POSTGRES_USER: cognee
|
||||
POSTGRES_PASSWORD: cognee
|
||||
POSTGRES_DB: test_migration_db
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
ports:
|
||||
- 5432:5432
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: '3.11.x'
|
||||
extra-dependencies: "postgres"
|
||||
|
||||
- name: Install specific db dependency
|
||||
run: echo "Dependencies already installed in setup"
|
||||
|
||||
- name: Run PostgreSQL Script to create test data (Chinook_PostgreSql.sql)
|
||||
env:
|
||||
PGPASSWORD: cognee
|
||||
PG_HOST: ${{ inputs.ci-image != '' && 'postgres' || 'localhost' }}
|
||||
run: |
|
||||
# Wait until the PostgreSQL service is available
|
||||
until pg_isready -h $PG_HOST -p 5432; do
|
||||
echo "Waiting for postgres..."
|
||||
sleep 2
|
||||
done
|
||||
|
||||
# Execute the SQL script against the test_migration_db database
|
||||
psql -h $PG_HOST -U cognee -d test_migration_db -f ./cognee/tests/test_data/Chinook_PostgreSql.sql
|
||||
|
||||
- name: Run relational db test
|
||||
env:
|
||||
ENV: 'dev'
|
||||
GRAPH_DATABASE_PROVIDER: 'kuzu'
|
||||
|
||||
LLM_PROVIDER: openai
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
|
||||
EMBEDDING_PROVIDER: openai
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
DB_HOST: ${{ inputs.ci-image != '' && 'postgres' || '127.0.0.1' }}
|
||||
run: uv run python ./cognee/tests/test_relational_db_migration.py
|
||||
|
||||
run-relational-db-migration-test-neo4j:
|
||||
name: Neo4j Relational DB Migration Test
|
||||
runs-on: ubuntu-22.04
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
services:
|
||||
postgres:
|
||||
image: ghcr.io/topoteretes/pgvector:pg17
|
||||
credentials:
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
env:
|
||||
POSTGRES_USER: cognee
|
||||
POSTGRES_PASSWORD: cognee
|
||||
POSTGRES_DB: test_migration_db
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
ports:
|
||||
- 5432:5432
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: '3.11.x'
|
||||
extra-dependencies: "postgres"
|
||||
|
||||
- name: Setup Neo4j with GDS
|
||||
uses: ./.github/actions/setup_neo4j
|
||||
id: neo4j
|
||||
|
||||
- name: Install specific db dependency
|
||||
run: echo "Dependencies already installed in setup"
|
||||
|
||||
- name: Run PostgreSQL Script to create test data (Chinook_PostgreSql.sql)
|
||||
env:
|
||||
PGPASSWORD: cognee
|
||||
run: |
|
||||
# Wait until the PostgreSQL service is available
|
||||
until pg_isready -h localhost -p 5432; do
|
||||
echo "Waiting for postgres..."
|
||||
sleep 2
|
||||
done
|
||||
|
||||
# Execute the SQL script against the test_migration_db database
|
||||
psql -h localhost -U cognee -d test_migration_db -f ./cognee/tests/test_data/Chinook_PostgreSql.sql
|
||||
|
||||
- name: Run relational db test
|
||||
env:
|
||||
ENV: 'dev'
|
||||
GRAPH_DATABASE_PROVIDER: "neo4j"
|
||||
GRAPH_DATABASE_URL: ${{ steps.neo4j.outputs.neo4j-url }}
|
||||
GRAPH_DATABASE_USERNAME: ${{ steps.neo4j.outputs.neo4j-username }}
|
||||
GRAPH_DATABASE_PASSWORD: ${{ steps.neo4j.outputs.neo4j-password }}
|
||||
|
||||
LLM_PROVIDER: openai
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
|
||||
EMBEDDING_PROVIDER: openai
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
run: uv run python ./cognee/tests/test_relational_db_migration.py
|
||||
@@ -0,0 +1,254 @@
|
||||
name: release.yml
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
release-github:
|
||||
name: Create GitHub Release from ${{ github.ref_name }}
|
||||
outputs:
|
||||
tag: ${{ steps.create_tag.outputs.tag }}
|
||||
version: ${{ steps.create_tag.outputs.version }}
|
||||
permissions:
|
||||
contents: write
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Check out ${{ github.ref_name }}
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ github.ref_name }}
|
||||
fetch-depth: 0 # Fetch all history for comparison
|
||||
|
||||
- name: Fetch main branch for comparison
|
||||
if: ${{ github.ref_name == 'dev' }}
|
||||
run: git fetch origin main:main
|
||||
|
||||
- name: Fetch dev branch for comparison
|
||||
if: ${{ github.ref_name == 'main' }}
|
||||
run: git fetch origin dev:dev
|
||||
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@v7
|
||||
|
||||
- name: Install Python
|
||||
run: uv python install
|
||||
|
||||
- name: Install dependencies
|
||||
run: uv sync --locked
|
||||
|
||||
- name: Create and push git tag
|
||||
id: create_tag
|
||||
run: |
|
||||
VERSION="$(uv version --short)"
|
||||
TAG="v${VERSION}"
|
||||
|
||||
echo "Tag to create: ${TAG}"
|
||||
|
||||
git config user.name "Cognee Team"
|
||||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
|
||||
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
|
||||
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
git tag "${TAG}"
|
||||
git push origin "${TAG}"
|
||||
|
||||
- name: Generate AI-powered release notes
|
||||
id: generate_notes
|
||||
env:
|
||||
LLM_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL != '' && secrets.LLM_MODEL || 'openai/gpt-4o-mini' }}
|
||||
run: |
|
||||
# Set PYTHONPATH to include project root
|
||||
export PYTHONPATH="${GITHUB_WORKSPACE}:${PYTHONPATH}"
|
||||
|
||||
# Generate release notes
|
||||
# Compares current branch against the latest release tag automatically
|
||||
uv run python tools/generate_release_notes.py \
|
||||
--version "${{ steps.create_tag.outputs.version }}" \
|
||||
--github-output
|
||||
|
||||
- name: Create GitHub Release with AI-generated notes
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
tag_name: ${{ steps.create_tag.outputs.tag }}
|
||||
name: ${{ steps.generate_notes.outputs.RELEASE_TITLE }}
|
||||
body: ${{ steps.generate_notes.outputs.RELEASE_NOTES }}
|
||||
prerelease: ${{ github.ref_name == 'dev' }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GH_RELEASE_TOKEN }}
|
||||
|
||||
release-pypi-package:
|
||||
needs: release-github
|
||||
name: Release PyPI Package from ${{ github.ref_name }}
|
||||
permissions:
|
||||
contents: read
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Check out ${{ github.ref_name }}
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ github.ref_name }}
|
||||
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@v7
|
||||
|
||||
- name: Install Python
|
||||
run: uv python install
|
||||
|
||||
- name: Install dependencies
|
||||
run: uv sync --locked --all-extras
|
||||
|
||||
- name: Build distributions
|
||||
run: uv build
|
||||
|
||||
- name: Publish ${{ github.ref_name }} release to PyPI
|
||||
env:
|
||||
UV_PUBLISH_TOKEN: ${{ secrets.PYPI_TOKEN }}
|
||||
run: uv publish
|
||||
|
||||
release-docker-image:
|
||||
needs: release-github
|
||||
name: Release Docker Image from ${{ github.ref_name }}
|
||||
permissions:
|
||||
contents: read
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Check out ${{ github.ref_name }}
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ github.ref_name }}
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Build and push Dev Docker Image
|
||||
if: ${{ github.ref_name == 'dev' }}
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: cognee/cognee:${{ needs.release-github.outputs.version }}
|
||||
labels: |
|
||||
version=${{ needs.release-github.outputs.version }}
|
||||
flavour=${{ github.ref_name }}
|
||||
cache-from: type=registry,ref=cognee/cognee:buildcache
|
||||
cache-to: type=registry,ref=cognee/cognee:buildcache,mode=max
|
||||
|
||||
- name: Build and push Main Docker Image
|
||||
if: ${{ github.ref_name == 'main' }}
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: |
|
||||
cognee/cognee:${{ needs.release-github.outputs.version }}
|
||||
cognee/cognee:latest
|
||||
labels: |
|
||||
version=${{ needs.release-github.outputs.version }}
|
||||
flavour=${{ github.ref_name }}
|
||||
cache-from: type=registry,ref=cognee/cognee:buildcache
|
||||
cache-to: type=registry,ref=cognee/cognee:buildcache,mode=max
|
||||
|
||||
- name: Build and push Dev MCP Docker Image
|
||||
if: ${{ github.ref_name == 'dev' }}
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: cognee-mcp/Dockerfile
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: cognee/cognee-mcp:${{ needs.release-github.outputs.version }}
|
||||
labels: |
|
||||
version=${{ needs.release-github.outputs.version }}
|
||||
flavour=${{ github.ref_name }}
|
||||
cache-from: type=registry,ref=cognee/cognee-mcp:buildcache
|
||||
cache-to: type=registry,ref=cognee/cognee-mcp:buildcache,mode=max
|
||||
|
||||
- name: Build and push Main MCP Docker Image
|
||||
if: ${{ github.ref_name == 'main' }}
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: cognee-mcp/Dockerfile
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: |
|
||||
cognee/cognee-mcp:${{ needs.release-github.outputs.version }}
|
||||
cognee/cognee-mcp:latest
|
||||
labels: |
|
||||
version=${{ needs.release-github.outputs.version }}
|
||||
flavour=${{ github.ref_name }}
|
||||
cache-from: type=registry,ref=cognee/cognee-mcp:buildcache
|
||||
cache-to: type=registry,ref=cognee/cognee-mcp:buildcache,mode=max
|
||||
|
||||
trigger-docs-test-suite:
|
||||
needs: release-pypi-package
|
||||
if: ${{ github.ref_name == 'main' }}
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Trigger docs tests
|
||||
run: |
|
||||
curl -L -X POST \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
-H "Authorization: Bearer ${{ secrets.REPO_DISPATCH_PAT_TOKEN }}" \
|
||||
-H "X-GitHub-Api-Version: 2022-11-28" \
|
||||
https://api.github.com/repos/topoteretes/cognee-docs/dispatches \
|
||||
-d '{"event_type":"new-main-release","client_payload":{"caller_repo":"'"${GITHUB_REPOSITORY}"'"}}'
|
||||
|
||||
trigger-community-test-suite:
|
||||
needs: release-pypi-package
|
||||
if: ${{ github.ref_name == 'main' }}
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Trigger community tests
|
||||
run: |
|
||||
curl -L -X POST \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
-H "Authorization: Bearer ${{ secrets.REPO_DISPATCH_PAT_TOKEN }}" \
|
||||
-H "X-GitHub-Api-Version: 2022-11-28" \
|
||||
https://api.github.com/repos/topoteretes/cognee-community/dispatches \
|
||||
-d '{"event_type":"new-main-release","client_payload":{"caller_repo":"'"${GITHUB_REPOSITORY}"'"}}'
|
||||
|
||||
notify-discord:
|
||||
needs: release-github
|
||||
name: Send Release to Discord
|
||||
if: ${{ github.ref_name == 'main' }}
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Send Discord notification
|
||||
env:
|
||||
WEBHOOK_URL: ${{ secrets.WEBHOOK_URL }}
|
||||
TAG: ${{ needs.release-github.outputs.tag }}
|
||||
VERSION: ${{ needs.release-github.outputs.version }}
|
||||
run: |
|
||||
RELEASE_URL="https://github.com/${{ github.repository }}/releases/tag/${TAG}"
|
||||
PAYLOAD=$(jq -n \
|
||||
--arg content "||@everyone|| **${TAG}** has been released!" \
|
||||
--arg title "Release ${TAG}" \
|
||||
--arg url "$RELEASE_URL" \
|
||||
--arg description "Version ${VERSION} released from \`${{ github.ref_name }}\`. [View release notes](${RELEASE_URL})" \
|
||||
--argjson color 2105893 \
|
||||
'{
|
||||
content: $content,
|
||||
embeds: [{
|
||||
title: $title,
|
||||
url: $url,
|
||||
description: $description,
|
||||
color: $color,
|
||||
footer: { text: "Changelog" },
|
||||
timestamp: (now | todate)
|
||||
}]
|
||||
}')
|
||||
curl -s -H "Content-Type: application/json" -d "$PAYLOAD" "$WEBHOOK_URL"
|
||||
@@ -0,0 +1,23 @@
|
||||
name: automation | Send Release to Discord
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
github-releases-to-discord:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
- name: Github Releases To Discord
|
||||
uses: SethCohen/github-releases-to-discord@v1.19.0
|
||||
with:
|
||||
webhook_url: ${{ secrets.WEBHOOK_URL }}
|
||||
color: "2105893"
|
||||
username: "Release Changelog"
|
||||
avatar_url: "https://cdn.discordapp.com/avatars/487431320314576937/bd64361e4ba6313d561d54e78c9e7171.png"
|
||||
content: "||@everyone||"
|
||||
footer_title: "Changelog"
|
||||
footer_icon_url: "https://cdn.discordapp.com/avatars/487431320314576937/bd64361e4ba6313d561d54e78c9e7171.png"
|
||||
footer_timestamp: true
|
||||
@@ -0,0 +1,201 @@
|
||||
# Long-running, heavy and resource-consuming tests for release validation.
|
||||
# Runs automatically on PRs targeting main (the dev -> main promotion) and manually
|
||||
# via workflow_dispatch. Fork PRs are skipped (no access to secrets).
|
||||
name: Release Test Workflow
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
cognee_version:
|
||||
required: false
|
||||
default: local
|
||||
type: string
|
||||
description: "Pypi-compatible version of cognee to use. For example, 0.5.2.dev0. `local` (default) - Installing Cognee from local source"
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
concurrency:
|
||||
group: release-tests-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
jobs:
|
||||
|
||||
mcp-test:
|
||||
name: MCP Tests
|
||||
if: ${{ github.event_name == 'workflow_dispatch' || github.event.pull_request.head.repo.full_name == github.repository }}
|
||||
uses: ./.github/workflows/test_mcp.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
cognee_version: ${{ inputs.cognee_version || 'local' }}
|
||||
|
||||
cli-test:
|
||||
name: CLI Tests
|
||||
if: ${{ github.event_name == 'workflow_dispatch' || github.event.pull_request.head.repo.full_name == github.repository }}
|
||||
uses: ./.github/workflows/cli_tests.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
cognee_version: ${{ inputs.cognee_version || 'local' }}
|
||||
|
||||
cot-retriever-test:
|
||||
name: COT Retriever Test
|
||||
if: ${{ github.event_name == 'workflow_dispatch' || github.event.pull_request.head.repo.full_name == github.repository }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@v7
|
||||
|
||||
- name: Install Python
|
||||
run: uv python install
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
if [ "${{ inputs.cognee_version }}" = "local" ] || [ -z "${{ inputs.cognee_version }}" ]; then
|
||||
uv sync --locked --all-extras
|
||||
else
|
||||
uv sync --locked --all-extras
|
||||
uv pip install cognee==${{ inputs.cognee_version }}
|
||||
fi
|
||||
|
||||
- name: Run COT retriever integration test
|
||||
env:
|
||||
LLM_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
run: |
|
||||
uv run pytest cognee/tests/integration/retrieval/test_graph_completion_retriever_cot.py -v --timeout=300
|
||||
|
||||
# 10 parallel users against a live HTTP server with access control enabled:
|
||||
# per-user dataset isolation, add/cognify/search verification via sentinel chunks
|
||||
# (LLM-free CHUNKS search), delete + recreate, forget + recreate-same-name.
|
||||
multi-user-e2e-default:
|
||||
name: Multi-User Release E2E (default file-based DBs)
|
||||
if: ${{ github.event_name == 'workflow_dispatch' || github.event.pull_request.head.repo.full_name == github.repository }}
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@v7
|
||||
|
||||
- name: Install Python
|
||||
run: uv python install
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
if [ "${{ inputs.cognee_version }}" = "local" ] || [ -z "${{ inputs.cognee_version }}" ]; then
|
||||
uv sync --locked --all-extras
|
||||
else
|
||||
uv sync --locked --all-extras
|
||||
uv pip install cognee==${{ inputs.cognee_version }}
|
||||
fi
|
||||
|
||||
- name: Run multi-user release E2E test
|
||||
env:
|
||||
ENV: 'dev'
|
||||
COGNEE_SKIP_CONNECTION_TEST: 'true'
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
run: uv run python ./cognee/tests/test_release_multi_user_e2e.py
|
||||
|
||||
multi-user-e2e-postgres:
|
||||
name: Multi-User Release E2E (Postgres graph + PGVector + Postgres)
|
||||
if: ${{ github.event_name == 'workflow_dispatch' || github.event.pull_request.head.repo.full_name == github.repository }}
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 60
|
||||
services:
|
||||
postgres:
|
||||
image: ghcr.io/topoteretes/pgvector:pg17
|
||||
credentials:
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
env:
|
||||
POSTGRES_USER: cognee
|
||||
POSTGRES_PASSWORD: cognee
|
||||
POSTGRES_DB: cognee_db
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
ports:
|
||||
- 5432:5432
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@v7
|
||||
|
||||
- name: Install Python
|
||||
run: uv python install
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
if [ "${{ inputs.cognee_version }}" = "local" ] || [ -z "${{ inputs.cognee_version }}" ]; then
|
||||
uv sync --locked --all-extras
|
||||
else
|
||||
uv sync --locked --all-extras
|
||||
uv pip install cognee==${{ inputs.cognee_version }}
|
||||
fi
|
||||
|
||||
- name: Run multi-user release E2E test
|
||||
env:
|
||||
ENV: 'dev'
|
||||
COGNEE_SKIP_CONNECTION_TEST: 'true'
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
DB_PROVIDER: 'postgres'
|
||||
DB_NAME: 'cognee_db'
|
||||
DB_HOST: '127.0.0.1'
|
||||
DB_PORT: 5432
|
||||
DB_USERNAME: cognee
|
||||
DB_PASSWORD: cognee
|
||||
VECTOR_DB_PROVIDER: 'pgvector'
|
||||
VECTOR_DB_NAME: 'cognee_db'
|
||||
VECTOR_DB_HOST: '127.0.0.1'
|
||||
VECTOR_DB_PORT: 5432
|
||||
VECTOR_DB_USERNAME: cognee
|
||||
VECTOR_DB_PASSWORD: cognee
|
||||
VECTOR_DATASET_DATABASE_HANDLER: 'pgvector'
|
||||
GRAPH_DATABASE_PROVIDER: 'postgres'
|
||||
GRAPH_DATABASE_NAME: 'cognee_db'
|
||||
GRAPH_DATABASE_HOST: '127.0.0.1'
|
||||
GRAPH_DATABASE_PORT: 5432
|
||||
GRAPH_DATABASE_USERNAME: cognee
|
||||
GRAPH_DATABASE_PASSWORD: cognee
|
||||
GRAPH_DATASET_DATABASE_HANDLER: 'postgres_graph'
|
||||
run: uv run python ./cognee/tests/test_release_multi_user_e2e.py
|
||||
|
||||
load-tests:
|
||||
if: false
|
||||
name: Load Tests
|
||||
uses: ./.github/workflows/load_tests.yml
|
||||
secrets: inherit
|
||||
|
||||
dev-canary-release:
|
||||
name: Dev Canary Release
|
||||
if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||
needs: load-tests
|
||||
uses: ./.github/workflows/dev_canary_release.yml
|
||||
secrets: inherit
|
||||
@@ -0,0 +1,40 @@
|
||||
name: Require Linear issue
|
||||
|
||||
# Every INTERNAL PR must reference a Linear issue (e.g. COG-123) in its title or
|
||||
# branch name — that is how Linear links a PR to a ticket. Since Linear does not
|
||||
# gate merges, enforcement is a required GitHub status check: this job fails when a
|
||||
# PR has no Linear key, and branch protection blocks the merge until it passes.
|
||||
#
|
||||
# Fork / external-contributor PRs are intentionally SKIPPED: they have no Linear
|
||||
# access, and a skipped required check counts as passing, so this never blocks the
|
||||
# community. Mark the `linear-issue-check` job as a required status check on
|
||||
# `main` and `dev` in branch protection.
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
# `synchronize` matters: a required check must re-run on the latest commit.
|
||||
types: [opened, edited, reopened, synchronize]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
linear-issue-check: # this job name is what you mark "required" in branch protection
|
||||
# Enforce for internal PRs only. Fork PRs (head repo != base repo) skip this job;
|
||||
# a skipped required check is treated as passing, so external PRs are not blocked.
|
||||
if: github.event.pull_request.head.repo.full_name == github.repository
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: PR title or branch must reference a Linear issue
|
||||
env:
|
||||
PR_TITLE: ${{ github.event.pull_request.title }}
|
||||
HEAD_REF: ${{ github.head_ref }}
|
||||
run: |
|
||||
# List ALL your Linear team prefixes — verify against Linear ▸ Settings ▸ Teams.
|
||||
KEYS='COG|SDK|CLO|COM|ENG'
|
||||
if echo "$PR_TITLE $HEAD_REF" | grep -Eiq "\b(${KEYS})-[0-9]+\b"; then
|
||||
echo "Linear issue reference found."
|
||||
else
|
||||
echo "::error::PR title or branch must reference a Linear issue, e.g. COG-123."
|
||||
exit 1
|
||||
fi
|
||||
@@ -0,0 +1,71 @@
|
||||
name: test-notebook
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
notebook-location:
|
||||
description: "Location of Jupyter notebook to run"
|
||||
required: true
|
||||
type: string
|
||||
ci-image:
|
||||
required: false
|
||||
type: string
|
||||
default: ''
|
||||
secrets:
|
||||
#LLM_MODEL:
|
||||
# required: true
|
||||
#LLM_ENDPOINT:
|
||||
# required: true
|
||||
LLM_API_KEY:
|
||||
required: true
|
||||
LLM_ARGS:
|
||||
required: false
|
||||
OPENAI_API_KEY:
|
||||
required: true
|
||||
#LLM_API_VERSION:
|
||||
# required: true
|
||||
EMBEDDING_MODEL:
|
||||
required: true
|
||||
EMBEDDING_API_KEY:
|
||||
required: true
|
||||
|
||||
env:
|
||||
RUNTIME__LOG_LEVEL: ERROR
|
||||
|
||||
jobs:
|
||||
|
||||
run_notebook_test:
|
||||
name: test
|
||||
runs-on: ubuntu-22.04
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
steps:
|
||||
- name: Check out
|
||||
uses: actions/checkout@master
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: ${{ inputs.python-version }}
|
||||
extra-dependencies: "notebook"
|
||||
|
||||
- name: Execute Jupyter Notebook
|
||||
env:
|
||||
ENV: 'dev'
|
||||
#LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
#LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} # Use OpenAI Until a multimedia model is deployed and DeepEval support for other models is added
|
||||
#LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
run: |
|
||||
uv run jupyter nbconvert \
|
||||
--to notebook \
|
||||
--execute ${{ inputs.notebook-location }} \
|
||||
--output executed_notebook.ipynb \
|
||||
--ExecutePreprocessor.timeout=1200
|
||||
@@ -0,0 +1,78 @@
|
||||
# This workflow uses actions that are not certified by GitHub. They are provided
|
||||
# by a third-party and are governed by separate terms of service, privacy
|
||||
# policy, and support documentation.
|
||||
|
||||
name: Scorecard supply-chain security
|
||||
on:
|
||||
# For Branch-Protection check. Only the default branch is supported. See
|
||||
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection
|
||||
branch_protection_rule:
|
||||
# To guarantee Maintained check is occasionally updated. See
|
||||
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained
|
||||
schedule:
|
||||
- cron: '35 8 * * 2'
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
|
||||
# Declare default permissions as read only.
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
analysis:
|
||||
name: Scorecard analysis
|
||||
runs-on: ubuntu-latest
|
||||
# `publish_results: true` only works when run from the default branch. conditional can be removed if disabled.
|
||||
if: github.event.repository.default_branch == github.ref_name || github.event_name == 'pull_request'
|
||||
permissions:
|
||||
# Needed to upload the results to code-scanning dashboard.
|
||||
security-events: write
|
||||
# Needed to publish results and get a badge (see publish_results below).
|
||||
id-token: write
|
||||
# Uncomment the permissions below if installing in a private repository.
|
||||
# contents: read
|
||||
# actions: read
|
||||
|
||||
steps:
|
||||
- name: "Checkout code"
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: "Run analysis"
|
||||
uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # v2.4.1
|
||||
with:
|
||||
results_file: results.sarif
|
||||
results_format: sarif
|
||||
# (Optional) "write" PAT token. Uncomment the `repo_token` line below if:
|
||||
# - you want to enable the Branch-Protection check on a *public* repository, or
|
||||
# - you are installing Scorecard on a *private* repository
|
||||
# To create the PAT, follow the steps in https://github.com/ossf/scorecard-action?tab=readme-ov-file#authentication-with-fine-grained-pat-optional.
|
||||
# repo_token: ${{ secrets.SCORECARD_TOKEN }}
|
||||
|
||||
# Public repositories:
|
||||
# - Publish results to OpenSSF REST API for easy access by consumers
|
||||
# - Allows the repository to include the Scorecard badge.
|
||||
# - See https://github.com/ossf/scorecard-action#publishing-results.
|
||||
# For private repositories:
|
||||
# - `publish_results` will always be set to `false`, regardless
|
||||
# of the value entered here.
|
||||
publish_results: true
|
||||
|
||||
# (Optional) Uncomment file_mode if you have a .gitattributes with files marked export-ignore
|
||||
# file_mode: git
|
||||
|
||||
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
|
||||
# format to the repository Actions tab.
|
||||
- name: "Upload artifact"
|
||||
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
|
||||
with:
|
||||
name: SARIF file
|
||||
path: results.sarif
|
||||
retention-days: 5
|
||||
|
||||
# Upload the results to GitHub's code scanning dashboard (optional).
|
||||
# Commenting out will disable upload of results to your repo's Code Scanning dashboard
|
||||
- name: "Upload to code-scanning"
|
||||
uses: github/codeql-action/upload-sarif@v4
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
@@ -0,0 +1,244 @@
|
||||
name: Reusable Search DB Tests
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: read
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
databases:
|
||||
required: false
|
||||
type: string
|
||||
default: "all"
|
||||
description: "Which vector databases to test (comma-separated list or 'all')"
|
||||
python-versions:
|
||||
required: false
|
||||
type: string
|
||||
default: '["3.10", "3.11", "3.12", "3.13"]'
|
||||
description: "Python versions to test (JSON array)"
|
||||
ci-image:
|
||||
required: false
|
||||
type: string
|
||||
default: ''
|
||||
description: "Container image for CI (empty string means no container)"
|
||||
|
||||
env:
|
||||
COGNEE_SKIP_CONNECTION_TEST: 'true'
|
||||
|
||||
jobs:
|
||||
run-kuzu-lance-sqlite-search-tests:
|
||||
name: Search test for Kuzu/LanceDB/Sqlite (Python ${{ matrix.python-version }})
|
||||
runs-on: ubuntu-22.04
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
if: ${{ inputs.databases == 'all' || contains(inputs.databases, 'kuzu/lance/sqlite') }}
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ${{ fromJSON(inputs.python-versions) }}
|
||||
fail-fast: false
|
||||
steps:
|
||||
- name: Check out
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
|
||||
- name: Dependencies already installed
|
||||
run: echo "Dependencies already installed in setup"
|
||||
|
||||
- name: Run Kuzu search Tests
|
||||
env:
|
||||
ENV: 'dev'
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
GRAPH_DATABASE_PROVIDER: 'kuzu'
|
||||
VECTOR_DB_PROVIDER: 'lancedb'
|
||||
DB_PROVIDER: 'sqlite'
|
||||
run: uv run pytest cognee/tests/test_search_db.py -v --log-level=INFO
|
||||
|
||||
run-neo4j-lance-sqlite-search-tests:
|
||||
name: Search test for Neo4j/LanceDB/Sqlite (Python ${{ matrix.python-version }})
|
||||
runs-on: ubuntu-22.04
|
||||
if: ${{ inputs.databases == 'all' || contains(inputs.databases, 'neo4j/lance/sqlite') }}
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ${{ fromJSON(inputs.python-versions) }}
|
||||
fail-fast: false
|
||||
steps:
|
||||
- name: Check out
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
|
||||
- name: Setup Neo4j with GDS
|
||||
uses: ./.github/actions/setup_neo4j
|
||||
id: neo4j
|
||||
|
||||
- name: Dependencies already installed
|
||||
run: echo "Dependencies already installed in setup"
|
||||
|
||||
- name: Run Neo4j search Tests
|
||||
env:
|
||||
ENV: 'dev'
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
GRAPH_DATABASE_PROVIDER: 'neo4j'
|
||||
VECTOR_DB_PROVIDER: 'lancedb'
|
||||
DB_PROVIDER: 'sqlite'
|
||||
ENABLE_BACKEND_ACCESS_CONTROL: 'false'
|
||||
GRAPH_DATABASE_URL: ${{ steps.neo4j.outputs.neo4j-url }}
|
||||
GRAPH_DATABASE_USERNAME: ${{ steps.neo4j.outputs.neo4j-username }}
|
||||
GRAPH_DATABASE_PASSWORD: ${{ steps.neo4j.outputs.neo4j-password }}
|
||||
run: uv run pytest cognee/tests/test_search_db.py -v --log-level=INFO
|
||||
|
||||
run-kuzu-pgvector-postgres-search-tests:
|
||||
name: Search test for Kuzu/PGVector/Postgres (Python ${{ matrix.python-version }})
|
||||
runs-on: ubuntu-22.04
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
if: ${{ inputs.databases == 'all' || contains(inputs.databases, 'kuzu/pgvector/postgres') }}
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ${{ fromJSON(inputs.python-versions) }}
|
||||
fail-fast: false
|
||||
services:
|
||||
postgres:
|
||||
image: ghcr.io/topoteretes/pgvector:pg17
|
||||
credentials:
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
env:
|
||||
POSTGRES_USER: cognee
|
||||
POSTGRES_PASSWORD: cognee
|
||||
POSTGRES_DB: cognee_db
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
ports:
|
||||
- 5432:5432
|
||||
steps:
|
||||
- name: Check out
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
extra-dependencies: "postgres"
|
||||
|
||||
- name: Dependencies already installed
|
||||
run: echo "Dependencies already installed in setup"
|
||||
|
||||
- name: Run Kuzu/PGVector/Postgres Tests
|
||||
env:
|
||||
ENV: dev
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
GRAPH_DATABASE_PROVIDER: 'kuzu'
|
||||
VECTOR_DB_PROVIDER: 'pgvector'
|
||||
ENABLE_BACKEND_ACCESS_CONTROL: 'false'
|
||||
DB_PROVIDER: 'postgres'
|
||||
DB_NAME: 'cognee_db'
|
||||
DB_HOST: ${{ inputs.ci-image != '' && 'postgres' || '127.0.0.1' }}
|
||||
DB_PORT: 5432
|
||||
DB_USERNAME: cognee
|
||||
DB_PASSWORD: cognee
|
||||
run: uv run pytest cognee/tests/test_search_db.py -v --log-level=INFO
|
||||
|
||||
run-neo4j-pgvector-postgres-search-tests:
|
||||
name: Search test for Neo4j/PGVector/Postgres (Python ${{ matrix.python-version }})
|
||||
runs-on: ubuntu-22.04
|
||||
if: ${{ inputs.databases == 'all' || contains(inputs.databases, 'neo4j/pgvector/postgres') }}
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ${{ fromJSON(inputs.python-versions) }}
|
||||
fail-fast: false
|
||||
services:
|
||||
postgres:
|
||||
image: ghcr.io/topoteretes/pgvector:pg17
|
||||
credentials:
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
env:
|
||||
POSTGRES_USER: cognee
|
||||
POSTGRES_PASSWORD: cognee
|
||||
POSTGRES_DB: cognee_db
|
||||
ports:
|
||||
- 5432:5432
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries=5
|
||||
steps:
|
||||
- name: Check out
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
extra-dependencies: "postgres"
|
||||
|
||||
- name: Setup Neo4j with GDS
|
||||
uses: ./.github/actions/setup_neo4j
|
||||
id: neo4j
|
||||
|
||||
- name: Dependencies already installed
|
||||
run: echo "Dependencies already installed in setup"
|
||||
|
||||
- name: Run Neo4j + PGVector + Postgres search Tests
|
||||
env:
|
||||
ENV: dev
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
GRAPH_DATABASE_PROVIDER: 'neo4j'
|
||||
VECTOR_DB_PROVIDER: 'pgvector'
|
||||
DB_PROVIDER: 'postgres'
|
||||
GRAPH_DATABASE_URL: ${{ steps.neo4j.outputs.neo4j-url }}
|
||||
GRAPH_DATABASE_USERNAME: ${{ steps.neo4j.outputs.neo4j-username }}
|
||||
GRAPH_DATABASE_PASSWORD: ${{ steps.neo4j.outputs.neo4j-password }}
|
||||
ENABLE_BACKEND_ACCESS_CONTROL: 'false'
|
||||
DB_NAME: cognee_db
|
||||
DB_HOST: 127.0.0.1
|
||||
DB_PORT: 5432
|
||||
DB_USERNAME: cognee
|
||||
DB_PASSWORD: cognee
|
||||
run: uv run pytest cognee/tests/test_search_db.py -v --log-level=INFO
|
||||
@@ -0,0 +1,93 @@
|
||||
name: Slow End-to-End Tests
|
||||
permissions:
|
||||
contents: read
|
||||
packages: read
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
python-version:
|
||||
required: false
|
||||
type: string
|
||||
default: '3.11.x'
|
||||
ci-image:
|
||||
required: false
|
||||
type: string
|
||||
default: ''
|
||||
secrets:
|
||||
LLM_MODEL:
|
||||
required: true
|
||||
LLM_ENDPOINT:
|
||||
required: true
|
||||
LLM_API_KEY:
|
||||
required: true
|
||||
LLM_ARGS:
|
||||
required: false
|
||||
LLM_API_VERSION:
|
||||
required: true
|
||||
EMBEDDING_MODEL:
|
||||
required: true
|
||||
EMBEDDING_API_KEY:
|
||||
required: true
|
||||
|
||||
env:
|
||||
COGNEE_SKIP_CONNECTION_TEST: 'true'
|
||||
|
||||
jobs:
|
||||
test-edge-centered-payload:
|
||||
name: Test Cognify - Edge Centered Payload
|
||||
runs-on: ubuntu-22.04
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: ${{ inputs.python-version }}
|
||||
|
||||
- name: Dependencies already installed
|
||||
run: echo "Dependencies already installed in setup"
|
||||
|
||||
- name: Run Edge Centered Payload Test
|
||||
env:
|
||||
ENV: 'dev'
|
||||
TRIPLET_EMBEDDING: True
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
run: uv run python ./cognee/tests/test_edge_centered_payload.py
|
||||
|
||||
test-deletion-on-default-graph_with_legacy_data_1_default:
|
||||
name: Delete default graph with legacy data test 1 in Kuzu case
|
||||
runs-on: ubuntu-22.04
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
steps:
|
||||
- name: Check out
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: ${{ inputs.python-version }}
|
||||
|
||||
- name: Run deletion on default graph with legacy data (Kuzu)
|
||||
env:
|
||||
ENV: 'dev'
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
ENABLE_AUTO_MIGRATIONS: 'false'
|
||||
run: uv run python ./cognee/tests/test_delete_default_graph_with_legacy_data_1.py
|
||||
@@ -0,0 +1,169 @@
|
||||
name: automation | Sync Mintlify Docs
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
sync-mintlify-docs:
|
||||
if: ${{ github.event_name != 'release' || github.event.release.prerelease == false }}
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 20
|
||||
|
||||
steps:
|
||||
- name: Check out core repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
# Normalize release metadata so the sync script can run unchanged for
|
||||
# published releases, manual dispatches, and branch-push preview runs.
|
||||
# This step always produces a body file plus synthetic tag/url/date
|
||||
# values when the event is not an actual GitHub release.
|
||||
- name: Prepare release body file
|
||||
id: release_meta
|
||||
env:
|
||||
EVENT_NAME: ${{ github.event_name }}
|
||||
REF_NAME: ${{ github.ref_name }}
|
||||
COMMIT_SHA: ${{ github.sha }}
|
||||
RELEASE_BODY: ${{ github.event.release.body }}
|
||||
RELEASE_TAG: ${{ github.event.release.tag_name }}
|
||||
RELEASE_URL: ${{ github.event.release.html_url }}
|
||||
RELEASE_PUBLISHED_AT: ${{ github.event.release.published_at }}
|
||||
REPOSITORY: ${{ github.repository }}
|
||||
SERVER_URL: ${{ github.server_url }}
|
||||
run: |
|
||||
BODY_FILE="$(mktemp)"
|
||||
if [ "${EVENT_NAME}" = "release" ]; then
|
||||
TAG="${RELEASE_TAG}"
|
||||
RELEASE_LINK="${RELEASE_URL}"
|
||||
PUBLISHED_AT="${RELEASE_PUBLISHED_AT}"
|
||||
DOCS_BRANCH_NAME="automation/sync-mintlify-docs-${RELEASE_TAG}"
|
||||
printf "%s" "${RELEASE_BODY}" > "${BODY_FILE}"
|
||||
else
|
||||
TAG="test-sync-${REF_NAME}-${COMMIT_SHA::7}"
|
||||
RELEASE_LINK="${SERVER_URL}/${REPOSITORY}/commit/${COMMIT_SHA}"
|
||||
PUBLISHED_AT="$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
|
||||
DOCS_BRANCH_NAME="${REF_NAME}"
|
||||
printf "%s\n\n- Source commit: \`%s\`\n- Workflow event: \`%s\`\n- Commit URL: %s\n" \
|
||||
"Automated docs sync test run from branch \`${REF_NAME}\`." \
|
||||
"${COMMIT_SHA}" \
|
||||
"${EVENT_NAME}" \
|
||||
"${RELEASE_LINK}" > "${BODY_FILE}"
|
||||
fi
|
||||
|
||||
SAFE_DOCS_BRANCH_NAME="${DOCS_BRANCH_NAME// /-}"
|
||||
|
||||
echo "body_file=${BODY_FILE}" >> "$GITHUB_OUTPUT"
|
||||
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
|
||||
echo "release_url=${RELEASE_LINK}" >> "$GITHUB_OUTPUT"
|
||||
echo "published_at=${PUBLISHED_AT}" >> "$GITHUB_OUTPUT"
|
||||
echo "docs_branch_name=${SAFE_DOCS_BRANCH_NAME}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@v7
|
||||
|
||||
- name: Install Python
|
||||
run: uv python install
|
||||
|
||||
- name: Install dependencies
|
||||
run: uv sync --locked --all-extras
|
||||
|
||||
- name: Check out docs repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
repository: topoteretes/cognee-docs
|
||||
token: ${{ secrets.REPO_DISPATCH_PAT_TOKEN }}
|
||||
ref: main
|
||||
path: docs-repo
|
||||
|
||||
- name: Sync OpenAPI and changelog
|
||||
run: |
|
||||
uv run python tools/sync_release_docs.py \
|
||||
--docs-repo "${GITHUB_WORKSPACE}/docs-repo" \
|
||||
--tag "${{ steps.release_meta.outputs.tag }}" \
|
||||
--release-url "${{ steps.release_meta.outputs.release_url }}" \
|
||||
--published-at "${{ steps.release_meta.outputs.published_at }}" \
|
||||
--release-body-file "${{ steps.release_meta.outputs.body_file }}"
|
||||
|
||||
- name: Commit docs changes
|
||||
id: commit_docs
|
||||
working-directory: docs-repo
|
||||
run: |
|
||||
BRANCH_NAME="${{ steps.release_meta.outputs.docs_branch_name }}"
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
git checkout -B "${BRANCH_NAME}"
|
||||
git add cognee_openapi_spec.json changelog.mdx
|
||||
if git diff --cached --quiet; then
|
||||
echo "changes_made=false" >> "$GITHUB_OUTPUT"
|
||||
echo "branch_name=${BRANCH_NAME}" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
git commit -m "docs: sync ${{ steps.release_meta.outputs.tag }}"
|
||||
echo "changes_made=true" >> "$GITHUB_OUTPUT"
|
||||
echo "branch_name=${BRANCH_NAME}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Push docs branch
|
||||
if: ${{ steps.commit_docs.outputs.changes_made == 'true' }}
|
||||
working-directory: docs-repo
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.REPO_DISPATCH_PAT_TOKEN }}
|
||||
run: |
|
||||
git push --force-with-lease origin "${{ steps.commit_docs.outputs.branch_name }}"
|
||||
|
||||
- name: Create or update docs pull request
|
||||
if: ${{ steps.commit_docs.outputs.changes_made == 'true' }}
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.REPO_DISPATCH_PAT_TOKEN }}
|
||||
EVENT_NAME: ${{ github.event_name }}
|
||||
RELEASE_TAG: ${{ steps.release_meta.outputs.tag }}
|
||||
RELEASE_URL: ${{ steps.release_meta.outputs.release_url }}
|
||||
TARGET_REPO: topoteretes/cognee-docs
|
||||
HEAD_BRANCH: ${{ steps.commit_docs.outputs.branch_name }}
|
||||
run: |
|
||||
if [ "${EVENT_NAME}" = "release" ]; then
|
||||
PR_TITLE="docs: sync release ${RELEASE_TAG}"
|
||||
PR_BODY=$(cat <<EOF
|
||||
Automated sync for release \`${RELEASE_TAG}\`.
|
||||
|
||||
Source release: ${RELEASE_URL}
|
||||
EOF
|
||||
)
|
||||
else
|
||||
PR_TITLE="test(docs): preview sync for ${HEAD_BRANCH}"
|
||||
PR_BODY=$(cat <<EOF
|
||||
Automated preview sync from branch \`${HEAD_BRANCH}\`.
|
||||
|
||||
Source commit/revision: ${RELEASE_URL}
|
||||
EOF
|
||||
)
|
||||
fi
|
||||
|
||||
HEAD_REF="topoteretes:${HEAD_BRANCH}"
|
||||
|
||||
EXISTING_PR_NUMBER="$(gh pr list \
|
||||
--repo "${TARGET_REPO}" \
|
||||
--head "${HEAD_REF}" \
|
||||
--base main \
|
||||
--state open \
|
||||
--json number \
|
||||
--jq '.[0].number // empty')"
|
||||
|
||||
if [ -n "${EXISTING_PR_NUMBER}" ]; then
|
||||
gh pr edit "${EXISTING_PR_NUMBER}" \
|
||||
--repo "${TARGET_REPO}" \
|
||||
--title "${PR_TITLE}" \
|
||||
--body "${PR_BODY}"
|
||||
else
|
||||
gh pr create \
|
||||
--repo "${TARGET_REPO}" \
|
||||
--base main \
|
||||
--head "${HEAD_REF}" \
|
||||
--title "${PR_TITLE}" \
|
||||
--body "${PR_BODY}"
|
||||
fi
|
||||
@@ -0,0 +1,230 @@
|
||||
name: Temporal Graph Tests
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: read
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
databases:
|
||||
required: false
|
||||
type: string
|
||||
default: "all"
|
||||
description: "Which vector databases to test (comma-separated list or 'all')"
|
||||
ci-image:
|
||||
required: false
|
||||
type: string
|
||||
default: ''
|
||||
description: "Optional container image for CI"
|
||||
|
||||
env:
|
||||
COGNEE_SKIP_CONNECTION_TEST: 'true'
|
||||
|
||||
jobs:
|
||||
run_temporal_graph_kuzu_lance_sqlite:
|
||||
name: Temporal Graph test Kuzu (lancedb + sqlite)
|
||||
runs-on: ubuntu-22.04
|
||||
if: ${{ inputs.databases == 'all' || contains(inputs.databases, 'kuzu/lance/sqlite') }}
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
steps:
|
||||
- name: Check out
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: ${{ inputs.python-version }}
|
||||
|
||||
- name: Dependencies already installed
|
||||
run: echo "Dependencies already installed in setup"
|
||||
|
||||
- name: Run Temporal Graph with Kuzu (lancedb + sqlite)
|
||||
env:
|
||||
ENV: 'dev'
|
||||
LLM_MODEL: ${{ secrets.OPENAI_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.OPENAI_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
GRAPH_DATABASE_PROVIDER: 'kuzu'
|
||||
VECTOR_DB_PROVIDER: 'lancedb'
|
||||
DB_PROVIDER: 'sqlite'
|
||||
run: uv run python ./cognee/tests/test_temporal_graph.py
|
||||
|
||||
run_temporal_graph_neo4j_lance_sqlite:
|
||||
name: Temporal Graph test Neo4j (lancedb + sqlite)
|
||||
runs-on: ubuntu-22.04
|
||||
if: ${{ inputs.databases == 'all' || contains(inputs.databases, 'neo4j/lance/sqlite') }}
|
||||
|
||||
steps:
|
||||
- name: Check out
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: ${{ inputs.python-version }}
|
||||
|
||||
- name: Setup Neo4j with GDS
|
||||
uses: ./.github/actions/setup_neo4j
|
||||
id: neo4j
|
||||
|
||||
- name: Dependencies already installed
|
||||
run: echo "Dependencies already installed in setup"
|
||||
|
||||
- name: Run Temporal Graph with Neo4j (lancedb + sqlite)
|
||||
env:
|
||||
ENV: 'dev'
|
||||
ENABLE_BACKEND_ACCESS_CONTROL: 'false'
|
||||
LLM_MODEL: ${{ secrets.OPENAI_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.OPENAI_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
GRAPH_DATABASE_PROVIDER: 'neo4j'
|
||||
VECTOR_DB_PROVIDER: 'lancedb'
|
||||
DB_PROVIDER: 'sqlite'
|
||||
GRAPH_DATABASE_URL: ${{ steps.neo4j.outputs.neo4j-url }}
|
||||
GRAPH_DATABASE_USERNAME: ${{ steps.neo4j.outputs.neo4j-username }}
|
||||
GRAPH_DATABASE_PASSWORD: ${{ steps.neo4j.outputs.neo4j-password }}
|
||||
run: uv run python ./cognee/tests/test_temporal_graph.py
|
||||
|
||||
run_temporal_graph_kuzu_postgres_pgvector:
|
||||
name: Temporal Graph test Kuzu (postgres + pgvector)
|
||||
runs-on: ubuntu-22.04
|
||||
if: ${{ inputs.databases == 'all' || contains(inputs.databases, 'kuzu/pgvector/postgres') }}
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
services:
|
||||
postgres:
|
||||
image: ghcr.io/topoteretes/pgvector:pg17
|
||||
credentials:
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
env:
|
||||
POSTGRES_USER: cognee
|
||||
POSTGRES_PASSWORD: cognee
|
||||
POSTGRES_DB: cognee_db
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
ports:
|
||||
- 5432:5432
|
||||
steps:
|
||||
- name: Check out
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: ${{ inputs.python-version }}
|
||||
extra-dependencies: "postgres"
|
||||
|
||||
- name: Dependencies already installed
|
||||
run: echo "Dependencies already installed in setup"
|
||||
|
||||
- name: Run Temporal Graph with Kuzu (postgres + pgvector)
|
||||
env:
|
||||
ENV: dev
|
||||
ENABLE_BACKEND_ACCESS_CONTROL: 'false'
|
||||
LLM_MODEL: ${{ secrets.OPENAI_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.OPENAI_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
GRAPH_DATABASE_PROVIDER: 'kuzu'
|
||||
VECTOR_DB_PROVIDER: 'pgvector'
|
||||
DB_PROVIDER: 'postgres'
|
||||
DB_NAME: 'cognee_db'
|
||||
DB_HOST: ${{ inputs.ci-image != '' && 'postgres' || '127.0.0.1' }}
|
||||
DB_PORT: 5432
|
||||
DB_USERNAME: cognee
|
||||
DB_PASSWORD: cognee
|
||||
run: uv run python ./cognee/tests/test_temporal_graph.py
|
||||
|
||||
run_temporal_graph_neo4j_postgres_pgvector:
|
||||
name: Temporal Graph test Neo4j (postgres + pgvector)
|
||||
runs-on: ubuntu-22.04
|
||||
if: ${{ inputs.databases == 'all' || contains(inputs.databases, 'neo4j/pgvector/postgres') }}
|
||||
services:
|
||||
neo4j:
|
||||
image: neo4j:5.11
|
||||
env:
|
||||
NEO4J_AUTH: neo4j/pleaseletmein
|
||||
NEO4J_PLUGINS: '["apoc","graph-data-science"]'
|
||||
ports:
|
||||
- 7474:7474
|
||||
- 7687:7687
|
||||
options: >-
|
||||
--health-cmd="cypher-shell -u neo4j -p pleaseletmein 'RETURN 1'"
|
||||
--health-interval=10s
|
||||
--health-timeout=5s
|
||||
--health-retries=5
|
||||
postgres:
|
||||
image: ghcr.io/topoteretes/pgvector:pg17
|
||||
credentials:
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
env:
|
||||
POSTGRES_USER: cognee
|
||||
POSTGRES_PASSWORD: cognee
|
||||
POSTGRES_DB: cognee_db
|
||||
ports:
|
||||
- 5432:5432
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries=5
|
||||
steps:
|
||||
- name: Check out
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: ${{ inputs.python-version }}
|
||||
extra-dependencies: "postgres"
|
||||
|
||||
- name: Dependencies already installed
|
||||
run: echo "Dependencies already installed in setup"
|
||||
|
||||
- name: Run Temporal Graph with Neo4j (postgres + pgvector)
|
||||
env:
|
||||
ENV: dev
|
||||
ENABLE_BACKEND_ACCESS_CONTROL: 'false'
|
||||
LLM_MODEL: ${{ secrets.OPENAI_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.OPENAI_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
GRAPH_DATABASE_PROVIDER: 'neo4j'
|
||||
VECTOR_DB_PROVIDER: 'pgvector'
|
||||
DB_PROVIDER: 'postgres'
|
||||
GRAPH_DATABASE_URL: bolt://localhost:7687
|
||||
GRAPH_DATABASE_USERNAME: neo4j
|
||||
GRAPH_DATABASE_PASSWORD: pleaseletmein
|
||||
DB_NAME: cognee_db
|
||||
DB_HOST: 127.0.0.1
|
||||
DB_PORT: 5432
|
||||
DB_USERNAME: cognee
|
||||
DB_PASSWORD: cognee
|
||||
run: uv run python ./cognee/tests/test_temporal_graph.py
|
||||
@@ -0,0 +1,220 @@
|
||||
name: Tests to run on different Operating Systems
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
python-versions:
|
||||
required: false
|
||||
type: string
|
||||
default: '["3.10.x", "3.12.x", "3.13.x"]'
|
||||
os:
|
||||
required: false
|
||||
type: string
|
||||
default: '["ubuntu-22.04", "macos-15", "windows-latest"]'
|
||||
extra-dependencies:
|
||||
# Space-separated package extras for the unit-test job (e.g. "postgres").
|
||||
# Driver-dependent tests importorskip when their extra is absent.
|
||||
required: false
|
||||
type: string
|
||||
default: ''
|
||||
secrets:
|
||||
LLM_PROVIDER:
|
||||
required: true
|
||||
LLM_MODEL:
|
||||
required: true
|
||||
LLM_ENDPOINT:
|
||||
required: true
|
||||
LLM_API_KEY:
|
||||
required: true
|
||||
LLM_ARGS:
|
||||
required: false
|
||||
LLM_API_VERSION:
|
||||
required: true
|
||||
EMBEDDING_PROVIDER:
|
||||
required: true
|
||||
EMBEDDING_MODEL:
|
||||
required: true
|
||||
EMBEDDING_API_KEY:
|
||||
required: true
|
||||
|
||||
env:
|
||||
RUNTIME__LOG_LEVEL: ERROR
|
||||
ENV: 'dev'
|
||||
|
||||
jobs:
|
||||
run-unit-tests:
|
||||
name: Unit tests ${{ matrix.python-version }} on ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ${{ fromJSON(inputs.python-versions) }}
|
||||
os: ${{ fromJSON(inputs.os) }}
|
||||
fail-fast: false
|
||||
steps:
|
||||
- name: Check out
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
extra-dependencies: ${{ inputs.extra-dependencies }}
|
||||
|
||||
- name: Run unit tests
|
||||
shell: bash
|
||||
run: uv run pytest cognee/tests/unit/ --timeout=300 --timeout-method=thread
|
||||
env:
|
||||
PYTHONUTF8: 1
|
||||
LLM_PROVIDER: openai
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
|
||||
EMBEDDING_PROVIDER: openai
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
|
||||
run-library-test:
|
||||
name: Library test ${{ matrix.python-version }} on ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ${{ fromJSON(inputs.python-versions) }}
|
||||
os: ${{ fromJSON(inputs.os) }}
|
||||
fail-fast: false
|
||||
steps:
|
||||
- name: Check out
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
|
||||
- name: Run default basic pipeline
|
||||
shell: bash
|
||||
env:
|
||||
PYTHONUTF8: 1
|
||||
LLM_PROVIDER: openai
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
|
||||
EMBEDDING_PROVIDER: openai
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
run: uv run python ./cognee/tests/test_library.py
|
||||
|
||||
run-build-test:
|
||||
name: Build test ${{ matrix.python-version }} on ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ${{ fromJSON(inputs.python-versions) }}
|
||||
os: ${{ fromJSON(inputs.os) }}
|
||||
fail-fast: false
|
||||
steps:
|
||||
- name: Check out
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
|
||||
- name: Build with uv
|
||||
shell: bash
|
||||
run: uv build
|
||||
|
||||
- name: Install Package
|
||||
if: ${{ !contains(matrix.os, 'windows-latest') }}
|
||||
run: |
|
||||
cd dist
|
||||
pip install *.whl
|
||||
|
||||
run-soft-deletion-test:
|
||||
name: Soft Delete test ${{ matrix.python-version }} on ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ${{ fromJSON(inputs.python-versions) }}
|
||||
os: ${{ fromJSON(inputs.os) }}
|
||||
fail-fast: false
|
||||
steps:
|
||||
- name: Check out
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
|
||||
- name: Path setup
|
||||
if: ${{ matrix.os == 'windows-latest' }}
|
||||
shell: bash
|
||||
run: |
|
||||
PATH=$(printf '%s' "$PATH" | tr ':' $'\n' | grep -vi '/git/usr/bin' | paste -sd: -)
|
||||
export PATH
|
||||
|
||||
- name: Run Soft Deletion Tests
|
||||
env:
|
||||
ENV: 'dev'
|
||||
LLM_API_KEY: ${{ secrets.OPENAI_API_KEY }} # Test needs OpenAI endpoint to handle multimedia
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
run: uv run python ./cognee/tests/test_delete_default_graph.py
|
||||
|
||||
run-hard-deletion-test:
|
||||
name: Custom Graph Delete test ${{ matrix.python-version }} on ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ${{ fromJSON(inputs.python-versions) }}
|
||||
os: ${{ fromJSON(inputs.os) }}
|
||||
fail-fast: false
|
||||
steps:
|
||||
- name: Check out
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
|
||||
- name: Run Custom Graph Deletion Test
|
||||
env:
|
||||
ENV: 'dev'
|
||||
LLM_API_KEY: ${{ secrets.OPENAI_API_KEY }} # Test needs OpenAI endpoint to handle multimedia
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
run: uv run python ./cognee/tests/test_delete_custom_graph.py
|
||||
@@ -0,0 +1,61 @@
|
||||
name: test | ollama
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
env:
|
||||
COGNEE_SKIP_CONNECTION_TEST: 'true'
|
||||
|
||||
jobs:
|
||||
|
||||
run_llama-cpp_test:
|
||||
|
||||
# needs ~4 Gb RAM for the GGUF model in a container which the smallest runner has
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: '3.13.x'
|
||||
extra-dependencies: postgres llama-cpp
|
||||
|
||||
- name: Install torch dependency
|
||||
run: |
|
||||
uv add torch
|
||||
|
||||
- name: Download Phi-3.5 GGUF model from S3
|
||||
# Mirrored from huggingface.co/bartowski/Phi-3.5-mini-instruct-GGUF (MIT)
|
||||
# into our bucket to avoid HuggingFace 429 rate limits in CI.
|
||||
# Phi-3.5-mini reliably emits the required per-node `description`;
|
||||
# the previous Phi-3-mini-q4 dropped it, failing extraction.
|
||||
env:
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_S3_DEV_USER_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_S3_DEV_USER_SECRET_KEY }}
|
||||
AWS_DEFAULT_REGION: eu-west-1
|
||||
BUCKET: github-runner-cognee-tests
|
||||
MODEL_KEY: nightly_ci_artifacts/huggingface_models/Phi-3.5-mini-instruct-Q4_K_M.gguf
|
||||
MODEL_SHA256: e4165e3a71af97f1b4820da61079826d8752a2088e313af0c7d346796c38eff5
|
||||
run: |
|
||||
set -euo pipefail
|
||||
aws s3 cp "s3://$BUCKET/$MODEL_KEY" ./Phi-3.5-mini-instruct-Q4_K_M.gguf
|
||||
echo "$MODEL_SHA256 ./Phi-3.5-mini-instruct-Q4_K_M.gguf" | sha256sum -c -
|
||||
|
||||
- name: Run example test
|
||||
env:
|
||||
PYTHONFAULTHANDLER: 1
|
||||
LLM_PROVIDER: "llama_cpp"
|
||||
LLAMA_CPP_MODEL_PATH: "./Phi-3.5-mini-instruct-Q4_K_M.gguf"
|
||||
LLM_ENDPOINT: ""
|
||||
LLAMA_CPP_N_CTX: 4096
|
||||
EMBEDDING_PROVIDER: "openai"
|
||||
LLM_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
EMBEDDING_MODEL: "openai/text-embedding-3-large"
|
||||
EMBEDDING_DIMENSIONS: "3072"
|
||||
EMBEDDING_MAX_TOKENS: "8191"
|
||||
STRUCTURED_OUTPUT_FRAMEWORK: "instructor"
|
||||
LLM_INSTRUCTOR_MODE: ""
|
||||
run: uv run python ./examples/demos/simple_cognee_example.py
|
||||
@@ -0,0 +1,220 @@
|
||||
name: LLM Test Suites
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: read
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
ci-image:
|
||||
required: false
|
||||
type: string
|
||||
default: ''
|
||||
|
||||
env:
|
||||
RUNTIME__LOG_LEVEL: ERROR
|
||||
ENV: 'dev'
|
||||
COGNEE_SKIP_CONNECTION_TEST: 'true'
|
||||
|
||||
jobs:
|
||||
test-gemini:
|
||||
name: Run Gemini Test
|
||||
runs-on: ubuntu-22.04
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: '3.11.x'
|
||||
|
||||
- name: Run Gemini Simple Example
|
||||
env:
|
||||
LLM_PROVIDER: "gemini"
|
||||
LLM_API_KEY: ${{ secrets.GEMINI_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_MODEL: "gemini/gemini-3-flash-preview"
|
||||
EMBEDDING_PROVIDER: "gemini"
|
||||
EMBEDDING_API_KEY: ${{ secrets.GEMINI_API_KEY }}
|
||||
EMBEDDING_MODEL: "gemini/gemini-embedding-001"
|
||||
EMBEDDING_DIMENSIONS: "768"
|
||||
EMBEDDING_MAX_TOKENS: "8076"
|
||||
run: uv run python ./examples/demos/simple_cognee_example.py
|
||||
|
||||
test-fastembed:
|
||||
name: Run Fastembed Test
|
||||
runs-on: ubuntu-22.04
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: '3.11.x'
|
||||
|
||||
- name: Run Fastembed Simple Example
|
||||
env:
|
||||
LLM_PROVIDER: "openai"
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_PROVIDER: "fastembed"
|
||||
EMBEDDING_MODEL: "sentence-transformers/all-MiniLM-L6-v2"
|
||||
EMBEDDING_DIMENSIONS: "384"
|
||||
EMBEDDING_MAX_TOKENS: "256"
|
||||
run: uv run python ./examples/demos/simple_cognee_example.py
|
||||
|
||||
test-openrouter:
|
||||
name: Run OpenRouter Test
|
||||
runs-on: ubuntu-22.04
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: '3.11.x'
|
||||
|
||||
- name: Run OpenRouter Simple Example
|
||||
env:
|
||||
LLM_PROVIDER: "custom"
|
||||
LLM_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_MODEL: "openrouter/x-ai/grok-4.3"
|
||||
LLM_ENDPOINT: "https://openrouter.ai/api/v1"
|
||||
EMBEDDING_PROVIDER: "openai"
|
||||
EMBEDDING_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
EMBEDDING_MODEL: "openai/text-embedding-3-large"
|
||||
EMBEDDING_DIMENSIONS: "3072"
|
||||
EMBEDDING_MAX_TOKENS: "8191"
|
||||
run: uv run python ./examples/demos/simple_cognee_example.py
|
||||
|
||||
test-bedrock-api-key:
|
||||
name: Run Bedrock API Key Test
|
||||
runs-on: ubuntu-22.04
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: '3.11.x'
|
||||
extra-dependencies: "aws"
|
||||
|
||||
- name: Run Bedrock API Key Simple Example
|
||||
env:
|
||||
LLM_PROVIDER: "bedrock"
|
||||
LLM_API_KEY: ${{ secrets.BEDROCK_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_MODEL: "eu.anthropic.claude-sonnet-4-5-20250929-v1:0"
|
||||
LLM_MAX_TOKENS: "16384"
|
||||
AWS_REGION_NAME: "eu-west-1"
|
||||
EMBEDDING_PROVIDER: "bedrock"
|
||||
EMBEDDING_API_KEY: ${{ secrets.BEDROCK_API_KEY }}
|
||||
EMBEDDING_MODEL: "amazon.titan-embed-text-v2:0"
|
||||
EMBEDDING_DIMENSIONS: "1024"
|
||||
EMBEDDING_MAX_TOKENS: "8191"
|
||||
run: uv run python ./examples/demos/simple_cognee_example.py
|
||||
|
||||
test-bedrock-aws-credentials:
|
||||
name: Run Bedrock AWS Credentials Test
|
||||
runs-on: ubuntu-22.04
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: '3.11.x'
|
||||
extra-dependencies: "aws"
|
||||
|
||||
- name: Run Bedrock AWS Credentials Simple Example
|
||||
env:
|
||||
LLM_PROVIDER: "bedrock"
|
||||
LLM_MODEL: "eu.anthropic.claude-sonnet-4-5-20250929-v1:0"
|
||||
LLM_MAX_TOKENS: "16384"
|
||||
AWS_REGION_NAME: "eu-west-1"
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
EMBEDDING_PROVIDER: "bedrock"
|
||||
EMBEDDING_API_KEY: ${{ secrets.BEDROCK_API_KEY }}
|
||||
EMBEDDING_MODEL: "amazon.titan-embed-text-v2:0"
|
||||
EMBEDDING_DIMENSIONS: "1024"
|
||||
EMBEDDING_MAX_TOKENS: "8191"
|
||||
run: uv run python ./examples/demos/simple_cognee_example.py
|
||||
|
||||
test-bedrock-aws-profile:
|
||||
name: Run Bedrock AWS Profile Test
|
||||
runs-on: ubuntu-22.04
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: '3.11.x'
|
||||
extra-dependencies: "aws"
|
||||
|
||||
- name: Configure AWS Profile
|
||||
run: |
|
||||
mkdir -p ~/.aws
|
||||
cat > ~/.aws/credentials << EOF
|
||||
[bedrock-test]
|
||||
aws_access_key_id = ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws_secret_access_key = ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
EOF
|
||||
|
||||
- name: Run Bedrock AWS Profile Simple Example
|
||||
env:
|
||||
LLM_PROVIDER: "bedrock"
|
||||
LLM_MODEL: "eu.anthropic.claude-sonnet-4-5-20250929-v1:0"
|
||||
LLM_MAX_TOKENS: "16384"
|
||||
AWS_PROFILE_NAME: "bedrock-test"
|
||||
AWS_REGION_NAME: "eu-west-1"
|
||||
EMBEDDING_PROVIDER: "bedrock"
|
||||
EMBEDDING_MODEL: "amazon.titan-embed-text-v2:0"
|
||||
EMBEDDING_DIMENSIONS: "1024"
|
||||
EMBEDDING_MAX_TOKENS: "8191"
|
||||
run: uv run python ./examples/demos/simple_cognee_example.py
|
||||
|
||||
test-claude-anthropic:
|
||||
name: Run Anthropic Claude LLM Test
|
||||
runs-on: ubuntu-22.04
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: '3.11.x'
|
||||
|
||||
- name: Run Claude Anthropic LLM Simple Example
|
||||
env:
|
||||
LLM_PROVIDER: "anthropic"
|
||||
# Note: If model becomes outdated update docs with new model as well
|
||||
LLM_MODEL: "anthropic/claude-sonnet-4-5-20250929"
|
||||
LLM_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_MAX_TOKENS: "16384"
|
||||
EMBEDDING_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
EMBEDDING_MODEL: "openai/text-embedding-3-large"
|
||||
EMBEDDING_DIMENSIONS: "3072"
|
||||
EMBEDDING_MAX_TOKENS: "8191"
|
||||
run: uv run python ./examples/demos/simple_cognee_example.py
|
||||
@@ -0,0 +1,64 @@
|
||||
name: test | mcp
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
cognee_version:
|
||||
required: false
|
||||
type: string
|
||||
default: "local" # local - Installing Cognee from local source
|
||||
description: "Pypi-compatible version of cognee to use. For example, 0.5.2.dev0. `local` (default) - Installing Cognee from local source"
|
||||
|
||||
env:
|
||||
COGNEE_SKIP_CONNECTION_TEST: 'true'
|
||||
|
||||
jobs:
|
||||
test-mcp:
|
||||
name: Run MCP Test
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: ${{ inputs.python-version }}
|
||||
|
||||
- name: Install UV
|
||||
shell: bash
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install uv
|
||||
|
||||
- name: Install dependencies
|
||||
shell: bash
|
||||
working-directory: cognee-mcp
|
||||
run: uv sync
|
||||
|
||||
- name: Install Cognee
|
||||
uses: ./.github/actions/install_cognee
|
||||
with:
|
||||
python-version: ${{ inputs.python-version }}
|
||||
cognee_version: ${{ inputs.cognee_version }}
|
||||
|
||||
- name: Run MCP unit tests
|
||||
working-directory: cognee-mcp
|
||||
run: uv run --no-sync pytest tests/
|
||||
|
||||
- name: Run MCP test
|
||||
env:
|
||||
ENV: 'dev'
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
working-directory: cognee-mcp
|
||||
run: |
|
||||
echo "Cognee Version:"
|
||||
uv pip show cognee | grep Version
|
||||
uv run --no-sync python ./src/test_client.py
|
||||
@@ -0,0 +1,111 @@
|
||||
name: test | ollama
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
env:
|
||||
COGNEE_SKIP_CONNECTION_TEST: 'true'
|
||||
|
||||
jobs:
|
||||
|
||||
run_ollama_test:
|
||||
|
||||
# TODO: needs 32 Gb RAM for phi4 in a container — GitHub-hosted larger runner
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: '3.11.x'
|
||||
|
||||
- name: Install torch dependency
|
||||
run: |
|
||||
uv add torch
|
||||
|
||||
- name: Start Ollama container
|
||||
run: |
|
||||
docker run -d --name ollama -p 11434:11434 ollama/ollama
|
||||
sleep 5
|
||||
docker exec -d ollama bash -c "ollama serve --openai"
|
||||
|
||||
- name: Check Ollama logs
|
||||
run: docker logs ollama
|
||||
|
||||
- name: Wait for Ollama to be ready
|
||||
run: |
|
||||
for i in {1..30}; do
|
||||
if curl -s http://localhost:11434/v1/models > /dev/null; then
|
||||
echo "Ollama is ready"
|
||||
exit 0
|
||||
fi
|
||||
echo "Waiting for Ollama... attempt $i"
|
||||
sleep 2
|
||||
done
|
||||
echo "Ollama failed to start"
|
||||
exit 1
|
||||
|
||||
- name: Pull required Ollama models
|
||||
run: |
|
||||
curl -X POST http://localhost:11434/api/pull -d '{"name": "phi4"}'
|
||||
curl -X POST http://localhost:11434/api/pull -d '{"name": "qwen3-embedding:latest"}'
|
||||
|
||||
- name: Call ollama API
|
||||
run: |
|
||||
curl -X POST http://localhost:11434/v1/chat/completions \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"model": "phi4",
|
||||
"stream": false,
|
||||
"messages": [
|
||||
{ "role": "system", "content": "You are a helpful assistant." },
|
||||
{ "role": "user", "content": "Whatever I say, answer with Yes." }
|
||||
]
|
||||
}'
|
||||
curl -X POST http://127.0.0.1:11434/api/embed \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"model": "qwen3-embedding:latest",
|
||||
"input": "This is a test sentence to generate an embedding."
|
||||
}'
|
||||
|
||||
- name: Dump Docker logs
|
||||
run: |
|
||||
docker ps
|
||||
docker logs $(docker ps --filter "ancestor=ollama/ollama" --format "{{.ID}}")
|
||||
|
||||
- name: Download embedding tokenizer from S3
|
||||
# Mirrored from huggingface.co/Qwen/Qwen3-Embedding-8B (Apache-2.0) so the
|
||||
# embedding tokenizer loads offline and never hits HuggingFace 429s in CI.
|
||||
env:
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_S3_DEV_USER_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_S3_DEV_USER_SECRET_KEY }}
|
||||
AWS_DEFAULT_REGION: eu-west-1
|
||||
BUCKET: github-runner-cognee-tests
|
||||
TOKENIZER_KEY: nightly_ci_artifacts/huggingface_models/qwen3-embedding-tokenizer.tar.gz
|
||||
TOKENIZER_SHA256: 8f5834d8791c8da03220feaccc2fe9c443e23b1092dcd99c576ef613990bbd00
|
||||
run: |
|
||||
set -euo pipefail
|
||||
aws s3 cp "s3://$BUCKET/$TOKENIZER_KEY" tokenizer.tar.gz
|
||||
echo "$TOKENIZER_SHA256 tokenizer.tar.gz" | sha256sum -c -
|
||||
tar -xzf tokenizer.tar.gz -C "$GITHUB_WORKSPACE"
|
||||
|
||||
- name: Run example test
|
||||
env:
|
||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
PYTHONFAULTHANDLER: 1
|
||||
LLM_PROVIDER: "ollama"
|
||||
LLM_API_KEY: "ollama"
|
||||
LLM_ENDPOINT: "http://localhost:11434/v1/"
|
||||
LLM_MODEL: "phi4"
|
||||
EMBEDDING_PROVIDER: "ollama"
|
||||
EMBEDDING_MODEL: "qwen3-embedding:latest"
|
||||
EMBEDDING_ENDPOINT: "http://localhost:11434/api/embed"
|
||||
EMBEDDING_DIMENSIONS: "4096"
|
||||
# Load the tokenizer from the S3-mirrored local dir, fully offline.
|
||||
HUGGINGFACE_TOKENIZER: "${{ github.workspace }}/qwen3-embedding-tokenizer"
|
||||
HF_HUB_OFFLINE: "1"
|
||||
TRANSFORMERS_OFFLINE: "1"
|
||||
run: uv run python ./examples/demos/simple_cognee_example.py
|
||||
@@ -0,0 +1,52 @@
|
||||
name: test | s3 file storage
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
ci-image:
|
||||
required: false
|
||||
type: string
|
||||
default: ''
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: read
|
||||
|
||||
env:
|
||||
RUNTIME__LOG_LEVEL: ERROR
|
||||
ENV: 'dev'
|
||||
COGNEE_SKIP_CONNECTION_TEST: 'true'
|
||||
|
||||
jobs:
|
||||
test-s3-storage:
|
||||
name: Run S3 File Storage Test
|
||||
runs-on: ubuntu-22.04
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: '3.11.x'
|
||||
extra-dependencies: "aws"
|
||||
|
||||
- name: Run S3 File Storage Test
|
||||
env:
|
||||
STORAGE_BACKEND: s3
|
||||
ENABLE_BACKEND_ACCESS_CONTROL: True
|
||||
AWS_REGION: eu-west-1
|
||||
AWS_ENDPOINT_URL: https://s3-eu-west-1.amazonaws.com
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_S3_DEV_USER_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_S3_DEV_USER_SECRET_KEY }}
|
||||
STORAGE_BUCKET_NAME: github-runner-cognee-tests
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
run: uv run python ./cognee/tests/test_s3_file_storage.py
|
||||
@@ -0,0 +1,413 @@
|
||||
name: Test Suites
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, dev ]
|
||||
pull_request:
|
||||
branches: [ main, dev ]
|
||||
types: [opened, synchronize, reopened, labeled]
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
RUNTIME__LOG_LEVEL: ERROR
|
||||
ENV: 'dev'
|
||||
|
||||
jobs:
|
||||
# ── Build pre-baked CI container ──────────────────────────────────────
|
||||
build-ci-env:
|
||||
name: Build CI Environment
|
||||
runs-on: ubuntu-latest
|
||||
if: >-
|
||||
github.event_name == 'push' || github.event_name == 'workflow_dispatch' ||
|
||||
(github.event_name == 'pull_request' &&
|
||||
github.event.pull_request.head.repo.full_name == github.repository)
|
||||
outputs:
|
||||
ci-image: ${{ steps.set-image.outputs.image }}
|
||||
steps:
|
||||
- name: Sparse checkout (deps only)
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
sparse-checkout: |
|
||||
pyproject.toml
|
||||
uv.lock
|
||||
README.md
|
||||
Dockerfile.ci
|
||||
.dockerignore.ci
|
||||
sparse-checkout-cone-mode: false
|
||||
|
||||
- name: Compute dep hash and image tag
|
||||
id: set-image
|
||||
run: |
|
||||
DEP_HASH=$(sha256sum pyproject.toml uv.lock | sha256sum | head -c 16)
|
||||
IMAGE="ghcr.io/${{ github.repository }}/ci-env:deps-${DEP_HASH}"
|
||||
echo "image=${IMAGE}" >> "$GITHUB_OUTPUT"
|
||||
echo "dep_hash=${DEP_HASH}" >> "$GITHUB_OUTPUT"
|
||||
echo "Image tag: ${IMAGE}"
|
||||
|
||||
- name: Log in to GHCR
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Check if image already exists
|
||||
id: check
|
||||
run: |
|
||||
if docker manifest inspect "${{ steps.set-image.outputs.image }}" > /dev/null 2>&1; then
|
||||
echo "exists=true" >> "$GITHUB_OUTPUT"
|
||||
echo "Image already exists, skipping build."
|
||||
else
|
||||
echo "exists=false" >> "$GITHUB_OUTPUT"
|
||||
echo "Image not found, will build."
|
||||
fi
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
if: steps.check.outputs.exists != 'true'
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Build and push CI image
|
||||
if: steps.check.outputs.exists != 'true'
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: Dockerfile.ci
|
||||
push: true
|
||||
tags: ${{ steps.set-image.outputs.image }}
|
||||
cache-from: type=registry,ref=ghcr.io/${{ github.repository }}/ci-env:buildcache
|
||||
cache-to: type=registry,ref=ghcr.io/${{ github.repository }}/ci-env:buildcache,mode=max
|
||||
|
||||
pre-test:
|
||||
name: basic checks
|
||||
uses: ./.github/workflows/pre_test.yml
|
||||
|
||||
basic-tests:
|
||||
name: Basic Tests
|
||||
uses: ./.github/workflows/basic_tests.yml
|
||||
needs: [ build-ci-env ]
|
||||
if: ${{ !cancelled() }}
|
||||
with:
|
||||
ci-image: ${{ needs.build-ci-env.outputs.ci-image || '' }}
|
||||
secrets: inherit
|
||||
|
||||
e2e-tests:
|
||||
name: End-to-End Tests
|
||||
uses: ./.github/workflows/e2e_tests.yml
|
||||
needs: [ build-ci-env ]
|
||||
if: ${{ !cancelled() }}
|
||||
with:
|
||||
ci-image: ${{ needs.build-ci-env.outputs.ci-image || '' }}
|
||||
secrets: inherit
|
||||
|
||||
cli-tests:
|
||||
name: CLI Tests
|
||||
uses: ./.github/workflows/cli_tests.yml
|
||||
needs: [ build-ci-env ]
|
||||
if: ${{ !cancelled() }}
|
||||
with:
|
||||
ci-image: ${{ needs.build-ci-env.outputs.ci-image || '' }}
|
||||
secrets: inherit
|
||||
|
||||
slow-e2e-tests:
|
||||
name: Slow End-to-End Tests
|
||||
uses: ./.github/workflows/slow_e2e_tests.yml
|
||||
needs: [ build-ci-env ]
|
||||
if: ${{ !cancelled() }}
|
||||
with:
|
||||
ci-image: ${{ needs.build-ci-env.outputs.ci-image || '' }}
|
||||
secrets: inherit
|
||||
|
||||
graph-db-tests:
|
||||
name: Graph Database Tests
|
||||
needs: [ build-ci-env ]
|
||||
if: ${{ !cancelled() }}
|
||||
uses: ./.github/workflows/graph_db_tests.yml
|
||||
with:
|
||||
ci-image: ${{ needs.build-ci-env.outputs.ci-image || '' }}
|
||||
secrets: inherit
|
||||
|
||||
vector-db-tests:
|
||||
name: Vector DB Tests
|
||||
needs: [ build-ci-env ]
|
||||
if: ${{ !cancelled() }}
|
||||
uses: ./.github/workflows/vector_db_tests.yml
|
||||
with:
|
||||
ci-image: ${{ needs.build-ci-env.outputs.ci-image || '' }}
|
||||
secrets: inherit
|
||||
|
||||
example-tests:
|
||||
name: Example Tests
|
||||
needs: [ build-ci-env ]
|
||||
if: ${{ !cancelled() }}
|
||||
uses: ./.github/workflows/examples_tests.yml
|
||||
with:
|
||||
ci-image: ${{ needs.build-ci-env.outputs.ci-image || '' }}
|
||||
secrets: inherit
|
||||
|
||||
notebook-tests:
|
||||
name: Notebook Tests
|
||||
needs: [ build-ci-env ]
|
||||
if: ${{ !cancelled() }}
|
||||
uses: ./.github/workflows/notebooks_tests.yml
|
||||
with:
|
||||
ci-image: ${{ needs.build-ci-env.outputs.ci-image || '' }}
|
||||
secrets: inherit
|
||||
|
||||
different-os-tests-basic:
|
||||
name: OS and Python Tests Ubuntu
|
||||
uses: ./.github/workflows/test_different_operating_systems.yml
|
||||
with:
|
||||
python-versions: '["3.10.x", "3.11.x", "3.12.x", "3.13.x", "3.14.x"]'
|
||||
os: '["ubuntu-22.04"]'
|
||||
# postgres so the SQL cache adapter tests run instead of skipping; omitted
|
||||
# on macos/windows (extended) where psycopg2 has no prebuilt wheels.
|
||||
extra-dependencies: 'postgres'
|
||||
secrets: inherit
|
||||
|
||||
different-os-tests-extended:
|
||||
name: OS and Python Tests Extended
|
||||
uses: ./.github/workflows/test_different_operating_systems.yml
|
||||
with:
|
||||
python-versions: '["3.13.x"]'
|
||||
os: '["macos-15", "windows-latest"]'
|
||||
secrets: inherit
|
||||
|
||||
llm-tests:
|
||||
name: LLM Test Suite
|
||||
needs: [ build-ci-env ]
|
||||
if: ${{ !cancelled() }}
|
||||
uses: ./.github/workflows/test_llms.yml
|
||||
with:
|
||||
ci-image: ${{ needs.build-ci-env.outputs.ci-image || '' }}
|
||||
secrets: inherit
|
||||
|
||||
s3-file-storage-test:
|
||||
name: S3 File Storage Test
|
||||
needs: [ build-ci-env ]
|
||||
if: ${{ !cancelled() }}
|
||||
uses: ./.github/workflows/test_s3_file_storage.yml
|
||||
with:
|
||||
ci-image: ${{ needs.build-ci-env.outputs.ci-image || '' }}
|
||||
secrets: inherit
|
||||
|
||||
integration-tests:
|
||||
name: Run Integration Tests
|
||||
needs: [ build-ci-env ]
|
||||
if: ${{ !cancelled() }}
|
||||
uses: ./.github/workflows/integration_tests.yml
|
||||
with:
|
||||
ci-image: ${{ needs.build-ci-env.outputs.ci-image || '' }}
|
||||
secrets: inherit
|
||||
|
||||
mcp-test:
|
||||
name: MCP Tests
|
||||
uses: ./.github/workflows/test_mcp.yml
|
||||
secrets: inherit
|
||||
|
||||
docker-compose-test:
|
||||
name: Docker Compose Test
|
||||
uses: ./.github/workflows/docker_compose.yml
|
||||
secrets: inherit
|
||||
|
||||
docker-ci-test:
|
||||
name: Docker CI test
|
||||
uses: ./.github/workflows/backend_docker_build_test.yml
|
||||
secrets: inherit
|
||||
|
||||
temporal-graph-tests:
|
||||
name: Temporal Graph Test
|
||||
needs: [ build-ci-env ]
|
||||
if: ${{ !cancelled() }}
|
||||
uses: ./.github/workflows/temporal_graph_tests.yml
|
||||
with:
|
||||
ci-image: ${{ needs.build-ci-env.outputs.ci-image || '' }}
|
||||
secrets: inherit
|
||||
|
||||
search-db-tests:
|
||||
name: Search Test on Different DBs
|
||||
needs: [ build-ci-env ]
|
||||
if: ${{ !cancelled() }}
|
||||
uses: ./.github/workflows/search_db_tests.yml
|
||||
with:
|
||||
ci-image: ${{ needs.build-ci-env.outputs.ci-image || '' }}
|
||||
secrets: inherit
|
||||
|
||||
relational-db-migration-tests:
|
||||
name: Relational DB Migration Tests
|
||||
needs: [ build-ci-env ]
|
||||
if: ${{ !cancelled() }}
|
||||
uses: ./.github/workflows/relational_db_migration_tests.yml
|
||||
with:
|
||||
ci-image: ${{ needs.build-ci-env.outputs.ci-image || '' }}
|
||||
secrets: inherit
|
||||
|
||||
# NOTE: intentionally excluded from the `notify` aggregator below — this is
|
||||
# external infra (Modal + Azure secrets), informational only; it must not gate
|
||||
# merges. (`continue-on-error` is not allowed on a reusable-workflow job.)
|
||||
distributed-tests:
|
||||
name: Distributed Cognee Test
|
||||
needs: [ build-ci-env ]
|
||||
if: ${{ !cancelled() }}
|
||||
uses: ./.github/workflows/distributed_test.yml
|
||||
with:
|
||||
ci-image: ${{ needs.build-ci-env.outputs.ci-image || '' }}
|
||||
secrets: inherit
|
||||
|
||||
db-examples-tests:
|
||||
name: DB Examples Tests
|
||||
needs: [ build-ci-env ]
|
||||
if: ${{ !cancelled() }}
|
||||
uses: ./.github/workflows/db_examples_tests.yml
|
||||
with:
|
||||
ci-image: ${{ needs.build-ci-env.outputs.ci-image || '' }}
|
||||
secrets: inherit
|
||||
|
||||
notify:
|
||||
name: Test Completion Status
|
||||
needs: [
|
||||
pre-test,
|
||||
basic-tests,
|
||||
e2e-tests,
|
||||
cli-tests,
|
||||
slow-e2e-tests,
|
||||
graph-db-tests,
|
||||
vector-db-tests,
|
||||
example-tests,
|
||||
notebook-tests,
|
||||
different-os-tests-basic,
|
||||
different-os-tests-extended,
|
||||
llm-tests,
|
||||
s3-file-storage-test,
|
||||
integration-tests,
|
||||
mcp-test,
|
||||
docker-compose-test,
|
||||
docker-ci-test,
|
||||
temporal-graph-tests,
|
||||
search-db-tests,
|
||||
relational-db-migration-tests,
|
||||
db-examples-tests,
|
||||
]
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ !cancelled() }}
|
||||
steps:
|
||||
- name: Check Status
|
||||
run: |
|
||||
if [[ "${{ needs.pre-test.result }}" == "success" &&
|
||||
"${{ needs.basic-tests.result }}" == "success" &&
|
||||
"${{ needs.e2e-tests.result }}" == "success" &&
|
||||
"${{ needs.cli-tests.result }}" == "success" &&
|
||||
"${{ needs.slow-e2e-tests.result }}" == "success" &&
|
||||
"${{ needs.graph-db-tests.result }}" == "success" &&
|
||||
"${{ needs.vector-db-tests.result }}" == "success" &&
|
||||
"${{ needs.example-tests.result }}" == "success" &&
|
||||
"${{ needs.notebook-tests.result }}" == "success" &&
|
||||
"${{ needs.different-os-tests-basic.result }}" == "success" &&
|
||||
"${{ needs.different-os-tests-extended.result }}" == "success" &&
|
||||
"${{ needs.llm-tests.result }}" == "success" &&
|
||||
"${{ needs.s3-file-storage-test.result }}" == "success" &&
|
||||
"${{ needs.integration-tests.result }}" == "success" &&
|
||||
"${{ needs.mcp-test.result }}" == "success" &&
|
||||
"${{ needs.docker-compose-test.result }}" == "success" &&
|
||||
"${{ needs.docker-ci-test.result }}" == "success" &&
|
||||
"${{ needs.temporal-graph-tests.result }}" == "success" &&
|
||||
"${{ needs.search-db-tests.result }}" == "success" &&
|
||||
"${{ needs.relational-db-migration-tests.result }}" == "success" &&
|
||||
"${{ needs.db-examples-tests.result }}" == "success" ]]; then
|
||||
echo "All test suites completed successfully!"
|
||||
else
|
||||
echo "One or more test suites failed."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ── Advisory Claude Code review — pulls the private skill from cognee-ci at runtime ──
|
||||
# The rubric + Slack map live in the private cognee-ci repo; this job carries no review
|
||||
# logic. Runs only after the suite is green (needs: notify), core-team PRs only, advisory.
|
||||
claude-review:
|
||||
name: Claude Code Review
|
||||
needs: [ notify ]
|
||||
if: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository }}
|
||||
runs-on: ubuntu-latest
|
||||
continue-on-error: true
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Checkout PR
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Core-team gate
|
||||
id: gate
|
||||
env:
|
||||
AUTHOR: ${{ github.event.pull_request.user.login }}
|
||||
run: |
|
||||
author_lc="$(printf '%s' "$AUTHOR" | tr '[:upper:]' '[:lower:]')"
|
||||
if grep -vE '^[[:space:]]*#' .github/core-team.txt \
|
||||
| sed 's/^@//' | tr '[:upper:]' '[:lower:]' | grep -qxF "$author_lc"; then
|
||||
echo "run=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "run=false" >> "$GITHUB_OUTPUT"
|
||||
echo "PR author '$AUTHOR' not in core-team.txt — skipping."
|
||||
fi
|
||||
|
||||
- name: Mint private-repo token
|
||||
if: ${{ steps.gate.outputs.run == 'true' }}
|
||||
id: app-token
|
||||
uses: actions/create-github-app-token@v1
|
||||
with:
|
||||
app-id: ${{ secrets.CI_APP_ID }}
|
||||
private-key: ${{ secrets.CI_APP_PRIVATE_KEY }}
|
||||
owner: ${{ github.repository_owner }}
|
||||
repositories: cognee-ci
|
||||
|
||||
- name: Fetch private review skill + slack map
|
||||
if: ${{ steps.gate.outputs.run == 'true' }}
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
repository: ${{ github.repository_owner }}/cognee-ci
|
||||
token: ${{ steps.app-token.outputs.token }}
|
||||
path: .ci-private
|
||||
|
||||
- name: Stage skill into the user skills dir
|
||||
if: ${{ steps.gate.outputs.run == 'true' }}
|
||||
run: |
|
||||
# Stage into the USER skills dir ($HOME/.claude), NOT the repo's .claude/.
|
||||
# claude-code-action sanitizes the repo .claude for untrusted PR heads
|
||||
# (it moves the working-tree .claude to .claude-pr/ and restores a clean
|
||||
# .claude from the base branch), which wipes the staged private skill and
|
||||
# leaves /pr-review unresolved -> 0 turns, nothing posted. $HOME/.claude is
|
||||
# untouched by that sanitization and is loaded via settingSources: [user,...].
|
||||
mkdir -p "$HOME/.claude/skills"
|
||||
cp -r .ci-private/.claude/skills/pr-review "$HOME/.claude/skills/"
|
||||
|
||||
- name: Claude Code review
|
||||
if: ${{ steps.gate.outputs.run == 'true' }}
|
||||
uses: anthropics/claude-code-action@v1
|
||||
with:
|
||||
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
prompt: "/pr-review"
|
||||
claude_args: >-
|
||||
--allowed-tools "mcp__github_inline_comment__create_inline_comment,Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Read,Glob,Grep"
|
||||
--max-turns 20
|
||||
--model claude-sonnet-4-5-20250929
|
||||
|
||||
- name: DM review summary to PR author on Slack
|
||||
if: ${{ steps.gate.outputs.run == 'true' }}
|
||||
env:
|
||||
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
AUTHOR: ${{ github.event.pull_request.user.login }}
|
||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
PR_URL: ${{ github.event.pull_request.html_url }}
|
||||
PR_TITLE: ${{ github.event.pull_request.title }}
|
||||
REPO: ${{ github.repository }}
|
||||
run: python3 .ci-private/scripts/pr_review_slack_notify.py
|
||||
@@ -0,0 +1,37 @@
|
||||
name: community | contributors leaderboard
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 0 * * 1" # Runs every Monday
|
||||
workflow_dispatch: # Allows manual trigger
|
||||
|
||||
jobs:
|
||||
update-contributors:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Generate Contributor List
|
||||
run: |
|
||||
echo "## 💫 Contributors" > CONTRIBUTORS.md
|
||||
echo "" >> CONTRIBUTORS.md
|
||||
echo "Thanks to our amazing contributors! 💖" >> CONTRIBUTORS.md
|
||||
echo "" >> CONTRIBUTORS.md
|
||||
echo '<a href="https://github.com/topoteretes/cognee/graphs/contributors">' >> CONTRIBUTORS.md
|
||||
echo ' <img src="https://contrib.rocks/image?repo=topoteretes/cognee" />' >> CONTRIBUTORS.md
|
||||
echo '</a>' >> CONTRIBUTORS.md
|
||||
echo "" >> CONTRIBUTORS.md
|
||||
echo "## 🏆 Top Contributors" >> CONTRIBUTORS.md
|
||||
echo "" >> CONTRIBUTORS.md
|
||||
echo "| Rank | Contributor | Contributions |" >> CONTRIBUTORS.md
|
||||
echo "|------|------------|---------------|" >> CONTRIBUTORS.md
|
||||
git shortlog -sne | sort -rn | head -10 | awk '{print "| "NR" | ["$2"](https://github.com/"$2") | "$1" Commits |"}' >> CONTRIBUTORS.md
|
||||
|
||||
- name: Commit and Push Changes
|
||||
run: |
|
||||
git config --global user.name "github-actions[bot]"
|
||||
git config --global user.email "github-actions@users.noreply.github.com"
|
||||
git add CONTRIBUTORS.md
|
||||
git commit -m "Update contributors list"
|
||||
git push
|
||||
@@ -0,0 +1,153 @@
|
||||
name: Reusable Vector DB Tests
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
databases:
|
||||
required: false
|
||||
type: string
|
||||
default: "all"
|
||||
description: "Which vector databases to test (comma-separated list or 'all')"
|
||||
ci-image:
|
||||
required: false
|
||||
type: string
|
||||
default: ''
|
||||
secrets:
|
||||
|
||||
POSTGRES_PASSWORD:
|
||||
required: false
|
||||
|
||||
env:
|
||||
COGNEE_SKIP_CONNECTION_TEST: 'true'
|
||||
|
||||
jobs:
|
||||
run-postgres-tests:
|
||||
name: PostgreSQL Tests
|
||||
runs-on: ubuntu-22.04
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
if: ${{ inputs.databases == 'all' || contains(inputs.databases, 'postgres') }}
|
||||
services:
|
||||
postgres:
|
||||
image: ghcr.io/topoteretes/pgvector:pg17
|
||||
credentials:
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
env:
|
||||
POSTGRES_USER: cognee
|
||||
POSTGRES_PASSWORD: ${{ secrets.POSTGRES_PASSWORD }}
|
||||
POSTGRES_DB: cognee_db
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
ports:
|
||||
- 5432:5432
|
||||
steps:
|
||||
- name: Check out
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: ${{ inputs.python-version }}
|
||||
extra-dependencies: "postgres"
|
||||
|
||||
- name: Run PGVector Tests
|
||||
env:
|
||||
ENV: 'dev'
|
||||
ENABLE_BACKEND_ACCESS_CONTROL: 'false'
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
DB_HOST: ${{ inputs.ci-image != '' && 'postgres' || '127.0.0.1' }}
|
||||
run: uv run python ./cognee/tests/test_pgvector.py
|
||||
|
||||
run-pgvector-multi-user-tests:
|
||||
name: PGVector Multi-User Tests
|
||||
runs-on: ubuntu-22.04
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
if: ${{ inputs.databases == 'all' || contains(inputs.databases, 'postgres') }}
|
||||
services:
|
||||
postgres:
|
||||
image: ghcr.io/topoteretes/pgvector:pg17
|
||||
credentials:
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
env:
|
||||
POSTGRES_USER: cognee
|
||||
POSTGRES_PASSWORD: ${{ secrets.POSTGRES_PASSWORD }}
|
||||
POSTGRES_DB: cognee_db
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
ports:
|
||||
- 5432:5432
|
||||
steps:
|
||||
- name: Check out
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: ${{ inputs.python-version }}
|
||||
extra-dependencies: "postgres"
|
||||
|
||||
- name: Run PGVector Permissions Tests
|
||||
env:
|
||||
ENV: 'dev'
|
||||
ENABLE_BACKEND_ACCESS_CONTROL: 'true'
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
VECTOR_DB_HOST: ${{ inputs.ci-image != '' && 'postgres' || '127.0.0.1' }}
|
||||
VECTOR_DB_PORT: 5432
|
||||
VECTOR_DB_USERNAME: cognee
|
||||
VECTOR_DB_PASSWORD: ${{ secrets.POSTGRES_PASSWORD }}
|
||||
VECTOR_DATASET_DATABASE_HANDLER: pgvector
|
||||
run: uv run python ./cognee/tests/test_permissions.py
|
||||
|
||||
run-lancedb-tests:
|
||||
name: LanceDB Tests
|
||||
runs-on: ubuntu-22.04
|
||||
container: ${{ inputs.ci-image != '' && fromJSON(format('{{"image":"{0}","credentials":{{"username":"{1}","password":"{2}"}}}}', inputs.ci-image, github.actor, github.token)) || null }}
|
||||
steps:
|
||||
- name: Check out
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: ${{ inputs.python-version }}
|
||||
|
||||
- name: Run LanceDB Tests
|
||||
env:
|
||||
ENV: 'dev'
|
||||
# Cap cached DB adapters
|
||||
DATABASE_MAX_LRU_CACHE_SIZE: 1
|
||||
LLM_MODEL: ${{ secrets.LLM_MODEL }}
|
||||
LLM_ENDPOINT: ${{ secrets.LLM_ENDPOINT }}
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
run: uv run python ./cognee/tests/test_lancedb.py
|
||||
@@ -0,0 +1,169 @@
|
||||
name: Weighted Edges Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, dev, weighted_edges]
|
||||
paths:
|
||||
- 'cognee/modules/graph/utils/get_graph_from_model.py'
|
||||
- 'cognee/infrastructure/engine/models/Edge.py'
|
||||
- 'cognee/tests/unit/interfaces/graph/test_weighted_edges.py'
|
||||
- 'examples/demos/dynamic_multiple_weighted_edges_example.py'
|
||||
- '.github/workflows/weighted_edges_tests.yml'
|
||||
pull_request:
|
||||
branches: [ main, dev ]
|
||||
paths:
|
||||
- 'cognee/modules/graph/utils/get_graph_from_model.py'
|
||||
- 'cognee/infrastructure/engine/models/Edge.py'
|
||||
- 'cognee/tests/unit/interfaces/graph/test_weighted_edges.py'
|
||||
- 'examples/demos/dynamic_multiple_weighted_edges_example.py'
|
||||
- '.github/workflows/weighted_edges_tests.yml'
|
||||
|
||||
env:
|
||||
RUNTIME__LOG_LEVEL: ERROR
|
||||
ENV: 'dev'
|
||||
|
||||
jobs:
|
||||
test-weighted-edges-functionality:
|
||||
name: Test Weighted Edges Core Functionality
|
||||
runs-on: ubuntu-22.04
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ['3.11', '3.12']
|
||||
env:
|
||||
LLM_PROVIDER: openai
|
||||
LLM_MODEL: gpt-5-mini
|
||||
LLM_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
|
||||
- name: Run Weighted Edges Unit Tests
|
||||
run: |
|
||||
uv run pytest cognee/tests/unit/interfaces/graph/test_weighted_edges.py -v --tb=short
|
||||
|
||||
- name: Run Standard Graph Tests (Regression)
|
||||
run: |
|
||||
uv run pytest cognee/tests/unit/interfaces/graph/get_graph_from_model_unit_test.py -v --tb=short
|
||||
|
||||
test-with-different-databases:
|
||||
name: Test Weighted Edges with Different Graph Databases
|
||||
runs-on: ubuntu-22.04
|
||||
strategy:
|
||||
matrix:
|
||||
database: ['kuzu', 'neo4j']
|
||||
include:
|
||||
- database: kuzu
|
||||
graph_db_provider: "kuzu"
|
||||
- database: neo4j
|
||||
graph_db_provider: "neo4j"
|
||||
env:
|
||||
LLM_PROVIDER: openai
|
||||
LLM_MODEL: gpt-5-mini
|
||||
LLM_ENDPOINT: https://api.openai.com/v1
|
||||
LLM_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: "2024-02-01"
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: '3.11'
|
||||
|
||||
- name: Setup Neo4j with GDS
|
||||
uses: ./.github/actions/setup_neo4j
|
||||
id: neo4j
|
||||
|
||||
- name: Dependencies already installed
|
||||
run: echo "Dependencies already installed in setup"
|
||||
|
||||
- name: Run Weighted Edges Tests
|
||||
env:
|
||||
ENABLE_BACKEND_ACCESS_CONTROL: 'false'
|
||||
GRAPH_DATABASE_PROVIDER: ${{ matrix.graph_db_provider }}
|
||||
GRAPH_DATABASE_URL: ${{ matrix.graph_db_provider == 'neo4j' && steps.neo4j.outputs.neo4j-url || '' }}
|
||||
GRAPH_DATABASE_USERNAME: ${{ matrix.graph_db_provider == 'neo4j' && steps.neo4j.outputs.neo4j-username || '' }}
|
||||
GRAPH_DATABASE_PASSWORD: ${{ matrix.graph_db_provider == 'neo4j' && steps.neo4j.outputs.neo4j-password || '' }}
|
||||
run: |
|
||||
uv run pytest cognee/tests/unit/interfaces/graph/test_weighted_edges.py -v --tb=short
|
||||
|
||||
test-examples:
|
||||
name: Test Weighted Edges Examples
|
||||
runs-on: ubuntu-22.04
|
||||
env:
|
||||
LLM_PROVIDER: openai
|
||||
LLM_MODEL: gpt-5-mini
|
||||
LLM_ENDPOINT: https://api.openai.com/v1
|
||||
LLM_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
LLM_ARGS: ${{ secrets.LLM_ARGS }}
|
||||
LLM_API_VERSION: "2024-02-01"
|
||||
EMBEDDING_DIMENSIONS: 300
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: '3.11'
|
||||
|
||||
- name: Test Weighted Edges Example
|
||||
run: |
|
||||
uv run python examples/demos/dynamic_multiple_weighted_edges_example.py
|
||||
|
||||
- name: Verify Visualization File Created
|
||||
run: |
|
||||
if [ -f "examples/demos/.artifacts/dunder_mifflin_company_graph.html" ]; then
|
||||
echo "✅ Visualization file created successfully"
|
||||
ls -la examples/demos/.artifacts/dunder_mifflin_company_graph.html
|
||||
else
|
||||
echo "❌ Visualization file not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
|
||||
code-quality:
|
||||
name: Code Quality for Weighted Edges
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cognee Setup
|
||||
uses: ./.github/actions/cognee_setup
|
||||
with:
|
||||
python-version: '3.11'
|
||||
|
||||
- name: Run Linting on Weighted Edges Files
|
||||
uses: astral-sh/ruff-action@v3
|
||||
with:
|
||||
args: "check cognee/modules/graph/utils/get_graph_from_model.py cognee/tests/unit/interfaces/graph/test_weighted_edges.py examples/demos/dynamic_multiple_weighted_edges_example.py"
|
||||
|
||||
- name: Run Formatting Check on Weighted Edges Files
|
||||
uses: astral-sh/ruff-action@v3
|
||||
with:
|
||||
args: "format --check cognee/modules/graph/utils/get_graph_from_model.py cognee/tests/unit/interfaces/graph/test_weighted_edges.py examples/demos/dynamic_multiple_weighted_edges_example.py"
|
||||
@@ -0,0 +1,213 @@
|
||||
.data
|
||||
.env
|
||||
.local.env
|
||||
.prod.env
|
||||
cognee/.data/
|
||||
|
||||
code_pipeline_output*/
|
||||
|
||||
# Test output files
|
||||
test_outputs/
|
||||
|
||||
*.lance/
|
||||
.DS_Store
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
full_run.ipynb
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
.python-version
|
||||
cognee-mcp/.python-version
|
||||
MANIFEST
|
||||
|
||||
# cognee-mcp app bundle (built by `npm run build` under cognee-mcp/apps-src/).
|
||||
# Generated artifact — see cognee-mcp/README.md for the build step.
|
||||
cognee-mcp/src/app_bundles/
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
cover/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
# Cognee logs directory - keep directory, ignore contents
|
||||
logs/*
|
||||
!logs/.gitkeep
|
||||
!logs/README.md
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
.pybuilder/
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# pyenv
|
||||
# For a library or package, you might want to ignore these files since the code is
|
||||
# intended to run in multiple environments; otherwise, check them in:
|
||||
# .python-version
|
||||
|
||||
# pipenv
|
||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||
# install all needed dependencies.
|
||||
#Pipfile.lock
|
||||
|
||||
# poetry
|
||||
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||
# commonly ignored for libraries.
|
||||
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||
#poetry.lock
|
||||
|
||||
# pdm
|
||||
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||
#pdm.lock
|
||||
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
||||
# in version control.
|
||||
# https://pdm.fming.dev/#use-with-ide
|
||||
.pdm.toml
|
||||
|
||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||
__pypackages__/
|
||||
|
||||
# Celery stuff
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.env.local
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
mise.toml
|
||||
deployment/helm/values-local.yml
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# pytype static type analyzer
|
||||
.pytype/
|
||||
|
||||
# Cython debug symbols
|
||||
cython_debug/
|
||||
|
||||
# PyCharm
|
||||
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||
.idea/
|
||||
|
||||
.vscode/
|
||||
cognee/data/
|
||||
cognee/cache/
|
||||
|
||||
# Default cognee system directory, used in development
|
||||
.cognee_system/
|
||||
.data_storage/
|
||||
.cognee_cache/
|
||||
.artifacts/
|
||||
.anon_id
|
||||
|
||||
node_modules/
|
||||
|
||||
# Evals
|
||||
SWE-bench_testsample/
|
||||
|
||||
# ChromaDB Data
|
||||
.chromadb_data/
|
||||
|
||||
deployment/helm/values-local.yml
|
||||
|
||||
# Performance test results
|
||||
cognee/tests/performance/results
|
||||
@@ -0,0 +1,9 @@
|
||||
pull_request_rules:
|
||||
- name: Backport to main when backport_main label is set
|
||||
conditions:
|
||||
- label=backport_main
|
||||
- base=dev
|
||||
actions:
|
||||
backport:
|
||||
branches:
|
||||
- main
|
||||
@@ -0,0 +1,21 @@
|
||||
# See https://pre-commit.com for more information
|
||||
# See https://pre-commit.com/hooks.html for more hooks
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v3.2.0
|
||||
hooks:
|
||||
- id: trailing-whitespace
|
||||
- id: end-of-file-fixer
|
||||
- id: check-yaml
|
||||
exclude: ^deployment/helm/templates/
|
||||
- id: check-added-large-files
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
# Ruff version.
|
||||
rev: v0.15.11
|
||||
hooks:
|
||||
# Run the linter.
|
||||
- id: ruff
|
||||
types_or: [python, pyi]
|
||||
# Run the formatter.
|
||||
- id: ruff-format
|
||||
types_or: [python, pyi]
|
||||
@@ -0,0 +1,130 @@
|
||||
## Repository Guidelines
|
||||
|
||||
This document summarizes how to work with the cognee repository: how it’s organized, how to build, test, lint, and contribute. It mirrors our actual tooling and CI while providing quick commands for local development.
|
||||
|
||||
## Project Structure & Module Organization
|
||||
|
||||
- `cognee/`: Core Python library and API.
|
||||
- `api/`: FastAPI application and versioned routers (add, cognify, memify, search, delete, users, datasets, responses, visualize, settings, sync, update, checks).
|
||||
- `cli/`: CLI entry points and subcommands invoked via `cognee` / `cognee-cli`.
|
||||
- `infrastructure/`: Databases, LLM providers, embeddings, loaders, and storage adapters.
|
||||
- `modules/`: Domain logic (graph, retrieval, ontology, users, processing, observability, etc.).
|
||||
- `tasks/`: Reusable tasks (e.g., code graph, web scraping, storage). Extend with new tasks here.
|
||||
- `eval_framework/`: Evaluation utilities and adapters.
|
||||
- `shared/`: Cross-cutting helpers (logging, settings, utils).
|
||||
- `tests/`: Unit, integration, CLI, and end-to-end tests organized by feature.
|
||||
- `__main__.py`: Entrypoint to route to CLI.
|
||||
- `cognee-mcp/`: Model Context Protocol server exposing cognee as MCP tools (SSE/HTTP/stdio). Contains its own README and Dockerfile.
|
||||
- `cognee-frontend/`: Next.js UI for local development and demos.
|
||||
- `distributed/`: Utilities for distributed execution (Modal, workers, queues).
|
||||
- `examples/`: Example scripts demonstrating the public APIs and features (graph, code graph, multimodal, permissions, etc.).
|
||||
- `notebooks/`: Jupyter notebooks for demos and tutorials.
|
||||
- `alembic/`: Database migrations for relational backends.
|
||||
|
||||
Notes:
|
||||
- Co-locate feature-specific helpers under their respective package (`modules/`, `infrastructure/`, or `tasks/`).
|
||||
- Extend the system by adding new tasks, loaders, or retrievers rather than modifying core pipeline mechanisms.
|
||||
|
||||
## Build, Test, and Development Commands
|
||||
|
||||
Python (root) – requires Python >= 3.10 and < 3.14. We recommend `uv` for speed and reproducibility.
|
||||
|
||||
- Create/refresh env and install dev deps:
|
||||
```bash
|
||||
uv sync --dev --all-extras --reinstall
|
||||
```
|
||||
|
||||
- Run the CLI (examples):
|
||||
```bash
|
||||
uv run cognee-cli add "Cognee turns documents into AI memory."
|
||||
uv run cognee-cli cognify
|
||||
uv run cognee-cli search "What does cognee do?"
|
||||
uv run cognee-cli -ui # Launches UI, backend API, and MCP server together
|
||||
```
|
||||
|
||||
- Start the FastAPI server directly:
|
||||
```bash
|
||||
uv run python -m cognee.api.client
|
||||
```
|
||||
|
||||
- Run tests (CI mirrors these commands):
|
||||
```bash
|
||||
uv run pytest cognee/tests/unit/ -v
|
||||
uv run pytest cognee/tests/integration/ -v
|
||||
```
|
||||
|
||||
- Lint and format (ruff):
|
||||
```bash
|
||||
uv run ruff check .
|
||||
uv run ruff format .
|
||||
```
|
||||
|
||||
- Optional static type checks (ty):
|
||||
```bash
|
||||
uv run ty check .
|
||||
```
|
||||
|
||||
MCP Server (`cognee-mcp/`):
|
||||
|
||||
- Install and run locally:
|
||||
```bash
|
||||
cd cognee-mcp
|
||||
uv sync --dev --all-extras --reinstall
|
||||
uv run python src/server.py # stdio (default)
|
||||
uv run python src/server.py --transport sse
|
||||
uv run python src/server.py --transport http --host 127.0.0.1 --port 8000 --path /mcp
|
||||
```
|
||||
|
||||
- API Mode (connect to a running Cognee API):
|
||||
```bash
|
||||
uv run python src/server.py --transport sse --api-url http://localhost:8000 --api-token YOUR_TOKEN
|
||||
```
|
||||
|
||||
- Docker quickstart (examples): see `cognee-mcp/README.md` for full details
|
||||
```bash
|
||||
docker run -e TRANSPORT_MODE=http --env-file ./.env -p 8000:8000 --rm -it cognee/cognee-mcp:main
|
||||
```
|
||||
|
||||
Frontend (`cognee-frontend/`):
|
||||
```bash
|
||||
cd cognee-frontend
|
||||
npm install
|
||||
npm run dev # Next.js dev server
|
||||
npm run lint # ESLint
|
||||
npm run build && npm start
|
||||
```
|
||||
|
||||
## Coding Style & Naming Conventions
|
||||
|
||||
Python:
|
||||
- 4-space indentation, modules and functions in `snake_case`, classes in `PascalCase`.
|
||||
- Public APIs should be type-annotated where practical. Make sure type defined in API signature will be properly displayed in Swagger UI docs. For example this definition: content_type: Optional[str] = Form(default=None) maps to "string" as the default in Swagger docs for content_type, but it should be None/null instead.
|
||||
- Use `ruff format` before committing; `ruff check` enforces import hygiene and style (line-length 100 configured in `pyproject.toml`).
|
||||
- Prefer explicit, structured error handling. Use shared logging utilities in `cognee.shared.logging_utils`.
|
||||
|
||||
MCP server and Frontend:
|
||||
- Follow the local `README.md` and ESLint/TypeScript configuration in `cognee-frontend/`.
|
||||
|
||||
## Testing Guidelines
|
||||
|
||||
- Place Python tests under `cognee/tests/`.
|
||||
- Unit tests: `cognee/tests/unit/`
|
||||
- Integration tests: `cognee/tests/integration/`
|
||||
- CLI tests: `cognee/tests/cli_tests/`
|
||||
- Name test files `test_*.py`. Use `pytest.mark.asyncio` for async tests.
|
||||
- Avoid external state; rely on test fixtures and the CI-provided env vars when LLM/embedding providers are required. See CI workflows under `.github/workflows/` for expected environment variables.
|
||||
- When adding public APIs, provide/update targeted examples under `examples/python/`.
|
||||
|
||||
## Commit & Pull Request Guidelines
|
||||
|
||||
- Use clear, imperative subjects (≤ 72 chars) and conventional commit styling in PR titles. Our CI validates semantic PR titles (see `.github/workflows/pr_lint`). Examples:
|
||||
- `feat(graph): add temporal edge weighting`
|
||||
- `fix(api): handle missing auth cookie`
|
||||
- `docs: update installation instructions`
|
||||
- Reference related issues/discussions in the PR body and provide brief context.
|
||||
- PRs should describe scope, list local test commands run, and mention any impacts on MCP server or UI if applicable.
|
||||
- Sign commits and affirm the DCO (see `CONTRIBUTING.md`).
|
||||
|
||||
## CI Mirrors Local Commands
|
||||
|
||||
Our GitHub Actions run the same ruff checks and pytest suites shown above (`.github/workflows/basic_tests.yml` and related workflows). Use the commands in this document locally to minimize CI surprises.
|
||||
@@ -0,0 +1,605 @@
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## Project Overview
|
||||
|
||||
Cognee is an open-source AI memory platform that transforms raw data into persistent knowledge graphs for AI agents. It replaces traditional RAG (Retrieval-Augmented Generation) with an ECL (Extract, Cognify, Load) pipeline combining vector search, graph databases, and LLM-powered entity extraction.
|
||||
|
||||
**Requirements**: Python 3.10 - 3.14
|
||||
|
||||
## Development Commands
|
||||
|
||||
### Setup
|
||||
```bash
|
||||
# Create virtual environment (recommended: uv)
|
||||
uv venv && source .venv/bin/activate
|
||||
|
||||
# Install with pip, poetry, or uv
|
||||
uv pip install -e .
|
||||
|
||||
# Install with dev dependencies
|
||||
uv pip install -e ".[dev]"
|
||||
|
||||
# Install with specific extras
|
||||
uv pip install -e ".[postgres,neo4j,docs,chromadb]"
|
||||
|
||||
# Set up pre-commit hooks
|
||||
pre-commit install
|
||||
```
|
||||
|
||||
### Available Installation Extras
|
||||
- **postgres** / **postgres-binary** - PostgreSQL + PGVector support (also enables the Postgres session-cache backend, `CACHE_BACKEND=postgres`)
|
||||
- **neo4j** - Neo4j graph database support
|
||||
- **neptune** - AWS Neptune support
|
||||
- **chromadb** - ChromaDB vector database
|
||||
- **docs** - Document processing (unstructured library)
|
||||
- **scraping** - Web scraping (Tavily, BeautifulSoup, Playwright)
|
||||
- **langchain** - LangChain integration
|
||||
- **llama-index** - LlamaIndex integration
|
||||
- **anthropic** - Anthropic Claude models
|
||||
- **gemini** - Google Gemini models
|
||||
- **ollama** - Ollama local models
|
||||
- **mistral** - Mistral AI models
|
||||
- **groq** - Groq API support
|
||||
- **llama-cpp** - Llama.cpp local inference
|
||||
- **huggingface** - HuggingFace transformers
|
||||
- **aws** - S3 storage backend
|
||||
- **redis** - Redis caching
|
||||
- **graphiti** - Graphiti-core integration
|
||||
- **baml** - BAML structured output
|
||||
- **dlt** - Data load tool (dlt) integration
|
||||
- **docling** - Docling document processing
|
||||
- **codegraph** - Code graph extraction
|
||||
- **evals** - Evaluation tools
|
||||
- **deepeval** - DeepEval testing framework
|
||||
- **posthog** - PostHog analytics
|
||||
- **tracing** - OpenTelemetry tracing
|
||||
- **distributed** - Modal distributed execution
|
||||
- **dev** - All development tools (pytest, ty, ruff, etc.)
|
||||
- **debug** - Debugpy for debugging
|
||||
|
||||
### Testing
|
||||
```bash
|
||||
# Run all tests
|
||||
pytest
|
||||
|
||||
# Run with coverage
|
||||
pytest --cov=cognee --cov-report=html
|
||||
|
||||
# Run specific test file
|
||||
pytest cognee/tests/test_custom_model.py
|
||||
|
||||
# Run specific test function
|
||||
pytest cognee/tests/test_custom_model.py::test_function_name
|
||||
|
||||
# Run async tests
|
||||
pytest -v cognee/tests/integration/
|
||||
|
||||
# Run unit tests only
|
||||
pytest cognee/tests/unit/
|
||||
|
||||
# Run integration tests only
|
||||
pytest cognee/tests/integration/
|
||||
```
|
||||
|
||||
### Code Quality
|
||||
```bash
|
||||
# Run ruff linter
|
||||
ruff check .
|
||||
|
||||
# Run ruff formatter
|
||||
ruff format .
|
||||
|
||||
# Run both linting and formatting (pre-commit)
|
||||
pre-commit run --all-files
|
||||
|
||||
# Type checking with ty
|
||||
ty check .
|
||||
```
|
||||
|
||||
### Running Cognee
|
||||
```bash
|
||||
# Using Python SDK
|
||||
uv run python examples/demos/simple_cognee_example.py
|
||||
|
||||
# Using CLI
|
||||
cognee-cli add "Your text here"
|
||||
cognee-cli cognify
|
||||
cognee-cli search "Your query"
|
||||
cognee-cli delete --all
|
||||
|
||||
# Launch full stack with UI
|
||||
cognee-cli -ui
|
||||
```
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
### Core Workflow: add → cognify → search/memify
|
||||
|
||||
1. **add()** - Ingest data (files, URLs, text) into datasets
|
||||
2. **cognify()** - Extract entities/relationships and build knowledge graph
|
||||
3. **search()** - Query knowledge using various retrieval strategies
|
||||
4. **memify()** - Enrich graph with additional context and rules
|
||||
|
||||
### Key Architectural Patterns
|
||||
|
||||
#### 1. Pipeline-Based Processing
|
||||
All data flows through task-based pipelines (`cognee/modules/pipelines/`). Tasks are composable units that can run sequentially or in parallel. Example pipeline tasks: `classify_documents`, `extract_graph_from_data`, `add_data_points`.
|
||||
|
||||
#### 2. Interface-Based Database Adapters
|
||||
Multiple backends are supported through adapter interfaces:
|
||||
- **Graph**: Ladybug (default), Neo4j, Neptune, Postgres via `GraphDBInterface`
|
||||
- **Vector**: LanceDB (default), ChromaDB, PGVector via `VectorDBInterface`
|
||||
- **Relational**: SQLite (default), PostgreSQL
|
||||
|
||||
Key files:
|
||||
- `cognee/infrastructure/databases/graph/graph_db_interface.py`
|
||||
- `cognee/infrastructure/databases/vector/vector_db_interface.py`
|
||||
|
||||
#### 3. Multi-Tenant Access Control
|
||||
User → Dataset → Data hierarchy with permission-based filtering. Enable with `ENABLE_BACKEND_ACCESS_CONTROL=True`. Each user+dataset combination can have isolated graph/vector databases (when using supported backends: Ladybug, LanceDB, SQLite, Postgres).
|
||||
|
||||
### Layer Structure
|
||||
|
||||
```
|
||||
API Layer (cognee/api/v1/)
|
||||
↓
|
||||
Main Functions (add, cognify, search, memify)
|
||||
↓
|
||||
Pipeline Orchestrator (cognee/modules/pipelines/)
|
||||
↓
|
||||
Task Execution Layer (cognee/tasks/)
|
||||
↓
|
||||
Domain Modules (graph, retrieval, ingestion, etc.)
|
||||
↓
|
||||
Infrastructure Adapters (LLM, databases)
|
||||
↓
|
||||
External Services (OpenAI, Ladybug, LanceDB, etc.)
|
||||
```
|
||||
|
||||
### Critical Data Flow Paths
|
||||
|
||||
#### ADD: Data Ingestion
|
||||
`add()` → `resolve_data_directories` → `ingest_data` → `save_data_item_to_storage` → Create Dataset + Data records in relational DB
|
||||
|
||||
Key files: `cognee/api/v1/add/add.py`, `cognee/tasks/ingestion/ingest_data.py`
|
||||
|
||||
#### COGNIFY: Knowledge Graph Construction
|
||||
`cognify()` → `classify_documents` → `extract_chunks_from_documents` → `extract_graph_from_data` (LLM extracts entities/relationships using Instructor) → `summarize_text` → `add_data_points` (store in graph + vector DBs)
|
||||
|
||||
Key files:
|
||||
- `cognee/api/v1/cognify/cognify.py`
|
||||
- `cognee/tasks/graph/extract_graph_from_data.py`
|
||||
- `cognee/tasks/storage/add_data_points.py`
|
||||
|
||||
#### SEARCH: Retrieval
|
||||
`search(query_text, query_type)` → route to retriever type → filter by permissions → return results
|
||||
|
||||
Available search types (from `cognee/modules/search/types/SearchType.py`):
|
||||
- **GRAPH_COMPLETION** (default) - Graph traversal + LLM completion
|
||||
- **GRAPH_SUMMARY_COMPLETION** - Uses pre-computed summaries with graph context
|
||||
- **GRAPH_COMPLETION_COT** - Chain-of-thought reasoning over graph
|
||||
- **GRAPH_COMPLETION_CONTEXT_EXTENSION** - Extended context graph retrieval
|
||||
- **TRIPLET_COMPLETION** - Triplet-based (subject-predicate-object) search
|
||||
- **RAG_COMPLETION** - Traditional RAG with chunks
|
||||
- **CHUNKS** - Vector similarity search over chunks
|
||||
- **CHUNKS_LEXICAL** - Lexical (keyword) search over chunks
|
||||
- **SUMMARIES** - Search pre-computed document summaries
|
||||
- **CYPHER** - Direct Cypher query execution (requires `ALLOW_CYPHER_QUERY=True`)
|
||||
- **NATURAL_LANGUAGE** - Natural language to structured query
|
||||
- **TEMPORAL** - Time-aware graph search
|
||||
- **FEELING_LUCKY** - Automatic search type selection
|
||||
- **CODING_RULES** - Code-specific search rules
|
||||
|
||||
Key files:
|
||||
- `cognee/api/v1/search/search.py`
|
||||
- `cognee/modules/retrieval/context_providers/TripletSearchContextProvider.py`
|
||||
- `cognee/modules/search/types/SearchType.py`
|
||||
|
||||
### Core Data Models
|
||||
|
||||
#### Engine Models (`cognee/infrastructure/engine/models/`)
|
||||
- **DataPoint** - Base class for all graph nodes (versioned, with metadata)
|
||||
- **Edge** - Graph relationships (source, target, relationship type)
|
||||
- **Triplet** - (Subject, Predicate, Object) representation
|
||||
|
||||
#### Graph Models (`cognee/shared/data_models.py`)
|
||||
- **KnowledgeGraph** - Container for nodes and edges
|
||||
- **Node** - Entity (id, name, type, description)
|
||||
- **Edge** - Relationship (source_node_id, target_node_id, relationship_name)
|
||||
|
||||
### Key Infrastructure Components
|
||||
|
||||
#### LLM Gateway (`cognee/infrastructure/llm/LLMGateway.py`)
|
||||
Unified interface for multiple LLM providers: OpenAI, Anthropic, Gemini, Ollama, Mistral, Bedrock. Uses Instructor for structured output extraction.
|
||||
|
||||
#### Embedding Engines
|
||||
Factory pattern for embeddings: `cognee/infrastructure/databases/vector/embeddings/get_embedding_engine.py`
|
||||
|
||||
#### Document Loaders
|
||||
Support for PDF, DOCX, CSV, images, audio, code files in `cognee/infrastructure/files/`
|
||||
|
||||
## Important Configuration
|
||||
|
||||
### Environment Setup
|
||||
Copy `.env.template` to `.env` and configure:
|
||||
|
||||
```bash
|
||||
# Minimal setup (defaults to OpenAI + local file-based databases)
|
||||
LLM_API_KEY="your_openai_api_key"
|
||||
LLM_MODEL="openai/gpt-5-mini" # Default model
|
||||
```
|
||||
|
||||
**Important**: If you configure only LLM or only embeddings, the other defaults to OpenAI. Ensure you have a working OpenAI API key, or configure both to avoid unexpected defaults.
|
||||
|
||||
Default databases (no extra setup needed):
|
||||
- **Relational**: SQLite (metadata and state storage)
|
||||
- **Vector**: LanceDB (embeddings for semantic search)
|
||||
- **Graph**: Ladybug (knowledge graph and relationships)
|
||||
|
||||
All stored in `.venv` by default. Override with `DATA_ROOT_DIRECTORY` and `SYSTEM_ROOT_DIRECTORY`.
|
||||
|
||||
### Switching Databases
|
||||
|
||||
#### Relational Databases
|
||||
```bash
|
||||
# PostgreSQL (requires postgres extra: pip install cognee[postgres])
|
||||
DB_PROVIDER=postgres
|
||||
DB_HOST=localhost
|
||||
DB_PORT=5432
|
||||
DB_USERNAME=cognee
|
||||
DB_PASSWORD=cognee
|
||||
DB_NAME=cognee_db
|
||||
```
|
||||
|
||||
#### Vector Databases
|
||||
Supported: lancedb (default), pgvector, chromadb, qdrant, weaviate, milvus
|
||||
```bash
|
||||
# ChromaDB (requires chromadb extra)
|
||||
VECTOR_DB_PROVIDER=chromadb
|
||||
|
||||
# PGVector (requires postgres extra)
|
||||
VECTOR_DB_PROVIDER=pgvector
|
||||
VECTOR_DB_URL=postgresql://cognee:cognee@localhost:5432/cognee_db
|
||||
```
|
||||
|
||||
#### Graph Databases
|
||||
Supported: ladybug (default), neo4j, neptune, ladybug-remote, postgres
|
||||
```bash
|
||||
# Neo4j (requires neo4j extra: pip install cognee[neo4j])
|
||||
GRAPH_DATABASE_PROVIDER=neo4j
|
||||
GRAPH_DATABASE_URL=bolt://localhost:7687
|
||||
GRAPH_DATABASE_NAME=neo4j
|
||||
GRAPH_DATABASE_USERNAME=neo4j
|
||||
GRAPH_DATABASE_PASSWORD=yourpassword
|
||||
|
||||
# Remote Ladybug
|
||||
GRAPH_DATABASE_PROVIDER=ladybug-remote
|
||||
GRAPH_DATABASE_URL=http://localhost:8000
|
||||
GRAPH_DATABASE_USERNAME=your_username
|
||||
GRAPH_DATABASE_PASSWORD=your_password
|
||||
|
||||
# Postgres (requires postgres extra: pip install cognee[postgres])
|
||||
# Does not support raw Cypher queries, natural language search, or Graphiti.
|
||||
GRAPH_DATABASE_PROVIDER=postgres
|
||||
GRAPH_DATABASE_URL=postgresql+asyncpg://cognee:cognee@localhost:5432/cognee_db
|
||||
```
|
||||
|
||||
#### Session Cache
|
||||
```bash
|
||||
# Session/conversation cache backend: sqlite (default), postgres, redis, fs, tapes
|
||||
CACHE_BACKEND=sqlite
|
||||
# Optional explicit SQLAlchemy URL for sqlite/postgres cache backends (overrides defaults)
|
||||
CACHE_DB_URL=postgresql+asyncpg://cognee:cognee@localhost:5432/cognee_db
|
||||
```
|
||||
|
||||
### LLM Provider Configuration
|
||||
|
||||
Supported providers: OpenAI (default), Azure OpenAI, Google Gemini, Anthropic, AWS Bedrock, Ollama, LM Studio, Custom (OpenAI-compatible APIs)
|
||||
|
||||
#### OpenAI (Recommended - Minimal Setup)
|
||||
```bash
|
||||
LLM_API_KEY="your_openai_api_key"
|
||||
LLM_MODEL="openai/gpt-5-mini" # default; or gpt-5, gpt-4o, gpt-4o-mini, etc.
|
||||
LLM_PROVIDER="openai"
|
||||
```
|
||||
|
||||
#### Azure OpenAI
|
||||
```bash
|
||||
LLM_PROVIDER="azure"
|
||||
LLM_MODEL="azure/gpt-4o-mini"
|
||||
LLM_ENDPOINT="https://YOUR-RESOURCE.openai.azure.com/openai/deployments/gpt-4o-mini"
|
||||
LLM_API_KEY="your_azure_api_key"
|
||||
LLM_API_VERSION="2024-12-01-preview"
|
||||
```
|
||||
|
||||
#### Google Gemini (requires gemini extra)
|
||||
```bash
|
||||
LLM_PROVIDER="gemini"
|
||||
LLM_MODEL="gemini/gemini-2.0-flash-exp"
|
||||
LLM_API_KEY="your_gemini_api_key"
|
||||
```
|
||||
|
||||
#### Anthropic Claude (requires anthropic extra)
|
||||
```bash
|
||||
LLM_PROVIDER="anthropic"
|
||||
LLM_MODEL="claude-3-5-sonnet-20241022"
|
||||
LLM_API_KEY="your_anthropic_api_key"
|
||||
```
|
||||
|
||||
#### Ollama (Local - requires ollama extra)
|
||||
```bash
|
||||
LLM_PROVIDER="ollama"
|
||||
LLM_MODEL="llama3.1:8b"
|
||||
LLM_ENDPOINT="http://localhost:11434/v1"
|
||||
LLM_API_KEY="ollama"
|
||||
EMBEDDING_PROVIDER="ollama"
|
||||
EMBEDDING_MODEL="nomic-embed-text:latest"
|
||||
EMBEDDING_ENDPOINT="http://localhost:11434/api/embed"
|
||||
HUGGINGFACE_TOKENIZER="nomic-ai/nomic-embed-text-v1.5"
|
||||
```
|
||||
|
||||
#### Custom / OpenRouter / vLLM
|
||||
```bash
|
||||
LLM_PROVIDER="custom"
|
||||
LLM_MODEL="openrouter/google/gemini-2.0-flash-lite-preview-02-05:free"
|
||||
LLM_ENDPOINT="https://openrouter.ai/api/v1"
|
||||
LLM_API_KEY="your_api_key"
|
||||
```
|
||||
|
||||
#### AWS Bedrock (requires aws extra)
|
||||
```bash
|
||||
LLM_PROVIDER="bedrock"
|
||||
LLM_MODEL="anthropic.claude-3-sonnet-20240229-v1:0"
|
||||
AWS_REGION="us-east-1"
|
||||
AWS_ACCESS_KEY_ID="your_access_key"
|
||||
AWS_SECRET_ACCESS_KEY="your_secret_key"
|
||||
# Optional for temporary credentials:
|
||||
# AWS_SESSION_TOKEN="your_session_token"
|
||||
```
|
||||
|
||||
#### LLM Rate Limiting
|
||||
```bash
|
||||
LLM_RATE_LIMIT_ENABLED=true
|
||||
LLM_RATE_LIMIT_REQUESTS=60 # Requests per interval
|
||||
LLM_RATE_LIMIT_INTERVAL=60 # Interval in seconds
|
||||
```
|
||||
|
||||
#### Instructor Mode (Structured Output)
|
||||
```bash
|
||||
# LLM_INSTRUCTOR_MODE controls how structured data is extracted
|
||||
# Each LLM has its own default (e.g., gpt-4o models use "json_schema_mode")
|
||||
# Override if needed:
|
||||
LLM_INSTRUCTOR_MODE="json_schema_mode" # or "tool_call", "md_json", etc.
|
||||
```
|
||||
|
||||
### Structured Output Framework
|
||||
```bash
|
||||
# Use Instructor (default, via litellm)
|
||||
STRUCTURED_OUTPUT_FRAMEWORK="instructor"
|
||||
|
||||
# Or use BAML (requires baml extra: pip install cognee[baml])
|
||||
STRUCTURED_OUTPUT_FRAMEWORK="baml"
|
||||
BAML_LLM_PROVIDER=openai
|
||||
BAML_LLM_MODEL="gpt-4o-mini"
|
||||
BAML_LLM_API_KEY="your_api_key"
|
||||
```
|
||||
|
||||
### Storage Backend
|
||||
```bash
|
||||
# Local filesystem (default)
|
||||
STORAGE_BACKEND="local"
|
||||
|
||||
# S3 (requires aws extra: pip install cognee[aws])
|
||||
STORAGE_BACKEND="s3"
|
||||
STORAGE_BUCKET_NAME="your-bucket-name"
|
||||
AWS_REGION="us-east-1"
|
||||
AWS_ACCESS_KEY_ID="your_access_key"
|
||||
AWS_SECRET_ACCESS_KEY="your_secret_key"
|
||||
DATA_ROOT_DIRECTORY="s3://your-bucket/cognee/data"
|
||||
SYSTEM_ROOT_DIRECTORY="s3://your-bucket/cognee/system"
|
||||
```
|
||||
|
||||
## Extension Points
|
||||
|
||||
### Adding New Functionality
|
||||
|
||||
1. **New Task Type**: Create task function in `cognee/tasks/`, return Task object, register in pipeline
|
||||
2. **New Database Backend**: Implement `GraphDBInterface` or `VectorDBInterface` in `cognee/infrastructure/databases/`
|
||||
3. **New LLM Provider**: Add configuration in LLM config (uses litellm)
|
||||
4. **New Document Processor**: Extend loaders in `cognee/modules/data/processing/`
|
||||
5. **New Search Type**: Add to `SearchType` enum and implement retriever in `cognee/modules/retrieval/`
|
||||
6. **Custom Graph Models**: Define Pydantic models extending `DataPoint` in your code
|
||||
|
||||
### Working with Ontologies
|
||||
Cognee supports ontology-based entity extraction to ground knowledge graphs in standardized semantic frameworks (e.g., OWL ontologies).
|
||||
|
||||
Configuration:
|
||||
```bash
|
||||
ONTOLOGY_RESOLVER=rdflib # Default: uses rdflib and OWL files
|
||||
MATCHING_STRATEGY=fuzzy # Default: fuzzy matching with 80% similarity
|
||||
ONTOLOGY_FILE_PATH=/path/to/your/ontology.owl # Full path to ontology file
|
||||
```
|
||||
|
||||
Implementation: `cognee/modules/ontology/`
|
||||
|
||||
## Branching Strategy
|
||||
|
||||
**IMPORTANT**: Always branch from `dev`, not `main`. The `dev` branch is the active development branch.
|
||||
|
||||
```bash
|
||||
git checkout dev
|
||||
git pull origin dev
|
||||
git checkout -b feature/your-feature-name
|
||||
```
|
||||
|
||||
**Core-team PRs must reference a Linear issue.** Put the issue key (e.g. `COG-123`)
|
||||
in the PR title or the branch name so Linear links the PR to its ticket. This is
|
||||
enforced by the `Require Linear issue` workflow (`linear-issue-check`), a required
|
||||
status check. Fork / external-contributor PRs are exempt (the check skips them), so
|
||||
this rule applies only to internal PRs.
|
||||
|
||||
## Code Style
|
||||
|
||||
- **Formatter**: Ruff (configured in `pyproject.toml`)
|
||||
- **Line length**: 100 characters
|
||||
- **String quotes**: Use double quotes `"` not single quotes `'` (enforced by ruff-format)
|
||||
- **Pre-commit hooks**: Run ruff linting and formatting automatically
|
||||
- **Type hints**: Encouraged (ty checks enabled)
|
||||
- **Important**: Always run `pre-commit run --all-files` before committing to catch formatting issues
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
Tests are organized in `cognee/tests/`:
|
||||
- `unit/` - Unit tests for individual modules
|
||||
- `integration/` - Full pipeline integration tests
|
||||
- `cli_tests/` - CLI command tests
|
||||
- `tasks/` - Task-specific tests
|
||||
|
||||
When adding features, add corresponding tests. Integration tests should cover the full add → cognify → search flow.
|
||||
|
||||
## API Structure
|
||||
|
||||
FastAPI application with versioned routes under `cognee/api/v1/`:
|
||||
- `/add` - Data ingestion
|
||||
- `/cognify` - Knowledge graph processing
|
||||
- `/search` - Query interface
|
||||
- `/memify` - Graph enrichment
|
||||
- `/datasets` - Dataset management
|
||||
- `/users` - Authentication (when `REQUIRE_AUTHENTICATION` is effectively true; see auth posture below)
|
||||
- `/visualize` - Graph visualization server
|
||||
|
||||
## Python SDK Entry Points
|
||||
|
||||
Main functions exported from `cognee/__init__.py`:
|
||||
- `add(data, dataset_name)` - Ingest data
|
||||
- `cognify(datasets)` - Build knowledge graph
|
||||
- `search(query_text, query_type)` - Query knowledge
|
||||
- `memify(extraction_tasks, enrichment_tasks)` - Enrich graph
|
||||
- `delete(data_id)` - Remove data
|
||||
- `config()` - Configuration management
|
||||
- `datasets()` - Dataset operations
|
||||
|
||||
All functions are async - use `await` or `asyncio.run()`.
|
||||
|
||||
## Security Considerations
|
||||
|
||||
Several security environment variables in `.env`:
|
||||
- `ACCEPT_LOCAL_FILE_PATH` - Allow local file paths (default: True)
|
||||
- `ALLOW_HTTP_REQUESTS` - Allow HTTP requests from Cognee (default: True)
|
||||
- `ALLOW_CYPHER_QUERY` - Allow raw Cypher queries (default: True)
|
||||
- `ENABLE_BACKEND_ACCESS_CONTROL` - Multi-tenant isolation (default: True). When `true`, API auth is required and per-user/dataset DB isolation is enabled. When `false`, single-user mode: shared DBs and auth off unless overridden.
|
||||
- `REQUIRE_AUTHENTICATION` - Explicit auth override. Unset (default): follows `ENABLE_BACKEND_ACCESS_CONTROL`. `false` is ignored when `ENABLE_BACKEND_ACCESS_CONTROL=true`. For a single-user deployment with auth off, set `ENABLE_BACKEND_ACCESS_CONTROL=false` (and optionally `REQUIRE_AUTHENTICATION=false`).
|
||||
|
||||
For production deployments, review and tighten these settings.
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Creating a Custom Pipeline Task
|
||||
```python
|
||||
from cognee.modules.pipelines.tasks.Task import Task
|
||||
|
||||
async def my_custom_task(data):
|
||||
# Your logic here
|
||||
processed_data = process(data)
|
||||
return processed_data
|
||||
|
||||
# Use in pipeline
|
||||
task = Task(my_custom_task)
|
||||
```
|
||||
|
||||
### Accessing Databases Directly
|
||||
```python
|
||||
from cognee.infrastructure.databases.graph import get_graph_engine
|
||||
from cognee.infrastructure.databases.vector import get_vector_engine_async
|
||||
|
||||
graph_engine = await get_graph_engine()
|
||||
vector_engine = await get_vector_engine_async()
|
||||
```
|
||||
|
||||
### Using LLM Gateway
|
||||
```python
|
||||
from cognee.infrastructure.llm.get_llm_client import get_llm_client
|
||||
|
||||
llm_client = get_llm_client()
|
||||
response = await llm_client.acreate_structured_output(
|
||||
text_input="Your prompt",
|
||||
system_prompt="System instructions",
|
||||
response_model=YourPydanticModel
|
||||
)
|
||||
```
|
||||
|
||||
## Key Concepts
|
||||
|
||||
### Datasets
|
||||
Datasets are project-level containers that support organization, permissions, and isolated processing workflows. Each user can have multiple datasets with different access permissions.
|
||||
|
||||
```python
|
||||
# Create/use a dataset
|
||||
await cognee.add(data, dataset_name="my_project")
|
||||
await cognee.cognify(datasets=["my_project"])
|
||||
```
|
||||
|
||||
### DataPoints
|
||||
Atomic knowledge units that form the foundation of graph structures. All graph nodes extend the `DataPoint` base class with versioning and metadata support.
|
||||
|
||||
### Permissions System
|
||||
Multi-tenant architecture with users, roles, and Access Control Lists (ACLs):
|
||||
- Read, write, delete, and share permissions per dataset
|
||||
- Enable with `ENABLE_BACKEND_ACCESS_CONTROL=True`
|
||||
- Supports isolated databases per user+dataset (Ladybug, LanceDB, SQLite, Postgres)
|
||||
|
||||
### Graph Visualization
|
||||
Launch visualization server:
|
||||
```bash
|
||||
# Via CLI
|
||||
cognee-cli -ui # Launches full stack with UI at http://localhost:3000
|
||||
|
||||
# Via Python
|
||||
from cognee.api.v1.visualize import start_visualization_server
|
||||
await start_visualization_server(port=8080)
|
||||
```
|
||||
|
||||
## Debugging & Troubleshooting
|
||||
|
||||
### Debug Configuration
|
||||
- Set `LITELLM_LOG="DEBUG"` for verbose LLM logs (default: "ERROR")
|
||||
- Enable debug mode: `ENV="development"` or `ENV="debug"`
|
||||
- Disable telemetry: `TELEMETRY_DISABLED=1`
|
||||
- Check logs in structured format (uses structlog)
|
||||
- Use `debugpy` optional dependency for debugging: `pip install cognee[debug]`
|
||||
|
||||
### Common Issues
|
||||
|
||||
**Ollama + OpenAI Embeddings NoDataError**
|
||||
- Issue: Mixing Ollama with OpenAI embeddings can cause errors
|
||||
- Solution: Configure both LLM and embeddings to use the same provider, or ensure `HUGGINGFACE_TOKENIZER` is set when using Ollama
|
||||
|
||||
**LM Studio Structured Output**
|
||||
- Issue: LM Studio requires explicit instructor mode
|
||||
- Solution: Set `LLM_INSTRUCTOR_MODE="json_schema_mode"` (or appropriate mode)
|
||||
|
||||
**Default Provider Fallback**
|
||||
- Issue: Configuring only LLM or only embeddings defaults the other to OpenAI
|
||||
- Solution: Always configure both LLM and embedding providers, or ensure valid OpenAI API key
|
||||
|
||||
**Permission Denied on Search**
|
||||
- Behavior: Returns empty list rather than error (prevents information leakage)
|
||||
- Solution: Check dataset permissions and user access rights
|
||||
|
||||
**Database Connection Issues**
|
||||
- Check: Verify database URLs, credentials, and that services are running
|
||||
- Docker users: Use `DB_HOST=host.docker.internal` for local databases
|
||||
|
||||
**Rate Limiting Errors**
|
||||
- Enable client-side rate limiting: `LLM_RATE_LIMIT_ENABLED=true`
|
||||
- Adjust limits: `LLM_RATE_LIMIT_REQUESTS` and `LLM_RATE_LIMIT_INTERVAL`
|
||||
|
||||
## Resources
|
||||
|
||||
- [Documentation](https://docs.cognee.ai/)
|
||||
- [Discord Community](https://discord.gg/NQPKmU5CCg)
|
||||
- [GitHub Issues](https://github.com/topoteretes/cognee/issues)
|
||||
- [Example Notebooks](examples/python/)
|
||||
- [Research Paper](https://arxiv.org/abs/2505.24478) - Optimizing knowledge graphs for LLM reasoning
|
||||
@@ -0,0 +1,128 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
We as members, contributors, and leaders pledge to make participation in our
|
||||
community a harassment-free experience for everyone, regardless of age, body
|
||||
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
||||
identity and expression, level of experience, education, socio-economic status,
|
||||
nationality, personal appearance, race, religion, or sexual identity
|
||||
and orientation.
|
||||
|
||||
We pledge to act and interact in ways that contribute to an open, welcoming,
|
||||
diverse, inclusive, and healthy community.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to a positive environment for our
|
||||
community include:
|
||||
|
||||
- Demonstrating empathy and kindness toward other people
|
||||
- Being respectful of differing opinions, viewpoints, and experiences
|
||||
- Giving and gracefully accepting constructive feedback
|
||||
- Accepting responsibility and apologizing to those affected by our mistakes,
|
||||
and learning from the experience
|
||||
- Focusing on what is best not just for us as individuals, but for the
|
||||
overall community
|
||||
|
||||
Examples of unacceptable behavior include:
|
||||
|
||||
- The use of sexualized language or imagery, and sexual attention or
|
||||
advances of any kind
|
||||
- Trolling, insulting or derogatory comments, and personal or political attacks
|
||||
- Public or private harassment
|
||||
- Publishing others' private information, such as a physical or email
|
||||
address, without their explicit permission
|
||||
- Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Enforcement Responsibilities
|
||||
|
||||
Community leaders are responsible for clarifying and enforcing our standards of
|
||||
acceptable behavior and will take appropriate and fair corrective action in
|
||||
response to any behavior that they deem inappropriate, threatening, offensive,
|
||||
or harmful.
|
||||
|
||||
Community leaders have the right and responsibility to remove, edit, or reject
|
||||
comments, commits, code, wiki edits, issues, and other contributions that are
|
||||
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
||||
decisions when appropriate.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies within all community spaces, and also applies when
|
||||
an individual is officially representing the community in public spaces.
|
||||
Examples of representing our community include using an official e-mail address,
|
||||
posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported to the community leaders responsible for enforcement by emailing <NAME> at <EMAIL>.
|
||||
All complaints will be reviewed and investigated promptly and fairly.
|
||||
|
||||
All community leaders are obligated to respect the privacy and security of the
|
||||
reporter of any incident.
|
||||
|
||||
## Enforcement Guidelines
|
||||
|
||||
Community leaders will follow these Community Impact Guidelines in determining
|
||||
the consequences for any action they deem in violation of this Code of Conduct:
|
||||
|
||||
### 1. Correction
|
||||
|
||||
**Community Impact**: Use of inappropriate language or other behavior deemed
|
||||
unprofessional or unwelcome in the community.
|
||||
|
||||
**Consequence**: A private, written warning from community leaders, providing
|
||||
clarity around the nature of the violation and an explanation of why the
|
||||
behavior was inappropriate. A public apology may be requested.
|
||||
|
||||
### 2. Warning
|
||||
|
||||
**Community Impact**: A violation through a single incident or series
|
||||
of actions.
|
||||
|
||||
**Consequence**: A warning with consequences for continued behavior. No
|
||||
interaction with the people involved, including unsolicited interaction with
|
||||
those enforcing the Code of Conduct, for a specified period of time. This
|
||||
includes avoiding interactions in community spaces as well as external channels
|
||||
like social media. Violating these terms may lead to a temporary or
|
||||
permanent ban.
|
||||
|
||||
### 3. Temporary Ban
|
||||
|
||||
**Community Impact**: A serious violation of community standards, including
|
||||
sustained inappropriate behavior.
|
||||
|
||||
**Consequence**: A temporary ban from any sort of interaction or public
|
||||
communication with the community for a specified period of time. No public or
|
||||
private interaction with the people involved, including unsolicited interaction
|
||||
with those enforcing the Code of Conduct, is allowed during this period.
|
||||
Violating these terms may lead to a permanent ban.
|
||||
|
||||
### 4. Permanent Ban
|
||||
|
||||
**Community Impact**: Demonstrating a pattern of violation of community
|
||||
standards, including sustained inappropriate behavior, harassment of an
|
||||
individual, or aggression toward or disparagement of classes of individuals.
|
||||
|
||||
**Consequence**: A permanent ban from any sort of public interaction within
|
||||
the community.
|
||||
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||
version 2.0, available at
|
||||
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
|
||||
|
||||
Community Impact Guidelines were inspired by [Mozilla's code of conduct
|
||||
enforcement ladder](https://github.com/mozilla/diversity).
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
|
||||
For answers to common questions about this code of conduct, see the FAQ at
|
||||
https://www.contributor-covenant.org/faq. Translations are available at
|
||||
https://www.contributor-covenant.org/translations.
|
||||
@@ -0,0 +1,163 @@
|
||||
> [!IMPORTANT]
|
||||
> **Note for contributors:** When branching out, create a new branch from the `dev` branch.
|
||||
|
||||
# 🎉 Welcome to **cognee**!
|
||||
|
||||
We're excited that you're interested in contributing to our project!
|
||||
We want to ensure that every user and contributor feels welcome, included and supported to participate in cognee community.
|
||||
This guide will help you get started and ensure your contributions can be efficiently integrated into the project.
|
||||
|
||||
## 🌟 Quick Links
|
||||
|
||||
- [Code of Conduct](CODE_OF_CONDUCT.md)
|
||||
- [Discord Community](https://discord.gg/bcy8xFAtfd)
|
||||
- [Issue Tracker](https://github.com/topoteretes/cognee/issues)
|
||||
- [Cognee Docs](https://docs.cognee.ai)
|
||||
|
||||
## 1. 🚀 Ways to Contribute
|
||||
|
||||
You can contribute to **cognee** in many ways:
|
||||
|
||||
- 📝 Submitting bug reports or feature requests
|
||||
- 💡 Improving documentation
|
||||
- 🔍 Reviewing pull requests
|
||||
- 🛠️ Contributing code or tests
|
||||
- 🌐 Helping other users
|
||||
|
||||
## 📫 Get in Touch
|
||||
|
||||
There are several ways to connect with the **cognee** team and community:
|
||||
|
||||
### GitHub Collaboration
|
||||
- [Open an issue](https://github.com/topoteretes/cognee/issues) for bug reports, feature requests, or discussions
|
||||
- Submit pull requests to contribute code or documentation
|
||||
- Join ongoing discussions in existing issues and PRs
|
||||
|
||||
### Community Channels
|
||||
- Join our [Discord community](https://discord.gg/bcy8xFAtfd) for real-time discussions
|
||||
- Participate in community events and discussions
|
||||
- Get help from other community members
|
||||
|
||||
### Direct Contact
|
||||
- Email: vasilije@cognee.ai
|
||||
- For business inquiries or sensitive matters, please reach out via email
|
||||
- For general questions, prefer public channels like GitHub issues or Discord
|
||||
|
||||
We aim to respond to all communications within 2 business days. For faster responses, consider using our Discord channel where the whole community can help!
|
||||
|
||||
## Issue Labels
|
||||
|
||||
To help you find the most appropriate issues to work on, we use the following labels:
|
||||
|
||||
- `good first issue` - Perfect for newcomers to the project
|
||||
- `bug` - Something isn't working as expected
|
||||
- `documentation` - Improvements or additions to documentation
|
||||
- `enhancement` - New features or improvements
|
||||
- `help wanted` - Extra attention or assistance needed
|
||||
- `question` - Further information is requested
|
||||
- `wontfix` - This will not be worked on
|
||||
|
||||
Looking for a place to start? Try filtering for [good first issues](https://github.com/topoteretes/cognee/labels/good%20first%20issue)!
|
||||
|
||||
|
||||
## 2. 🛠️ Development Setup
|
||||
|
||||
### Required tools
|
||||
* [Python](https://www.python.org/downloads/)
|
||||
* [uv](https://docs.astral.sh/uv/getting-started/installation/)
|
||||
* pre-commit: `uv run pip install pre-commit && pre-commit install`
|
||||
|
||||
### Fork and Clone
|
||||
|
||||
1. Fork the [**cognee**](https://github.com/topoteretes/cognee) repository
|
||||
2. Clone your fork:
|
||||
```shell
|
||||
git clone https://github.com/<your-github-username>/cognee.git
|
||||
cd cognee
|
||||
```
|
||||
In case you are working on Vector and Graph Adapters
|
||||
1. Fork the [**cognee-community**](https://github.com/topoteretes/cognee-community) repository
|
||||
2. Clone your fork:
|
||||
```shell
|
||||
git clone https://github.com/<your-github-username>/cognee-community.git
|
||||
cd cognee-community
|
||||
```
|
||||
|
||||
### Create a Branch
|
||||
|
||||
Create a new branch for your work:
|
||||
```shell
|
||||
git checkout -b feature/your-feature-name
|
||||
```
|
||||
|
||||
## 3. 🎯 Making Changes
|
||||
|
||||
1. **Code Style**: Follow the project's coding standards
|
||||
2. **Documentation**: Update relevant documentation
|
||||
3. **Tests**: Add tests for new features
|
||||
4. **Commits**: Write clear commit messages
|
||||
|
||||
### Running Tests
|
||||
|
||||
Copy `.env.template` to `.env` and provide your OPENAI_API_KEY as LLM_API_KEY
|
||||
|
||||
```shell
|
||||
uv run python cognee/tests/test_library.py
|
||||
```
|
||||
|
||||
### Running Simple Example
|
||||
|
||||
Copy `.env.template` to `.env` and provide your OPENAI_API_KEY as LLM_API_KEY
|
||||
|
||||
Make sure to run ```shell uv sync ``` in the root cloned folder or set up a virtual environment to run cognee
|
||||
|
||||
```shell
|
||||
uv run python examples/demos/simple_cognee_example.py
|
||||
```
|
||||
|
||||
## 4. 📤 Submitting Changes
|
||||
|
||||
1. Make sure that `pre-commit` and hooks are installed. See `Required tools` section for more information. Try executing `pre-commit run` if you are not sure.
|
||||
3. Push your changes:
|
||||
```shell
|
||||
git add .
|
||||
git commit -s -m "Description of your changes"
|
||||
git push origin feature/your-feature-name
|
||||
```
|
||||
|
||||
2. Create a Pull Request:
|
||||
- Go to the [**cognee** repository](https://github.com/topoteretes/cognee) or [cognee community repository](https://github.com/topoteretes/cognee-community)
|
||||
- Click "Compare & Pull Request" and open a PR against dev branch
|
||||
- Fill in the PR template with details about your changes
|
||||
- You MUST provide screenshots of unit and integration tests passing on your machine. We can't merge PRs otherwise
|
||||
|
||||
> **Reviewers are auto-routed.** Cognee uses a [`CODEOWNERS`](.github/CODEOWNERS)
|
||||
> file to request reviews automatically based on the directories your PR touches.
|
||||
> No manual ping required — the right person will get notified when you open the PR.
|
||||
|
||||
## 5. 📜 Developer Certificate of Origin (DCO)
|
||||
|
||||
All contributions must be signed-off to indicate agreement with our DCO:
|
||||
|
||||
```shell
|
||||
git config alias.cos "commit -s" # Create alias for signed commits
|
||||
```
|
||||
|
||||
When your PR is ready, please include:
|
||||
> "I affirm that all code in every commit of this pull request conforms to the terms of the Topoteretes Developer Certificate of Origin"
|
||||
|
||||
## 6. 🤝 Community Guidelines
|
||||
|
||||
- Be respectful and inclusive
|
||||
- Help others learn and grow
|
||||
- Follow our [Code of Conduct](CODE_OF_CONDUCT.md)
|
||||
- Provide constructive feedback
|
||||
- Ask questions when unsure
|
||||
|
||||
## 7. 📫 Getting Help
|
||||
|
||||
- Open an [issue](https://github.com/topoteretes/cognee/issues)
|
||||
- Join our Discord community
|
||||
- Check existing documentation
|
||||
|
||||
Thank you for contributing to **cognee**! 🌟
|
||||
@@ -0,0 +1,12 @@
|
||||
## 💫 Contributors
|
||||
|
||||
Thanks to our amazing contributors! 💖
|
||||
|
||||
<a href="https://github.com/topoteretes/cognee/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=topoteretes/cognee" />
|
||||
</a>
|
||||
|
||||
## 🏆 Top Contributors
|
||||
|
||||
| Rank | Contributor | Contributions |
|
||||
|------|------------|---------------|
|
||||
@@ -0,0 +1,17 @@
|
||||
Developer Certificate of Origin Version 1.1
|
||||
|
||||
Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
|
||||
|
||||
Developer's Certificate of Origin 1.1
|
||||
|
||||
By making a contribution to this project, I certify that:
|
||||
|
||||
(a) The contribution was created in whole or in part by me and I have the right to submit it under the open source license indicated in the file; or
|
||||
|
||||
(b) The contribution is based upon previous work that, to the best of my knowledge, is covered under an appropriate open source license and I have the right under that license to submit that work with modifications, whether created in whole or in part by me, under the same open source license (unless I am permitted to submit under a different license), as indicated in the file; or
|
||||
|
||||
(c) The contribution was provided directly to me by some other person who certified (a), (b) or (c) and I have not modified it.
|
||||
|
||||
(d) I understand and agree that this project and the contribution are public and that a record of the contribution (including all personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with this project or the open source license(s) involved.
|
||||
@@ -0,0 +1,74 @@
|
||||
# Use a Python image with uv pre-installed
|
||||
FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim AS uv
|
||||
|
||||
# Install the project into `/app`
|
||||
WORKDIR /app
|
||||
|
||||
# Enable bytecode compilation: without it the venv ships no .pyc files, so
|
||||
# every container cold start recompiles the entire dependency tree from
|
||||
# source (measured on cognee-saas-pod: ~8s of a ~13s import, halving startup).
|
||||
ENV UV_COMPILE_BYTECODE=1
|
||||
|
||||
# Copy from the cache instead of linking since it's a mounted volume
|
||||
ENV UV_LINK_MODE=copy
|
||||
|
||||
# Set build argument
|
||||
ARG DEBUG
|
||||
|
||||
# Set environment variable based on the build argument
|
||||
ENV DEBUG=${DEBUG}
|
||||
|
||||
# Install system dependencies
|
||||
RUN apt-get update && apt-get install -y \
|
||||
gcc \
|
||||
libpq-dev \
|
||||
git \
|
||||
curl \
|
||||
cmake \
|
||||
clang \
|
||||
build-essential \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Copy pyproject.toml and lockfile first for better caching
|
||||
COPY README.md pyproject.toml uv.lock entrypoint.sh ./
|
||||
|
||||
# Install the project's dependencies using the lockfile and settings
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
uv sync --extra debug --extra api --extra postgres --extra neo4j --extra llama-index --extra ollama --extra mistral --extra groq --extra anthropic --frozen --no-install-project --no-dev --no-editable
|
||||
|
||||
# Then, add the rest of the project source code and install it
|
||||
# Installing separately from its dependencies allows optimal layer caching
|
||||
COPY ./cognee /app/cognee
|
||||
COPY ./distributed /app/distributed
|
||||
COPY ./cognee_db_workers /app/cognee_db_workers
|
||||
# Compatibility shim that re-exports ladybug under the legacy `kuzu`
|
||||
# module name. Listed in [tool.hatch.build.targets.wheel] packages, and
|
||||
# imported at module load by alembic/versions/b9274c27a25a_kuzu_11_migration.py.
|
||||
COPY ./kuzu /app/kuzu
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
uv sync --extra debug --extra api --extra postgres --extra neo4j --extra llama-index --extra ollama --extra mistral --extra groq --extra anthropic --frozen --no-dev --no-editable
|
||||
|
||||
FROM python:3.12-slim-bookworm
|
||||
|
||||
RUN apt-get update && apt-get install -y \
|
||||
libpq5 \
|
||||
curl \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY --from=uv /app /app
|
||||
# COPY --from=uv /app/.venv /app/.venv
|
||||
# COPY --from=uv /root/.local /root/.local
|
||||
|
||||
# Strip Windows carriage returns (fixes "no such file" on Windows Docker)
|
||||
RUN sed -i 's/\r$//' /app/entrypoint.sh && chmod +x /app/entrypoint.sh
|
||||
|
||||
# Place executables in the environment at the front of the path
|
||||
ENV PATH="/app/.venv/bin:$PATH"
|
||||
|
||||
ENV PYTHONPATH=/app
|
||||
# ENV LOG_LEVEL=ERROR
|
||||
ENV PYTHONUNBUFFERED=1
|
||||
|
||||
ENTRYPOINT ["/app/entrypoint.sh"]
|
||||
@@ -0,0 +1,26 @@
|
||||
FROM ghcr.io/astral-sh/uv:python3.11-bookworm-slim
|
||||
WORKDIR /app
|
||||
ENV UV_LINK_MODE=copy
|
||||
|
||||
# System deps (superset of all CI needs)
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
gcc g++ libpq-dev git curl cmake clang build-essential \
|
||||
postgresql-client libgl1 libglib2.0-0 \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY pyproject.toml uv.lock README.md ./
|
||||
|
||||
# ALL extras used across CI - no-install-project so project code isn't baked in
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
uv sync --frozen --no-install-project \
|
||||
--extra api --extra docs --extra evals --extra codegraph --extra ollama \
|
||||
--extra dev --extra neo4j --extra redis --extra postgres --extra aws \
|
||||
--extra baml --extra distributed --extra deepeval --extra scraping \
|
||||
--extra notebook --extra docling
|
||||
|
||||
# Marker file for container detection in cognee_setup
|
||||
RUN echo "test-machine" > /app/.anon_id
|
||||
|
||||
ENV PATH="/app/.venv/bin:$PATH"
|
||||
ENV PYTHONPATH=/app
|
||||
ENV PYTHONUNBUFFERED=1
|
||||
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2024 Topoteretes UG
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
@@ -0,0 +1,10 @@
|
||||
topoteretes - cognee
|
||||
Copyright © 2024 Topoteretes UG. (haftungsbeschränkt), Schonehauser Allee 163, Berlin.
|
||||
|
||||
This project includes software developed at Topoteretes UG. (https://www.cognee.ai/).
|
||||
|
||||
<!-- Add software from external sources that you used here. e.g.
|
||||
|
||||
This project redistributes code originally from <website>.
|
||||
|
||||
-->
|
||||
@@ -0,0 +1,437 @@
|
||||
<div align="center">
|
||||
<a href="https://github.com/topoteretes/cognee">
|
||||
<img src="https://raw.githubusercontent.com/topoteretes/cognee/refs/heads/dev/assets/cognee-logo-transparent.png" alt="Cognee Logo" height="60">
|
||||
</a>
|
||||
|
||||
<br />
|
||||
|
||||
Cognee - The Open-Source AI Memory Platform for Agents
|
||||
|
||||
<p align="center">
|
||||
<a href="https://www.youtube.com/watch?v=8hmqS2Y5RVQ&t=13s">Demo</a>
|
||||
.
|
||||
<a href="https://docs.cognee.ai/">Docs</a>
|
||||
.
|
||||
<a href="https://cognee.ai">Learn More</a>
|
||||
·
|
||||
<a href="https://discord.gg/NQPKmU5CCg">Join Discord</a>
|
||||
·
|
||||
<a href="https://www.reddit.com/r/AIMemory/">Join r/AIMemory</a>
|
||||
.
|
||||
<a href="https://github.com/topoteretes/cognee-community">Community Plugins & Add-ons</a>
|
||||
</p>
|
||||
|
||||
|
||||
[](https://GitHub.com/topoteretes/cognee/network/)
|
||||
[](https://GitHub.com/topoteretes/cognee/stargazers/)
|
||||
[](https://GitHub.com/topoteretes/cognee/commit/)
|
||||
[](https://github.com/topoteretes/cognee/tags/)
|
||||
[](https://pepy.tech/project/cognee)
|
||||
[](https://github.com/topoteretes/cognee/blob/main/LICENSE)
|
||||
[](https://github.com/topoteretes/cognee/graphs/contributors)
|
||||
<a href="https://github.com/sponsors/topoteretes"><img src="https://img.shields.io/badge/Sponsor-❤️-ff69b4.svg" alt="Sponsor"></a>
|
||||
|
||||
<p>
|
||||
<a href="https://trendshift.io/repositories/13955" target="_blank" style="display:inline-block;">
|
||||
<img src="https://trendshift.io/api/badge/repositories/13955" alt="topoteretes%2Fcognee | Trendshift" width="250" height="55" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
Cognee is the open-source AI memory platform that gives AI agents persistent long-term memory across sessions. Ingest data in any format, build a self-hosted knowledge graph, and let every agent recall, connect, and act with full context
|
||||
|
||||
<p align="center">
|
||||
🌐 This README is also available in:
|
||||
:
|
||||
<!-- Keep these links. Translations will automatically update with the README. -->
|
||||
<a href="https://www.readme-i18n.com/topoteretes/cognee?lang=de">Deutsch</a> |
|
||||
<a href="https://www.readme-i18n.com/topoteretes/cognee?lang=es">Español</a> |
|
||||
<a href="https://www.readme-i18n.com/topoteretes/cognee?lang=fr">Français</a> |
|
||||
<a href="https://www.readme-i18n.com/topoteretes/cognee?lang=ja">日本語</a> |
|
||||
<a href="README_ko.md">한국어</a> |
|
||||
<a href="https://www.readme-i18n.com/topoteretes/cognee?lang=pt">Português</a> |
|
||||
<a href="https://www.readme-i18n.com/topoteretes/cognee?lang=ru">Русский</a> |
|
||||
<a href="https://www.readme-i18n.com/topoteretes/cognee?lang=zh">中文</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<img src="assets/cognee-demo.gif" alt="Cognee Demo" width="80%" />
|
||||
</p>
|
||||
</div>
|
||||
|
||||
📄 Read the research paper: [Optimizing the Interface Between Knowledge Graphs and LLMs for Complex Reasoning](https://arxiv.org/abs/2505.24478) — Markovic et al., 2025
|
||||
|
||||
|
||||
## About Cognee
|
||||
|
||||
Cognee is an open-source AI memory platform for AI Agents. Ingest data in any format, and Cognee continuously builds a self-hosted knowledge graph that gives your agents persistent long-term memory across sessions. Cognee combines vector embeddings, graph reasoning, and cognitive-science-grounded ontology generation to make documents both searchable by meaning and connected by relationships that evolve as your knowledge does.
|
||||
|
||||
:star: _Help us reach more developers and grow the cognee community. Star this repo!_
|
||||
|
||||
:books: _Check our detailed [documentation](https://docs.cognee.ai/getting-started/installation#environment-configuration) for setup and configuration._
|
||||
|
||||
:crab: _Available as a plugin for your OpenClaw — [cognee-openclaw](https://www.npmjs.com/package/@cognee/cognee-openclaw)_
|
||||
|
||||
✴️ _Available as a plugin for your Claude Code — [claude-code-plugin](https://github.com/topoteretes/cognee-integrations/tree/main/integrations/claude-code)_
|
||||
|
||||
🦀 _Available as a Rust client — [cognee-rs](https://github.com/topoteretes/cognee-rs)_
|
||||
|
||||
🟦 _Available as a TypeScript client — [@cognee/cognee-ts](https://www.npmjs.com/package/@cognee/cognee-ts)_
|
||||
|
||||
|
||||
|
||||
### Why use Cognee:
|
||||
|
||||
- Easily Build Company Brain - unify data from various sources in one place and enable Agents with your domain knowledge
|
||||
- Knowledge infrastructure — unified ingestion, graph/vector search, runs locally, ontology grounding, multimodal
|
||||
- Persistent and Learning Agents - learn from feedback, context management, cross-agent knowledge sharing
|
||||
- Reliable and Trustworthy Agents - agentic user/tenant isolation, traceability, OTEL collector, audit traits
|
||||
|
||||
### How it Works
|
||||
|
||||
<p align="center">
|
||||
<img src="assets/remember.svg" alt="Cognee Products" width="80%" />
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<img src="assets/recall.svg" alt="Cognee Recall" width="80%" />
|
||||
</p>
|
||||
|
||||
## Basic Usage & Feature Guide
|
||||
|
||||
To learn more, [check out this short, end-to-end Colab walkthrough](https://colab.research.google.com/drive/1HRrzIvzcbwrESVfX76wJLKmtIg00SUga?usp=sharing) of Cognee's core features.
|
||||
|
||||
[](https://colab.research.google.com/drive/1HRrzIvzcbwrESVfX76wJLKmtIg00SUga?usp=sharing)
|
||||
|
||||
## Quickstart
|
||||
|
||||
Let’s try Cognee in just a few lines of code.
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Python 3.10 to 3.14
|
||||
|
||||
### Step 1: Install Cognee
|
||||
|
||||
You can install Cognee with **pip**, **poetry**, **uv**, or your preferred Python package manager.
|
||||
|
||||
```bash
|
||||
uv pip install cognee
|
||||
```
|
||||
|
||||
### Step 2: Configure the LLM
|
||||
```python
|
||||
import os
|
||||
os.environ["LLM_API_KEY"] = "YOUR OPENAI_API_KEY"
|
||||
```
|
||||
Alternatively, create a `.env` file using our [template](https://github.com/topoteretes/cognee/blob/main/.env.template).
|
||||
|
||||
To integrate other LLM providers, see our [LLM Provider Documentation](https://docs.cognee.ai/setup-configuration/llm-providers).
|
||||
|
||||
### Step 3: Run the Pipeline
|
||||
|
||||
Cognee's API gives you four operations — `remember`, `recall`, `forget`, and `improve`:
|
||||
|
||||
```python
|
||||
import cognee
|
||||
import asyncio
|
||||
|
||||
|
||||
async def main():
|
||||
# Store permanently in the knowledge graph (runs add + cognify + improve)
|
||||
await cognee.remember("Cognee turns documents into AI memory.")
|
||||
|
||||
# Store in session memory (fast cache, syncs to graph in background)
|
||||
await cognee.remember("User prefers detailed explanations.", session_id="chat_1")
|
||||
|
||||
# Query with auto-routing (picks best search strategy automatically)
|
||||
results = await cognee.recall("What does Cognee do?")
|
||||
for result in results:
|
||||
print(result)
|
||||
|
||||
# Query session memory first, fall through to graph if needed
|
||||
results = await cognee.recall("What does the user prefer?", session_id="chat_1")
|
||||
for result in results:
|
||||
print(result)
|
||||
|
||||
# Delete when done
|
||||
await cognee.forget(dataset="main_dataset")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(main())
|
||||
|
||||
```
|
||||
|
||||
### Use the Cognee CLI
|
||||
|
||||
```bash
|
||||
cognee-cli remember "Cognee turns documents into AI memory."
|
||||
|
||||
cognee-cli recall "What does Cognee do?"
|
||||
|
||||
cognee-cli forget --all
|
||||
```
|
||||
|
||||
To open the local UI, run:
|
||||
```bash
|
||||
cognee-cli -ui
|
||||
```
|
||||
|
||||
> **Note:** The MCP server launched by `cognee-cli -ui` runs inside a Docker container.
|
||||
> Docker Desktop, Colima, or any OCI-compatible runtime with a working `docker` CLI is
|
||||
> required. See [Docker & Colima Setup](docs/docker-colima-setup.md) for details.
|
||||
|
||||
## Run with Docker
|
||||
|
||||
Prefer containers? Cognee publishes prebuilt images to Docker Hub on every push to `main`:
|
||||
[`cognee/cognee`](https://hub.docker.com/r/cognee/cognee) (the API server) and
|
||||
[`cognee/cognee-mcp`](https://hub.docker.com/r/cognee/cognee-mcp) (the MCP server).
|
||||
|
||||
### Option A — Docker Compose (build from source)
|
||||
|
||||
Clone the repo, create a `.env` with at least `LLM_API_KEY`, then:
|
||||
|
||||
```bash
|
||||
cp .env.template .env # then edit .env and set LLM_API_KEY
|
||||
|
||||
# Start the API server (http://localhost:8000)
|
||||
docker compose up
|
||||
|
||||
# Optional profiles (combine as needed):
|
||||
docker compose --profile ui up # + frontend on http://localhost:3000
|
||||
docker compose --profile mcp up # + MCP server on http://localhost:8001
|
||||
docker compose --profile postgres up # + Postgres/PGVector
|
||||
docker compose --profile neo4j up # + Neo4j
|
||||
```
|
||||
|
||||
> The `cognee` and `cognee-mcp` services publish different host ports (`8000` vs `8001`),
|
||||
> so you can run both at once.
|
||||
|
||||
### Option B — Pull the prebuilt image (no clone required)
|
||||
|
||||
```bash
|
||||
# Create a minimal .env in the current directory
|
||||
echo 'LLM_API_KEY="YOUR_OPENAI_API_KEY"' > .env
|
||||
|
||||
# API server
|
||||
docker run --env-file ./.env -p 8000:8000 --rm -it cognee/cognee:main
|
||||
|
||||
# MCP server (HTTP transport)
|
||||
docker pull cognee/cognee-mcp:main
|
||||
docker run -e TRANSPORT_MODE=http --env-file ./.env -p 8000:8000 --rm -it cognee/cognee-mcp:main
|
||||
```
|
||||
|
||||
See the [MCP server README](cognee-mcp/README.md) for SSE/stdio transports, optional
|
||||
extras, and MCP client configuration.
|
||||
|
||||
## Use with AI Agents
|
||||
|
||||
### Claude Code
|
||||
|
||||
Install the [Cognee memory plugin](https://github.com/topoteretes/cognee-integrations/tree/main/integrations/claude-code) to give Claude Code persistent memory across sessions. The plugin captures prompts, tool traces, and assistant responses into session memory, injects relevant context on every prompt, and syncs session memory into the permanent knowledge graph at session end.
|
||||
|
||||
**Install** from the Claude Code marketplace. The recommended way is from your shell, *before* launching Claude Code, so the first `claude` launch is a clean session that bootstraps memory automatically:
|
||||
|
||||
```bash
|
||||
# Add the marketplace and install the plugin (one-time, user-scoped)
|
||||
claude plugin marketplace add topoteretes/cognee-integrations
|
||||
claude plugin install cognee-memory@cognee
|
||||
|
||||
# Set env vars for your mode (see below), then launch
|
||||
export LLM_API_KEY="sk-..." # local mode; or COGNEE_BASE_URL + COGNEE_API_KEY for cloud
|
||||
claude
|
||||
```
|
||||
|
||||
**Local mode** (default) — the plugin bootstraps a local Cognee API at `http://localhost:8011`. Only `LLM_API_KEY` is required; the Cognee API key is auto-minted if absent:
|
||||
|
||||
```bash
|
||||
export LLM_API_KEY="sk-..."
|
||||
```
|
||||
|
||||
**Cognee Cloud or a remote server** — set both:
|
||||
|
||||
```bash
|
||||
export COGNEE_BASE_URL="https://your-instance.cognee.ai"
|
||||
export COGNEE_API_KEY="ck_..."
|
||||
```
|
||||
|
||||
On startup you should see a "Cognee Memory Connected" system message.
|
||||
|
||||
The plugin hooks into Claude Code's lifecycle — `SessionStart` selects mode and sets up identity, `UserPromptSubmit` injects dataset-scoped context, `PostToolUse` captures tool traces, `Stop` writes the assistant's answer, `PreCompact` preserves memory across context resets, and `SessionEnd` triggers the final sync into the permanent graph.
|
||||
|
||||
See the [plugin README](https://github.com/topoteretes/cognee-integrations/tree/main/integrations/claude-code) for sessions, datasets, and full configuration.
|
||||
|
||||
### Connect to Cognee Cloud
|
||||
|
||||
Point any Python agent at a managed Cognee instance — all SDK calls route to the cloud:
|
||||
|
||||
```python
|
||||
import cognee
|
||||
|
||||
await cognee.serve(url="https://your-instance.cognee.ai", api_key="ck_...")
|
||||
|
||||
await cognee.remember("important context")
|
||||
results = await cognee.recall("what happened?")
|
||||
|
||||
await cognee.disconnect()
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
Browse more examples in the [`examples/`](examples/) folder — demos, guides, custom pipelines, and database configurations.
|
||||
|
||||
**Use Case 1 — Customer Support Agent**
|
||||
|
||||
```python
|
||||
Goal: Resolve customer issues using their personal data across finance, support, and product history.
|
||||
|
||||
User: "My invoice looks wrong and the issue is still not resolved."
|
||||
|
||||
Cognee tracks: past interactions, failed actions, resolved cases, product history
|
||||
|
||||
# Agent response:
|
||||
Agent: "I found 2 similar billing cases resolved last month.
|
||||
The issue was caused by a sync delay between payment
|
||||
and invoice systems — a fix was applied on your account."
|
||||
|
||||
# What happens under the hood:
|
||||
- Unifies data sources from various company channels
|
||||
- Reconstructs the interaction timeline and tracks outcomes
|
||||
- Retrieves similar resolved cases
|
||||
- Maps to the best resolution strategy
|
||||
- Updates memory after execution so the agent never repeats the same mistake
|
||||
```
|
||||
|
||||
**Use Case 2 — Expert Knowledge Distillation (SQL Copilot)**
|
||||
|
||||
```python
|
||||
Goal: Help junior analysts solve tasks by reusing expert-level queries, patterns, and reasoning.
|
||||
|
||||
User: "How do I calculate customer retention for this dataset?"
|
||||
|
||||
Cognee tracks: expert SQL queries, workflow patterns, schema structures, successful implementations
|
||||
|
||||
# Agent response:
|
||||
Agent: "Here's how senior analysts solved a similar retention query.
|
||||
Cognee matched your schema to a known structure and adapted
|
||||
the expert's logic to fit your dataset."
|
||||
|
||||
# What happens under the hood:
|
||||
- Extracts and stores patterns from expert SQL queries and workflows
|
||||
- Maps the current schema to previously seen structures
|
||||
- Retrieves similar tasks and their successful implementations
|
||||
- Adapts expert reasoning to the current context
|
||||
- Updates memory with new successful patterns so junior analysts perform at near-expert level
|
||||
```
|
||||
|
||||
## Run the Whole Memory Layer on Postgres
|
||||
|
||||
Graph memory traditionally means operating a stack — a graph database for relationships, a vector database for embeddings, Redis for sessions, and a relational database for metadata — all deployed, secured, and paid for before an agent remembers anything. In cognee 1.0 you can run the entire memory layer on a single Postgres instance.
|
||||
|
||||
| Memory layer | Traditional stack | cognee on Postgres |
|
||||
| --- | --- | --- |
|
||||
| Relationships | Neo4j or another graph database | cognee's Postgres graph backend |
|
||||
| Embeddings | Dedicated vector database | pgvector |
|
||||
| Sessions | Redis | SQL session-cache backend |
|
||||
| Metadata | Relational database | same Postgres |
|
||||
|
||||
The graph still exists — it just lives inside the same Postgres-backed memory layer as the text, metadata, and embeddings, so retrieval moves between similarity and structure without crossing service boundaries. In our CI benchmarks, Postgres search ran ~10% faster than the separate graph-plus-vector setup.
|
||||
|
||||
Postgres is the default we recommend for most deployments, but you can still swap in dedicated backends when a workload needs them (Neo4j and Neptune for graphs, Redis for sessions, pgvector and LanceDB for vectors, plus Qdrant, ChromaDB, Weaviate, and Milvus via community adapters). Local development stays fully embedded — SQLite, LanceDB, and Kuzudb — with no extra services to stand up.
|
||||
|
||||
```bash
|
||||
pip install "cognee[postgres]"
|
||||
```
|
||||
|
||||
```bash
|
||||
DB_PROVIDER=postgres
|
||||
VECTOR_DB_PROVIDER=pgvector
|
||||
GRAPH_DATABASE_PROVIDER=postgres
|
||||
CACHE_BACKEND=postgres
|
||||
|
||||
DB_HOST=localhost
|
||||
DB_PORT=5432
|
||||
DB_USERNAME=cognee
|
||||
DB_PASSWORD=cognee
|
||||
DB_NAME=cognee_db
|
||||
```
|
||||
|
||||
## Deploy Cognee
|
||||
|
||||
Use [Cognee Cloud](https://www.cognee.ai) for a fully managed experience, or self-host with one of the 1-click deployment configurations below.
|
||||
|
||||
| Platform | Best For | Command |
|
||||
|----------|----------|---------|
|
||||
| **Cognee Cloud** | Managed service, no infrastructure to maintain | [Sign up](https://www.cognee.ai) or `await cognee.serve()` |
|
||||
| **Modal** | Serverless, auto-scaling, GPU workloads | `bash distributed/deploy/modal-deploy.sh` |
|
||||
| **Railway** | Simplest PaaS, native Postgres | `railway init && railway up` |
|
||||
| **Fly.io** | Edge deployment, persistent volumes | `bash distributed/deploy/fly-deploy.sh` |
|
||||
| **Render** | Simple PaaS with managed Postgres | Deploy to Render button |
|
||||
| **Daytona** | Cloud sandboxes (SDK or CLI) | See `distributed/deploy/daytona_sandbox.py` |
|
||||
|
||||
See the [`distributed/`](distributed/) folder for deploy scripts, worker configurations, and additional details.
|
||||
|
||||
## Use Cognee in Other Languages
|
||||
|
||||
Prefer something other than Python? Cognee also ships official clients for Rust and TypeScript.
|
||||
|
||||
### Getting Started with Rust
|
||||
|
||||
Use the [cognee-rs](https://github.com/topoteretes/cognee-rs) crate to add, cognify, and search from Rust.
|
||||
|
||||
```bash
|
||||
cargo add cognee
|
||||
```
|
||||
|
||||
See the [cognee-rs repository](https://github.com/topoteretes/cognee-rs) for full setup and examples.
|
||||
|
||||
### Getting Started with TypeScript
|
||||
|
||||
Use the [@cognee/cognee-ts](https://www.npmjs.com/package/@cognee/cognee-ts) package to add, cognify, and search from Node.js or the browser.
|
||||
|
||||
```bash
|
||||
npm install @cognee/cognee-ts
|
||||
```
|
||||
|
||||
See the [@cognee/cognee-ts package](https://www.npmjs.com/package/@cognee/cognee-ts) for full setup and examples.
|
||||
|
||||
## Benchmarks
|
||||
|
||||
We ran cognee against [BEAM](https://github.com/topoteretes/cognee), a long-context benchmark that tests whether a system can keep track of a long conversation as it changes — a more useful test for agent memory than typical needle-in-a-haystack benchmarks. Using only cognee's default settings and standard open-source features (no custom models, no BEAM-specific pipelines), we beat the previous state of the art at the 100K-token setting and matched it at 10M tokens.
|
||||
|
||||
| Benchmark | Setting | cognee | Previous SOTA | Obsidian / RAG baseline |
|
||||
|-----------|---------|--------|---------------|--------------------------|
|
||||
| BEAM | 100K tokens | **0.79** (>0.8 with per-question routing) | 0.735 | ~0.33 |
|
||||
| BEAM | 10M tokens | **0.67** | 0.641 | ~0.33 |
|
||||
|
||||
These numbers are a directional signal rather than a definitive measure — see the write-up for the full methodology, caveats, and what the results actually mean.
|
||||
|
||||
## Latest News
|
||||
|
||||
[](https://www.youtube.com/watch?v=8hmqS2Y5RVQ&t=13s)
|
||||
|
||||
|
||||
## Community & Support
|
||||
|
||||
### Contributing
|
||||
We welcome contributions from the community! Your input helps make Cognee better for everyone. See [`CONTRIBUTING.md`](CONTRIBUTING.md) to get started.
|
||||
|
||||
### Code of Conduct
|
||||
|
||||
We're committed to fostering an inclusive and respectful community. Read our [Code of Conduct](https://github.com/topoteretes/cognee/blob/main/CODE_OF_CONDUCT.md) for guidelines.
|
||||
|
||||
## Research & Citation
|
||||
|
||||
We recently published a research paper on optimizing knowledge graphs for LLM reasoning:
|
||||
|
||||
```bibtex
|
||||
@misc{markovic2025optimizinginterfaceknowledgegraphs,
|
||||
title={Optimizing the Interface Between Knowledge Graphs and LLMs for Complex Reasoning},
|
||||
author={Vasilije Markovic and Lazar Obradovic and Laszlo Hajdu and Jovan Pavlovic},
|
||||
year={2025},
|
||||
eprint={2505.24478},
|
||||
archivePrefix={arXiv},
|
||||
primaryClass={cs.AI},
|
||||
url={https://arxiv.org/abs/2505.24478},
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,7 @@
|
||||
# WeHub 来源说明
|
||||
|
||||
- 原始项目:`topoteretes/cognee`
|
||||
- 原始仓库:https://github.com/topoteretes/cognee
|
||||
- 导入方式:上游默认分支的最新快照
|
||||
- 原作者、版权和许可证信息以原始仓库及本仓库 LICENSE 为准
|
||||
- 本文件仅用于记录来源,不代表 WeHub 是原项目作者
|
||||
@@ -0,0 +1,220 @@
|
||||
<div align="center">
|
||||
<a href="https://github.com/topoteretes/cognee">
|
||||
<img src="https://raw.githubusercontent.com/topoteretes/cognee/refs/heads/dev/assets/cognee-logo-transparent.png" alt="Cognee Logo" height="60">
|
||||
</a>
|
||||
|
||||
<br />
|
||||
|
||||
Cognee - 정확하고 지속적인 AI 메모리
|
||||
|
||||
<p align="center">
|
||||
<a href="https://www.youtube.com/watch?v=1bezuvLwJmw&t=2s">데모</a>
|
||||
.
|
||||
<a href="https://docs.cognee.ai/">문서</a>
|
||||
.
|
||||
<a href="https://cognee.ai">더 알아보기</a>
|
||||
·
|
||||
<a href="https://discord.gg/NQPKmU5CCg">Discord 참여</a>
|
||||
·
|
||||
<a href="https://www.reddit.com/r/AIMemory/">r/AIMemory 참여</a>
|
||||
.
|
||||
<a href="https://github.com/topoteretes/cognee-community">커뮤니티 플러그인 & 애드온</a>
|
||||
</p>
|
||||
|
||||
|
||||
[](https://GitHub.com/topoteretes/cognee/network/)
|
||||
[](https://GitHub.com/topoteretes/cognee/stargazers/)
|
||||
[](https://GitHub.com/topoteretes/cognee/commit/)
|
||||
[](https://github.com/topoteretes/cognee/tags/)
|
||||
[](https://pepy.tech/project/cognee)
|
||||
[](https://github.com/topoteretes/cognee/blob/main/LICENSE)
|
||||
[](https://github.com/topoteretes/cognee/graphs/contributors)
|
||||
<a href="https://github.com/sponsors/topoteretes"><img src="https://img.shields.io/badge/Sponsor-❤️-ff69b4.svg" alt="Sponsor"></a>
|
||||
|
||||
<p>
|
||||
<a href="https://www.producthunt.com/posts/cognee?embed=true&utm_source=badge-top-post-badge&utm_medium=badge&utm_souce=badge-cognee" target="_blank" style="display:inline-block; margin-right:10px;">
|
||||
<img src="https://api.producthunt.com/widgets/embed-image/v1/top-post-badge.svg?post_id=946346&theme=light&period=daily&t=1744472480704" alt="cognee - Memory for AI Agents  in 5 lines of code | Product Hunt" width="250" height="54" />
|
||||
</a>
|
||||
|
||||
<a href="https://trendshift.io/repositories/13955" target="_blank" style="display:inline-block;">
|
||||
<img src="https://trendshift.io/api/badge/repositories/13955" alt="topoteretes%2Fcognee | Trendshift" width="250" height="55" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
데이터를 사용하여 AI 에이전트를 위한 개인화되고 동적인 메모리를 구축하세요. Cognee를 사용하면 RAG를 확장 가능하고 모듈화된 ECL(추출[Extract], 인지화[Cognify], 로드[Load]) 파이프라인으로 대체할 수 있습니다.
|
||||
|
||||
<p align="center">
|
||||
🌐 사용 가능한 언어
|
||||
:
|
||||
<!-- Keep these links. Translations will automatically update with the README. -->
|
||||
<a href="https://www.readme-i18n.com/topoteretes/cognee?lang=de">Deutsch</a> |
|
||||
<a href="https://www.readme-i18n.com/topoteretes/cognee?lang=es">Español</a> |
|
||||
<a href="https://www.readme-i18n.com/topoteretes/cognee?lang=fr">Français</a> |
|
||||
<a href="https://www.readme-i18n.com/topoteretes/cognee?lang=ja">日本語</a> |
|
||||
<a href="README_ko.md">한국어</a> |
|
||||
<a href="https://www.readme-i18n.com/topoteretes/cognee?lang=pt">Português</a> |
|
||||
<a href="https://www.readme-i18n.com/topoteretes/cognee?lang=ru">Русский</a> |
|
||||
<a href="https://www.readme-i18n.com/topoteretes/cognee?lang=zh">中文</a>
|
||||
</p>
|
||||
|
||||
|
||||
<div style="text-align: center">
|
||||
<img src="https://raw.githubusercontent.com/topoteretes/cognee/refs/heads/main/assets/cognee_benefits.png" alt="Why cognee?" width="50%" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
## Cognee 소개
|
||||
|
||||
Cognee는 원시 데이터를 에이전트를 위한 지속적이고 동적인 AI 메모리로 변환하는 오픈 소스 도구이자 플랫폼입니다. 벡터 검색과 그래프 데이터베이스를 결합하여 문서를 의미적으로 검색 가능하게 하고 관계별로 연결합니다.
|
||||
|
||||
Cognee는 두 가지 방식으로 사용할 수 있습니다.
|
||||
|
||||
1. [Cognee 오픈 소스 (셀프 호스팅)](https://docs.cognee.ai/getting-started/installation): 기본적으로 모든 데이터를 로컬에 저장합니다.
|
||||
2. [Cognee Cloud (관리형)](https://platform.cognee.ai/): 관리형 인프라에서 동일한 OSS 스택을 사용하여 더 쉽게 개발하고 프로덕션화할 수 있습니다.
|
||||
|
||||
### Cognee 오픈 소스 (셀프 호스팅):
|
||||
|
||||
- 과거 대화, 파일, 이미지, 오디오 스크립트 등 모든 유형의 데이터를 상호 연결
|
||||
- 기존 RAG 시스템을 그래프와 벡터 기반의 통합 메모리 계층으로 대체
|
||||
- 품질과 정밀도를 향상시키면서 개발자 노력과 인프라 비용 절감
|
||||
- 30개 이상의 데이터 소스에서 데이터를 수집할 수 있는 Pythonic 데이터 파이프라인 제공
|
||||
- 사용자 정의 작업, 모듈식 파이프라인, 내장 검색 엔드포인트를 통한 높은 사용자 정의 가능성 제공
|
||||
|
||||
### Cognee Cloud (관리형):
|
||||
- 호스팅된 웹 UI 대시보드
|
||||
- 자동 버전 업데이트
|
||||
- 리소스 사용량 분석
|
||||
- GDPR 준수, 엔터프라이즈급 보안
|
||||
|
||||
## 기본 사용법 & 기능 가이드
|
||||
|
||||
자세한 내용은 [Colab 튜토리얼](https://colab.research.google.com/drive/12Vi9zID-M3fpKpKiaqDBvkk98ElkRPWy?usp=sharing)을 확인하세요.
|
||||
|
||||
[](https://colab.research.google.com/drive/12Vi9zID-M3fpKpKiaqDBvkk98ElkRPWy?usp=sharing)
|
||||
|
||||
## 빠른 시작
|
||||
|
||||
단 몇 줄의 코드로 Cognee를 사용해 보세요. 자세한 설정 및 구성은 [Cognee 문서](https://docs.cognee.ai/getting-started/installation#environment-configuration)를 참조하세요.
|
||||
|
||||
### 필수 조건
|
||||
|
||||
- Python 3.10 ~ 3.14
|
||||
|
||||
### 1단계: Cognee 설치
|
||||
|
||||
**pip**, **poetry**, **uv** 또는 선호하는 Python 패키지 관리자를 사용하여 Cognee를 설치할 수 있습니다.
|
||||
|
||||
```bash
|
||||
uv pip install cognee
|
||||
```
|
||||
|
||||
### 2단계: LLM 구성
|
||||
```python
|
||||
import os
|
||||
os.environ["LLM_API_KEY"] = "YOUR OPENAI_API_KEY"
|
||||
```
|
||||
또는 [템플릿](https://github.com/topoteretes/cognee/blob/main/.env.template)을 사용하여 `.env` 파일을 생성하세요.
|
||||
|
||||
다른 LLM 공급자를 통합하려면 [LLM 공급자 문서](https://docs.cognee.ai/setup-configuration/llm-providers)를 참조하세요.
|
||||
|
||||
### 3단계: 파이프라인 실행
|
||||
|
||||
Cognee는 문서를 가져와 지식 그래프를 생성한 다음 결합된 관계를 기반으로 그래프를 쿼리합니다.
|
||||
|
||||
이제 최소한의 파이프라인을 실행해 보겠습니다.
|
||||
|
||||
```python
|
||||
import cognee
|
||||
import asyncio
|
||||
from pprint import pprint
|
||||
|
||||
|
||||
async def main():
|
||||
# Cognee에 텍스트 추가
|
||||
await cognee.add("Cognee turns documents into AI memory.")
|
||||
|
||||
# 지식 그래프 생성
|
||||
await cognee.cognify()
|
||||
|
||||
# 그래프에 메모리 알고리즘 추가
|
||||
await cognee.memify()
|
||||
|
||||
# 지식 그래프 쿼리
|
||||
results = await cognee.search("What does Cognee do?")
|
||||
|
||||
# 결과 표시
|
||||
for result in results:
|
||||
pprint(result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(main())
|
||||
|
||||
```
|
||||
|
||||
보시다시피, 출력은 이전에 Cognee에 저장한 문서에서 생성됩니다.
|
||||
|
||||
```bash
|
||||
Cognee turns documents into AI memory.
|
||||
```
|
||||
|
||||
### Cognee CLI 사용
|
||||
|
||||
대안으로 다음 필수 명령으로 시작할 수 있습니다.
|
||||
|
||||
```bash
|
||||
cognee-cli add "Cognee turns documents into AI memory."
|
||||
|
||||
cognee-cli cognify
|
||||
|
||||
cognee-cli search "What does Cognee do?"
|
||||
cognee-cli delete --all
|
||||
|
||||
```
|
||||
|
||||
로컬 UI를 열려면 다음을 실행하세요.
|
||||
```bash
|
||||
cognee-cli -ui
|
||||
```
|
||||
|
||||
## 데모 및 예제
|
||||
|
||||
Cognee 작동 모습 확인:
|
||||
|
||||
### 지속적인 에이전트 메모리
|
||||
|
||||
[LangGraph 에이전트를 위한 Cognee 메모리](https://github.com/user-attachments/assets/e113b628-7212-4a2b-b288-0be39a93a1c3)
|
||||
|
||||
### 간단한 GraphRAG
|
||||
|
||||
[데모 보기](https://github.com/user-attachments/assets/f2186b2e-305a-42b0-9c2d-9f4473f15df8)
|
||||
|
||||
### Cognee와 Ollama
|
||||
|
||||
[데모 보기](https://github.com/user-attachments/assets/39672858-f774-4136-b957-1e2de67b8981)
|
||||
|
||||
|
||||
## 커뮤니티 및 지원
|
||||
|
||||
### 기여하기
|
||||
여러분들의 기여를 환영합니다! 여러분의 의견은 Cognee를 더 좋게 만드는 데 큰 도움이 됩니다. 시작하려면 [`CONTRIBUTING.md`](CONTRIBUTING.md)를 참조하세요.
|
||||
|
||||
### 규칙
|
||||
|
||||
우리는 포용적이고 존중하는 커뮤니티를 만들기 위해 노력하고 있습니다. 규칙은 [규칙 문서](https://github.com/topoteretes/cognee/blob/main/CODE_OF_CONDUCT.md)를 확인해주세요.
|
||||
|
||||
## 연구 및 인용
|
||||
|
||||
최근 LLM 추론을 위한 지식 그래프 최적화에 관한 연구 논문을 발표했습니다.
|
||||
|
||||
```bibtex
|
||||
@misc{markovic2025optimizinginterfaceknowledgegraphs,
|
||||
title={Optimizing the Interface Between Knowledge Graphs and LLMs for Complex Reasoning},
|
||||
author={Vasilije Markovic and Lazar Obradovic and Laszlo Hajdu and Jovan Pavlovic},
|
||||
year={2025},
|
||||
eprint={2505.24478},
|
||||
archivePrefix={arXiv},
|
||||
primaryClass={cs.AI},
|
||||
url={https://arxiv.org/abs/2505.24478},
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,6 @@
|
||||
# Reporting Security Issues
|
||||
The Cognee team takes security issues seriously. We appreciate your efforts to responsibly disclose your findings, and will make every effort to acknowledge your contributions.
|
||||
|
||||
To report a security issue, email [info@topoteretes.com](mailto:info@topoteretes.com) and include the word "SECURITY" in the subject line.
|
||||
|
||||
We'll endeavor to respond quickly, and will keep you updated throughout the process.
|
||||
@@ -0,0 +1,336 @@
|
||||
# Implementation Plan: Postgres-backed Session Store (CacheDBInterface adapter)
|
||||
|
||||
**Goal:** store cognee session data (QA entries, agent traces, usage logs, and small string KV values) in Postgres via a new `CacheDBInterface` adapter, removing the Redis requirement for session memory. Default backend stays `fs`; Redis and Tapes keep working unchanged. The design keeps a clean seam for a future Turbopuffer backend.
|
||||
|
||||
**Design stance:** minimal-surface adapter that slots into the existing backend plug point (like `FSCacheAdapter`), follows the graph Postgres adapter's engine/schema patterns, and adds **zero new dependencies** (SQLAlchemy is core; asyncpg/psycopg2 ship in the existing `postgres` extra). Where the minimal approach was naive (TTL purging, multi-worker RMW, lock semantics, prune scope), the robust alternatives are grafted in below — each divergence from the minimal design is justified inline.
|
||||
|
||||
---
|
||||
|
||||
## 1. Overview & goals
|
||||
|
||||
- Add `CACHE_BACKEND=postgres` as a fourth cache backend alongside `redis`, `fs`, `tapes`.
|
||||
- Implement `PostgresCacheAdapter(CacheDBInterface)` with full behavioral parity to `RedisAdapter`/`FSCacheAdapter` (TTL semantics, merge semantics, error contracts), improving on known Redis races where doing so is observably identical (atomic deletes, `FOR UPDATE` updates).
|
||||
- Support the formal string KV methods on `CacheDBInterface` (`get_value`/`set_value`/`delete_value`) for small cache values. The old graph-to-session sync contract is removed; new backends should not add an `async_redis` shim for it.
|
||||
- Non-goals (v1): data migration tooling (cache is 7-day-TTL ephemeral), per-dataset DB isolation (sessions are per-user), distributed `SHARED_LADYBUG_LOCK` support on Postgres (Phase 6), multi-worker `improve()` mutex.
|
||||
|
||||
---
|
||||
|
||||
## 2. Current state
|
||||
|
||||
**Cache interface** — `cognee/infrastructure/databases/cache/cache_db_interface.py`: ABC with sync lock methods (`acquire_lock`/`release_lock`, concrete `hold_lock()` contextmanager), async QA CRUD (`create_qa_entry`, `get_latest_qa_entries`, `get_all_qa_entries`, `update_qa_entry`, `delete_feedback`, `delete_qa_entry`, `delete_session`), agent traces (`append_agent_trace_step`, `get_agent_trace_session`, `get_agent_trace_feedback`, `get_agent_trace_count`), `prune`, `close`, `log_usage`/`get_usage_logs`, plus concrete back-compat shims `add_qa`/`get_latest_qa`/`get_all_qas` (do not reimplement). Base `__init__(host, port, lock_key="default_lock", log_key="usage_logs")`. Payload models: `SessionQAEntry`/`SessionAgentTraceEntry` in `cognee/infrastructure/databases/cache/models.py` (validators: feedback_score 1–5, `used_graph_element_ids` only `node_ids`/`edge_ids`, `memify_metadata` str→bool, trace sanitization/truncation).
|
||||
|
||||
**Backends** — `cache/redis/RedisAdapter.py` (sync `redis.Redis` for locks + async `redis.asyncio.Redis` for data; one Redis LIST per key `agent_sessions:{user_id}:{session_id}` / `agent_traces:{user_id}:{session_id}` / `{log_key}:{user_id}`; JSON-string elements; `EXPIRE`-on-write sliding TTL; `FLUSHDB` prune); `cache/fscache/FsCacheAdapter.py` (diskcache, whole list as one JSON value under `self.cache`, `cache.transact()`, lock methods raise `SharedLadybugLockRequiresRedisError`); `cache/tapes/TapesCacheAdapter.py` (FS subclass mirroring QA creates over HTTP).
|
||||
|
||||
**Factory** — `cache/get_cache_engine.py`: `@lru_cache`'d `create_cache_engine(...)` branches on `CacheConfig.cache_backend` (`Literal["redis","fs","tapes"]`, default `"fs"`, in `cache/config.py`); returns `None` when `caching` and `usage_logging` are both off; `close_cache_engine()` closes + `cache_clear()`s. **Verified gotcha:** `from ...RedisAdapter import RedisAdapter` executes unconditionally inside the caching-on block, *before* the backend dispatch — it only works because the unused core dep `fakeredis[lua]` transitively installs `redis`.
|
||||
|
||||
**Session manager** — `cognee/infrastructure/session/session_manager.py` (built by `get_session_manager.py`): wraps every interface method, no-ops when `cache_engine is None`. It no longer stores graph snapshots in session prompts. For one release, `delete_session` still deletes the legacy `graph_knowledge:{user_id}:{session_id}` key via `delete_value` so old cache rows do not linger.
|
||||
|
||||
**Locks** — two unrelated systems: (1) `cognee/infrastructure/locks/session_lock.py`: pure in-process asyncio locks (per-`(session_id, op)` dict + improve-lock set), explicitly single-worker scope, **no Redis dependency, no change required**; (2) `CacheDBInterface.acquire_lock`/`release_lock`: **sync** methods used only by the Ladybug graph adapter (`graph/ladybug/adapter.py` ~line 187, via `asyncio.to_thread`) when `SHARED_LADYBUG_LOCK=true` — Redis-only today.
|
||||
|
||||
**Relational sibling** — `cognee/modules/session_lifecycle/models.py` (`session_records`, `session_model_usage`): alembic-managed lifecycle/metrics rows, already Postgres-compatible, untouched by this plan. No FK between cache rows and `session_records` (cache rows TTL-expire; lifecycle rows persist — by design).
|
||||
|
||||
**Template** — `cognee/infrastructure/databases/graph/postgres/adapter.py` + `tables.py`: own `create_async_engine(uri, json_serializer=lambda obj: json.dumps(obj, cls=JSONEncoder), **pool_args)` (verified, lines 40–58), `async_sessionmaker(expire_on_commit=False)`, private `MetaData()` with `create_all(checkfirst=True)` in `initialize()` — not alembic.
|
||||
|
||||
---
|
||||
|
||||
## 3. Target architecture
|
||||
|
||||
```
|
||||
SessionManager / usage_logger / forget / prune_system / memify tasks
|
||||
│ (unchanged call sites)
|
||||
▼
|
||||
get_cache_engine() ──reads── CacheConfig (.env: CACHE_BACKEND, CACHE_DB_URL, ...)
|
||||
│ @lru_cache create_cache_engine()
|
||||
├── "redis" → RedisAdapter (unchanged)
|
||||
├── "fs" → FSCacheAdapter (unchanged)
|
||||
├── "tapes" → TapesCacheAdapter (unchanged)
|
||||
└── "postgres" → PostgresCacheAdapter (NEW, lazy import)
|
||||
│
|
||||
├── own async engine (postgresql+asyncpg://...)
|
||||
│ json_serializer=JSONEncoder (UUID/datetime-safe JSONB)
|
||||
├── tables (private MetaData, create-on-init):
|
||||
│ cache_qa_entries ← agent_sessions:{u}:{s} lists
|
||||
│ cache_trace_entries← agent_traces:{u}:{s} lists
|
||||
│ cache_usage_logs ← {log_key}:{u} lists
|
||||
│ cache_kv ← generic small string KV values
|
||||
└── get_value/set_value/delete_value over cache_kv
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Postgres adapter design
|
||||
|
||||
### 4.1 Module layout
|
||||
|
||||
Mirror the existing backend layout:
|
||||
|
||||
```
|
||||
cognee/infrastructure/databases/cache/postgres/
|
||||
├── __init__.py # re-export PostgresCacheAdapter
|
||||
├── tables.py # private MetaData + SQLAlchemy Core tables
|
||||
└── PostgresCacheAdapter.py # class PostgresCacheAdapter(CacheDBInterface)
|
||||
```
|
||||
|
||||
### 4.2 Class skeleton
|
||||
|
||||
```python
|
||||
class PostgresCacheAdapter(CacheDBInterface):
|
||||
def __init__(
|
||||
self,
|
||||
connection_string: str, # any SQLAlchemy async URL (asyncpg in prod, aiosqlite in tests)
|
||||
lock_key: str = "default_lock",
|
||||
log_key: str = "usage_logs",
|
||||
session_ttl_seconds: int | None = 604800,
|
||||
agentic_lock_expire: int = 240, # stored now, used by Phase 6 advisory locks
|
||||
agentic_lock_timeout: int = 300,
|
||||
purge_interval_seconds: int = 900,
|
||||
):
|
||||
super().__init__(host="", port=0, lock_key=lock_key, log_key=log_key)
|
||||
self.db_uri = connection_string
|
||||
self.session_ttl_seconds = session_ttl_seconds
|
||||
pool_args = dict(get_relational_config().pool_args or {})
|
||||
self.engine = create_async_engine(
|
||||
connection_string,
|
||||
json_serializer=lambda obj: json.dumps(obj, cls=JSONEncoder),
|
||||
**pool_args,
|
||||
)
|
||||
self.sessionmaker = async_sessionmaker(bind=self.engine, expire_on_commit=False)
|
||||
self._initialized = False
|
||||
self._init_lock = asyncio.Lock()
|
||||
self._last_purge = 0.0
|
||||
```
|
||||
|
||||
Notes:
|
||||
- Call `super().__init__` (Redis does; FS doesn't — calling it gives `lock_key`/`log_key`/`lock` attributes).
|
||||
- Single hashable `connection_string` arg keeps the `@lru_cache`'d factory happy.
|
||||
- Owning the engine (rather than borrowing `get_relational_engine()`'s) keeps `close()` safe: `close_cache_engine()` → `adapter.close()` → `engine.dispose()` must not kill the shared relational pool.
|
||||
- Engine-level `json_serializer` with `cognee.modules.storage.utils.JSONEncoder` is load-bearing: without it, asyncpg JSONB inserts containing UUIDs/datetimes fail (graph-adapter gotcha, replicated).
|
||||
- Connection validation is **lazy** (in `_ensure_initialized`), not eager like Redis's `ping()` — the constructor must stay sync and lru_cache-friendly; the contract only requires `CacheConnectionError` to surface, which it does on first use. Also raise a clear `CacheConnectionError("CACHE_BACKEND=postgres requires cognee[postgres]")` if the asyncpg import fails.
|
||||
|
||||
### 4.3 Table DDL (`cache/postgres/tables.py`)
|
||||
|
||||
Private `MetaData()` — **not** the relational declarative `Base`, **not** alembic-managed (graph-adapter precedent: `graph_node`/`graph_edge` are create-on-init while `session_records` is alembic-managed; private MetaData keeps alembic autogenerate from seeing these). Payload columns use `JSONB().with_variant(JSON(), "sqlite")` so unit tests run on aiosqlite. `cache_`-prefixed names avoid collision with `session_records`/`session_model_usage`.
|
||||
|
||||
```sql
|
||||
-- QA entries: one row per entry; qa_id promoted to a column for direct UPDATE
|
||||
-- (Redis buries it in JSON and does linear scan + LSET)
|
||||
CREATE TABLE cache_qa_entries (
|
||||
seq BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, -- insertion order
|
||||
user_id TEXT NOT NULL,
|
||||
session_id TEXT NOT NULL,
|
||||
qa_id TEXT NOT NULL,
|
||||
payload JSONB NOT NULL, -- full SessionQAEntry.model_dump() (incl. qa_id, time)
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
expires_at TIMESTAMPTZ NULL, -- NULL = no expiry
|
||||
UNIQUE (user_id, session_id, qa_id)
|
||||
);
|
||||
CREATE INDEX idx_cache_qa_session ON cache_qa_entries (user_id, session_id, seq);
|
||||
CREATE INDEX idx_cache_qa_expires ON cache_qa_entries (expires_at) WHERE expires_at IS NOT NULL;
|
||||
|
||||
-- Agent traces: append-only
|
||||
CREATE TABLE cache_trace_entries (
|
||||
seq BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
||||
user_id TEXT NOT NULL,
|
||||
session_id TEXT NOT NULL,
|
||||
payload JSONB NOT NULL, -- SessionAgentTraceEntry.model_dump()
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
expires_at TIMESTAMPTZ NULL
|
||||
);
|
||||
CREATE INDEX idx_cache_trace_session ON cache_trace_entries (user_id, session_id, seq);
|
||||
CREATE INDEX idx_cache_trace_expires ON cache_trace_entries (expires_at) WHERE expires_at IS NOT NULL;
|
||||
|
||||
-- Usage logs (Redis key {log_key}:{user_id})
|
||||
CREATE TABLE cache_usage_logs (
|
||||
seq BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
||||
log_key TEXT NOT NULL, -- adapter's self.log_key
|
||||
user_id TEXT NOT NULL,
|
||||
payload JSONB NOT NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
expires_at TIMESTAMPTZ NULL
|
||||
);
|
||||
CREATE INDEX idx_cache_usage ON cache_usage_logs (log_key, user_id, seq);
|
||||
|
||||
-- String KV for small cache values; legacy graph_knowledge:{u}:{s} keys may be deleted by SessionManager
|
||||
CREATE TABLE cache_kv (
|
||||
key TEXT PRIMARY KEY,
|
||||
value TEXT NOT NULL,
|
||||
expires_at TIMESTAMPTZ NULL
|
||||
);
|
||||
```
|
||||
|
||||
Notes:
|
||||
- `session_id` stays a **plain string, no FK** to `session_records` (same `session_id` exists under multiple users; cache rows expire while lifecycle rows persist). Keying is always `(user_id, session_id)` — the exact relational analogue of the Redis key prefixes, which also preserves cross-user reads (recall / sessions router resolve the *owner's* `user_id` from `SessionRecord`).
|
||||
- JSONB, not bytea/pickle: parity with `graph_node.properties` and the Redis JSON-string encoding; queryable for debugging.
|
||||
- Hot-path: `get_latest_qa_entries` runs on every completion (last 10); `idx_cache_qa_session` makes the tail read an index scan. Rows can be tens of KB (payload embeds `context`) — a later `payload - 'context'` projection optimization is possible, but the contract returns full entries today; don't change behavior.
|
||||
|
||||
### 4.4 Method-by-method implementation
|
||||
|
||||
Every public async method: `await self._ensure_initialized()` first (once-flag under `self._init_lock`; runs `conn.run_sync(cache_metadata.create_all, checkfirst=True)`, wraps first-connect failure in `CacheConnectionError`), then `async with self.sessionmaker() as session, session.begin():`. Error contract (pinned by `test_redis_adapter_crud.py`/`test_fs_adapter_crud.py`): backend/SQLAlchemy errors → wrap in `CacheConnectionError`; create-path *validation* failures → also `CacheConnectionError` (odd but tested); update-path validation → `SessionQAEntryValidationError` **propagated unwrapped**.
|
||||
|
||||
| Method | Implementation |
|
||||
|---|---|
|
||||
| `create_qa_entry(user_id, session_id, question, context, answer, qa_id=None, ...)` | `qa_id: str \| None = None` with `str(uuid4())` fallback — match the adapters, not the ABC's `qa_id: str`. Build `SessionQAEntry` (stamps `time=datetime.utcnow().isoformat()`, runs validators; failure → `CacheConnectionError`). `INSERT` `payload=entry.model_dump()`; session-wide TTL refresh (§4.5); scoped lazy purge. One transaction. |
|
||||
| `get_latest_qa_entries(u, s, last_n=5)` | `SELECT payload WHERE u/s AND not-expired ORDER BY seq DESC LIMIT :n`, reverse in Python → chronological; `SessionQAEntry.model_validate` each. **Return `[]` always on empty, including `last_n==1`** — the Redis `None`-on-`last_n==1` quirk is not replicated; all callers go through `SessionManager` and treat falsy uniformly (FS already returns `[]`). Pin in the unit test. |
|
||||
| `get_all_qa_entries(u, s)` | Same, `ORDER BY seq ASC`, no LIMIT; `[]` if none. |
|
||||
| `update_qa_entry(u, s, qa_id, ...)` | One transaction: `SELECT payload ... WHERE user_id/session_id/qa_id ... FOR UPDATE` (`with_for_update()`; no-op on the sqlite test variant, fine). No row → `False`. Merge in Python with exact existing semantics: `None` preserves every field; `memify_metadata = {**existing, **new}` (MERGE not replace — `apply_feedback_weights`/`apply_frequency_weights` idempotency flags depend on it); re-validate via `SessionQAEntry.model_validate`, letting `SessionQAEntryValidationError` propagate; `UPDATE payload`; TTL refresh; `True`. `FOR UPDATE` makes this RMW multi-worker-safe — strictly better than Redis's load/LSET race, observably identical. |
|
||||
| `delete_feedback(u, s, qa_id)` | Same `FOR UPDATE` pattern; set `feedback_text`/`feedback_score` to `None` in payload; TTL refresh; bool. (This is the only way to clear feedback — `update_qa_entry(feedback_score=None)` preserves.) |
|
||||
| `delete_qa_entry(u, s, qa_id)` | Single atomic `DELETE ... WHERE user_id/session_id/qa_id` (replaces Redis's non-atomic DEL+RPUSH-loop rewrite — crash-safe improvement); TTL refresh on remaining rows (Redis re-applies TTL after rewrite); return `rowcount > 0`. No "drop key when empty" step — empty session ≡ zero rows. |
|
||||
| `delete_session(u, s)` | One transaction: `DELETE FROM cache_qa_entries` + `DELETE FROM cache_trace_entries` for `(u, s)`; `True` if either rowcount > 0. (`SessionManager.delete_session` separately deletes the legacy `graph_knowledge:` key via `delete_value` — keep that division for one release.) |
|
||||
| `append_agent_trace_step(u, s, trace_id, origin_function, status, ...)` | Build `SessionAgentTraceEntry` (`method_params or {}`; model validators do sanitization/truncation for free; blank `trace_id`/`origin_function` → `CacheConnectionError`); INSERT; trace-session TTL refresh. |
|
||||
| `get_agent_trace_session(u, s, last_n=None)` | `ORDER BY seq ASC`; when `last_n is not None`, `DESC LIMIT` + reverse. Reads do NOT refresh TTL. |
|
||||
| `get_agent_trace_feedback(u, s, last_n=None)` | `[e.session_feedback for e in await self.get_agent_trace_session(...)]` — exactly the delegation both adapters use. |
|
||||
| `get_agent_trace_count(u, s)` | `SELECT count(*)` with expiry filter; 0 for missing session. |
|
||||
| `prune()` | `DELETE FROM` / `TRUNCATE` the **four cache tables only**. Deliberate, documented divergence from Redis `FLUSHDB` (which nukes co-tenant keys and other users' data) — strictly safer; both proposals agree. |
|
||||
| `close()` | `await self.engine.dispose(close=True)`; dispose the sync lock engine if created (Phase 6); idempotent, swallow + debug-log errors (called by `close_cache_engine` and `prune_data.py`). Reset `self._initialized = False` so a reused instance re-inits. |
|
||||
| `log_usage(user_id, log_entry, ttl=604800)` | INSERT into `cache_usage_logs` with `log_key=self.log_key`, `expires_at = now()+ttl` if ttl else NULL; **also refresh `expires_at` on the user's existing rows** under the same `(log_key, user_id)` — Redis `EXPIRE`s the whole list, so per-row-only TTL would diverge. |
|
||||
| `get_usage_logs(user_id, limit=100)` | `SELECT payload WHERE log_key/user_id AND not-expired ORDER BY seq DESC LIMIT :limit` — already most-recent-first (Redis does lrange + reverse). |
|
||||
| `acquire_lock()` / `release_lock(lock=None)` | **SYNC — do not make async** (Ladybug calls them via `asyncio.to_thread`). **v1: raise `SharedLadybugLockRequiresRedisError`**, imported from `cognee.infrastructure.databases.exceptions.exceptions` directly (it is NOT re-exported in the package `__init__`) — exactly like `FsCacheAdapter`. Inherited `hold_lock()` then raises too — correct. Phase 6 upgrade in §7. |
|
||||
| Inherited (do not reimplement) | `hold_lock()`, `add_qa`, `get_latest_qa`, `get_all_qas`. |
|
||||
|
||||
**Concurrency posture:** unlike the graph adapter, **no global `asyncio.Lock` serializing writes** — row-level `FOR UPDATE` + single-statement deletes give correct multi-worker behavior with better throughput; the graph adapter's lock exists for bulk upsert batches that don't occur here. Add the graph adapter's tenacity retry on asyncpg `DeadlockDetectedError` as belt-and-braces.
|
||||
|
||||
### 4.5 TTL strategy: `expires_at` + read-time filter + lazy purge + throttled sweep
|
||||
|
||||
Replicates Redis sliding whole-key TTL exactly:
|
||||
|
||||
- **Write refresh:** every mutating op runs, inside its transaction, `UPDATE <table> SET expires_at = now() + :ttl WHERE user_id=:u AND session_id=:s` (skipped when `session_ttl_seconds` is `None`/`<= 0` — `expires_at` stays NULL, expiry disabled). Whole-session refresh matches `EXPIRE session_key`. Sessions are small (tens–hundreds of rows); cheap.
|
||||
- **Read filter:** every SELECT adds `AND (expires_at IS NULL OR expires_at > now())`. Reads never refresh TTL (tested Redis behavior). Correctness never depends on purging.
|
||||
- **Purge** ("purge on init only" would leak rows in long-lived processes): (a) scoped `DELETE ... WHERE user_id=:u AND session_id=:s AND expires_at <= now()` opportunistically on writes to that session; (b) a throttled global sweep `DELETE FROM <each table> WHERE expires_at <= now()` at most once per `purge_interval_seconds` (default 900) per process, guarded by `pg_try_advisory_lock` on Postgres (skip the guard on the sqlite test variant) so concurrent workers don't stampede. No external cron. Precedents: `FSCacheAdapter.cache.expire()` on init; `session_lifecycle` computing "abandoned" at read time.
|
||||
- **KV behavior:** string KV values are exact-key values with optional TTL support where the adapter exposes it. No graph-to-session checkpoint keys are written anymore.
|
||||
|
||||
### 4.6 String KV methods
|
||||
|
||||
The old hidden `async_redis` duck-type contract is gone with graph-to-session sync. Implement the formal `CacheDBInterface` string KV methods directly:
|
||||
|
||||
```python
|
||||
async def get_value(self, key: str) -> str | None: ...
|
||||
async def set_value(self, key: str, value: str, ttl: int | None = None) -> None: ...
|
||||
async def delete_value(self, key: str) -> None: ...
|
||||
```
|
||||
|
||||
`get_value` returns `str | None`. `set_value` should upsert by key and set `expires_at` when a TTL is supplied. `delete_value` should be idempotent.
|
||||
|
||||
---
|
||||
|
||||
## 5. Config & provider selection changes
|
||||
|
||||
**`cognee/infrastructure/databases/cache/config.py`:**
|
||||
- `cache_backend: Literal["redis", "fs", "tapes", "postgres"] = "fs"` (default **unchanged**).
|
||||
- New fields: `cache_db_url: Optional[str] = None` (env `CACHE_DB_URL`, e.g. `postgresql+asyncpg://cognee:cognee@localhost:5432/cognee_db`) and `cache_purge_interval_seconds: int = 900`. **Single-URL chosen over five discrete `CACHE_DB_*` fields**: one hashable kwarg through the lru_cache'd factory, one config field instead of five, and it matches the adapter's `connection_string` constructor. Do **not** reuse `cache_host`/`cache_port` — they default to Redis's `localhost:6379` (silent misdirection risk).
|
||||
- Fallback resolution (helper `_resolve_cache_db_url` in `get_cache_engine.py`, mirroring `get_graph_engine.py`'s GRAPH_DATABASE_* → DB_* fallback): `CACHE_DB_URL` if set; else, when `get_relational_config().db_provider == "postgres"`, build `postgresql+asyncpg://DB_USERNAME:DB_PASSWORD@DB_HOST:DB_PORT/DB_NAME` with a warning-level log; else raise `CacheConnectionError("CACHE_BACKEND=postgres requires CACHE_DB_URL or DB_PROVIDER=postgres")`.
|
||||
- Extend `to_dict()` and the class docstring (both pinned by `cognee/tests/unit/infrastructure/databases/cache/test_cache_config.py::test_cache_config_defaults/test_cache_config_to_dict`, which assert the exact full dict — update them).
|
||||
|
||||
**`cognee/infrastructure/databases/cache/get_cache_engine.py`:**
|
||||
- Thread two new hashable params through both signatures (same pattern as the `tapes_*` params): `create_cache_engine(..., cache_db_url: str | None = None, cache_purge_interval_seconds: int = 900)`; pass from `get_cache_engine()`.
|
||||
- New branch with **lazy import** (verified pattern: `TapesCacheAdapter` is imported inside its branch):
|
||||
|
||||
```python
|
||||
elif config.cache_backend == "postgres":
|
||||
from cognee.infrastructure.databases.cache.postgres.PostgresCacheAdapter import (
|
||||
PostgresCacheAdapter,
|
||||
)
|
||||
return PostgresCacheAdapter(
|
||||
connection_string=_resolve_cache_db_url(cache_db_url),
|
||||
lock_key=lock_key,
|
||||
log_key=log_key,
|
||||
session_ttl_seconds=session_ttl_seconds,
|
||||
agentic_lock_expire=agentic_lock_expire,
|
||||
agentic_lock_timeout=agentic_lock_timeout,
|
||||
purge_interval_seconds=cache_purge_interval_seconds,
|
||||
)
|
||||
```
|
||||
|
||||
- Update the `ValueError` message to `"'redis', 'fs', 'tapes', 'postgres'"`.
|
||||
- Move the currently-unconditional `from ...RedisAdapter import RedisAdapter` (verified: executes for ALL backends once caching is on) inside the `== "redis"` branch — 2-line cleanup that removes the accidental reliance on `fakeredis` pulling in `redis`. Low-risk, do it in this PR.
|
||||
- lru_cache caveats respected: `cache_db_url` is a hashable string; constructor params frozen after first call until `cache_clear()` (existing behavior); note the existing pool-per-`lock_key` instantiation pattern (Ladybug per-db lock_key) in the adapter docstring.
|
||||
|
||||
**`pyproject.toml`:** no changes — SQLAlchemy is core; asyncpg/psycopg2 are in the existing `postgres` extra. Document "`CACHE_BACKEND=postgres` requires `cognee[postgres]`".
|
||||
|
||||
---
|
||||
|
||||
## 6. Schema creation / migration approach
|
||||
|
||||
Graph-adapter style, **not alembic**:
|
||||
- Tables on a private `MetaData()` in `cache/postgres/tables.py`; alembic's `env.py` (`target_metadata = Base.metadata`) never sees them; no migration files.
|
||||
- Idempotent `create_all(checkfirst=True)` inside `_ensure_initialized()` (once-flag + `asyncio.Lock`), re-run lazily after `close_cache_engine()`/`prune_system`'s `cache_clear()` recreates the adapter — necessary because the cache factory has no `_GraphEngineHandle` equivalent.
|
||||
- Rationale: cache content is ephemeral/TTL'd, schema is additive, and the repo precedent is explicit (`graph_node`/`graph_edge` create-on-init vs alembic-managed `session_records`).
|
||||
- **No per-dataset database handler** — do not register anything in `supported_dataset_database_handlers.py` or copy `PostgresGraphDatasetDatabaseHandler`. Sessions are per-user, not per-dataset; isolation parity comes from `(user_id, session_id)` columns. Deployments wanting physical separation point `CACHE_DB_URL` at a dedicated database.
|
||||
|
||||
---
|
||||
|
||||
## 7. Session lock handling
|
||||
|
||||
- **`cognee/infrastructure/locks/session_lock.py`: no change.** It is pure in-process asyncio with no Redis dependency; its documented single-worker scope is unchanged. Note in the PR description that the adapter's `FOR UPDATE` in `update_qa_entry`/`delete_feedback` makes those RMW paths multi-worker-safe at the storage layer anyway (closes the gap session_lock.py's own docstring flags).
|
||||
- **`CacheDBInterface.acquire_lock`/`release_lock` (shared Ladybug lock):**
|
||||
- **v1 (core PR):** raise `SharedLadybugLockRequiresRedisError` — established FS precedent; `SHARED_LADYBUG_LOCK=true + CACHE_BACKEND=postgres` stays unsupported with a clear error.
|
||||
- **Phase 6 (separate PR):** lazy-create a small **sync** engine (`postgresql+psycopg2`, `pool_size=2`; psycopg2 is already in the `postgres` extra) used only for locks. `lock_id = int.from_bytes(sha256(self.lock_key.encode()).digest()[:8], "big", signed=True)`. `acquire_lock()`: check out a dedicated connection, loop `SELECT pg_try_advisory_lock(:id)` with 0.1 s sleeps until the `agentic_lock_timeout` deadline; on success return a handle object owning the connection; on timeout raise `RuntimeError` (mirrors Redis). `release_lock(lock=None)`: `pg_advisory_unlock` on the **passed** handle, not `self.lock` (explicitly tested Redis behavior); close/return the connection; swallow errors if not held. Handle-bound connections give `thread_local=False` parity (releasable from worker threads). Semantics note to document: advisory locks release on connection death (safer than, but different from, Redis's 240 s `agentic_lock_expire` auto-expiry, which has no direct equivalent).
|
||||
- Multi-worker `improve()` mutex via `pg_try_advisory_lock` behind `try_acquire_improve_lock`: explicit non-goal / future work.
|
||||
|
||||
---
|
||||
|
||||
## 8. Test plan
|
||||
|
||||
**Unit CRUD** — new `cognee/tests/unit/infrastructure/databases/cache/test_postgres_adapter_crud.py`, mirroring `test_redis_adapter_crud.py`'s ~25 cases. No real Postgres in pytest (repo convention — Redis suites use a hand-rolled `_InMemoryRedisList` fake; here we get a real-engine equivalent for free): construct `PostgresCacheAdapter("sqlite+aiosqlite:///<tmp>/cache.db")` — the `with_variant(JSON(), "sqlite")` columns and identity-PK→autoincrement degradation make the same code paths run without a server. Cover:
|
||||
- QA create/get-latest/get-all ordering; uuid4 `qa_id` fallback; `[]` on empty **including `last_n=1`** (pins the FS-style choice)
|
||||
- update: None-preserves every field; `memify_metadata` MERGE; `SessionQAEntryValidationError` propagates unwrapped; `False` on missing qa_id
|
||||
- `delete_feedback` nulls both fields; `delete_qa_entry` rowcount semantics + TTL survival; `delete_session` clears both tables
|
||||
- traces: append/get/count/feedback delegation; sanitization via model validators; blank `trace_id` → `CacheConnectionError`
|
||||
- TTL: `expires_at` set/refreshed on create/update/delete_feedback/after-delete; NOT refreshed on reads; disabled when `session_ttl_seconds in (0, None)`; expired rows invisible to reads (assert via direct SQL with backdated `expires_at`)
|
||||
- `prune()` clears only the four cache tables; `close()` idempotent; legacy `add_qa`/`get_latest_qa`/`get_all_qas` shims
|
||||
- `acquire_lock`/`release_lock` raise `SharedLadybugLockRequiresRedisError`
|
||||
- KV `get_value`/`set_value`/`delete_value` round-trips, including one legacy `graph_knowledge:{u}:{s}` deletion path through `SessionManager.delete_session`
|
||||
|
||||
**Integration** — add `"postgres"` to the `params=["fs", "redis"]` fixtures in `cognee/tests/integration/infrastructure/session/test_session_sdk_integration.py`, `test_session_persistence_memify_integration.py`, `test_feedback_weights_memify_integration.py` (aiosqlite URL, no server); new `test_session_manager_postgres.py` mirroring `test_session_manager_redis.py` (LLM mocked via `AsyncMock` on `LLMGateway.acreate_structured_output`).
|
||||
|
||||
**Config/factory** — update `test_cache_config.py` exact-dict assertions; new factory tests: `CACHE_BACKEND=postgres` returns `PostgresCacheAdapter`, unknown backend `ValueError` lists all four, URL fallback resolution (CACHE_DB_URL → DB_* → error).
|
||||
|
||||
**CI e2e (real Postgres)** — third twin job `run_conversation_sessions_test_postgres` in `.github/workflows/e2e_tests.yml`, copying `run_conversation_sessions_test_redis` minus the redis service (the pgvector/pg17 service is already provisioned there): env `CACHING=true AUTO_FEEDBACK=true CACHE_BACKEND=postgres DB_PROVIDER=postgres` (relying on the DB_* fallback, which also exercises it) or explicit `CACHE_DB_URL`; extras `"postgres"` only; runs `cognee/tests/test_conversation_history.py` unmodified. Phase 6 adds a `SHARED_LADYBUG_LOCK=true CACHE_BACKEND=postgres` variant of the concurrent-subprocess job running `test_concurrent_subprocess_access.py`, plus real-Postgres-gated advisory-lock unit tests (acquire/release of the *passed* handle, contention timeout → `RuntimeError`, cross-connection mutual exclusion).
|
||||
|
||||
**Regression coverage** — FS/Redis/Postgres tests proving generic string KV round-trips and the legacy `graph_knowledge:` cleanup path work consistently.
|
||||
|
||||
---
|
||||
|
||||
## 9. Rollout & backward compatibility
|
||||
|
||||
- **No behavior change by default:** `cache_backend` default stays `"fs"`; redis/tapes branches untouched; `get_cache_engine()` still returns `None` when caching + usage_logging are off (every consumer already handles `None`).
|
||||
- **No data migration tooling:** session cache is 7-day-TTL ephemeral; switching backends starts fresh — same story as redis↔fs today. One-liner in docs. `SessionRecord` rows in the relational DB are unaffected.
|
||||
- **`forget(everything=True)` / `prune_system` / `prune_data`** paths work unchanged (`prune()`, `close_cache_engine()`, `cache_clear()`); document that Postgres `prune()` is scoped to cognee cache tables (an improvement over `FLUSHDB`).
|
||||
- **Failure modes:** misconfigured backend raises `CacheConnectionError` (503) at first use; `SHARED_LADYBUG_LOCK=true` + postgres raises `SharedLadybugLockRequiresRedisError` with a clear message until Phase 6.
|
||||
- **Docs:** `.env.template` "Session cache settings" block (~line 375): add `# CACHE_BACKEND=postgres` + `# CACHE_DB_URL=postgresql+asyncpg://...`; `config.py` docstring backend list; factory `ValueError` message; `CLAUDE.md` extras note ("postgres — also enables the Postgres session-cache backend"); file a task for the external docs.cognee.ai "sessions-and-caching" page. `docker-compose.yml` needs nothing (postgres service exists; redis stays behind its profile).
|
||||
|
||||
---
|
||||
|
||||
## 10. Phased work breakdown
|
||||
|
||||
| Phase | Scope | Size |
|
||||
|---|---|---|
|
||||
| **P1 — Adapter core** | `cache/postgres/tables.py` + `PostgresCacheAdapter.py`: engine, `_ensure_initialized`, QA CRUD (`FOR UPDATE` updates, atomic deletes), TTL refresh + read filter + scoped/throttled purge, prune, close | **L** (~1.5–2 days, ~450 LOC) |
|
||||
| **P2 — Traces, usage logs, locks-raise, string KV** | `append_agent_trace_step`/trace reads, `log_usage`/`get_usage_logs` (whole-list TTL refresh), lock methods raising `SharedLadybugLockRequiresRedisError`, `get_value`/`set_value`/`delete_value` | **M** (~0.5–1 day, ~150 LOC) |
|
||||
| **P3 — Wiring** | `config.py` Literal + `cache_db_url` + `cache_purge_interval_seconds` + `to_dict` + docstring; `get_cache_engine.py` branch + `_resolve_cache_db_url` fallback + error msg + RedisAdapter import moved into its branch; config-test fixes | **S** (~0.5 day) |
|
||||
| **P4 — Tests** | Unit CRUD suite (aiosqlite), `test_session_manager_postgres.py`, `"postgres"` params in 3 integration files, factory/config tests | **M** (~1 day, ~500 LOC tests) |
|
||||
| **P5 — CI + docs** | `run_conversation_sessions_test_postgres` e2e twin job, `.env.template`, `CLAUDE.md`, docs.cognee.ai task | **S** (~0.5 day) |
|
||||
| **P6 — Follow-up PR: advisory locks** | psycopg2 `pg_try_advisory_lock` sync lock impl lifting the `SHARED_LADYBUG_LOCK` restriction + concurrent-subprocess CI variant | **M** (~1 day) |
|
||||
|
||||
Core (P1–P5): **~4 days**, one reviewable PR (or two: adapter+tests, then wiring+CI). P6 ships separately.
|
||||
|
||||
---
|
||||
|
||||
## 11. Future: Turbopuffer adapter sketch (do not build now — verify the seam)
|
||||
|
||||
Turbopuffer is a namespaced object/vector store with upsert-by-id, delete-by-id, and attribute-filtered queries. The same `CacheDBInterface` maps because every cognee cache access is by exact composite key, append-or-point-update, with no cross-key scans:
|
||||
|
||||
- **Namespaces:** today's key strings verbatim (`agent_sessions:{user_id}:{session_id}`, `agent_traces:{...}`, `usage_logs:{user_id}`) — key-prefix tenancy carries over unchanged.
|
||||
- **Rows:** id = `qa_id` / trace uuid; attributes = entry fields plus a client-stamped monotonic `seq`/`created_at` for ordering (no serial column); vector optional (zero/1-dim placeholder if mandatory — or embed `question+answer` for free semantic recall later, a genuine upside).
|
||||
- **Operations:** create/append → upsert; `get_latest/get_all` → seq-ordered query (tail = desc + limit + reverse); `update_qa_entry`/`delete_feedback` → read-merge-upsert by id (back to Redis-grade RMW races — no `FOR UPDATE`; acceptable for a cache tier, flag in docs); `delete_session` → namespace delete; `prune()` → enumerate + delete `cognee-*` namespaces by prefix; KV → a `cache_kv` namespace with key-as-id rows; TTL → `expires_at` attribute + query filter + periodic GC (no native TTL — the Postgres TTL design transfers directly); locks → raise `SharedLadybugLockRequiresRedisError` (precedent).
|
||||
- **Seam requirements this plan satisfies:** (1) all storage details stay behind `CacheDBInterface`; no caller touches adapter internals; (2) entries cross the boundary only as pydantic `model_dump()` payloads; (3) ordering is adapter-internal (`seq` column vs `seq` attribute) — nothing leaks; do not let SQL row ids escape into return values during P2; (4) wiring is mechanical: `cache_backend` Literal += `"turbopuffer"`, lazy-import elif, `TURBOPUFFER_API_KEY`/`TURBOPUFFER_REGION` threaded through the lru_cache'd factory.
|
||||
|
||||
---
|
||||
|
||||
## 12. Open questions
|
||||
|
||||
1. **Default fallback to the relational DB:** when `CACHE_DB_URL` is unset and `DB_PROVIDER=postgres`, the cache silently shares the relational database (distinct `cache_*` tables, warning logged). Is co-tenancy acceptable as the default, or should `CACHE_DB_URL` be mandatory?
|
||||
2. **Normalize the Redis `None`-on-`last_n==1` quirk in `RedisAdapter` itself** (return `[]` like FS/Postgres), or leave Redis as-is and only document Postgres's `[]` choice? (Some tests pin the Redis behavior.)
|
||||
3. **Hot-path payload size:** should `get_latest_qa_entries` eventually project `payload - 'context'` for history reads (formatted history uses `include_context=False` but still fetches full entries)? Behavior-preserving today; revisit with real latency data.
|
||||
4. **Throttled global purge tuning:** is 900 s / per-process advisory-lock-guarded sweep enough for high-volume deployments, or is a documented external cron (`DELETE ... WHERE expires_at <= now()`) preferable at scale?
|
||||
5. **`fakeredis[lua]` core dependency:** verified unused in-repo and only load-bearing because it transitively installs `redis` for the unconditional import this plan removes — candidate for deletion in a separate cleanup PR (needs a check that no downstream consumers rely on it).
|
||||
6. **Lock auto-expiry parity (Phase 6):** Redis locks auto-expire after `agentic_lock_expire=240` s; pg advisory locks hold until connection death. Is connection-scoped release acceptable, or do we need a watchdog that closes the lock connection after 240 s?
|
||||
|
After Width: | Height: | Size: 3.2 MiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 446 KiB |
|
After Width: | Height: | Size: 88 KiB |
|
After Width: | Height: | Size: 878 KiB |
|
After Width: | Height: | Size: 936 KiB |
|
After Width: | Height: | Size: 109 KiB |
|
After Width: | Height: | Size: 569 KiB |
|
After Width: | Height: | Size: 4.2 MiB |