Merge branch 'feature/cog-3532-empower-test_search-db-retrievers-tests-reorg-3' into feature/cog-3532-empower-test_search-db-retrievers-tests-reorg-4
This commit is contained in:
commit
757d5fca65
13 changed files with 4096 additions and 3767 deletions
|
|
@ -91,6 +91,15 @@ DB_NAME=cognee_db
|
|||
#DB_USERNAME=cognee
|
||||
#DB_PASSWORD=cognee
|
||||
|
||||
# -- Advanced: Custom database connection arguments (optional) ---------------
|
||||
# Pass additional connection parameters as JSON. Useful for SSL, timeouts, etc.
|
||||
# Examples:
|
||||
# For PostgreSQL with SSL:
|
||||
# DATABASE_CONNECT_ARGS='{"sslmode": "require", "connect_timeout": 10}'
|
||||
# For SQLite with custom timeout:
|
||||
# DATABASE_CONNECT_ARGS='{"timeout": 60}'
|
||||
#DATABASE_CONNECT_ARGS='{}'
|
||||
|
||||
################################################################################
|
||||
# 🕸️ Graph Database settings
|
||||
################################################################################
|
||||
|
|
|
|||
61
.github/workflows/examples_tests.yml
vendored
61
.github/workflows/examples_tests.yml
vendored
|
|
@ -257,7 +257,7 @@ jobs:
|
|||
with:
|
||||
python-version: '3.11.x'
|
||||
|
||||
- name: Run Memify Tests
|
||||
- name: Run Permissions Example
|
||||
env:
|
||||
ENV: 'dev'
|
||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
|
|
@ -270,6 +270,65 @@ jobs:
|
|||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
EMBEDDING_API_VERSION: ${{ secrets.EMBEDDING_API_VERSION }}
|
||||
run: uv run python ./examples/python/permissions_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
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
services:
|
||||
postgres: # Using postgres to avoid storing and using SQLite from S3
|
||||
image: pgvector/pgvector:pg17
|
||||
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@v4
|
||||
|
||||
- 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_API_VERSION: ${{ secrets.LLM_API_VERSION }}
|
||||
EMBEDDING_MODEL: ${{ secrets.EMBEDDING_MODEL }}
|
||||
EMBEDDING_ENDPOINT: ${{ secrets.EMBEDDING_ENDPOINT }}
|
||||
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
|
||||
EMBEDDING_API_VERSION: ${{ secrets.EMBEDDING_API_VERSION }}
|
||||
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: '127.0.0.1'
|
||||
DB_PORT: 5432
|
||||
DB_USERNAME: cognee
|
||||
DB_PASSWORD: cognee
|
||||
run: uv run python ./examples/python/permissions_example.py
|
||||
|
||||
test_docling_add:
|
||||
name: Run Add with Docling Test
|
||||
runs-on: macos-15
|
||||
|
|
|
|||
32
.github/workflows/release.yml
vendored
32
.github/workflows/release.yml
vendored
|
|
@ -10,10 +10,6 @@ on:
|
|||
- dev
|
||||
- main
|
||||
description: Dev or Main release
|
||||
test_mode:
|
||||
required: true
|
||||
type: boolean
|
||||
description: Aka Dry Run. If true, it won't affect public indices or repositories
|
||||
|
||||
jobs:
|
||||
release-github:
|
||||
|
|
@ -35,8 +31,6 @@ jobs:
|
|||
|
||||
- name: Create and push git tag
|
||||
id: create_tag
|
||||
env:
|
||||
TEST_MODE: ${{ inputs.test_mode }}
|
||||
run: |
|
||||
VERSION="$(uv version --short)"
|
||||
TAG="v${VERSION}"
|
||||
|
|
@ -48,13 +42,10 @@ jobs:
|
|||
|
||||
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
|
||||
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
if [ "$TEST_MODE" = "false" ]; then
|
||||
git tag "${TAG}"
|
||||
git push origin "${TAG}"
|
||||
else
|
||||
echo "Test mode is enabled. Skipping tag creation and push."
|
||||
fi
|
||||
|
||||
git tag "${TAG}"
|
||||
git push origin "${TAG}"
|
||||
|
||||
|
||||
- name: Create GitHub Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
|
|
@ -89,14 +80,7 @@ jobs:
|
|||
- name: Build distributions
|
||||
run: uv build
|
||||
|
||||
- name: Publish ${{ inputs.flavour }} release to TestPyPI
|
||||
if: ${{ inputs.test_mode }}
|
||||
env:
|
||||
UV_PUBLISH_TOKEN: ${{ secrets.TEST_PYPI_TOKEN }}
|
||||
run: uv publish --publish-url https://test.pypi.org/legacy/
|
||||
|
||||
- name: Publish ${{ inputs.flavour }} release to PyPI
|
||||
if: ${{ !inputs.test_mode }}
|
||||
env:
|
||||
UV_PUBLISH_TOKEN: ${{ secrets.PYPI_TOKEN }}
|
||||
run: uv publish
|
||||
|
|
@ -121,15 +105,15 @@ jobs:
|
|||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Build and push Dev Docker Image
|
||||
if: ${{ inputs.flavour == 'dev' }}
|
||||
if: ${{ inputs.flavour == 'dev' }}
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: ${{ !inputs.test_mode }}
|
||||
push: true
|
||||
tags: cognee/cognee:${{ needs.release-github.outputs.version }}
|
||||
labels: |
|
||||
version=${{ needs.release-github.outputs.version }}
|
||||
|
|
@ -143,7 +127,7 @@ jobs:
|
|||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: ${{ !inputs.test_mode }}
|
||||
push: true
|
||||
tags: |
|
||||
cognee/cognee:${{ needs.release-github.outputs.version }}
|
||||
cognee/cognee:latest
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[project]
|
||||
name = "cognee-mcp"
|
||||
version = "0.4.0"
|
||||
version = "0.5.0"
|
||||
description = "Cognee MCP server"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.10"
|
||||
|
|
@ -9,7 +9,7 @@ dependencies = [
|
|||
# For local cognee repo usage remove comment bellow and add absolute path to cognee. Then run `uv sync --reinstall` in the mcp folder on local cognee changes.
|
||||
#"cognee[postgres,codegraph,gemini,huggingface,docs,neo4j] @ file:/Users/igorilic/Desktop/cognee",
|
||||
# TODO: Remove gemini from optional dependecnies for new Cognee version after 0.3.4
|
||||
"cognee[postgres,docs,neo4j]==0.3.7",
|
||||
"cognee[postgres,docs,neo4j]==0.5.0",
|
||||
"fastmcp>=2.10.0,<3.0.0",
|
||||
"mcp>=1.12.0,<2.0.0",
|
||||
"uv>=0.6.3,<1.0.0",
|
||||
|
|
|
|||
|
|
@ -627,8 +627,7 @@ class TestModel:
|
|||
print(f"Failed: {failed}")
|
||||
print(f"Success Rate: {(passed / total_tests * 100):.1f}%")
|
||||
|
||||
if failed > 0:
|
||||
print(f"\n ⚠️ {failed} test(s) failed - review results above for details")
|
||||
assert failed == 0, f"\n ⚠️ {failed} test(s) failed - review results above for details"
|
||||
|
||||
|
||||
async def main():
|
||||
|
|
|
|||
7633
cognee-mcp/uv.lock
generated
7633
cognee-mcp/uv.lock
generated
File diff suppressed because it is too large
Load diff
|
|
@ -90,6 +90,7 @@ def get_memify_router() -> APIRouter:
|
|||
dataset=payload.dataset_id if payload.dataset_id else payload.dataset_name,
|
||||
node_name=payload.node_name,
|
||||
user=user,
|
||||
run_in_background=payload.run_in_background,
|
||||
)
|
||||
|
||||
if isinstance(memify_run, PipelineRunErrored):
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import os
|
||||
import json
|
||||
import pydantic
|
||||
from typing import Union
|
||||
from functools import lru_cache
|
||||
|
|
@ -19,6 +20,7 @@ class RelationalConfig(BaseSettings):
|
|||
db_username: Union[str, None] = None # "cognee"
|
||||
db_password: Union[str, None] = None # "cognee"
|
||||
db_provider: str = "sqlite"
|
||||
database_connect_args: Union[str, None] = None
|
||||
|
||||
model_config = SettingsConfigDict(env_file=".env", extra="allow")
|
||||
|
||||
|
|
@ -30,6 +32,17 @@ class RelationalConfig(BaseSettings):
|
|||
databases_directory_path = os.path.join(base_config.system_root_directory, "databases")
|
||||
self.db_path = databases_directory_path
|
||||
|
||||
# Parse database_connect_args if provided as JSON string
|
||||
if self.database_connect_args and isinstance(self.database_connect_args, str):
|
||||
try:
|
||||
parsed_args = json.loads(self.database_connect_args)
|
||||
if isinstance(parsed_args, dict):
|
||||
self.database_connect_args = parsed_args
|
||||
else:
|
||||
self.database_connect_args = {}
|
||||
except json.JSONDecodeError:
|
||||
self.database_connect_args = {}
|
||||
|
||||
return self
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
|
|
@ -40,7 +53,8 @@ class RelationalConfig(BaseSettings):
|
|||
--------
|
||||
|
||||
- dict: A dictionary containing database configuration settings including db_path,
|
||||
db_name, db_host, db_port, db_username, db_password, and db_provider.
|
||||
db_name, db_host, db_port, db_username, db_password, db_provider, and
|
||||
database_connect_args.
|
||||
"""
|
||||
return {
|
||||
"db_path": self.db_path,
|
||||
|
|
@ -50,6 +64,7 @@ class RelationalConfig(BaseSettings):
|
|||
"db_username": self.db_username,
|
||||
"db_password": self.db_password,
|
||||
"db_provider": self.db_provider,
|
||||
"database_connect_args": self.database_connect_args,
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ def create_relational_engine(
|
|||
db_username: str,
|
||||
db_password: str,
|
||||
db_provider: str,
|
||||
database_connect_args: dict = None,
|
||||
):
|
||||
"""
|
||||
Create a relational database engine based on the specified parameters.
|
||||
|
|
@ -29,6 +30,7 @@ def create_relational_engine(
|
|||
- db_password (str): The password for database authentication, required for
|
||||
PostgreSQL.
|
||||
- db_provider (str): The type of database provider (e.g., 'sqlite' or 'postgres').
|
||||
- database_connect_args (dict, optional): Database driver connection arguments.
|
||||
|
||||
Returns:
|
||||
--------
|
||||
|
|
@ -51,4 +53,4 @@ def create_relational_engine(
|
|||
"PostgreSQL dependencies are not installed. Please install with 'pip install cognee\"[postgres]\"' or 'pip install cognee\"[postgres-binary]\"' to use PostgreSQL functionality."
|
||||
)
|
||||
|
||||
return SQLAlchemyAdapter(connection_string)
|
||||
return SQLAlchemyAdapter(connection_string, connect_args=database_connect_args)
|
||||
|
|
|
|||
|
|
@ -29,10 +29,31 @@ class SQLAlchemyAdapter:
|
|||
functions.
|
||||
"""
|
||||
|
||||
def __init__(self, connection_string: str):
|
||||
def __init__(self, connection_string: str, connect_args: dict = None):
|
||||
"""
|
||||
Initialize the SQLAlchemy adapter with connection settings.
|
||||
|
||||
Parameters:
|
||||
-----------
|
||||
connection_string (str): The database connection string (e.g., 'sqlite:///path/to/db'
|
||||
or 'postgresql://user:pass@host:port/db').
|
||||
connect_args (dict, optional): Database driver connection arguments.
|
||||
Configuration is loaded from RelationalConfig.database_connect_args, which reads
|
||||
from the DATABASE_CONNECT_ARGS environment variable.
|
||||
|
||||
Examples:
|
||||
PostgreSQL with SSL:
|
||||
DATABASE_CONNECT_ARGS='{"sslmode": "require", "connect_timeout": 10}'
|
||||
|
||||
SQLite with custom timeout:
|
||||
DATABASE_CONNECT_ARGS='{"timeout": 60}'
|
||||
"""
|
||||
self.db_path: str = None
|
||||
self.db_uri: str = connection_string
|
||||
|
||||
# Use provided connect_args (already parsed from config)
|
||||
final_connect_args = connect_args or {}
|
||||
|
||||
if "sqlite" in connection_string:
|
||||
[prefix, db_path] = connection_string.split("///")
|
||||
self.db_path = db_path
|
||||
|
|
@ -53,7 +74,7 @@ class SQLAlchemyAdapter:
|
|||
self.engine = create_async_engine(
|
||||
connection_string,
|
||||
poolclass=NullPool,
|
||||
connect_args={"timeout": 30},
|
||||
connect_args={**{"timeout": 30}, **final_connect_args},
|
||||
)
|
||||
else:
|
||||
self.engine = create_async_engine(
|
||||
|
|
@ -63,6 +84,7 @@ class SQLAlchemyAdapter:
|
|||
pool_recycle=280,
|
||||
pool_pre_ping=True,
|
||||
pool_timeout=280,
|
||||
connect_args=final_connect_args,
|
||||
)
|
||||
|
||||
self.sessionmaker = async_sessionmaker(bind=self.engine, expire_on_commit=False)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,69 @@
|
|||
import os
|
||||
from unittest.mock import patch
|
||||
from cognee.infrastructure.databases.relational.config import RelationalConfig
|
||||
|
||||
|
||||
class TestRelationalConfig:
|
||||
"""Test suite for RelationalConfig DATABASE_CONNECT_ARGS parsing."""
|
||||
|
||||
def test_database_connect_args_valid_json_dict(self):
|
||||
"""Test that DATABASE_CONNECT_ARGS is parsed correctly when it's a valid JSON dict."""
|
||||
with patch.dict(
|
||||
os.environ, {"DATABASE_CONNECT_ARGS": '{"timeout": 60, "sslmode": "require"}'}
|
||||
):
|
||||
config = RelationalConfig()
|
||||
assert config.database_connect_args == {"timeout": 60, "sslmode": "require"}
|
||||
|
||||
def test_database_connect_args_empty_string(self):
|
||||
"""Test that empty DATABASE_CONNECT_ARGS is handled correctly."""
|
||||
with patch.dict(os.environ, {"DATABASE_CONNECT_ARGS": ""}):
|
||||
config = RelationalConfig()
|
||||
assert config.database_connect_args == ""
|
||||
|
||||
def test_database_connect_args_not_set(self):
|
||||
"""Test that missing DATABASE_CONNECT_ARGS results in None."""
|
||||
with patch.dict(os.environ, {}, clear=True):
|
||||
config = RelationalConfig()
|
||||
assert config.database_connect_args is None
|
||||
|
||||
def test_database_connect_args_invalid_json(self):
|
||||
"""Test that invalid JSON in DATABASE_CONNECT_ARGS results in empty dict."""
|
||||
with patch.dict(os.environ, {"DATABASE_CONNECT_ARGS": '{"timeout": 60'}): # Invalid JSON
|
||||
config = RelationalConfig()
|
||||
assert config.database_connect_args == {}
|
||||
|
||||
def test_database_connect_args_non_dict_json(self):
|
||||
"""Test that non-dict JSON in DATABASE_CONNECT_ARGS results in empty dict."""
|
||||
with patch.dict(os.environ, {"DATABASE_CONNECT_ARGS": '["list", "instead", "of", "dict"]'}):
|
||||
config = RelationalConfig()
|
||||
assert config.database_connect_args == {}
|
||||
|
||||
def test_database_connect_args_to_dict(self):
|
||||
"""Test that database_connect_args is included in to_dict() output."""
|
||||
with patch.dict(os.environ, {"DATABASE_CONNECT_ARGS": '{"timeout": 60}'}):
|
||||
config = RelationalConfig()
|
||||
config_dict = config.to_dict()
|
||||
assert "database_connect_args" in config_dict
|
||||
assert config_dict["database_connect_args"] == {"timeout": 60}
|
||||
|
||||
def test_database_connect_args_integer_value(self):
|
||||
"""Test that DATABASE_CONNECT_ARGS with integer values is parsed correctly."""
|
||||
with patch.dict(os.environ, {"DATABASE_CONNECT_ARGS": '{"connect_timeout": 10}'}):
|
||||
config = RelationalConfig()
|
||||
assert config.database_connect_args == {"connect_timeout": 10}
|
||||
|
||||
def test_database_connect_args_mixed_types(self):
|
||||
"""Test that DATABASE_CONNECT_ARGS with mixed value types is parsed correctly."""
|
||||
with patch.dict(
|
||||
os.environ,
|
||||
{
|
||||
"DATABASE_CONNECT_ARGS": '{"timeout": 60, "sslmode": "require", "retries": 3, "keepalive": true}'
|
||||
},
|
||||
):
|
||||
config = RelationalConfig()
|
||||
assert config.database_connect_args == {
|
||||
"timeout": 60,
|
||||
"sslmode": "require",
|
||||
"retries": 3,
|
||||
"keepalive": True,
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
[project]
|
||||
name = "cognee"
|
||||
|
||||
version = "0.5.0.dev1"
|
||||
version = "0.5.0"
|
||||
description = "Cognee - is a library for enriching LLM context with a semantic layer for better understanding and reasoning."
|
||||
authors = [
|
||||
{ name = "Vasilije Markovic" },
|
||||
|
|
|
|||
2
uv.lock
generated
2
uv.lock
generated
|
|
@ -946,7 +946,7 @@ wheels = [
|
|||
|
||||
[[package]]
|
||||
name = "cognee"
|
||||
version = "0.5.0.dev1"
|
||||
version = "0.5.0"
|
||||
source = { editable = "." }
|
||||
dependencies = [
|
||||
{ name = "aiofiles" },
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue