Skip to main content

AI Report Assistant

Overview

The AI Report Assistant is a conversational helper built into the stored‑procedure editor. It drafts, explains and fixes myDBR report procedures for you, grounded in three things:

  • Your database schema
    It can look up tables, columns and foreign keys on demand.

  • Your existing reports
    It can search your own sp_DBR_* procedures and read their source, so new reports follow the conventions already used in your installation.

  • The myDBR command syntax
    The full dbr.* command reference and the myDBR manual are available to it.

The assistant never changes anything on its own. It produces a CREATE PROCEDURE statement (or an explanation) in the chat panel; you decide whether to insert it into the editor and save it through the normal editor flow.

Its explanations are written in the myDBR user's interface language (SQL and dbr.* code stay as they are); override or disable this with $mydbr_defaults['ai']['response_language'].

The feature requires an OEM licence and is turned off by default.

What it can do

  • Write a new report "Create an organization chart from the staff table. Sales by month with a bar chart and a drill‑down to the order detail report". It confirms columns, works out joins from foreign keys, checks how similar reports in your installation are written, and returns a complete CREATE PROCEDURE.

  • Explain an existing report Paste it into the editor (or use Explain with AI) and ask what it does.

  • Fix / change a report "this errors on an empty date range", "add a total row and right‑align the amount column", "make the chart a pie chart".

  • Answer myDBR questions "how does dbr.crosstab column ordering work?", "which command adds a column filter?", answered from the indexed manual.

Under the hood it has these read‑only tools:

ToolPurpose
list_tables, describe_table, foreign_keysInspect the schema of the databases in scope.
search_reports, get_report_sourceFind and read your existing report procedures for style.
search_docsSearch the indexed myDBR documentation.
validate_sqlCompile‑check its final CREATE PROCEDURE by creating a temporary copy and dropping it, with no effect on the real procedure.
sample_rowsOnly if "Allow reading sample data rows" is enabled, reads up to 5 rows from a table.

Requirements

  • An OEM licence.
  • Access to a supported model service, selected as the API type:
    • Anthropic (the default),
    • Google Gemini (native API),
    • OpenAI (hosted), or
    • Local / self‑hosted: any OpenAI‑compatible server or gateway (Ollama, Open WebUI, vLLM, LiteLLM, …).
  • The PHP curl extension, and outbound HTTPS from the web server to the model service (see Server configuration).
  • Optional: the pdftotext utility (from poppler) to index the myDBR manual for the assistant's documentation search.

Enabling and configuring

Open Settings → OEM tab → AI report assistant. The fields are disabled until an OEM licence is present.

