diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 65ca8f35..c5382f47 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -54,7 +54,7 @@ } }, // Use 'postCreateCommand' to run commands after the container is created. - "postCreateCommand": "pip install -r requirements-dev.txt && pip install -e src", + "postCreateCommand": "pip install -r requirements-dev.txt && pip install -e src/backend", // Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. "remoteUser": "vscode" } diff --git a/.github/workflows/app-tests.yaml b/.github/workflows/app-tests.yaml index 3ca63843..ec3e5e1b 100755 --- a/.github/workflows/app-tests.yaml +++ b/.github/workflows/app-tests.yaml @@ -55,12 +55,12 @@ jobs: python -m pip install -r requirements-dev.txt - name: Install app as editable app run: | - python -m pip install -e src + python -m pip install -e src/backend - name: Setup local database with seed data run: | cp .env.sample .env - python ./src/fastapi_app/setup_postgres_database.py - python ./src/fastapi_app/setup_postgres_seeddata.py + python ./src/backend/fastapi_app/setup_postgres_database.py + python ./src/backend/fastapi_app/setup_postgres_seeddata.py - name: Setup node uses: actions/setup-node@v4 with: diff --git a/README.md b/README.md index cc59e2d2..882181c6 100644 --- a/README.md +++ b/README.md @@ -128,9 +128,9 @@ Since the local app uses OpenAI models, you should first deploy it for the optim 1. Run these commands to install the web app as a local package (named `fastapi_app`), set up the local database, and seed it with test data: ```bash - python3 -m pip install -e src - python ./src/fastapi_app/setup_postgres_database.py - python ./src/fastapi_app/setup_postgres_seeddata.py + python3 -m pip install -e src/backend + python ./src/backend/fastapi_app/setup_postgres_database.py + python ./src/backend/fastapi_app/setup_postgres_seeddata.py ``` 2. Build the frontend: @@ -139,7 +139,7 @@ Since the local app uses OpenAI models, you should first deploy it for the optim cd src/frontend npm install npm run build - cd ../.. + cd ../../ ``` There must be an initial build of static assets before running the backend, since the backend serves static files from the `src/static` directory. diff --git a/azure.yaml b/azure.yaml index cd48df0a..1d65f443 100644 --- a/azure.yaml +++ b/azure.yaml @@ -4,7 +4,7 @@ metadata: template: rag-postgres-openai-python@0.0.1 services: web: - project: ./src + project: ./src/backend language: py module: web host: containerapp diff --git a/requirements-dev.txt b/requirements-dev.txt index 5b2e11a0..bfe6862b 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,4 +1,4 @@ --r src/requirements.txt +-r src/backend/requirements.txt ruff pre-commit pip-tools diff --git a/scripts/load_python_env.sh b/scripts/load_python_env.sh index 58d7a045..d92b58bb 100755 --- a/scripts/load_python_env.sh +++ b/scripts/load_python_env.sh @@ -4,5 +4,5 @@ echo 'Creating Python virtual environment in .venv...' python3 -m venv .venv echo 'Installing dependencies from "requirements.txt" into virtual environment (in quiet mode)...' -.venv/bin/python -m pip --quiet --disable-pip-version-check install -e src +.venv/bin/python -m pip --quiet --disable-pip-version-check install -e src/backend .venv/bin/python -m pip --quiet --disable-pip-version-check install -r requirements-dev.txt diff --git a/scripts/setup_postgres_azurerole.ps1 b/scripts/setup_postgres_azurerole.ps1 index 5a7434f7..9a6d2562 100644 --- a/scripts/setup_postgres_azurerole.ps1 +++ b/scripts/setup_postgres_azurerole.ps1 @@ -7,4 +7,4 @@ if ([string]::IsNullOrEmpty($POSTGRES_HOST) -or [string]::IsNullOrEmpty($POSTGRE exit 1 } -python ./src/fastapi_app/setup_postgres_azurerole.py --host $POSTGRES_HOST --username $POSTGRES_USERNAME --app-identity-name $APP_IDENTITY_NAME \ No newline at end of file +python ./src/backend/fastapi_app/setup_postgres_azurerole.py --host $POSTGRES_HOST --username $POSTGRES_USERNAME --app-identity-name $APP_IDENTITY_NAME \ No newline at end of file diff --git a/scripts/setup_postgres_azurerole.sh b/scripts/setup_postgres_azurerole.sh index d750ddc8..64b065f4 100755 --- a/scripts/setup_postgres_azurerole.sh +++ b/scripts/setup_postgres_azurerole.sh @@ -9,4 +9,4 @@ fi . ./scripts/load_python_env.sh -.venv/bin/python ./src/fastapi_app/setup_postgres_azurerole.py --host $POSTGRES_HOST --username $POSTGRES_USERNAME --app-identity-name $APP_IDENTITY_NAME +.venv/bin/python ./src/backend/fastapi_app/setup_postgres_azurerole.py --host $POSTGRES_HOST --username $POSTGRES_USERNAME --app-identity-name $APP_IDENTITY_NAME diff --git a/scripts/setup_postgres_database.ps1 b/scripts/setup_postgres_database.ps1 index 11ae8976..a81b15cd 100644 --- a/scripts/setup_postgres_database.ps1 +++ b/scripts/setup_postgres_database.ps1 @@ -7,4 +7,4 @@ if ([string]::IsNullOrEmpty($POSTGRES_HOST) -or [string]::IsNullOrEmpty($POSTGRE exit 1 } -python ./src/fastapi_app/setup_postgres_database.py --host $POSTGRES_HOST --username $POSTGRES_USERNAME --password $POSTGRES_PASSWORD \ No newline at end of file +python ./backend/src/fastapi_app/setup_postgres_database.py --host $POSTGRES_HOST --username $POSTGRES_USERNAME --password $POSTGRES_PASSWORD \ No newline at end of file diff --git a/scripts/setup_postgres_database.sh b/scripts/setup_postgres_database.sh index add480ca..8f0e9df6 100755 --- a/scripts/setup_postgres_database.sh +++ b/scripts/setup_postgres_database.sh @@ -4,4 +4,4 @@ POSTGRES_DATABASE=$(azd env get-values | grep POSTGRES_DATABASE | sed 's/="/=/' . ./scripts/load_python_env.sh -.venv/bin/python ./src/fastapi_app/setup_postgres_database.py --host $POSTGRES_HOST --username $POSTGRES_USERNAME --database $POSTGRES_DATABASE +.venv/bin/python ./src/backend/fastapi_app/setup_postgres_database.py --host $POSTGRES_HOST --username $POSTGRES_USERNAME --database $POSTGRES_DATABASE diff --git a/scripts/setup_postgres_seeddata.ps1 b/scripts/setup_postgres_seeddata.ps1 index b6c7400d..bb56f2b8 100644 --- a/scripts/setup_postgres_seeddata.ps1 +++ b/scripts/setup_postgres_seeddata.ps1 @@ -7,4 +7,4 @@ if ([string]::IsNullOrEmpty($POSTGRES_HOST) -or [string]::IsNullOrEmpty($POSTGRE exit 1 } -python ./src/fastapi_app/setup_postgres_seeddata.py --host $POSTGRES_HOST --username $POSTGRES_USERNAME --password $POSTGRES_PASSWORD \ No newline at end of file +python ./src/backend/fastapi_app/setup_postgres_seeddata.py --host $POSTGRES_HOST --username $POSTGRES_USERNAME --password $POSTGRES_PASSWORD \ No newline at end of file diff --git a/scripts/setup_postgres_seeddata.sh b/scripts/setup_postgres_seeddata.sh index 0422d389..b88ff396 100755 --- a/scripts/setup_postgres_seeddata.sh +++ b/scripts/setup_postgres_seeddata.sh @@ -4,4 +4,4 @@ POSTGRES_DATABASE=$(azd env get-values | grep POSTGRES_DATABASE | sed 's/="/=/' . ./scripts/load_python_env.sh -.venv/bin/python ./src/fastapi_app/setup_postgres_seeddata.py --host $POSTGRES_HOST --username $POSTGRES_USERNAME --database $POSTGRES_DATABASE +.venv/bin/python ./src/backend/fastapi_app/setup_postgres_seeddata.py --host $POSTGRES_HOST --username $POSTGRES_USERNAME --database $POSTGRES_DATABASE diff --git a/src/.dockerignore b/src/backend/.dockerignore similarity index 100% rename from src/.dockerignore rename to src/backend/.dockerignore diff --git a/src/Dockerfile b/src/backend/Dockerfile similarity index 100% rename from src/Dockerfile rename to src/backend/Dockerfile diff --git a/src/entrypoint.sh b/src/backend/entrypoint.sh similarity index 100% rename from src/entrypoint.sh rename to src/backend/entrypoint.sh diff --git a/src/fastapi_app/__init__.py b/src/backend/fastapi_app/__init__.py similarity index 100% rename from src/fastapi_app/__init__.py rename to src/backend/fastapi_app/__init__.py diff --git a/src/fastapi_app/api_models.py b/src/backend/fastapi_app/api_models.py similarity index 100% rename from src/fastapi_app/api_models.py rename to src/backend/fastapi_app/api_models.py diff --git a/src/fastapi_app/dependencies.py b/src/backend/fastapi_app/dependencies.py similarity index 100% rename from src/fastapi_app/dependencies.py rename to src/backend/fastapi_app/dependencies.py diff --git a/src/fastapi_app/embeddings.py b/src/backend/fastapi_app/embeddings.py similarity index 100% rename from src/fastapi_app/embeddings.py rename to src/backend/fastapi_app/embeddings.py diff --git a/src/fastapi_app/openai_clients.py b/src/backend/fastapi_app/openai_clients.py similarity index 100% rename from src/fastapi_app/openai_clients.py rename to src/backend/fastapi_app/openai_clients.py diff --git a/src/fastapi_app/postgres_engine.py b/src/backend/fastapi_app/postgres_engine.py similarity index 100% rename from src/fastapi_app/postgres_engine.py rename to src/backend/fastapi_app/postgres_engine.py diff --git a/src/fastapi_app/postgres_models.py b/src/backend/fastapi_app/postgres_models.py similarity index 100% rename from src/fastapi_app/postgres_models.py rename to src/backend/fastapi_app/postgres_models.py diff --git a/src/fastapi_app/postgres_searcher.py b/src/backend/fastapi_app/postgres_searcher.py similarity index 100% rename from src/fastapi_app/postgres_searcher.py rename to src/backend/fastapi_app/postgres_searcher.py diff --git a/src/fastapi_app/prompts/answer.txt b/src/backend/fastapi_app/prompts/answer.txt similarity index 100% rename from src/fastapi_app/prompts/answer.txt rename to src/backend/fastapi_app/prompts/answer.txt diff --git a/src/fastapi_app/prompts/query.txt b/src/backend/fastapi_app/prompts/query.txt similarity index 100% rename from src/fastapi_app/prompts/query.txt rename to src/backend/fastapi_app/prompts/query.txt diff --git a/src/fastapi_app/query_rewriter.py b/src/backend/fastapi_app/query_rewriter.py similarity index 100% rename from src/fastapi_app/query_rewriter.py rename to src/backend/fastapi_app/query_rewriter.py diff --git a/src/fastapi_app/rag_advanced.py b/src/backend/fastapi_app/rag_advanced.py similarity index 100% rename from src/fastapi_app/rag_advanced.py rename to src/backend/fastapi_app/rag_advanced.py diff --git a/src/fastapi_app/rag_simple.py b/src/backend/fastapi_app/rag_simple.py similarity index 100% rename from src/fastapi_app/rag_simple.py rename to src/backend/fastapi_app/rag_simple.py diff --git a/src/fastapi_app/routes/api_routes.py b/src/backend/fastapi_app/routes/api_routes.py similarity index 100% rename from src/fastapi_app/routes/api_routes.py rename to src/backend/fastapi_app/routes/api_routes.py diff --git a/src/fastapi_app/routes/frontend_routes.py b/src/backend/fastapi_app/routes/frontend_routes.py similarity index 100% rename from src/fastapi_app/routes/frontend_routes.py rename to src/backend/fastapi_app/routes/frontend_routes.py diff --git a/src/fastapi_app/seed_data.json b/src/backend/fastapi_app/seed_data.json similarity index 100% rename from src/fastapi_app/seed_data.json rename to src/backend/fastapi_app/seed_data.json diff --git a/src/fastapi_app/setup_postgres_azurerole.py b/src/backend/fastapi_app/setup_postgres_azurerole.py similarity index 100% rename from src/fastapi_app/setup_postgres_azurerole.py rename to src/backend/fastapi_app/setup_postgres_azurerole.py diff --git a/src/fastapi_app/setup_postgres_database.py b/src/backend/fastapi_app/setup_postgres_database.py similarity index 100% rename from src/fastapi_app/setup_postgres_database.py rename to src/backend/fastapi_app/setup_postgres_database.py diff --git a/src/fastapi_app/setup_postgres_seeddata.py b/src/backend/fastapi_app/setup_postgres_seeddata.py similarity index 100% rename from src/fastapi_app/setup_postgres_seeddata.py rename to src/backend/fastapi_app/setup_postgres_seeddata.py diff --git a/src/fastapi_app/update_embeddings.py b/src/backend/fastapi_app/update_embeddings.py similarity index 100% rename from src/fastapi_app/update_embeddings.py rename to src/backend/fastapi_app/update_embeddings.py diff --git a/src/gunicorn.conf.py b/src/backend/gunicorn.conf.py similarity index 100% rename from src/gunicorn.conf.py rename to src/backend/gunicorn.conf.py diff --git a/src/pyproject.toml b/src/backend/pyproject.toml similarity index 100% rename from src/pyproject.toml rename to src/backend/pyproject.toml diff --git a/src/requirements.txt b/src/backend/requirements.txt similarity index 100% rename from src/requirements.txt rename to src/backend/requirements.txt diff --git a/src/frontend/vite.config.ts b/src/frontend/vite.config.ts index cb70c752..9a0b6141 100644 --- a/src/frontend/vite.config.ts +++ b/src/frontend/vite.config.ts @@ -5,7 +5,7 @@ import react from "@vitejs/plugin-react"; export default defineConfig({ plugins: [react()], build: { - outDir: "../static", + outDir: "../backend/static", emptyOutDir: true, sourcemap: true, rollupOptions: { diff --git a/tests/conftest.py b/tests/conftest.py index d503fd3d..6dffdb5b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -84,7 +84,7 @@ async def create_and_seed_db(): @pytest_asyncio.fixture(scope="session") async def app(mock_session_env): """Create a FastAPI app.""" - if not Path("src/static/").exists(): + if not Path("src/backend/static/").exists(): pytest.skip("Please generate frontend files first!") app = create_app(testing=True) await create_and_seed_db() diff --git a/tests/mocks.py b/tests/mocks.py index 172a4ed1..2c84ef06 100644 --- a/tests/mocks.py +++ b/tests/mocks.py @@ -1,22 +1,34 @@ -from collections import namedtuple +from typing import Any -from azure.core.credentials import TokenCredential - -MockToken = namedtuple("MockToken", ["token", "expires_on"]) +from azure.core.credentials import AccessToken, TokenCredential class MockAzureCredential(TokenCredential): - def get_token(self, uri): - return MockToken("", 9999999999) + def get_token( + self, + *scopes: str, + claims: str | None = None, + tenant_id: str | None = None, + enable_cae: bool = False, + **kwargs: Any, + ) -> AccessToken: + return AccessToken("", 9999999999) class MockAzureCredentialExpired(TokenCredential): def __init__(self): self.access_number = 0 - async def get_token(self, uri): + def get_token( + self, + *scopes: str, + claims: str | None = None, + tenant_id: str | None = None, + enable_cae: bool = False, + **kwargs: Any, + ) -> AccessToken: self.access_number += 1 if self.access_number == 1: - return MockToken("", 0) + return AccessToken("", 0) else: - return MockToken("", 9999999999) + return AccessToken("", 9999999999) diff --git a/tests/test_frontend_routes.py b/tests/test_frontend_routes.py index 10bf4ec4..52ca8618 100644 --- a/tests/test_frontend_routes.py +++ b/tests/test_frontend_routes.py @@ -8,7 +8,7 @@ async def test_index(test_client): """test the index route""" response = test_client.get("/") - html_index_file_path = "src/static/index.html" + html_index_file_path = "src/backend/static/index.html" with open(html_index_file_path, "rb") as f: html_index_file = f.read() @@ -23,7 +23,7 @@ async def test_favicon(test_client): """test the favicon route""" response = test_client.get("/favicon.ico") - favicon_file_path = "src/static/favicon.ico" + favicon_file_path = "src/backend/static/favicon.ico" with open(favicon_file_path, "rb") as f: favicon_file = f.read() @@ -46,7 +46,7 @@ async def test_assets_non_existent_404(test_client): @pytest.mark.asyncio async def test_assets(test_client): """test the assets route with an existing file""" - assets_dir_path = "src/static/assets" + assets_dir_path = "src/backend/static/assets" assets_file_path = os.listdir(assets_dir_path)[0] with open(os.path.join(assets_dir_path, assets_file_path), "rb") as f: