bsovran opened a new pull request, #42805: URL: https://github.com/apache/superset/pull/42805
<!-- Suggested PR title (conventional commits): feat(ai): add an opt-in AI assistant for natural-language data questions --> ### SUMMARY Adds an AI assistant behind the `AI_ASSISTANT` feature flag, off by default. A user can ask questions about the dashboard, chart or query in front of them and get an answer grounded in the data they already have access to. Architecture, in layers that can each be replaced by configuration: - **Provider seam** (`AI_LLM_PROVIDER_CLASS`): no vendor name, model identifier, base URL or credential appears in core. Ships an OpenAI-compatible and an Anthropic provider behind optional extras, so a private gateway or a self-hosted model is configuration rather than a fork. - **Agent runtime** (`AI_AGENT_RUNTIME_CLASS`): a tool-use loop that streams the answer as the model produces it and reports each step as it completes. - **Tools** over the existing MCP service, gated by per-profile allowlists and a policy chain that keeps generated SQL read-only. - **Prompt assembly** that fails the build rather than shipping a prompt carrying deployment-specific tables, hostnames or stale tool names. - **Storage**: threads, messages and feedback, with client-supplied idempotency enforced by a unique constraint. Execution is inline by default and can run on the Celery worker (`AI_ASSISTANT_EXECUTION_MODE`), which decouples a run from any reader and lets a client reconnect to one already in progress. Permissions follow the existing model: the API is `@protect()`-ed, the menu is Alpha-only so Gamma and Public cannot reach it, and tools run as the requesting user so a question can never read past that user's grants. Read-only enforcement does not rely on the prompt. Generated SQL is parsed with `SQLScript.has_mutation()` and refused if it writes, because an instruction is not a security boundary — particularly when tool output can carry text an attacker authored. Tool output is framed as untrusted data in the prompt, never as instruction. **Surface area:** a new `/api/v1/ai` resource (12 routes), three new tables, 34 new `AI_*` config keys all with defaults, and a new `src/features/ai` frontend feature that registers itself through the existing `registerChat` extension point. No existing component, view or table is changed. **With the flag off — the default — nothing is registered, no panel renders, and no new dependency is required.** The only footprint is three empty tables. ### BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF <!-- TODO before opening: attach a screenshot or short screencast of the panel on a dashboard, ideally showing a run in progress with an expanded SQL step. Reviewers respond much better to this than to prose, and there is currently no visual here. --> <img width="1906" height="883" alt="image" src="https://github.com/user-attachments/assets/a7f324b2-1865-4505-a782-98c5dbfa6885" /> <img width="646" height="925" alt="image" src="https://github.com/user-attachments/assets/7ad1eb16-2e4a-49e0-b27d-1ab00b9590ca" /> <img width="724" height="906" alt="image" src="https://github.com/user-attachments/assets/68a3fd5b-dfa8-49f2-bddd-7cba004ead6d" /> ### TESTING INSTRUCTIONS The feature is off by default, so start by enabling it. **1. Point it at a model.** Any OpenAI-compatible endpoint works. In `docker/.env-local` (see `docker/.env-local.example`): ``` SUPERSET_AI_LLM_BASE_URL=https://your-endpoint/v1 SUPERSET_AI_LLM_API_KEY=your-token SUPERSET_AI_MODEL_DEFAULT=your-model ``` Or in `superset_config.py`: ```python FEATURE_FLAGS = {"AI_ASSISTANT": True} AI_LLM_PROVIDER_CLASS = "superset.ai.llm.openai_compatible.OpenAICompatibleProvider" AI_LLM_PROVIDER_CONFIG = { "base_url": "https://your-endpoint/v1", "api_key": "...", "models": {"default": "your-model", "fast": "your-model", "reasoning": "your-model"}, } ``` **2. Bring it up and load the examples.** ```bash docker compose up -d ``` **3. Exercise it.** Open a dashboard from the examples (e.g. *USA Births Names*) and open the assistant from the header. - **Grounding** — ask *"summarise what this dashboard shows"*. The answer should name the charts actually on the active tab. Expand "Thought process" → "Context used" to see exactly what it was told. - **Querying** — ask *"how many rows are in birth_names?"*. Expect `75,691`. Expand the `execute_sql` step to see the SQL and the rows returned. - **Read-only enforcement** — ask it to `DROP TABLE birth_names` or `UPDATE` a row. It must refuse. Verify the refusal comes from the policy layer, not the model, by checking the step is recorded as denied. - **Permissions** — repeat as a Gamma user. The assistant should not be reachable at all (`AIAssistant` is in `ALPHA_ONLY_VIEW_MENUS`). As an Alpha user without access to a given dataset, questions about it should fail on access, not answer. - **Streaming** — the answer should appear progressively, and each tool call should appear as it completes rather than all at the end. - **Cancellation** — press Stop mid-run. The partial answer and reasoning should persist; reloading should show the transcript, not an empty bubble. - **Reconnection (worker mode)** — set `SUPERSET_AI_EXECUTION_MODE=worker`, restart, start a long question and reload the page mid-run. The run should continue and the panel should re-attach to it. This needs the `superset-worker` container and Redis. - **Standalone** — append `?standalone=1` to a dashboard URL. The assistant must not render. **4. Automated tests.** ```bash pytest tests/unit_tests/ai/ # 694 tests cd superset-frontend && npm run test -- src/features/ai # 105 tests ``` Integration tests live in `tests/integration_tests/ai/`. ### ADDITIONAL INFORMATION <!--- Check any relevant boxes with "x" --> <!--- HINT: Include "Fixes #nnn" if you are fixing an existing issue --> - [x] Has associated issue: <!-- SIP link goes here once the SIP is filed --> - [x] Required feature flags: `AI_ASSISTANT` - [x] Changes UI - [x] Includes DB Migration (follow approval process in [SIP-59](https://github.com/apache/superset/issues/13351)) - [x] Migration is atomic, supports rollback & is backwards-compatible - [x] Confirm DB migration upgrade and downgrade tested - [x] Runtime estimates and downtime expectations provided - [x] Introduces new feature or API - [ ] Removes existing feature or API **Migration detail (SIP-59).** One additive revision creating three tables — `ai_chat_threads`, `ai_chat_messages`, `ai_chat_feedback`. No existing table is altered and no data is backfilled, so it is backwards-compatible with the previous release: an older Superset ignores the tables entirely. - **Runtime:** three empty `CREATE TABLE`s plus their indexes. Sub-second on any supported backend, independent of existing data volume — nothing is scanned, copied or rewritten. - **Downtime:** none required. No locks are taken on existing tables. - **Rollback:** `downgrade()` drops the three tables. Verified by running upgrade → downgrade → upgrade on PostgreSQL, and verified as part of a fresh install from an empty database. - **Retention:** `AI_ASSISTANT_MESSAGE_RETENTION_DAYS` prunes old transcripts for deployments that do not want to keep them indefinitely. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
