From 8992670a15921b094d1e96535fe56eb2d499e41a Mon Sep 17 00:00:00 2001 From: emrgnt-cmplxty Date: Fri, 4 Oct 2024 12:49:26 -0700 Subject: [PATCH 01/30] add postgres to integration --- .../integration-test-workflow-debian.yml | 149 +++--------------- 1 file changed, 18 insertions(+), 131 deletions(-) diff --git a/.github/workflows/integration-test-workflow-debian.yml b/.github/workflows/integration-test-workflow-debian.yml index 70f754484..43f039600 100644 --- a/.github/workflows/integration-test-workflow-debian.yml +++ b/.github/workflows/integration-test-workflow-debian.yml @@ -1,10 +1,14 @@ -name: R2R CLI Integration Test (Debian GNU/Linux 12 (bookworm) amd64) +name: R2R CLI Integration (ubuntu latest) on: + pull_request: + branches: + - 'dev*' + - 'dev-minor*' push: branches: - - '**' - workflow_dispatch: + - 'dev*' + - 'dev-minor*' jobs: build-and-test: @@ -16,133 +20,16 @@ jobs: env: OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} TELEMETRY_ENABLED: false - POSTGRES_USER: ${{ secrets.POSTGRES_USER }} - POSTGRES_PASSWORD: ${{ secrets.POSTGRES_PASSWORD }} - POSTGRES_DBNAME: ${{ secrets.POSTGRES_DBNAME }} - POSTGRES_HOST: ${{ secrets.POSTGRES_HOST }} - POSTGRES_PORT: ${{ secrets.POSTGRES_PORT }} - R2R_PROJECT_NAME: ${{ secrets.R2R_PROJECT_NAME }} + POSTGRES_HOST: localhost + POSTGRES_DBNAME: postgres + POSTGRES_PORT: 5432 + POSTGRES_PASSWORD: postgres + POSTGRES_USER: postgres steps: - - uses: actions/checkout@v4 - - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: '3.x' - - - name: Install Poetry - run: | - curl -sSL https://install.python-poetry.org | python3 - - - - name: Install dependencies - working-directory: ./py - run: | - poetry install -E core -E ingestion-bundle - - - name: Start R2R server - working-directory: ./py - run: | - poetry run r2r serve & - echo "Waiting for services to start..." - sleep 30 - - - name: Run integration tests - working-directory: ./py - run: | - echo "R2R Version" - poetry run r2r version - - - name: Walkthrough - working-directory: ./py - run: | - echo "Ingest Data" - poetry run r2r ingest-sample-files - - echo "Get Documents Overview" - poetry run r2r documents-overview - - echo "Get Document Chunks" - poetry run r2r document-chunks --document-id=9fbe403b-c11c-5aae-8ade-ef22980c3ad1 - - echo "Delete Documents" - poetry run r2r delete --filter=document_id:eq:9fbe403b-c11c-5aae-8ade-ef22980c3ad1 - - echo "Update Document" - poetry run r2r update-files core/examples/data/aristotle_v2.txt --document-ids=9fbe403b-c11c-5aae-8ade-ef22980c3ad1 - - echo "Vector Search" - poetry run r2r search --query="What was Uber's profit in 2020?" - - echo "Hybrid Search" - r2r search --query="What was Uber's profit in 2020?" --use-hybrid-search - - echo "Basic RAG" - poetry run r2r rag --query="What was Uber's profit in 2020?" - - echo "RAG with Hybrid Search" - poetry run r2r rag --query="Who is Jon Snow?" --use-hybrid-search - - echo "Streaming RAG" - poetry run r2r rag --query="who was aristotle" --use-hybrid-search --stream - - echo "User Registration" - curl -X POST http://localhost:7272/v2/register \ - -H "Content-Type: application/json" \ - -d '{ - "email": "test@example.com", - "password": "password123" - }' - - echo "User Login" - curl -X POST http://localhost:7272/v2/login \ - -H "Content-Type: application/x-www-form-urlencoded" \ - -d "username=test@example.com&password=password123" - - echo "Users Overview" - poetry run r2r users-overview - - echo "Logging" - poetry run r2r logs - - echo "Analytics" - poetry run r2r analytics --filters '{"search_latencies": "search_latency"}' --analysis-types '{"search_latencies": ["basic_statistics", "search_latency"]}' - - - name: GraphRAG - working-directory: ./py - run: | - echo "Create Knowledge Graph" - poetry run r2r create-graph --document-ids=9fbe403b-c11c-5aae-8ade-ef22980c3ad1 - - echo "Inspect Knowledge Graph" - poetry run r2r inspect-knowledge-graph - - echo "Graph Enrichment" - poetry run r2r enrich-graph - - echo "Local Search" - r2r search --query="Who is Aristotle?" --use-kg-search --kg-search-type=local - - echo "Global Search" - r2r search --query="What were Aristotles key contributions to philosophy?" --use-kg-search --kg-search-type=global --max-llm-queries-for-global-search=100 - - echo "RAG" - r2r rag --query="What are the key contributions of Aristotle to modern society?" --use-kg-search --kg-search-type=global --max-llm-queries-for-global-search=100 - - - - - - - - name: Advanced RAG - working-directory: ./py - run: | - echo "HyDE" - poetry run r2r rag --query="who was aristotle" --use-hybrid-search --stream --search-strategy=hyde - - echo "Rag-Fusion" - r2r rag --query="Explain the theory of relativity" --use-hybrid-search --stream --search-strategy=rag_fusion - - - name: Stop R2R server - run: | - pkill -f "r2r serve" + - name: Install and configure PostgreSQL + run: | + sudo apt-get update + sudo apt-get install -y postgresql + sudo systemctl start postgresql.service + sudo -u postgres psql -c "ALTER USER postgres PASSWORD 'postgres';" From 9d0c824fdcbf9edef7fe68679002fffd99298208 Mon Sep 17 00:00:00 2001 From: emrgnt-cmplxty Date: Fri, 4 Oct 2024 12:49:45 -0700 Subject: [PATCH 02/30] add postgres to integration --- .github/workflows/integration-test-workflow-debian.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/integration-test-workflow-debian.yml b/.github/workflows/integration-test-workflow-debian.yml index 43f039600..98f3a7324 100644 --- a/.github/workflows/integration-test-workflow-debian.yml +++ b/.github/workflows/integration-test-workflow-debian.yml @@ -33,3 +33,11 @@ jobs: sudo apt-get install -y postgresql sudo systemctl start postgresql.service sudo -u postgres psql -c "ALTER USER postgres PASSWORD 'postgres';" + + # Add your other steps here + + - name: Cleanup PostgreSQL + if: always() # Run this step even if the job fails + run: | + sudo systemctl stop postgresql.service + sudo rm -rf /var/lib/postgresql/ \ No newline at end of file From 32bba85d21ff8f492dc79ae0ac17573790f54c8c Mon Sep 17 00:00:00 2001 From: emrgnt-cmplxty Date: Fri, 4 Oct 2024 14:00:46 -0700 Subject: [PATCH 03/30] up --- .../integration-test-workflow-debian.yml | 58 ++++++++------ py/tests/integration/runner.py | 78 +++++++++++++++++++ 2 files changed, 111 insertions(+), 25 deletions(-) create mode 100644 py/tests/integration/runner.py diff --git a/.github/workflows/integration-test-workflow-debian.yml b/.github/workflows/integration-test-workflow-debian.yml index 98f3a7324..a7af81442 100644 --- a/.github/workflows/integration-test-workflow-debian.yml +++ b/.github/workflows/integration-test-workflow-debian.yml @@ -1,14 +1,9 @@ -name: R2R CLI Integration (ubuntu latest) +name: R2R CLI Integration and Regression Test on: - pull_request: - branches: - - 'dev*' - - 'dev-minor*' push: - branches: - - 'dev*' - - 'dev-minor*' + branches: ['**'] + workflow_dispatch: jobs: build-and-test: @@ -20,24 +15,37 @@ jobs: env: OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} TELEMETRY_ENABLED: false - POSTGRES_HOST: localhost - POSTGRES_DBNAME: postgres - POSTGRES_PORT: 5432 - POSTGRES_PASSWORD: postgres - POSTGRES_USER: postgres + POSTGRES_USER: ${{ secrets.POSTGRES_USER }} + POSTGRES_PASSWORD: ${{ secrets.POSTGRES_PASSWORD }} + POSTGRES_DBNAME: ${{ secrets.POSTGRES_DBNAME }} + POSTGRES_HOST: ${{ secrets.POSTGRES_HOST }} + POSTGRES_PORT: ${{ secrets.POSTGRES_PORT }} + R2R_PROJECT_NAME: ${{ secrets.R2R_PROJECT_NAME }} steps: - - name: Install and configure PostgreSQL - run: | - sudo apt-get update - sudo apt-get install -y postgresql - sudo systemctl start postgresql.service - sudo -u postgres psql -c "ALTER USER postgres PASSWORD 'postgres';" + - uses: actions/checkout@v4 + - uses: actions/setup-python@v4 + with: + python-version: '3.x' - # Add your other steps here + - name: Install Poetry and dependencies + run: | + curl -sSL https://install.python-poetry.org | python3 - + cd py && poetry install -E core -E ingestion-bundle - - name: Cleanup PostgreSQL - if: always() # Run this step even if the job fails - run: | - sudo systemctl stop postgresql.service - sudo rm -rf /var/lib/postgresql/ \ No newline at end of file + - name: Start R2R server + working-directory: ./py + run: | + poetry run r2r serve & + echo "Waiting for services to start..." + sleep 30 + + - name: Run integration tests + working-directory: ./py + run: | + python tests/integration/r2r_integration_tests.py test_ingest_sample_files_cli + python tests/integration/r2r_integration_tests.py test_document_ingestion_cli + + - name: Stop R2R server + if: always() + run: pkill -f "r2r serve" diff --git a/py/tests/integration/runner.py b/py/tests/integration/runner.py new file mode 100644 index 000000000..350335479 --- /dev/null +++ b/py/tests/integration/runner.py @@ -0,0 +1,78 @@ +# File: tests/integration/r2r_integration_tests.py + +import json +import subprocess +import sys + + +def run_command(command): + result = subprocess.run( + command, shell=True, capture_output=True, text=True + ) + if result.returncode != 0: + print(f"Command failed: {command}") + print(f"Error: {result.stderr}") + sys.exit(1) + return result.stdout + + +def test_ingest_sample_files_cli(): + print("Testing: Ingest sample files") + run_command("poetry run r2r ingest-sample-files") + print("Ingestion successful") + + +def test_document_ingestion_cli(): + print("Testing: Document ingestion") + output = run_command("poetry run r2r documents-overview") + documents = json.loads(output) + + expected_document = { + "id": "9fbe403b-c11c-5aae-8ade-ef22980c3ad1", + "title": "aristotle.txt", + "type": "txt", + "ingestion_status": "success", + "kg_extraction_status": "success", + "version": "v0", + "metadata": {"title": "aristotle.txt", "version": "v0"}, + } + + if not any( + all(doc.get(k) == v for k, v in expected_document.items()) + for doc in documents + ): + print("Document ingestion test failed") + print(f"Expected document not found in output: {output}") + sys.exit(1) + print("Document ingestion test passed") + + +def test_vector_search_cli(): + print("Testing: Vector search") + output = run_command( + "poetry run r2r search --query='What was Uber's profit in 2020?'" + ) + results = json.loads(output) + if not results.get("results"): + print("Vector search test failed: No results returned") + sys.exit(1) + print("Vector search test passed") + + +def test_rag_query_cli(): + print("Testing: RAG query") + output = run_command("poetry run r2r rag --query='Who was Aristotle?'") + response = json.loads(output) + if not response.get("answer"): + print("RAG query test failed: No answer returned") + sys.exit(1) + print("RAG query test passed") + + +if __name__ == "__main__": + if len(sys.argv) < 2: + print("Please specify a test function to run") + sys.exit(1) + + test_function = sys.argv[1] + globals()[test_function]() From 04c437c9d75a27d175b0b4982c4ace056443e679 Mon Sep 17 00:00:00 2001 From: emrgnt-cmplxty Date: Fri, 4 Oct 2024 14:02:32 -0700 Subject: [PATCH 04/30] rename --- .github/workflows/integration-test-workflow-debian.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/integration-test-workflow-debian.yml b/.github/workflows/integration-test-workflow-debian.yml index a7af81442..fc435d6e6 100644 --- a/.github/workflows/integration-test-workflow-debian.yml +++ b/.github/workflows/integration-test-workflow-debian.yml @@ -43,8 +43,8 @@ jobs: - name: Run integration tests working-directory: ./py run: | - python tests/integration/r2r_integration_tests.py test_ingest_sample_files_cli - python tests/integration/r2r_integration_tests.py test_document_ingestion_cli + python tests/integration/runner.py test_ingest_sample_files_cli + python tests/integration/runner.py test_document_ingestion_cli - name: Stop R2R server if: always() From 6843c4b4df607374cdc93683cb729e2ff79996db Mon Sep 17 00:00:00 2001 From: emrgnt-cmplxty Date: Fri, 4 Oct 2024 14:06:41 -0700 Subject: [PATCH 05/30] hardcode --- .../workflows/integration-test-workflow-debian.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/integration-test-workflow-debian.yml b/.github/workflows/integration-test-workflow-debian.yml index fc435d6e6..79338ae71 100644 --- a/.github/workflows/integration-test-workflow-debian.yml +++ b/.github/workflows/integration-test-workflow-debian.yml @@ -15,12 +15,12 @@ jobs: env: OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} TELEMETRY_ENABLED: false - POSTGRES_USER: ${{ secrets.POSTGRES_USER }} - POSTGRES_PASSWORD: ${{ secrets.POSTGRES_PASSWORD }} - POSTGRES_DBNAME: ${{ secrets.POSTGRES_DBNAME }} - POSTGRES_HOST: ${{ secrets.POSTGRES_HOST }} - POSTGRES_PORT: ${{ secrets.POSTGRES_PORT }} - R2R_PROJECT_NAME: ${{ secrets.R2R_PROJECT_NAME }} + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DBNAME: postgres + POSTGRES_HOST: localhost + POSTGRES_PORT: 5432 + R2R_PROJECT_NAME: R2R steps: - uses: actions/checkout@v4 From 5bebd3bc6d94d6d6a09d7e2e723fecca699faac9 Mon Sep 17 00:00:00 2001 From: emrgnt-cmplxty Date: Fri, 4 Oct 2024 14:09:40 -0700 Subject: [PATCH 06/30] add back postgres --- .../integration-test-workflow-debian.yml | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/.github/workflows/integration-test-workflow-debian.yml b/.github/workflows/integration-test-workflow-debian.yml index 79338ae71..72cee2f8a 100644 --- a/.github/workflows/integration-test-workflow-debian.yml +++ b/.github/workflows/integration-test-workflow-debian.yml @@ -15,14 +15,19 @@ jobs: env: OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} TELEMETRY_ENABLED: false - POSTGRES_USER: postgres - POSTGRES_PASSWORD: postgres - POSTGRES_DBNAME: postgres POSTGRES_HOST: localhost + POSTGRES_DBNAME: postgres POSTGRES_PORT: 5432 - R2R_PROJECT_NAME: R2R - + POSTGRES_PASSWORD: postgres + POSTGRES_USER: postgres steps: + - name: Install and configure PostgreSQL + run: | + sudo apt-get update + sudo apt-get install -y postgresql + sudo systemctl start postgresql.service + sudo -u postgres psql -c "ALTER USER postgres PASSWORD 'postgres';" + - uses: actions/checkout@v4 - uses: actions/setup-python@v4 with: From 2924dfaee2e724d3d15b0dde7d6f64004ae5c57f Mon Sep 17 00:00:00 2001 From: emrgnt-cmplxty Date: Fri, 4 Oct 2024 14:18:30 -0700 Subject: [PATCH 07/30] add back postgres --- .../integration-test-workflow-debian.yml | 1 + py/core/__init__.py | 1 + py/core/base/__init__.py | 1 + py/tests/conftest.py | 38 +++++++++++-------- 4 files changed, 25 insertions(+), 16 deletions(-) diff --git a/.github/workflows/integration-test-workflow-debian.yml b/.github/workflows/integration-test-workflow-debian.yml index 72cee2f8a..697f7eb34 100644 --- a/.github/workflows/integration-test-workflow-debian.yml +++ b/.github/workflows/integration-test-workflow-debian.yml @@ -20,6 +20,7 @@ jobs: POSTGRES_PORT: 5432 POSTGRES_PASSWORD: postgres POSTGRES_USER: postgres + R2R_PROJECT_NAME: r2r_default steps: - name: Install and configure PostgreSQL run: | diff --git a/py/core/__init__.py b/py/core/__init__.py index ae875d33a..b4c7421a3 100644 --- a/py/core/__init__.py +++ b/py/core/__init__.py @@ -130,6 +130,7 @@ "PipeType", ## PROVIDERS # Base provider classes + "AppConfig", "Provider", "ProviderConfig", # Auth provider diff --git a/py/core/base/__init__.py b/py/core/base/__init__.py index 779fb8710..47c166b8a 100644 --- a/py/core/base/__init__.py +++ b/py/core/base/__init__.py @@ -103,6 +103,7 @@ "PipeType", ## PROVIDERS # Base provider classes + "AppConfig", "Provider", "ProviderConfig", # Auth provider diff --git a/py/tests/conftest.py b/py/tests/conftest.py index e8a3b83ca..0731cacfa 100644 --- a/py/tests/conftest.py +++ b/py/tests/conftest.py @@ -6,6 +6,7 @@ import pytest from core import ( + AppConfig, AuthConfig, BCryptConfig, CompletionConfig, @@ -59,32 +60,35 @@ def generate_random_vector_entry( generate_random_vector_entry(i, dimension) for i in range(num_entries) ] +@pytest.fixture(scope="session") +def app_config(): + return AppConfig() # Crypto @pytest.fixture(scope="session") -def crypto_config(): - return BCryptConfig() +def crypto_config(app_config): + return BCryptConfig(app=app_config) @pytest.fixture(scope="session") -def crypto_provider(crypto_config): +def crypto_provider(crypto_config, app_config): return BCryptProvider(crypto_config) # Postgres @pytest.fixture(scope="session") -def db_config(): +def db_config(app_config): collection_id = uuid.uuid4() random_project_name = f"test_collection_{collection_id.hex}" return DatabaseConfig.create( - provider="postgres", project_name=random_project_name + provider="postgres", project_name=random_project_name, app=app_config ) @pytest.fixture(scope="function") async def postgres_db_provider( - db_config, dimension, crypto_provider, sample_entries + db_config, dimension, crypto_provider, sample_entries, app_config ): db = PostgresDBProvider( db_config, dimension=dimension, crypto_provider=crypto_provider @@ -98,12 +102,12 @@ async def postgres_db_provider( @pytest.fixture(scope="function") -def db_config_temporary(): +def db_config_temporary(app_config): collection_id = uuid.uuid4() random_project_name = f"test_collection_{collection_id.hex}" return DatabaseConfig.create( - provider="postgres", project_name=random_project_name + provider="postgres", project_name=random_project_name, app=app_config ) @@ -127,12 +131,13 @@ async def temporary_postgres_db_provider( # Auth @pytest.fixture(scope="session") -def auth_config(): +def auth_config(app_config): return AuthConfig( secret_key="test_secret_key", access_token_lifetime_in_minutes=15, refresh_token_lifetime_in_days=1, require_email_verification=False, + app=app_config ) @@ -149,19 +154,20 @@ async def r2r_auth_provider( # Embeddings @pytest.fixture -def litellm_provider(): +def litellm_provider(app_config): config = EmbeddingConfig( provider="litellm", base_model="text-embedding-3-small", base_dimension=1536, + app=app_config ) return LiteLLMEmbeddingProvider(config) # File Provider @pytest.fixture(scope="function") -def file_config(): - return FileConfig(provider="postgres") +def file_config(app_config): + return FileConfig(provider="postgres", app=app_config) @pytest.fixture(scope="function") @@ -176,18 +182,18 @@ async def postgres_file_provider(file_config, temporary_postgres_db_provider): # LLM provider @pytest.fixture -def litellm_completion_provider(): - config = CompletionConfig(provider="litellm") +def litellm_completion_provider(app_config): + config = CompletionConfig(provider="litellm", app=app_config) return LiteCompletionProvider(config) # Logging @pytest.fixture(scope="function") -async def local_logging_provider(): +async def local_logging_provider(app_config): unique_id = str(uuid.uuid4()) logging_path = f"test_{unique_id}.sqlite" provider = LocalRunLoggingProvider( - LoggingConfig(logging_path=logging_path) + LoggingConfig(logging_path=logging_path, app=app_config) ) await provider._init() yield provider From b11ce365b24e8de4fbd262b583c89cc4b4e6d50a Mon Sep 17 00:00:00 2001 From: emrgnt-cmplxty Date: Fri, 4 Oct 2024 14:22:17 -0700 Subject: [PATCH 08/30] add pgvector --- .../integration-test-workflow-debian.yml | 11 +++++++++++ py/tests/core/providers/embedding/conftest.py | 6 ++++-- .../embedding/test_litellm_embedding_provider.py | 16 ++++++++++------ 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/.github/workflows/integration-test-workflow-debian.yml b/.github/workflows/integration-test-workflow-debian.yml index 697f7eb34..84b73b025 100644 --- a/.github/workflows/integration-test-workflow-debian.yml +++ b/.github/workflows/integration-test-workflow-debian.yml @@ -29,6 +29,17 @@ jobs: sudo systemctl start postgresql.service sudo -u postgres psql -c "ALTER USER postgres PASSWORD 'postgres';" + - name: Install pgvector + run: | + sudo apt-get install -y build-essential + sudo apt-get install -y postgresql-server-dev-all + git clone https://github.com/pgvector/pgvector.git + cd pgvector + make + sudo make install + cd .. + sudo -u postgres psql -c "CREATE EXTENSION vector;" + - uses: actions/checkout@v4 - uses: actions/setup-python@v4 with: diff --git a/py/tests/core/providers/embedding/conftest.py b/py/tests/core/providers/embedding/conftest.py index 48cf7fb69..75e67a124 100644 --- a/py/tests/core/providers/embedding/conftest.py +++ b/py/tests/core/providers/embedding/conftest.py @@ -20,20 +20,22 @@ async def cleanup_tasks(): @pytest.fixture -def openai_provider(): +def openai_provider(app_config): config = EmbeddingConfig( provider="openai", base_model="text-embedding-ada-002", base_dimension=1536, + app=app_config ) return OpenAIEmbeddingProvider(config) @pytest.fixture -def ollama_provider(): +def ollama_provider(app_config): config = EmbeddingConfig( provider="ollama", base_model="mxbai-embed-large", base_dimension=1024, + app=app_config ) return OllamaEmbeddingProvider(config) diff --git a/py/tests/core/providers/embedding/test_litellm_embedding_provider.py b/py/tests/core/providers/embedding/test_litellm_embedding_provider.py index b3c35a83e..e66eaf36c 100644 --- a/py/tests/core/providers/embedding/test_litellm_embedding_provider.py +++ b/py/tests/core/providers/embedding/test_litellm_embedding_provider.py @@ -21,11 +21,12 @@ async def cleanup_tasks(): @pytest.fixture -def litellm_provider(): +def litellm_provider(app_config): config = EmbeddingConfig( provider="litellm", base_model="openai/text-embedding-3-small", base_dimension=1536, + app=app_config ) return LiteLLMEmbeddingProvider(config) @@ -37,9 +38,9 @@ def test_litellm_initialization(litellm_provider): assert litellm_provider.base_dimension == 1536 -def test_litellm_invalid_provider_initialization(): +def test_litellm_invalid_provider_initialization(app_config): with pytest.raises(ValueError): - config = EmbeddingConfig(provider="invalid_provider") + config = EmbeddingConfig(provider="invalid_provider", app=app_config) LiteLLMEmbeddingProvider(config) @@ -73,12 +74,13 @@ async def test_litellm_async_get_embeddings(litellm_provider): assert all(len(emb) == 1536 for emb in embeddings) -def test_litellm_rerank_model_not_supported(): +def test_litellm_rerank_model_not_supported(app_config): config = EmbeddingConfig( provider="litellm", base_model="openai/text-embedding-3-small", base_dimension=1536, rerank_model="some-model", + app=app_config ) with pytest.raises( ValueError, match="does not support separate reranking" @@ -86,11 +88,12 @@ def test_litellm_rerank_model_not_supported(): LiteLLMEmbeddingProvider(config) -def test_litellm_unsupported_stage(): +def test_litellm_unsupported_stage(app_config): config = EmbeddingConfig( provider="litellm", base_model="openai/text-embedding-3-small", base_dimension=1536, + app=app_config ) provider = LiteLLMEmbeddingProvider(config) with pytest.raises( @@ -102,11 +105,12 @@ def test_litellm_unsupported_stage(): @pytest.mark.asyncio -async def test_litellm_async_unsupported_stage(): +async def test_litellm_async_unsupported_stage(app_config): config = EmbeddingConfig( provider="litellm", base_model="openai/text-embedding-3-small", base_dimension=1536, + app=app_config ) provider = LiteLLMEmbeddingProvider(config) with pytest.raises( From 54380c1317af405011695236f6386eca2ba7615d Mon Sep 17 00:00:00 2001 From: emrgnt-cmplxty Date: Fri, 4 Oct 2024 14:24:31 -0700 Subject: [PATCH 09/30] add pgvector --- .github/workflows/integration-test-workflow-debian.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/integration-test-workflow-debian.yml b/.github/workflows/integration-test-workflow-debian.yml index 84b73b025..dd3662f6d 100644 --- a/.github/workflows/integration-test-workflow-debian.yml +++ b/.github/workflows/integration-test-workflow-debian.yml @@ -25,6 +25,7 @@ jobs: - name: Install and configure PostgreSQL run: | sudo apt-get update + sudo apt-get upgrade -y sudo apt-get install -y postgresql sudo systemctl start postgresql.service sudo -u postgres psql -c "ALTER USER postgres PASSWORD 'postgres';" From 494f03c79bfdf3014b14f530516059d5f86606d6 Mon Sep 17 00:00:00 2001 From: emrgnt-cmplxty Date: Fri, 4 Oct 2024 14:30:59 -0700 Subject: [PATCH 10/30] add pgvector --- .../integration-test-workflow-debian.yml | 37 +++++++++++-------- py/tests/conftest.py | 12 +++--- 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/.github/workflows/integration-test-workflow-debian.yml b/.github/workflows/integration-test-workflow-debian.yml index dd3662f6d..0f99b91ef 100644 --- a/.github/workflows/integration-test-workflow-debian.yml +++ b/.github/workflows/integration-test-workflow-debian.yml @@ -2,8 +2,9 @@ name: R2R CLI Integration and Regression Test on: push: - branches: ['**'] - workflow_dispatch: + branches: + - '**' # Trigger on all branches + workflow_dispatch: # Allow manual trigger jobs: build-and-test: @@ -21,7 +22,21 @@ jobs: POSTGRES_PASSWORD: postgres POSTGRES_USER: postgres R2R_PROJECT_NAME: r2r_default + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Python environment + uses: actions/setup-python@v4 + with: + python-version: '3.x' + + - name: Install Poetry and dependencies + run: | + curl -sSL https://install.python-poetry.org | python3 - + cd py && poetry install -E core -E ingestion-bundle + - name: Install and configure PostgreSQL run: | sudo apt-get update @@ -32,24 +47,16 @@ jobs: - name: Install pgvector run: | - sudo apt-get install -y build-essential - sudo apt-get install -y postgresql-server-dev-all + sudo apt-get install -y build-essential postgresql-server-dev-all git clone https://github.com/pgvector/pgvector.git cd pgvector make sudo make install cd .. sudo -u postgres psql -c "CREATE EXTENSION vector;" - - - uses: actions/checkout@v4 - - uses: actions/setup-python@v4 - with: - python-version: '3.x' - - name: Install Poetry and dependencies - run: | - curl -sSL https://install.python-poetry.org | python3 - - cd py && poetry install -E core -E ingestion-bundle + - name: Start PostgreSQL + run: sudo systemctl start postgresql.service - name: Start R2R server working-directory: ./py @@ -58,7 +65,7 @@ jobs: echo "Waiting for services to start..." sleep 30 - - name: Run integration tests + - name: Run integration tests - Ingestion working-directory: ./py run: | python tests/integration/runner.py test_ingest_sample_files_cli @@ -66,4 +73,4 @@ jobs: - name: Stop R2R server if: always() - run: pkill -f "r2r serve" + run: pkill -f "r2r serve" \ No newline at end of file diff --git a/py/tests/conftest.py b/py/tests/conftest.py index 0731cacfa..023a4a139 100644 --- a/py/tests/conftest.py +++ b/py/tests/conftest.py @@ -62,7 +62,12 @@ def generate_random_vector_entry( @pytest.fixture(scope="session") def app_config(): - return AppConfig() + collection_id = uuid.uuid4() + + random_project_name = f"_{collection_id.hex}_test_project" + print("random_project_name", random_project_name) + + return AppConfig(project_name=random_project_name) # Crypto @pytest.fixture(scope="session") @@ -78,11 +83,8 @@ def crypto_provider(crypto_config, app_config): # Postgres @pytest.fixture(scope="session") def db_config(app_config): - collection_id = uuid.uuid4() - - random_project_name = f"test_collection_{collection_id.hex}" return DatabaseConfig.create( - provider="postgres", project_name=random_project_name, app=app_config + provider="postgres", app=app_config ) From 1961b2cfea284252fd71630edc285edd42c9556b Mon Sep 17 00:00:00 2001 From: emrgnt-cmplxty Date: Fri, 4 Oct 2024 14:37:31 -0700 Subject: [PATCH 11/30] add pgvector --- .../integration-test-workflow-debian.yml | 35 +++++++++---------- py/tests/conftest.py | 2 +- 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/.github/workflows/integration-test-workflow-debian.yml b/.github/workflows/integration-test-workflow-debian.yml index 0f99b91ef..5fd339e4e 100644 --- a/.github/workflows/integration-test-workflow-debian.yml +++ b/.github/workflows/integration-test-workflow-debian.yml @@ -30,34 +30,31 @@ jobs: - name: Set up Python environment uses: actions/setup-python@v4 with: - python-version: '3.x' + python-version: '3.10' # Use a stable Python version - name: Install Poetry and dependencies run: | curl -sSL https://install.python-poetry.org | python3 - cd py && poetry install -E core -E ingestion-bundle - - name: Install and configure PostgreSQL + - name: Add PostgreSQL Apt Repository + run: | + sudo sh -c 'echo "deb [signed-by=/usr/share/keyrings/postgresql-archive-keyring.gpg] http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list' + wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo tee /usr/share/keyrings/postgresql-archive-keyring.gpg > /dev/null + + - name: Install PostgreSQL and pgvector run: | sudo apt-get update - sudo apt-get upgrade -y - sudo apt-get install -y postgresql - sudo systemctl start postgresql.service - sudo -u postgres psql -c "ALTER USER postgres PASSWORD 'postgres';" + sudo apt-get install -y postgresql-15 postgresql-client-15 postgresql-15-pgvector - - name: Install pgvector + - name: Start PostgreSQL service + run: sudo systemctl start postgresql + + - name: Configure PostgreSQL run: | - sudo apt-get install -y build-essential postgresql-server-dev-all - git clone https://github.com/pgvector/pgvector.git - cd pgvector - make - sudo make install - cd .. + sudo -u postgres psql -c "ALTER USER postgres PASSWORD 'postgres';" sudo -u postgres psql -c "CREATE EXTENSION vector;" - - name: Start PostgreSQL - run: sudo systemctl start postgresql.service - - name: Start R2R server working-directory: ./py run: | @@ -68,9 +65,9 @@ jobs: - name: Run integration tests - Ingestion working-directory: ./py run: | - python tests/integration/runner.py test_ingest_sample_files_cli - python tests/integration/runner.py test_document_ingestion_cli + poetry run python tests/integration/runner.py test_ingest_sample_files_cli + poetry run python tests/integration/runner.py test_document_ingestion_cli - name: Stop R2R server if: always() - run: pkill -f "r2r serve" \ No newline at end of file + run: pkill -f "r2r serve" diff --git a/py/tests/conftest.py b/py/tests/conftest.py index 023a4a139..b77e3eff6 100644 --- a/py/tests/conftest.py +++ b/py/tests/conftest.py @@ -64,7 +64,7 @@ def generate_random_vector_entry( def app_config(): collection_id = uuid.uuid4() - random_project_name = f"_{collection_id.hex}_test_project" + random_project_name = f"a_{collection_id.hex}_test_project" print("random_project_name", random_project_name) return AppConfig(project_name=random_project_name) From beba917c136f044cc06dff5e8eb435546875b83a Mon Sep 17 00:00:00 2001 From: emrgnt-cmplxty Date: Fri, 4 Oct 2024 14:41:12 -0700 Subject: [PATCH 12/30] add pgvector --- .github/workflows/integration-test-workflow-debian.yml | 6 ++++-- py/tests/conftest.py | 3 +-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/integration-test-workflow-debian.yml b/.github/workflows/integration-test-workflow-debian.yml index 5fd339e4e..da18212b0 100644 --- a/.github/workflows/integration-test-workflow-debian.yml +++ b/.github/workflows/integration-test-workflow-debian.yml @@ -39,8 +39,10 @@ jobs: - name: Add PostgreSQL Apt Repository run: | - sudo sh -c 'echo "deb [signed-by=/usr/share/keyrings/postgresql-archive-keyring.gpg] http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list' - wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo tee /usr/share/keyrings/postgresql-archive-keyring.gpg > /dev/null + # Add the PostgreSQL Apt repository + echo "deb [signed-by=/usr/share/keyrings/postgresql-archive-keyring.gpg] http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" | sudo tee /etc/apt/sources.list.d/pgdg.list + # Download and add the repository GPG key + wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo gpg --dearmor -o /usr/share/keyrings/postgresql-archive-keyring.gpg - name: Install PostgreSQL and pgvector run: | diff --git a/py/tests/conftest.py b/py/tests/conftest.py index b77e3eff6..d647fd482 100644 --- a/py/tests/conftest.py +++ b/py/tests/conftest.py @@ -60,12 +60,11 @@ def generate_random_vector_entry( generate_random_vector_entry(i, dimension) for i in range(num_entries) ] -@pytest.fixture(scope="session") +@pytest.fixture(scope="function") def app_config(): collection_id = uuid.uuid4() random_project_name = f"a_{collection_id.hex}_test_project" - print("random_project_name", random_project_name) return AppConfig(project_name=random_project_name) From ba3356840922f1fd7cf1057f98a953da355e3928 Mon Sep 17 00:00:00 2001 From: emrgnt-cmplxty Date: Fri, 4 Oct 2024 14:41:49 -0700 Subject: [PATCH 13/30] add pgvector --- py/tests/conftest.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/py/tests/conftest.py b/py/tests/conftest.py index d647fd482..5f24fc95d 100644 --- a/py/tests/conftest.py +++ b/py/tests/conftest.py @@ -29,17 +29,17 @@ # Vectors -@pytest.fixture(scope="session") +@pytest.fixture(scope="function") def dimension(): return 128 -@pytest.fixture(scope="session") +@pytest.fixture(scope="function") def num_entries(): return 100 -@pytest.fixture(scope="session") +@pytest.fixture(scope="function") def sample_entries(dimension, num_entries): def generate_random_vector_entry( id_value: int, dimension: int @@ -69,18 +69,18 @@ def app_config(): return AppConfig(project_name=random_project_name) # Crypto -@pytest.fixture(scope="session") +@pytest.fixture(scope="function") def crypto_config(app_config): return BCryptConfig(app=app_config) -@pytest.fixture(scope="session") +@pytest.fixture(scope="function") def crypto_provider(crypto_config, app_config): return BCryptProvider(crypto_config) # Postgres -@pytest.fixture(scope="session") +@pytest.fixture(scope="function") def db_config(app_config): return DatabaseConfig.create( provider="postgres", app=app_config @@ -131,7 +131,7 @@ async def temporary_postgres_db_provider( # Auth -@pytest.fixture(scope="session") +@pytest.fixture(scope="function") def auth_config(app_config): return AuthConfig( secret_key="test_secret_key", From f316e39d55548553a9a8ffcd3e0293f1bbb56d86 Mon Sep 17 00:00:00 2001 From: emrgnt-cmplxty Date: Fri, 4 Oct 2024 14:46:46 -0700 Subject: [PATCH 14/30] add pgvector --- .../integration-test-workflow-debian.yml | 29 +++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/.github/workflows/integration-test-workflow-debian.yml b/.github/workflows/integration-test-workflow-debian.yml index da18212b0..3c8dfcacd 100644 --- a/.github/workflows/integration-test-workflow-debian.yml +++ b/.github/workflows/integration-test-workflow-debian.yml @@ -37,6 +37,13 @@ jobs: curl -sSL https://install.python-poetry.org | python3 - cd py && poetry install -E core -E ingestion-bundle + - name: Remove pre-installed PostgreSQL + run: | + sudo apt-get purge -y 'postgresql-*' + sudo rm -rf /var/lib/postgresql + sudo rm -rf /var/log/postgresql + sudo rm -rf /etc/postgresql + - name: Add PostgreSQL Apt Repository run: | # Add the PostgreSQL Apt repository @@ -44,18 +51,22 @@ jobs: # Download and add the repository GPG key wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo gpg --dearmor -o /usr/share/keyrings/postgresql-archive-keyring.gpg - - name: Install PostgreSQL and pgvector + - name: Install PostgreSQL 15 and pgvector run: | sudo apt-get update sudo apt-get install -y postgresql-15 postgresql-client-15 postgresql-15-pgvector - - name: Start PostgreSQL service - run: sudo systemctl start postgresql + - name: Start PostgreSQL 15 service + run: | + sudo systemctl enable postgresql@15-main + sudo systemctl start postgresql@15-main - name: Configure PostgreSQL run: | - sudo -u postgres psql -c "ALTER USER postgres PASSWORD 'postgres';" - sudo -u postgres psql -c "CREATE EXTENSION vector;" + # Change to a directory accessible by the postgres user to avoid permission warnings + cd / + sudo -u postgres /usr/lib/postgresql/15/bin/psql -c "ALTER USER postgres PASSWORD 'postgres';" + sudo -u postgres /usr/lib/postgresql/15/bin/psql -c "CREATE EXTENSION vector;" - name: Start R2R server working-directory: ./py @@ -73,3 +84,11 @@ jobs: - name: Stop R2R server if: always() run: pkill -f "r2r serve" + + - name: Uninstall PostgreSQL after tests (Optional) + if: always() + run: | + sudo apt-get purge -y 'postgresql-*' + sudo rm -rf /var/lib/postgresql + sudo rm -rf /var/log/postgresql + sudo rm -rf /etc/postgresql From d11ed321fe3b9a6db56a71a17a13f94e1f7e59ed Mon Sep 17 00:00:00 2001 From: emrgnt-cmplxty Date: Fri, 4 Oct 2024 14:53:32 -0700 Subject: [PATCH 15/30] tweak config docs --- docs/api-reference/openapi.json | 2 +- py/core/main/api/ingestion_router.py | 9 +++------ py/core/main/api/kg_router.py | 2 +- py/core/main/api/retrieval_router.py | 6 +++--- py/core/main/orchestration/hatchet/kg_workflow.py | 6 +++--- py/tests/conftest.py | 10 +++++----- py/tests/core/providers/embedding/conftest.py | 4 ++-- .../embedding/test_litellm_embedding_provider.py | 8 ++++---- 8 files changed, 22 insertions(+), 25 deletions(-) diff --git a/docs/api-reference/openapi.json b/docs/api-reference/openapi.json index b6058b532..5f42c6c6d 100644 --- a/docs/api-reference/openapi.json +++ b/docs/api-reference/openapi.json @@ -1 +1 @@ -{"openapi":"3.1.0","info":{"title":"R2R Application API","version":"1.0.0"},"paths":{"/v2/ingest_files":{"post":{"summary":"Ingest Files App","description":"Ingest files into the system.\n\nThis endpoint supports multipart/form-data requests, enabling you to ingest files and their associated metadatas into R2R.\n\nA valid user authentication token is required to access this endpoint, as regular users can only ingest files for their own access. More expansive collection permissioning is under development.","operationId":"ingest_files_app_v2_ingest_files_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"response_model","in":"query","required":false,"schema":{"title":"Response Model"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_ingest_files_app_v2_ingest_files_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"x-codeSamples":[{"lang":"Python","source":"from r2r import R2RClient\n\nclient = R2RClient(\"http://localhost:7272\")\n# when using auth, do client.login(...)\n\nresult = client.ingest_files(\n file_paths=[\"pg_essay_1.html\", \"got.txt\"],\n metadatas=[{\"metadata_1\":\"some random metadata\"}, {\"metadata_2\": \"some other random metadata\"}],\n document_ids=None,\n versions=None\n)\n"},{"lang":"Shell","source":"curl -X POST \"https://api.example.com/ingest_files\" \\\n -H \"Content-Type: multipart/form-data\" \\\n -H \"Authorization: Bearer YOUR_API_KEY\" \\\n -F \"file=@pg_essay_1.html;type=text/html\" \\\n -F \"file=@got.txt;type=text/plain\" \\\n -F 'metadatas=[{},{}]' \\\n -F 'document_ids=null' \\\n -F 'versions=null'\n"}]}},"/v2/update_files":{"post":{"summary":"Update Files App","description":"Update existing files in the system.\n\nThis endpoint supports multipart/form-data requests, enabling you to update files and their associated metadatas into R2R.\n\nA valid user authentication token is required to access this endpoint, as regular users can only update their own files. More expansive collection permissioning is under development.","operationId":"update_files_app_v2_update_files_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"response_model","in":"query","required":false,"schema":{"title":"Response Model"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_update_files_app_v2_update_files_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"x-codeSamples":[{"lang":"Python","source":"from r2r import R2RClient\n\nclient = R2RClient(\"http://localhost:7272\")\n# when using auth, do client.login(...)\n\nresult = client.update_files(\n file_paths=[\"pg_essay_1_v2.txt\"],\n document_ids=[\"b4ac4dd6-5f27-596e-a55b-7cf242ca30aa\"]\n)\n"},{"lang":"Shell","source":"curl -X POST \"https://api.example.com/update_files\" \\\n -H \"Content-Type: multipart/form-data\" \\\n -H \"Authorization: Bearer YOUR_API_KEY\" \\\n -F \"file=@pg_essay_1_v2.txt;type=text/plain\" \\\n -F 'document_ids=[\"b4ac4dd6-5f27-596e-a55b-7cf242ca30aa\"]'\n"}]}},"/v2/ingest_chunks":{"post":{"summary":"Ingest Chunks App","description":"Ingest text chunks into the system.\n\nThis endpoint supports multipart/form-data requests, enabling you to ingest pre-parsed text chunks into R2R.\n\nA valid user authentication token is required to access this endpoint, as regular users can only ingest chunks for their own access. More expansive collection permissioning is under development.","operationId":"ingest_chunks_app_v2_ingest_chunks_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"response_model","in":"query","required":false,"schema":{"title":"Response Model"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_ingest_chunks_app_v2_ingest_chunks_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"x-codeSamples":[{"lang":"Python","source":"from r2r import R2RClient\n\nclient = R2RClient(\"http://localhost:7272\")\n# when using auth, do client.login(...)\n\nresult = client.ingest_chunks(\n chunks=[\n {\n \"text\": \"Another chunk of text\",\n },\n {\n \"text\": \"Yet another chunk of text\",\n },\n {\n \"text\": \"A chunk of text\",\n },\n ],\n)\n"},{"lang":"Shell","source":"curl -X POST \"https://api.example.com/ingest_chunks\" \\\n -H \"Content-Type: application/json\" \\\n -H \"Authorization: Bearer YOUR_API_KEY\" \\\n -d '{\n \"chunks\": [\n {\n \"text\": \"Another chunk of text\"\n },\n {\n \"text\": \"Yet another chunk of text\"\n },\n {\n \"text\": \"A chunk of text\"\n }\n ],\n \"document_id\": \"b4ac4dd6-5f27-596e-a55b-7cf242ca30aa\",\n \"metadata\": {}\n }'\n"}]}},"/v2/health":{"get":{"summary":"Health Check","operationId":"health_check_v2_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v2/server_stats":{"get":{"summary":"Server Stats","operationId":"server_stats_v2_server_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_ServerStats_"}}}}},"security":[{"HTTPBearer":[]}]}},"/v2/update_prompt":{"post":{"summary":"Update Prompt App","operationId":"update_prompt_app_v2_update_prompt_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_update_prompt_app_v2_update_prompt_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_UpdatePromptResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v2/add_prompt":{"post":{"summary":"Add Prompt App","operationId":"add_prompt_app_v2_add_prompt_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_add_prompt_app_v2_add_prompt_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_UpdatePromptResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v2/get_prompt/{prompt_name}":{"get":{"summary":"Get Prompt App","operationId":"get_prompt_app_v2_get_prompt__prompt_name__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"prompt_name","in":"path","required":true,"schema":{"type":"string","description":"Prompt name","title":"Prompt Name"},"description":"Prompt name"},{"name":"inputs","in":"query","required":false,"schema":{"anyOf":[{"type":"string","contentMediaType":"application/json","contentSchema":{"type":"object"}},{"type":"null"}],"description":"JSON-encoded prompt inputs","title":"Inputs"},"description":"JSON-encoded prompt inputs"},{"name":"prompt_override","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Prompt override","title":"Prompt Override"},"description":"Prompt override"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_UpdatePromptResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/get_all_prompts":{"get":{"summary":"Get All Prompts App","operationId":"get_all_prompts_app_v2_get_all_prompts_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_AllPromptsResponse_"}}}}},"security":[{"HTTPBearer":[]}]}},"/v2/delete_prompt/{prompt_name}":{"delete":{"summary":"Delete Prompt App","operationId":"delete_prompt_app_v2_delete_prompt__prompt_name__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"prompt_name","in":"path","required":true,"schema":{"type":"string","description":"Prompt name","title":"Prompt Name"},"description":"Prompt name"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_NoneType_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/analytics":{"get":{"summary":"Get Analytics App","operationId":"get_analytics_app_v2_analytics_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"filter_criteria","in":"query","required":false,"schema":{"anyOf":[{"type":"string","contentMediaType":"application/json","contentSchema":{"type":"object"}},{"type":"null"}],"default":{},"title":"Filter Criteria"}},{"name":"analysis_types","in":"query","required":false,"schema":{"anyOf":[{"type":"string","contentMediaType":"application/json","contentSchema":{"type":"object"}},{"type":"null"}],"default":{},"title":"Analysis Types"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_AnalyticsResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/logs":{"get":{"summary":"Logs App","operationId":"logs_app_v2_logs_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"run_type_filter","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":"","title":"Run Type Filter"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_list_LogResponse__"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/app_settings":{"get":{"summary":"App Settings","operationId":"app_settings_v2_app_settings_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_AppSettingsResponse_"}}}}},"security":[{"HTTPBearer":[]}]}},"/v2/score_completion":{"post":{"summary":"Score Completion","operationId":"score_completion_v2_score_completion_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_score_completion_v2_score_completion_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_ScoreCompletionResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v2/users_overview":{"get":{"summary":"Users Overview App","operationId":"users_overview_app_v2_users_overview_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_ids","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"default":[],"title":"User Ids"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResultsWrapper_list_UserOverviewResponse__"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/delete":{"delete":{"summary":"Delete App","operationId":"delete_app_v2_delete_delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"filters","in":"query","required":true,"schema":{"type":"string","description":"JSON-encoded filters","title":"Filters"},"description":"JSON-encoded filters"}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/download_file/{document_id}":{"get":{"summary":"Download File App","description":"Download a file by its document ID as a stream.","operationId":"download_file_app_v2_download_file__document_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"document_id","in":"path","required":true,"schema":{"type":"string","description":"Document ID","title":"Document Id"},"description":"Document ID"}],"responses":{"200":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/documents_overview":{"get":{"summary":"Documents Overview App","operationId":"documents_overview_app_v2_documents_overview_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"document_ids","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"default":[],"title":"Document Ids"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResultsWrapper_list_DocumentOverviewResponse__"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/document_chunks/{document_id}":{"get":{"summary":"Document Chunks App","operationId":"document_chunks_app_v2_document_chunks__document_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"document_id","in":"path","required":true,"schema":{"type":"string","title":"Document Id"}},{"name":"offset","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"default":0,"title":"Offset"}},{"name":"limit","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResultsWrapper_list_DocumentChunkResponse__"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/collections_overview":{"get":{"summary":"Collections Overview App","operationId":"collections_overview_app_v2_collections_overview_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"collection_ids","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Collection Ids"}},{"name":"offset","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"default":0,"title":"Offset"}},{"name":"limit","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":1000,"minimum":1},{"type":"null"}],"default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_list_CollectionOverviewResponse__"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/create_collection":{"post":{"summary":"Create Collection App","operationId":"create_collection_app_v2_create_collection_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_create_collection_app_v2_create_collection_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_CollectionResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v2/get_collection/{collection_id}":{"get":{"summary":"Get Collection App","operationId":"get_collection_app_v2_get_collection__collection_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"collection_id","in":"path","required":true,"schema":{"type":"string","description":"Collection ID","title":"Collection Id"},"description":"Collection ID"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_CollectionResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/update_collection":{"put":{"summary":"Update Collection App","operationId":"update_collection_app_v2_update_collection_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_update_collection_app_v2_update_collection_put"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_CollectionResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v2/delete_collection/{collection_id}":{"delete":{"summary":"Delete Collection App","operationId":"delete_collection_app_v2_delete_collection__collection_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"collection_id","in":"path","required":true,"schema":{"type":"string","description":"Collection ID","title":"Collection Id"},"description":"Collection ID"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/list_collections":{"get":{"summary":"List Collections App","operationId":"list_collections_app_v2_list_collections_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_list_CollectionResponse__"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/add_user_to_collection":{"post":{"summary":"Add User To Collection App","operationId":"add_user_to_collection_app_v2_add_user_to_collection_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_add_user_to_collection_app_v2_add_user_to_collection_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_AddUserResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v2/remove_user_from_collection":{"post":{"summary":"Remove User From Collection App","operationId":"remove_user_from_collection_app_v2_remove_user_from_collection_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_remove_user_from_collection_app_v2_remove_user_from_collection_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v2/get_users_in_collection/{collection_id}":{"get":{"summary":"Get Users In Collection App","operationId":"get_users_in_collection_app_v2_get_users_in_collection__collection_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"collection_id","in":"path","required":true,"schema":{"type":"string","description":"Collection ID","title":"Collection Id"},"description":"Collection ID"},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Pagination offset","default":0,"title":"Offset"},"description":"Pagination offset"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"description":"Pagination limit","default":100,"title":"Limit"},"description":"Pagination limit"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResultsWrapper_list_UserResponse__"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/user_collections/{user_id}":{"get":{"summary":"Get Collections For User App","operationId":"get_collections_for_user_app_v2_user_collections__user_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","description":"User ID","title":"User Id"},"description":"User ID"},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Pagination offset","default":0,"title":"Offset"},"description":"Pagination offset"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"description":"Pagination limit","default":100,"title":"Limit"},"description":"Pagination limit"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResultsWrapper_list_CollectionOverviewResponse__"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/assign_document_to_collection":{"post":{"summary":"Assign Document To Collection App","operationId":"assign_document_to_collection_app_v2_assign_document_to_collection_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_assign_document_to_collection_app_v2_assign_document_to_collection_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v2/remove_document_from_collection":{"post":{"summary":"Remove Document From Collection App","operationId":"remove_document_from_collection_app_v2_remove_document_from_collection_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_remove_document_from_collection_app_v2_remove_document_from_collection_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_NoneType_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v2/document_collections/{document_id}":{"get":{"summary":"Document Collections App","operationId":"document_collections_app_v2_document_collections__document_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"document_id","in":"path","required":true,"schema":{"type":"string","description":"Document ID","title":"Document Id"},"description":"Document ID"},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_list_CollectionResponse__"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/collection/{collection_id}/documents":{"get":{"summary":"Documents In Collection App","operationId":"documents_in_collection_app_v2_collection__collection_id__documents_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"collection_id","in":"path","required":true,"schema":{"type":"string","description":"Collection ID","title":"Collection Id"},"description":"Collection ID"},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResultsWrapper_list_DocumentOverviewResponse__"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/search":{"post":{"summary":"Search App","description":"Perform a search query on the vector database and knowledge graph.\n\nThis endpoint allows for complex filtering of search results using PostgreSQL-based queries.\nFilters can be applied to various fields such as document_id, and internal metadata values.\n\n\nAllowed operators include `eq`, `neq`, `gt`, `gte`, `lt`, `lte`, `like`, `ilike`, `in`, and `nin`.","operationId":"search_app_v2_search_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_search_app_v2_search_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_SearchResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}],"x-codeSamples":[{"lang":"Python","source":"from r2r import R2RClient\n\nclient = R2RClient(\"http://localhost:7272\")\n# when using auth, do client.login(...)\n\nresult = client.search(\n query=\"Who is Aristotle?\",\n vector_search_settings={\n \"use_vector_search\": True,\n \"filters\": {\"document_id\": {\"$eq\": \"3e157b3a-8469-51db-90d9-52e7d896b49b\"}},\n \"search_limit\": 20,\n \"use_hybrid_search\": True\n },\n kg_search_settings={\n \"use_kg_search\": True, # graph needs to be constructed first\n \"kg_search_type\": \"local\",\n \"kg_search_level\": \"0\",\n \"generation_config\": {\n \"model\": \"gpt-4o-mini\",\n \"temperature\": 0.7,\n },\n \"local_search_limits\": {\n \"__Entity__\": 20,\n \"__Relationship__\": 20,\n \"__Community__\": 20,\n },\n \"max_community_description_length\": 65536,\n \"max_llm_queries_for_global_search\": 250\n }\n)\n"},{"lang":"Shell","source":"curl -X POST \"https://api.example.com/search\" \\\n -H \"Content-Type: application/json\" \\\n -H \"Authorization: Bearer YOUR_API_KEY\" \\\n -d '{\n \"query\": \"Who is Aristotle?\",\n \"vector_search_settings\": {\n \"use_vector_search\": true,\n \"filters\": {\"document_id\": {\"$eq\": \"3e157b3a-8469-51db-90d9-52e7d896b49b\"}},\n \"search_limit\": 20,\n \"use_hybrid_search\": true\n },\n \"kg_search_settings\": {\n \"use_kg_search\": true, # graph needs to be constructed first\n \"kg_search_type\": \"local\",\n \"kg_search_level\": \"0\",\n \"generation_config\": {\n \"model\": \"gpt-4o-mini\",\n \"temperature\": 0.7\n },\n \"local_search_limits\": {\n \"__Entity__\": 20,\n \"__Relationship__\": 20,\n \"__Community__\": 20,\n },\n \"max_community_description_length\": 65536,\n \"max_llm_queries_for_global_search\": 250\n }\n }'\n"}]}},"/v2/rag":{"post":{"summary":"Rag App","description":"Execute a RAG (Retrieval-Augmented Generation) query.\n\nThis endpoint combines search results with language model generation.\nIt supports the same filtering capabilities as the search endpoint,\nallowing for precise control over the retrieved context.\n\nThe generation process can be customized using the rag_generation_config parameter.","operationId":"rag_app_v2_rag_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_rag_app_v2_rag_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_RAGResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}],"x-codeSamples":[{"lang":"Python","source":"from r2r import R2RClient\n\nclient = R2RClient(\"http://localhost:7272\")\n# when using auth, do client.login(...)\n\nresult = client.rag(\n query=\"Who is Aristotle?\",\n vector_search_settings={\n \"use_vector_search\": True,\n \"filters\": {\"document_id\": {\"$eq\": \"3e157b3a-8469-51db-90d9-52e7d896b49b\"}},\n \"search_limit\": 20,\n \"use_hybrid_search\": True\n },\n kg_search_settings={\n \"use_kg_search\": True,\n \"kg_search_type\": \"local\",\n \"kg_search_level\": \"0\",\n \"generation_config\": {\n \"model\": \"gpt-4o-mini\",\n \"temperature\": 0.7,\n },\n \"local_search_limits\": {\n \"__Entity__\": 20,\n \"__Relationship__\": 20,\n \"__Community__\": 20,\n },\n \"max_community_description_length\": 65536,\n \"max_llm_queries_for_global_search\": 250\n },\n rag_generation_config={\n \"stream\": False,\n \"temperature\": 0.7,\n \"max_tokens\": 150\n }\n)\n"},{"lang":"Shell","source":"curl -X POST \"https://api.example.com/rag\" \\\n -H \"Content-Type: application/json\" \\\n -H \"Authorization: Bearer YOUR_API_KEY\" \\\n -d '{\n \"query\": \"Who is Aristotle?\",\n \"vector_search_settings\": {\n \"use_vector_search\": true,\n \"filters\": {\"document_id\": {\"$eq\": \"3e157b3a-8469-51db-90d9-52e7d896b49b\"}},\n \"search_limit\": 20,\n \"use_hybrid_search\": True\n },\n \"kg_search_settings\": {\n \"use_kg_search\": true, # graph needs to be constructed first\n \"kg_search_type\": \"local\",\n \"kg_search_level\": \"0\",\n \"generation_config\": {\n \"model\": \"gpt-4o-mini\",\n \"temperature\": 0.7\n },\n \"local_search_limits\": {\n \"__Entity__\": 20,\n \"__Relationship__\": 20,\n \"__Community__\": 20,\n },\n \"max_community_description_length\": 65536,\n \"max_llm_queries_for_global_search\": 250\n },\n \"rag_generation_config\": {\n \"stream\": false,\n \"temperature\": 0.7,\n \"max_tokens\": 150\n }\n }'\n"}]}},"/v2/agent":{"post":{"summary":"Agent App","description":"Implement an agent-based interaction for complex query processing.\n\nThis endpoint supports multi-turn conversations and can handle complex queries\nby breaking them down into sub-tasks. It uses the same filtering capabilities\nas the search and RAG endpoints for retrieving relevant information.\n\nThe agent's behavior can be customized using the rag_generation_config and\ntask_prompt_override parameters.","operationId":"agent_app_v2_agent_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_agent_app_v2_agent_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_RAGAgentResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}],"x-codeSamples":[{"lang":"Python","source":"from r2r import R2RClient\n\nclient = R2RClient(\"http://localhost:7272\")\n# when using auth, do client.login(...)\n\nresult = client.agent(\n messages=[\n {\"role\": \"user\", \"content\": \"Who is the greatest philospher of all time?\"},\n {\"role\": \"assistant\", \"content\": \"Aristotle is widely considered the greatest philospher of all time.\"},\n {\"role\": \"user\", \"content\": \"Can you tell me more about him?\"}\n ],\n vector_search_settings={\n \"use_vector_search\": True,\n \"filters\": {\"document_id\": {\"$eq\": \"5e157b3a-8469-51db-90d9-52e7d896b49b\"}},\n \"search_limit\": 20,\n \"use_hybrid_search\": True\n },\n rag_generation_config={\n \"stream\": False,\n \"temperature\": 0.7,\n \"max_tokens\": 200\n },\n include_title_if_available=True\n)\n"},{"lang":"Shell","source":"curl -X POST \"https://api.example.com/agent\" \\\n -H \"Content-Type: application/json\" \\\n -H \"Authorization: Bearer YOUR_API_KEY\" \\\n -d '{\n \"messages\": [\n {\"role\": \"user\", \"content\": \"Who is the greatest philospher of all time?\"},\n {\"role\": \"assistant\", \"content\": \"Aristotle is widely considered the greatest philospher of all time.\"},\n {\"role\": \"user\", \"content\": \"Can you tell me more about him?\"}\n ],\n \"vector_search_settings\": {\n \"use_vector_search\": true,\n \"filters\": {\"document_id\": {\"$eq\": \"5e157b3a-8469-51db-90d9-52e7d896b49b\"}},\n \"search_limit\": 20,\n \"use_hybrid_search\": true\n },\n \"kg_search_settings\": {\n \"use_kg_search\": false # to enable this, please read the graphrag cookbook\n },\n \"rag_generation_config\": {\n \"stream\": false,\n \"temperature\": 0.7,\n \"max_tokens\": 200\n },\n \"include_title_if_available\": true\n }'\n"}]}},"/v2/completion":{"post":{"summary":"Completion","description":"Generate completions for a list of messages.\n\nThis endpoint uses the language model to generate completions for the provided messages.\nThe generation process can be customized using the generation_config parameter.","operationId":"completion_v2_completion_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"response_model","in":"query","required":false,"schema":{"title":"Response Model"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_completion_v2_completion_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/register":{"post":{"summary":"Register App","description":"Register a new user with the given email and password.","operationId":"register_app_v2_register_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_register_app_v2_register_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_UserResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/verify_email":{"post":{"summary":"Verify Email App","description":"Verify a user's email address.\n\nThis endpoint is used to confirm a user's email address using the verification code\nsent to their email after registration.","operationId":"verify_email_app_v2_verify_email_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_verify_email_app_v2_verify_email_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_GenericMessageResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/login":{"post":{"summary":"Login App","description":"Authenticate a user and provide access tokens.\n\nThis endpoint authenticates a user using their email (username) and password,\nand returns access and refresh tokens upon successful authentication.","operationId":"login_app_v2_login_post","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/Body_login_app_v2_login_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_TokenResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/logout":{"post":{"summary":"Logout App","description":"Log out the current user.\n\nThis endpoint invalidates the user's current access token, effectively logging them out.","operationId":"logout_app_v2_logout_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_GenericMessageResponse_"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"HTTPBearer":[]}]}},"/v2/user":{"get":{"summary":"Get User App","description":"Get the current user's profile information.\n\nThis endpoint returns the profile information of the currently authenticated user.","operationId":"get_user_app_v2_user_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_UserResponse_"}}}}},"security":[{"HTTPBearer":[]}]},"put":{"summary":"Put User App","description":"Update the current user's profile information.\n\nThis endpoint allows the authenticated user to update their profile information.","operationId":"put_user_app_v2_user_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_put_user_app_v2_user_put"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_UserResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v2/refresh_access_token":{"post":{"summary":"Refresh Access Token App","description":"Refresh the access token using a refresh token.\n\nThis endpoint allows users to obtain a new access token using their refresh token.","operationId":"refresh_access_token_app_v2_refresh_access_token_post","requestBody":{"content":{"application/json":{"schema":{"type":"string","title":"Refresh Token","description":"Refresh token"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_TokenResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/change_password":{"post":{"summary":"Change Password App","description":"Change the authenticated user's password.\n\nThis endpoint allows users to change their password by providing their current password\nand a new password.","operationId":"change_password_app_v2_change_password_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_change_password_app_v2_change_password_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_GenericMessageResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v2/request_password_reset":{"post":{"summary":"Request Password Reset App","description":"Request a password reset for a user.\n\nThis endpoint initiates the password reset process by sending a reset link\nto the specified email address.","operationId":"request_password_reset_app_v2_request_password_reset_post","requestBody":{"content":{"application/json":{"schema":{"type":"string","format":"email","title":"Email","description":"User's email address"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_GenericMessageResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/reset_password":{"post":{"summary":"Reset Password App","operationId":"reset_password_app_v2_reset_password_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_reset_password_app_v2_reset_password_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_GenericMessageResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/user/{user_id}":{"delete":{"summary":"Delete User App","description":"Delete a user account.\n\nThis endpoint allows users to delete their own account or, for superusers,\nto delete any user account.","operationId":"delete_user_app_v2_user__user_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","description":"ID of the user to delete","title":"User Id"},"description":"ID of the user to delete"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_delete_user_app_v2_user__user_id__delete"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_GenericMessageResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/create_graph":{"post":{"summary":"Create Graph","description":"Creating a graph on your documents. This endpoint takes input a list of document ids and KGCreationSettings. If document IDs are not provided, the graph will be created on all documents in the system.\nThis step extracts the relevant entities and relationships from the documents and creates a graph based on the extracted information.\nIn order to do GraphRAG, you will need to run the enrich_graph endpoint.","operationId":"create_graph_v2_create_graph_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_create_graph_v2_create_graph_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_Union_KGCreationResponse__KGCreationEstimationResponse__"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v2/enrich_graph":{"post":{"summary":"Enrich Graph","description":"This endpoint enriches the graph with additional information. It creates communities of nodes based on their similarity and adds embeddings to the graph. This step is necessary for GraphRAG to work.","operationId":"enrich_graph_v2_enrich_graph_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_enrich_graph_v2_enrich_graph_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_Union_KGEnrichmentResponse__KGEnrichmentEstimationResponse__"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v2/entities":{"get":{"summary":"Get Entities","description":"Retrieve entities from the knowledge graph.","operationId":"get_entities_v2_entities_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"collection_id","in":"query","required":true,"schema":{"type":"string","format":"uuid","description":"Collection ID to retrieve entities from.","title":"Collection Id"},"description":"Collection ID to retrieve entities from."},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Offset for pagination.","default":0,"title":"Offset"},"description":"Offset for pagination."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"description":"Limit for pagination.","default":100,"title":"Limit"},"description":"Limit for pagination."},{"name":"entity_ids","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Entity IDs to filter by.","title":"Entity Ids"},"description":"Entity IDs to filter by."},{"name":"with_description","in":"query","required":false,"schema":{"type":"boolean","description":"Include entity descriptions in the response.","default":false,"title":"With Description"},"description":"Include entity descriptions in the response."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/triples":{"get":{"summary":"Get Triples","description":"Retrieve triples from the knowledge graph.","operationId":"get_triples_v2_triples_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"collection_id","in":"query","required":true,"schema":{"type":"string","format":"uuid","description":"Collection ID to retrieve triples from.","title":"Collection Id"},"description":"Collection ID to retrieve triples from."},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Offset for pagination.","default":0,"title":"Offset"},"description":"Offset for pagination."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"description":"Limit for pagination.","default":100,"title":"Limit"},"description":"Limit for pagination."},{"name":"triple_ids","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Triple IDs to filter by.","title":"Triple Ids"},"description":"Triple IDs to filter by."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/openapi_spec":{"get":{"summary":"Openapi Spec","operationId":"openapi_spec_v2_openapi_spec_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}}},"components":{"schemas":{"AddUserResponse":{"properties":{"result":{"type":"boolean","title":"Result"}},"type":"object","required":["result"],"title":"AddUserResponse"},"AllPromptsResponse":{"properties":{"prompts":{"additionalProperties":{"$ref":"#/components/schemas/PromptResponse"},"type":"object","title":"Prompts"}},"type":"object","required":["prompts"],"title":"AllPromptsResponse"},"AnalyticsResponse":{"properties":{"analytics_data":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Analytics Data"},"filtered_logs":{"type":"object","title":"Filtered Logs"}},"type":"object","required":["filtered_logs"],"title":"AnalyticsResponse"},"AppSettingsResponse":{"properties":{"config":{"type":"object","title":"Config"},"prompts":{"type":"object","title":"Prompts"}},"type":"object","required":["config","prompts"],"title":"AppSettingsResponse"},"Body_add_prompt_app_v2_add_prompt_post":{"properties":{"name":{"type":"string","title":"Name","description":"Prompt name"},"template":{"type":"string","title":"Template","description":"Prompt template"},"input_types":{"additionalProperties":{"type":"string"},"type":"object","title":"Input Types","description":"Input types","default":{}}},"type":"object","required":["name","template"],"title":"Body_add_prompt_app_v2_add_prompt_post"},"Body_add_user_to_collection_app_v2_add_user_to_collection_post":{"properties":{"user_id":{"type":"string","title":"User Id","description":"User ID"},"collection_id":{"type":"string","title":"Collection Id","description":"Collection ID"}},"type":"object","required":["user_id","collection_id"],"title":"Body_add_user_to_collection_app_v2_add_user_to_collection_post"},"Body_agent_app_v2_agent_post":{"properties":{"messages":{"items":{"$ref":"#/components/schemas/Message"},"type":"array","title":"Messages","description":"List of message objects"},"vector_search_settings":{"$ref":"#/components/schemas/VectorSearchSettings","description":"Vector search settings"},"kg_search_settings":{"$ref":"#/components/schemas/KGSearchSettings","description":"Knowledge graph search settings"},"rag_generation_config":{"$ref":"#/components/schemas/GenerationConfig","description":"RAG generation configuration"},"task_prompt_override":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Task Prompt Override","description":"Task prompt override"},"include_title_if_available":{"type":"boolean","title":"Include Title If Available","description":"Includes document title in chunk response, if available.","default":true}},"type":"object","required":["messages"],"title":"Body_agent_app_v2_agent_post"},"Body_assign_document_to_collection_app_v2_assign_document_to_collection_post":{"properties":{"document_id":{"type":"string","title":"Document Id","description":"Document ID"},"collection_id":{"type":"string","title":"Collection Id","description":"Collection ID"}},"type":"object","required":["document_id","collection_id"],"title":"Body_assign_document_to_collection_app_v2_assign_document_to_collection_post"},"Body_change_password_app_v2_change_password_post":{"properties":{"current_password":{"type":"string","title":"Current Password","description":"Current password"},"new_password":{"type":"string","title":"New Password","description":"New password"}},"type":"object","required":["current_password","new_password"],"title":"Body_change_password_app_v2_change_password_post"},"Body_completion_v2_completion_post":{"properties":{"messages":{"items":{"$ref":"#/components/schemas/Message"},"type":"array","title":"Messages","description":"The messages to complete"},"generation_config":{"$ref":"#/components/schemas/GenerationConfig","description":"The generation config"}},"type":"object","required":["messages"],"title":"Body_completion_v2_completion_post"},"Body_create_collection_app_v2_create_collection_post":{"properties":{"name":{"type":"string","title":"Name","description":"Collection name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description","description":"Collection description","default":""}},"type":"object","required":["name"],"title":"Body_create_collection_app_v2_create_collection_post"},"Body_create_graph_v2_create_graph_post":{"properties":{"collection_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Collection Id","description":"Collection ID to create graph for."},"run_type":{"anyOf":[{"$ref":"#/components/schemas/KGRunType"},{"type":"null"}],"description":"Run type for the graph creation process."},"kg_creation_settings":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Kg Creation Settings","description":"Settings for the graph creation process."}},"type":"object","title":"Body_create_graph_v2_create_graph_post"},"Body_delete_user_app_v2_user__user_id__delete":{"properties":{"password":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Password","description":"User's current password"},"delete_vector_data":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Delete Vector Data","description":"Whether to delete the user's vector data","default":false}},"type":"object","title":"Body_delete_user_app_v2_user__user_id__delete"},"Body_enrich_graph_v2_enrich_graph_post":{"properties":{"collection_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Collection Id","description":"Collection ID to enrich graph for."},"run_type":{"anyOf":[{"$ref":"#/components/schemas/KGRunType"},{"type":"null"}],"description":"Run type for the graph enrichment process.","default":"estimate"},"kg_enrichment_settings":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Kg Enrichment Settings","description":"Settings for the graph enrichment process."}},"type":"object","title":"Body_enrich_graph_v2_enrich_graph_post"},"Body_ingest_chunks_app_v2_ingest_chunks_post":{"properties":{"chunks":{"items":{"$ref":"#/components/schemas/RawChunk"},"type":"array","title":"Chunks","description":"A list of text chunks to ingest into the system.","default":{}},"document_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Document Id","description":"An optional document id to associate the chunks with. If not provided, a unique document id will be generated."},"metadata":{"anyOf":[{"type":"string","contentMediaType":"application/json","contentSchema":{"type":"object"}},{"type":"null"}],"title":"Metadata"}},"type":"object","title":"Body_ingest_chunks_app_v2_ingest_chunks_post"},"Body_ingest_files_app_v2_ingest_files_post":{"properties":{"files":{"items":{"type":"string","format":"binary"},"type":"array","title":"Files","description":"The list of paths of input files to ingest into the system."},"document_ids":{"anyOf":[{"type":"string","contentMediaType":"application/json","contentSchema":{"items":{"type":"string","format":"uuid"},"type":"array"}},{"type":"null"}],"title":"Document Ids","description":"An optional list of document ids for each file. If not provided, the system will generate a unique document id via the `generate_document_id` method."},"metadatas":{"anyOf":[{"type":"string","contentMediaType":"application/json","contentSchema":{"items":{"type":"object"},"type":"array"}},{"type":"null"}],"title":"Metadatas","description":"An optional list of JSON metadata to affix to each file"},"ingestion_config":{"anyOf":[{"type":"string","contentMediaType":"application/json","contentSchema":{"type":"object"}},{"type":"null"}],"title":"Ingestion Config","description":"An optional dictionary to override the default chunking configuration for the ingestion process. If not provided, the system will use the default server-side chunking configuration."}},"type":"object","required":["files"],"title":"Body_ingest_files_app_v2_ingest_files_post"},"Body_login_app_v2_login_post":{"properties":{"grant_type":{"anyOf":[{"type":"string","pattern":"password"},{"type":"null"}],"title":"Grant Type"},"username":{"type":"string","title":"Username"},"password":{"type":"string","title":"Password"},"scope":{"type":"string","title":"Scope","default":""},"client_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Id"},"client_secret":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Secret"}},"type":"object","required":["username","password"],"title":"Body_login_app_v2_login_post"},"Body_put_user_app_v2_user_put":{"properties":{"user_id":{"type":"string","title":"User Id","description":"ID of the user to update"},"email":{"anyOf":[{"type":"string","format":"email"},{"type":"null"}],"title":"Email","description":"Updated email address"},"is_superuser":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Superuser","description":"Updated superuser status"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name","description":"Updated user name"},"bio":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bio","description":"Updated user bio"},"profile_picture":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Profile Picture","description":"Updated profile picture URL"}},"type":"object","title":"Body_put_user_app_v2_user_put"},"Body_rag_app_v2_rag_post":{"properties":{"query":{"type":"string","title":"Query","description":"RAG query"},"vector_search_settings":{"$ref":"#/components/schemas/VectorSearchSettings","description":"Vector search settings"},"kg_search_settings":{"$ref":"#/components/schemas/KGSearchSettings","description":"Knowledge graph search settings"},"rag_generation_config":{"$ref":"#/components/schemas/GenerationConfig","description":"RAG generation configuration"},"task_prompt_override":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Task Prompt Override","description":"Task prompt override"},"include_title_if_available":{"type":"boolean","title":"Include Title If Available","description":"Includes document title in chunk response, if available.","default":false}},"type":"object","required":["query"],"title":"Body_rag_app_v2_rag_post"},"Body_register_app_v2_register_post":{"properties":{"email":{"type":"string","format":"email","title":"Email","description":"User's email address"},"password":{"type":"string","title":"Password","description":"User's password"}},"type":"object","required":["email","password"],"title":"Body_register_app_v2_register_post"},"Body_remove_document_from_collection_app_v2_remove_document_from_collection_post":{"properties":{"document_id":{"type":"string","title":"Document Id","description":"Document ID"},"collection_id":{"type":"string","title":"Collection Id","description":"Collection ID"}},"type":"object","required":["document_id","collection_id"],"title":"Body_remove_document_from_collection_app_v2_remove_document_from_collection_post"},"Body_remove_user_from_collection_app_v2_remove_user_from_collection_post":{"properties":{"user_id":{"type":"string","title":"User Id","description":"User ID"},"collection_id":{"type":"string","title":"Collection Id","description":"Collection ID"}},"type":"object","required":["user_id","collection_id"],"title":"Body_remove_user_from_collection_app_v2_remove_user_from_collection_post"},"Body_reset_password_app_v2_reset_password_post":{"properties":{"reset_token":{"type":"string","title":"Reset Token","description":"Password reset token"},"new_password":{"type":"string","title":"New Password","description":"New password"}},"type":"object","required":["reset_token","new_password"],"title":"Body_reset_password_app_v2_reset_password_post"},"Body_score_completion_v2_score_completion_post":{"properties":{"message_id":{"type":"string","title":"Message Id","description":"Message ID"},"score":{"type":"number","title":"Score","description":"Completion score"}},"type":"object","required":["message_id","score"],"title":"Body_score_completion_v2_score_completion_post"},"Body_search_app_v2_search_post":{"properties":{"query":{"type":"string","title":"Query","description":"Search query"},"vector_search_settings":{"$ref":"#/components/schemas/VectorSearchSettings","description":"Vector search settings"},"kg_search_settings":{"$ref":"#/components/schemas/KGSearchSettings","description":"Knowledge graph search settings"}},"type":"object","required":["query"],"title":"Body_search_app_v2_search_post"},"Body_update_collection_app_v2_update_collection_put":{"properties":{"collection_id":{"type":"string","title":"Collection Id","description":"Collection ID"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name","description":"Updated collection name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description","description":"Updated collection description"}},"type":"object","required":["collection_id"],"title":"Body_update_collection_app_v2_update_collection_put"},"Body_update_files_app_v2_update_files_post":{"properties":{"files":{"items":{"type":"string","format":"binary"},"type":"array","title":"Files","description":"The list of paths of input files to update in the system."},"document_ids":{"anyOf":[{"type":"string","contentMediaType":"application/json","contentSchema":{"items":{"type":"string","format":"uuid"},"type":"array"}},{"type":"null"}],"title":"Document Ids","description":"An optional list of document ids for each file. If not provided, the system will generate a unique document id via the `generate_document_id` method."},"metadatas":{"anyOf":[{"type":"string","contentMediaType":"application/json","contentSchema":{"items":{"type":"object"},"type":"array"}},{"type":"null"}],"title":"Metadatas","description":"An optional list of JSON metadata to affix to each file"},"ingestion_config":{"anyOf":[{"type":"string","contentMediaType":"application/json","contentSchema":{"type":"object"}},{"type":"null"}],"title":"Ingestion Config","description":"An optional dictionary to override the default chunking configuration for the ingestion process. If not provided, the system will use the default server-side chunking configuration."}},"type":"object","required":["files"],"title":"Body_update_files_app_v2_update_files_post"},"Body_update_prompt_app_v2_update_prompt_post":{"properties":{"name":{"type":"string","title":"Name","description":"Prompt name"},"template":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Template","description":"Prompt template"},"input_types":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Input Types","description":"Input types","default":{}}},"type":"object","required":["name"],"title":"Body_update_prompt_app_v2_update_prompt_post"},"Body_verify_email_app_v2_verify_email_post":{"properties":{"email":{"type":"string","format":"email","title":"Email","description":"User's email address"},"verification_code":{"type":"string","title":"Verification Code","description":"Email verification code"}},"type":"object","required":["email","verification_code"],"title":"Body_verify_email_app_v2_verify_email_post"},"CollectionOverviewResponse":{"properties":{"collection_id":{"type":"string","format":"uuid","title":"Collection Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"user_count":{"type":"integer","title":"User Count"},"document_count":{"type":"integer","title":"Document Count"}},"type":"object","required":["collection_id","name","description","created_at","updated_at","user_count","document_count"],"title":"CollectionOverviewResponse"},"CollectionResponse":{"properties":{"collection_id":{"type":"string","format":"uuid","title":"Collection Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["collection_id","name","description","created_at","updated_at"],"title":"CollectionResponse"},"DocumentChunkResponse":{"properties":{"extraction_id":{"type":"string","format":"uuid","title":"Extraction Id"},"document_id":{"type":"string","format":"uuid","title":"Document Id"},"user_id":{"type":"string","format":"uuid","title":"User Id"},"collection_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Collection Ids"},"text":{"type":"string","title":"Text"},"metadata":{"type":"object","title":"Metadata"}},"type":"object","required":["extraction_id","document_id","user_id","collection_ids","text","metadata"],"title":"DocumentChunkResponse"},"DocumentOverviewResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"title":{"type":"string","title":"Title"},"user_id":{"type":"string","format":"uuid","title":"User Id"},"type":{"type":"string","title":"Type"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"ingestion_status":{"type":"string","title":"Ingestion Status"},"kg_extraction_status":{"type":"string","title":"Kg Extraction Status"},"version":{"type":"string","title":"Version"},"collection_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Collection Ids"},"metadata":{"type":"object","title":"Metadata"}},"type":"object","required":["id","title","user_id","type","created_at","updated_at","ingestion_status","kg_extraction_status","version","collection_ids","metadata"],"title":"DocumentOverviewResponse"},"GenerationConfig":{"properties":{"model":{"type":"string","title":"Model"},"temperature":{"type":"number","title":"Temperature"},"top_p":{"type":"number","title":"Top P"},"max_tokens_to_sample":{"type":"integer","title":"Max Tokens To Sample"},"stream":{"type":"boolean","title":"Stream"},"functions":{"anyOf":[{"items":{"type":"object"},"type":"array"},{"type":"null"}],"title":"Functions"},"tools":{"anyOf":[{"items":{"type":"object"},"type":"array"},{"type":"null"}],"title":"Tools"},"add_generation_kwargs":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Add Generation Kwargs"},"api_base":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Api Base"}},"type":"object","title":"GenerationConfig","max_tokens_to_sample":1024,"model":"openai/gpt-4o","stream":false,"temperature":0.1,"top_p":1.0},"GenericMessageResponse":{"properties":{"message":{"type":"string","title":"Message"}},"type":"object","required":["message"],"title":"GenericMessageResponse"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"HybridSearchSettings":{"properties":{"full_text_weight":{"type":"number","title":"Full Text Weight","description":"Weight to apply to full text search","default":1.0},"semantic_weight":{"type":"number","title":"Semantic Weight","description":"Weight to apply to semantic search","default":5.0},"full_text_limit":{"type":"integer","title":"Full Text Limit","description":"Maximum number of results to return from full text search","default":200},"rrf_k":{"type":"integer","title":"Rrf K","description":"K-value for RRF (Rank Reciprocal Fusion)","default":50}},"type":"object","title":"HybridSearchSettings"},"IndexMeasure":{"type":"string","enum":["cosine_distance","l2_distance","max_inner_product"],"title":"IndexMeasure","description":"An enum representing the types of distance measures available for indexing.\n\nAttributes:\n cosine_distance (str): The cosine distance measure for indexing.\n l2_distance (str): The Euclidean (L2) distance measure for indexing.\n max_inner_product (str): The maximum inner product measure for indexing."},"KGCommunityResult":{"properties":{"name":{"type":"string","title":"Name"},"summary":{"type":"string","title":"Summary"},"rating":{"type":"number","title":"Rating"},"rating_explanation":{"type":"string","title":"Rating Explanation"},"findings":{"items":{"type":"string"},"type":"array","title":"Findings"},"metadata":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Metadata"}},"type":"object","required":["name","summary","rating","rating_explanation","findings"],"title":"KGCommunityResult","findings":["Finding 1","Finding 2"],"metadata":{},"name":"Community Name","rating":9,"rating_explanation":"Rating Explanation","summary":"Community Summary"},"KGCreationEstimationResponse":{"properties":{"message":{"type":"string","title":"Message","description":"The message to display to the user.","default":""},"document_count":{"type":"integer","title":"Document Count","description":"The number of documents in the collection.","default":-1},"number_of_jobs_created":{"type":"integer","title":"Number Of Jobs Created","description":"The number of jobs created for the graph creation process.","default":-1},"total_chunks":{"type":"integer","title":"Total Chunks","description":"The estimated total number of chunks.","default":-1},"estimated_entities":{"type":"string","title":"Estimated Entities","description":"The estimated number of entities in the graph.","default":"NA"},"estimated_triples":{"type":"string","title":"Estimated Triples","description":"The estimated number of triples in the graph.","default":"NA"},"estimated_llm_calls":{"type":"string","title":"Estimated Llm Calls","description":"The estimated number of LLM calls in millions.","default":"NA"},"estimated_total_in_out_tokens_in_millions":{"type":"string","title":"Estimated Total In Out Tokens In Millions","description":"The estimated total number of input and output tokens in millions.","default":"NA"},"estimated_total_time_in_minutes":{"type":"string","title":"Estimated Total Time In Minutes","description":"The estimated total time to run the graph creation process in minutes.","default":"NA"},"estimated_cost_in_usd":{"type":"string","title":"Estimated Cost In Usd","description":"The estimated cost to run the graph creation process in USD.","default":"NA"}},"type":"object","title":"KGCreationEstimationResponse","description":"Response for knowledge graph creation estimation."},"KGCreationResponse":{"properties":{"message":{"type":"string","title":"Message","description":"A message describing the result of the KG creation request."},"task_id":{"type":"string","format":"uuid","title":"Task Id","description":"The task ID of the KG creation request."}},"type":"object","required":["message","task_id"],"title":"KGCreationResponse","example":{"message":"Graph creation queued successfully.","task_id":"c68dc72e-fc23-5452-8f49-d7bd46088a96"}},"KGEnrichmentEstimationResponse":{"properties":{"message":{"type":"string","title":"Message","description":"The message to display to the user.","default":""},"total_entities":{"type":"integer","title":"Total Entities","description":"The total number of entities in the graph.","default":-1},"total_triples":{"type":"integer","title":"Total Triples","description":"The total number of triples in the graph.","default":-1},"estimated_llm_calls":{"type":"string","title":"Estimated Llm Calls","description":"The estimated number of LLM calls.","default":"NA"},"estimated_total_in_out_tokens_in_millions":{"type":"string","title":"Estimated Total In Out Tokens In Millions","description":"The estimated total number of input and output tokens in millions.","default":"NA"},"estimated_cost_in_usd":{"type":"string","title":"Estimated Cost In Usd","description":"The estimated cost to run the graph enrichment process.","default":"NA"},"estimated_total_time_in_minutes":{"type":"string","title":"Estimated Total Time In Minutes","description":"The estimated total time to run the graph enrichment process.","default":"NA"}},"type":"object","title":"KGEnrichmentEstimationResponse","description":"Response for knowledge graph enrichment estimation."},"KGEnrichmentResponse":{"properties":{"message":{"type":"string","title":"Message","description":"A message describing the result of the KG enrichment request."},"task_id":{"type":"string","format":"uuid","title":"Task Id","description":"The task ID of the KG enrichment request."}},"type":"object","required":["message","task_id"],"title":"KGEnrichmentResponse","example":{"message":"Graph enrichment queued successfuly.","task_id":"c68dc72e-fc23-5452-8f49-d7bd46088a96"}},"KGEntityResult":{"properties":{"name":{"type":"string","title":"Name"},"description":{"type":"string","title":"Description"},"metadata":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Metadata"}},"type":"object","required":["name","description"],"title":"KGEntityResult","description":"Entity Description","metadata":{},"name":"Entity Name"},"KGGlobalResult":{"properties":{"name":{"type":"string","title":"Name"},"description":{"type":"string","title":"Description"},"metadata":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Metadata"}},"type":"object","required":["name","description"],"title":"KGGlobalResult","description":"Global Result Description","metadata":{},"name":"Global Result Name"},"KGRelationshipResult":{"properties":{"name":{"type":"string","title":"Name"},"description":{"type":"string","title":"Description"},"metadata":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Metadata"}},"type":"object","required":["name","description"],"title":"KGRelationshipResult","description":"Relationship Description","metadata":{},"name":"Relationship Name"},"KGRunType":{"type":"string","enum":["estimate","run"],"title":"KGRunType","description":"Type of KG run."},"KGSearchMethod":{"type":"string","enum":["local","global"],"title":"KGSearchMethod"},"KGSearchResult":{"properties":{"method":{"$ref":"#/components/schemas/KGSearchMethod"},"content":{"anyOf":[{"$ref":"#/components/schemas/KGEntityResult"},{"$ref":"#/components/schemas/KGRelationshipResult"},{"$ref":"#/components/schemas/KGCommunityResult"},{"$ref":"#/components/schemas/KGGlobalResult"}],"title":"Content"},"result_type":{"anyOf":[{"$ref":"#/components/schemas/KGSearchResultType"},{"type":"null"}]},"extraction_ids":{"anyOf":[{"items":{"type":"string","format":"uuid"},"type":"array"},{"type":"null"}],"title":"Extraction Ids"},"metadata":{"type":"object","title":"Metadata","default":{}}},"type":"object","required":["method","content"],"title":"KGSearchResult","content":{"description":"Entity Description","metadata":{},"name":"Entity Name"},"extraction_ids":["c68dc72e-fc23-5452-8f49-d7bd46088a96"],"metadata":{"associated_query":"What is the capital of France?"},"method":"local","result_type":"entity"},"KGSearchResultType":{"type":"string","enum":["entity","relationship","community"],"title":"KGSearchResultType"},"KGSearchSettings":{"properties":{"filters":{"type":"object","title":"Filters","description":"Filters to apply to the KG search"},"selected_collection_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Selected Collection Ids","description":"Collection IDs to search for"},"graphrag_map_system_prompt":{"type":"string","title":"Graphrag Map System Prompt","description":"The system prompt for the graphrag map prompt.","default":"graphrag_map_system_prompt"},"graphrag_reduce_system_prompt":{"type":"string","title":"Graphrag Reduce System Prompt","description":"The system prompt for the graphrag reduce prompt.","default":"graphrag_reduce_system_prompt"},"use_kg_search":{"type":"boolean","title":"Use Kg Search","description":"Whether to use KG search","default":false},"kg_search_type":{"type":"string","title":"Kg Search Type","description":"KG search type","default":"local"},"kg_search_level":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Kg Search Level","description":"KG search level"},"generation_config":{"$ref":"#/components/schemas/GenerationConfig","description":"Configuration for text generation during graph search."},"max_community_description_length":{"type":"integer","title":"Max Community Description Length","default":65536},"max_llm_queries_for_global_search":{"type":"integer","title":"Max Llm Queries For Global Search","default":250},"local_search_limits":{"additionalProperties":{"type":"integer"},"type":"object","title":"Local Search Limits","default":{"__Entity__":20,"__Relationship__":20,"__Community__":20}}},"type":"object","title":"KGSearchSettings","generation_config":{"max_tokens_to_sample":1024,"model":"openai/gpt-4o","stream":false,"temperature":0.1,"top_p":1.0},"kg_search_level":"0","kg_search_type":"global","local_search_limits":{"__Community__":20,"__Entity__":20,"__Relationship__":20},"max_community_description_length":65536,"max_llm_queries_for_global_search":250,"use_kg_search":true},"LogEntry":{"properties":{"key":{"type":"string","title":"Key"},"value":{"title":"Value"},"timestamp":{"type":"string","format":"date-time","title":"Timestamp"}},"type":"object","required":["key","value","timestamp"],"title":"LogEntry"},"LogResponse":{"properties":{"run_id":{"type":"string","format":"uuid","title":"Run Id"},"run_type":{"type":"string","title":"Run Type"},"entries":{"items":{"$ref":"#/components/schemas/LogEntry"},"type":"array","title":"Entries"},"timestamp":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Timestamp"},"user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"User Id"}},"type":"object","required":["run_id","run_type","entries","timestamp","user_id"],"title":"LogResponse"},"Message":{"properties":{"role":{"anyOf":[{"$ref":"#/components/schemas/MessageType"},{"type":"string"}],"title":"Role"},"content":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Content"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"function_call":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Function Call"},"tool_calls":{"anyOf":[{"items":{"type":"object"},"type":"array"},{"type":"null"}],"title":"Tool Calls"}},"type":"object","required":["role"],"title":"Message","content":"This is a test message.","role":"user"},"MessageType":{"type":"string","enum":["system","user","assistant","function","tool"],"title":"MessageType"},"PaginatedResultsWrapper_list_CollectionOverviewResponse__":{"properties":{"results":{"items":{"$ref":"#/components/schemas/CollectionOverviewResponse"},"type":"array","title":"Results"},"total_entries":{"type":"integer","title":"Total Entries"}},"type":"object","required":["results","total_entries"],"title":"PaginatedResultsWrapper[list[CollectionOverviewResponse]]"},"PaginatedResultsWrapper_list_DocumentChunkResponse__":{"properties":{"results":{"items":{"$ref":"#/components/schemas/DocumentChunkResponse"},"type":"array","title":"Results"},"total_entries":{"type":"integer","title":"Total Entries"}},"type":"object","required":["results","total_entries"],"title":"PaginatedResultsWrapper[list[DocumentChunkResponse]]"},"PaginatedResultsWrapper_list_DocumentOverviewResponse__":{"properties":{"results":{"items":{"$ref":"#/components/schemas/DocumentOverviewResponse"},"type":"array","title":"Results"},"total_entries":{"type":"integer","title":"Total Entries"}},"type":"object","required":["results","total_entries"],"title":"PaginatedResultsWrapper[list[DocumentOverviewResponse]]"},"PaginatedResultsWrapper_list_UserOverviewResponse__":{"properties":{"results":{"items":{"$ref":"#/components/schemas/UserOverviewResponse"},"type":"array","title":"Results"},"total_entries":{"type":"integer","title":"Total Entries"}},"type":"object","required":["results","total_entries"],"title":"PaginatedResultsWrapper[list[UserOverviewResponse]]"},"PaginatedResultsWrapper_list_UserResponse__":{"properties":{"results":{"items":{"$ref":"#/components/schemas/shared__api__models__management__responses__UserResponse"},"type":"array","title":"Results"},"total_entries":{"type":"integer","title":"Total Entries"}},"type":"object","required":["results","total_entries"],"title":"PaginatedResultsWrapper[list[UserResponse]]"},"PromptResponse":{"properties":{"name":{"type":"string","title":"Name"},"template":{"type":"string","title":"Template"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"input_types":{"additionalProperties":{"type":"string"},"type":"object","title":"Input Types"}},"type":"object","required":["name","template","created_at","updated_at","input_types"],"title":"PromptResponse"},"RAGAgentResponse":{"properties":{"messages":{"items":{"$ref":"#/components/schemas/Message"},"type":"array","title":"Messages","description":"List of messages in the RAG agent response"}},"type":"object","required":["messages"],"title":"RAGAgentResponse","example":[{"content":"## You are a helpful assistant that can search for information.\n\nWhen asked a question, perform a search to find relevant information and provide a response.\n\nThe response should contain line-item attributions to relevent search results, and be as informative if possible.\nIf no relevant results are found, then state that no results were found.\nIf no obvious question is present, then do not carry out a search, and instead ask for clarification.","role":"system"},{"content":"You are a helpful assistant.","role":"system"},{"content":"Who is the greatest philospher of all time?","role":"user"},{"content":"Aristotle is widely considered the greatest philospher of all time.","role":"assistant"},{"content":"Can you tell me more about him?","role":"user"},{"function_call":{"arguments":"{\"query\":\"Aristotle biography\"}","name":"search"},"role":"assistant"},{"content":"1. Aristotle[A] (Greek: Ἀριστοτέλης Aristotélēs, pronounced [aristotélɛːs]; 384–322 BC) was an Ancient Greek philosopher and polymath. His writings cover a broad range of subjects spanning the natural sciences, philosophy, linguistics, economics, politics, psychology, and the arts. As the founder of the Peripatetic school of philosophy in the Lyceum in Athens, he began the wider Aristotelian tradition that followed, which set the groundwork for the development of modern science.\n2. Aristotle[A] (Greek: Ἀριστοτέλης Aristotélēs, pronounced [aristotélɛːs]; 384–322 BC) was an Ancient Greek philosopher and polymath. His writings cover a broad range of subjects spanning the natural sciences, philosophy, linguistics, economics, politics, psychology, and the arts. As the founder of the Peripatetic school of philosophy in the Lyceum in Athens, he began the wider Aristotelian tradition that followed, which set the groundwork for the development of modern science.\n3. Aristotle was born in 384 BC[C] in Stagira, Chalcidice,[2] about 55 km (34 miles) east of modern-day Thessaloniki.[3][4] His father, Nicomachus, was the personal physician to King Amyntas of Macedon. While he was young, Aristotle learned about biology and medical information, which was taught by his father.[5] Both of Aristotle's parents died when he was about thirteen, and Proxenus of Atarneus became his guardian.[6] Although little information about Aristotle's childhood has survived, he probably spent\n4. Aristotle was born in 384 BC[C] in Stagira, Chalcidice,[2] about 55 km (34 miles) east of modern-day Thessaloniki.[3][4] His father, Nicomachus, was the personal physician to King Amyntas of Macedon. While he was young, Aristotle learned about biology and medical information, which was taught by his father.[5] Both of Aristotle's parents died when he was about thirteen, and Proxenus of Atarneus became his guardian.[6] Although little information about Aristotle's childhood has survived, he probably spent\n5. Life\nIn general, the details of Aristotle's life are not well-established. The biographies written in ancient times are often speculative and historians only agree on a few salient points.[B]\n","name":"search","role":"function"},{"content":"Aristotle (384–322 BC) was an Ancient Greek philosopher and polymath whose contributions have had a profound impact on various fields of knowledge. Here are some key points about his life and work:\n\n1. **Early Life**: Aristotle was born in 384 BC in Stagira, Chalcidice, which is near modern-day Thessaloniki, Greece. His father, Nicomachus, was the personal physician to King Amyntas of Macedon, which exposed Aristotle to medical and biological knowledge from a young age [C].\n\n2. **Education and Career**: After the death of his parents, Aristotle was sent to Athens to study at Plato's Academy, where he remained for about 20 years. After Plato's death, Aristotle left Athens and eventually became the tutor of Alexander the Great [C].\n\n3. **Philosophical Contributions**: Aristotle founded the Lyceum in Athens, where he established the Peripatetic school of philosophy. His works cover a wide range of subjects, including metaphysics, ethics, politics, logic, biology, and aesthetics. His writings laid the groundwork for many modern scientific and philosophical inquiries [A].\n\n4. **Legacy**: Aristotle's influence extends beyond philosophy to the natural sciences, linguistics, economics, and psychology. His method of systematic observation and analysis has been foundational to the development of modern science [A].\n\nAristotle's comprehensive approach to knowledge and his systematic methodology have earned him a lasting legacy as one of the greatest philosophers of all time.\n\nSources:\n- [A] Aristotle's broad range of writings and influence on modern science.\n- [C] Details about Aristotle's early life and education.","role":"assistant"}]},"RAGResponse":{"properties":{"completion":{"title":"Completion","description":"The generated completion from the RAG process"},"search_results":{"$ref":"#/components/schemas/SearchResponse","description":"The search results used for the RAG process"}},"type":"object","required":["completion","search_results"],"title":"RAGResponse","example":{"completion":{"choices":[{"finish_reason":"stop","index":0,"message":{"content":"Paris is the capital of France.","role":"assistant"}}],"id":"chatcmpl-example123"},"search_results":{"kg_search_results":[{"content":{"description":"Entity Description","metadata":{},"name":"Entity Name"},"extraction_ids":["c68dc72e-fc23-5452-8f49-d7bd46088a96"],"metadata":{"associated_query":"What is the capital of France?"},"method":"local","result_type":"entity"}],"vector_search_results":[{"collection_ids":[],"document_id":"3e157b3a-8469-51db-90d9-52e7d896b49b","extraction_id":"3f3d47f3-8baf-58eb-8bc2-0171fb1c6e09","metadata":{"associated_query":"What is the capital of France?","title":"example_document.pdf"},"score":0.23943702876567796,"text":"Example text from the document","user_id":"2acb499e-8428-543b-bd85-0d9098718220"}]}}},"RawChunk":{"properties":{"text":{"type":"string","title":"Text"}},"type":"object","required":["text"],"title":"RawChunk"},"ResultsWrapper_AddUserResponse_":{"properties":{"results":{"$ref":"#/components/schemas/AddUserResponse"}},"type":"object","required":["results"],"title":"ResultsWrapper[AddUserResponse]"},"ResultsWrapper_AllPromptsResponse_":{"properties":{"results":{"$ref":"#/components/schemas/AllPromptsResponse"}},"type":"object","required":["results"],"title":"ResultsWrapper[AllPromptsResponse]"},"ResultsWrapper_AnalyticsResponse_":{"properties":{"results":{"$ref":"#/components/schemas/AnalyticsResponse"}},"type":"object","required":["results"],"title":"ResultsWrapper[AnalyticsResponse]"},"ResultsWrapper_AppSettingsResponse_":{"properties":{"results":{"$ref":"#/components/schemas/AppSettingsResponse"}},"type":"object","required":["results"],"title":"ResultsWrapper[AppSettingsResponse]"},"ResultsWrapper_CollectionResponse_":{"properties":{"results":{"$ref":"#/components/schemas/CollectionResponse"}},"type":"object","required":["results"],"title":"ResultsWrapper[CollectionResponse]"},"ResultsWrapper_GenericMessageResponse_":{"properties":{"results":{"$ref":"#/components/schemas/GenericMessageResponse"}},"type":"object","required":["results"],"title":"ResultsWrapper[GenericMessageResponse]"},"ResultsWrapper_NoneType_":{"properties":{"results":{"type":"null","title":"Results"}},"type":"object","required":["results"],"title":"ResultsWrapper[NoneType]"},"ResultsWrapper_RAGAgentResponse_":{"properties":{"results":{"$ref":"#/components/schemas/RAGAgentResponse"}},"type":"object","required":["results"],"title":"ResultsWrapper[RAGAgentResponse]"},"ResultsWrapper_RAGResponse_":{"properties":{"results":{"$ref":"#/components/schemas/RAGResponse"}},"type":"object","required":["results"],"title":"ResultsWrapper[RAGResponse]"},"ResultsWrapper_ScoreCompletionResponse_":{"properties":{"results":{"$ref":"#/components/schemas/ScoreCompletionResponse"}},"type":"object","required":["results"],"title":"ResultsWrapper[ScoreCompletionResponse]"},"ResultsWrapper_SearchResponse_":{"properties":{"results":{"$ref":"#/components/schemas/SearchResponse"}},"type":"object","required":["results"],"title":"ResultsWrapper[SearchResponse]"},"ResultsWrapper_ServerStats_":{"properties":{"results":{"$ref":"#/components/schemas/ServerStats"}},"type":"object","required":["results"],"title":"ResultsWrapper[ServerStats]"},"ResultsWrapper_TokenResponse_":{"properties":{"results":{"$ref":"#/components/schemas/TokenResponse"}},"type":"object","required":["results"],"title":"ResultsWrapper[TokenResponse]"},"ResultsWrapper_Union_KGCreationResponse__KGCreationEstimationResponse__":{"properties":{"results":{"anyOf":[{"$ref":"#/components/schemas/KGCreationResponse"},{"$ref":"#/components/schemas/KGCreationEstimationResponse"}],"title":"Results"}},"type":"object","required":["results"],"title":"ResultsWrapper[Union[KGCreationResponse, KGCreationEstimationResponse]]"},"ResultsWrapper_Union_KGEnrichmentResponse__KGEnrichmentEstimationResponse__":{"properties":{"results":{"anyOf":[{"$ref":"#/components/schemas/KGEnrichmentResponse"},{"$ref":"#/components/schemas/KGEnrichmentEstimationResponse"}],"title":"Results"}},"type":"object","required":["results"],"title":"ResultsWrapper[Union[KGEnrichmentResponse, KGEnrichmentEstimationResponse]]"},"ResultsWrapper_UpdatePromptResponse_":{"properties":{"results":{"$ref":"#/components/schemas/UpdatePromptResponse"}},"type":"object","required":["results"],"title":"ResultsWrapper[UpdatePromptResponse]"},"ResultsWrapper_UserResponse_":{"properties":{"results":{"$ref":"#/components/schemas/shared__api__models__auth__responses__UserResponse"}},"type":"object","required":["results"],"title":"ResultsWrapper[UserResponse]"},"ResultsWrapper_list_CollectionOverviewResponse__":{"properties":{"results":{"items":{"$ref":"#/components/schemas/CollectionOverviewResponse"},"type":"array","title":"Results"}},"type":"object","required":["results"],"title":"ResultsWrapper[list[CollectionOverviewResponse]]"},"ResultsWrapper_list_CollectionResponse__":{"properties":{"results":{"items":{"$ref":"#/components/schemas/CollectionResponse"},"type":"array","title":"Results"}},"type":"object","required":["results"],"title":"ResultsWrapper[list[CollectionResponse]]"},"ResultsWrapper_list_LogResponse__":{"properties":{"results":{"items":{"$ref":"#/components/schemas/LogResponse"},"type":"array","title":"Results"}},"type":"object","required":["results"],"title":"ResultsWrapper[list[LogResponse]]"},"ScoreCompletionResponse":{"properties":{"message":{"type":"string","title":"Message"}},"type":"object","required":["message"],"title":"ScoreCompletionResponse"},"SearchResponse":{"properties":{"vector_search_results":{"items":{"$ref":"#/components/schemas/VectorSearchResult"},"type":"array","title":"Vector Search Results","description":"List of vector search results"},"kg_search_results":{"anyOf":[{"items":{"$ref":"#/components/schemas/KGSearchResult"},"type":"array"},{"type":"null"}],"title":"Kg Search Results","description":"Knowledge graph search results, if applicable"}},"type":"object","required":["vector_search_results"],"title":"SearchResponse","example":{"kg_search_results":[{"content":{"description":"Entity Description","metadata":{},"name":"Entity Name"},"extraction_ids":["c68dc72e-fc23-5452-8f49-d7bd46088a96"],"metadata":{"associated_query":"What is the capital of France?"},"method":"local","result_type":"entity"}],"vector_search_results":[{"collection_ids":[],"document_id":"3e157b3a-8469-51db-90d9-52e7d896b49b","extraction_id":"3f3d47f3-8baf-58eb-8bc2-0171fb1c6e09","metadata":{"associated_query":"What is the capital of France?","title":"example_document.pdf"},"score":0.23943702876567796,"text":"Example text from the document","user_id":"2acb499e-8428-543b-bd85-0d9098718220"}]}},"ServerStats":{"properties":{"start_time":{"type":"string","format":"date-time","title":"Start Time"},"uptime_seconds":{"type":"number","title":"Uptime Seconds"},"cpu_usage":{"type":"number","title":"Cpu Usage"},"memory_usage":{"type":"number","title":"Memory Usage"}},"type":"object","required":["start_time","uptime_seconds","cpu_usage","memory_usage"],"title":"ServerStats"},"Token":{"properties":{"token":{"type":"string","title":"Token"},"token_type":{"type":"string","title":"Token Type"}},"type":"object","required":["token","token_type"],"title":"Token"},"TokenResponse":{"properties":{"access_token":{"$ref":"#/components/schemas/Token"},"refresh_token":{"$ref":"#/components/schemas/Token"}},"type":"object","required":["access_token","refresh_token"],"title":"TokenResponse"},"UpdatePromptResponse":{"properties":{"message":{"type":"string","title":"Message"}},"type":"object","required":["message"],"title":"UpdatePromptResponse"},"UserOverviewResponse":{"properties":{"user_id":{"type":"string","format":"uuid","title":"User Id"},"num_files":{"type":"integer","title":"Num Files"},"total_size_in_bytes":{"type":"integer","title":"Total Size In Bytes"},"document_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Document Ids"}},"type":"object","required":["user_id","num_files","total_size_in_bytes","document_ids"],"title":"UserOverviewResponse"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"VectorSearchResult":{"properties":{"extraction_id":{"type":"string","format":"uuid","title":"Extraction Id"},"document_id":{"type":"string","format":"uuid","title":"Document Id"},"user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"User Id"},"collection_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Collection Ids"},"score":{"type":"number","title":"Score"},"text":{"type":"string","title":"Text"},"metadata":{"type":"object","title":"Metadata"}},"type":"object","required":["extraction_id","document_id","user_id","collection_ids","score","text","metadata"],"title":"VectorSearchResult","description":"Result of a search operation.","collection_ids":[],"document_id":"3e157b3a-8469-51db-90d9-52e7d896b49b","extraction_id":"3f3d47f3-8baf-58eb-8bc2-0171fb1c6e09","metadata":{"associated_query":"What is the capital of France?","title":"example_document.pdf"},"score":0.23943702876567796,"text":"Example text from the document","user_id":"2acb499e-8428-543b-bd85-0d9098718220"},"VectorSearchSettings":{"properties":{"use_vector_search":{"type":"boolean","title":"Use Vector Search","description":"Whether to use vector search","default":true},"use_hybrid_search":{"type":"boolean","title":"Use Hybrid Search","description":"Whether to perform a hybrid search (combining vector and keyword search)","default":false},"filters":{"type":"object","title":"Filters","description":"Filters to apply to the vector search"},"search_limit":{"type":"integer","maximum":1000.0,"minimum":1.0,"title":"Search Limit","description":"Maximum number of results to return","default":10},"offset":{"type":"integer","minimum":0.0,"title":"Offset","description":"Offset to paginate search results","default":0},"selected_collection_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Selected Collection Ids","description":"Collection IDs to search for"},"index_measure":{"$ref":"#/components/schemas/IndexMeasure","description":"The distance measure to use for indexing","default":"cosine_distance"},"include_values":{"type":"boolean","title":"Include Values","description":"Whether to include search score values in the search results","default":true},"include_metadatas":{"type":"boolean","title":"Include Metadatas","description":"Whether to include element metadata in the search results","default":true},"probes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Probes","description":"Number of ivfflat index lists to query. Higher increases accuracy but decreases speed.","default":10},"ef_search":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Ef Search","description":"Size of the dynamic candidate list for HNSW index search. Higher increases accuracy but decreases speed.","default":40},"hybrid_search_settings":{"anyOf":[{"$ref":"#/components/schemas/HybridSearchSettings"},{"type":"null"}],"description":"Settings for hybrid search","default":{"full_text_weight":1.0,"semantic_weight":5.0,"full_text_limit":200,"rrf_k":50}},"search_strategy":{"type":"string","title":"Search Strategy","description":"Search strategy to use (e.g., 'default', 'query_fusion', 'hyde')","default":"vanilla"}},"type":"object","title":"VectorSearchSettings","ef_search":40,"filters":{"category":"technology"},"hybrid_search_settings":{"full_text_limit":200,"full_text_weight":1.0,"rrf_k":50,"semantic_weight":5.0},"include_metadata":true,"index_measure":"cosine_distance","limit":20,"offset":0,"probes":10,"selected_collection_ids":["2acb499e-8428-543b-bd85-0d9098718220","3e157b3a-8469-51db-90d9-52e7d896b49b"],"use_hybrid_search":true,"use_vector_search":true},"shared__api__models__auth__responses__UserResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"email":{"type":"string","title":"Email"},"is_active":{"type":"boolean","title":"Is Active","default":true},"is_superuser":{"type":"boolean","title":"Is Superuser","default":false},"created_at":{"type":"string","format":"date-time","title":"Created At","default":"2024-10-04T15:32:28.154901"},"updated_at":{"type":"string","format":"date-time","title":"Updated At","default":"2024-10-04T15:32:28.154905"},"is_verified":{"type":"boolean","title":"Is Verified","default":false},"collection_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Collection Ids","default":[]},"hashed_password":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hashed Password"},"verification_code_expiry":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Verification Code Expiry"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"bio":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bio"},"profile_picture":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Profile Picture"}},"type":"object","required":["id","email"],"title":"UserResponse"},"shared__api__models__management__responses__UserResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"email":{"type":"string","title":"Email"},"is_active":{"type":"boolean","title":"Is Active","default":true},"is_superuser":{"type":"boolean","title":"Is Superuser","default":false},"created_at":{"type":"string","format":"date-time","title":"Created At","default":"2024-10-04T15:32:28.171824"},"updated_at":{"type":"string","format":"date-time","title":"Updated At","default":"2024-10-04T15:32:28.171829"},"is_verified":{"type":"boolean","title":"Is Verified","default":false},"collection_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Collection Ids","default":[]},"hashed_password":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hashed Password"},"verification_code_expiry":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Verification Code Expiry"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"bio":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bio"},"profile_picture":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Profile Picture"}},"type":"object","required":["id","email"],"title":"UserResponse"}},"securitySchemes":{"HTTPBearer":{"type":"http","scheme":"bearer"},"OAuth2PasswordBearer":{"type":"oauth2","flows":{"password":{"scopes":{},"tokenUrl":"token"}}}}}} +{"openapi":"3.1.0","info":{"title":"R2R Application API","version":"1.0.0"},"paths":{"/v2/ingest_files":{"post":{"summary":"Ingest Files App","description":"Ingest files into the system.\n\nThis endpoint supports multipart/form-data requests, enabling you to ingest files and their associated metadatas into R2R.\n\nA valid user authentication token is required to access this endpoint, as regular users can only ingest files for their own access. More expansive collection permissioning is under development.","operationId":"ingest_files_app_v2_ingest_files_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_ingest_files_app_v2_ingest_files_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_list_IngestionResponse__"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}],"x-codeSamples":[{"lang":"Python","source":"from r2r import R2RClient\n\nclient = R2RClient(\"http://localhost:7272\")\n# when using auth, do client.login(...)\n\nresult = client.ingest_files(\n file_paths=[\"pg_essay_1.html\", \"got.txt\"],\n metadatas=[{\"metadata_1\":\"some random metadata\"}, {\"metadata_2\": \"some other random metadata\"}],\n document_ids=None,\n versions=None\n)\n"},{"lang":"Shell","source":"curl -X POST \"https://api.example.com/ingest_files\" \\\n -H \"Content-Type: multipart/form-data\" \\\n -H \"Authorization: Bearer YOUR_API_KEY\" \\\n -F \"file=@pg_essay_1.html;type=text/html\" \\\n -F \"file=@got.txt;type=text/plain\" \\\n -F 'metadatas=[{},{}]' \\\n -F 'document_ids=null' \\\n -F 'versions=null'\n"}]}},"/v2/update_files":{"post":{"summary":"Update Files App","description":"Update existing files in the system.\n\nThis endpoint supports multipart/form-data requests, enabling you to update files and their associated metadatas into R2R.\n\nA valid user authentication token is required to access this endpoint, as regular users can only update their own files. More expansive collection permissioning is under development.","operationId":"update_files_app_v2_update_files_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_update_files_app_v2_update_files_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_UpdateResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}],"x-codeSamples":[{"lang":"Python","source":"from r2r import R2RClient\n\nclient = R2RClient(\"http://localhost:7272\")\n# when using auth, do client.login(...)\n\nresult = client.update_files(\n file_paths=[\"pg_essay_1_v2.txt\"],\n document_ids=[\"b4ac4dd6-5f27-596e-a55b-7cf242ca30aa\"]\n)\n"},{"lang":"Shell","source":"curl -X POST \"https://api.example.com/update_files\" \\\n -H \"Content-Type: multipart/form-data\" \\\n -H \"Authorization: Bearer YOUR_API_KEY\" \\\n -F \"file=@pg_essay_1_v2.txt;type=text/plain\" \\\n -F 'document_ids=[\"b4ac4dd6-5f27-596e-a55b-7cf242ca30aa\"]'\n"}]}},"/v2/ingest_chunks":{"post":{"summary":"Ingest Chunks App","description":"Ingest text chunks into the system.\n\nThis endpoint supports multipart/form-data requests, enabling you to ingest pre-parsed text chunks into R2R.\n\nA valid user authentication token is required to access this endpoint, as regular users can only ingest chunks for their own access. More expansive collection permissioning is under development.","operationId":"ingest_chunks_app_v2_ingest_chunks_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_ingest_chunks_app_v2_ingest_chunks_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_list_IngestionResponse__"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}],"x-codeSamples":[{"lang":"Python","source":"from r2r import R2RClient\n\nclient = R2RClient(\"http://localhost:7272\")\n# when using auth, do client.login(...)\n\nresult = client.ingest_chunks(\n chunks=[\n {\n \"text\": \"Another chunk of text\",\n },\n {\n \"text\": \"Yet another chunk of text\",\n },\n {\n \"text\": \"A chunk of text\",\n },\n ],\n)\n"},{"lang":"Shell","source":"curl -X POST \"https://api.example.com/ingest_chunks\" \\\n -H \"Content-Type: application/json\" \\\n -H \"Authorization: Bearer YOUR_API_KEY\" \\\n -d '{\n \"chunks\": [\n {\n \"text\": \"Another chunk of text\"\n },\n {\n \"text\": \"Yet another chunk of text\"\n },\n {\n \"text\": \"A chunk of text\"\n }\n ],\n \"document_id\": \"b4ac4dd6-5f27-596e-a55b-7cf242ca30aa\",\n \"metadata\": {}\n }'\n"}]}},"/v2/health":{"get":{"summary":"Health Check","operationId":"health_check_v2_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v2/server_stats":{"get":{"summary":"Server Stats","operationId":"server_stats_v2_server_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_ServerStats_"}}}}},"security":[{"HTTPBearer":[]}]}},"/v2/update_prompt":{"post":{"summary":"Update Prompt App","operationId":"update_prompt_app_v2_update_prompt_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_update_prompt_app_v2_update_prompt_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_UpdatePromptResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v2/add_prompt":{"post":{"summary":"Add Prompt App","operationId":"add_prompt_app_v2_add_prompt_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_add_prompt_app_v2_add_prompt_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_UpdatePromptResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v2/get_prompt/{prompt_name}":{"get":{"summary":"Get Prompt App","operationId":"get_prompt_app_v2_get_prompt__prompt_name__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"prompt_name","in":"path","required":true,"schema":{"type":"string","description":"Prompt name","title":"Prompt Name"},"description":"Prompt name"},{"name":"inputs","in":"query","required":false,"schema":{"anyOf":[{"type":"string","contentMediaType":"application/json","contentSchema":{"type":"object"}},{"type":"null"}],"description":"JSON-encoded prompt inputs","title":"Inputs"},"description":"JSON-encoded prompt inputs"},{"name":"prompt_override","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Prompt override","title":"Prompt Override"},"description":"Prompt override"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_UpdatePromptResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/get_all_prompts":{"get":{"summary":"Get All Prompts App","operationId":"get_all_prompts_app_v2_get_all_prompts_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_AllPromptsResponse_"}}}}},"security":[{"HTTPBearer":[]}]}},"/v2/delete_prompt/{prompt_name}":{"delete":{"summary":"Delete Prompt App","operationId":"delete_prompt_app_v2_delete_prompt__prompt_name__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"prompt_name","in":"path","required":true,"schema":{"type":"string","description":"Prompt name","title":"Prompt Name"},"description":"Prompt name"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_NoneType_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/analytics":{"get":{"summary":"Get Analytics App","operationId":"get_analytics_app_v2_analytics_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"filter_criteria","in":"query","required":false,"schema":{"anyOf":[{"type":"string","contentMediaType":"application/json","contentSchema":{"type":"object"}},{"type":"null"}],"default":{},"title":"Filter Criteria"}},{"name":"analysis_types","in":"query","required":false,"schema":{"anyOf":[{"type":"string","contentMediaType":"application/json","contentSchema":{"type":"object"}},{"type":"null"}],"default":{},"title":"Analysis Types"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_AnalyticsResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/logs":{"get":{"summary":"Logs App","operationId":"logs_app_v2_logs_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"run_type_filter","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":"","title":"Run Type Filter"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_list_LogResponse__"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/app_settings":{"get":{"summary":"App Settings","operationId":"app_settings_v2_app_settings_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_AppSettingsResponse_"}}}}},"security":[{"HTTPBearer":[]}]}},"/v2/score_completion":{"post":{"summary":"Score Completion","operationId":"score_completion_v2_score_completion_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_score_completion_v2_score_completion_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_ScoreCompletionResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v2/users_overview":{"get":{"summary":"Users Overview App","operationId":"users_overview_app_v2_users_overview_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_ids","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"default":[],"title":"User Ids"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResultsWrapper_list_UserOverviewResponse__"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/delete":{"delete":{"summary":"Delete App","operationId":"delete_app_v2_delete_delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"filters","in":"query","required":true,"schema":{"type":"string","description":"JSON-encoded filters","title":"Filters"},"description":"JSON-encoded filters"}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/download_file/{document_id}":{"get":{"summary":"Download File App","description":"Download a file by its document ID as a stream.","operationId":"download_file_app_v2_download_file__document_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"document_id","in":"path","required":true,"schema":{"type":"string","description":"Document ID","title":"Document Id"},"description":"Document ID"}],"responses":{"200":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/documents_overview":{"get":{"summary":"Documents Overview App","operationId":"documents_overview_app_v2_documents_overview_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"document_ids","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"},"default":[],"title":"Document Ids"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResultsWrapper_list_DocumentOverviewResponse__"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/document_chunks/{document_id}":{"get":{"summary":"Document Chunks App","operationId":"document_chunks_app_v2_document_chunks__document_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"document_id","in":"path","required":true,"schema":{"type":"string","title":"Document Id"}},{"name":"offset","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"default":0,"title":"Offset"}},{"name":"limit","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResultsWrapper_list_DocumentChunkResponse__"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/collections_overview":{"get":{"summary":"Collections Overview App","operationId":"collections_overview_app_v2_collections_overview_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"collection_ids","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Collection Ids"}},{"name":"offset","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"default":0,"title":"Offset"}},{"name":"limit","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":1000,"minimum":1},{"type":"null"}],"default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_list_CollectionOverviewResponse__"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/create_collection":{"post":{"summary":"Create Collection App","operationId":"create_collection_app_v2_create_collection_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_create_collection_app_v2_create_collection_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_CollectionResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v2/get_collection/{collection_id}":{"get":{"summary":"Get Collection App","operationId":"get_collection_app_v2_get_collection__collection_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"collection_id","in":"path","required":true,"schema":{"type":"string","description":"Collection ID","title":"Collection Id"},"description":"Collection ID"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_CollectionResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/update_collection":{"put":{"summary":"Update Collection App","operationId":"update_collection_app_v2_update_collection_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_update_collection_app_v2_update_collection_put"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_CollectionResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v2/delete_collection/{collection_id}":{"delete":{"summary":"Delete Collection App","operationId":"delete_collection_app_v2_delete_collection__collection_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"collection_id","in":"path","required":true,"schema":{"type":"string","description":"Collection ID","title":"Collection Id"},"description":"Collection ID"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/list_collections":{"get":{"summary":"List Collections App","operationId":"list_collections_app_v2_list_collections_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_list_CollectionResponse__"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/add_user_to_collection":{"post":{"summary":"Add User To Collection App","operationId":"add_user_to_collection_app_v2_add_user_to_collection_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_add_user_to_collection_app_v2_add_user_to_collection_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_AddUserResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v2/remove_user_from_collection":{"post":{"summary":"Remove User From Collection App","operationId":"remove_user_from_collection_app_v2_remove_user_from_collection_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_remove_user_from_collection_app_v2_remove_user_from_collection_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v2/get_users_in_collection/{collection_id}":{"get":{"summary":"Get Users In Collection App","operationId":"get_users_in_collection_app_v2_get_users_in_collection__collection_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"collection_id","in":"path","required":true,"schema":{"type":"string","description":"Collection ID","title":"Collection Id"},"description":"Collection ID"},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Pagination offset","default":0,"title":"Offset"},"description":"Pagination offset"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"description":"Pagination limit","default":100,"title":"Limit"},"description":"Pagination limit"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResultsWrapper_list_UserResponse__"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/user_collections/{user_id}":{"get":{"summary":"Get Collections For User App","operationId":"get_collections_for_user_app_v2_user_collections__user_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","description":"User ID","title":"User Id"},"description":"User ID"},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Pagination offset","default":0,"title":"Offset"},"description":"Pagination offset"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"description":"Pagination limit","default":100,"title":"Limit"},"description":"Pagination limit"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResultsWrapper_list_CollectionOverviewResponse__"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/assign_document_to_collection":{"post":{"summary":"Assign Document To Collection App","operationId":"assign_document_to_collection_app_v2_assign_document_to_collection_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_assign_document_to_collection_app_v2_assign_document_to_collection_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v2/remove_document_from_collection":{"post":{"summary":"Remove Document From Collection App","operationId":"remove_document_from_collection_app_v2_remove_document_from_collection_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_remove_document_from_collection_app_v2_remove_document_from_collection_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_NoneType_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v2/document_collections/{document_id}":{"get":{"summary":"Document Collections App","operationId":"document_collections_app_v2_document_collections__document_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"document_id","in":"path","required":true,"schema":{"type":"string","description":"Document ID","title":"Document Id"},"description":"Document ID"},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_list_CollectionResponse__"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/collection/{collection_id}/documents":{"get":{"summary":"Documents In Collection App","operationId":"documents_in_collection_app_v2_collection__collection_id__documents_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"collection_id","in":"path","required":true,"schema":{"type":"string","description":"Collection ID","title":"Collection Id"},"description":"Collection ID"},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResultsWrapper_list_DocumentOverviewResponse__"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/search":{"post":{"summary":"Search App","description":"Perform a search query on the vector database and knowledge graph.\n\nThis endpoint allows for complex filtering of search results using PostgreSQL-based queries.\nFilters can be applied to various fields such as document_id, and internal metadata values.\n\n\nAllowed operators include `eq`, `neq`, `gt`, `gte`, `lt`, `lte`, `like`, `ilike`, `in`, and `nin`.","operationId":"search_app_v2_search_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_search_app_v2_search_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_SearchResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}],"x-codeSamples":[{"lang":"Python","source":"from r2r import R2RClient\n\nclient = R2RClient(\"http://localhost:7272\")\n# when using auth, do client.login(...)\n\nresult = client.search(\n query=\"Who is Aristotle?\",\n vector_search_settings={\n \"use_vector_search\": True,\n \"filters\": {\"document_id\": {\"$eq\": \"3e157b3a-8469-51db-90d9-52e7d896b49b\"}},\n \"search_limit\": 20,\n \"use_hybrid_search\": True\n },\n kg_search_settings={\n \"use_kg_search\": True, # graph needs to be constructed first\n \"kg_search_type\": \"local\",\n \"kg_search_level\": \"0\",\n \"generation_config\": {\n \"model\": \"gpt-4o-mini\",\n \"temperature\": 0.7,\n },\n \"local_search_limits\": {\n \"__Entity__\": 20,\n \"__Relationship__\": 20,\n \"__Community__\": 20,\n },\n \"max_community_description_length\": 65536,\n \"max_llm_queries_for_global_search\": 250\n }\n)\n"},{"lang":"Shell","source":"curl -X POST \"https://api.example.com/search\" \\\n -H \"Content-Type: application/json\" \\\n -H \"Authorization: Bearer YOUR_API_KEY\" \\\n -d '{\n \"query\": \"Who is Aristotle?\",\n \"vector_search_settings\": {\n \"use_vector_search\": true,\n \"filters\": {\"document_id\": {\"$eq\": \"3e157b3a-8469-51db-90d9-52e7d896b49b\"}},\n \"search_limit\": 20,\n \"use_hybrid_search\": true\n },\n \"kg_search_settings\": {\n \"use_kg_search\": true, # graph needs to be constructed first\n \"kg_search_type\": \"local\",\n \"kg_search_level\": \"0\",\n \"generation_config\": {\n \"model\": \"gpt-4o-mini\",\n \"temperature\": 0.7\n },\n \"local_search_limits\": {\n \"__Entity__\": 20,\n \"__Relationship__\": 20,\n \"__Community__\": 20,\n },\n \"max_community_description_length\": 65536,\n \"max_llm_queries_for_global_search\": 250\n }\n }'\n"}]}},"/v2/rag":{"post":{"summary":"Rag App","description":"Execute a RAG (Retrieval-Augmented Generation) query.\n\nThis endpoint combines search results with language model generation.\nIt supports the same filtering capabilities as the search endpoint,\nallowing for precise control over the retrieved context.\n\nThe generation process can be customized using the rag_generation_config parameter.","operationId":"rag_app_v2_rag_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_rag_app_v2_rag_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_RAGResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}],"x-codeSamples":[{"lang":"Python","source":"from r2r import R2RClient\n\nclient = R2RClient(\"http://localhost:7272\")\n# when using auth, do client.login(...)\n\nresult = client.rag(\n query=\"Who is Aristotle?\",\n vector_search_settings={\n \"use_vector_search\": True,\n \"filters\": {\"document_id\": {\"$eq\": \"3e157b3a-8469-51db-90d9-52e7d896b49b\"}},\n \"search_limit\": 20,\n \"use_hybrid_search\": True\n },\n kg_search_settings={\n \"use_kg_search\": True,\n \"kg_search_type\": \"local\",\n \"kg_search_level\": \"0\",\n \"generation_config\": {\n \"model\": \"gpt-4o-mini\",\n \"temperature\": 0.7,\n },\n \"local_search_limits\": {\n \"__Entity__\": 20,\n \"__Relationship__\": 20,\n \"__Community__\": 20,\n },\n \"max_community_description_length\": 65536,\n \"max_llm_queries_for_global_search\": 250\n },\n rag_generation_config={\n \"stream\": False,\n \"temperature\": 0.7,\n \"max_tokens\": 150\n }\n)\n"},{"lang":"Shell","source":"curl -X POST \"https://api.example.com/rag\" \\\n -H \"Content-Type: application/json\" \\\n -H \"Authorization: Bearer YOUR_API_KEY\" \\\n -d '{\n \"query\": \"Who is Aristotle?\",\n \"vector_search_settings\": {\n \"use_vector_search\": true,\n \"filters\": {\"document_id\": {\"$eq\": \"3e157b3a-8469-51db-90d9-52e7d896b49b\"}},\n \"search_limit\": 20,\n \"use_hybrid_search\": True\n },\n \"kg_search_settings\": {\n \"use_kg_search\": true, # graph needs to be constructed first\n \"kg_search_type\": \"local\",\n \"kg_search_level\": \"0\",\n \"generation_config\": {\n \"model\": \"gpt-4o-mini\",\n \"temperature\": 0.7\n },\n \"local_search_limits\": {\n \"__Entity__\": 20,\n \"__Relationship__\": 20,\n \"__Community__\": 20,\n },\n \"max_community_description_length\": 65536,\n \"max_llm_queries_for_global_search\": 250\n },\n \"rag_generation_config\": {\n \"stream\": false,\n \"temperature\": 0.7,\n \"max_tokens\": 150\n }\n }'\n"}]}},"/v2/agent":{"post":{"summary":"Agent App","description":"Implement an agent-based interaction for complex query processing.\n\nThis endpoint supports multi-turn conversations and can handle complex queries\nby breaking them down into sub-tasks. It uses the same filtering capabilities\nas the search and RAG endpoints for retrieving relevant information.\n\nThe agent's behavior can be customized using the rag_generation_config and\ntask_prompt_override parameters.","operationId":"agent_app_v2_agent_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_agent_app_v2_agent_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_RAGAgentResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}],"x-codeSamples":[{"lang":"Python","source":"from r2r import R2RClient\n\nclient = R2RClient(\"http://localhost:7272\")\n# when using auth, do client.login(...)\n\nresult = client.agent(\n messages=[\n {\"role\": \"user\", \"content\": \"Who is the greatest philospher of all time?\"},\n {\"role\": \"assistant\", \"content\": \"Aristotle is widely considered the greatest philospher of all time.\"},\n {\"role\": \"user\", \"content\": \"Can you tell me more about him?\"}\n ],\n vector_search_settings={\n \"use_vector_search\": True,\n \"filters\": {\"document_id\": {\"$eq\": \"5e157b3a-8469-51db-90d9-52e7d896b49b\"}},\n \"search_limit\": 20,\n \"use_hybrid_search\": True\n },\n rag_generation_config={\n \"stream\": False,\n \"temperature\": 0.7,\n \"max_tokens\": 200\n },\n include_title_if_available=True\n)\n"},{"lang":"Shell","source":"curl -X POST \"https://api.example.com/agent\" \\\n -H \"Content-Type: application/json\" \\\n -H \"Authorization: Bearer YOUR_API_KEY\" \\\n -d '{\n \"messages\": [\n {\"role\": \"user\", \"content\": \"Who is the greatest philospher of all time?\"},\n {\"role\": \"assistant\", \"content\": \"Aristotle is widely considered the greatest philospher of all time.\"},\n {\"role\": \"user\", \"content\": \"Can you tell me more about him?\"}\n ],\n \"vector_search_settings\": {\n \"use_vector_search\": true,\n \"filters\": {\"document_id\": {\"$eq\": \"5e157b3a-8469-51db-90d9-52e7d896b49b\"}},\n \"search_limit\": 20,\n \"use_hybrid_search\": true\n },\n \"kg_search_settings\": {\n \"use_kg_search\": false # to enable this, please read the graphrag cookbook\n },\n \"rag_generation_config\": {\n \"stream\": false,\n \"temperature\": 0.7,\n \"max_tokens\": 200\n },\n \"include_title_if_available\": true\n }'\n"}]}},"/v2/completion":{"post":{"summary":"Completion","description":"Generate completions for a list of messages.\n\nThis endpoint uses the language model to generate completions for the provided messages.\nThe generation process can be customized using the generation_config parameter.","operationId":"completion_v2_completion_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"response_model","in":"query","required":false,"schema":{"title":"Response Model"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_completion_v2_completion_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/register":{"post":{"summary":"Register App","description":"Register a new user with the given email and password.","operationId":"register_app_v2_register_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_register_app_v2_register_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_UserResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/verify_email":{"post":{"summary":"Verify Email App","description":"Verify a user's email address.\n\nThis endpoint is used to confirm a user's email address using the verification code\nsent to their email after registration.","operationId":"verify_email_app_v2_verify_email_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_verify_email_app_v2_verify_email_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_GenericMessageResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/login":{"post":{"summary":"Login App","description":"Authenticate a user and provide access tokens.\n\nThis endpoint authenticates a user using their email (username) and password,\nand returns access and refresh tokens upon successful authentication.","operationId":"login_app_v2_login_post","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/Body_login_app_v2_login_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_TokenResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/logout":{"post":{"summary":"Logout App","description":"Log out the current user.\n\nThis endpoint invalidates the user's current access token, effectively logging them out.","operationId":"logout_app_v2_logout_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_GenericMessageResponse_"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"HTTPBearer":[]}]}},"/v2/user":{"get":{"summary":"Get User App","description":"Get the current user's profile information.\n\nThis endpoint returns the profile information of the currently authenticated user.","operationId":"get_user_app_v2_user_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_UserResponse_"}}}}},"security":[{"HTTPBearer":[]}]},"put":{"summary":"Put User App","description":"Update the current user's profile information.\n\nThis endpoint allows the authenticated user to update their profile information.","operationId":"put_user_app_v2_user_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_put_user_app_v2_user_put"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_UserResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v2/refresh_access_token":{"post":{"summary":"Refresh Access Token App","description":"Refresh the access token using a refresh token.\n\nThis endpoint allows users to obtain a new access token using their refresh token.","operationId":"refresh_access_token_app_v2_refresh_access_token_post","requestBody":{"content":{"application/json":{"schema":{"type":"string","title":"Refresh Token","description":"Refresh token"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_TokenResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/change_password":{"post":{"summary":"Change Password App","description":"Change the authenticated user's password.\n\nThis endpoint allows users to change their password by providing their current password\nand a new password.","operationId":"change_password_app_v2_change_password_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_change_password_app_v2_change_password_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_GenericMessageResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v2/request_password_reset":{"post":{"summary":"Request Password Reset App","description":"Request a password reset for a user.\n\nThis endpoint initiates the password reset process by sending a reset link\nto the specified email address.","operationId":"request_password_reset_app_v2_request_password_reset_post","requestBody":{"content":{"application/json":{"schema":{"type":"string","format":"email","title":"Email","description":"User's email address"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_GenericMessageResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/reset_password":{"post":{"summary":"Reset Password App","operationId":"reset_password_app_v2_reset_password_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_reset_password_app_v2_reset_password_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_GenericMessageResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/user/{user_id}":{"delete":{"summary":"Delete User App","description":"Delete a user account.\n\nThis endpoint allows users to delete their own account or, for superusers,\nto delete any user account.","operationId":"delete_user_app_v2_user__user_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","description":"ID of the user to delete","title":"User Id"},"description":"ID of the user to delete"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_delete_user_app_v2_user__user_id__delete"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_GenericMessageResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/create_graph":{"post":{"summary":"Create Graph","description":"Creating a graph on your documents. This endpoint takes input a list of document ids and KGCreationSettings. If document IDs are not provided, the graph will be created on all documents in the system.\nThis step extracts the relevant entities and relationships from the documents and creates a graph based on the extracted information.\nIn order to do GraphRAG, you will need to run the enrich_graph endpoint.","operationId":"create_graph_v2_create_graph_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_create_graph_v2_create_graph_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_Union_KGCreationResponse__KGCreationEstimationResponse__"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v2/enrich_graph":{"post":{"summary":"Enrich Graph","description":"This endpoint enriches the graph with additional information. It creates communities of nodes based on their similarity and adds embeddings to the graph. This step is necessary for GraphRAG to work.","operationId":"enrich_graph_v2_enrich_graph_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_enrich_graph_v2_enrich_graph_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResultsWrapper_Union_KGEnrichmentResponse__KGEnrichmentEstimationResponse__"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v2/entities":{"get":{"summary":"Get Entities","description":"Retrieve entities from the knowledge graph.","operationId":"get_entities_v2_entities_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"collection_id","in":"query","required":true,"schema":{"type":"string","format":"uuid","description":"Collection ID to retrieve entities from.","title":"Collection Id"},"description":"Collection ID to retrieve entities from."},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Offset for pagination.","default":0,"title":"Offset"},"description":"Offset for pagination."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"description":"Limit for pagination.","default":100,"title":"Limit"},"description":"Limit for pagination."},{"name":"entity_ids","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Entity IDs to filter by.","title":"Entity Ids"},"description":"Entity IDs to filter by."},{"name":"with_description","in":"query","required":false,"schema":{"type":"boolean","description":"Include entity descriptions in the response.","default":false,"title":"With Description"},"description":"Include entity descriptions in the response."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/triples":{"get":{"summary":"Get Triples","description":"Retrieve triples from the knowledge graph.","operationId":"get_triples_v2_triples_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"collection_id","in":"query","required":true,"schema":{"type":"string","format":"uuid","description":"Collection ID to retrieve triples from.","title":"Collection Id"},"description":"Collection ID to retrieve triples from."},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Offset for pagination.","default":0,"title":"Offset"},"description":"Offset for pagination."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"description":"Limit for pagination.","default":100,"title":"Limit"},"description":"Limit for pagination."},{"name":"triple_ids","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Triple IDs to filter by.","title":"Triple Ids"},"description":"Triple IDs to filter by."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/openapi_spec":{"get":{"summary":"Openapi Spec","operationId":"openapi_spec_v2_openapi_spec_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}}},"components":{"schemas":{"AddUserResponse":{"properties":{"result":{"type":"boolean","title":"Result"}},"type":"object","required":["result"],"title":"AddUserResponse"},"AllPromptsResponse":{"properties":{"prompts":{"additionalProperties":{"$ref":"#/components/schemas/PromptResponse"},"type":"object","title":"Prompts"}},"type":"object","required":["prompts"],"title":"AllPromptsResponse"},"AnalyticsResponse":{"properties":{"analytics_data":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Analytics Data"},"filtered_logs":{"type":"object","title":"Filtered Logs"}},"type":"object","required":["filtered_logs"],"title":"AnalyticsResponse"},"AppSettingsResponse":{"properties":{"config":{"type":"object","title":"Config"},"prompts":{"type":"object","title":"Prompts"}},"type":"object","required":["config","prompts"],"title":"AppSettingsResponse"},"Body_add_prompt_app_v2_add_prompt_post":{"properties":{"name":{"type":"string","title":"Name","description":"Prompt name"},"template":{"type":"string","title":"Template","description":"Prompt template"},"input_types":{"additionalProperties":{"type":"string"},"type":"object","title":"Input Types","description":"Input types","default":{}}},"type":"object","required":["name","template"],"title":"Body_add_prompt_app_v2_add_prompt_post"},"Body_add_user_to_collection_app_v2_add_user_to_collection_post":{"properties":{"user_id":{"type":"string","title":"User Id","description":"User ID"},"collection_id":{"type":"string","title":"Collection Id","description":"Collection ID"}},"type":"object","required":["user_id","collection_id"],"title":"Body_add_user_to_collection_app_v2_add_user_to_collection_post"},"Body_agent_app_v2_agent_post":{"properties":{"messages":{"items":{"$ref":"#/components/schemas/Message"},"type":"array","title":"Messages","description":"List of message objects"},"vector_search_settings":{"$ref":"#/components/schemas/VectorSearchSettings","description":"Vector search settings"},"kg_search_settings":{"$ref":"#/components/schemas/KGSearchSettings","description":"Knowledge graph search settings"},"rag_generation_config":{"$ref":"#/components/schemas/GenerationConfig","description":"RAG generation configuration"},"task_prompt_override":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Task Prompt Override","description":"Task prompt override"},"include_title_if_available":{"type":"boolean","title":"Include Title If Available","description":"Includes document title in chunk response, if available.","default":true}},"type":"object","required":["messages"],"title":"Body_agent_app_v2_agent_post"},"Body_assign_document_to_collection_app_v2_assign_document_to_collection_post":{"properties":{"document_id":{"type":"string","title":"Document Id","description":"Document ID"},"collection_id":{"type":"string","title":"Collection Id","description":"Collection ID"}},"type":"object","required":["document_id","collection_id"],"title":"Body_assign_document_to_collection_app_v2_assign_document_to_collection_post"},"Body_change_password_app_v2_change_password_post":{"properties":{"current_password":{"type":"string","title":"Current Password","description":"Current password"},"new_password":{"type":"string","title":"New Password","description":"New password"}},"type":"object","required":["current_password","new_password"],"title":"Body_change_password_app_v2_change_password_post"},"Body_completion_v2_completion_post":{"properties":{"messages":{"items":{"$ref":"#/components/schemas/Message"},"type":"array","title":"Messages","description":"The messages to complete"},"generation_config":{"$ref":"#/components/schemas/GenerationConfig","description":"The generation config"}},"type":"object","required":["messages"],"title":"Body_completion_v2_completion_post"},"Body_create_collection_app_v2_create_collection_post":{"properties":{"name":{"type":"string","title":"Name","description":"Collection name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description","description":"Collection description","default":""}},"type":"object","required":["name"],"title":"Body_create_collection_app_v2_create_collection_post"},"Body_create_graph_v2_create_graph_post":{"properties":{"collection_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Collection Id","description":"Collection ID to create graph for."},"run_type":{"anyOf":[{"$ref":"#/components/schemas/KGRunType"},{"type":"null"}],"description":"Run type for the graph creation process."},"kg_creation_settings":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Kg Creation Settings","description":"Settings for the graph creation process."}},"type":"object","title":"Body_create_graph_v2_create_graph_post"},"Body_delete_user_app_v2_user__user_id__delete":{"properties":{"password":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Password","description":"User's current password"},"delete_vector_data":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Delete Vector Data","description":"Whether to delete the user's vector data","default":false}},"type":"object","title":"Body_delete_user_app_v2_user__user_id__delete"},"Body_enrich_graph_v2_enrich_graph_post":{"properties":{"collection_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Collection Id","description":"Collection ID to enrich graph for."},"run_type":{"anyOf":[{"$ref":"#/components/schemas/KGRunType"},{"type":"null"}],"description":"Run type for the graph enrichment process.","default":"estimate"},"kg_enrichment_settings":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Kg Enrichment Settings","description":"Settings for the graph enrichment process."}},"type":"object","title":"Body_enrich_graph_v2_enrich_graph_post"},"Body_ingest_chunks_app_v2_ingest_chunks_post":{"properties":{"chunks":{"items":{"$ref":"#/components/schemas/RawChunk"},"type":"array","title":"Chunks","description":"A list of text chunks to ingest into the system.","default":{}},"document_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Document Id","description":"An optional document id to associate the chunks with. If not provided, a unique document id will be generated."},"metadata":{"anyOf":[{"type":"string","contentMediaType":"application/json","contentSchema":{"type":"object"}},{"type":"null"}],"title":"Metadata"}},"type":"object","title":"Body_ingest_chunks_app_v2_ingest_chunks_post"},"Body_ingest_files_app_v2_ingest_files_post":{"properties":{"files":{"items":{"type":"string","format":"binary"},"type":"array","title":"Files","description":"The list of paths of input files to ingest into the system."},"document_ids":{"anyOf":[{"type":"string","contentMediaType":"application/json","contentSchema":{"items":{"type":"string","format":"uuid"},"type":"array"}},{"type":"null"}],"title":"Document Ids","description":"An optional list of document ids for each file. If not provided, the system will generate a unique document id via the `generate_document_id` method."},"metadatas":{"anyOf":[{"type":"string","contentMediaType":"application/json","contentSchema":{"items":{"type":"object"},"type":"array"}},{"type":"null"}],"title":"Metadatas","description":"An optional list of JSON metadata to affix to each file"},"ingestion_config":{"anyOf":[{"type":"string","contentMediaType":"application/json","contentSchema":{"type":"object"}},{"type":"null"}],"title":"Ingestion Config","description":"An optional dictionary to override the default chunking configuration for the ingestion process. If not provided, the system will use the default server-side chunking configuration."}},"type":"object","required":["files"],"title":"Body_ingest_files_app_v2_ingest_files_post"},"Body_login_app_v2_login_post":{"properties":{"grant_type":{"anyOf":[{"type":"string","pattern":"password"},{"type":"null"}],"title":"Grant Type"},"username":{"type":"string","title":"Username"},"password":{"type":"string","title":"Password"},"scope":{"type":"string","title":"Scope","default":""},"client_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Id"},"client_secret":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Secret"}},"type":"object","required":["username","password"],"title":"Body_login_app_v2_login_post"},"Body_put_user_app_v2_user_put":{"properties":{"user_id":{"type":"string","title":"User Id","description":"ID of the user to update"},"email":{"anyOf":[{"type":"string","format":"email"},{"type":"null"}],"title":"Email","description":"Updated email address"},"is_superuser":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Superuser","description":"Updated superuser status"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name","description":"Updated user name"},"bio":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bio","description":"Updated user bio"},"profile_picture":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Profile Picture","description":"Updated profile picture URL"}},"type":"object","title":"Body_put_user_app_v2_user_put"},"Body_rag_app_v2_rag_post":{"properties":{"query":{"type":"string","title":"Query","description":"RAG query"},"vector_search_settings":{"$ref":"#/components/schemas/VectorSearchSettings","description":"Vector search settings"},"kg_search_settings":{"$ref":"#/components/schemas/KGSearchSettings","description":"Knowledge graph search settings"},"rag_generation_config":{"$ref":"#/components/schemas/GenerationConfig","description":"RAG generation configuration"},"task_prompt_override":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Task Prompt Override","description":"Task prompt override"},"include_title_if_available":{"type":"boolean","title":"Include Title If Available","description":"Includes document title in chunk response, if available.","default":false}},"type":"object","required":["query"],"title":"Body_rag_app_v2_rag_post"},"Body_register_app_v2_register_post":{"properties":{"email":{"type":"string","format":"email","title":"Email","description":"User's email address"},"password":{"type":"string","title":"Password","description":"User's password"}},"type":"object","required":["email","password"],"title":"Body_register_app_v2_register_post"},"Body_remove_document_from_collection_app_v2_remove_document_from_collection_post":{"properties":{"document_id":{"type":"string","title":"Document Id","description":"Document ID"},"collection_id":{"type":"string","title":"Collection Id","description":"Collection ID"}},"type":"object","required":["document_id","collection_id"],"title":"Body_remove_document_from_collection_app_v2_remove_document_from_collection_post"},"Body_remove_user_from_collection_app_v2_remove_user_from_collection_post":{"properties":{"user_id":{"type":"string","title":"User Id","description":"User ID"},"collection_id":{"type":"string","title":"Collection Id","description":"Collection ID"}},"type":"object","required":["user_id","collection_id"],"title":"Body_remove_user_from_collection_app_v2_remove_user_from_collection_post"},"Body_reset_password_app_v2_reset_password_post":{"properties":{"reset_token":{"type":"string","title":"Reset Token","description":"Password reset token"},"new_password":{"type":"string","title":"New Password","description":"New password"}},"type":"object","required":["reset_token","new_password"],"title":"Body_reset_password_app_v2_reset_password_post"},"Body_score_completion_v2_score_completion_post":{"properties":{"message_id":{"type":"string","title":"Message Id","description":"Message ID"},"score":{"type":"number","title":"Score","description":"Completion score"}},"type":"object","required":["message_id","score"],"title":"Body_score_completion_v2_score_completion_post"},"Body_search_app_v2_search_post":{"properties":{"query":{"type":"string","title":"Query","description":"Search query"},"vector_search_settings":{"$ref":"#/components/schemas/VectorSearchSettings","description":"Vector search settings"},"kg_search_settings":{"$ref":"#/components/schemas/KGSearchSettings","description":"Knowledge graph search settings"}},"type":"object","required":["query"],"title":"Body_search_app_v2_search_post"},"Body_update_collection_app_v2_update_collection_put":{"properties":{"collection_id":{"type":"string","title":"Collection Id","description":"Collection ID"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name","description":"Updated collection name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description","description":"Updated collection description"}},"type":"object","required":["collection_id"],"title":"Body_update_collection_app_v2_update_collection_put"},"Body_update_files_app_v2_update_files_post":{"properties":{"files":{"items":{"type":"string","format":"binary"},"type":"array","title":"Files","description":"The list of paths of input files to update in the system."},"document_ids":{"anyOf":[{"type":"string","contentMediaType":"application/json","contentSchema":{"items":{"type":"string","format":"uuid"},"type":"array"}},{"type":"null"}],"title":"Document Ids","description":"An optional list of document ids for each file. If not provided, the system will generate a unique document id via the `generate_document_id` method."},"metadatas":{"anyOf":[{"type":"string","contentMediaType":"application/json","contentSchema":{"items":{"type":"object"},"type":"array"}},{"type":"null"}],"title":"Metadatas","description":"An optional list of JSON metadata to affix to each file"},"ingestion_config":{"anyOf":[{"type":"string","contentMediaType":"application/json","contentSchema":{"type":"object"}},{"type":"null"}],"title":"Ingestion Config","description":"An optional dictionary to override the default chunking configuration for the ingestion process. If not provided, the system will use the default server-side chunking configuration."}},"type":"object","required":["files"],"title":"Body_update_files_app_v2_update_files_post"},"Body_update_prompt_app_v2_update_prompt_post":{"properties":{"name":{"type":"string","title":"Name","description":"Prompt name"},"template":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Template","description":"Prompt template"},"input_types":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Input Types","description":"Input types","default":{}}},"type":"object","required":["name"],"title":"Body_update_prompt_app_v2_update_prompt_post"},"Body_verify_email_app_v2_verify_email_post":{"properties":{"email":{"type":"string","format":"email","title":"Email","description":"User's email address"},"verification_code":{"type":"string","title":"Verification Code","description":"Email verification code"}},"type":"object","required":["email","verification_code"],"title":"Body_verify_email_app_v2_verify_email_post"},"CollectionOverviewResponse":{"properties":{"collection_id":{"type":"string","format":"uuid","title":"Collection Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"user_count":{"type":"integer","title":"User Count"},"document_count":{"type":"integer","title":"Document Count"}},"type":"object","required":["collection_id","name","description","created_at","updated_at","user_count","document_count"],"title":"CollectionOverviewResponse"},"CollectionResponse":{"properties":{"collection_id":{"type":"string","format":"uuid","title":"Collection Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["collection_id","name","description","created_at","updated_at"],"title":"CollectionResponse"},"DocumentChunkResponse":{"properties":{"extraction_id":{"type":"string","format":"uuid","title":"Extraction Id"},"document_id":{"type":"string","format":"uuid","title":"Document Id"},"user_id":{"type":"string","format":"uuid","title":"User Id"},"collection_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Collection Ids"},"text":{"type":"string","title":"Text"},"metadata":{"type":"object","title":"Metadata"}},"type":"object","required":["extraction_id","document_id","user_id","collection_ids","text","metadata"],"title":"DocumentChunkResponse"},"DocumentOverviewResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"title":{"type":"string","title":"Title"},"user_id":{"type":"string","format":"uuid","title":"User Id"},"type":{"type":"string","title":"Type"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"ingestion_status":{"type":"string","title":"Ingestion Status"},"kg_extraction_status":{"type":"string","title":"Kg Extraction Status"},"version":{"type":"string","title":"Version"},"collection_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Collection Ids"},"metadata":{"type":"object","title":"Metadata"}},"type":"object","required":["id","title","user_id","type","created_at","updated_at","ingestion_status","kg_extraction_status","version","collection_ids","metadata"],"title":"DocumentOverviewResponse"},"GenerationConfig":{"properties":{"model":{"type":"string","title":"Model"},"temperature":{"type":"number","title":"Temperature"},"top_p":{"type":"number","title":"Top P"},"max_tokens_to_sample":{"type":"integer","title":"Max Tokens To Sample"},"stream":{"type":"boolean","title":"Stream"},"functions":{"anyOf":[{"items":{"type":"object"},"type":"array"},{"type":"null"}],"title":"Functions"},"tools":{"anyOf":[{"items":{"type":"object"},"type":"array"},{"type":"null"}],"title":"Tools"},"add_generation_kwargs":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Add Generation Kwargs"},"api_base":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Api Base"}},"type":"object","title":"GenerationConfig","max_tokens_to_sample":1024,"model":"openai/gpt-4o","stream":false,"temperature":0.1,"top_p":1.0},"GenericMessageResponse":{"properties":{"message":{"type":"string","title":"Message"}},"type":"object","required":["message"],"title":"GenericMessageResponse"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"HybridSearchSettings":{"properties":{"full_text_weight":{"type":"number","title":"Full Text Weight","description":"Weight to apply to full text search","default":1.0},"semantic_weight":{"type":"number","title":"Semantic Weight","description":"Weight to apply to semantic search","default":5.0},"full_text_limit":{"type":"integer","title":"Full Text Limit","description":"Maximum number of results to return from full text search","default":200},"rrf_k":{"type":"integer","title":"Rrf K","description":"K-value for RRF (Rank Reciprocal Fusion)","default":50}},"type":"object","title":"HybridSearchSettings"},"IndexMeasure":{"type":"string","enum":["cosine_distance","l2_distance","max_inner_product"],"title":"IndexMeasure","description":"An enum representing the types of distance measures available for indexing.\n\nAttributes:\n cosine_distance (str): The cosine distance measure for indexing.\n l2_distance (str): The Euclidean (L2) distance measure for indexing.\n max_inner_product (str): The maximum inner product measure for indexing."},"IngestionResponse":{"properties":{"message":{"type":"string","title":"Message","description":"A message describing the result of the ingestion request."},"task_id":{"type":"string","format":"uuid","title":"Task Id","description":"The task ID of the ingestion request."},"document_id":{"type":"string","format":"uuid","title":"Document Id","description":"The ID of the document that was ingested."}},"type":"object","required":["message","task_id","document_id"],"title":"IngestionResponse","example":{"document_id":"9fbe403b-c11c-5aae-8ade-ef22980c3ad1","message":"Ingestion task queued successfully.","task_id":"c68dc72e-fc23-5452-8f49-d7bd46088a96"}},"KGCommunityResult":{"properties":{"name":{"type":"string","title":"Name"},"summary":{"type":"string","title":"Summary"},"rating":{"type":"number","title":"Rating"},"rating_explanation":{"type":"string","title":"Rating Explanation"},"findings":{"items":{"type":"string"},"type":"array","title":"Findings"},"metadata":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Metadata"}},"type":"object","required":["name","summary","rating","rating_explanation","findings"],"title":"KGCommunityResult","findings":["Finding 1","Finding 2"],"metadata":{},"name":"Community Name","rating":9,"rating_explanation":"Rating Explanation","summary":"Community Summary"},"KGCreationEstimationResponse":{"properties":{"message":{"type":"string","title":"Message","description":"The message to display to the user.","default":""},"document_count":{"type":"integer","title":"Document Count","description":"The number of documents in the collection.","default":-1},"number_of_jobs_created":{"type":"integer","title":"Number Of Jobs Created","description":"The number of jobs created for the graph creation process.","default":-1},"total_chunks":{"type":"integer","title":"Total Chunks","description":"The estimated total number of chunks.","default":-1},"estimated_entities":{"type":"string","title":"Estimated Entities","description":"The estimated number of entities in the graph.","default":"NA"},"estimated_triples":{"type":"string","title":"Estimated Triples","description":"The estimated number of triples in the graph.","default":"NA"},"estimated_llm_calls":{"type":"string","title":"Estimated Llm Calls","description":"The estimated number of LLM calls in millions.","default":"NA"},"estimated_total_in_out_tokens_in_millions":{"type":"string","title":"Estimated Total In Out Tokens In Millions","description":"The estimated total number of input and output tokens in millions.","default":"NA"},"estimated_total_time_in_minutes":{"type":"string","title":"Estimated Total Time In Minutes","description":"The estimated total time to run the graph creation process in minutes.","default":"NA"},"estimated_cost_in_usd":{"type":"string","title":"Estimated Cost In Usd","description":"The estimated cost to run the graph creation process in USD.","default":"NA"}},"type":"object","title":"KGCreationEstimationResponse","description":"Response for knowledge graph creation estimation."},"KGCreationResponse":{"properties":{"message":{"type":"string","title":"Message","description":"A message describing the result of the KG creation request."},"task_id":{"type":"string","format":"uuid","title":"Task Id","description":"The task ID of the KG creation request."}},"type":"object","required":["message","task_id"],"title":"KGCreationResponse","example":{"message":"Graph creation queued successfully.","task_id":"c68dc72e-fc23-5452-8f49-d7bd46088a96"}},"KGEnrichmentEstimationResponse":{"properties":{"message":{"type":"string","title":"Message","description":"The message to display to the user.","default":""},"total_entities":{"type":"integer","title":"Total Entities","description":"The total number of entities in the graph.","default":-1},"total_triples":{"type":"integer","title":"Total Triples","description":"The total number of triples in the graph.","default":-1},"estimated_llm_calls":{"type":"string","title":"Estimated Llm Calls","description":"The estimated number of LLM calls.","default":"NA"},"estimated_total_in_out_tokens_in_millions":{"type":"string","title":"Estimated Total In Out Tokens In Millions","description":"The estimated total number of input and output tokens in millions.","default":"NA"},"estimated_cost_in_usd":{"type":"string","title":"Estimated Cost In Usd","description":"The estimated cost to run the graph enrichment process.","default":"NA"},"estimated_total_time_in_minutes":{"type":"string","title":"Estimated Total Time In Minutes","description":"The estimated total time to run the graph enrichment process.","default":"NA"}},"type":"object","title":"KGEnrichmentEstimationResponse","description":"Response for knowledge graph enrichment estimation."},"KGEnrichmentResponse":{"properties":{"message":{"type":"string","title":"Message","description":"A message describing the result of the KG enrichment request."},"task_id":{"type":"string","format":"uuid","title":"Task Id","description":"The task ID of the KG enrichment request."}},"type":"object","required":["message","task_id"],"title":"KGEnrichmentResponse","example":{"message":"Graph enrichment queued successfuly.","task_id":"c68dc72e-fc23-5452-8f49-d7bd46088a96"}},"KGEntityResult":{"properties":{"name":{"type":"string","title":"Name"},"description":{"type":"string","title":"Description"},"metadata":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Metadata"}},"type":"object","required":["name","description"],"title":"KGEntityResult","description":"Entity Description","metadata":{},"name":"Entity Name"},"KGGlobalResult":{"properties":{"name":{"type":"string","title":"Name"},"description":{"type":"string","title":"Description"},"metadata":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Metadata"}},"type":"object","required":["name","description"],"title":"KGGlobalResult","description":"Global Result Description","metadata":{},"name":"Global Result Name"},"KGRelationshipResult":{"properties":{"name":{"type":"string","title":"Name"},"description":{"type":"string","title":"Description"},"metadata":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Metadata"}},"type":"object","required":["name","description"],"title":"KGRelationshipResult","description":"Relationship Description","metadata":{},"name":"Relationship Name"},"KGRunType":{"type":"string","enum":["estimate","run"],"title":"KGRunType","description":"Type of KG run."},"KGSearchMethod":{"type":"string","enum":["local","global"],"title":"KGSearchMethod"},"KGSearchResult":{"properties":{"method":{"$ref":"#/components/schemas/KGSearchMethod"},"content":{"anyOf":[{"$ref":"#/components/schemas/KGEntityResult"},{"$ref":"#/components/schemas/KGRelationshipResult"},{"$ref":"#/components/schemas/KGCommunityResult"},{"$ref":"#/components/schemas/KGGlobalResult"}],"title":"Content"},"result_type":{"anyOf":[{"$ref":"#/components/schemas/KGSearchResultType"},{"type":"null"}]},"extraction_ids":{"anyOf":[{"items":{"type":"string","format":"uuid"},"type":"array"},{"type":"null"}],"title":"Extraction Ids"},"metadata":{"type":"object","title":"Metadata","default":{}}},"type":"object","required":["method","content"],"title":"KGSearchResult","content":{"description":"Entity Description","metadata":{},"name":"Entity Name"},"extraction_ids":["c68dc72e-fc23-5452-8f49-d7bd46088a96"],"metadata":{"associated_query":"What is the capital of France?"},"method":"local","result_type":"entity"},"KGSearchResultType":{"type":"string","enum":["entity","relationship","community"],"title":"KGSearchResultType"},"KGSearchSettings":{"properties":{"filters":{"type":"object","title":"Filters","description":"Filters to apply to the KG search"},"selected_collection_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Selected Collection Ids","description":"Collection IDs to search for"},"graphrag_map_system_prompt":{"type":"string","title":"Graphrag Map System Prompt","description":"The system prompt for the graphrag map prompt.","default":"graphrag_map_system_prompt"},"graphrag_reduce_system_prompt":{"type":"string","title":"Graphrag Reduce System Prompt","description":"The system prompt for the graphrag reduce prompt.","default":"graphrag_reduce_system_prompt"},"use_kg_search":{"type":"boolean","title":"Use Kg Search","description":"Whether to use KG search","default":false},"kg_search_type":{"type":"string","title":"Kg Search Type","description":"KG search type","default":"local"},"kg_search_level":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Kg Search Level","description":"KG search level"},"generation_config":{"$ref":"#/components/schemas/GenerationConfig","description":"Configuration for text generation during graph search."},"max_community_description_length":{"type":"integer","title":"Max Community Description Length","default":65536},"max_llm_queries_for_global_search":{"type":"integer","title":"Max Llm Queries For Global Search","default":250},"local_search_limits":{"additionalProperties":{"type":"integer"},"type":"object","title":"Local Search Limits","default":{"__Entity__":20,"__Relationship__":20,"__Community__":20}}},"type":"object","title":"KGSearchSettings","generation_config":{"max_tokens_to_sample":1024,"model":"openai/gpt-4o","stream":false,"temperature":0.1,"top_p":1.0},"kg_search_level":"0","kg_search_type":"global","local_search_limits":{"__Community__":20,"__Entity__":20,"__Relationship__":20},"max_community_description_length":65536,"max_llm_queries_for_global_search":250,"use_kg_search":true},"LogEntry":{"properties":{"key":{"type":"string","title":"Key"},"value":{"title":"Value"},"timestamp":{"type":"string","format":"date-time","title":"Timestamp"}},"type":"object","required":["key","value","timestamp"],"title":"LogEntry"},"LogResponse":{"properties":{"run_id":{"type":"string","format":"uuid","title":"Run Id"},"run_type":{"type":"string","title":"Run Type"},"entries":{"items":{"$ref":"#/components/schemas/LogEntry"},"type":"array","title":"Entries"},"timestamp":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Timestamp"},"user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"User Id"}},"type":"object","required":["run_id","run_type","entries","timestamp","user_id"],"title":"LogResponse"},"Message":{"properties":{"role":{"anyOf":[{"$ref":"#/components/schemas/MessageType"},{"type":"string"}],"title":"Role"},"content":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Content"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"function_call":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Function Call"},"tool_calls":{"anyOf":[{"items":{"type":"object"},"type":"array"},{"type":"null"}],"title":"Tool Calls"}},"type":"object","required":["role"],"title":"Message","content":"This is a test message.","role":"user"},"MessageType":{"type":"string","enum":["system","user","assistant","function","tool"],"title":"MessageType"},"PaginatedResultsWrapper_list_CollectionOverviewResponse__":{"properties":{"results":{"items":{"$ref":"#/components/schemas/CollectionOverviewResponse"},"type":"array","title":"Results"},"total_entries":{"type":"integer","title":"Total Entries"}},"type":"object","required":["results","total_entries"],"title":"PaginatedResultsWrapper[list[CollectionOverviewResponse]]"},"PaginatedResultsWrapper_list_DocumentChunkResponse__":{"properties":{"results":{"items":{"$ref":"#/components/schemas/DocumentChunkResponse"},"type":"array","title":"Results"},"total_entries":{"type":"integer","title":"Total Entries"}},"type":"object","required":["results","total_entries"],"title":"PaginatedResultsWrapper[list[DocumentChunkResponse]]"},"PaginatedResultsWrapper_list_DocumentOverviewResponse__":{"properties":{"results":{"items":{"$ref":"#/components/schemas/DocumentOverviewResponse"},"type":"array","title":"Results"},"total_entries":{"type":"integer","title":"Total Entries"}},"type":"object","required":["results","total_entries"],"title":"PaginatedResultsWrapper[list[DocumentOverviewResponse]]"},"PaginatedResultsWrapper_list_UserOverviewResponse__":{"properties":{"results":{"items":{"$ref":"#/components/schemas/UserOverviewResponse"},"type":"array","title":"Results"},"total_entries":{"type":"integer","title":"Total Entries"}},"type":"object","required":["results","total_entries"],"title":"PaginatedResultsWrapper[list[UserOverviewResponse]]"},"PaginatedResultsWrapper_list_UserResponse__":{"properties":{"results":{"items":{"$ref":"#/components/schemas/shared__api__models__management__responses__UserResponse"},"type":"array","title":"Results"},"total_entries":{"type":"integer","title":"Total Entries"}},"type":"object","required":["results","total_entries"],"title":"PaginatedResultsWrapper[list[UserResponse]]"},"PromptResponse":{"properties":{"name":{"type":"string","title":"Name"},"template":{"type":"string","title":"Template"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"input_types":{"additionalProperties":{"type":"string"},"type":"object","title":"Input Types"}},"type":"object","required":["name","template","created_at","updated_at","input_types"],"title":"PromptResponse"},"RAGAgentResponse":{"properties":{"messages":{"items":{"$ref":"#/components/schemas/Message"},"type":"array","title":"Messages","description":"List of messages in the RAG agent response"}},"type":"object","required":["messages"],"title":"RAGAgentResponse","example":[{"content":"## You are a helpful assistant that can search for information.\n\nWhen asked a question, perform a search to find relevant information and provide a response.\n\nThe response should contain line-item attributions to relevent search results, and be as informative if possible.\nIf no relevant results are found, then state that no results were found.\nIf no obvious question is present, then do not carry out a search, and instead ask for clarification.","role":"system"},{"content":"You are a helpful assistant.","role":"system"},{"content":"Who is the greatest philospher of all time?","role":"user"},{"content":"Aristotle is widely considered the greatest philospher of all time.","role":"assistant"},{"content":"Can you tell me more about him?","role":"user"},{"function_call":{"arguments":"{\"query\":\"Aristotle biography\"}","name":"search"},"role":"assistant"},{"content":"1. Aristotle[A] (Greek: Ἀριστοτέλης Aristotélēs, pronounced [aristotélɛːs]; 384–322 BC) was an Ancient Greek philosopher and polymath. His writings cover a broad range of subjects spanning the natural sciences, philosophy, linguistics, economics, politics, psychology, and the arts. As the founder of the Peripatetic school of philosophy in the Lyceum in Athens, he began the wider Aristotelian tradition that followed, which set the groundwork for the development of modern science.\n2. Aristotle[A] (Greek: Ἀριστοτέλης Aristotélēs, pronounced [aristotélɛːs]; 384–322 BC) was an Ancient Greek philosopher and polymath. His writings cover a broad range of subjects spanning the natural sciences, philosophy, linguistics, economics, politics, psychology, and the arts. As the founder of the Peripatetic school of philosophy in the Lyceum in Athens, he began the wider Aristotelian tradition that followed, which set the groundwork for the development of modern science.\n3. Aristotle was born in 384 BC[C] in Stagira, Chalcidice,[2] about 55 km (34 miles) east of modern-day Thessaloniki.[3][4] His father, Nicomachus, was the personal physician to King Amyntas of Macedon. While he was young, Aristotle learned about biology and medical information, which was taught by his father.[5] Both of Aristotle's parents died when he was about thirteen, and Proxenus of Atarneus became his guardian.[6] Although little information about Aristotle's childhood has survived, he probably spent\n4. Aristotle was born in 384 BC[C] in Stagira, Chalcidice,[2] about 55 km (34 miles) east of modern-day Thessaloniki.[3][4] His father, Nicomachus, was the personal physician to King Amyntas of Macedon. While he was young, Aristotle learned about biology and medical information, which was taught by his father.[5] Both of Aristotle's parents died when he was about thirteen, and Proxenus of Atarneus became his guardian.[6] Although little information about Aristotle's childhood has survived, he probably spent\n5. Life\nIn general, the details of Aristotle's life are not well-established. The biographies written in ancient times are often speculative and historians only agree on a few salient points.[B]\n","name":"search","role":"function"},{"content":"Aristotle (384–322 BC) was an Ancient Greek philosopher and polymath whose contributions have had a profound impact on various fields of knowledge. Here are some key points about his life and work:\n\n1. **Early Life**: Aristotle was born in 384 BC in Stagira, Chalcidice, which is near modern-day Thessaloniki, Greece. His father, Nicomachus, was the personal physician to King Amyntas of Macedon, which exposed Aristotle to medical and biological knowledge from a young age [C].\n\n2. **Education and Career**: After the death of his parents, Aristotle was sent to Athens to study at Plato's Academy, where he remained for about 20 years. After Plato's death, Aristotle left Athens and eventually became the tutor of Alexander the Great [C].\n\n3. **Philosophical Contributions**: Aristotle founded the Lyceum in Athens, where he established the Peripatetic school of philosophy. His works cover a wide range of subjects, including metaphysics, ethics, politics, logic, biology, and aesthetics. His writings laid the groundwork for many modern scientific and philosophical inquiries [A].\n\n4. **Legacy**: Aristotle's influence extends beyond philosophy to the natural sciences, linguistics, economics, and psychology. His method of systematic observation and analysis has been foundational to the development of modern science [A].\n\nAristotle's comprehensive approach to knowledge and his systematic methodology have earned him a lasting legacy as one of the greatest philosophers of all time.\n\nSources:\n- [A] Aristotle's broad range of writings and influence on modern science.\n- [C] Details about Aristotle's early life and education.","role":"assistant"}]},"RAGResponse":{"properties":{"completion":{"title":"Completion","description":"The generated completion from the RAG process"},"search_results":{"$ref":"#/components/schemas/SearchResponse","description":"The search results used for the RAG process"}},"type":"object","required":["completion","search_results"],"title":"RAGResponse","example":{"completion":{"choices":[{"finish_reason":"stop","index":0,"message":{"content":"Paris is the capital of France.","role":"assistant"}}],"id":"chatcmpl-example123"},"search_results":{"kg_search_results":[{"content":{"description":"Entity Description","metadata":{},"name":"Entity Name"},"extraction_ids":["c68dc72e-fc23-5452-8f49-d7bd46088a96"],"metadata":{"associated_query":"What is the capital of France?"},"method":"local","result_type":"entity"}],"vector_search_results":[{"collection_ids":[],"document_id":"3e157b3a-8469-51db-90d9-52e7d896b49b","extraction_id":"3f3d47f3-8baf-58eb-8bc2-0171fb1c6e09","metadata":{"associated_query":"What is the capital of France?","title":"example_document.pdf"},"score":0.23943702876567796,"text":"Example text from the document","user_id":"2acb499e-8428-543b-bd85-0d9098718220"}]}}},"RawChunk":{"properties":{"text":{"type":"string","title":"Text"}},"type":"object","required":["text"],"title":"RawChunk"},"ResultsWrapper_AddUserResponse_":{"properties":{"results":{"$ref":"#/components/schemas/AddUserResponse"}},"type":"object","required":["results"],"title":"ResultsWrapper[AddUserResponse]"},"ResultsWrapper_AllPromptsResponse_":{"properties":{"results":{"$ref":"#/components/schemas/AllPromptsResponse"}},"type":"object","required":["results"],"title":"ResultsWrapper[AllPromptsResponse]"},"ResultsWrapper_AnalyticsResponse_":{"properties":{"results":{"$ref":"#/components/schemas/AnalyticsResponse"}},"type":"object","required":["results"],"title":"ResultsWrapper[AnalyticsResponse]"},"ResultsWrapper_AppSettingsResponse_":{"properties":{"results":{"$ref":"#/components/schemas/AppSettingsResponse"}},"type":"object","required":["results"],"title":"ResultsWrapper[AppSettingsResponse]"},"ResultsWrapper_CollectionResponse_":{"properties":{"results":{"$ref":"#/components/schemas/CollectionResponse"}},"type":"object","required":["results"],"title":"ResultsWrapper[CollectionResponse]"},"ResultsWrapper_GenericMessageResponse_":{"properties":{"results":{"$ref":"#/components/schemas/GenericMessageResponse"}},"type":"object","required":["results"],"title":"ResultsWrapper[GenericMessageResponse]"},"ResultsWrapper_NoneType_":{"properties":{"results":{"type":"null","title":"Results"}},"type":"object","required":["results"],"title":"ResultsWrapper[NoneType]"},"ResultsWrapper_RAGAgentResponse_":{"properties":{"results":{"$ref":"#/components/schemas/RAGAgentResponse"}},"type":"object","required":["results"],"title":"ResultsWrapper[RAGAgentResponse]"},"ResultsWrapper_RAGResponse_":{"properties":{"results":{"$ref":"#/components/schemas/RAGResponse"}},"type":"object","required":["results"],"title":"ResultsWrapper[RAGResponse]"},"ResultsWrapper_ScoreCompletionResponse_":{"properties":{"results":{"$ref":"#/components/schemas/ScoreCompletionResponse"}},"type":"object","required":["results"],"title":"ResultsWrapper[ScoreCompletionResponse]"},"ResultsWrapper_SearchResponse_":{"properties":{"results":{"$ref":"#/components/schemas/SearchResponse"}},"type":"object","required":["results"],"title":"ResultsWrapper[SearchResponse]"},"ResultsWrapper_ServerStats_":{"properties":{"results":{"$ref":"#/components/schemas/ServerStats"}},"type":"object","required":["results"],"title":"ResultsWrapper[ServerStats]"},"ResultsWrapper_TokenResponse_":{"properties":{"results":{"$ref":"#/components/schemas/TokenResponse"}},"type":"object","required":["results"],"title":"ResultsWrapper[TokenResponse]"},"ResultsWrapper_Union_KGCreationResponse__KGCreationEstimationResponse__":{"properties":{"results":{"anyOf":[{"$ref":"#/components/schemas/KGCreationResponse"},{"$ref":"#/components/schemas/KGCreationEstimationResponse"}],"title":"Results"}},"type":"object","required":["results"],"title":"ResultsWrapper[Union[KGCreationResponse, KGCreationEstimationResponse]]"},"ResultsWrapper_Union_KGEnrichmentResponse__KGEnrichmentEstimationResponse__":{"properties":{"results":{"anyOf":[{"$ref":"#/components/schemas/KGEnrichmentResponse"},{"$ref":"#/components/schemas/KGEnrichmentEstimationResponse"}],"title":"Results"}},"type":"object","required":["results"],"title":"ResultsWrapper[Union[KGEnrichmentResponse, KGEnrichmentEstimationResponse]]"},"ResultsWrapper_UpdatePromptResponse_":{"properties":{"results":{"$ref":"#/components/schemas/UpdatePromptResponse"}},"type":"object","required":["results"],"title":"ResultsWrapper[UpdatePromptResponse]"},"ResultsWrapper_UpdateResponse_":{"properties":{"results":{"$ref":"#/components/schemas/UpdateResponse"}},"type":"object","required":["results"],"title":"ResultsWrapper[UpdateResponse]"},"ResultsWrapper_UserResponse_":{"properties":{"results":{"$ref":"#/components/schemas/shared__api__models__auth__responses__UserResponse"}},"type":"object","required":["results"],"title":"ResultsWrapper[UserResponse]"},"ResultsWrapper_list_CollectionOverviewResponse__":{"properties":{"results":{"items":{"$ref":"#/components/schemas/CollectionOverviewResponse"},"type":"array","title":"Results"}},"type":"object","required":["results"],"title":"ResultsWrapper[list[CollectionOverviewResponse]]"},"ResultsWrapper_list_CollectionResponse__":{"properties":{"results":{"items":{"$ref":"#/components/schemas/CollectionResponse"},"type":"array","title":"Results"}},"type":"object","required":["results"],"title":"ResultsWrapper[list[CollectionResponse]]"},"ResultsWrapper_list_IngestionResponse__":{"properties":{"results":{"items":{"$ref":"#/components/schemas/IngestionResponse"},"type":"array","title":"Results"}},"type":"object","required":["results"],"title":"ResultsWrapper[list[IngestionResponse]]"},"ResultsWrapper_list_LogResponse__":{"properties":{"results":{"items":{"$ref":"#/components/schemas/LogResponse"},"type":"array","title":"Results"}},"type":"object","required":["results"],"title":"ResultsWrapper[list[LogResponse]]"},"ScoreCompletionResponse":{"properties":{"message":{"type":"string","title":"Message"}},"type":"object","required":["message"],"title":"ScoreCompletionResponse"},"SearchResponse":{"properties":{"vector_search_results":{"items":{"$ref":"#/components/schemas/VectorSearchResult"},"type":"array","title":"Vector Search Results","description":"List of vector search results"},"kg_search_results":{"anyOf":[{"items":{"$ref":"#/components/schemas/KGSearchResult"},"type":"array"},{"type":"null"}],"title":"Kg Search Results","description":"Knowledge graph search results, if applicable"}},"type":"object","required":["vector_search_results"],"title":"SearchResponse","example":{"kg_search_results":[{"content":{"description":"Entity Description","metadata":{},"name":"Entity Name"},"extraction_ids":["c68dc72e-fc23-5452-8f49-d7bd46088a96"],"metadata":{"associated_query":"What is the capital of France?"},"method":"local","result_type":"entity"}],"vector_search_results":[{"collection_ids":[],"document_id":"3e157b3a-8469-51db-90d9-52e7d896b49b","extraction_id":"3f3d47f3-8baf-58eb-8bc2-0171fb1c6e09","metadata":{"associated_query":"What is the capital of France?","title":"example_document.pdf"},"score":0.23943702876567796,"text":"Example text from the document","user_id":"2acb499e-8428-543b-bd85-0d9098718220"}]}},"ServerStats":{"properties":{"start_time":{"type":"string","format":"date-time","title":"Start Time"},"uptime_seconds":{"type":"number","title":"Uptime Seconds"},"cpu_usage":{"type":"number","title":"Cpu Usage"},"memory_usage":{"type":"number","title":"Memory Usage"}},"type":"object","required":["start_time","uptime_seconds","cpu_usage","memory_usage"],"title":"ServerStats"},"Token":{"properties":{"token":{"type":"string","title":"Token"},"token_type":{"type":"string","title":"Token Type"}},"type":"object","required":["token","token_type"],"title":"Token"},"TokenResponse":{"properties":{"access_token":{"$ref":"#/components/schemas/Token"},"refresh_token":{"$ref":"#/components/schemas/Token"}},"type":"object","required":["access_token","refresh_token"],"title":"TokenResponse"},"UpdatePromptResponse":{"properties":{"message":{"type":"string","title":"Message"}},"type":"object","required":["message"],"title":"UpdatePromptResponse"},"UpdateResponse":{"properties":{"message":{"type":"string","title":"Message","description":"A message describing the result of the ingestion request."},"task_id":{"type":"string","format":"uuid","title":"Task Id","description":"The task ID of the ingestion request."},"document_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Document Ids","description":"The ID of the document that was ingested."}},"type":"object","required":["message","task_id","document_ids"],"title":"UpdateResponse","example":{"document_ids":["9fbe403b-c11c-5aae-8ade-ef22980c3ad1"],"message":"Update task queued successfully.","task_id":"c68dc72e-fc23-5452-8f49-d7bd46088a96"}},"UserOverviewResponse":{"properties":{"user_id":{"type":"string","format":"uuid","title":"User Id"},"num_files":{"type":"integer","title":"Num Files"},"total_size_in_bytes":{"type":"integer","title":"Total Size In Bytes"},"document_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Document Ids"}},"type":"object","required":["user_id","num_files","total_size_in_bytes","document_ids"],"title":"UserOverviewResponse"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"VectorSearchResult":{"properties":{"extraction_id":{"type":"string","format":"uuid","title":"Extraction Id"},"document_id":{"type":"string","format":"uuid","title":"Document Id"},"user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"User Id"},"collection_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Collection Ids"},"score":{"type":"number","title":"Score"},"text":{"type":"string","title":"Text"},"metadata":{"type":"object","title":"Metadata"}},"type":"object","required":["extraction_id","document_id","user_id","collection_ids","score","text","metadata"],"title":"VectorSearchResult","description":"Result of a search operation.","collection_ids":[],"document_id":"3e157b3a-8469-51db-90d9-52e7d896b49b","extraction_id":"3f3d47f3-8baf-58eb-8bc2-0171fb1c6e09","metadata":{"associated_query":"What is the capital of France?","title":"example_document.pdf"},"score":0.23943702876567796,"text":"Example text from the document","user_id":"2acb499e-8428-543b-bd85-0d9098718220"},"VectorSearchSettings":{"properties":{"use_vector_search":{"type":"boolean","title":"Use Vector Search","description":"Whether to use vector search","default":true},"use_hybrid_search":{"type":"boolean","title":"Use Hybrid Search","description":"Whether to perform a hybrid search (combining vector and keyword search)","default":false},"filters":{"type":"object","title":"Filters","description":"Filters to apply to the vector search"},"search_limit":{"type":"integer","maximum":1000.0,"minimum":1.0,"title":"Search Limit","description":"Maximum number of results to return","default":10},"offset":{"type":"integer","minimum":0.0,"title":"Offset","description":"Offset to paginate search results","default":0},"selected_collection_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Selected Collection Ids","description":"Collection IDs to search for"},"index_measure":{"$ref":"#/components/schemas/IndexMeasure","description":"The distance measure to use for indexing","default":"cosine_distance"},"include_values":{"type":"boolean","title":"Include Values","description":"Whether to include search score values in the search results","default":true},"include_metadatas":{"type":"boolean","title":"Include Metadatas","description":"Whether to include element metadata in the search results","default":true},"probes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Probes","description":"Number of ivfflat index lists to query. Higher increases accuracy but decreases speed.","default":10},"ef_search":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Ef Search","description":"Size of the dynamic candidate list for HNSW index search. Higher increases accuracy but decreases speed.","default":40},"hybrid_search_settings":{"anyOf":[{"$ref":"#/components/schemas/HybridSearchSettings"},{"type":"null"}],"description":"Settings for hybrid search","default":{"full_text_weight":1.0,"semantic_weight":5.0,"full_text_limit":200,"rrf_k":50}},"search_strategy":{"type":"string","title":"Search Strategy","description":"Search strategy to use (e.g., 'default', 'query_fusion', 'hyde')","default":"vanilla"}},"type":"object","title":"VectorSearchSettings","ef_search":40,"filters":{"category":"technology"},"hybrid_search_settings":{"full_text_limit":200,"full_text_weight":1.0,"rrf_k":50,"semantic_weight":5.0},"include_metadata":true,"index_measure":"cosine_distance","limit":20,"offset":0,"probes":10,"selected_collection_ids":["2acb499e-8428-543b-bd85-0d9098718220","3e157b3a-8469-51db-90d9-52e7d896b49b"],"use_hybrid_search":true,"use_vector_search":true},"shared__api__models__auth__responses__UserResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"email":{"type":"string","title":"Email"},"is_active":{"type":"boolean","title":"Is Active","default":true},"is_superuser":{"type":"boolean","title":"Is Superuser","default":false},"created_at":{"type":"string","format":"date-time","title":"Created At","default":"2024-10-04T21:51:35.256442"},"updated_at":{"type":"string","format":"date-time","title":"Updated At","default":"2024-10-04T21:51:35.256446"},"is_verified":{"type":"boolean","title":"Is Verified","default":false},"collection_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Collection Ids","default":[]},"hashed_password":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hashed Password"},"verification_code_expiry":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Verification Code Expiry"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"bio":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bio"},"profile_picture":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Profile Picture"}},"type":"object","required":["id","email"],"title":"UserResponse"},"shared__api__models__management__responses__UserResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"email":{"type":"string","title":"Email"},"is_active":{"type":"boolean","title":"Is Active","default":true},"is_superuser":{"type":"boolean","title":"Is Superuser","default":false},"created_at":{"type":"string","format":"date-time","title":"Created At","default":"2024-10-04T21:51:35.268663"},"updated_at":{"type":"string","format":"date-time","title":"Updated At","default":"2024-10-04T21:51:35.268667"},"is_verified":{"type":"boolean","title":"Is Verified","default":false},"collection_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Collection Ids","default":[]},"hashed_password":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hashed Password"},"verification_code_expiry":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Verification Code Expiry"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"bio":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bio"},"profile_picture":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Profile Picture"}},"type":"object","required":["id","email"],"title":"UserResponse"}},"securitySchemes":{"HTTPBearer":{"type":"http","scheme":"bearer"},"OAuth2PasswordBearer":{"type":"oauth2","flows":{"password":{"scopes":{},"tokenUrl":"token"}}}}}} diff --git a/py/core/main/api/ingestion_router.py b/py/core/main/api/ingestion_router.py index 1e6775708..4934a04e2 100644 --- a/py/core/main/api/ingestion_router.py +++ b/py/core/main/api/ingestion_router.py @@ -92,8 +92,7 @@ async def ingest_files_app( description=ingest_files_descriptions.get("ingestion_config"), ), auth_user=Depends(self.service.providers.auth.auth_wrapper), - response_model=WrappedIngestionResponse, - ): + ) -> WrappedIngestionResponse: # type: ignore """ Ingest files into the system. @@ -189,8 +188,7 @@ async def update_files_app( description=ingest_files_descriptions.get("ingestion_config"), ), auth_user=Depends(self.service.providers.auth.auth_wrapper), - response_model=WrappedUpdateResponse, - ): + ) -> WrappedUpdateResponse: # type: ignore """ Update existing files in the system. @@ -280,8 +278,7 @@ async def ingest_chunks_app( None, description=ingest_files_descriptions.get("metadata") ), auth_user=Depends(self.service.providers.auth.auth_wrapper), - response_model=WrappedIngestionResponse, - ): + ) -> WrappedIngestionResponse: # type: ignore """ Ingest text chunks into the system. diff --git a/py/core/main/api/kg_router.py b/py/core/main/api/kg_router.py index 1112a30b0..4e872a0c3 100644 --- a/py/core/main/api/kg_router.py +++ b/py/core/main/api/kg_router.py @@ -72,7 +72,7 @@ async def create_graph( description="Settings for the graph creation process.", ), auth_user=Depends(self.service.providers.auth.auth_wrapper), - ) -> WrappedKGCreationResponse: + ) -> WrappedKGCreationResponse: # type: ignore """ Creating a graph on your documents. This endpoint takes input a list of document ids and KGCreationSettings. If document IDs are not provided, the graph will be created on all documents in the system. This step extracts the relevant entities and relationships from the documents and creates a graph based on the extracted information. diff --git a/py/core/main/api/retrieval_router.py b/py/core/main/api/retrieval_router.py index 6528b5616..84f0a5bf0 100644 --- a/py/core/main/api/retrieval_router.py +++ b/py/core/main/api/retrieval_router.py @@ -112,7 +112,7 @@ async def search_app( description=search_descriptions.get("kg_search_settings"), ), auth_user=Depends(self.service.providers.auth.auth_wrapper), - ) -> WrappedSearchResponse: + ) -> WrappedSearchResponse: # type: ignore """ Perform a search query on the vector database and knowledge graph. @@ -168,7 +168,7 @@ async def rag_app( description=rag_descriptions.get("include_title_if_available"), ), auth_user=Depends(self.service.providers.auth.auth_wrapper), - ) -> WrappedRAGResponse: + ) -> WrappedRAGResponse: # type: ignore """ Execute a RAG (Retrieval-Augmented Generation) query. @@ -240,7 +240,7 @@ async def agent_app( ), ), auth_user=Depends(self.service.providers.auth.auth_wrapper), - ) -> WrappedRAGAgentResponse: + ) -> WrappedRAGAgentResponse: # type: ignore """ Implement an agent-based interaction for complex query processing. diff --git a/py/core/main/orchestration/hatchet/kg_workflow.py b/py/core/main/orchestration/hatchet/kg_workflow.py index 644ae1a85..0586f3787 100644 --- a/py/core/main/orchestration/hatchet/kg_workflow.py +++ b/py/core/main/orchestration/hatchet/kg_workflow.py @@ -4,7 +4,7 @@ import math import uuid -from hatchet_sdk import Context, ConcurrencyLimitStrategy +from hatchet_sdk import ConcurrencyLimitStrategy, Context from core import GenerationConfig from core.base import OrchestrationProvider @@ -41,8 +41,8 @@ class KGExtractDescribeEmbedWorkflow: def __init__(self, kg_service: KgService): self.kg_service = kg_service - @orchestration_provider.concurrency( - max_runs=orchestration_provider.config.kg_creation_concurrency_limit, + @orchestration_provider.concurrency( # type: ignore + max_runs=orchestration_provider.config.kg_creation_concurrency_limit, # type: ignore limit_strategy=ConcurrencyLimitStrategy.GROUP_ROUND_ROBIN, ) def concurrency(self, context) -> str: diff --git a/py/tests/conftest.py b/py/tests/conftest.py index 5f24fc95d..12d0418a6 100644 --- a/py/tests/conftest.py +++ b/py/tests/conftest.py @@ -60,6 +60,7 @@ def generate_random_vector_entry( generate_random_vector_entry(i, dimension) for i in range(num_entries) ] + @pytest.fixture(scope="function") def app_config(): collection_id = uuid.uuid4() @@ -68,6 +69,7 @@ def app_config(): return AppConfig(project_name=random_project_name) + # Crypto @pytest.fixture(scope="function") def crypto_config(app_config): @@ -82,9 +84,7 @@ def crypto_provider(crypto_config, app_config): # Postgres @pytest.fixture(scope="function") def db_config(app_config): - return DatabaseConfig.create( - provider="postgres", app=app_config - ) + return DatabaseConfig.create(provider="postgres", app=app_config) @pytest.fixture(scope="function") @@ -138,7 +138,7 @@ def auth_config(app_config): access_token_lifetime_in_minutes=15, refresh_token_lifetime_in_days=1, require_email_verification=False, - app=app_config + app=app_config, ) @@ -160,7 +160,7 @@ def litellm_provider(app_config): provider="litellm", base_model="text-embedding-3-small", base_dimension=1536, - app=app_config + app=app_config, ) return LiteLLMEmbeddingProvider(config) diff --git a/py/tests/core/providers/embedding/conftest.py b/py/tests/core/providers/embedding/conftest.py index 75e67a124..5945a0b52 100644 --- a/py/tests/core/providers/embedding/conftest.py +++ b/py/tests/core/providers/embedding/conftest.py @@ -25,7 +25,7 @@ def openai_provider(app_config): provider="openai", base_model="text-embedding-ada-002", base_dimension=1536, - app=app_config + app=app_config, ) return OpenAIEmbeddingProvider(config) @@ -36,6 +36,6 @@ def ollama_provider(app_config): provider="ollama", base_model="mxbai-embed-large", base_dimension=1024, - app=app_config + app=app_config, ) return OllamaEmbeddingProvider(config) diff --git a/py/tests/core/providers/embedding/test_litellm_embedding_provider.py b/py/tests/core/providers/embedding/test_litellm_embedding_provider.py index e66eaf36c..508e080f7 100644 --- a/py/tests/core/providers/embedding/test_litellm_embedding_provider.py +++ b/py/tests/core/providers/embedding/test_litellm_embedding_provider.py @@ -26,7 +26,7 @@ def litellm_provider(app_config): provider="litellm", base_model="openai/text-embedding-3-small", base_dimension=1536, - app=app_config + app=app_config, ) return LiteLLMEmbeddingProvider(config) @@ -80,7 +80,7 @@ def test_litellm_rerank_model_not_supported(app_config): base_model="openai/text-embedding-3-small", base_dimension=1536, rerank_model="some-model", - app=app_config + app=app_config, ) with pytest.raises( ValueError, match="does not support separate reranking" @@ -93,7 +93,7 @@ def test_litellm_unsupported_stage(app_config): provider="litellm", base_model="openai/text-embedding-3-small", base_dimension=1536, - app=app_config + app=app_config, ) provider = LiteLLMEmbeddingProvider(config) with pytest.raises( @@ -110,7 +110,7 @@ async def test_litellm_async_unsupported_stage(app_config): provider="litellm", base_model="openai/text-embedding-3-small", base_dimension=1536, - app=app_config + app=app_config, ) provider = LiteLLMEmbeddingProvider(config) with pytest.raises( From 453623d642372921ffb104fd33d900276fb2dd53 Mon Sep 17 00:00:00 2001 From: emrgnt-cmplxty Date: Fri, 4 Oct 2024 15:23:52 -0700 Subject: [PATCH 16/30] fix integration suite --- .../integration-test-workflow-debian.yml | 5 +- py/core/base/api/models/__init__.py | 2 +- py/core/base/providers/kg.py | 4 +- py/core/main/api/ingestion_router.py | 19 ++--- py/core/providers/kg/postgres.py | 8 +- py/shared/api/models/ingestion/responses.py | 4 +- py/tests/integration/runner.py | 77 ++++++++++++++----- 7 files changed, 79 insertions(+), 40 deletions(-) diff --git a/.github/workflows/integration-test-workflow-debian.yml b/.github/workflows/integration-test-workflow-debian.yml index 3c8dfcacd..ba49fac7b 100644 --- a/.github/workflows/integration-test-workflow-debian.yml +++ b/.github/workflows/integration-test-workflow-debian.yml @@ -78,8 +78,9 @@ jobs: - name: Run integration tests - Ingestion working-directory: ./py run: | - poetry run python tests/integration/runner.py test_ingest_sample_files_cli - poetry run python tests/integration/runner.py test_document_ingestion_cli + poetry run python tests/integration/runner.py test_ingest_sample_file_cli + poetry run python tests/integration/runner.py test_document_overview_sample_file_cli + poetry run python tests/integration/runner.py test_vector_search_sample_file_filter_cli - name: Stop R2R server if: always() diff --git a/py/core/base/api/models/__init__.py b/py/core/base/api/models/__init__.py index aaa20db8c..8f5671a0b 100644 --- a/py/core/base/api/models/__init__.py +++ b/py/core/base/api/models/__init__.py @@ -53,10 +53,10 @@ RAGAgentResponse, RAGResponse, SearchResponse, + WrappedCompletionResponse, WrappedRAGAgentResponse, WrappedRAGResponse, WrappedSearchResponse, - WrappedCompletionResponse, ) __all__ = [ diff --git a/py/core/base/providers/kg.py b/py/core/base/providers/kg.py index ae0febacc..639a39b13 100644 --- a/py/core/base/providers/kg.py +++ b/py/core/base/providers/kg.py @@ -89,7 +89,7 @@ async def get_entities( limit: int, entity_ids: list[str] | None = None, with_description: bool = False, - ) -> list[Entity]: + ) -> dict: """Abstract method to get entities.""" pass @@ -100,7 +100,7 @@ async def get_triples( offset: int, limit: int, triple_ids: list[str] | None = None, - ) -> list[Triple]: + ) -> dict: """Abstract method to get triples.""" pass diff --git a/py/core/main/api/ingestion_router.py b/py/core/main/api/ingestion_router.py index 4934a04e2..e4bc40c60 100644 --- a/py/core/main/api/ingestion_router.py +++ b/py/core/main/api/ingestion_router.py @@ -2,7 +2,7 @@ import logging from io import BytesIO from pathlib import Path -from typing import Optional +from typing import Optional, Union from uuid import UUID import yaml @@ -118,7 +118,7 @@ async def ingest_files_app( file_datas = await self._process_files(files) - messages = [] + messages: list[dict[str, Union[str, None]]] = [] for it, file_data in enumerate(file_datas): content_length = len(file_data["content"]) file_content = BytesIO(base64.b64decode(file_data["content"])) @@ -149,7 +149,7 @@ async def ingest_files_app( file_content, file_data["content_type"], ) - raw_message = await self.orchestration_provider.run_workflow( + raw_message: dict[str, Union[str, None]] = await self.orchestration_provider.run_workflow( # type: ignore "ingest-files", {"request": workflow_input}, options={ @@ -159,9 +159,10 @@ async def ingest_files_app( }, ) raw_message["document_id"] = str(document_id) + if "task_id" not in raw_message: + raw_message["task_id"] = None messages.append(raw_message) - - return messages + return messages # type: ignore update_files_extras = self.openapi_extras.get("update_files", {}) update_files_descriptions = update_files_extras.get( @@ -188,7 +189,7 @@ async def update_files_app( description=ingest_files_descriptions.get("ingestion_config"), ), auth_user=Depends(self.service.providers.auth.auth_wrapper), - ) -> WrappedUpdateResponse: # type: ignore + ) -> WrappedUpdateResponse: """ Update existing files in the system. @@ -255,7 +256,7 @@ async def update_files_app( ) raw_message["message"] = "Update task queued successfully." raw_message["document_ids"] = workflow_input["document_ids"] - return raw_message + return raw_message # type: ignore ingest_chunks_extras = self.openapi_extras.get("ingest_chunks", {}) ingest_chunks_descriptions = ingest_chunks_extras.get( @@ -278,7 +279,7 @@ async def ingest_chunks_app( None, description=ingest_files_descriptions.get("metadata") ), auth_user=Depends(self.service.providers.auth.auth_wrapper), - ) -> WrappedIngestionResponse: # type: ignore + ) -> WrappedIngestionResponse: """ Ingest text chunks into the system. @@ -308,7 +309,7 @@ async def ingest_chunks_app( }, ) raw_message["document_id"] = str(document_id) - return raw_message + return raw_message # type: ignore @staticmethod def _validate_ingestion_config(ingestion_config): diff --git a/py/core/providers/kg/postgres.py b/py/core/providers/kg/postgres.py index ece2b4aae..9cefe4452 100644 --- a/py/core/providers/kg/postgres.py +++ b/py/core/providers/kg/postgres.py @@ -16,11 +16,7 @@ KGProvider, Triple, ) -from shared.abstractions import ( - KGCreationSettings, - KGEnrichmentSettings, - KGRunType, -) +from shared.abstractions import KGCreationSettings, KGEnrichmentSettings from shared.api.models.kg.responses import ( KGCreationEstimationResponse, KGEnrichmentEstimationResponse, @@ -923,7 +919,7 @@ async def get_entities( with_description: bool = False, ) -> dict: conditions = [] - params = [collection_id] + params: list = [collection_id] if entity_ids: conditions.append(f"id = ANY(${len(params) + 1})") diff --git a/py/shared/api/models/ingestion/responses.py b/py/shared/api/models/ingestion/responses.py index 7771d3c4c..1ded10865 100644 --- a/py/shared/api/models/ingestion/responses.py +++ b/py/shared/api/models/ingestion/responses.py @@ -1,4 +1,4 @@ -from typing import TypeVar +from typing import Optional, TypeVar from uuid import UUID from pydantic import BaseModel, Field @@ -13,7 +13,7 @@ class IngestionResponse(BaseModel): ..., description="A message describing the result of the ingestion request.", ) - task_id: UUID = Field( + task_id: Optional[UUID] = Field( ..., description="The task ID of the ingestion request.", ) diff --git a/py/tests/integration/runner.py b/py/tests/integration/runner.py index 350335479..21bddb4d2 100644 --- a/py/tests/integration/runner.py +++ b/py/tests/integration/runner.py @@ -16,46 +16,87 @@ def run_command(command): return result.stdout -def test_ingest_sample_files_cli(): - print("Testing: Ingest sample files") - run_command("poetry run r2r ingest-sample-files") +def test_ingest_sample_file_cli(): + print("Testing: Ingest sample file CLI") + run_command("poetry run r2r ingest-sample-file") print("Ingestion successful") -def test_document_ingestion_cli(): - print("Testing: Document ingestion") +def test_document_overview_sample_file_cli(): + print("Testing: Document overview contains 'aristotle.txt'") output = run_command("poetry run r2r documents-overview") - documents = json.loads(output) + output = output.replace("'", '"') + output_lines = output.strip().split('\n')[1:] + documents = [json.loads(ele) for ele in output_lines] - expected_document = { - "id": "9fbe403b-c11c-5aae-8ade-ef22980c3ad1", + aristotle_document = { "title": "aristotle.txt", "type": "txt", "ingestion_status": "success", - "kg_extraction_status": "success", + "kg_extraction_status": "pending", "version": "v0", "metadata": {"title": "aristotle.txt", "version": "v0"}, } + # Check if any document in the overview matches the Aristotle document if not any( - all(doc.get(k) == v for k, v in expected_document.items()) + all(doc.get(k) == v for k, v in aristotle_document.items()) for doc in documents ): - print("Document ingestion test failed") - print(f"Expected document not found in output: {output}") + print("Document overview test failed") + print("Aristotle document not found in the overview") sys.exit(1) - print("Document ingestion test passed") + print("Document overview test passed") - -def test_vector_search_cli(): +def test_vector_search_sample_file_filter_cli(): print("Testing: Vector search") output = run_command( - "poetry run r2r search --query='What was Uber's profit in 2020?'" + """poetry run r2r search --query="Who was aristotle?" """ ) - results = json.loads(output) - if not results.get("results"): + # Split the output into lines and remove the first and last lines + output_lines = output.strip().split('\n')[1:-1] + # Replace single quotes with double quotes in each line + cleaned_output_lines = [line.replace("'", '"') for line in output_lines] + results = [] + for line in cleaned_output_lines: + try: + result = json.loads(line) + results.append(result) + # Skip lines that are not valid JSON b/c of the single quote replacement + except json.JSONDecodeError: + continue + + if not results: print("Vector search test failed: No results returned") sys.exit(1) + + expected_lead_search_result = { + "extraction_id": "ff8accdb-791e-5b6d-a83a-5adc32c4222c", + "document_id": "9fbe403b-c11c-5aae-8ade-ef22980c3ad1", + "user_id": "2acb499e-8428-543b-bd85-0d9098718220", + "score": 0.7820796370506287, + "text": """Aristotle[A] (Greek: Ἀριστοτέλης Aristotélēs, pronounced [aristotélɛːs]; 384–322 BC) was an Ancient Greek philosopher and polymath. His writings cover a broad range of subjects spanning the natural sciences, philosophy, linguistics, economics, politics, psychology, and the arts. As the founder of the Peripatetic school of philosophy in the Lyceum in Athens, he began the wider Aristotelian tradition that followed, which set the groundwork for the development of modern science.""" + } + lead_result = results[0] + + if lead_result['text'] != expected_lead_search_result['text']: + print('Vector search test failed: Incorrect search result text') + print('Expected lead search text:', expected_lead_search_result['text']) + print('Actual lead search text:', lead_result['text']) + sys.exit(1) + + if lead_result['extraction_id'] != expected_lead_search_result['extraction_id']: + print("Vector search test failed: Incorrect extraction_id") + print('Expected extraction_id:', expected_lead_search_result['extraction_id']) + print('Actual extraction_id:', lead_result['extraction_id']) + sys.exit(1) + + if lead_result['document_id'] != expected_lead_search_result['document_id']: + print("Vector search test failed: Incorrect document_id") + print('Expected document_id:', expected_lead_search_result['document_id']) + print('Actual document_id:', lead_result['document_id']) + sys.exit(1) + print("Vector search test passed") From b44ce40e1fd16598ab40575b2b270c9483625c56 Mon Sep 17 00:00:00 2001 From: emrgnt-cmplxty Date: Fri, 4 Oct 2024 15:44:07 -0700 Subject: [PATCH 17/30] fix integration suite --- .../integration-test-workflow-debian.yml | 2 +- py/tests/integration/runner.py | 92 +++++++++++++------ 2 files changed, 64 insertions(+), 30 deletions(-) diff --git a/.github/workflows/integration-test-workflow-debian.yml b/.github/workflows/integration-test-workflow-debian.yml index ba49fac7b..5b0fb65e9 100644 --- a/.github/workflows/integration-test-workflow-debian.yml +++ b/.github/workflows/integration-test-workflow-debian.yml @@ -84,7 +84,7 @@ jobs: - name: Stop R2R server if: always() - run: pkill -f "r2r serve" + run: ps aux | grep "r2r serve" | awk '{print $2}' | xargs kill || true - name: Uninstall PostgreSQL after tests (Optional) if: always() diff --git a/py/tests/integration/runner.py b/py/tests/integration/runner.py index 21bddb4d2..5ee890fbe 100644 --- a/py/tests/integration/runner.py +++ b/py/tests/integration/runner.py @@ -4,6 +4,20 @@ import subprocess import sys +def compare_result_fields(result, expected_fields): + for field, expected_value in expected_fields.items(): + if callable(expected_value): + if not expected_value(result[field]): + print(f"Test failed: Incorrect {field}") + print(f"Expected {field} to satisfy the condition") + print(f"Actual {field}:", result[field]) + sys.exit(1) + else: + if result[field] != expected_value: + print(f"Test failed: Incorrect {field}") + print(f"Expected {field}:", expected_value) + print(f"Actual {field}:", result[field]) + sys.exit(1) def run_command(command): result = subprocess.run( @@ -20,6 +34,7 @@ def test_ingest_sample_file_cli(): print("Testing: Ingest sample file CLI") run_command("poetry run r2r ingest-sample-file") print("Ingestion successful") + print("~" * 100) def test_document_overview_sample_file_cli(): @@ -47,22 +62,20 @@ def test_document_overview_sample_file_cli(): print("Aristotle document not found in the overview") sys.exit(1) print("Document overview test passed") + print("~" * 100) def test_vector_search_sample_file_filter_cli(): print("Testing: Vector search") output = run_command( - """poetry run r2r search --query="Who was aristotle?" """ + """poetry run r2r search --query="Who was aristotle?" --filters='{"document_id": {"$eq": "9fbe403b-c11c-5aae-8ade-ef22980c3ad1"}}'""" ) - # Split the output into lines and remove the first and last lines output_lines = output.strip().split('\n')[1:-1] - # Replace single quotes with double quotes in each line cleaned_output_lines = [line.replace("'", '"') for line in output_lines] results = [] for line in cleaned_output_lines: try: result = json.loads(line) results.append(result) - # Skip lines that are not valid JSON b/c of the single quote replacement except json.JSONDecodeError: continue @@ -70,46 +83,67 @@ def test_vector_search_sample_file_filter_cli(): print("Vector search test failed: No results returned") sys.exit(1) + lead_result = results[0] expected_lead_search_result = { + "text": "Aristotle[A] (Greek: Ἀριστοτέλης Aristotélēs, pronounced [aristotélɛːs]; 384–322 BC) was an Ancient Greek philosopher and polymath. His writings cover a broad range of subjects spanning the natural sciences, philosophy, linguistics, economics, politics, psychology, and the arts. As the founder of the Peripatetic school of philosophy in the Lyceum in Athens, he began the wider Aristotelian tradition that followed, which set the groundwork for the development of modern science.", "extraction_id": "ff8accdb-791e-5b6d-a83a-5adc32c4222c", - "document_id": "9fbe403b-c11c-5aae-8ade-ef22980c3ad1", + "document_id": "9fbe403b-c11c-5aae-8ade-ef22980c3ad1", "user_id": "2acb499e-8428-543b-bd85-0d9098718220", - "score": 0.7820796370506287, - "text": """Aristotle[A] (Greek: Ἀριστοτέλης Aristotélēs, pronounced [aristotélɛːs]; 384–322 BC) was an Ancient Greek philosopher and polymath. His writings cover a broad range of subjects spanning the natural sciences, philosophy, linguistics, economics, politics, psychology, and the arts. As the founder of the Peripatetic school of philosophy in the Lyceum in Athens, he began the wider Aristotelian tradition that followed, which set the groundwork for the development of modern science.""" + "score": lambda x: 0.77 <= x <= 0.79 } - lead_result = results[0] + compare_result_fields(lead_result, expected_lead_search_result) - if lead_result['text'] != expected_lead_search_result['text']: - print('Vector search test failed: Incorrect search result text') - print('Expected lead search text:', expected_lead_search_result['text']) - print('Actual lead search text:', lead_result['text']) - sys.exit(1) + print("Vector search test passed") - if lead_result['extraction_id'] != expected_lead_search_result['extraction_id']: - print("Vector search test failed: Incorrect extraction_id") - print('Expected extraction_id:', expected_lead_search_result['extraction_id']) - print('Actual extraction_id:', lead_result['extraction_id']) - sys.exit(1) +def test_hybrid_search_sample_file_filter_cli(): + print("Testing: Vector search") + output = run_command( + """poetry run r2r search --query="Who was aristotle?" --use-hybrid-search --filters='{"document_id": {"$eq": "9fbe403b-c11c-5aae-8ade-ef22980c3ad1"}}'""" + ) + output_lines = output.strip().split('\n')[1:-1] + cleaned_output_lines = [line.replace("'", '"') for line in output_lines] + results = [] + for line in cleaned_output_lines: + try: + result = json.loads(line) + results.append(result) + except json.JSONDecodeError: + continue - if lead_result['document_id'] != expected_lead_search_result['document_id']: - print("Vector search test failed: Incorrect document_id") - print('Expected document_id:', expected_lead_search_result['document_id']) - print('Actual document_id:', lead_result['document_id']) + if not results: + print("Vector search test failed: No results returned") sys.exit(1) + + # TODO - Fix loading of CLI result to allow comparison below + # (e.g. lead result does not properly load as a dictionary) + # lead_result = results[0] + # expected_lead_search_result = { + # "text": "Life\nIn general, the details of Aristotle's life are not well-established. The biographies written in ancient times are often speculative and historians only agree on a few salient points.[B]\n\nAristotle was born in 384 BC[C] in Stagira, Chalcidice,[2] about 55 km (34 miles) east of modern-day Thessaloniki.[3][4] His father, Nicomachus, was the personal physician to King Amyntas of Macedon. While he was young, Aristotle learned about biology and medical information, which was taught by his father.[5] Both of Aristotle's parents died when he was about thirteen, and Proxenus of Atarneus became his guardian.[6] Although little information about Aristotle's childhood has survived, he probably spent some time within the Macedonian palace, making his first connections with the Macedonian monarchy.[7]", + # "extraction_id": "f6f5cfb6-8654-5e1c-b574-849a8a313452", + # "document_id": "9fbe403b-c11c-5aae-8ade-ef22980c3ad1", + # "user_id": "2acb499e-8428-543b-bd85-0d9098718220", + # "score": lambda x: 0.016 <= x <= 0.018, + # "full_text_rank": 10, + # "semantic_rank": 5, + # } + # compare_result_fields(lead_result, expected_lead_search_result) print("Vector search test passed") +def test_rag_query_aristotle_birth_year_cli(): + print("Testing: RAG query for Aristotle's birth year") + output = run_command("poetry run r2r rag --query='What year was Aristotle born?'") + # TODO - Can we fix the test to check by loading JSON output? + # response = json.loads(output) -def test_rag_query_cli(): - print("Testing: RAG query") - output = run_command("poetry run r2r rag --query='Who was Aristotle?'") - response = json.loads(output) - if not response.get("answer"): - print("RAG query test failed: No answer returned") + expected_answer = "Aristotle was born in 384 BC" + + if expected_answer not in output: + print(f"RAG query test failed: Expected answer '{expected_answer}' not found in '{output}'") sys.exit(1) + print("RAG query test passed") - if __name__ == "__main__": if len(sys.argv) < 2: print("Please specify a test function to run") From 7d02203a8e9c2679e18759cf36e2fc20f125b7dd Mon Sep 17 00:00:00 2001 From: emrgnt-cmplxty Date: Fri, 4 Oct 2024 15:47:34 -0700 Subject: [PATCH 18/30] fix integration suite --- py/tests/integration/runner.py | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/py/tests/integration/runner.py b/py/tests/integration/runner.py index 5ee890fbe..aaa64c627 100644 --- a/py/tests/integration/runner.py +++ b/py/tests/integration/runner.py @@ -94,6 +94,7 @@ def test_vector_search_sample_file_filter_cli(): compare_result_fields(lead_result, expected_lead_search_result) print("Vector search test passed") + print("~" * 100) def test_hybrid_search_sample_file_filter_cli(): print("Testing: Vector search") @@ -129,8 +130,9 @@ def test_hybrid_search_sample_file_filter_cli(): # compare_result_fields(lead_result, expected_lead_search_result) print("Vector search test passed") + print("~" * 100) -def test_rag_query_aristotle_birth_year_cli(): +def test_rag_response_sample_file_cli(): print("Testing: RAG query for Aristotle's birth year") output = run_command("poetry run r2r rag --query='What year was Aristotle born?'") # TODO - Can we fix the test to check by loading JSON output? @@ -142,7 +144,33 @@ def test_rag_query_aristotle_birth_year_cli(): print(f"RAG query test failed: Expected answer '{expected_answer}' not found in '{output}'") sys.exit(1) - print("RAG query test passed") + print("RAG response test passed") + print("~" * 100) + +def test_rag_response_stream_sample_file_cli(): + print("Testing: Streaming RAG query for who Aristotle was") + + # Run the command and capture the output + # output = run_command("poetry run r2r rag --query='who was aristotle' --use-hybrid-search --stream", capture_output=True) + process = subprocess.Popen( + ["poetry", "run", "r2r", "rag", "--query='who was aristotle'", "--use-hybrid-search", "--stream"], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True + ) + output, _ = process.communicate() + + # Check if the output contains the search and completion tags + if "" not in output or "" not in output: + print("Streaming RAG query test failed: Search results not found in output") + sys.exit(1) + + if "" not in output or "" not in output: + print("Streaming RAG query test failed: Completion not found in output") + sys.exit(1) + + print("RAG response stream test passed") + print("~" * 100) if __name__ == "__main__": if len(sys.argv) < 2: From dfebad3f36c929325292359878aa40345991a40a Mon Sep 17 00:00:00 2001 From: emrgnt-cmplxty Date: Fri, 4 Oct 2024 16:03:57 -0700 Subject: [PATCH 19/30] up --- .../integration-test-workflow-debian.yml | 9 +- py/core/main/api/ingestion_router.py | 2 +- .../integration/{runner.py => harness_cli.py} | 57 +++-- py/tests/integration/harness_sdk.py | 194 ++++++++++++++++++ 4 files changed, 241 insertions(+), 21 deletions(-) rename py/tests/integration/{runner.py => harness_cli.py} (88%) create mode 100644 py/tests/integration/harness_sdk.py diff --git a/.github/workflows/integration-test-workflow-debian.yml b/.github/workflows/integration-test-workflow-debian.yml index 5b0fb65e9..941a675b2 100644 --- a/.github/workflows/integration-test-workflow-debian.yml +++ b/.github/workflows/integration-test-workflow-debian.yml @@ -78,9 +78,12 @@ jobs: - name: Run integration tests - Ingestion working-directory: ./py run: | - poetry run python tests/integration/runner.py test_ingest_sample_file_cli - poetry run python tests/integration/runner.py test_document_overview_sample_file_cli - poetry run python tests/integration/runner.py test_vector_search_sample_file_filter_cli + poetry run python tests/integration/harness_cli.py test_ingest_sample_file_cli + poetry run python tests/integration/harness_cli.py test_document_overview_sample_file_cli + poetry run python tests/integration/harness_cli.py test_vector_search_sample_file_filter_cli + + poetry run python tests/integration/harness_cli.py test_ingest_sample_file_sdk + poetry run python tests/integration/harness_cli.py test_reingest_sample_file_sdk - name: Stop R2R server if: always() diff --git a/py/core/main/api/ingestion_router.py b/py/core/main/api/ingestion_router.py index e4bc40c60..185ec6df0 100644 --- a/py/core/main/api/ingestion_router.py +++ b/py/core/main/api/ingestion_router.py @@ -149,7 +149,7 @@ async def ingest_files_app( file_content, file_data["content_type"], ) - raw_message: dict[str, Union[str, None]] = await self.orchestration_provider.run_workflow( # type: ignore + raw_message: dict[str, Union[str, None]] = await self.orchestration_provider.run_workflow( # type: ignore "ingest-files", {"request": workflow_input}, options={ diff --git a/py/tests/integration/runner.py b/py/tests/integration/harness_cli.py similarity index 88% rename from py/tests/integration/runner.py rename to py/tests/integration/harness_cli.py index aaa64c627..cf176c65f 100644 --- a/py/tests/integration/runner.py +++ b/py/tests/integration/harness_cli.py @@ -4,6 +4,7 @@ import subprocess import sys + def compare_result_fields(result, expected_fields): for field, expected_value in expected_fields.items(): if callable(expected_value): @@ -19,6 +20,7 @@ def compare_result_fields(result, expected_fields): print(f"Actual {field}:", result[field]) sys.exit(1) + def run_command(command): result = subprocess.run( command, shell=True, capture_output=True, text=True @@ -41,7 +43,7 @@ def test_document_overview_sample_file_cli(): print("Testing: Document overview contains 'aristotle.txt'") output = run_command("poetry run r2r documents-overview") output = output.replace("'", '"') - output_lines = output.strip().split('\n')[1:] + output_lines = output.strip().split("\n")[1:] documents = [json.loads(ele) for ele in output_lines] aristotle_document = { @@ -64,12 +66,13 @@ def test_document_overview_sample_file_cli(): print("Document overview test passed") print("~" * 100) + def test_vector_search_sample_file_filter_cli(): print("Testing: Vector search") output = run_command( """poetry run r2r search --query="Who was aristotle?" --filters='{"document_id": {"$eq": "9fbe403b-c11c-5aae-8ade-ef22980c3ad1"}}'""" ) - output_lines = output.strip().split('\n')[1:-1] + output_lines = output.strip().split("\n")[1:-1] cleaned_output_lines = [line.replace("'", '"') for line in output_lines] results = [] for line in cleaned_output_lines: @@ -89,19 +92,20 @@ def test_vector_search_sample_file_filter_cli(): "extraction_id": "ff8accdb-791e-5b6d-a83a-5adc32c4222c", "document_id": "9fbe403b-c11c-5aae-8ade-ef22980c3ad1", "user_id": "2acb499e-8428-543b-bd85-0d9098718220", - "score": lambda x: 0.77 <= x <= 0.79 + "score": lambda x: 0.77 <= x <= 0.79, } compare_result_fields(lead_result, expected_lead_search_result) print("Vector search test passed") print("~" * 100) + def test_hybrid_search_sample_file_filter_cli(): print("Testing: Vector search") output = run_command( """poetry run r2r search --query="Who was aristotle?" --use-hybrid-search --filters='{"document_id": {"$eq": "9fbe403b-c11c-5aae-8ade-ef22980c3ad1"}}'""" ) - output_lines = output.strip().split('\n')[1:-1] + output_lines = output.strip().split("\n")[1:-1] cleaned_output_lines = [line.replace("'", '"') for line in output_lines] results = [] for line in cleaned_output_lines: @@ -114,7 +118,7 @@ def test_hybrid_search_sample_file_filter_cli(): if not results: print("Vector search test failed: No results returned") sys.exit(1) - + # TODO - Fix loading of CLI result to allow comparison below # (e.g. lead result does not properly load as a dictionary) # lead_result = results[0] @@ -132,46 +136,65 @@ def test_hybrid_search_sample_file_filter_cli(): print("Vector search test passed") print("~" * 100) + def test_rag_response_sample_file_cli(): print("Testing: RAG query for Aristotle's birth year") - output = run_command("poetry run r2r rag --query='What year was Aristotle born?'") + output = run_command( + "poetry run r2r rag --query='What year was Aristotle born?'" + ) # TODO - Can we fix the test to check by loading JSON output? # response = json.loads(output) expected_answer = "Aristotle was born in 384 BC" - + if expected_answer not in output: - print(f"RAG query test failed: Expected answer '{expected_answer}' not found in '{output}'") + print( + f"RAG query test failed: Expected answer '{expected_answer}' not found in '{output}'" + ) sys.exit(1) - + print("RAG response test passed") print("~" * 100) + def test_rag_response_stream_sample_file_cli(): print("Testing: Streaming RAG query for who Aristotle was") - + # Run the command and capture the output # output = run_command("poetry run r2r rag --query='who was aristotle' --use-hybrid-search --stream", capture_output=True) process = subprocess.Popen( - ["poetry", "run", "r2r", "rag", "--query='who was aristotle'", "--use-hybrid-search", "--stream"], + [ + "poetry", + "run", + "r2r", + "rag", + "--query='who was aristotle'", + "--use-hybrid-search", + "--stream", + ], stdout=subprocess.PIPE, stderr=subprocess.PIPE, - text=True + text=True, ) - output, _ = process.communicate() - + output, _ = process.communicate() + # Check if the output contains the search and completion tags if "" not in output or "" not in output: - print("Streaming RAG query test failed: Search results not found in output") + print( + "Streaming RAG query test failed: Search results not found in output" + ) sys.exit(1) - + if "" not in output or "" not in output: - print("Streaming RAG query test failed: Completion not found in output") + print( + "Streaming RAG query test failed: Completion not found in output" + ) sys.exit(1) print("RAG response stream test passed") print("~" * 100) + if __name__ == "__main__": if len(sys.argv) < 2: print("Please specify a test function to run") diff --git a/py/tests/integration/harness_sdk.py b/py/tests/integration/harness_sdk.py new file mode 100644 index 000000000..11521d156 --- /dev/null +++ b/py/tests/integration/harness_sdk.py @@ -0,0 +1,194 @@ +import json +import sys + +from r2r import R2RClient + +client = R2RClient() + + +def compare_result_fields(result, expected_fields): + for field, expected_value in expected_fields.items(): + if callable(expected_value): + if not expected_value(result[field]): + print(f"Test failed: Incorrect {field}") + print(f"Expected {field} to satisfy the condition") + print(f"Actual {field}:", result[field]) + sys.exit(1) + else: + if result[field] != expected_value: + print(f"Test failed: Incorrect {field}") + print(f"Expected {field}:", expected_value) + print(f"Actual {field}:", result[field]) + sys.exit(1) + + +def test_ingest_sample_file_sdk(): + print("Testing: Ingest sample file SDK") + file_paths = ["core/examples/data/uber_2021.pdf"] + ingest_response = client.ingest_files(file_paths=file_paths) + + if not ingest_response["results"]: + print("Ingestion test failed") + sys.exit(1) + + print("Ingestion successful") + print("~" * 100) + + +def test_reingest_sample_file_sdk(): + print("Testing: Ingest sample file SDK") + file_paths = ["core/examples/data/uber_2021.pdf"] + try: + reingest_response = client.ingest_files(file_paths=file_paths) + print( + "Re-ingestion test failed: Expected an error but ingestion succeeded" + ) + sys.exit(1) + except Exception as e: + error_message = str(e) + if ( + "Must increment version number before attempting to overwrite document" + not in error_message + ): + print( + f"Re-ingestion test failed: Unexpected error - {error_message}" + ) + sys.exit(1) + else: + print("Re-ingestion failed as expected") + + print("Re-ingestion test passed") + print("~" * 100) + + +def test_document_overview_sample_file_sdk(): + print("Testing: Document overview contains 'uber.txt'") + documents_overview = client.documents_overview() + + aristotle_document = { + "title": "aristotle.txt", + "type": "txt", + "ingestion_status": "success", + "kg_extraction_status": "pending", + "version": "v0", + "metadata": {"title": "aristotle.txt", "version": "v0"}, + } + + if not any( + all(doc.get(k) == v for k, v in aristotle_document.items()) + for doc in documents_overview + ): + print("Document overview test failed") + print("Aristotle document not found in the overview") + sys.exit(1) + print("Document overview test passed") + print("~" * 100) + + +def test_vector_search_sample_file_filter_sdk(): + print("Testing: Vector search") + results = client.search( + query="Who was aristotle?", + filters={ + "document_id": {"$eq": "9fbe403b-c11c-5aae-8ade-ef22980c3ad1"} + }, + ) + + if not results: + print("Vector search test failed: No results returned") + sys.exit(1) + + lead_result = results[0] + expected_lead_search_result = { + "text": "Aristotle[A] (Greek: Ἀριστοτέλης Aristotélēs, pronounced [aristotélɛːs]; 384–322 BC) was an Ancient Greek philosopher and polymath. His writings cover a broad range of subjects spanning the natural sciences, philosophy, linguistics, economics, politics, psychology, and the arts. As the founder of the Peripatetic school of philosophy in the Lyceum in Athens, he began the wider Aristotelian tradition that followed, which set the groundwork for the development of modern science.", + "extraction_id": "ff8accdb-791e-5b6d-a83a-5adc32c4222c", + "document_id": "9fbe403b-c11c-5aae-8ade-ef22980c3ad1", + "user_id": "2acb499e-8428-543b-bd85-0d9098718220", + "score": lambda x: 0.77 <= x <= 0.79, + } + compare_result_fields(lead_result, expected_lead_search_result) + + print("Vector search test passed") + print("~" * 100) + + +def test_hybrid_search_sample_file_filter_sdk(): + print("Testing: Hybrid search") + results = client.search( + query="Who was aristotle?", + vector_search_settings={"use_hybrid_search": True}, + filters={ + "document_id": {"$eq": "9fbe403b-c11c-5aae-8ade-ef22980c3ad1"} + }, + ) + + if not results: + print("Hybrid search test failed: No results returned") + sys.exit(1) + + lead_result = results[0] + expected_lead_search_result = { + "text": "Aristotle[A] (Greek: Ἀριστοτέλης Aristotélēs, pronounced [aristotélɛːs]; 384–322 BC) was an Ancient Greek philosopher and polymath. His writings cover a broad range of subjects spanning the natural sciences, philosophy, linguistics, economics, politics, psychology, and the arts. As the founder of the Peripatetic school of philosophy in the Lyceum in Athens, he began the wider Aristotelian tradition that followed, which set the groundwork for the development of modern science.", + "extraction_id": "ff8accdb-791e-5b6d-a83a-5adc32c4222c", + "document_id": "9fbe403b-c11c-5aae-8ade-ef22980c3ad1", + "user_id": "2acb499e-8428-543b-bd85-0d9098718220", + "score": lambda x: 0.77 <= x <= 0.79, + } + compare_result_fields(lead_result, expected_lead_search_result) + + print("Hybrid search test passed") + print("~" * 100) + + +def test_rag_response_sample_file_sdk(): + print("Testing: RAG query for Aristotle's birth year") + response = client.rag(query="What year was Aristotle born?") + + expected_answer = "Aristotle was born in 384 BC" + + if expected_answer not in response: + print( + f"RAG query test failed: Expected answer '{expected_answer}' not found in '{response}'" + ) + sys.exit(1) + + print("RAG response test passed") + print("~" * 100) + + +def test_rag_response_stream_sample_file_sdk(): + print("Testing: Streaming RAG query for who Aristotle was") + + rag_agent_response = client.agent( + messages=[{"role": "user", "content": "who was aristotle"}], + vector_search_settings={"use_hybrid_search": True}, + rag_generation_config={"stream": True}, + ) + + output = "" + for response in rag_agent_response: + output += response + + if "" not in output or "" not in output: + print( + "Streaming RAG query test failed: Search results not found in output" + ) + sys.exit(1) + + if "" not in output or "" not in output: + print( + "Streaming RAG query test failed: Completion not found in output" + ) + sys.exit(1) + + print("RAG response stream test passed") + print("~" * 100) + + +if __name__ == "__main__": + if len(sys.argv) < 2: + print("Please specify a test function to run") + sys.exit(1) + + test_function = sys.argv[1] + globals()[test_function]() From 7439b1bdf74d10a6834a63b86e02e88a25af6ac5 Mon Sep 17 00:00:00 2001 From: emrgnt-cmplxty Date: Fri, 4 Oct 2024 16:14:29 -0700 Subject: [PATCH 20/30] up --- .../integration-test-workflow-debian.yml | 9 ++- py/tests/integration/harness_sdk.py | 62 +++++++++++-------- 2 files changed, 42 insertions(+), 29 deletions(-) diff --git a/.github/workflows/integration-test-workflow-debian.yml b/.github/workflows/integration-test-workflow-debian.yml index 941a675b2..6eeabcfd3 100644 --- a/.github/workflows/integration-test-workflow-debian.yml +++ b/.github/workflows/integration-test-workflow-debian.yml @@ -81,9 +81,14 @@ jobs: poetry run python tests/integration/harness_cli.py test_ingest_sample_file_cli poetry run python tests/integration/harness_cli.py test_document_overview_sample_file_cli poetry run python tests/integration/harness_cli.py test_vector_search_sample_file_filter_cli + poetry run python tests/integration/harness_cli.py test_rag_response_sample_file_cli + poetry run python tests/integration/harness_cli.py test_rag_response_stream_sample_file_cli - poetry run python tests/integration/harness_cli.py test_ingest_sample_file_sdk - poetry run python tests/integration/harness_cli.py test_reingest_sample_file_sdk + poetry run python tests/integration/harness_sdk.py test_ingest_sample_file_sdk + poetry run python tests/integration/harness_sdk.py test_reingest_sample_file_sdk + poetry run python tests/integration/harness_sdk.py test_document_overview_sample_file_sdk + poetry run python tests/integration/harness_cli.py test_vector_search_sample_file_filter_sdk + poetry run python tests/integration/harness_cli.py test_hybrid_search_sample_file_filter_sdk - name: Stop R2R server if: always() diff --git a/py/tests/integration/harness_sdk.py b/py/tests/integration/harness_sdk.py index 11521d156..e12aa0aca 100644 --- a/py/tests/integration/harness_sdk.py +++ b/py/tests/integration/harness_sdk.py @@ -62,24 +62,25 @@ def test_reingest_sample_file_sdk(): def test_document_overview_sample_file_sdk(): - print("Testing: Document overview contains 'uber.txt'") - documents_overview = client.documents_overview() + documents_overview = client.documents_overview()["results"] - aristotle_document = { - "title": "aristotle.txt", - "type": "txt", + uber_document = { + "id": "3e157b3a-8469-51db-90d9-52e7d896b49b", + "title": "uber_2021.pdf", + "type": "pdf", "ingestion_status": "success", "kg_extraction_status": "pending", - "version": "v0", - "metadata": {"title": "aristotle.txt", "version": "v0"}, + "collection_ids": ["122fdf6a-e116-546b-a8f6-e4cb2e2c0a09"], + # "version": "v0", + # "metadata": {"title": "uber_2021.pdf"}, } if not any( - all(doc.get(k) == v for k, v in aristotle_document.items()) + all(doc.get(k) == v for k, v in uber_document.items()) for doc in documents_overview ): print("Document overview test failed") - print("Aristotle document not found in the overview") + print("Uber document not found in the overview") sys.exit(1) print("Document overview test passed") print("~" * 100) @@ -88,11 +89,13 @@ def test_document_overview_sample_file_sdk(): def test_vector_search_sample_file_filter_sdk(): print("Testing: Vector search") results = client.search( - query="Who was aristotle?", - filters={ - "document_id": {"$eq": "9fbe403b-c11c-5aae-8ade-ef22980c3ad1"} + query="What was Uber's recent profit??", + vector_search_settings={ + "search_filters": { + "document_id": {"$eq": "3e157b3a-8469-51db-90d9-52e7d896b49b"} + } }, - ) + )["results"]["vector_search_results"] if not results: print("Vector search test failed: No results returned") @@ -100,11 +103,11 @@ def test_vector_search_sample_file_filter_sdk(): lead_result = results[0] expected_lead_search_result = { - "text": "Aristotle[A] (Greek: Ἀριστοτέλης Aristotélēs, pronounced [aristotélɛːs]; 384–322 BC) was an Ancient Greek philosopher and polymath. His writings cover a broad range of subjects spanning the natural sciences, philosophy, linguistics, economics, politics, psychology, and the arts. As the founder of the Peripatetic school of philosophy in the Lyceum in Athens, he began the wider Aristotelian tradition that followed, which set the groundwork for the development of modern science.", - "extraction_id": "ff8accdb-791e-5b6d-a83a-5adc32c4222c", - "document_id": "9fbe403b-c11c-5aae-8ade-ef22980c3ad1", + "text": "was $17.5 billion, or up 57% year-over-year, reflecting the overall growth in our Delivery business and an increase in Freight revenue attributable tothe\n acquisition of Transplace in the fourth quarter of 2021 as well as growth in the number of shippers and carriers on the network combined with an increase involumes with our top shippers.\nNet\n loss attributable to Uber Technologies, Inc. was $496 million, a 93% improvement year-over-year, driven by a $1.6 billion pre-tax gain on the sale of ourATG\n Business to Aurora, a $1.6 billion pre-tax net benefit relating to Ubers equity investments, as well as reductions in our fixed cost structure and increasedvariable cost effi\nciencies. Net loss attributable to Uber Technologies, Inc. also included $1.2 billion of stock-based compensation expense.Adjusted\n EBITDA loss was $774 million, improving $1.8 billion from 2020 with Mobility Adjusted EBITDA profit of $1.6 billion. Additionally, DeliveryAdjusted", + "extraction_id": "6b4cdb93-f6f5-5ff4-8a89-7a4b1b7cd034", + "document_id": "3e157b3a-8469-51db-90d9-52e7d896b49b", "user_id": "2acb499e-8428-543b-bd85-0d9098718220", - "score": lambda x: 0.77 <= x <= 0.79, + "score": lambda x: 0.71 <= x <= 0.73, } compare_result_fields(lead_result, expected_lead_search_result) @@ -114,25 +117,30 @@ def test_vector_search_sample_file_filter_sdk(): def test_hybrid_search_sample_file_filter_sdk(): print("Testing: Hybrid search") + results = client.search( - query="Who was aristotle?", - vector_search_settings={"use_hybrid_search": True}, - filters={ - "document_id": {"$eq": "9fbe403b-c11c-5aae-8ade-ef22980c3ad1"} + query="What was Uber's recent profit??", + vector_search_settings={ + "use_hybrid_search": True, + "search_filters": { + "document_id": {"$eq": "3e157b3a-8469-51db-90d9-52e7d896b49b"} + } }, - ) + )["results"]["vector_search_results"] if not results: - print("Hybrid search test failed: No results returned") + print("Vector search test failed: No results returned") sys.exit(1) lead_result = results[0] expected_lead_search_result = { - "text": "Aristotle[A] (Greek: Ἀριστοτέλης Aristotélēs, pronounced [aristotélɛːs]; 384–322 BC) was an Ancient Greek philosopher and polymath. His writings cover a broad range of subjects spanning the natural sciences, philosophy, linguistics, economics, politics, psychology, and the arts. As the founder of the Peripatetic school of philosophy in the Lyceum in Athens, he began the wider Aristotelian tradition that followed, which set the groundwork for the development of modern science.", - "extraction_id": "ff8accdb-791e-5b6d-a83a-5adc32c4222c", - "document_id": "9fbe403b-c11c-5aae-8ade-ef22980c3ad1", + "text": "was $17.5 billion, or up 57% year-over-year, reflecting the overall growth in our Delivery business and an increase in Freight revenue attributable tothe\n acquisition of Transplace in the fourth quarter of 2021 as well as growth in the number of shippers and carriers on the network combined with an increase involumes with our top shippers.\nNet\n loss attributable to Uber Technologies, Inc. was $496 million, a 93% improvement year-over-year, driven by a $1.6 billion pre-tax gain on the sale of ourATG\n Business to Aurora, a $1.6 billion pre-tax net benefit relating to Ubers equity investments, as well as reductions in our fixed cost structure and increasedvariable cost effi\nciencies. Net loss attributable to Uber Technologies, Inc. also included $1.2 billion of stock-based compensation expense.Adjusted\n EBITDA loss was $774 million, improving $1.8 billion from 2020 with Mobility Adjusted EBITDA profit of $1.6 billion. Additionally, DeliveryAdjusted", + "extraction_id": "6b4cdb93-f6f5-5ff4-8a89-7a4b1b7cd034", + "document_id": "3e157b3a-8469-51db-90d9-52e7d896b49b", "user_id": "2acb499e-8428-543b-bd85-0d9098718220", - "score": lambda x: 0.77 <= x <= 0.79, + "score": lambda x: 0.016 <= x <= 0.017, + "semantic_rank": 1, + "full_text_rank": 200 } compare_result_fields(lead_result, expected_lead_search_result) From fd9cfd6639c949d83d9b42d951b4b17b4c3aa471 Mon Sep 17 00:00:00 2001 From: emrgnt-cmplxty Date: Fri, 4 Oct 2024 16:15:21 -0700 Subject: [PATCH 21/30] up --- .github/workflows/integration-test-workflow-debian.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/integration-test-workflow-debian.yml b/.github/workflows/integration-test-workflow-debian.yml index 6eeabcfd3..529e38d52 100644 --- a/.github/workflows/integration-test-workflow-debian.yml +++ b/.github/workflows/integration-test-workflow-debian.yml @@ -87,8 +87,8 @@ jobs: poetry run python tests/integration/harness_sdk.py test_ingest_sample_file_sdk poetry run python tests/integration/harness_sdk.py test_reingest_sample_file_sdk poetry run python tests/integration/harness_sdk.py test_document_overview_sample_file_sdk - poetry run python tests/integration/harness_cli.py test_vector_search_sample_file_filter_sdk - poetry run python tests/integration/harness_cli.py test_hybrid_search_sample_file_filter_sdk + poetry run python tests/integration/harness_sdk.py test_vector_search_sample_file_filter_sdk + poetry run python tests/integration/harness_sdk.py test_hybrid_search_sample_file_filter_sdk - name: Stop R2R server if: always() From 05a068bc03d6225361218fb01ca36617d29a7f4c Mon Sep 17 00:00:00 2001 From: emrgnt-cmplxty Date: Fri, 4 Oct 2024 16:29:39 -0700 Subject: [PATCH 22/30] up --- .../integration-test-workflow-debian.yml | 2 + py/tests/integration/harness_sdk.py | 105 +++++++++++++++++- 2 files changed, 101 insertions(+), 6 deletions(-) diff --git a/.github/workflows/integration-test-workflow-debian.yml b/.github/workflows/integration-test-workflow-debian.yml index 529e38d52..5259ee755 100644 --- a/.github/workflows/integration-test-workflow-debian.yml +++ b/.github/workflows/integration-test-workflow-debian.yml @@ -89,6 +89,8 @@ jobs: poetry run python tests/integration/harness_sdk.py test_document_overview_sample_file_sdk poetry run python tests/integration/harness_sdk.py test_vector_search_sample_file_filter_sdk poetry run python tests/integration/harness_sdk.py test_hybrid_search_sample_file_filter_sdk + poetry run python tests/integration/harness_sdk.py test_rag_response_sample_file_sdk + poetry run python tests/integration/harness_sdk.py test_rag_response_stream_sample_file_sdk - name: Stop R2R server if: always() diff --git a/py/tests/integration/harness_sdk.py b/py/tests/integration/harness_sdk.py index e12aa0aca..9c25d5fc5 100644 --- a/py/tests/integration/harness_sdk.py +++ b/py/tests/integration/harness_sdk.py @@ -138,7 +138,7 @@ def test_hybrid_search_sample_file_filter_sdk(): "extraction_id": "6b4cdb93-f6f5-5ff4-8a89-7a4b1b7cd034", "document_id": "3e157b3a-8469-51db-90d9-52e7d896b49b", "user_id": "2acb499e-8428-543b-bd85-0d9098718220", - "score": lambda x: 0.016 <= x <= 0.017, + "score": lambda x: 0.016 <= x <= 0.018, "semantic_rank": 1, "full_text_rank": 200 } @@ -149,14 +149,23 @@ def test_hybrid_search_sample_file_filter_sdk(): def test_rag_response_sample_file_sdk(): - print("Testing: RAG query for Aristotle's birth year") - response = client.rag(query="What year was Aristotle born?") + print("Testing: RAG query for Uber's recent P&L") + response = client.rag( + query="What was Uber's recent profit and loss?", + vector_search_settings={ + "search_filters": { + "document_id": {"$eq": "3e157b3a-8469-51db-90d9-52e7d896b49b"} + } + }, + )["results"]["completion"]["choices"][0]["message"]["content"] + - expected_answer = "Aristotle was born in 384 BC" + expected_answer_0 = "net loss" + expected_answer_1 = "$496 million" - if expected_answer not in response: + if expected_answer_0 not in response or expected_answer_1 not in response: print( - f"RAG query test failed: Expected answer '{expected_answer}' not found in '{response}'" + f"RAG query test failed: Expected answer(s) '{expected_answer_0}, {expected_answer_1}' not found in '{response}'" ) sys.exit(1) @@ -164,6 +173,36 @@ def test_rag_response_sample_file_sdk(): print("~" * 100) + +def test_rag_response_stream_sample_file_sdk(): + print("Testing: Streaming RAG query for Uber's recent P&L") + response = client.rag( + query="What was Uber's recent profit and loss?", + rag_generation_config={"stream": True}, + vector_search_settings={ + "search_filters": { + "document_id": {"$eq": "3e157b3a-8469-51db-90d9-52e7d896b49b"} + } + }, + ) # ["results"]["completion"]["choices"][0]["message"]["content"] + + response = "" + for res in response: + response += res + print(res) + + expected_answer_0 = "net loss" + expected_answer_1 = "$496 million" + + if expected_answer_0 not in response or expected_answer_1 not in response: + print( + f"RAG query test failed: Expected answer(s) '{expected_answer_0}, {expected_answer_1}' not found in '{response}'" + ) + sys.exit(1) + + print("Streaming RAG response test passed") + print("~" * 100) + def test_rag_response_stream_sample_file_sdk(): print("Testing: Streaming RAG query for who Aristotle was") @@ -192,6 +231,60 @@ def test_rag_response_stream_sample_file_sdk(): print("RAG response stream test passed") print("~" * 100) +def test_agent_sample_file_sdk(): + print("Testing: Agent query for Uber's recent P&L") + response = client.agent( + messages=[{"role": "user", "content": "What was Uber's recent profit and loss?"}], + rag_generation_config={"stream": False}, + vector_search_settings={ + "search_filters": { + "document_id": {"$eq": "3e157b3a-8469-51db-90d9-52e7d896b49b"} + } + }, + )["results"] + response_content = response["messages"][-1]["content"] + + expected_answer_0 = "net loss" + expected_answer_1 = "$496 million" + + if expected_answer_0 not in response_content or expected_answer_1 not in response_content: + print( + f"Agent query test failed: Expected answer(s) '{expected_answer_0}, {expected_answer_1}' not found in '{response_content}'" + ) + sys.exit(1) + + print("Agent response test passed") + print("~" * 100) + +def test_agent_stream_sample_file_sdk(): + print("Testing: Streaming agent query for who Aristotle was") + + response = client.agent( + messages=[{"role": "user", "content": "What was Uber's recent profit and loss?"}], + rag_generation_config={"stream": True}, + vector_search_settings={ + "search_filters": { + "document_id": {"$eq": "3e157b3a-8469-51db-90d9-52e7d896b49b"} + } + }, + ) + output = "" + for response in response: + output += response["content"] + + expected_answer_0 = "net loss" + expected_answer_1 = "$496 million" + + if expected_answer_0 not in response or expected_answer_1 not in response: + print( + f"Agent query test failed: Expected answer(s) '{expected_answer_0}, {expected_answer_1}' not found in '{response_content}'" + ) + sys.exit(1) + + print("Agent response stream test passed") + print("~" * 100) + + if __name__ == "__main__": if len(sys.argv) < 2: From f7103df50c767481da63e3445a1ed4dac845cd5a Mon Sep 17 00:00:00 2001 From: emrgnt-cmplxty Date: Fri, 4 Oct 2024 16:36:46 -0700 Subject: [PATCH 23/30] up --- .../integration-test-workflow-debian.yml | 13 ++++++- py/tests/integration/harness_sdk.py | 34 +++++++++++++------ 2 files changed, 35 insertions(+), 12 deletions(-) diff --git a/.github/workflows/integration-test-workflow-debian.yml b/.github/workflows/integration-test-workflow-debian.yml index 5259ee755..95cad369e 100644 --- a/.github/workflows/integration-test-workflow-debian.yml +++ b/.github/workflows/integration-test-workflow-debian.yml @@ -75,18 +75,29 @@ jobs: echo "Waiting for services to start..." sleep 30 - - name: Run integration tests - Ingestion + - name: Run CLI Ingestion working-directory: ./py run: | poetry run python tests/integration/harness_cli.py test_ingest_sample_file_cli poetry run python tests/integration/harness_cli.py test_document_overview_sample_file_cli + + - name: Run CLI Retrieval + working-directory: ./py + run: | poetry run python tests/integration/harness_cli.py test_vector_search_sample_file_filter_cli poetry run python tests/integration/harness_cli.py test_rag_response_sample_file_cli poetry run python tests/integration/harness_cli.py test_rag_response_stream_sample_file_cli + - name: Run SDK Integration + working-directory: ./py + run: | poetry run python tests/integration/harness_sdk.py test_ingest_sample_file_sdk poetry run python tests/integration/harness_sdk.py test_reingest_sample_file_sdk poetry run python tests/integration/harness_sdk.py test_document_overview_sample_file_sdk + + - name: Run SDK Retrieval + working-directory: ./py + run: | poetry run python tests/integration/harness_sdk.py test_vector_search_sample_file_filter_sdk poetry run python tests/integration/harness_sdk.py test_hybrid_search_sample_file_filter_sdk poetry run python tests/integration/harness_sdk.py test_rag_response_sample_file_sdk diff --git a/py/tests/integration/harness_sdk.py b/py/tests/integration/harness_sdk.py index 9c25d5fc5..10eccd2b4 100644 --- a/py/tests/integration/harness_sdk.py +++ b/py/tests/integration/harness_sdk.py @@ -124,7 +124,7 @@ def test_hybrid_search_sample_file_filter_sdk(): "use_hybrid_search": True, "search_filters": { "document_id": {"$eq": "3e157b3a-8469-51db-90d9-52e7d896b49b"} - } + }, }, )["results"]["vector_search_results"] @@ -139,8 +139,7 @@ def test_hybrid_search_sample_file_filter_sdk(): "document_id": "3e157b3a-8469-51db-90d9-52e7d896b49b", "user_id": "2acb499e-8428-543b-bd85-0d9098718220", "score": lambda x: 0.016 <= x <= 0.018, - "semantic_rank": 1, - "full_text_rank": 200 + 'metadata': {'version': 'v0', 'chunk_order': 587, 'document_type': 'pdf', 'semantic_rank': 1, 'full_text_rank': 200, 'associated_query': "What was Uber's recent profit??"} } compare_result_fields(lead_result, expected_lead_search_result) @@ -159,7 +158,6 @@ def test_rag_response_sample_file_sdk(): }, )["results"]["completion"]["choices"][0]["message"]["content"] - expected_answer_0 = "net loss" expected_answer_1 = "$496 million" @@ -173,7 +171,6 @@ def test_rag_response_sample_file_sdk(): print("~" * 100) - def test_rag_response_stream_sample_file_sdk(): print("Testing: Streaming RAG query for Uber's recent P&L") response = client.rag( @@ -184,7 +181,7 @@ def test_rag_response_stream_sample_file_sdk(): "document_id": {"$eq": "3e157b3a-8469-51db-90d9-52e7d896b49b"} } }, - ) # ["results"]["completion"]["choices"][0]["message"]["content"] + ) # ["results"]["completion"]["choices"][0]["message"]["content"] response = "" for res in response: @@ -203,6 +200,7 @@ def test_rag_response_stream_sample_file_sdk(): print("Streaming RAG response test passed") print("~" * 100) + def test_rag_response_stream_sample_file_sdk(): print("Testing: Streaming RAG query for who Aristotle was") @@ -231,10 +229,16 @@ def test_rag_response_stream_sample_file_sdk(): print("RAG response stream test passed") print("~" * 100) + def test_agent_sample_file_sdk(): print("Testing: Agent query for Uber's recent P&L") response = client.agent( - messages=[{"role": "user", "content": "What was Uber's recent profit and loss?"}], + messages=[ + { + "role": "user", + "content": "What was Uber's recent profit and loss?", + } + ], rag_generation_config={"stream": False}, vector_search_settings={ "search_filters": { @@ -247,7 +251,10 @@ def test_agent_sample_file_sdk(): expected_answer_0 = "net loss" expected_answer_1 = "$496 million" - if expected_answer_0 not in response_content or expected_answer_1 not in response_content: + if ( + expected_answer_0 not in response_content + or expected_answer_1 not in response_content + ): print( f"Agent query test failed: Expected answer(s) '{expected_answer_0}, {expected_answer_1}' not found in '{response_content}'" ) @@ -256,11 +263,17 @@ def test_agent_sample_file_sdk(): print("Agent response test passed") print("~" * 100) + def test_agent_stream_sample_file_sdk(): print("Testing: Streaming agent query for who Aristotle was") response = client.agent( - messages=[{"role": "user", "content": "What was Uber's recent profit and loss?"}], + messages=[ + { + "role": "user", + "content": "What was Uber's recent profit and loss?", + } + ], rag_generation_config={"stream": True}, vector_search_settings={ "search_filters": { @@ -281,11 +294,10 @@ def test_agent_stream_sample_file_sdk(): ) sys.exit(1) - print("Agent response stream test passed") + print("Agent response stream test passed") print("~" * 100) - if __name__ == "__main__": if len(sys.argv) < 2: print("Please specify a test function to run") From 8095e72810d81e2796c5669ec0dfd00a2b4a372b Mon Sep 17 00:00:00 2001 From: emrgnt-cmplxty Date: Fri, 4 Oct 2024 16:45:22 -0700 Subject: [PATCH 24/30] up --- .../integration-test-workflow-debian.yml | 1 + docs/cookbooks/walkthrough.mdx | 6 ++-- py/core/configs/r2r_aws_bedrock.toml | 2 +- py/tests/integration/harness_cli.py | 17 ++++++++++ py/tests/integration/harness_sdk.py | 32 ++++++++++++++++++- 5 files changed, 53 insertions(+), 5 deletions(-) diff --git a/.github/workflows/integration-test-workflow-debian.yml b/.github/workflows/integration-test-workflow-debian.yml index 95cad369e..34b8ed684 100644 --- a/.github/workflows/integration-test-workflow-debian.yml +++ b/.github/workflows/integration-test-workflow-debian.yml @@ -80,6 +80,7 @@ jobs: run: | poetry run python tests/integration/harness_cli.py test_ingest_sample_file_cli poetry run python tests/integration/harness_cli.py test_document_overview_sample_file_cli + poetry run python tests/integration/harness_cli.py test_document_chunks_sample_file_cli - name: Run CLI Retrieval working-directory: ./py diff --git a/docs/cookbooks/walkthrough.mdx b/docs/cookbooks/walkthrough.mdx index bfa289931..e2a4b5a79 100644 --- a/docs/cookbooks/walkthrough.mdx +++ b/docs/cookbooks/walkthrough.mdx @@ -81,11 +81,11 @@ concurrent_request_limit = 16 model = "openai/gpt-4o" temperature = 0.5 -[chunking] +[ingestion] provider = "r2r" chunking_strategy = "recursive" -chunk_size = 512 -chunk_overlap = 256 +chunk_size = 1_024 +chunk_overlap = 512 excluded_parsers = ["mp4"] ``` diff --git a/py/core/configs/r2r_aws_bedrock.toml b/py/core/configs/r2r_aws_bedrock.toml index e5fd2858c..d83fadbc2 100644 --- a/py/core/configs/r2r_aws_bedrock.toml +++ b/py/core/configs/r2r_aws_bedrock.toml @@ -7,7 +7,7 @@ require_email_verification = false default_admin_email = "admin@example.com" default_admin_password = "change_me_immediately" -[chunking] +[ingestion] provider = "unstructured_local" strategy = "auto" chunking_strategy = "by_title" diff --git a/py/tests/integration/harness_cli.py b/py/tests/integration/harness_cli.py index cf176c65f..562c4ee03 100644 --- a/py/tests/integration/harness_cli.py +++ b/py/tests/integration/harness_cli.py @@ -67,6 +67,23 @@ def test_document_overview_sample_file_cli(): print("~" * 100) +def test_document_chunks_sample_file_cli(): + print("Testing: Document chunks") + output = run_command( + "poetry run r2r document-chunks --document-id=9fbe403b-c11c-5aae-8ade-ef22980c3ad1" + ) + output = output.replace("'", '"') + output_lines = output.strip().split("\n")[1:] + aristotle_is_in_chunks = False + for line in output_lines: + if "aristotle" in line.lower(): + aristotle_is_in_chunks = True + break + assert len(output_lines) >= 100 and aristotle_is_in_chunks + print("Document chunks test passed") + print("~" * 100) + + def test_vector_search_sample_file_filter_cli(): print("Testing: Vector search") output = run_command( diff --git a/py/tests/integration/harness_sdk.py b/py/tests/integration/harness_sdk.py index 10eccd2b4..1e4a38cee 100644 --- a/py/tests/integration/harness_sdk.py +++ b/py/tests/integration/harness_sdk.py @@ -86,6 +86,29 @@ def test_document_overview_sample_file_sdk(): print("~" * 100) +def test_document_chunks_sample_file_sdk(): + print("Testing: Document chunks") + document_id = "3e157b3a-8469-51db-90d9-52e7d896b49b" # Replace with the actual document ID + chunks = client.document_chunks(document_id=document_id)["results"] + + lead_chunk = { + "extraction_id": "57d761ac-b2df-529c-9c47-6e6e1bbf854f", + "document_id": "3e157b3a-8469-51db-90d9-52e7d896b49b", + "user_id": "2acb499e-8428-543b-bd85-0d9098718220", + "collection_ids": ["122fdf6a-e116-546b-a8f6-e4cb2e2c0a09"], + "text": "UNITED STATESSECURITIES AND EXCHANGE COMMISSION\nWashington, D.C. 20549\n____________________________________________ \nFORM\n 10-K____________________________________________ \n(Mark One)\n\n ANNUAL REPORT PURSUANT TO SECTION 13 OR 15(d) OF THE SECURITIES EXCHANGE ACT OF 1934For the fiscal year ended\n December 31, 2021OR", + "metadata": { + "version": "v0", + "chunk_order": 0, + "document_type": "pdf", + }, + } + + assert len(chunks) >= 100 and lead_chunk == chunks[0] + print("Document chunks test passed") + print("~" * 100) + + def test_vector_search_sample_file_filter_sdk(): print("Testing: Vector search") results = client.search( @@ -139,7 +162,14 @@ def test_hybrid_search_sample_file_filter_sdk(): "document_id": "3e157b3a-8469-51db-90d9-52e7d896b49b", "user_id": "2acb499e-8428-543b-bd85-0d9098718220", "score": lambda x: 0.016 <= x <= 0.018, - 'metadata': {'version': 'v0', 'chunk_order': 587, 'document_type': 'pdf', 'semantic_rank': 1, 'full_text_rank': 200, 'associated_query': "What was Uber's recent profit??"} + "metadata": { + "version": "v0", + "chunk_order": 587, + "document_type": "pdf", + "semantic_rank": 1, + "full_text_rank": 200, + "associated_query": "What was Uber's recent profit??", + }, } compare_result_fields(lead_result, expected_lead_search_result) From 68f34ed5031dc8d4969ae0ee9cfd14a26e62c109 Mon Sep 17 00:00:00 2001 From: emrgnt-cmplxty Date: Fri, 4 Oct 2024 16:53:39 -0700 Subject: [PATCH 25/30] up --- .../integration-test-workflow-debian.yml | 3 + py/tests/integration/harness_cli.py | 23 +++++++ py/tests/integration/harness_sdk.py | 63 ++++++++++--------- 3 files changed, 58 insertions(+), 31 deletions(-) diff --git a/.github/workflows/integration-test-workflow-debian.yml b/.github/workflows/integration-test-workflow-debian.yml index 34b8ed684..51f805fe1 100644 --- a/.github/workflows/integration-test-workflow-debian.yml +++ b/.github/workflows/integration-test-workflow-debian.yml @@ -81,6 +81,7 @@ jobs: poetry run python tests/integration/harness_cli.py test_ingest_sample_file_cli poetry run python tests/integration/harness_cli.py test_document_overview_sample_file_cli poetry run python tests/integration/harness_cli.py test_document_chunks_sample_file_cli + poetry run python tests/integration/harness_cli.py test_delete_and_reingest_sample_file_cli - name: Run CLI Retrieval working-directory: ./py @@ -95,6 +96,8 @@ jobs: poetry run python tests/integration/harness_sdk.py test_ingest_sample_file_sdk poetry run python tests/integration/harness_sdk.py test_reingest_sample_file_sdk poetry run python tests/integration/harness_sdk.py test_document_overview_sample_file_sdk + poetry run python tests/integration/harness_sdk.py test_document_chunks_sample_file_sdk + poetry run python tests/integration/harness_cli.py test_delete_and_reingest_sample_file_sdk - name: Run SDK Retrieval working-directory: ./py diff --git a/py/tests/integration/harness_cli.py b/py/tests/integration/harness_cli.py index 562c4ee03..4b138d80c 100644 --- a/py/tests/integration/harness_cli.py +++ b/py/tests/integration/harness_cli.py @@ -84,6 +84,29 @@ def test_document_chunks_sample_file_cli(): print("~" * 100) +def test_delete_and_reingest_sample_file_cli(): + print("Testing: Delete and re-ingest Aristotle document") + + # Delete the Aristotle document + delete_output = run_command( + "poetry run r2r delete --filter='document_id:eq:9fbe403b-c11c-5aae-8ade-ef22980c3ad1'" + ) + + # Check if the deletion was successful + if "'results': {}" not in delete_output: + print("Delete and re-ingest test failed: Deletion unsuccessful") + print("Delete output:", delete_output) + sys.exit(1) + + print("Aristotle document deleted successfully") + + # Re-ingest the sample file + run_command("poetry run r2r ingest-sample-file") + print("Sample file re-ingested successfully") + + print("Delete and re-ingest test passed") + print("~" * 100) + def test_vector_search_sample_file_filter_cli(): print("Testing: Vector search") output = run_command( diff --git a/py/tests/integration/harness_sdk.py b/py/tests/integration/harness_sdk.py index 1e4a38cee..321fdbcc1 100644 --- a/py/tests/integration/harness_sdk.py +++ b/py/tests/integration/harness_sdk.py @@ -108,6 +108,37 @@ def test_document_chunks_sample_file_sdk(): print("Document chunks test passed") print("~" * 100) +def test_delete_and_reingest_sample_file_sdk(): + print("Testing: Delete and re-ingest the Uber document") + + # Delete the Aristotle document + delete_response = client.delete( + { + "document_id": {"$eq": "9fbe403b-c11c-5aae-8ade-ef22980c3ad1"} + } + ) + + # Check if the deletion was successful + if delete_response["results"] != {}: + print("Delete and re-ingest test failed: Deletion unsuccessful") + print("Delete response:", delete_response) + sys.exit(1) + + print("Uber document deleted successfully") + + # Re-ingest the sample file + file_paths = ["core/examples/data/uber_2021.pdf"] + ingest_response = client.ingest_files(file_paths=file_paths) + + if not ingest_response["results"]: + print("Delete and re-ingest test failed: Re-ingestion unsuccessful") + sys.exit(1) + + print("Sample file re-ingested successfully") + + print("Delete and re-ingest test passed") + print("~" * 100) + def test_vector_search_sample_file_filter_sdk(): print("Testing: Vector search") @@ -211,7 +242,7 @@ def test_rag_response_stream_sample_file_sdk(): "document_id": {"$eq": "3e157b3a-8469-51db-90d9-52e7d896b49b"} } }, - ) # ["results"]["completion"]["choices"][0]["message"]["content"] + ) response = "" for res in response: @@ -230,36 +261,6 @@ def test_rag_response_stream_sample_file_sdk(): print("Streaming RAG response test passed") print("~" * 100) - -def test_rag_response_stream_sample_file_sdk(): - print("Testing: Streaming RAG query for who Aristotle was") - - rag_agent_response = client.agent( - messages=[{"role": "user", "content": "who was aristotle"}], - vector_search_settings={"use_hybrid_search": True}, - rag_generation_config={"stream": True}, - ) - - output = "" - for response in rag_agent_response: - output += response - - if "" not in output or "" not in output: - print( - "Streaming RAG query test failed: Search results not found in output" - ) - sys.exit(1) - - if "" not in output or "" not in output: - print( - "Streaming RAG query test failed: Completion not found in output" - ) - sys.exit(1) - - print("RAG response stream test passed") - print("~" * 100) - - def test_agent_sample_file_sdk(): print("Testing: Agent query for Uber's recent P&L") response = client.agent( From dc0fcb15baa690fd06ace4f51ea8854005f20b0b Mon Sep 17 00:00:00 2001 From: emrgnt-cmplxty Date: Fri, 4 Oct 2024 16:53:49 -0700 Subject: [PATCH 26/30] up --- py/tests/integration/harness_cli.py | 11 ++++++----- py/tests/integration/harness_sdk.py | 22 +++++++++++----------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/py/tests/integration/harness_cli.py b/py/tests/integration/harness_cli.py index 4b138d80c..151f81576 100644 --- a/py/tests/integration/harness_cli.py +++ b/py/tests/integration/harness_cli.py @@ -86,27 +86,28 @@ def test_document_chunks_sample_file_cli(): def test_delete_and_reingest_sample_file_cli(): print("Testing: Delete and re-ingest Aristotle document") - + # Delete the Aristotle document delete_output = run_command( "poetry run r2r delete --filter='document_id:eq:9fbe403b-c11c-5aae-8ade-ef22980c3ad1'" ) - + # Check if the deletion was successful if "'results': {}" not in delete_output: print("Delete and re-ingest test failed: Deletion unsuccessful") print("Delete output:", delete_output) sys.exit(1) - + print("Aristotle document deleted successfully") - + # Re-ingest the sample file run_command("poetry run r2r ingest-sample-file") print("Sample file re-ingested successfully") - + print("Delete and re-ingest test passed") print("~" * 100) + def test_vector_search_sample_file_filter_cli(): print("Testing: Vector search") output = run_command( diff --git a/py/tests/integration/harness_sdk.py b/py/tests/integration/harness_sdk.py index 321fdbcc1..76e5b33d1 100644 --- a/py/tests/integration/harness_sdk.py +++ b/py/tests/integration/harness_sdk.py @@ -108,34 +108,33 @@ def test_document_chunks_sample_file_sdk(): print("Document chunks test passed") print("~" * 100) + def test_delete_and_reingest_sample_file_sdk(): print("Testing: Delete and re-ingest the Uber document") - + # Delete the Aristotle document delete_response = client.delete( - { - "document_id": {"$eq": "9fbe403b-c11c-5aae-8ade-ef22980c3ad1"} - } + {"document_id": {"$eq": "9fbe403b-c11c-5aae-8ade-ef22980c3ad1"}} ) - + # Check if the deletion was successful if delete_response["results"] != {}: print("Delete and re-ingest test failed: Deletion unsuccessful") print("Delete response:", delete_response) sys.exit(1) - + print("Uber document deleted successfully") - + # Re-ingest the sample file file_paths = ["core/examples/data/uber_2021.pdf"] ingest_response = client.ingest_files(file_paths=file_paths) - + if not ingest_response["results"]: print("Delete and re-ingest test failed: Re-ingestion unsuccessful") sys.exit(1) - + print("Sample file re-ingested successfully") - + print("Delete and re-ingest test passed") print("~" * 100) @@ -242,7 +241,7 @@ def test_rag_response_stream_sample_file_sdk(): "document_id": {"$eq": "3e157b3a-8469-51db-90d9-52e7d896b49b"} } }, - ) + ) response = "" for res in response: @@ -261,6 +260,7 @@ def test_rag_response_stream_sample_file_sdk(): print("Streaming RAG response test passed") print("~" * 100) + def test_agent_sample_file_sdk(): print("Testing: Agent query for Uber's recent P&L") response = client.agent( From c329e201d3d0197b3e9d8fb3534f7a2bef7cf85b Mon Sep 17 00:00:00 2001 From: emrgnt-cmplxty Date: Fri, 4 Oct 2024 17:03:05 -0700 Subject: [PATCH 27/30] up --- .github/workflows/integration-test-workflow-debian.yml | 2 +- docs/documentation/installation/light/docker.mdx | 2 +- py/tests/integration/harness_sdk.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/integration-test-workflow-debian.yml b/.github/workflows/integration-test-workflow-debian.yml index 51f805fe1..1b5b1308c 100644 --- a/.github/workflows/integration-test-workflow-debian.yml +++ b/.github/workflows/integration-test-workflow-debian.yml @@ -97,7 +97,7 @@ jobs: poetry run python tests/integration/harness_sdk.py test_reingest_sample_file_sdk poetry run python tests/integration/harness_sdk.py test_document_overview_sample_file_sdk poetry run python tests/integration/harness_sdk.py test_document_chunks_sample_file_sdk - poetry run python tests/integration/harness_cli.py test_delete_and_reingest_sample_file_sdk + poetry run python tests/integration/harness_sdk.py test_delete_and_reingest_sample_file_sdk - name: Run SDK Retrieval working-directory: ./py diff --git a/docs/documentation/installation/light/docker.mdx b/docs/documentation/installation/light/docker.mdx index 2e03edcc8..203722a20 100644 --- a/docs/documentation/installation/light/docker.mdx +++ b/docs/documentation/installation/light/docker.mdx @@ -32,7 +32,7 @@ pip install r2r To start R2R with your local computer as the default LLM inference provider: ```bash - r2r serve --docker --config-name=light_local_llm + r2r serve --docker --config-name=local_llm ``` Then, in a separate terminal you will need to run Ollama to provide completions: ```bash diff --git a/py/tests/integration/harness_sdk.py b/py/tests/integration/harness_sdk.py index 76e5b33d1..b6670d9bf 100644 --- a/py/tests/integration/harness_sdk.py +++ b/py/tests/integration/harness_sdk.py @@ -114,7 +114,7 @@ def test_delete_and_reingest_sample_file_sdk(): # Delete the Aristotle document delete_response = client.delete( - {"document_id": {"$eq": "9fbe403b-c11c-5aae-8ade-ef22980c3ad1"}} + {"document_id": {"$eq": "3e157b3a-8469-51db-90d9-52e7d896b49b"}} ) # Check if the deletion was successful From f6683a675d68095571ca36c866ce46336054e956 Mon Sep 17 00:00:00 2001 From: emrgnt-cmplxty Date: Fri, 4 Oct 2024 17:54:37 -0700 Subject: [PATCH 28/30] update integration test --- .../integration-test-workflow-debian.yml | 11 +- py/core/main/api/auth_router.py | 10 +- py/core/main/api/ingestion_router.py | 13 - py/core/main/assembly/factory.py | 16 +- py/core/main/services/auth_service.py | 4 +- py/sdk/auth.py | 1 + py/tests/integration/harness_sdk.py | 271 ++++++++++++++++++ 7 files changed, 305 insertions(+), 21 deletions(-) diff --git a/.github/workflows/integration-test-workflow-debian.yml b/.github/workflows/integration-test-workflow-debian.yml index 1b5b1308c..5e518f3a7 100644 --- a/.github/workflows/integration-test-workflow-debian.yml +++ b/.github/workflows/integration-test-workflow-debian.yml @@ -90,7 +90,7 @@ jobs: poetry run python tests/integration/harness_cli.py test_rag_response_sample_file_cli poetry run python tests/integration/harness_cli.py test_rag_response_stream_sample_file_cli - - name: Run SDK Integration + - name: Run SDK Ingestion working-directory: ./py run: | poetry run python tests/integration/harness_sdk.py test_ingest_sample_file_sdk @@ -98,6 +98,7 @@ jobs: poetry run python tests/integration/harness_sdk.py test_document_overview_sample_file_sdk poetry run python tests/integration/harness_sdk.py test_document_chunks_sample_file_sdk poetry run python tests/integration/harness_sdk.py test_delete_and_reingest_sample_file_sdk + poetry run python tests/integration/harness_sdk.py test_ingest_sample_file_with_config_sdk - name: Run SDK Retrieval working-directory: ./py @@ -107,6 +108,14 @@ jobs: poetry run python tests/integration/harness_sdk.py test_rag_response_sample_file_sdk poetry run python tests/integration/harness_sdk.py test_rag_response_stream_sample_file_sdk + - name: Run SDK Auth + working-directory: ./py + run: | + poetry run python tests/integration/harness_sdk.py test_vector_search_sample_file_filter_sdk + poetry run python tests/integration/harness_sdk.py test_hybrid_search_sample_file_filter_sdk + poetry run python tests/integration/harness_sdk.py test_rag_response_sample_file_sdk + poetry run python tests/integration/harness_sdk.py test_rag_response_stream_sample_file_sdk + - name: Stop R2R server if: always() run: ps aux | grep "r2r serve" | awk '{print $2}' | xargs kill || true diff --git a/py/core/main/api/auth_router.py b/py/core/main/api/auth_router.py index a06db2590..0c8f3cff2 100644 --- a/py/core/main/api/auth_router.py +++ b/py/core/main/api/auth_router.py @@ -109,7 +109,8 @@ async def get_user_app( @self.router.put("/user", response_model=WrappedUserResponse) @self.base_endpoint async def put_user_app( - user_id: str = Body(None, description="ID of the user to update"), + id: UUID = Body(None, description="ID of the user to update"), + user_id: UUID = Body(None, description="ID of the user to update"), email: EmailStr | None = Body( None, description="Updated email address" ), @@ -128,11 +129,18 @@ async def put_user_app( This endpoint allows the authenticated user to update their profile information. """ + if is_superuser is not None and not auth_user.is_superuser: raise R2RException( "Only superusers can update the superuser status of a user", 403, ) + if not auth_user.is_superuser: + if not auth_user.id == user_id: + raise R2RException( + "Only superusers can update other users' information", + 403, + ) try: user_uuid = UUID(user_id) diff --git a/py/core/main/api/ingestion_router.py b/py/core/main/api/ingestion_router.py index 185ec6df0..adf63ba36 100644 --- a/py/core/main/api/ingestion_router.py +++ b/py/core/main/api/ingestion_router.py @@ -100,8 +100,6 @@ async def ingest_files_app( A valid user authentication token is required to access this endpoint, as regular users can only ingest files for their own access. More expansive collection permissioning is under development. """ - self._validate_ingestion_config(ingestion_config) - # Check if the user is a superuser if not auth_user.is_superuser: for metadata in metadatas or []: @@ -311,17 +309,6 @@ async def ingest_chunks_app( raw_message["document_id"] = str(document_id) return raw_message # type: ignore - @staticmethod - def _validate_ingestion_config(ingestion_config): - from ..assembly.factory import R2RProviderFactory - - if ingestion_config: - R2RProviderFactory.create_ingestion_provider(ingestion_config) - else: - logger.info( - "No ingestion config override provided. Using default." - ) - @staticmethod async def _process_files(files): import base64 diff --git a/py/core/main/assembly/factory.py b/py/core/main/assembly/factory.py index ec61dda16..acf1d914b 100644 --- a/py/core/main/assembly/factory.py +++ b/py/core/main/assembly/factory.py @@ -82,17 +82,23 @@ def create_crypto_provider( def create_ingestion_provider( ingestion_config: IngestionConfig, *args, **kwargs ) -> IngestionProvider: - config_dict = ingestion_config.model_dump() + + config_dict = ( + ingestion_config.model_dump() + if isinstance(ingestion_config, IngestionConfig) + else ingestion_config + ) + extra_fields = config_dict.pop("extra_fields", {}) - if ingestion_config.provider == "r2r": + if config_dict["provider"] == "r2r": from core.providers import R2RIngestionConfig, R2RIngestionProvider r2r_ingestion_config = R2RIngestionConfig( **config_dict, **extra_fields ) return R2RIngestionProvider(r2r_ingestion_config) - elif ingestion_config.provider in [ + elif config_dict["provider"] in [ "unstructured_local", "unstructured_api", ]: @@ -110,7 +116,7 @@ def create_ingestion_provider( ) else: raise ValueError( - f"Ingestion provider {ingestion_config.provider} not supported" + f"Ingestion provider {ingestion_config['provider']} not supported" ) @staticmethod @@ -292,7 +298,7 @@ async def create_providers( self.config.embedding, *args, **kwargs ) ) - + print("self.config.ingestion = ", self.config.ingestion) ingestion_provider = ( ingestion_provider_override or self.create_ingestion_provider( diff --git a/py/core/main/services/auth_service.py b/py/core/main/services/auth_service.py index 646b62a50..19ebd1da1 100644 --- a/py/core/main/services/auth_service.py +++ b/py/core/main/services/auth_service.py @@ -124,7 +124,9 @@ async def update_user( profile_picture: Optional[str] = None, ) -> UserResponse: user: UserResponse = ( - await self.providers.database.relational.get_user_by_id(user_id) + await self.providers.database.relational.get_user_by_id( + str(user_id) + ) ) if not user: raise R2RException(status_code=404, message="User not found") diff --git a/py/sdk/auth.py b/py/sdk/auth.py index fc2716649..35833b7fd 100644 --- a/py/sdk/auth.py +++ b/py/sdk/auth.py @@ -108,6 +108,7 @@ async def update_user( "bio": bio, "profile_picture": profile_picture, } + print("data = ", data) data = {k: v for k, v in data.items() if v is not None} return await client._make_request("PUT", "user", json=data) diff --git a/py/tests/integration/harness_sdk.py b/py/tests/integration/harness_sdk.py index b6670d9bf..1a2e51cdc 100644 --- a/py/tests/integration/harness_sdk.py +++ b/py/tests/integration/harness_sdk.py @@ -35,6 +35,32 @@ def test_ingest_sample_file_sdk(): print("~" * 100) +def test_ingest_sample_file_with_config_sdk(): + print("Testing: Ingest sample file 2") + file_paths = ["core/examples/data/aristotle_v2.txt"] + + ingest_response = client.ingest_files( + file_paths=file_paths, ingestion_config={"chunk_size": 4_096} + ) + + if not ingest_response["results"]: + print("Ingestion test failed") + sys.exit(1) + + document_id = ingest_response["results"][0]["document_id"] + + if document_id != "c3291abf-8a4e-5d9d-80fd-232ef6fd8526": + print("Ingestion test failed: Incorrect document ID") + sys.exit(1) + + if len(ingest_response["results"]) != 1: + print("Ingestion test failed: Incorrect number of results") + sys.exit(1) + + print("Ingestion with config successful") + print("~" * 100) + + def test_reingest_sample_file_sdk(): print("Testing: Ingest sample file SDK") file_paths = ["core/examples/data/uber_2021.pdf"] @@ -329,6 +355,251 @@ def test_agent_stream_sample_file_sdk(): print("~" * 100) +def test_user_registration_and_login(): + print("Testing: User registration and login") + + # Register a new user + user_result = client.register("user_test@example.com", "password123")[ + "results" + ] + + # Login immediately (assuming email verification is disabled) + login_results = client.login("user_test@example.com", "password123")[ + "results" + ] + + if "access_token" not in login_results: + print("User registration and login test failed") + sys.exit(1) + + if "refresh_token" not in login_results: + print("User registration and login test failed") + sys.exit(1) + + print("User registration and login test passed") + print("~" * 100) + + +def test_duplicate_user_registration(): + print("Testing: Duplicate user registration") + + # Register a new user + client.register("duplicate_test@example.com", "password123")["results"] + + # Attempt to register the same user again + try: + client.register("duplicate_test@example.com", "password123") + print( + "Duplicate user registration test failed: Expected an error but registration succeeded" + ) + sys.exit(1) + except Exception as e: + error_message = str(e) + if "User with this email already exists" not in error_message: + print( + f"Duplicate user registration test failed: Unexpected error - {error_message}" + ) + sys.exit(1) + else: + print("Duplicate user registration failed as expected") + + print("Duplicate user registration test passed") + print("~" * 100) + + +def test_token_refresh(): + print("Testing: Access token refresh") + client.login("user_test@example.com", "password123") + + refresh_result = client.refresh_access_token()["results"] + if "access_token" not in refresh_result: + print("Access token refresh test failed") + sys.exit(1) + + if "refresh_token" not in refresh_result: + print("Access token refresh test failed") + sys.exit(1) + + print("Access token refresh test passed") + print("~" * 100) + + +def test_user_document_management(): + print("Testing: User document management") + client.login("user_test@example.com", "password123") + + # Ingest a sample file for the logged-in user + ingestion_result = client.ingest_files( + ["core/examples/data/lyft_2021.pdf"] + )["results"] + + # Check the ingestion result + if not ingestion_result: + print("User document management test failed: Ingestion failed") + sys.exit(1) + + ingested_document = ingestion_result[0] + expected_ingestion_result = { + "message": "Ingestion task completed successfully.", + "task_id": None, + "document_id": lambda x: len(x) + == 36, # Check if document_id is a valid UUID + } + compare_result_fields(ingested_document, expected_ingestion_result) + + # Check the user's documents + documents_overview = client.documents_overview()["results"] + + if not documents_overview: + print( + "User document management test failed: No documents found in the overview" + ) + sys.exit(1) + + ingested_document_overview = documents_overview[0] + expected_document_overview = { + "id": ingested_document["document_id"], + "title": "lyft_2021.pdf", + "user_id": lambda x: len(x) == 36, # Check if user_id is a valid UUID + "type": "pdf", + "ingestion_status": "success", + "kg_extraction_status": "pending", + "version": "v0", + "collection_ids": lambda x: len(x) == 1 + and len(x[0]) == 36, # Check if collection_ids contains a valid UUID + "metadata": {"version": "v0"}, + } + compare_result_fields( + ingested_document_overview, expected_document_overview + ) + + print("User document management test passed") + print("~" * 100) + + +def test_user_search_and_rag(): + print("Testing: User search and RAG") + client.login("user_test@example.com", "password123") + + # Perform a search + search_query = "What was Lyft's revenue in 2021?" + search_result = client.search(query=search_query)["results"] + print(f"Search Result:\n{search_result}") + + # Check the search result + if not search_result["vector_search_results"]: + print("User search test failed: No search results found") + sys.exit(1) + + lead_search_result = search_result["vector_search_results"][0] + expected_search_result = { + "text": lambda x: "Lyft" in x and "revenue" in x and "2021" in x, + "score": lambda x: 0.5 <= x <= 1.0, + } + compare_result_fields(lead_search_result, expected_search_result) + + # Perform a RAG query + rag_query = "What was Lyft's total revenue in 2021 and how did it compare to the previous year?" + rag_result = client.rag(query=rag_query)["results"] + + # Check the RAG result + if not rag_result["completion"]["choices"]: + print("User RAG test failed: No RAG results found") + sys.exit(1) + + rag_response = rag_result["completion"]["choices"][0]["message"]["content"] + expected_rag_response = ( + lambda x: "Lyft" in x + and "revenue" in x + and "2021" in x + and "2020" in x + ) + + if not expected_rag_response(rag_response): + print( + f"User RAG test failed: Unexpected RAG response - {rag_response}" + ) + sys.exit(1) + + print("User search and RAG test passed") + print("~" * 100) + + +def test_user_password_management(): + print("Testing: User password management") + + # Test for duplicate user + client.login("duplicate_test@example.com", "password123") + + # Change password + client.change_password("password123", "new_password") + # Request password reset + client.request_password_reset("user_test@example.com") + + # Confirm password reset (after user receives reset token) + # reset_confirm_result = client.confirm_password_reset("reset_token_here", "password123") + # print(f"Reset Confirm Result:\n{reset_confirm_result}") + + print("User password management test passed") + print("~" * 100) + + +def test_user_profile_management(): + print("Testing: User profile management") + + client.register("test_user_123456@example.com", "password123") + client.login("test_user_123456@example.com", "password123") + + # Get user profile + profile = client.user()["results"] + print(f"User Profile:\n{profile}") + + # Update user profile + update_result = client.update_user( + user_id=str(profile["id"]), name="John Doe", bio="R2R enthusiast" + ) + print(f"Update User Result:\n{update_result}") + + print("User profile management test passed") + print("~" * 100) + + +def test_user_logout(): + print("Testing: User logout") + + logout_result = client.logout() + print(f"Logout Result:\n{logout_result}") + + print("User logout test passed") + print("~" * 100) + + +def test_superuser_capabilities(): + print("Testing: Superuser capabilities") + + # Login as admin + login_result = client.login("admin@example.com", "change_me_immediately") + print(f"Admin Login Result:\n{login_result}") + + # Access users overview + users_overview = client.users_overview() + print(f"Users Overview:\n{users_overview}") + + # Access system-wide logs + logs = client.logs() + print(f"System Logs:\n{logs}") + + # Perform analytics + analytics_result = client.analytics( + {"search_latencies": "search_latency"}, + {"search_latencies": ["basic_statistics", "search_latency"]}, + ) + print(f"Analytics Result:\n{analytics_result}") + + print("Superuser capabilities test passed") + print("~" * 100) + + if __name__ == "__main__": if len(sys.argv) < 2: print("Please specify a test function to run") From d149776ed1bf63d0551efe1aa9062e72eff8d4fd Mon Sep 17 00:00:00 2001 From: emrgnt-cmplxty Date: Fri, 4 Oct 2024 19:16:09 -0700 Subject: [PATCH 29/30] final user tests --- .../integration-test-workflow-debian.yml | 13 +++++++----- py/core/main/api/auth_router.py | 10 +-------- py/core/main/api/ingestion_router.py | 1 - py/core/main/assembly/factory.py | 2 +- py/tests/integration/harness_sdk.py | 21 ++++++++----------- 5 files changed, 19 insertions(+), 28 deletions(-) diff --git a/.github/workflows/integration-test-workflow-debian.yml b/.github/workflows/integration-test-workflow-debian.yml index 5e518f3a7..eb3adb6e4 100644 --- a/.github/workflows/integration-test-workflow-debian.yml +++ b/.github/workflows/integration-test-workflow-debian.yml @@ -106,15 +106,18 @@ jobs: poetry run python tests/integration/harness_sdk.py test_vector_search_sample_file_filter_sdk poetry run python tests/integration/harness_sdk.py test_hybrid_search_sample_file_filter_sdk poetry run python tests/integration/harness_sdk.py test_rag_response_sample_file_sdk - poetry run python tests/integration/harness_sdk.py test_rag_response_stream_sample_file_sdk - name: Run SDK Auth working-directory: ./py run: | - poetry run python tests/integration/harness_sdk.py test_vector_search_sample_file_filter_sdk - poetry run python tests/integration/harness_sdk.py test_hybrid_search_sample_file_filter_sdk - poetry run python tests/integration/harness_sdk.py test_rag_response_sample_file_sdk - poetry run python tests/integration/harness_sdk.py test_rag_response_stream_sample_file_sdk + poetry run python tests/integration/harness_sdk.py test_user_registration_and_login + poetry run python tests/integration/harness_sdk.py test_duplicate_user_registration + poetry run python tests/integration/harness_sdk.py test_token_refresh + poetry run python tests/integration/harness_sdk.py test_user_document_management + poetry run python tests/integration/harness_sdk.py test_user_search_and_rag + poetry run python tests/integration/harness_sdk.py test_user_password_management + poetry run python tests/integration/harness_sdk.py test_user_profile_management + poetry run python tests/integration/harness_sdk.py test_user_logout - name: Stop R2R server if: always() diff --git a/py/core/main/api/auth_router.py b/py/core/main/api/auth_router.py index 0c8f3cff2..edcb49b2e 100644 --- a/py/core/main/api/auth_router.py +++ b/py/core/main/api/auth_router.py @@ -109,7 +109,6 @@ async def get_user_app( @self.router.put("/user", response_model=WrappedUserResponse) @self.base_endpoint async def put_user_app( - id: UUID = Body(None, description="ID of the user to update"), user_id: UUID = Body(None, description="ID of the user to update"), email: EmailStr | None = Body( None, description="Updated email address" @@ -142,15 +141,8 @@ async def put_user_app( 403, ) - try: - user_uuid = UUID(user_id) - except ValueError: - raise R2RException( - status_code=400, message="Invalid user ID format." - ) - return await self.service.update_user( - user_id=user_uuid, + user_id=user_id, email=email, is_superuser=is_superuser, name=name, diff --git a/py/core/main/api/ingestion_router.py b/py/core/main/api/ingestion_router.py index adf63ba36..53eab945e 100644 --- a/py/core/main/api/ingestion_router.py +++ b/py/core/main/api/ingestion_router.py @@ -195,7 +195,6 @@ async def update_files_app( A valid user authentication token is required to access this endpoint, as regular users can only update their own files. More expansive collection permissioning is under development. """ - self._validate_ingestion_config(ingestion_config) if not auth_user.is_superuser: for metadata in metadatas or []: if "user_id" in metadata and metadata["user_id"] != str( diff --git a/py/core/main/assembly/factory.py b/py/core/main/assembly/factory.py index acf1d914b..0108bf542 100644 --- a/py/core/main/assembly/factory.py +++ b/py/core/main/assembly/factory.py @@ -116,7 +116,7 @@ def create_ingestion_provider( ) else: raise ValueError( - f"Ingestion provider {ingestion_config['provider']} not supported" + f"Ingestion provider {ingestion_config.provider} not supported" ) @staticmethod diff --git a/py/tests/integration/harness_sdk.py b/py/tests/integration/harness_sdk.py index 1a2e51cdc..7d476c8a1 100644 --- a/py/tests/integration/harness_sdk.py +++ b/py/tests/integration/harness_sdk.py @@ -3,7 +3,7 @@ from r2r import R2RClient -client = R2RClient() +client = R2RClient("http://localhost:7274") def compare_result_fields(result, expected_fields): @@ -484,7 +484,6 @@ def test_user_search_and_rag(): # Perform a search search_query = "What was Lyft's revenue in 2021?" search_result = client.search(query=search_query)["results"] - print(f"Search Result:\n{search_result}") # Check the search result if not search_result["vector_search_results"]: @@ -547,19 +546,17 @@ def test_user_password_management(): def test_user_profile_management(): print("Testing: User profile management") - client.register("test_user_123456@example.com", "password123") - client.login("test_user_123456@example.com", "password123") + client.register("user_test123@example.com", "password123") + client.login("user_test123@example.com", "password123") # Get user profile profile = client.user()["results"] - print(f"User Profile:\n{profile}") # Update user profile update_result = client.update_user( user_id=str(profile["id"]), name="John Doe", bio="R2R enthusiast" ) - print(f"Update User Result:\n{update_result}") - + assert update_result["results"]["name"] == "John Doe" print("User profile management test passed") print("~" * 100) @@ -567,9 +564,10 @@ def test_user_profile_management(): def test_user_logout(): print("Testing: User logout") + client.login("user_test@example.com", "password123") logout_result = client.logout() - print(f"Logout Result:\n{logout_result}") + assert logout_result["results"]["message"] == "Logged out successfully" print("User logout test passed") print("~" * 100) @@ -579,22 +577,21 @@ def test_superuser_capabilities(): # Login as admin login_result = client.login("admin@example.com", "change_me_immediately") - print(f"Admin Login Result:\n{login_result}") # Access users overview users_overview = client.users_overview() - print(f"Users Overview:\n{users_overview}") + assert users_overview["total_entries"] > 0 # Access system-wide logs logs = client.logs() - print(f"System Logs:\n{logs}") + assert len(logs["results"]) > 0 # Perform analytics analytics_result = client.analytics( {"search_latencies": "search_latency"}, {"search_latencies": ["basic_statistics", "search_latency"]}, ) - print(f"Analytics Result:\n{analytics_result}") + assert analytics_result["results"]["analytics_data"]["search_latencies"] print("Superuser capabilities test passed") print("~" * 100) From 8f9fde0f6d2154c651654caa633c8a364908a1f4 Mon Sep 17 00:00:00 2001 From: emrgnt-cmplxty Date: Fri, 4 Oct 2024 19:17:42 -0700 Subject: [PATCH 30/30] final user tests --- py/tests/integration/harness_sdk.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py/tests/integration/harness_sdk.py b/py/tests/integration/harness_sdk.py index 7d476c8a1..b47c20a37 100644 --- a/py/tests/integration/harness_sdk.py +++ b/py/tests/integration/harness_sdk.py @@ -3,7 +3,7 @@ from r2r import R2RClient -client = R2RClient("http://localhost:7274") +client = R2RClient("http://localhost:7272") def compare_result_fields(result, expected_fields):