SettingDescription
EnabledMaster switch. When off, the panel, the Fix SQL button and the Explain with AI button are hidden.
API keyThe API key / bearer token for the selected service. Stored server‑side, never sent to the browser. A Local endpoint that needs no key still requires any non‑empty value here.
API typeAnthropic (default), Google Gemini (native API), OpenAI, or Local / self-hosted (OpenAI-compatible).
API base URLLeave blank to use the default for the chosen API type (https://api.anthropic.com / https://generativelanguage.googleapis.com/v1beta / https://api.openai.com/v1). Local has no default: set your server URL, including the /v1 path, e.g. http://localhost:11434/v1.
ModelFor Anthropic / Gemini / OpenAI, a dropdown of the models in $mydbr_defaults['ai']['models'] (an id you already had configured stays selectable). For Local, a free‑text field: enter the id your server exposes (e.g. qwen2.5-coder:7b).
Schema databasesComma‑separated list of the report database(s) the assistant may read table and column names from. The myDBR database login must have access to them. Leave empty to use whichever database is selected in the editor.
Best practicesFree‑text house rules added to every request: naming conventions, preferred commands, formatting, things to avoid. A user/ai_instructions.md file, if present, is appended to this.
Allow reading sample data rowsOff by default. When on, the assistant may fetch up to 5 rows from a table to see the actual value shapes the schema does not reveal (codes vs. names, A/I vs. active/inactive, cents vs. decimals, date formats), which gives more accurate WHERE clauses, column formatting and pick‑lists on the first try. It sends real data to the model service, so enable it only with a local model or non‑sensitive databases.

Below the settings are the two Knowledge indexes, each with a status line and a Build / rebuild button. They are optional but strongly recommended. Build both once the assistant is enabled:

  • Documentation index
    The myDBR command reference and manual, so the assistant can answer "how do I…" questions and cite the right dbr.* syntax instead of guessing.

  • Report index
    A skeleton of every existing report plus a derived house‑style summary and a reporting data model (the tables your reports actually use, the join paths between them, and which column each in parameter filters), so new drafts follow this installation's naming, preferred commands, layout conventions and real join structure rather than generic ones.

Until an index is built the matching lookups fall back to a plain text search. Full details and rebuild guidance are in Knowledge indexes.

Getting an Anthropic API key

API access is separate from a Claude.ai subscription and is billed per use.

  1. Sign in at console.anthropic.com.
  2. Add a payment method / credit under Billing.
  3. Settings → API Keys → Create Key. Copy the key (shown once) into the API key field.

Cost per request is small for report authoring (a large system prompt plus a short answer); a few dollars of credit lasts a long time. You can set a spend limit on the key in the console.

Google Gemini

Set API type to Google Gemini (native API).

  • API type: Google Gemini (native API)
  • API base URL: leave blank (defaults to https://generativelanguage.googleapis.com/v1beta)
  • API key: a Gemini API key (see below)
  • Model: gemini-3.6-flash (fast, low cost) or gemini-3.6-pro

Getting a Google Gemini API key

  1. Sign in at aistudio.google.com with a Google account.
  2. Click DashboardGet API key (top‑left, or at aistudio.google.com/apikey).
  3. Create API key → pick or create a Google Cloud project → copy the key (starts with AIza…) into the API key field.
  4. The free tier has low rate limits and Google may use the data to improve its products. For production use, open the key's Cloud project and enable billing (in console.cloud.google.comBilling); paid usage is not used for training. You can set budget alerts there.

The native API type talks to Gemini's own generateContent endpoint rather than its OpenAI‑compatibility shim. Compared with using the OpenAI‑compatible type against the same host it adds:

  • usage reporting For cached‑ and thinking‑token counts (visible via the /aidebug panel command), so cost is easier to track;

  • an optional thinking budget $mydbr_defaults['ai']['thinking_budget']: leave null for the model's standard behaviour, or set an explicit positive token budget (e.g. 1024);

  • optional relaxed safety filters $mydbr_defaults['ai']['safety'] = 'none' sets every category to BLOCK_NONE, so report prompts containing sensitive column names are not blocked;

  • clearer block reasons on the rare occasions a request is stopped.

Embedding‑based search uses text-embedding-004 automatically on this API type. Gemini applies context caching to a large repeated prompt prefix on its own server‑side, with no configuration.

You can still reach Gemini through the Local / self-hosted type instead (API base URL https://generativelanguage.googleapis.com/v1beta/openai); the native type is preferred.

OpenAI

Set API type to OpenAI. API base URL can be left blank (defaults to https://api.openai.com/v1). Pick a Model from the dropdown; to offer a different one, add it to $mydbr_defaults['ai']['models']['openai'] in user/defaults.php.

Getting an OpenAI API key

  1. Sign in at platform.openai.com (this is the developer platform, separate from a ChatGPT subscription; usage is billed per request).

  2. Billing → Payment methods Add a card and buy some prepaid credit, or enable auto‑recharge. Requests fail with a quota error until the account has credit.

  3. API keys (platform.openai.com/api-keys) → Create new secret key. Copy the key (starts with sk-…, shown once) into the API key field.

  4. Optionally set a monthly usage limit under Settings → Limits.

Local / self‑hosted

Set API type to Local / self-hosted (OpenAI-compatible). This speaks the OpenAI wire protocol, so any server that exposes an OpenAI‑compatible /chat/completions endpoint works.

  • API base URL: required, no default. Set your server URL including the /v1 path.
  • API key: enter any non‑empty value if the endpoint does not need one.
  • Model: free‑text; enter the id your server exposes.
ServerAPI base URLModel examples
Ollamahttp://<host>:11434/v1qwen3-coder:30b, qwen3:14b, llama3.1:8b
Open WebUIhttp://<host>:3000/apias listed in Open WebUI
vLLM / LiteLLM / gatewaythe server's OpenAI base, ending in /v1server‑dependent
Google Gemini (OpenAI shim)https://generativelanguage.googleapis.com/v1beta/openaigemini-3.6-flash (prefer the native Google Gemini type)

For embedding‑based search on a local server, set $mydbr_defaults['ai']['embed_model'] in user/defaults.php to an id your server exposes (e.g. nomic-embed-text).

Points to check with local models

  • Context window. The assistant's system prompt (the full command reference) is large (about 10k tokens) and a request re‑sends the growing history on every tool step. Ollama's default context (2–4k) silently truncates it and the model then invents column names; raise it to at least 32k (OLLAMA_CONTEXT_LENGTH, or num_ctx in a Modelfile).
  • Tool calling. The assistant relies on function/tool calling to look up schema and reports. Use a model that supports it well (Qwen 3 Coder, Qwen 2.5 Coder, Llama 3.1+, Mistral). If tools are not being called, the model will guess column names.
  • Networking. If myDBR runs in a container, use host.docker.internal (or a shared Docker network) instead of localhost. If a proxy is configured under Settings → Miscellaneous, it is applied to every outbound request, including local ones. Clear it or the local model will be unreachable.
  • Quality. Small local models produce weaker, occasionally invalid report syntax. The validate_sql check catches database errors but not every dbr.* mistake.

If a local model stops mid‑answer

A smaller model sometimes runs a few tool calls, writes an opening sentence such as "Let's check which reports use this table", and then stops without producing the report or the answer. This happens because the model did not close its own tool loop: after max_turns round‑trips the assistant forces a final turn with no tools, and a weak model tends to answer that with the sentence it would have said before its next tool call rather than with the finished result. Context truncation (num_ctx too low) makes it more likely, because by the later steps the model has lost part of its instructions.

To make it finish, send a normal follow‑up message: continue (or "finish the answer" / "write the report now"). It is an ordinary chat message, not a command. The panel keeps the whole conversation, including every tool call and its result, so the model resumes with all of that still in context and only has to write the conclusion. Repeat once more if it stops again.

To make it happen less often:

  • Raise the Ollama context to num_ctx 40960 (see Context window above).
  • Raise $mydbr_defaults['ai']['max_turns'] to about 10 and max_tokens to 4096, so the model has room to finish exploring before the forced final turn and room to write a long procedure.
  • Build the Report index. Questions about which tables, joins or parameters your reports use are answered from the injected reporting data model with no tool loop at all, which is where local models stall most.
  • For genuinely multi‑step questions, a larger local model or a hosted one completes the loop far more reliably.

Example: a local model with Ollama

Which local model you can run is decided by the machine Ollama runs on: its RAM (or GPU VRAM), and whether it has a usable GPU at all. There is no single "right" local model. Pick the largest one that fits in memory and still answers fast enough for interactive use:

MachineReasonable choice
~16 GB, no / weak GPUa small model such as qwen3:8b or qwen2.5-coder:7b. Expect weaker, sometimes invalid SQL and less reliable tool use.
~24–32 GB RAM, or a 16–24 GB GPUqwen3-coder:30b, a Mixture-of-Experts model (~30B total, ~3B active per token, so it runs fast for its size)
48 GB+ RAM or a 24 GB+ GPUqwen3-coder:30b at a higher quant, or a larger code model

The walkthrough below uses qwen3-coder:30b as a concrete example: it has solid OpenAI-style function calling (which the assistant depends on), is code-tuned, and has no "thinking" mode that could leak into replies. Substitute whatever tag fits your hardware; the steps are the same. A vision model (e.g. qwen3-vl:30b) also works but brings no benefit here; the assistant only sends text.

1. Install Ollama: https://ollama.com/download.

  • macOS: the .dmg, or brew install ollama. The menu-bar app starts the server.
  • Linux: curl -fsSL https://ollama.com/install.sh | sh (installs a systemd service).
  • Windows: OllamaSetup.exe. Runs in the system tray, listens on 127.0.0.1:11434.

2. Pull the model:

ollama pull qwen3-coder:30b

(~18 GB; check with ollama list.)

3. Raise the context window: the step most setups miss. Ollama's default context (2–4k) is far below the assistant's ~10k-token system prompt plus the schema card and the growing tool-loop history, and Ollama silently truncates the excess. Create a file named Modelfile:

FROM qwen3-coder:30b

PARAMETER num_ctx 40960
PARAMETER temperature 0.15
PARAMETER top_p 0.9
PARAMETER repeat_penalty 1.05

(on a 24 GB machine use num_ctx 24576), then build a derived model:

ollama create qwen3-mydbr -f ./Modelfile

ollama show qwen3-mydbr confirms num_ctx.

4. Ollama server settings: set these and restart Ollama:

VariableValueWhy
OLLAMA_KEEP_ALIVE30mKeep the model resident; otherwise the first request after an idle period pays a slow reload ("Load failed" in the browser).
OLLAMA_FLASH_ATTENTION1Faster, smaller KV cache.
OLLAMA_CONTEXT_LENGTH40960Only if you skipped the Modelfile, a server-wide default.
OLLAMA_KV_CACHE_TYPEq8_0Optional, memory-tight machines, roughly halves KV-cache memory.
OLLAMA_HOST0.0.0.0Only if myDBR runs on a different host than Ollama (then open port 11434).

Setting env vars: macOS launchctl setenv NAME value then reopen Ollama.app; Linux sudo systemctl edit ollamaEnvironment="NAME=value"daemon-reload

  • restart; Windows System → Environment Variables (or setx), then quit and relaunch Ollama from the tray. If you run ollama serve manually, just export them.

5. Configure myDBR: Settings → OEM tab → AI report assistant:

FieldValue
Enabledon
API keyollama (any non-empty value)
API typeLocal / self-hosted (OpenAI-compatible)
API base URLhttp://localhost:11434/v1, or http://host.docker.internal:11434/v1 if myDBR is in a container, or http://<ollama-host-ip>:11434/v1 if on another machine
Modelqwen3-mydbr
Schema databasesyour report database(s)

Clear any proxy under Settings → Miscellaneous; it applies to localhost too.

6. user/defaults.php:

$mydbr_defaults['ai']['timeout'] = 240; // local generation is slower
$mydbr_defaults['ai']['max_turns'] = 5; // caps wall-clock per request (optional)

Keep the web-server / PHP timeouts (see Server configuration) at 300 s or more.

7. Embeddings (optional): enables semantic ranking for the Knowledge indexes (otherwise they fall back to keyword search):

ollama pull nomic-embed-text
$mydbr_defaults['ai']['embed_model'] = 'nomic-embed-text';

Then rebuild both indexes from Settings.

8. Verify:

ollama run qwen3-mydbr "one-line MySQL SELECT of the current time"

Check that function calling works: the reply must contain a tool_calls array, not a call written as plain text:

curl -s http://localhost:11434/v1/chat/completions -H "Content-Type: application/json" -d "{\"model\":\"qwen3-mydbr\",\"messages\":[{\"role\":\"user\",\"content\":\"Use the list_tables tool.\"}],\"tools\":[{\"type\":\"function\",\"function\":{\"name\":\"list_tables\",\"description\":\"list db tables\",\"parameters\":{\"type\":\"object\",\"properties\":{}}}}]}"

Then in a report's editor open the assistant panel, type /aidebug to confirm the endpoint and model, and ask for a small report. A truncating input prompt line in the Ollama log means num_ctx is still too low. The log is at ~/.ollama/logs/server.log (macOS / manual Linux), journalctl -u ollama (Linux systemd), or %LOCALAPPDATA%\Ollama\server.log (Windows).

SymptomCause / fix
Invents column or table namesTool calls not firing, or the prompt is truncated. Raise num_ctx; keep a -coder model.
Rambles, never returns a CREATE PROCEDUREContext truncation on later turns, or thinking leaking from a non-coder model. Raise num_ctx, use qwen3-coder, lower max_turns.
Stops after a few tool calls, no answerModel did not close its tool loop. Send continue as a follow-up message; raise num_ctx and max_turns; build the Report index for schema-usage questions.
"Load failed" after a pauseModel unloaded; set OLLAMA_KEEP_ALIVE; raise timeout.
Long answers cut offRaise $mydbr_defaults['ai']['max_tokens'].
Out of memory / very slowSmaller model, lower num_ctx, or OLLAMA_KV_CACHE_TYPE=q8_0.

Advanced defaults (user/defaults.php)

Most sites do not need these. They live under $mydbr_defaults['ai']. api_key, api_style, api_base and model are normally set in Settings instead; a value here is the fallback when the Settings field is blank.

$mydbr_defaults['ai'] = [
// 'api_key' => '', // normally set in Settings
// 'api_style' => 'anthropic', // 'anthropic' | 'gemini' | 'openai' | 'local' (normally set in Settings)
// 'api_base' => '', // blank = default for the API type (normally set in Settings)
'model' => 'claude-sonnet-5', // resolves to models[api_style][0] when api_style is not 'anthropic'
'models' => [ // options in the Settings Model dropdown per API type
'anthropic' => ['claude-sonnet-5', 'claude-opus-4-8', 'claude-haiku-4-5'],
'gemini' => ['gemini-3.6-flash', 'gemini-3.6-pro'],
'openai' => ['gpt-5.6-luna', 'gpt-5.6-terra'],
// 'local' has no list - it uses a free-text field
],
'embed_model' => 'text-embedding-3-small', // OpenAI / Local; Gemini native defaults to text-embedding-004
'anthropic_version' => '2023-06-01', // Anthropic API version header - only change if Anthropic asks
'max_tokens' => 3072, // per-response output cap
'timeout' => 120, // seconds per model HTTP call
'connect_timeout' => 15,
'allow_validate' => true, // set false to disable the validate_sql tool
'cache_ttl' => '5m', // Anthropic prompt-cache TTL: '5m' or '1h' (see Cost)
'few_shot_count' => 1, // worked examples inlined in the system prompt (0-3)
'max_turns' => 6, // model round-trips per request (tool calls + final answer)
'response_language' => null, // null = reply in the myDBR user's UI language; a name ('English', 'German', …) forces it; false = no instruction
// 'thinking_budget' => 1024, // Gemini native only: null = standard, or a positive token budget
// 'safety' => 'none', // Gemini native only: relax every safety filter (BLOCK_NONE)
// 'openai_max_tokens_param' => 'max_tokens', // OpenAI / Local only: force the output-cap parameter name (default: auto)
// 'openai_reasoning_effort' => 'none', // OpenAI / Local only: value for reasoning_effort (default: omit; auto-set to 'none' when a model needs it for tools)
// 'debug' => true, // enables the /aidebug panel command
];

To add or change the models offered in the Settings → Model dropdown, edit $mydbr_defaults['ai']['models'] in user/defaults.php, no code change needed. An id already saved as the active model stays selectable even if it is not in the list.

embed_model must be an id the current API type serves. OpenAI uses text-embedding-3-small (the default) or text-embedding-3-large; Gemini native uses text-embedding-004 (set automatically); a Local server uses whatever it exposes (nomic-embed-text, mxbai-embed-large, …). A leftover local value like nomic-embed-text sent to hosted OpenAI fails the index build with embeddings HTTP 404 … does not exist; clear the override (or set an OpenAI id) when you switch the API type away from Local.

Reply language

response_language controls the language of the assistant's prose: its explanations, notes, and the Fix SQL one‑line summary. Code is never affected: SQL, dbr.* command names, table and column names and identifiers are left as they are.

ValueBehaviour
null (default)Reply in the myDBR user's interface language. Recognised for the shipped UI languages (English, Finnish, Swedish, German, French, Spanish, Italian, Dutch, Greek, Hebrew); any other locale falls back to no instruction.
'English', 'German', …Always reply in that language.
falseAdd no language instruction; the model answers in whatever language you write your prompt in.

With a weak local model the "leave code untranslated" rule is not always respected; a hosted model or a larger local one is more reliable.

Cost

Each request re-sends a system prompt (the dbr.* command reference and a short grammar primer) on every step of the tool loop, so that prompt is the main cost driver. Levers, in order of effect:

  • Prompt caching. The system prompt is marked as a cache breakpoint automatically. On the Anthropic API a cache read costs about a tenth of a normal input token, so a multi-step request only pays full price for it once. The default 5-minute cache expires between turns if the user pauses; set 'cache_ttl' => '1h' to keep it warm across 5-60 minute gaps (a cache write then costs 2x instead of 1.25x, so this pays off only with regular back-to-back use). Gemini and OpenAI-compatible endpoints cache a repeated prompt prefix on their own and need no configuration.
  • Model. Pick a fast, low-cost model - gemini-3.6-flash, claude-haiku-4-5, a small local model - for routine drafting; switch to a larger model only for hard reports.
  • few_shot_count. Drop to 0 to remove the inlined example reports (about 600 tokens); the derived house-style summary from the report index then does most of that job.
  • max_tokens. Lower it further if drafts are short; raise it if procedures come back truncated.
  • Schema databases. Listing only the database(s) actually in use keeps the schema section of each request small.

Server configuration

A single request can be several sequential calls to the model service (each time the assistant uses a tool, it calls the model again with the result). The whole exchange runs inside one PHP request, so the default web PHP limits are often too low and the connection is dropped mid‑answer (the panel shows a generic "Load failed" / request error).

Recommended values:

SettingWhereRecommended
max_execution_timephp.ini120 or more
memory_limitphp.ini256M or more
request_terminate_timeoutPHP‑FPM pool config (php-fpm.d/www.conf)300 (or 0 = unlimited)
fastcgi_read_timeout / proxy_read_timeoutnginx300
TimeoutApache300

The AI endpoints raise their own execution time (to 300s) and memory limit (to 512M) at runtime, so editing php.ini is usually not required unless set_time_limit or ini_set appears in the PHP disable_functions list, in which case the runtime override cannot take effect and you must raise the values in php.ini and the web‑server / FPM configuration instead.

Other requirements:

  • curl PHP extension.
  • Outbound HTTPS to api.anthropic.com (or your model host). Requests honour the proxy configured under Settings → Miscellaneous.
  • pdftotext (package poppler-utils / poppler) if you want the myDBR manual indexed for documentation search. Without it the manual PDF is downloaded and saved for you to convert manually; local .md/.txt files are still indexed.

Knowledge indexes

Two optional indexes make the assistant's answers more accurate. Build both after enabling the assistant until an index exists, the matching tools return an "index is empty" message and the assistant falls back to a plain text search where possible.

Open Settings → AI report assistant → Knowledge indexes. Each index has a status line (not built, or N … indexed with the time of the last build) and a Build / rebuild button. Building runs on the server and may take a minute or two; the status line updates when it finishes.

Save the Settings form before you build. The Build buttons read the saved configuration, not what is currently shown in the form. If you change the API type or key and click Build without saving first, the build still uses the old settings, and the build log may say embed skipped: saved API type is "…".

Embedding‑based (semantic) ranking is applied only when the saved API type is OpenAI, Google Gemini or Local, and an API key is set; otherwise the index is still built and used, just with plain text matching. The build log states which path was taken (embed N vectors or embed skipped: <reason>).

Documentation index

Indexes the local lib/ai/docs/*.md|*.txt files and the full myDBR manual PDF (https://mydbr.com/fileserve.php?get=mydbr_doc.pdf, split into page‑sized chunks). Powers the assistant's search_docs tool for "how do I…" questions. Build it once; rebuild only after a myDBR upgrade.

Report index

Reads every registered report, stores a skeleton of each (its parameters, the ordered list of dbr.* commands it uses, and the tables it reads) plus the full source, and derives two summaries that are added to every request:

  • House‑style summary: naming pattern, most‑used commands, how often charts / cross‑tabs / drill‑downs are used, parameter naming, named‑style usage.
  • Reporting data model: pattern‑matched from the report SQL, it lists the tables your reports actually use (with how many reports use each), the join paths seen between them (orders.customer_id = customers.id and so on), and which column each in‑prefixed parameter filters (inCustomerID -> customers.id). This points the assistant at the handful of tables and joins that matter in a schema of hundreds, which cuts wrong column guesses and needless exploration, especially with smaller local models. It is a hint only: it cannot see comma‑joins or dynamic SQL and does not prove a column exists, so the assistant still confirms with describe_table / foreign_keys. It is metadata, not data: no table rows leave the server (that is the separate Allow reading sample data rows setting).

Both power search_reports / get_report_source as well. Rebuild the index after adding or substantially changing reports so the assistant keeps following current house style and join structure. Rebuilding is safe to repeat and always rebuilds from scratch.

Using the assistant

In the procedure editor

Open a report's stored‑procedure editor (SQL editor). The toolbar has an AI assistant button that opens the panel.

  • Type a request in the box and press Send (or Ctrl/Cmd + Enter).
  • The assistant streams its answer. While it works, each tool it uses is shown as a small line (e.g. 🔧 describe_table(database=shop, table=Orders)).
  • Every SQL block in the answer has two buttons:
    • Insert at cursor: inserts the code at the current cursor position.
    • Replace selection: replaces the selected text.
  • After inserting, run and save the procedure through the normal editor buttons. The assistant does not save anything itself.

The panel sees your current editor contents, any selected text, the database selected in the editor (plus the Schema databases setting), and the previous turns of the current conversation.

Fix SQL

Next to the AI assistant button is a Fix SQL button. It compile‑checks the procedure in the editor (a real CREATE PROCEDURE is created under a throwaway name and dropped, the live procedure is untouched) and:

  • compiles → tells you so, and makes no AI call at all;
  • has a syntax error → sends just the procedure and the database error to the model once (no command reference, no schema, no tool loop), re‑checks the result, and, if it now compiles, shows a one‑line note on what was changed and offers to replace the editor contents with the fixed version.

Progress and the outcome are shown next to the button (a local model can take a minute); the request times out after five minutes.

The DROP PROCEDURE IF EXISTS x $$ / DROP FUNCTION IF EXISTS x $$ line myDBR puts at the top, an optional DELIMITER line, and the trailing $$ (or ;) delimiter are split off, kept verbatim, and re‑attached to the fixed CREATE; only the CREATE part is compile‑checked. If the buffer is not a single CREATE PROCEDURE / CREATE FUNCTION (optionally preceded by DROP … IF EXISTS), Fix SQL reports that it could not check it and does nothing.

It is deliberately narrow: it fixes SQL / MySQL syntax so the procedure compiles. It does not check dbr.* command usage, table or column names, or report logic. Use the assistant panel for those. A fix costs roughly a tenth of a panel conversation, and a procedure that already compiles costs nothing.

Requires an OEM licence and a configured API key, like the panel. Without an OEM licence the AI buttons still appear in the editor but are greyed out. It is hidden entirely if $mydbr_defaults['ai']['allow_validate'] is false (the compile check is the whole mechanism).

From the report list

On a report's Edit report screen there is an Explain with AI button. It opens the procedure editor with the assistant panel open and a request pre‑filled to explain that report. Its parameters, each result set, the commands used and what the user sees.

Privacy and data handling

When enabled, each request sends to the configured model service:

  • database schema table and column names for the schemas in scope,
  • the SQL source of your report procedures that the assistant looks up as style examples,
  • your prompts and the current editor contents,
  • actual table rows only if Allow reading sample data rows is turned on.

It does not send database credentials, myDBR user accounts, or report output.

For an installation that must not send anything to an external service, use a self‑hosted OpenAI‑compatible model as described above; nothing then leaves your network.

Troubleshooting

  • No "AI assistant" button in the editor: check that Enabled is ticked and saved, and that an OEM licence is active. Hard‑refresh the editor page.
  • "The AI assistant has no API key": the key is empty; add it under Settings and save.
  • Authentication / key errors from the service: re‑enter the key, making sure there is no trailing whitespace, and confirm the Model name is one the service accepts.
  • "Load failed" / the answer stops partway: a PHP or web‑server timeout is cutting the connection on a long, tool‑heavy request. Raise the limits listed in Server configuration.
  • The assistant guesses wrong column names: build the report and documentation indexes, set Schema databases to the correct database(s), and confirm the myDBR login can see those schemas (they appear in the editor's database selector).
  • search_docs says the index is empty: build the documentation index from Settings → AI report assistant → Knowledge indexes (the manual needs pdftotext).
  • Gemini: "Function call is missing a thought_signature": Gemini 3 models require the thought signature returned with each function call to be sent back in the conversation; myDBR does this automatically. If you still see this error, update myDBR, or switch Model to a Gemini 2.x id.
  • OpenAI: "'max_tokens' is not supported with this model. Use 'max_completion_tokens' instead": the OpenAI API type already sends max_completion_tokens; a Local endpoint sends max_tokens. If your endpoint needs the other name, set $mydbr_defaults['ai']['openai_max_tokens_param'] to 'max_completion_tokens' or 'max_tokens' in user/defaults.php.
  • OpenAI: "Function tools with reasoning_effort are not supported … set reasoning_effort to 'none'": handled automatically: the request is retried with reasoning_effort: none and that is kept for the rest of the conversation. To skip the initial failed call, set $mydbr_defaults['ai']['openai_reasoning_effort'] = 'none'.