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 ownsp_DBR_*procedures and read their source, so new reports follow the conventions already used in your installation. -
The myDBR command syntax
The fulldbr.*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
stafftable. 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 completeCREATE 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.crosstabcolumn ordering work?", "which command adds a column filter?", answered from the indexed manual.
Under the hood it has these read‑only tools:
| Tool | Purpose |
|---|---|
list_tables, describe_table, foreign_keys | Inspect the schema of the databases in scope. |
search_reports, get_report_source | Find and read your existing report procedures for style. |
search_docs | Search the indexed myDBR documentation. |
validate_sql | Compile‑check its final CREATE PROCEDURE by creating a temporary copy and dropping it, with no effect on the real procedure. |
sample_rows | Only 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
curlextension, and outbound HTTPS from the web server to the model service (see Server configuration). - Optional: the
pdftotextutility (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.
| Setting | Description |
|---|---|
| Enabled | Master switch. When off, the panel, the Fix SQL button and the Explain with AI button are hidden. |
| API key | The 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 type | Anthropic (default), Google Gemini (native API), OpenAI, or Local / self-hosted (OpenAI-compatible). |
| API base URL | Leave 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. |
| Model | For 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 databases | Comma‑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 practices | Free‑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 rows | Off 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 rightdbr.*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 eachinparameter 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.
- Sign in at console.anthropic.com.
- Add a payment method / credit under Billing.
- 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) orgemini-3.6-pro
Getting a Google Gemini API key
- Sign in at aistudio.google.com with a Google account.
- Click Dashboard → Get API key (top‑left, or at aistudio.google.com/apikey).
- Create API key → pick or create a Google Cloud project → copy the key
(starts with
AIza…) into the API key field. - 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.com → Billing); 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:
-
usagereporting For cached‑ and thinking‑token counts (visible via the/aidebugpanel command), so cost is easier to track; -
an optional thinking budget
$mydbr_defaults['ai']['thinking_budget']: leavenullfor 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 toBLOCK_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
-
Sign in at platform.openai.com (this is the developer platform, separate from a ChatGPT subscription; usage is billed per request).
-
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.
-
API keys (platform.openai.com/api-keys) → Create new secret key. Copy the key (starts with
sk-…, shown once) into the API key field. -
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
/v1path. - API key: enter any non‑empty value if the endpoint does not need one.
- Model: free‑text; enter the id your server exposes.
| Server | API base URL | Model examples |
|---|---|---|
| Ollama | http://<host>:11434/v1 | qwen3-coder:30b, qwen3:14b, llama3.1:8b |
| Open WebUI | http://<host>:3000/api | as listed in Open WebUI |
| vLLM / LiteLLM / gateway | the server's OpenAI base, ending in /v1 | server‑dependent |
| Google Gemini (OpenAI shim) | https://generativelanguage.googleapis.com/v1beta/openai | gemini-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, ornum_ctxin 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 oflocalhost. 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_sqlcheck catches database errors but not everydbr.*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 about10andmax_tokensto4096, 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:
| Machine | Reasonable choice |
|---|---|
| ~16 GB, no / weak GPU | a 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 GPU | qwen3-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+ GPU | qwen3-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, orbrew install ollama. The menu-bar app starts the server. - Linux:
curl -fsSL https://ollama.com/install.sh | sh(installs asystemdservice). - Windows:
OllamaSetup.exe. Runs in the system tray, listens on127.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:
| Variable | Value | Why |
|---|---|---|
OLLAMA_KEEP_ALIVE | 30m | Keep the model resident; otherwise the first request after an idle period pays a slow reload ("Load failed" in the browser). |
OLLAMA_FLASH_ATTENTION | 1 | Faster, smaller KV cache. |
OLLAMA_CONTEXT_LENGTH | 40960 | Only if you skipped the Modelfile, a server-wide default. |
OLLAMA_KV_CACHE_TYPE | q8_0 | Optional, memory-tight machines, roughly halves KV-cache memory. |
OLLAMA_HOST | 0.0.0.0 | Only 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 ollama → Environment="NAME=value" → daemon-reload
restart; Windows System → Environment Variables (orsetx), then quit and relaunch Ollama from the tray. If you runollama servemanually, justexportthem.
5. Configure myDBR: Settings → OEM tab → AI report assistant:
| Field | Value |
|---|---|
| Enabled | on |
| API key | ollama (any non-empty value) |
| API type | Local / self-hosted (OpenAI-compatible) |
| API base URL | http://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 |
| Model | qwen3-mydbr |
| Schema databases | your 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).
| Symptom | Cause / fix |
|---|---|
| Invents column or table names | Tool calls not firing, or the prompt is truncated. Raise num_ctx; keep a -coder model. |
Rambles, never returns a CREATE PROCEDURE | Context 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 answer | Model 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 pause | Model unloaded; set OLLAMA_KEEP_ALIVE; raise timeout. |
| Long answers cut off | Raise $mydbr_defaults['ai']['max_tokens']. |
| Out of memory / very slow | Smaller 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.
| Value | Behaviour |
|---|---|
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. |
false | Add 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 to0to 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:
| Setting | Where | Recommended |
|---|---|---|
max_execution_time | php.ini | 120 or more |
memory_limit | php.ini | 256M or more |
request_terminate_timeout | PHP‑FPM pool config (php-fpm.d/www.conf) | 300 (or 0 = unlimited) |
fastcgi_read_timeout / proxy_read_timeout | nginx | 300 |
Timeout | Apache | 300 |
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:
curlPHP 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/.txtfiles 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.idand so on), and which column eachin‑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 withdescribe_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_docssays the index is empty: build the documentation index from Settings → AI report assistant → Knowledge indexes (the manual needspdftotext).- 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 sendsmax_tokens. If your endpoint needs the other name, set$mydbr_defaults['ai']['openai_max_tokens_param']to'max_completion_tokens'or'max_tokens'inuser/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: noneand that is kept for the rest of the conversation. To skip the initial failed call, set$mydbr_defaults['ai']['openai_reasoning_effort'] = 'none'.