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]

Reply via email to