Merge branch 'dev' into move_to_gpt5

This commit is contained in:
Vasilije 2025-08-17 12:20:57 +02:00 committed by GitHub
commit c4ec6799a6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
93 changed files with 794 additions and 1410 deletions

View file

@ -1,11 +1,15 @@
name: cognee-setup
description: "Sets up Python, installs Poetry, loads venv from cache, and installs dependencies for Cognee."
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: ""
runs:
using: "composite"
@ -16,18 +20,25 @@ runs:
with:
python-version: ${{ inputs.python-version }}
- name: Install Poetry
- name: Install uv
uses: astral-sh/setup-uv@v4
with:
enable-cache: true
- name: Rebuild uv lockfile
shell: bash
run: |
python -m pip install --upgrade pip
pip install poetry
- name: Rebuild Poetry lock file
shell: bash
run: |
rm poetry.lock
poetry lock
rm uv.lock
uv lock
- name: Install dependencies
shell: bash
run: poetry install --no-interaction -E api -E docs -E evals -E gemini -E codegraph -E ollama -E dev -E neo4j
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 gemini --extra codegraph --extra ollama --extra dev --extra neo4j $EXTRA_ARGS

67
.github/actions/setup_neo4j/action.yml vendored Normal file
View file

@ -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!"

View file

@ -98,7 +98,7 @@ jobs:
python-version: ${{ inputs.python-version }}
- name: Run Unit Tests
run: poetry run pytest cognee/tests/unit/
run: uv run pytest cognee/tests/unit/
integration-tests:
name: Run Integration Tests
@ -115,7 +115,7 @@ jobs:
python-version: ${{ inputs.python-version }}
- name: Run Integration Tests
run: poetry run pytest cognee/tests/integration/
run: uv run pytest cognee/tests/integration/
simple-examples:
name: Run Simple Examples
@ -144,7 +144,7 @@ jobs:
python-version: ${{ inputs.python-version }}
- name: Run Simple Examples
run: poetry run python ./examples/python/simple_example.py
run: uv run python ./examples/python/simple_example.py
simple-examples-baml:
name: Run Simple Examples BAML
@ -180,7 +180,7 @@ jobs:
python-version: ${{ inputs.python-version }}
- name: Run Simple Examples
run: poetry run python ./examples/python/simple_example.py
run: uv run python ./examples/python/simple_example.py
graph-tests:
name: Run Basic Graph Tests
@ -209,4 +209,4 @@ jobs:
python-version: ${{ inputs.python-version }}
- name: Run Graph Tests
run: poetry run python ./examples/python/code_graph_example.py --repo_path ./cognee/tasks/graph
run: uv run python ./examples/python/code_graph_example.py --repo_path ./cognee/tasks/graph

View file

@ -54,10 +54,6 @@ jobs:
with:
python-version: ${{ inputs.python-version }}
- name: Install Neo4j extra
run: |
poetry install -E neo4j
- name: Run Neo4j Example
env:
ENV: dev
@ -74,7 +70,7 @@ jobs:
GRAPH_DATABASE_USERNAME: "neo4j"
GRAPH_DATABASE_PASSWORD: ${{ secrets.NEO4J_API_KEY }}
run: |
poetry run python examples/database_examples/neo4j_example.py
uv run python examples/database_examples/neo4j_example.py
run-db-example-kuzu:
name: "Kuzu DB Example Test"
@ -90,9 +86,8 @@ jobs:
with:
python-version: ${{ inputs.python-version }}
- name: Install Kuzu extra
run: |
poetry install
- name: Dependencies already installed
run: echo "Dependencies already installed in setup"
- name: Run Kuzu Example
env:
@ -107,7 +102,7 @@ jobs:
EMBEDDING_API_VERSION: ${{ secrets.EMBEDDING_API_VERSION }}
GRAPH_DATABASE_PROVIDER: "kuzu"
run: |
poetry run python examples/database_examples/kuzu_example.py
uv run python examples/database_examples/kuzu_example.py
run-db-example-pgvector:
name: "PostgreSQL PGVector DB Example Test"
@ -138,10 +133,7 @@ jobs:
uses: ./.github/actions/cognee_setup
with:
python-version: ${{ inputs.python-version }}
- name: Install PGVector extra
run: |
poetry install -E postgres
extra-dependencies: "postgres"
- name: Run PGVector Example
env:
@ -155,4 +147,4 @@ jobs:
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
EMBEDDING_API_VERSION: ${{ secrets.EMBEDDING_API_VERSION }}
run: |
poetry run python examples/database_examples/pgvector_example.py
uv run python examples/database_examples/pgvector_example.py

View file

