diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000000..ecb8828dce --- /dev/null +++ b/.dockerignore @@ -0,0 +1,15 @@ +venv +.venv +.venv-* +node_modules +app/frontend/node_modules +.git +.gitignore +docs +data +tests +*.pyc +__pycache__ +dist +build +*.log diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 9a9fe8e1b2..272d141159 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -1,51 +1,57 @@ -# Adding new data -New files should be added to the `data` folder, and then either run scripts/prepdocs.sh or scripts/prepdocs.ps1 to ingest the data. +# Copilot & AI Agent Instructions for This Codebase -# Adding a new azd environment variable +This project is a RAG (Retrieval-Augmented Generation) chat app using Azure OpenAI and Azure AI Search, with a Python (Quart) backend and a React (Vite/TypeScript) frontend. It is designed for rapid iteration, Azure deployment, and extensibility. These instructions guide AI coding agents to be productive and follow project conventions. -An azd environment variable is stored by the azd CLI for each environment. It is passed to the "azd up" command and can configure both provisioning options and application settings. -When adding new azd environment variables, update: +## Architecture Overview -1. infra/main.parameters.json : Add the new parameter with a Bicep-friendly variable name and map to the new environment variable -1. infra/main.bicep: Add the new Bicep parameter at the top, and add it to the `appEnvVariables` object -1. azure.yaml: Add the new environment variable under pipeline config section -1. .azdo/pipelines/azure-dev.yml: Add the new environment variable under `env` section -1. .github/workflows/azure-dev.yml: Add the new environment variable under `env` section +- **Backend**: `app/backend` (Quart, Python) + - `approaches/`: Pluggable RAG strategies (e.g., `retrievethenread.py`, `chatreadretrieveread.py`) + - `app.py`: Main entry point +- **Frontend**: `app/frontend` (React, Vite, TypeScript) + - `src/api/`: API client + - `src/components/`: UI components + - `src/locales/`: i18n translations (edit all languages for new UI strings) +- **Infra**: `infra/` (Bicep templates, `azure.yaml`) +- **Data**: `data/` (documents for ingestion) +- **Tests**: `tests/` (pytest, Playwright e2e) -# Adding a new setting to "Developer Settings" in RAG app +See `docs/architecture.md` for diagrams and data flow. -When adding a new developer setting, update: +## Key Workflows -* frontend: - * app/frontend/src/api/models.ts : Add to ChatAppRequestOverrides - * app/frontend/src/components/Settings.tsx : Add a UI element for the setting - * app/frontend/src/locales/*/translations.json: Add a translation for the setting label/tooltip for all languages - * app/frontend/src/pages/chat/Chat.tsx: Add the setting to the component, pass it to Settings - * app/frontend/src/pages/ask/Ask.tsx: Add the setting to the component, pass it to Settings +- **Local Dev**: Use VS Code Dev Containers or Codespaces for pre-configured environments. See `docs/localdev.md` for hot reloading, debug, and task usage. + - Start dev servers: Use the VS Code "Development" task or run `app/start.sh` (runs both frontend and backend with hot reload). +- **Azure Deployment**: Use `azd up` to provision infra and deploy code. Use `azd deploy` to redeploy code only. See `README.md` and `docs/azd.md`. +- **Data Ingestion**: Add files to `data/`, then run `scripts/prepdocs.sh` to ingest. +- **Testing**: All tests in `tests/` (pytest). E2E tests in `e2e.py` (Playwright, mocks backend). Activate `.venv` before running tests. -* backend: - * app/backend/approaches/chatreadretrieveread.py : Retrieve from overrides parameter - * app/backend/approaches/retrievethenread.py : Retrieve from overrides parameter - * app/backend/app.py: Some settings may need to be sent down in the /config route. +## Project-Specific Conventions -# When adding tests for a new feature: +- **Adding azd env vars**: Update all of: + 1. `infra/main.parameters.json` (add param) + 2. `infra/main.bicep` (add param, wire to `appEnvVariables`) + 3. `azure.yaml` (pipeline config) + 4. `.azdo/pipelines/azure-dev.yml` and `.github/workflows/azure-dev.yml` (env section) +- **Adding Developer Settings**: + - Frontend: Update `src/api/models.ts`, `components/Settings.tsx`, all `locales/*/translation.json`, and pass through `pages/chat/Chat.tsx` and `pages/ask/Ask.tsx`. + - Backend: Update `approaches/chatreadretrieveread.py`, `approaches/retrievethenread.py`, and `app.py` as needed. +- **Tests**: Add e2e for UI, integration for API, unit for functions. Use `conftest.py` for mocks. +- **Pull Requests**: Follow `PULL_REQUEST_TEMPLATE.md`. -All tests are in the `tests` folder and use the pytest framework. -There are three styles of tests: +## Integration & Patterns -* e2e tests: These use playwright to run the app in a browser and test the UI end-to-end. They are in e2e.py and they mock the backend using the snapshots from the app tests. -* app integration tests: Mostly in test_app.py, these test the app's API endpoints and use mocks for services like Azure OpenAI and Azure Search. -* unit tests: The rest of the tests are unit tests that test individual functions and methods. They are in test_*.py files. +- **Backend/Frontend API**: REST endpoints defined in backend, consumed via `src/api/`. +- **RAG Approaches**: Add new strategies in `app/backend/approaches/` and register in `app.py`. +- **Internationalization**: All UI strings must be added to every language in `src/locales/`. +- **Infra**: All infra changes must be reflected in both Bicep and pipeline config files. -When adding a new feature, add tests for it in the appropriate file. -If the feature is a UI element, add an e2e test for it. -If it is an API endpoint, add an app integration test for it. -If it is a function or method, add a unit test for it. -Use mocks from conftest.py to mock external services. +## References -When you're running tests, make sure you activate the .venv virtual environment first: +- [README.md](../README.md) — Quickstart, deployment, and dev environment +- [docs/architecture.md](../docs/architecture.md) — Architecture diagrams and explanation +- [docs/localdev.md](../docs/localdev.md) — Local dev, debugging, and tasks -```bash -source .venv/bin/activate -``` +> **Nota:** Mantenha os links de referência acima atualizados conforme a estrutura do projeto. Se mover arquivos como AGENTS.md, ajuste o caminho aqui. + +Keep this file up to date with any changes to workflows or conventions. diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 5afef11fda..9276c83b28 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -4,6 +4,7 @@ "ms-azuretools.vscode-bicep", "ms-python.python", "esbenp.prettier-vscode", - "DavidAnson.vscode-markdownlint" + "DavidAnson.vscode-markdownlint", + "github.copilot-chat" ] } diff --git a/.vscode/launch.json b/.vscode/launch.json index 46bd4f00d4..b7c9783d72 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,53 +1,56 @@ { - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "name": "Backend (Python)", - "type": "debugpy", - "request": "launch", - "module": "quart", - "cwd": "${workspaceFolder}/app/backend", - "python": "${workspaceFolder}/.venv/bin/python", - "env": { - "QUART_APP": "main:app", - "QUART_ENV": "development", - "QUART_DEBUG": "0", - // Set this to "no-override" if you want env vars here to override AZD env vars - "LOADING_MODE_FOR_AZD_ENV_VARS": "override" - }, - "args": [ - "run", - "--no-reload", - "-p 50505" - ], - "console": "integratedTerminal", - "justMyCode": false - }, - { - "name": "Frontend", - "type": "node-terminal", - "request": "launch", - "command": "npm run dev", - "cwd": "${workspaceFolder}/app/frontend", - }, - { - "name": "Tests (Python)", - "type": "debugpy", - "request": "launch", - "program": "${file}", - "purpose": ["debug-test"], - "console": "integratedTerminal", - "justMyCode": false - } - ], - "compounds": [ - { - "name": "Frontend & Backend", - "configurations": ["Backend (Python)", "Frontend"], - "stopAll": true - } - ] + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Python Debugger: Current File", + "type": "debugpy", + "request": "launch", + "program": "${file}", + "console": "integratedTerminal" + }, + { + "name": "Backend (Python)", + "type": "debugpy", + "request": "launch", + "module": "quart", + "cwd": "${workspaceFolder}/app/backend", + "python": "${workspaceFolder}/.venv/bin/python", + "env": { + "QUART_APP": "main:app", + "QUART_ENV": "development", + "QUART_DEBUG": "0", + // Set this to "no-override" if you want env vars here to override AZD env vars + "LOADING_MODE_FOR_AZD_ENV_VARS": "override" + }, + "args": ["run", "--no-reload", "-p 50505"], + "console": "integratedTerminal", + "justMyCode": false + }, + { + "name": "Frontend", + "type": "node-terminal", + "request": "launch", + "command": "npm run dev", + "cwd": "${workspaceFolder}/app/frontend" + }, + { + "name": "Tests (Python)", + "type": "debugpy", + "request": "launch", + "program": "${file}", + "purpose": ["debug-test"], + "console": "integratedTerminal", + "justMyCode": false + } + ], + "compounds": [ + { + "name": "Frontend & Backend", + "configurations": ["Backend (Python)", "Frontend"], + "stopAll": true + } + ] } diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000000..767757e3da --- /dev/null +++ b/Dockerfile @@ -0,0 +1,30 @@ +FROM python:3.11-slim + +ENV PYTHONDONTWRITEBYTECODE=1 \ + PYTHONUNBUFFERED=1 + +WORKDIR /app + +# install system deps +RUN apt-get update \ + && apt-get install -y --no-install-recommends curl build-essential gcc libpq-dev \ + && rm -rf /var/lib/apt/lists/* + +# copy only what's needed for the backend +COPY app/backend/ ./backend/ +COPY pyproject.toml ./ +COPY requirements-dev.txt ./ + +WORKDIR /app/backend + +# install python deps +RUN python -m venv /opt/venv +ENV PATH="/opt/venv/bin:$PATH" +RUN pip install --upgrade pip setuptools wheel +RUN if [ -f requirements.txt ]; then pip install --no-cache-dir -r requirements.txt; fi + +EXPOSE 50505 + +ENV PORT=50505 + +CMD ["python", "-m", "quart", "--app", "main:app", "run", "--host", "0.0.0.0", "--port", "50505"] diff --git a/docs/run-mcp.md b/docs/run-mcp.md new file mode 100644 index 0000000000..92552126e4 --- /dev/null +++ b/docs/run-mcp.md @@ -0,0 +1,65 @@ +# Run the MCP (backend) server + +This document explains how to run only the backend (MCP/SSE) server locally or inside Docker. The backend exposes the SSE endpoint `/chat/stream` which can be used by an external connector. + +Prerequisites +- Python 3.10+ (for local run) +- Docker (optional) +- cloudflared (optional) to create a public tunnel + +## Option A — Run locally (recommended) + +From the repository root: + +```bash +./run_mcp.sh 50505 +``` + +This will: +- create `.venv` if not present +- install backend requirements from `app/backend/requirements.txt` +- start the Quart backend on `0.0.0.0:50505` + +Test endpoints: + +```bash +curl http://localhost:50505/config +``` + +SSE endpoint (use this for connectors): + +``` +http://localhost:50505/chat/stream +``` + +## Option B — Run with Docker + +Build image: + +```bash +docker build -t azure-search-mcp . +``` + +Run container: + +```bash +docker run -d --name azure-search-mcp -p 50505:50505 azure-search-mcp +``` + +Then the same endpoints are available on the host. + +## Expose a public HTTPS tunnel (Cloudflare Tunnel) + +Install `cloudflared` and run: + +```bash +cloudflared tunnel --url http://localhost:50505 +``` + +The command prints a public URL like `https://xxxx.trycloudflare.com`. Use the SSE path when registering the connector: + +``` +https://xxxx.trycloudflare.com/chat/stream +``` + +Note: if your connector expects a different path (e.g., `/sse`), create a small proxy or add a redirect handler in `app/backend/app.py`. diff --git a/run_mcp.sh b/run_mcp.sh new file mode 100644 index 0000000000..bfaa3a342c --- /dev/null +++ b/run_mcp.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Lightweight runner for the MCP backend (Quart) +# Usage: ./run_mcp.sh [port] + +ROOT_DIR="$(cd "$(dirname "$0")" && pwd)" +VENV_DIR="$ROOT_DIR/.venv" +PORT=${1:-50505} + +if [ ! -d "$VENV_DIR" ]; then + echo "Creating virtualenv at $VENV_DIR" + python3 -m venv "$VENV_DIR" +fi + +source "$VENV_DIR/bin/activate" +pip install --upgrade pip + +if [ -f "$ROOT_DIR/app/backend/requirements.txt" ]; then + pip install -r "$ROOT_DIR/app/backend/requirements.txt" +fi + +cd "$ROOT_DIR/app/backend" +echo "Starting Quart backend on 0.0.0.0:$PORT" +exec "$VENV_DIR/bin/python" -m quart --app main:app run --host 0.0.0.0 --port "$PORT" --reload