@ -57,7 +57,7 @@ jobs:
EMBEDDING_ENDPOINT: ${{ secrets.EMBEDDING_ENDPOINT }}
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
EMBEDDING_API_VERSION: ${{ secrets.EMBEDDING_API_VERSION }}
run: poetry run python ./cognee/tests/test_cognee_server_start.py
run: uv run python ./cognee/tests/test_cognee_server_start.py
run-telemetry-test:
name: Run Telemetry Test
@ -81,7 +81,7 @@ jobs:
EMBEDDING_ENDPOINT: ${{ secrets.EMBEDDING_ENDPOINT }}
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
EMBEDDING_API_VERSION: ${{ secrets.EMBEDDING_API_VERSION }}
run: poetry run python ./cognee/tests/test_telemetry.py
run: uv run python ./cognee/tests/test_telemetry.py
run-telemetry-pipeline-test:
name: Run Telemetry Pipeline Test
@ -110,7 +110,7 @@ jobs:
EMBEDDING_ENDPOINT: ${{ secrets.EMBEDDING_ENDPOINT }}
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
EMBEDDING_API_VERSION: ${{ secrets.EMBEDDING_API_VERSION }}
run: poetry run python ./cognee/tests/test_library.py
run: uv run python ./cognee/tests/test_library.py
run-deduplication-test:
name: Deduplication Test
@ -140,10 +140,7 @@ jobs:
uses: ./.github/actions/cognee_setup
with:
python-version: '3.11.x'
- name: Install specific db dependency
run: |
poetry install -E postgres
extra-dependencies: "postgres"
- name: Run Deduplication Example
env:
@ -154,7 +151,7 @@ jobs:
EMBEDDING_ENDPOINT: ${{ secrets.EMBEDDING_ENDPOINT }}
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
EMBEDDING_API_VERSION: ${{ secrets.EMBEDDING_API_VERSION }}
run: poetry run python ./cognee/tests/test_deduplication.py
run: uv run python ./cognee/tests/test_deduplication.py
run-deletion-test:
name: Deletion Test
@ -179,7 +176,7 @@ jobs:
EMBEDDING_ENDPOINT: ${{ secrets.EMBEDDING_ENDPOINT }}
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
EMBEDDING_API_VERSION: ${{ secrets.EMBEDDING_API_VERSION }}
run: poetry run python ./cognee/tests/test_deletion.py
run: uv run python ./cognee/tests/test_deletion.py
run-s3-bucket-test:
name: S3 Bucket Test
@ -192,10 +189,10 @@ jobs:
uses: ./.github/actions/cognee_setup
with:
python-version: '3.11.x'
extra-dependencies: "aws"
- name: Install specific S3 dependency
run: |
poetry install -E aws
- name: Dependencies already installed
run: echo "Dependencies already installed in setup"
- name: Run S3 Bucket Test
env:
@ -210,7 +207,7 @@ jobs:
EMBEDDING_API_VERSION: ${{ secrets.EMBEDDING_API_VERSION }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
run: poetry run python ./cognee/tests/test_s3.py
run: uv run python ./cognee/tests/test_s3.py
test-parallel-databases:
name: Test using different async databases in parallel in Cognee
@ -224,9 +221,8 @@ jobs:
with:
python-version: '3.11.x'
- name: Install specific graph db dependency
run: |
poetry install
- name: Dependencies already installed
run: echo "Dependencies already installed in setup"
- name: Run parallel databases test
env:
@ -239,7 +235,7 @@ jobs:
EMBEDDING_ENDPOINT: ${{ secrets.EMBEDDING_ENDPOINT }}
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
EMBEDDING_API_VERSION: ${{ secrets.EMBEDDING_API_VERSION }}
run: poetry run python ./cognee/tests/test_parallel_databases.py
run: uv run python ./cognee/tests/test_parallel_databases.py
test-permissions:
name: Test permissions with different situations in Cognee
@ -253,9 +249,8 @@ jobs:
with:
python-version: '3.11.x'
- name: Install specific graph db dependency
run: |
poetry install
- name: Dependencies already installed
run: echo "Dependencies already installed in setup"
- name: Run parallel databases test
env:
@ -268,7 +263,7 @@ jobs:
EMBEDDING_ENDPOINT: ${{ secrets.EMBEDDING_ENDPOINT }}
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
EMBEDDING_API_VERSION: ${{ secrets.EMBEDDING_API_VERSION }}
run: poetry run python ./cognee/tests/test_permissions.py
run: uv run python ./cognee/tests/test_permissions.py
test-graph-edges:
name: Test graph edge ingestion
@ -282,9 +277,8 @@ jobs:
with:
python-version: '3.11.x'
- name: Install specific graph db dependency
run: |
poetry install
- name: Dependencies already installed
run: echo "Dependencies already installed in setup"
- name: Run graph edges test
env:
@ -297,4 +291,4 @@ jobs:
EMBEDDING_ENDPOINT: ${{ secrets.EMBEDDING_ENDPOINT }}
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
EMBEDDING_API_VERSION: ${{ secrets.EMBEDDING_API_VERSION }}
run: poetry run python ./cognee/tests/test_edge_ingestion.py
run: uv run python ./cognee/tests/test_edge_ingestion.py

View file

@ -20,7 +20,7 @@ jobs:
env:
LLM_API_KEY: ${{ secrets.OPENAI_API_KEY }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
run: poetry run python ./examples/python/multimedia_example.py
run: uv run python ./examples/python/multimedia_example.py
test-eval-example:
name: Run Eval Example
@ -33,10 +33,7 @@ jobs:
uses: ./.github/actions/cognee_setup
with:
python-version: '3.11.x'
- name: Install specific eval dependency
run: |
poetry install -E deepeval
extra-dependencies: "deepeval"
- name: Run Evaluation Framework Example
env:
@ -49,7 +46,7 @@ jobs:
EMBEDDING_ENDPOINT: ${{ secrets.EMBEDDING_ENDPOINT }}
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
EMBEDDING_API_VERSION: ${{ secrets.EMBEDDING_API_VERSION }}
run: poetry run python ./cognee/eval_framework/run_eval.py
run: uv run python ./cognee/eval_framework/run_eval.py
test-descriptive-metrics:
name: Run Descriptive Metrics Example
@ -63,6 +60,10 @@ jobs:
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:
LLM_MODEL: ${{ secrets.LLM_MODEL }}
@ -74,7 +75,11 @@ jobs:
EMBEDDING_ENDPOINT: ${{ secrets.EMBEDDING_ENDPOINT }}
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
EMBEDDING_API_VERSION: ${{ secrets.EMBEDDING_API_VERSION }}
run: poetry run python ./cognee/tests/tasks/descriptive_metrics/networkx_metrics_test.py
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-dynamic-steps-metrics:
@ -100,4 +105,4 @@ jobs:
EMBEDDING_ENDPOINT: ${{ secrets.EMBEDDING_ENDPOINT }}
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
EMBEDDING_API_VERSION: ${{ secrets.EMBEDDING_API_VERSION }}
run: poetry run python ./examples/python/dynamic_steps_example.py
run: uv run python ./examples/python/dynamic_steps_example.py

View file

@ -28,9 +28,8 @@ jobs:
with:
python-version: ${{ inputs.python-version }}
- name: Install specific db dependency
run: |
poetry install
- name: Dependencies already installed
run: echo "Dependencies already installed in setup"
- name: Run Kuzu Tests
env:
@ -43,7 +42,7 @@ jobs:
EMBEDDING_ENDPOINT: ${{ secrets.EMBEDDING_ENDPOINT }}
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
EMBEDDING_API_VERSION: ${{ secrets.EMBEDDING_API_VERSION }}
run: poetry run python ./cognee/tests/test_kuzu.py
run: uv run python ./cognee/tests/test_kuzu.py
- name: Run Weighted Edges Tests with Kuzu
env:
@ -57,7 +56,7 @@ jobs:
EMBEDDING_ENDPOINT: ${{ secrets.EMBEDDING_ENDPOINT }}
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
EMBEDDING_API_VERSION: ${{ secrets.EMBEDDING_API_VERSION }}
run: poetry run pytest cognee/tests/unit/interfaces/graph/test_weighted_edges.py -v
run: uv run pytest cognee/tests/unit/interfaces/graph/test_weighted_edges.py -v
run-neo4j-tests:
name: Neo4j Tests
@ -72,10 +71,6 @@ jobs:
with:
python-version: ${{ inputs.python-version }}
- name: Install specific db dependency
run: |
poetry install -E neo4j
- name: Run default Neo4j
env:
ENV: 'dev'
@ -91,7 +86,7 @@ jobs:
GRAPH_DATABASE_URL: ${{ secrets.NEO4J_API_URL }}
GRAPH_DATABASE_PASSWORD: ${{ secrets.NEO4J_API_KEY }}
GRAPH_DATABASE_USERNAME: "neo4j"
run: poetry run python ./cognee/tests/test_neo4j.py
run: uv run python ./cognee/tests/test_neo4j.py
- name: Run Weighted Edges Tests with Neo4j
env:
@ -108,4 +103,4 @@ jobs:
EMBEDDING_ENDPOINT: ${{ secrets.EMBEDDING_ENDPOINT }}
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
EMBEDDING_API_VERSION: ${{ secrets.EMBEDDING_API_VERSION }}
run: poetry run pytest cognee/tests/unit/interfaces/graph/test_weighted_edges.py -v
run: uv run pytest cognee/tests/unit/interfaces/graph/test_weighted_edges.py -v

View file

@ -55,7 +55,7 @@ jobs:
- name: Run unit tests
shell: bash
run: poetry run pytest cognee/tests/unit/
run: uv run pytest cognee/tests/unit/
env:
PYTHONUTF8: 1
LLM_PROVIDER: openai
@ -73,7 +73,7 @@ jobs:
- name: Run integration tests
if: ${{ !contains(matrix.os, 'windows') }}
shell: bash
run: poetry run pytest cognee/tests/integration/
run: uv run pytest cognee/tests/integration/
env:
PYTHONUTF8: 1
LLM_PROVIDER: openai
@ -103,11 +103,11 @@ jobs:
EMBEDDING_ENDPOINT: ${{ secrets.EMBEDDING_ENDPOINT }}
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
EMBEDDING_API_VERSION: ${{ secrets.EMBEDDING_API_VERSION }}
run: poetry run python ./cognee/tests/test_library.py
run: uv run python ./cognee/tests/test_library.py
- name: Build with Poetry
- name: Build with uv
shell: bash
run: poetry build
run: uv build
- name: Install Package
if: ${{ !contains(matrix.os, 'windows') }}

View file

@ -58,10 +58,10 @@ jobs:
uses: ./.github/actions/cognee_setup
with:
python-version: '3.11.x'
extra-dependencies: "postgres"
- name: Install specific db dependency
run: |
poetry install -E postgres
run: echo "Dependencies already installed in setup"
- name: Run PostgreSQL Script to create test data (Chinook_PostgreSql.sql)
env:
@ -90,7 +90,7 @@ jobs:
EMBEDDING_ENDPOINT: ${{ secrets.EMBEDDING_ENDPOINT }}
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
EMBEDDING_API_VERSION: ${{ secrets.EMBEDDING_API_VERSION }}
run: poetry run python ./cognee/tests/test_relational_db_migration.py
run: uv run python ./cognee/tests/test_relational_db_migration.py
run-relational-db-migration-test-kuzu:
name: Kuzu Relational DB Migration Test
@ -120,10 +120,10 @@ jobs:
uses: ./.github/actions/cognee_setup
with:
python-version: '3.11.x'
extra-dependencies: "postgres"
- name: Install specific db dependency
run: |
poetry install -E postgres
run: echo "Dependencies already installed in setup"
- name: Run PostgreSQL Script to create test data (Chinook_PostgreSql.sql)
env:
@ -154,7 +154,7 @@ jobs:
EMBEDDING_ENDPOINT: ${{ secrets.EMBEDDING_ENDPOINT }}
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
EMBEDDING_API_VERSION: ${{ secrets.EMBEDDING_API_VERSION }}
run: poetry run python ./cognee/tests/test_relational_db_migration.py
run: uv run python ./cognee/tests/test_relational_db_migration.py
run-relational-db-migration-test-neo4j:
name: Neo4j Relational DB Migration Test
@ -184,10 +184,10 @@ jobs:
uses: ./.github/actions/cognee_setup
with:
python-version: '3.11.x'
extra-dependencies: "postgres"
- name: Install specific db dependency
run: |
poetry install -E postgres -E neo4j
run: echo "Dependencies already installed in setup"
- name: Run PostgreSQL Script to create test data (Chinook_PostgreSql.sql)
env:
@ -221,4 +221,4 @@ jobs:
EMBEDDING_ENDPOINT: ${{ secrets.EMBEDDING_ENDPOINT }}
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
EMBEDDING_API_VERSION: ${{ secrets.EMBEDDING_API_VERSION }}
run: poetry run python ./cognee/tests/test_relational_db_migration.py
run: uv run python ./cognee/tests/test_relational_db_migration.py

View file

@ -46,10 +46,7 @@ jobs:
uses: ./.github/actions/cognee_setup
with:
python-version: ${{ inputs.python-version }}
- name: Install specific db dependency
run: |
poetry install -E notebook
extra-dependencies: "notebook"
- name: Execute Jupyter Notebook
env:
@ -64,7 +61,7 @@ jobs:
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
EMBEDDING_API_VERSION: ${{ secrets.EMBEDDING_API_VERSION }}
run: |
poetry run jupyter nbconvert \
uv run jupyter nbconvert \
--to notebook \
--execute ${{ inputs.notebook-location }} \
--output executed_notebook.ipynb \

View file

@ -28,9 +28,8 @@ jobs:
with:
python-version: ${{ inputs.python-version }}
- name: Install specific db dependency
run: |
poetry install
- name: Dependencies already installed
run: echo "Dependencies already installed in setup"
- name: Run Kuzu search Tests
env:
@ -46,7 +45,7 @@ jobs:
GRAPH_DATABASE_PROVIDER: 'kuzu'
VECTOR_DB_PROVIDER: 'lancedb'
DB_PROVIDER: 'sqlite'
run: poetry run python ./cognee/tests/test_search_db.py
run: uv run python ./cognee/tests/test_search_db.py
run-neo4j-lance-sqlite-search-tests:
name: Search test for Neo4j/LanceDB/Sqlite
@ -78,9 +77,8 @@ jobs:
with:
python-version: ${{ inputs.python-version }}
- name: Install specific db dependency
run: |
poetry install -E neo4j
- name: Dependencies already installed
run: echo "Dependencies already installed in setup"
- name: Run Neo4j search Tests
env:
@ -99,7 +97,7 @@ jobs:
GRAPH_DATABASE_URL: bolt://localhost:7687
GRAPH_DATABASE_USERNAME: neo4j
GRAPH_DATABASE_PASSWORD: pleaseletmein
run: poetry run python ./cognee/tests/test_search_db.py
run: uv run python ./cognee/tests/test_search_db.py
run-kuzu-pgvector-postgres-search-tests:
name: Search test for Kuzu/PGVector/Postgres
@ -129,9 +127,10 @@ jobs:
uses: ./.github/actions/cognee_setup
with:
python-version: ${{ inputs.python-version }}
extra-dependencies: "postgres"
- name: Install dependencies
run: poetry install -E postgres
- name: Dependencies already installed
run: echo "Dependencies already installed in setup"
- name: Run Kuzu/PGVector/Postgres Tests
env:
@ -152,7 +151,7 @@ jobs:
DB_PORT: 5432
DB_USERNAME: cognee
DB_PASSWORD: cognee
run: poetry run python ./cognee/tests/test_search_db.py
run: uv run python ./cognee/tests/test_search_db.py
run-neo4j-pgvector-postgres-search-tests:
name: Search test for Neo4j/PGVector/Postgres
@ -195,10 +194,10 @@ jobs:
uses: ./.github/actions/cognee_setup
with:
python-version: ${{ inputs.python-version }}
extra-dependencies: "postgres"
- name: Install dependencies
run: |
poetry install -E neo4j -E postgres
- name: Dependencies already installed
run: echo "Dependencies already installed in setup"
- name: Run Neo4j + PGVector + Postgres search Tests
env:
@ -222,4 +221,4 @@ jobs:
DB_PORT: 5432
DB_USERNAME: cognee
DB_PASSWORD: cognee
run: poetry run python ./cognee/tests/test_search_db.py
run: uv run python ./cognee/tests/test_search_db.py

View file

@ -26,4 +26,4 @@ jobs:
EMBEDDING_MODEL: "gemini/text-embedding-004"
EMBEDDING_DIMENSIONS: "768"
EMBEDDING_MAX_TOKENS: "8076"
run: poetry run python ./examples/python/simple_example.py
run: uv run python ./examples/python/simple_example.py

View file

@ -26,7 +26,7 @@ jobs:
- name: Install torch dependency
run: |
poetry add torch
uv add torch
# - name: Install ollama
# run: curl -fsSL https://ollama.com/install.sh | sh
@ -101,4 +101,4 @@ jobs:
EMBEDDING_ENDPOINT: "http://localhost:11434/api/embeddings"
EMBEDDING_DIMENSIONS: "4096"
HUGGINGFACE_TOKENIZER: "Salesforce/SFR-Embedding-Mistral"
run: poetry run python ./examples/python/simple_example.py
run: uv run python ./examples/python/simple_example.py

View file

@ -36,4 +36,4 @@ jobs:
EMBEDDING_ENDPOINT: ${{ secrets.EMBEDDING_ENDPOINT }}
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
EMBEDDING_API_VERSION: ${{ secrets.EMBEDDING_API_VERSION }}
run: poetry run python ./cognee/tests/test_s3_file_storage.py
run: uv run python ./cognee/tests/test_s3_file_storage.py

View file

@ -56,7 +56,7 @@ jobs:
# EMBEDDING_ENDPOINT: ${{ secrets.EMBEDDING_ENDPOINT }}
# EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
# EMBEDDING_API_VERSION: ${{ secrets.EMBEDDING_API_VERSION }}
# run: poetry run python ./cognee/tests/test_chromadb.py
# run: uv run python ./cognee/tests/test_chromadb.py
run-postgres-tests:
@ -87,10 +87,7 @@ jobs:
uses: ./.github/actions/cognee_setup
with:
python-version: ${{ inputs.python-version }}
- name: Install specific db dependency
run: |
poetry install -E postgres
extra-dependencies: "postgres"
- name: Run PGVector Tests
env:
@ -103,4 +100,4 @@ jobs:
EMBEDDING_ENDPOINT: ${{ secrets.EMBEDDING_ENDPOINT }}
EMBEDDING_API_KEY: ${{ secrets.EMBEDDING_API_KEY }}
EMBEDDING_API_VERSION: ${{ secrets.EMBEDDING_API_VERSION }}
run: poetry run python ./cognee/tests/test_pgvector.py
run: uv run python ./cognee/tests/test_pgvector.py

View file

@ -47,11 +47,11 @@ jobs:
- name: Run Weighted Edges Unit Tests
run: |
poetry run pytest cognee/tests/unit/interfaces/graph/test_weighted_edges.py -v --tb=short
uv run pytest cognee/tests/unit/interfaces/graph/test_weighted_edges.py -v --tb=short
- name: Run Standard Graph Tests (Regression)
run: |
poetry run pytest cognee/tests/unit/interfaces/graph/get_graph_from_model_unit_test.py -v --tb=short
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
@ -61,10 +61,8 @@ jobs:
database: ['kuzu', 'neo4j']
include:
- database: kuzu
install_extra: ""
graph_db_provider: "kuzu"
- database: neo4j
install_extra: "-E neo4j"
graph_db_provider: "neo4j"
env:
LLM_PROVIDER: openai
@ -88,15 +86,14 @@ jobs:
with:
python-version: '3.11'
- name: Install Database Dependencies
run: |
poetry install ${{ matrix.install_extra }}
- name: Dependencies already installed
run: echo "Dependencies already installed in setup"
- name: Run Weighted Edges Tests
env:
GRAPH_DATABASE_PROVIDER: ${{ matrix.graph_db_provider }}
run: |
poetry run pytest cognee/tests/unit/interfaces/graph/test_weighted_edges.py -v --tb=short
uv run pytest cognee/tests/unit/interfaces/graph/test_weighted_edges.py -v --tb=short
test-examples:
name: Test Weighted Edges Examples
@ -125,7 +122,7 @@ jobs:
- name: Test Weighted Edges Example
run: |
poetry run python examples/python/weighted_edges_example.py
uv run python examples/python/weighted_edges_example.py
- name: Verify Visualization File Created
run: |

View file

@ -92,6 +92,7 @@ Your contributions are at the core of making this a true open source project. An
## 📦 Installation
You can install Cognee using either **pip**, **poetry**, **uv** or any other python package manager.
Cognee supports Python 3.10 to 3.13
### With pip
@ -102,7 +103,7 @@ pip install cognee
## Local Cognee installation
You can install the local Cognee repo using **pip**, **poetry** and **uv**.
You can install the local Cognee repo using **uv**, **pip** and **poetry**.
For local pip installation please make sure your pip version is above version 21.3.
### with UV with all optional dependencies

View file

@ -221,14 +221,6 @@ async def cognify(data: str, graph_model_file: str = None, graph_model_name: str
- The actual cognify process may take significant time depending on text length
- Use the cognify_status tool to check the progress of the operation
Raises
------
InvalidValueError
If LLM_API_KEY is not set
ValueError
If chunks exceed max token limits (reduce chunk_size)
DatabaseNotCreatedError
If databases are not properly initialized
"""
async def cognify_task(
@ -512,14 +504,6 @@ async def search(search_query: str, search_type: str) -> list:
- Different search types produce different output formats
- The function handles the conversion between Cognee's internal result format and MCP's output format
Raises
------
InvalidValueError
If LLM_API_KEY is not set (for LLM-based search types)
ValueError
If query_text is empty or search parameters are invalid
NoDataError
If no relevant data found for the search query
"""
async def search_task(search_query: str, search_type: str) -> str:

View file

@ -132,13 +132,8 @@ async def add(
- DEFAULT_USER_EMAIL: Custom default user email
- DEFAULT_USER_PASSWORD: Custom default user password
- VECTOR_DB_PROVIDER: "lancedb" (default), "chromadb", "pgvector"
- GRAPH_DATABASE_PROVIDER: "kuzu" (default), "neo4j", "networkx"
- GRAPH_DATABASE_PROVIDER: "kuzu" (default), "neo4j"
Raises:
FileNotFoundError: If specified file paths don't exist
PermissionError: If user lacks access to files or dataset
UnsupportedFileTypeError: If file format cannot be processed
InvalidValueError: If LLM_API_KEY is not set or invalid
"""
tasks = [
Task(resolve_data_directories, include_subdirectories=True),

View file

@ -177,14 +177,6 @@ async def cognify(
- LLM_PROVIDER, LLM_MODEL, VECTOR_DB_PROVIDER, GRAPH_DATABASE_PROVIDER
- LLM_RATE_LIMIT_ENABLED: Enable rate limiting (default: False)
- LLM_RATE_LIMIT_REQUESTS: Max requests per interval (default: 60)
Raises:
DatasetNotFoundError: If specified datasets don't exist
PermissionError: If user lacks processing rights
InvalidValueError: If LLM_API_KEY is not set
OntologyParsingError: If ontology file is malformed
ValueError: If chunks exceed max token limits (reduce chunk_size)
DatabaseNotCreatedError: If databases are not properly initialized
"""
tasks = await get_default_tasks(user, graph_model, chunker, chunk_size, ontology_file_path)

View file

@ -2,7 +2,6 @@
import os
from cognee.base_config import get_base_config
from cognee.exceptions import InvalidValueError, InvalidAttributeError
from cognee.modules.cognify.config import get_cognify_config
from cognee.infrastructure.data.chunking.config import get_chunk_config
from cognee.infrastructure.databases.vector import get_vectordb_config
@ -11,6 +10,7 @@ from cognee.infrastructure.llm.config import (
get_llm_config,
)
from cognee.infrastructure.databases.relational import get_relational_config, get_migration_config
from cognee.api.v1.exceptions.exceptions import InvalidConfigAttributeError
class config:
@ -92,9 +92,7 @@ class config:
if hasattr(llm_config, key):
object.__setattr__(llm_config, key, value)
else:
raise InvalidAttributeError(
message=f"'{key}' is not a valid attribute of the config."
)
raise InvalidConfigAttributeError(attribute=key)
@staticmethod
def set_chunk_strategy(chunk_strategy: object):
@ -131,9 +129,7 @@ class config:
if hasattr(relational_db_config, key):
object.__setattr__(relational_db_config, key, value)
else:
raise InvalidAttributeError(
message=f"'{key}' is not a valid attribute of the config."
)
raise InvalidConfigAttributeError(attribute=key)
@staticmethod
def set_migration_db_config(config_dict: dict):
@ -145,9 +141,7 @@ class config:
if hasattr(migration_db_config, key):
object.__setattr__(migration_db_config, key, value)
else:
raise InvalidAttributeError(
message=f"'{key}' is not a valid attribute of the config."
)
raise InvalidConfigAttributeError(attribute=key)
@staticmethod
def set_graph_db_config(config_dict: dict) -> None:
@ -171,9 +165,7 @@ class config:
if hasattr(vector_db_config, key):
object.__setattr__(vector_db_config, key, value)
else:
raise InvalidAttributeError(
message=f"'{key}' is not a valid attribute of the config."
)
InvalidConfigAttributeError(attribute=key)
@staticmethod
def set_vector_db_key(db_key: str):

View file

@ -13,7 +13,7 @@ from cognee.infrastructure.databases.relational import get_relational_engine
from cognee.modules.data.methods import get_authorized_existing_datasets
from cognee.modules.data.methods import create_dataset, get_datasets_by_name
from cognee.shared.logging_utils import get_logger
from cognee.api.v1.delete.exceptions import DataNotFoundError, DatasetNotFoundError
from cognee.api.v1.exceptions import DataNotFoundError, DatasetNotFoundError
from cognee.modules.users.models import User
from cognee.modules.users.methods import get_authenticated_user
from cognee.modules.users.permissions.methods import (

View file

@ -16,7 +16,7 @@ from cognee.modules.users.methods import get_default_user
from cognee.modules.data.methods import get_authorized_existing_datasets
from cognee.context_global_variables import set_database_global_context_variables
from cognee.api.v1.delete.exceptions import (
from cognee.api.v1.exceptions import (
DocumentNotFoundError,
DatasetNotFoundError,
DocumentSubgraphNotFoundError,

View file

@ -0,0 +1,13 @@
"""
Custom exceptions for the Cognee API.
This module defines a set of exceptions for handling various data errors
"""
from .exceptions import (
InvalidConfigAttributeError,
DocumentNotFoundError,
DatasetNotFoundError,
DataNotFoundError,
DocumentSubgraphNotFoundError,
)

View file

@ -1,10 +1,19 @@
from cognee.exceptions import CogneeApiError
from cognee.exceptions import CogneeConfigurationError, CogneeValidationError
from fastapi import status
class DocumentNotFoundError(CogneeApiError):
"""Raised when a document cannot be found in the database."""
class InvalidConfigAttributeError(CogneeConfigurationError):
def __init__(
self,
attribute: str,
name: str = "InvalidConfigAttributeError",
status_code: int = status.HTTP_400_BAD_REQUEST,
):
message = f"'{attribute}' is not a valid attribute of the configuration."
super().__init__(message, name, status_code)
class DocumentNotFoundError(CogneeValidationError):
def __init__(
self,
message: str = "Document not found in database.",
@ -14,9 +23,7 @@ class DocumentNotFoundError(CogneeApiError):
super().__init__(message, name, status_code)
class DatasetNotFoundError(CogneeApiError):
"""Raised when a dataset cannot be found."""
class DatasetNotFoundError(CogneeValidationError):
def __init__(
self,
message: str = "Dataset not found.",
@ -26,9 +33,7 @@ class DatasetNotFoundError(CogneeApiError):
super().__init__(message, name, status_code)
class DataNotFoundError(CogneeApiError):
"""Raised when a dataset cannot be found."""
class DataNotFoundError(CogneeValidationError):
def __init__(
self,
message: str = "Data not found.",
@ -38,9 +43,7 @@ class DataNotFoundError(CogneeApiError):
super().__init__(message, name, status_code)
class DocumentSubgraphNotFoundError(CogneeApiError):
"""Raised when a document's subgraph cannot be found in the graph database."""
class DocumentSubgraphNotFoundError(CogneeValidationError):
def __init__(
self,
message: str = "Document subgraph not found in graph database.",

View file

@ -158,13 +158,6 @@ async def search(
- VECTOR_DB_PROVIDER: Must match what was used during cognify
- GRAPH_DATABASE_PROVIDER: Must match what was used during cognify
Raises:
DatasetNotFoundError: If specified datasets don't exist or aren't accessible
PermissionDeniedError: If user lacks read access to requested datasets
NoDataError: If no relevant data found for the search query
InvalidValueError: If LLM_API_KEY is not set (for LLM-based search types)
ValueError: If query_text is empty or search parameters are invalid
CollectionNotFoundError: If vector collection not found (data not processed)
"""
# We use lists from now on for datasets
if isinstance(datasets, UUID) or isinstance(datasets, str):

View file

@ -2,13 +2,13 @@
Custom exceptions for the Cognee API.
This module defines a set of exceptions for handling various application errors,
such as service failures, resource conflicts, and invalid operations.
such as System, Validation, Configuration or TransientErrors
"""
from .exceptions import (
CogneeApiError,
ServiceError,
InvalidValueError,
InvalidAttributeError,
CriticalError,
CogneeSystemError,
CogneeValidationError,
CogneeConfigurationError,
CogneeTransientError,
)

View file

@ -35,37 +35,57 @@ class CogneeApiError(Exception):
return f"{self.name}: {self.message} (Status code: {self.status_code})"
class ServiceError(CogneeApiError):
"""Failures in external services or APIs, like a database or a third-party service"""
class CogneeSystemError(CogneeApiError):
"""System error"""
def __init__(
self,
message: str = "Service is unavailable.",
name: str = "ServiceError",
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
message: str = "A system error occurred.",
name: str = "CogneeSystemError",
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
log=True,
log_level="ERROR",
):
super().__init__(message, name, status_code)
super().__init__(message, name, status_code, log, log_level)
class InvalidValueError(CogneeApiError):
class CogneeValidationError(CogneeApiError):
"""Validation error"""
def __init__(
self,
message: str = "Invalid Value.",
name: str = "InvalidValueError",
message: str = "A validation error occurred.",
name: str = "CogneeValidationError",
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
log=True,
log_level="ERROR",
):
super().__init__(message, name, status_code)
super().__init__(message, name, status_code, log, log_level)
class InvalidAttributeError(CogneeApiError):
class CogneeConfigurationError(CogneeApiError):
"""SystemConfigError"""
def __init__(
self,
message: str = "Invalid attribute.",
name: str = "InvalidAttributeError",
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
message: str = "A system configuration error occurred.",
name: str = "CogneeConfigurationError",
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
log=True,
log_level="ERROR",
):
super().__init__(message, name, status_code)
super().__init__(message, name, status_code, log, log_level)
class CriticalError(CogneeApiError):
pass
class CogneeTransientError(CogneeApiError):
"""TransientError"""
def __init__(
self,
message: str = "A transient error occurred.",
name: str = "CogneeTransientError",
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
log=True,
log_level="ERROR",
):
super().__init__(message, name, status_code, log, log_level)

View file

@ -0,0 +1,7 @@
"""
Custom exceptions for the Cognee API.
This module defines a set of exceptions for handling various data errors
"""
from .exceptions import KeywordExtractionError

View file

@ -0,0 +1,22 @@
from cognee.exceptions import (
CogneeValidationError,
)
from fastapi import status
class KeywordExtractionError(CogneeValidationError):
"""
Raised when a provided value is syntactically valid but semantically unacceptable
for the given operation.
Example:
- Passing an empty string to a keyword extraction function.
"""
def __init__(
self,
message: str = "Extract_keywords cannot extract keywords from empty text.",
name: str = "KeywordExtractionError",
status_code: int = status.HTTP_400_BAD_REQUEST,
):
super().__init__(message, name, status_code)

View file

@ -1,6 +1,6 @@
from sklearn.feature_extraction.text import TfidfVectorizer
from cognee.exceptions import InvalidValueError
from cognee.infrastructure.data.exceptions.exceptions import KeywordExtractionError
from cognee.shared.utils import extract_pos_tags
@ -8,7 +8,7 @@ def extract_keywords(text: str) -> list[str]:
"""
Extract keywords from the provided text string.
This function raises an InvalidValueError if the input text is empty. It processes the
This function raises an KeyWordExtractionError if the input text is empty. It processes the
text to extract parts of speech, focusing on nouns, and uses TF-IDF to identify the most
relevant keywords based on their frequency. The function returns a list of up to 15
keywords, each having more than 3 characters.
@ -25,7 +25,7 @@ def extract_keywords(text: str) -> list[str]:
with more than 3 characters.
"""
if len(text) == 0:
raise InvalidValueError(message="extract_keywords cannot extract keywords from empty text.")
raise KeywordExtractionError()
tags = extract_pos_tags(text)
nouns = [word for (word, tag) in tags if tag == "NN"]

View file

@ -1,20 +0,0 @@
from cognee.exceptions import CogneeApiError
from fastapi import status
class EmbeddingException(CogneeApiError):
"""
Custom exception for handling embedding-related errors.
This exception class is designed to indicate issues specifically related to embeddings
within the application. It extends the base exception class CogneeApiError and allows
for customization of the error message, name, and status code.
"""
def __init__(
self,
message: str = "Embedding Exception.",
name: str = "EmbeddingException",
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
):
super().__init__(message, name, status_code)

View file

@ -8,4 +8,7 @@ from .exceptions import (
EntityNotFoundError,
EntityAlreadyExistsError,
DatabaseNotCreatedError,
EmbeddingException,
MissingQueryParameterError,
MutuallyExclusiveQueryParametersError,
)

View file

@ -1,13 +1,13 @@
from fastapi import status
from cognee.exceptions import CogneeApiError, CriticalError
from cognee.exceptions import CogneeSystemError, CogneeValidationError, CogneeConfigurationError
class DatabaseNotCreatedError(CriticalError):
class DatabaseNotCreatedError(CogneeSystemError):
"""
Represents an error indicating that the database has not been created. This error should
be raised when an attempt is made to access the database before it has been initialized.
Inherits from CriticalError. Overrides the constructor to include a default message and
Inherits from CogneeSystemError. Overrides the constructor to include a default message and
status code.
"""
@ -20,10 +20,10 @@ class DatabaseNotCreatedError(CriticalError):
super().__init__(message, name, status_code)
class EntityNotFoundError(CogneeApiError):
class EntityNotFoundError(CogneeValidationError):
"""
Represents an error when a requested entity is not found in the database. This class
inherits from CogneeApiError.
inherits from CogneeValidationError.
Public methods:
@ -49,11 +49,11 @@ class EntityNotFoundError(CogneeApiError):
# super().__init__(message, name, status_code) :TODO: This is not an error anymore with the dynamic exception handling therefore we shouldn't log error
class EntityAlreadyExistsError(CogneeApiError):
class EntityAlreadyExistsError(CogneeValidationError):
"""
Represents an error when an entity creation is attempted but the entity already exists.
This class is derived from CogneeApiError and is used to signal a conflict in operations
This class is derived from CogneeValidationError and is used to signal a conflict in operations
involving resource creation.
"""
@ -66,11 +66,11 @@ class EntityAlreadyExistsError(CogneeApiError):
super().__init__(message, name, status_code)
class NodesetFilterNotSupportedError(CogneeApiError):
class NodesetFilterNotSupportedError(CogneeConfigurationError):
"""
Raise an exception when a nodeset filter is not supported by the current database.
This exception inherits from `CogneeApiError` and is designed to provide information
This exception inherits from `CogneeConfigurationError` and is designed to provide information
about the specific issue of unsupported nodeset filters in the context of graph
databases.
"""
@ -84,3 +84,51 @@ class NodesetFilterNotSupportedError(CogneeApiError):
self.message = message
self.name = name
self.status_code = status_code
class EmbeddingException(CogneeConfigurationError):
"""
Custom exception for handling embedding-related errors.
This exception class is designed to indicate issues specifically related to embeddings
within the application. It extends the base exception class CogneeConfigurationError allows
for customization of the error message, name, and status code.
"""
def __init__(
self,
message: str = "Embedding Exception.",
name: str = "EmbeddingException",
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
):
super().__init__(message, name, status_code)
class MissingQueryParameterError(CogneeValidationError):
"""
Raised when neither 'query_text' nor 'query_vector' is provided,
and at least one is required to perform the operation.
"""
def __init__(
self,
name: str = "MissingQueryParameterError",
status_code: int = status.HTTP_400_BAD_REQUEST,
):
message = "One of query_text or query_vector must be provided!"
super().__init__(message, name, status_code)
class MutuallyExclusiveQueryParametersError(CogneeValidationError):
"""
Raised when both 'text' and 'embedding' are provided to the search function,
but only one type of input is allowed at a time.
"""
def __init__(
self,
name: str = "MutuallyExclusiveQueryParametersError",
status_code: int = status.HTTP_400_BAD_REQUEST,
):
message = "The search function accepts either text or embedding as input, but not both."
super().__init__(message, name, status_code)

View file

@ -21,10 +21,6 @@ async def get_graph_engine() -> GraphDBInterface:
if hasattr(graph_client, "initialize"):
await graph_client.initialize()
# Handle loading of graph for NetworkX
if config["graph_database_provider"].lower() == "networkx" and graph_client.graph is None:
await graph_client.load_graph_from_file()
return graph_client
@ -181,8 +177,7 @@ def create_graph_engine(
graph_id=graph_identifier,
)
from .networkx.adapter import NetworkXAdapter
graph_client = NetworkXAdapter(filename=graph_file_path)
return graph_client
raise EnvironmentError(
f"Unsupported graph database provider: {graph_database_provider}. "
f"Supported providers are: {', '.join(list(supported_databases.keys()) + ['neo4j', 'falkordb', 'kuzu', 'kuzu-remote', 'memgraph', 'neptune', 'neptune_analytics'])}"
)

View file

@ -3,11 +3,16 @@
This module defines custom exceptions for Neptune Analytics operations.
"""
from cognee.exceptions import CogneeApiError
from cognee.exceptions import (
CogneeSystemError,
CogneeTransientError,
CogneeValidationError,
CogneeConfigurationError,
)
from fastapi import status
class NeptuneAnalyticsError(CogneeApiError):
class NeptuneAnalyticsError(CogneeSystemError):
"""Base exception for Neptune Analytics operations."""
def __init__(
@ -19,7 +24,7 @@ class NeptuneAnalyticsError(CogneeApiError):
super().__init__(message, name, status_code)
class NeptuneAnalyticsConnectionError(NeptuneAnalyticsError):
class NeptuneAnalyticsConnectionError(CogneeTransientError):
"""Exception raised when connection to Neptune Analytics fails."""
def __init__(
@ -31,7 +36,7 @@ class NeptuneAnalyticsConnectionError(NeptuneAnalyticsError):
super().__init__(message, name, status_code)
class NeptuneAnalyticsQueryError(NeptuneAnalyticsError):
class NeptuneAnalyticsQueryError(CogneeValidationError):
"""Exception raised when a query execution fails."""
def __init__(
@ -43,7 +48,7 @@ class NeptuneAnalyticsQueryError(NeptuneAnalyticsError):
super().__init__(message, name, status_code)
class NeptuneAnalyticsAuthenticationError(NeptuneAnalyticsError):
class NeptuneAnalyticsAuthenticationError(CogneeConfigurationError):
"""Exception raised when authentication with Neptune Analytics fails."""
def __init__(
@ -55,7 +60,7 @@ class NeptuneAnalyticsAuthenticationError(NeptuneAnalyticsError):
super().__init__(message, name, status_code)
class NeptuneAnalyticsConfigurationError(NeptuneAnalyticsError):
class NeptuneAnalyticsConfigurationError(CogneeConfigurationError):
"""Exception raised when Neptune Analytics configuration is invalid."""
def __init__(
@ -67,7 +72,7 @@ class NeptuneAnalyticsConfigurationError(NeptuneAnalyticsError):
super().__init__(message, name, status_code)
class NeptuneAnalyticsTimeoutError(NeptuneAnalyticsError):
class NeptuneAnalyticsTimeoutError(CogneeTransientError):
"""Exception raised when a Neptune Analytics operation times out."""
def __init__(
@ -79,7 +84,7 @@ class NeptuneAnalyticsTimeoutError(NeptuneAnalyticsError):
super().__init__(message, name, status_code)
class NeptuneAnalyticsThrottlingError(NeptuneAnalyticsError):
class NeptuneAnalyticsThrottlingError(CogneeTransientError):
"""Exception raised when requests are throttled by Neptune Analytics."""
def __init__(
@ -91,7 +96,7 @@ class NeptuneAnalyticsThrottlingError(NeptuneAnalyticsError):
super().__init__(message, name, status_code)
class NeptuneAnalyticsResourceNotFoundError(NeptuneAnalyticsError):
class NeptuneAnalyticsResourceNotFoundError(CogneeValidationError):
"""Exception raised when a Neptune Analytics resource is not found."""
def __init__(
@ -103,7 +108,7 @@ class NeptuneAnalyticsResourceNotFoundError(NeptuneAnalyticsError):
super().__init__(message, name, status_code)
class NeptuneAnalyticsInvalidParameterError(NeptuneAnalyticsError):
class NeptuneAnalyticsInvalidParameterError(CogneeValidationError):
"""Exception raised when invalid parameters are provided to Neptune Analytics."""
def __init__(

File diff suppressed because it is too large Load diff

View file

@ -9,7 +9,7 @@ from typing import List, Dict, Any, Optional, Tuple, Type, Union
from falkordb import FalkorDB
from cognee.exceptions import InvalidValueError
from cognee.infrastructure.databases.exceptions import MissingQueryParameterError
from cognee.infrastructure.databases.graph.graph_db_interface import (
GraphDBInterface,
record_graph_changes,
@ -721,7 +721,7 @@ class FalkorDBAdapter(VectorDBInterface, GraphDBInterface):
Returns the search results as a result set from the graph database.
"""
if query_text is None and query_vector is None:
raise InvalidValueError(message="One of query_text or query_vector must be provided!")
raise MissingQueryParameterError()
if query_text and not query_vector:
query_vector = (await self.embed_data([query_text]))[0]

View file

@ -5,7 +5,8 @@ import json
from typing import List, Optional, Any, Dict, Type, Tuple
from uuid import UUID
from cognee.exceptions import InvalidValueError
from cognee.infrastructure.databases.exceptions import MissingQueryParameterError
from cognee.infrastructure.databases.exceptions import MutuallyExclusiveQueryParametersError
from cognee.infrastructure.databases.graph.neptune_driver.adapter import NeptuneGraphDB
from cognee.infrastructure.databases.vector.vector_db_interface import VectorDBInterface
from cognee.infrastructure.engine import DataPoint
@ -274,11 +275,9 @@ class NeptuneAnalyticsAdapter(NeptuneGraphDB, VectorDBInterface):
limit = self._TOPK_UPPER_BOUND
if query_vector and query_text:
raise InvalidValueError(
message="The search function accepts either text or embedding as input, but not both."
)
raise MutuallyExclusiveQueryParametersError()
elif query_text is None and query_vector is None:
raise InvalidValueError(message="One of query_text or query_vector must be provided!")
raise MissingQueryParameterError()
elif query_vector:
embedding = query_vector
else:

View file

@ -4,13 +4,13 @@ from uuid import UUID
from typing import List, Optional
from chromadb import AsyncHttpClient, Settings
from cognee.exceptions import InvalidValueError
from cognee.shared.logging_utils import get_logger
from cognee.modules.storage.utils import get_own_properties
from cognee.infrastructure.engine import DataPoint
from cognee.infrastructure.engine.utils import parse_id
from cognee.infrastructure.databases.vector.exceptions import CollectionNotFoundError
from cognee.infrastructure.databases.vector.models.ScoredResult import ScoredResult
from cognee.infrastructure.databases.exceptions import MissingQueryParameterError
from ..embeddings.EmbeddingEngine import EmbeddingEngine
from ..vector_db_interface import VectorDBInterface
@ -378,7 +378,7 @@ class ChromaDBAdapter(VectorDBInterface):
Returns a list of ScoredResult instances representing the search results.
"""
if query_text is None and query_vector is None:
raise InvalidValueError(message="One of query_text or query_vector must be provided!")
raise MissingQueryParameterError()
if query_text and not query_vector:
query_vector = (await self.embedding_engine.embed_text([query_text]))[0]

View file

@ -6,7 +6,7 @@ import math
import litellm
import os
from cognee.infrastructure.databases.vector.embeddings.EmbeddingEngine import EmbeddingEngine
from cognee.infrastructure.databases.exceptions.EmbeddingException import EmbeddingException
from cognee.infrastructure.databases.exceptions import EmbeddingException
from cognee.infrastructure.llm.tokenizer.Gemini import (
GeminiTokenizer,
)

View file

@ -1,12 +1,12 @@
from fastapi import status
from cognee.exceptions import CriticalError
from cognee.exceptions import CogneeValidationError
class CollectionNotFoundError(CriticalError):
class CollectionNotFoundError(CogneeValidationError):
"""
Represents an error that occurs when a requested collection cannot be found.
This class extends the CriticalError to handle specific cases where a requested
This class extends the CogneeValidationError to handle specific cases where a requested
collection is unavailable. It can be initialized with a custom message and allows for
logging options including log level and whether to log the error.
"""

View file

@ -5,7 +5,7 @@ from pydantic import BaseModel
from lancedb.pydantic import LanceModel, Vector
from typing import Generic, List, Optional, TypeVar, Union, get_args, get_origin, get_type_hints
from cognee.exceptions import InvalidValueError
from cognee.infrastructure.databases.exceptions import MissingQueryParameterError
from cognee.infrastructure.engine import DataPoint
from cognee.infrastructure.engine.utils import parse_id
from cognee.infrastructure.files.storage import get_file_storage
@ -228,7 +228,7 @@ class LanceDBAdapter(VectorDBInterface):
normalized: bool = True,
):
if query_text is None and query_vector is None:
raise InvalidValueError(message="One of query_text or query_vector must be provided!")
raise MissingQueryParameterError()
if query_text and not query_vector:
query_vector = (await self.embedding_engine.embed_text([query_text]))[0]

View file

@ -9,7 +9,7 @@ from sqlalchemy.exc import ProgrammingError
from tenacity import retry, retry_if_exception_type, stop_after_attempt, wait_exponential
from asyncpg import DeadlockDetectedError, DuplicateTableError, UniqueViolationError
from cognee.exceptions import InvalidValueError
from cognee.shared.logging_utils import get_logger
from cognee.infrastructure.engine import DataPoint
from cognee.infrastructure.engine.utils import parse_id
@ -17,6 +17,7 @@ from cognee.infrastructure.databases.relational import get_relational_engine
from distributed.utils import override_distributed
from distributed.tasks.queued_add_data_points import queued_add_data_points
from cognee.infrastructure.databases.exceptions import MissingQueryParameterError
from ...relational.ModelBase import Base
from ...relational.sqlalchemy.SqlAlchemyAdapter import SQLAlchemyAdapter
@ -275,7 +276,7 @@ class PGVectorAdapter(SQLAlchemyAdapter, VectorDBInterface):
return metadata.tables[collection_name]
else:
raise CollectionNotFoundError(
f"Collection '{collection_name}' not found!", log_level="DEBUG"
f"Collection '{collection_name}' not found!",
)
async def retrieve(self, collection_name: str, data_point_ids: List[str]):
@ -302,7 +303,7 @@ class PGVectorAdapter(SQLAlchemyAdapter, VectorDBInterface):
with_vector: bool = False,
) -> List[ScoredResult]:
if query_text is None and query_vector is None:
raise InvalidValueError(message="One of query_text or query_vector must be provided!")
raise MissingQueryParameterError()
if query_text and not query_vector:
query_vector = (await self.embedding_engine.embed_text([query_text]))[0]

View file

@ -1,5 +1,33 @@
from cognee.exceptions.exceptions import CriticalError
from cognee.exceptions.exceptions import CogneeValidationError
class ContentPolicyFilterError(CriticalError):
class ContentPolicyFilterError(CogneeValidationError):
pass
class LLMAPIKeyNotSetError(CogneeValidationError):
"""
Raised when the LLM API key is not set in the configuration.
"""
def __init__(self, message: str = "LLM API key is not set."):
super().__init__(message=message, name="LLMAPIKeyNotSetError")
class UnsupportedLLMProviderError(CogneeValidationError):
"""
Raised when an unsupported LLM provider is specified in the configuration.
"""
def __init__(self, provider: str):
message = f"Unsupported LLM provider: {provider}"
super().__init__(message=message, name="UnsupportedLLMProviderError")
class MissingSystemPromptPathError(CogneeValidationError):
def __init__(
self,
name: str = "MissingSystemPromptPathError",
):
message = "No system prompt path provided."
super().__init__(message, name)

View file

@ -2,7 +2,7 @@ from typing import Type
from pydantic import BaseModel
import instructor
from cognee.exceptions import InvalidValueError
from cognee.infrastructure.llm.exceptions import MissingSystemPromptPathError
from cognee.infrastructure.llm.structured_output_framework.litellm_instructor.llm.llm_interface import (
LLMInterface,
)
@ -89,7 +89,7 @@ class AnthropicAdapter(LLMInterface):
if not text_input:
text_input = "No user input provided."
if not system_prompt:
raise InvalidValueError(message="No system prompt path provided.")
raise MissingSystemPromptPathError()
system_prompt = LLMGateway.read_query_prompt(system_prompt)

View file

@ -5,7 +5,7 @@ from litellm import acompletion, JSONSchemaValidationError
from cognee.shared.logging_utils import get_logger
from cognee.modules.observability.get_observe import get_observe
from cognee.exceptions import InvalidValueError
from cognee.infrastructure.llm.exceptions import MissingSystemPromptPathError
from cognee.infrastructure.llm.structured_output_framework.litellm_instructor.llm.llm_interface import (
LLMInterface,
)
@ -118,7 +118,7 @@ class GeminiAdapter(LLMInterface):
"""
Format and display the prompt for a user query.
Raises an InvalidValueError if no system prompt is provided.
Raises an MissingQueryParameterError if no system prompt is provided.
Parameters:
-----------
@ -135,7 +135,7 @@ class GeminiAdapter(LLMInterface):
if not text_input:
text_input = "No user input provided."
if not system_prompt:
raise InvalidValueError(message="No system prompt path provided.")
raise MissingSystemPromptPathError()
system_prompt = LLMGateway.read_query_prompt(system_prompt)
formatted_prompt = (

View file

@ -2,11 +2,14 @@
from enum import Enum
from cognee.exceptions import InvalidValueError
from cognee.infrastructure.llm import get_llm_config
from cognee.infrastructure.llm.structured_output_framework.litellm_instructor.llm.ollama.adapter import (
OllamaAPIAdapter,
)
from cognee.infrastructure.llm.exceptions import (
LLMAPIKeyNotSetError,
UnsupportedLLMProviderError,
)
# Define an Enum for LLM Providers
@ -35,7 +38,7 @@ def get_llm_client():
This function retrieves the configuration for the LLM provider and model, and
initializes the appropriate LLM client adapter accordingly. It raises an
InvalidValueError if the LLM API key is not set for certain providers or if the provider
LLMAPIKeyNotSetError if the LLM API key is not set for certain providers or if the provider
is unsupported.
Returns:
@ -59,7 +62,7 @@ def get_llm_client():
if provider == LLMProvider.OPENAI:
if llm_config.llm_api_key is None:
raise InvalidValueError(message="LLM API key is not set.")
raise LLMAPIKeyNotSetError()
from cognee.infrastructure.llm.structured_output_framework.litellm_instructor.llm.openai.adapter import (
OpenAIAdapter,
@ -80,7 +83,7 @@ def get_llm_client():
elif provider == LLMProvider.OLLAMA:
if llm_config.llm_api_key is None:
raise InvalidValueError(message="LLM API key is not set.")
raise LLMAPIKeyNotSetError()
from cognee.infrastructure.llm.structured_output_framework.litellm_instructor.llm.generic_llm_api.adapter import (
GenericAPIAdapter,
@ -103,7 +106,7 @@ def get_llm_client():
elif provider == LLMProvider.CUSTOM:
if llm_config.llm_api_key is None:
raise InvalidValueError(message="LLM API key is not set.")
raise LLMAPIKeyNotSetError()
from cognee.infrastructure.llm.structured_output_framework.litellm_instructor.llm.generic_llm_api.adapter import (
GenericAPIAdapter,
@ -122,7 +125,7 @@ def get_llm_client():
elif provider == LLMProvider.GEMINI:
if llm_config.llm_api_key is None:
raise InvalidValueError(message="LLM API key is not set.")
raise LLMAPIKeyNotSetError()
from cognee.infrastructure.llm.structured_output_framework.litellm_instructor.llm.gemini.adapter import (
GeminiAdapter,
@ -138,4 +141,4 @@ def get_llm_client():
)
else:
raise InvalidValueError(message=f"Unsupported LLM provider: {provider}")
raise UnsupportedLLMProviderError(provider)

View file

@ -7,12 +7,14 @@ from openai import ContentFilterFinishReasonError
from litellm.exceptions import ContentPolicyViolationError
from instructor.exceptions import InstructorRetryException
from cognee.exceptions import InvalidValueError
from cognee.infrastructure.llm.LLMGateway import LLMGateway
from cognee.infrastructure.llm.structured_output_framework.litellm_instructor.llm.llm_interface import (
LLMInterface,
)
from cognee.infrastructure.llm.exceptions import ContentPolicyFilterError
from cognee.infrastructure.llm.exceptions import (
ContentPolicyFilterError,
MissingSystemPromptPathError,
)
from cognee.infrastructure.files.utils.open_data_file import open_data_file
from cognee.infrastructure.llm.structured_output_framework.litellm_instructor.llm.rate_limiter import (
rate_limit_async,
@ -308,7 +310,7 @@ class OpenAIAdapter(LLMInterface):
Format and display the prompt for a user query.
This method formats the prompt using the provided user input and system prompt,
returning a string representation. Raises InvalidValueError if the system prompt is not
returning a string representation. Raises MissingSystemPromptPathError if the system prompt is not
provided.
Parameters:
@ -325,7 +327,7 @@ class OpenAIAdapter(LLMInterface):
if not text_input:
text_input = "No user input provided."
if not system_prompt:
raise InvalidValueError(message="No system prompt path provided.")
raise MissingSystemPromptPathError()
system_prompt = LLMGateway.read_query_prompt(system_prompt)
formatted_prompt = (

View file

@ -58,7 +58,7 @@ class LoaderInterface(ABC):
pass
@abstractmethod
async def load(self, file_path: str, file_stream: Optional[Any] = None, **kwargs):
async def load(self, file_path: str, **kwargs):
"""
Load and process the file, returning standardized result.

View file

@ -1,8 +1,11 @@
from cognee.exceptions import CogneeApiError
from cognee.exceptions import (
CogneeValidationError,
CogneeConfigurationError,
)
from fastapi import status
class UnstructuredLibraryImportError(CogneeApiError):
class UnstructuredLibraryImportError(CogneeConfigurationError):
def __init__(
self,
message: str = "Import error. Unstructured library is not installed.",
@ -12,7 +15,7 @@ class UnstructuredLibraryImportError(CogneeApiError):
super().__init__(message, name, status_code)
class UnauthorizedDataAccessError(CogneeApiError):
class UnauthorizedDataAccessError(CogneeValidationError):
def __init__(
self,
message: str = "User does not have permission to access this data.",
@ -22,7 +25,7 @@ class UnauthorizedDataAccessError(CogneeApiError):
super().__init__(message, name, status_code)
class DatasetNotFoundError(CogneeApiError):
class DatasetNotFoundError(CogneeValidationError):
def __init__(
self,
message: str = "Dataset not found.",
@ -32,7 +35,7 @@ class DatasetNotFoundError(CogneeApiError):
super().__init__(message, name, status_code)
class DatasetTypeError(CogneeApiError):
class DatasetTypeError(CogneeValidationError):
def __init__(
self,
message: str = "Dataset type not supported.",
@ -40,3 +43,13 @@ class DatasetTypeError(CogneeApiError):
status_code=status.HTTP_400_BAD_REQUEST,
):
super().__init__(message, name, status_code)
class InvalidTableAttributeError(CogneeValidationError):
def __init__(
self,
message: str = "The provided data object is missing the required '__tablename__' attribute.",
name: str = "InvalidTableAttributeError",
status_code: int = status.HTTP_400_BAD_REQUEST,
):
super().__init__(message, name, status_code)

View file

@ -1,4 +1,4 @@
from cognee.exceptions import InvalidAttributeError
from cognee.modules.data.exceptions.exceptions import InvalidTableAttributeError
from cognee.modules.data.models import Data
from cognee.infrastructure.databases.relational import get_relational_engine
@ -13,9 +13,7 @@ async def delete_data(data: Data):
ValueError: If the data object is invalid.
"""
if not hasattr(data, "__tablename__"):
raise InvalidAttributeError(
message="The provided data object is missing the required '__tablename__' attribute."
)
raise InvalidTableAttributeError()
db_engine = get_relational_engine()

View file

@ -1,8 +1,8 @@
from cognee.exceptions import CogneeApiError
from cognee.exceptions import CogneeSystemError
from fastapi import status
class PyPdfInternalError(CogneeApiError):
class PyPdfInternalError(CogneeSystemError):
"""Internal pypdf error"""
def __init__(

View file

@ -2,8 +2,11 @@ import time
from cognee.shared.logging_utils import get_logger
from typing import List, Dict, Union, Optional, Type
from cognee.exceptions import InvalidValueError
from cognee.modules.graph.exceptions import EntityNotFoundError, EntityAlreadyExistsError
from cognee.modules.graph.exceptions import (
EntityNotFoundError,
EntityAlreadyExistsError,
InvalidDimensionsError,
)
from cognee.infrastructure.databases.graph.graph_db_interface import GraphDBInterface
from cognee.modules.graph.cognee_graph.CogneeGraphElements import Node, Edge
from cognee.modules.graph.cognee_graph.CogneeAbstractGraph import CogneeAbstractGraph
@ -66,8 +69,7 @@ class CogneeGraph(CogneeAbstractGraph):
node_name: Optional[List[str]] = None,
) -> None:
if node_dimension < 1 or edge_dimension < 1:
raise InvalidValueError(message="Dimensions must be positive integers")
raise InvalidDimensionsError()
try:
import time

View file

@ -1,7 +1,6 @@
import numpy as np
from typing import List, Dict, Optional, Any, Union
from cognee.exceptions import InvalidValueError
from cognee.modules.graph.exceptions import InvalidDimensionsError, DimensionOutOfRangeError
class Node:
@ -24,7 +23,7 @@ class Node:
self, node_id: str, attributes: Optional[Dict[str, Any]] = None, dimension: int = 1
):
if dimension <= 0:
raise InvalidValueError(message="Dimension must be a positive integer")
raise InvalidDimensionsError()
self.id = node_id
self.attributes = attributes if attributes is not None else {}
self.attributes["vector_distance"] = float("inf")
@ -58,9 +57,7 @@ class Node:
def is_node_alive_in_dimension(self, dimension: int) -> bool:
if dimension < 0 or dimension >= len(self.status):
raise InvalidValueError(
message=f"Dimension {dimension} is out of range. Valid range is 0 to {len(self.status) - 1}."
)
raise DimensionOutOfRangeError(dimension=dimension, max_index=len(self.status) - 1)
return self.status[dimension] == 1
def add_attribute(self, key: str, value: Any) -> None:
@ -110,7 +107,7 @@ class Edge:
dimension: int = 1,
):
if dimension <= 0:
raise InvalidValueError(message="Dimensions must be a positive integer.")
raise InvalidDimensionsError()
self.node1 = node1
self.node2 = node2
self.attributes = attributes if attributes is not None else {}
@ -120,9 +117,7 @@ class Edge:
def is_edge_alive_in_dimension(self, dimension: int) -> bool:
if dimension < 0 or dimension >= len(self.status):
raise InvalidValueError(
message=f"Dimension {dimension} is out of range. Valid range is 0 to {len(self.status) - 1}."
)
raise DimensionOutOfRangeError(dimension=dimension, max_index=len(self.status) - 1)
return self.status[dimension] == 1
def add_attribute(self, key: str, value: Any) -> None:

View file

@ -7,4 +7,6 @@ This module defines a set of exceptions for handling various graph errors
from .exceptions import (
EntityNotFoundError,
EntityAlreadyExistsError,
InvalidDimensionsError,
DimensionOutOfRangeError,
)

View file

@ -1,8 +1,8 @@
from cognee.exceptions import CogneeApiError
from cognee.exceptions import CogneeValidationError
from fastapi import status
class EntityNotFoundError(CogneeApiError):
class EntityNotFoundError(CogneeValidationError):
"""Database returns nothing"""
def __init__(
@ -14,7 +14,7 @@ class EntityNotFoundError(CogneeApiError):
super().__init__(message, name, status_code)
class EntityAlreadyExistsError(CogneeApiError):
class EntityAlreadyExistsError(CogneeValidationError):
"""Conflict detected, like trying to create a resource that already exists"""
def __init__(
@ -24,3 +24,25 @@ class EntityAlreadyExistsError(CogneeApiError):
status_code=status.HTTP_409_CONFLICT,
):
super().__init__(message, name, status_code)
class InvalidDimensionsError(CogneeValidationError):
def __init__(
self,
name: str = "InvalidDimensionsError",
status_code: int = status.HTTP_400_BAD_REQUEST,
):
message = "Dimensions must be positive integers."
super().__init__(message, name, status_code)
class DimensionOutOfRangeError(CogneeValidationError):
def __init__(
self,
dimension: int,
max_index: int,
name: str = "DimensionOutOfRangeError",
status_code: int = status.HTTP_400_BAD_REQUEST,
):
message = f"Dimension {dimension} is out of range. Valid range is 0 to {max_index}."
super().__init__(message, name, status_code)

View file

@ -1,8 +1,8 @@
from cognee.exceptions import CogneeApiError
from cognee.exceptions import CogneeValidationError
from fastapi import status
class IngestionError(CogneeApiError):
class IngestionError(CogneeValidationError):
def __init__(
self,
message: str = "Type of data sent to classify not supported.",

View file

@ -1,8 +1,8 @@
from cognee.exceptions import CogneeApiError
from cognee.exceptions import CogneeSystemError
from fastapi import status
class OntologyInitializationError(CogneeApiError):
class OntologyInitializationError(CogneeSystemError):
def __init__(
self,
message: str = "Ontology initialization failed",
@ -12,7 +12,7 @@ class OntologyInitializationError(CogneeApiError):
super().__init__(message, name, status_code)
class FindClosestMatchError(CogneeApiError):
class FindClosestMatchError(CogneeSystemError):
def __init__(
self,
message: str = "Error in find_closest_match",
@ -22,7 +22,7 @@ class FindClosestMatchError(CogneeApiError):
super().__init__(message, name, status_code)
class GetSubgraphError(CogneeApiError):
class GetSubgraphError(CogneeSystemError):
def __init__(
self,
message: str = "Failed to retrieve subgraph",

View file

@ -1,8 +1,8 @@
from cognee.exceptions import CogneeApiError
from cognee.exceptions import CogneeSystemError
from fastapi import status
class PipelineRunFailedError(CogneeApiError):
class PipelineRunFailedError(CogneeSystemError):
def __init__(
self,
message: str = "Pipeline run failed.",

View file

@ -1,6 +1,5 @@
from typing import Any, Optional
from cognee.infrastructure.databases.graph import get_graph_engine
from cognee.infrastructure.databases.graph.networkx.adapter import NetworkXAdapter
from cognee.modules.retrieval.base_retriever import BaseRetriever
from cognee.modules.retrieval.utils.completion import generate_completion
from cognee.modules.retrieval.exceptions import SearchTypeNotSupported, CypherSearchError
@ -31,8 +30,7 @@ class CypherSearchRetriever(BaseRetriever):
"""
Retrieves relevant context using a cypher query.
If the graph engine is an instance of NetworkXAdapter, raises SearchTypeNotSupported. If
any error occurs during execution, logs the error and raises CypherSearchError.
If any error occurs during execution, logs the error and raises CypherSearchError.
Parameters:
-----------
@ -46,12 +44,6 @@ class CypherSearchRetriever(BaseRetriever):
"""
try:
graph_engine = await get_graph_engine()
if isinstance(graph_engine, NetworkXAdapter):
raise SearchTypeNotSupported(
"CYPHER search type not supported for NetworkXAdapter."
)
result = await graph_engine.query(query)
except Exception as e:
logger.error("Failed to execture cypher search retrieval: %s", str(e))

View file

@ -1,8 +1,8 @@
from fastapi import status
from cognee.exceptions import CogneeApiError, CriticalError
from cognee.exceptions import CogneeValidationError, CogneeSystemError
class SearchTypeNotSupported(CogneeApiError):
class SearchTypeNotSupported(CogneeValidationError):
def __init__(
self,
message: str = "CYPHER search type not supported by the adapter.",
@ -12,7 +12,7 @@ class SearchTypeNotSupported(CogneeApiError):
super().__init__(message, name, status_code)
class CypherSearchError(CogneeApiError):
class CypherSearchError(CogneeSystemError):
def __init__(
self,
message: str = "An error occurred during the execution of the Cypher query.",
@ -22,11 +22,17 @@ class CypherSearchError(CogneeApiError):
super().__init__(message, name, status_code)
class NoDataError(CriticalError):
message: str = "No data found in the system, please add data first."
class NoDataError(CogneeValidationError):
def __init__(
self,
message: str = "No data found in the system, please add data first.",
name: str = "NoDataError",
status_code: int = status.HTTP_404_NOT_FOUND,
):
super().__init__(message, name, status_code)
class CollectionDistancesNotFoundError(CogneeApiError):
class CollectionDistancesNotFoundError(CogneeValidationError):
def __init__(
self,
message: str = "No collection distances found for the given query.",

View file

@ -1,7 +1,6 @@
from typing import Any, Optional
from cognee.shared.logging_utils import get_logger
from cognee.infrastructure.databases.graph import get_graph_engine
from cognee.infrastructure.databases.graph.networkx.adapter import NetworkXAdapter
from cognee.infrastructure.llm.LLMGateway import LLMGateway
from cognee.modules.retrieval.base_retriever import BaseRetriever
from cognee.modules.retrieval.exceptions import SearchTypeNotSupported
@ -123,9 +122,6 @@ class NaturalLanguageRetriever(BaseRetriever):
"""
graph_engine = await get_graph_engine()
if isinstance(graph_engine, (NetworkXAdapter)):
raise SearchTypeNotSupported("Natural language search type not supported.")
return await self._execute_cypher_query(query, graph_engine)
async def get_completion(self, query: str, context: Optional[Any] = None) -> Any:

View file

@ -0,0 +1,7 @@
"""
Custom exceptions for the Cognee API.
This module defines a set of exceptions for handling various data errors
"""
from .exceptions import UnsupportedSearchTypeError

View file

@ -0,0 +1,15 @@
from cognee.exceptions import (
CogneeValidationError,
)
from fastapi import status
class UnsupportedSearchTypeError(CogneeValidationError):
def __init__(
self,
search_type: str,
name: str = "UnsupportedSearchTypeError",
status_code: int = status.HTTP_400_BAD_REQUEST,
):
message = f"Unsupported search type: {search_type}"
super().__init__(message, name, status_code)

View file

@ -3,9 +3,8 @@ import json
import asyncio
from uuid import UUID
from typing import Callable, List, Optional, Type, Union
from cognee.modules.search.exceptions import UnsupportedSearchTypeError
from cognee.context_global_variables import set_database_global_context_variables
from cognee.exceptions import InvalidValueError
from cognee.modules.retrieval.chunks_retriever import ChunksRetriever
from cognee.modules.retrieval.insights_retriever import InsightsRetriever
from cognee.modules.retrieval.summaries_retriever import SummariesRetriever
@ -136,7 +135,7 @@ async def specific_search(
search_task = search_tasks.get(query_type)
if search_task is None:
raise InvalidValueError(message=f"Unsupported search type: {query_type}")
raise UnsupportedSearchTypeError(str(query_type))
send_telemetry("cognee.search EXECUTION STARTED", user.id)

View file

@ -1,8 +1,8 @@
from cognee.exceptions import CogneeApiError
from cognee.exceptions import CogneeValidationError
from fastapi import status
class RoleNotFoundError(CogneeApiError):
class RoleNotFoundError(CogneeValidationError):
"""User group not found"""
def __init__(
@ -14,7 +14,7 @@ class RoleNotFoundError(CogneeApiError):
super().__init__(message, name, status_code)
class TenantNotFoundError(CogneeApiError):
class TenantNotFoundError(CogneeValidationError):
"""User group not found"""
def __init__(
@ -26,7 +26,7 @@ class TenantNotFoundError(CogneeApiError):
super().__init__(message, name, status_code)
class UserNotFoundError(CogneeApiError):
class UserNotFoundError(CogneeValidationError):
"""User not found"""
def __init__(
@ -38,7 +38,7 @@ class UserNotFoundError(CogneeApiError):
super().__init__(message, name, status_code)
class PermissionDeniedError(CogneeApiError):
class PermissionDeniedError(CogneeValidationError):
def __init__(
self,
message: str = "User does not have permission on documents.",
@ -48,7 +48,7 @@ class PermissionDeniedError(CogneeApiError):
super().__init__(message, name, status_code)
class PermissionNotFoundError(CogneeApiError):
class PermissionNotFoundError(CogneeValidationError):
def __init__(
self,
message: str = "Permission type does not exist.",

View file

@ -1,8 +1,8 @@
from cognee.exceptions import CogneeApiError
from cognee.exceptions import CogneeValidationError
from fastapi import status
class IngestionError(CogneeApiError):
class IngestionError(CogneeValidationError):
def __init__(
self,
message: str = "Failed to load data.",

View file

@ -3,7 +3,6 @@
import os
import requests
from datetime import datetime, timezone
import networkx as nx
import matplotlib.pyplot as plt
import http.server
import socketserver

View file

@ -1,11 +1,11 @@
from cognee.exceptions import CogneeApiError
from cognee.exceptions import CogneeValidationError
from fastapi import status
class NoRelevantDataError(CogneeApiError):
class NoRelevantDataError(CogneeValidationError):
"""
Represents an error when no relevant data is found during a search. This class is a
subclass of CogneeApiError.
subclass of CogneeValidationError.
Public methods:

View file

@ -10,6 +10,7 @@ from cognee.modules.data.processing.document_types import (
)
from cognee.modules.engine.models.node_set import NodeSet
from cognee.modules.engine.utils.generate_node_id import generate_node_id
from cognee.tasks.documents.exceptions import WrongDataDocumentInputError
EXTENSION_TO_DOCUMENT_CLASS = {
"pdf": PdfDocument, # Text documents
@ -111,6 +112,9 @@ async def classify_documents(data_documents: list[Data]) -> list[Document]:
- list[Document]: A list of Document objects created based on the classified data
documents.
"""
if not isinstance(data_documents, list):
raise WrongDataDocumentInputError("data_documents")
documents = []
for data_item in data_documents:
document = EXTENSION_TO_DOCUMENT_CLASS[data_item.extension](

View file

@ -0,0 +1,11 @@
"""
Custom exceptions for the Cognee API.
This module defines a set of exceptions for handling various data errors
"""
from .exceptions import (
WrongDataDocumentInputError,
InvalidChunkSizeError,
InvalidChunkerError,
)

View file

@ -0,0 +1,36 @@
from cognee.exceptions import (
CogneeValidationError,
CogneeConfigurationError,
)
from fastapi import status
class WrongDataDocumentInputError(CogneeValidationError):
"""Raised when a wrong data document is provided."""
def __init__(
self,
field: str,
name: str = "WrongDataDocumentInputError",
status_code: int = status.HTTP_422_UNPROCESSABLE_ENTITY,
):
message = f"Missing of invalid parameter: '{field}'."
super().__init__(message, name, status_code)
class InvalidChunkSizeError(CogneeValidationError):
def __init__(self, value):
super().__init__(
message=f"max_chunk_size must be a positive integer (got {value}).",
name="InvalidChunkSizeError",
status_code=status.HTTP_400_BAD_REQUEST,
)
class InvalidChunkerError(CogneeValidationError):
def __init__(self):
super().__init__(
message="chunker must be a valid Chunker class.",
name="InvalidChunkerError",
status_code=status.HTTP_400_BAD_REQUEST,
)

View file

@ -8,6 +8,7 @@ from cognee.modules.data.models import Data
from cognee.infrastructure.databases.relational import get_relational_engine
from cognee.modules.chunking.TextChunker import TextChunker
from cognee.modules.chunking.Chunker import Chunker
from cognee.tasks.documents.exceptions import InvalidChunkSizeError, InvalidChunkerError
async def update_document_token_count(document_id: UUID, token_count: int) -> None:
@ -37,6 +38,13 @@ async def extract_chunks_from_documents(
- The `read` method of the `Document` class must be implemented to support the chunking operation.
- The `chunker` parameter determines the chunking logic and should align with the document type.
"""
if not isinstance(max_chunk_size, int) or max_chunk_size <= 0:
raise InvalidChunkSizeError(max_chunk_size)
if not isinstance(chunker, type):
raise InvalidChunkerError()
if not hasattr(chunker, "read"):
raise InvalidChunkerError()
for document in documents:
document_token_count = 0
@ -48,5 +56,3 @@ async def extract_chunks_from_documents(
yield document_chunk
await update_document_token_count(document.id, document_token_count)
# todo rita

View file

@ -0,0 +1,12 @@
"""
Custom exceptions for the Cognee API.
This module defines a set of exceptions for handling various data errors
"""
from .exceptions import (
InvalidDataChunksError,
InvalidGraphModelError,
InvalidOntologyAdapterError,
InvalidChunkGraphInputError,
)

View file

@ -0,0 +1,41 @@
from cognee.exceptions import (
CogneeValidationError,
CogneeConfigurationError,
)
from fastapi import status
class InvalidDataChunksError(CogneeValidationError):
def __init__(self, detail: str):
super().__init__(
message=f"Invalid data_chunks: {detail}",
name="InvalidDataChunksError",
status_code=status.HTTP_400_BAD_REQUEST,
)
class InvalidGraphModelError(CogneeValidationError):
def __init__(self, got):
super().__init__(
message=f"graph_model must be a subclass of BaseModel (got {got}).",
name="InvalidGraphModelError",
status_code=status.HTTP_400_BAD_REQUEST,
)
class InvalidOntologyAdapterError(CogneeConfigurationError):
def __init__(self, got):
super().__init__(
message=f"ontology_adapter lacks required interface (got {got}).",
name="InvalidOntologyAdapterError",
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
)
class InvalidChunkGraphInputError(CogneeValidationError):
def __init__(self, detail: str):
super().__init__(
message=f"Invalid chunk inputs or LLM Chunkgraphs: {detail}",
name="InvalidChunkGraphInputError",
status_code=status.HTTP_400_BAD_REQUEST,
)

View file

@ -12,6 +12,12 @@ from cognee.modules.graph.utils import (
)
from cognee.shared.data_models import KnowledgeGraph
from cognee.infrastructure.llm.LLMGateway import LLMGateway
from cognee.tasks.graph.exceptions import (
InvalidGraphModelError,
InvalidDataChunksError,
InvalidChunkGraphInputError,
InvalidOntologyAdapterError,
)
async def integrate_chunk_graphs(
@ -21,6 +27,20 @@ async def integrate_chunk_graphs(
ontology_adapter: OntologyResolver,
) -> List[DocumentChunk]:
"""Updates DocumentChunk objects, integrates data points and edges into databases."""
if not isinstance(data_chunks, list) or not isinstance(chunk_graphs, list):
raise InvalidChunkGraphInputError("data_chunks and chunk_graphs must be lists.")
if len(data_chunks) != len(chunk_graphs):
raise InvalidChunkGraphInputError(
f"length mismatch: {len(data_chunks)} chunks vs {len(chunk_graphs)} graphs."
)
if not isinstance(graph_model, type) or not issubclass(graph_model, BaseModel):
raise InvalidGraphModelError(graph_model)
if ontology_adapter is None or not hasattr(ontology_adapter, "get_subgraph"):
raise InvalidOntologyAdapterError(
type(ontology_adapter).__name__ if ontology_adapter else "None"
)
graph_engine = await get_graph_engine()
if graph_model is not KnowledgeGraph:
@ -55,6 +75,14 @@ async def extract_graph_from_data(
"""
Extracts and integrates a knowledge graph from the text content of document chunks using a specified graph model.
"""
if not isinstance(data_chunks, list) or not data_chunks:
raise InvalidDataChunksError("must be a non-empty list of DocumentChunk.")
if not all(hasattr(c, "text") for c in data_chunks):
raise InvalidDataChunksError("each chunk must have a 'text' attribute")
if not isinstance(graph_model, type) or not issubclass(graph_model, BaseModel):
raise InvalidGraphModelError(graph_model)
chunk_graphs = await asyncio.gather(
*[LLMGateway.extract_content_graph(chunk.text, graph_model) for chunk in data_chunks]
)

View file

@ -0,0 +1,8 @@
"""
Custom exceptions for the Cognee API.
This module defines a set of exceptions for handling various application errors,
such as System, Validation, Configuration or TransientErrors
"""
from .exceptions import S3FileSystemNotFoundError

View file

@ -0,0 +1,12 @@
from cognee.exceptions import CogneeSystemError
from fastapi import status
class S3FileSystemNotFoundError(CogneeSystemError):
def __init__(
self,
name: str = "S3FileSystemNotFoundError",
status_code: int = status.HTTP_500_INTERNAL_SERVER_ERROR,
):
message = "Could not find S3FileSystem."
super().__init__(message, name, status_code)

View file

@ -1,6 +1,9 @@
import os
from urllib.parse import urlparse
from typing import List, Union, BinaryIO
from cognee.tasks.ingestion.exceptions import S3FileSystemNotFoundError
from cognee.exceptions import CogneeSystemError
from cognee.infrastructure.files.storage.s3_config import get_s3_config
@ -54,6 +57,8 @@ async def resolve_data_directories(
else:
s3_files.append(key)
resolved_data.extend(s3_files)
else:
raise S3FileSystemNotFoundError()
elif os.path.isdir(item): # If it's a directory
if include_subdirectories:

View file

@ -5,9 +5,17 @@ from cognee.infrastructure.databases.graph import get_graph_engine
from cognee.modules.graph.utils import deduplicate_nodes_and_edges, get_graph_from_model
from .index_data_points import index_data_points
from .index_graph_edges import index_graph_edges
from cognee.tasks.storage.exceptions import (
InvalidDataPointsInAddDataPointsError,
)
async def add_data_points(data_points: List[DataPoint]) -> List[DataPoint]:
if not isinstance(data_points, list):
raise InvalidDataPointsInAddDataPointsError("data_points must be a list.")
if not all(isinstance(dp, DataPoint) for dp in data_points):
raise InvalidDataPointsInAddDataPointsError("data_points: each item must be a DataPoint.")
nodes = []
edges = []

View file

@ -0,0 +1,9 @@
"""
Custom exceptions for the Cognee API.
This module defines a set of exceptions for handling various data errors
"""
from .exceptions import (
InvalidDataPointsInAddDataPointsError,
)

View file

@ -0,0 +1,13 @@
from cognee.exceptions import (
CogneeValidationError,
)
from fastapi import status
class InvalidDataPointsInAddDataPointsError(CogneeValidationError):
def __init__(self, detail: str):
super().__init__(
message=f"Invalid data_points: {detail}",
name="InvalidDataPointsInAddDataPointsError",
status_code=status.HTTP_400_BAD_REQUEST,
)

View file

@ -1,6 +1,6 @@
from cognee.shared.logging_utils import get_logger
from cognee.infrastructure.databases.exceptions.EmbeddingException import EmbeddingException
from cognee.infrastructure.databases.exceptions import EmbeddingException
from cognee.infrastructure.databases.vector import get_vector_engine
from cognee.infrastructure.engine import DataPoint

View file

@ -0,0 +1,9 @@
"""
Custom exceptions for the Cognee API.
This module defines a set of exceptions for handling various data errors
"""
from .exceptions import (
InvalidSummaryInputsError,
)

View file

@ -0,0 +1,14 @@
from cognee.exceptions import (
CogneeValidationError,
CogneeConfigurationError,
)
from fastapi import status
class InvalidSummaryInputsError(CogneeValidationError):
def __init__(self, detail: str):
super().__init__(
message=f"Invalid summarize_text inputs: {detail}",
name="InvalidSummaryInputsError",
status_code=status.HTTP_400_BAD_REQUEST,
)

View file

@ -3,10 +3,11 @@ from typing import Type
from uuid import uuid5
from pydantic import BaseModel
from cognee.tasks.summarization.exceptions import InvalidSummaryInputsError
from cognee.modules.chunking.models.DocumentChunk import DocumentChunk
from cognee.infrastructure.llm.LLMGateway import LLMGateway
from cognee.modules.cognify.config import get_cognify_config
from .models import TextSummary
from cognee.tasks.summarization.models import TextSummary
async def summarize_text(
@ -35,6 +36,12 @@ async def summarize_text(
A list of TextSummary objects, each containing the summary of a corresponding
DocumentChunk.
"""
if not isinstance(data_chunks, list):
raise InvalidSummaryInputsError("data_chunks must be a list.")
if not all(hasattr(c, "text") for c in data_chunks):
raise InvalidSummaryInputsError("each DocumentChunk must have a 'text' attribute.")
if len(data_chunks) == 0:
return data_chunks

View file

@ -1,7 +0,0 @@
from cognee.tests.tasks.descriptive_metrics.metrics_test_utils import assert_metrics
import asyncio
if __name__ == "__main__":
asyncio.run(assert_metrics(provider="networkx", include_optional=False))
asyncio.run(assert_metrics(provider="networkx", include_optional=True))

View file

@ -7,7 +7,7 @@ from cognee.shared.logging_utils import get_logger
from cognee.modules.users.methods import get_default_user, create_user
from cognee.modules.users.permissions.methods import authorized_give_permission_on_datasets
from cognee.modules.data.methods import get_dataset_data, get_datasets_by_name
from cognee.api.v1.delete.exceptions import DocumentNotFoundError, DatasetNotFoundError
from cognee.api.v1.exceptions import DocumentNotFoundError, DatasetNotFoundError
logger = get_logger()

View file

@ -1,8 +1,8 @@
import numpy as np
import pytest
from cognee.exceptions import InvalidValueError
from cognee.modules.graph.cognee_graph.CogneeGraphElements import Edge, Node
from cognee.modules.graph.exceptions import InvalidDimensionsError, DimensionOutOfRangeError
def test_node_initialization():
@ -16,7 +16,7 @@ def test_node_initialization():
def test_node_invalid_dimension():
"""Test that initializing a Node with a non-positive dimension raises an error."""
with pytest.raises(InvalidValueError, match="Dimension must be a positive integer"):
with pytest.raises(InvalidDimensionsError):
Node("node1", dimension=0)
@ -69,7 +69,7 @@ def test_is_node_alive_in_dimension():
def test_node_alive_invalid_dimension():
"""Test that checking alive status with an invalid dimension raises an error."""
node = Node("node1", dimension=1)
with pytest.raises(InvalidValueError, match="Dimension 1 is out of range"):
with pytest.raises(DimensionOutOfRangeError):
node.is_node_alive_in_dimension(1)
@ -106,7 +106,7 @@ def test_edge_invalid_dimension():
"""Test that initializing an Edge with a non-positive dimension raises an error."""
node1 = Node("node1")
node2 = Node("node2")
with pytest.raises(InvalidValueError, match="Dimensions must be a positive integer."):
with pytest.raises(InvalidDimensionsError):
Edge(node1, node2, dimension=0)
@ -125,7 +125,7 @@ def test_edge_alive_invalid_dimension():
node1 = Node("node1")
node2 = Node("node2")
edge = Edge(node1, node2, dimension=1)
with pytest.raises(InvalidValueError, match="Dimension 1 is out of range"):
with pytest.raises(DimensionOutOfRangeError):
edge.is_edge_alive_in_dimension(1)

View file

@ -5,7 +5,7 @@ from unittest.mock import AsyncMock, MagicMock, patch
import pytest
from pylint.checkers.utils import node_type
from cognee.exceptions import InvalidValueError
from cognee.modules.search.exceptions import UnsupportedSearchTypeError
from cognee.modules.search.methods.search import search, specific_search
from cognee.modules.search.types import SearchType
from cognee.modules.users.models import User
@ -217,7 +217,7 @@ async def test_specific_search_invalid_type(mock_user):
query_type = "INVALID_TYPE" # Not a valid SearchType
# Execute and verify
with pytest.raises(InvalidValueError) as excinfo:
with pytest.raises(UnsupportedSearchTypeError) as excinfo:
await specific_search(query_type, query, mock_user)
assert "Unsupported search type" in str(excinfo.value)

View file

@ -1,7 +1,7 @@
[project]
name = "cognee"
version = "0.2.2"
version = "0.2.3.dev1"
description = "Cognee - is a library for enriching LLM context with a semantic layer for better understanding and reasoning."
authors = [
{ name = "Vasilije Markovic" },
@ -156,7 +156,6 @@ exclude = [
"/.data",
"/.github",
"/alembic",
"/distributed",
"/deployment",
"/cognee-mcp",
"/cognee-frontend",