← Back to list

How I Used Qwen2.5 Locally to Generate Power BI Dashboards Automatically

No cloud API key. No data leaving my machine. Just natural language → .pbit.

RAMESH JAIN · 2026-05-24 07:43 · 0 claps · 6.1 min read
#power-bi #data-visualization #analytics #ai
Open on Medium ↗
Wiki topics: LLM · Large Language Models AI · AI · General VIS · Visual & Graphic Design GRW · Growth & Analytics 🎬 · Film & Television

How I Used Qwen2.5 Locally to Generate Power BI Dashboards Automatically

[embed]

No cloud API key. No data leaving my machine. Just natural language → .pbit.

I build data tools for a living. But I have a dirty secret: I have spent more hours manually wiring up Power BI visuals than I care to admit. Drag a measure here, pick a chart type there, tweak the color palette, fight the slicer alignment. Repeat for every new dataset.

So when I started building ReportForge PBI, an open-source tool that compiles .pbit files from CSV or SQL sources, the obvious question was: can I wire a language model into this so I can just describe the dashboard I want in plain English?

The answer is yes. And the part that genuinely surprised me was how well a 3-billion-parameter model running entirely on my own CPU handled it.

This post walks through exactly how I connected Qwen2.5 (via Ollama) to ReportForge, what the model actually sees and returns, what works well, and where the edges are.

The Setup: ReportForge + Ollama + Qwen2.5

ReportForge is a local-first tool. Everything runs on 127.0.0.1. There is no SaaS backend, no telemetry, and critically, no data rows ever leave your machine. When you upload a CSV, the profiler reads column names, infers their roles (measure, dimension, date, geographic), and builds a dashboard from that metadata alone.

By default it produces a deterministic layout: three KPI cards, a bar chart, a line chart over time, a donut for low-cardinality dimensions, and a filter panel. Perfectly serviceable. But not what you asked for.

To go from “default layout” to “describe what you want”, I needed a language model in the loop. The path of least resistance for a privacy-first, offline-friendly tool is Ollama.

Installing the pieces

The Windows installer for ReportForge already bundles a CPU-only Ollama runtime. On first launch, if Qwen2.5:3b is not present, it pulls the model automatically. So for end users, there is nothing to install manually.

If you are running from source, you do it yourself:

In the browser UI at http://127.0.0.1:8000/, you select Local Qwen 2.5 (Ollama) from the provider dropdown. No API key field appears. That is the entire configuration.

What the Model Actually Sees

This is the part most AI-in-BI posts gloss over, so I want to be explicit. The Qwen model receives exactly three things:

  • Your prompt text (plain English description of what you want)

  • The column profile: a list of column names, their inferred role (measure or dimension), and semantic type (temporal, geographic, categorical, numeric)

  • The list of visuals already produced by the deterministic builder (so the model doesn’t suggest a second sales-over-time line chart when one already exists)

No data rows. Not a single value from your CSV. The payload is tiny, which is why a 3B model can handle it in a few seconds even on CPU.

Here is a representative system prompt (simplified):

You are a Power BI dashboard designer. Given a user prompt and column

metadata, return a JSON array of chart specifications.

Columns available:

  • Sales (measure, numeric)

  • Profit (measure, numeric)

  • Category (dimension, categorical)

  • Sub-Category (dimension, categorical)

  • Order Date (dimension, temporal)

  • State (dimension, geographic)

Visuals already on the report: barChart(Category, Sales), lineChart(Order Date, Sales)

User prompt: ‘show profit by sub-category and a donut of segment share’

Return ONLY a JSON array, no markdown, no preamble.

Qwen2.5 returns something like:

ReportForge validates each spec against the column profile. If the model hallucinates a column name that does not exist, that spec is dropped. The remaining specs are appended to the deterministic layout.

Prompt Patterns That Work Well

After testing with several datasets (Superstore, AdventureWorks, synthetic BFSI data), these prompt patterns produce reliable results with the 3B model:

Top-N filtering

“bar chart of sub-categories by sales, top 5”

The keywords top N, first N, or best N trigger a Top-N filter in the chart spec. Qwen picks this up reliably and includes a topN field in the JSON. The materializer applies it as a TopN visual-level filter in Power BI.

Multi-visual prompts

“show profit by region and quantity sold over time”

This produces two separate chart specs: a bar chart and a line chart. The model correctly decomposes the prompt into independent visuals rather than trying to cram both into one.

Donut / share charts

“donut chart of sales share by customer segment”

Donut charts work well when the dimension is low-cardinality (fewer than ~8 distinct values). The model generally respects this; on high-cardinality dimensions it tends to suggest a bar chart instead, which is the right call.

The map exception

Geographic visuals (filled maps / choropleths) are the one case where you need to be explicit. ReportForge will never emit a map unless your prompt contains one of the words map, choropleth, or geographic. This is an intentional guard: maps require the dataset to have a recognized geographic column, and they look alarming when generated on wrong data.

“choropleth map of total sales by state”

Model Comparison: Qwen2.5 vs Claude vs GPT-4o-mini

ReportForge supports three LLM paths. Here is an honest comparison based on my testing with the Superstore dataset:

For most everyday dashboard generation, Qwen2.5:3b is genuinely good enough. The 5% column hallucination rate sounds concerning but in practice the schema validation layer in ReportForge catches and drops those specs before they reach the compiler. What gets through is clean.

Where Claude and GPT-4o-mini pull ahead is on ambiguous prompts. If you write something like “show me the sales performance story”, a larger model produces more insightful chart selections. A 3B model tends to produce one or two generic charts. Still valid, just less creative.

The Full Flow, End to End

Here is the complete journey from CSV to open .pbit:

  1. Upload CSV. The profiler scans every column: numeric columns become measures, low-cardinality strings become dimensions, date columns become temporal, and columns named State / Country / Region / City / Zip become geographic.

  2. Deterministic builder runs. Always. KPI cards for top measures, a bar chart for the primary categorical dimension, a line chart if there is a date column, a donut if there is a low-cardinality dimension, filter panel.

  3. LLM path runs if a provider is selected. For Local Qwen, ReportForge calls http://127.0.0.1:11434/api/generate with the column profile and your prompt. The JSON response is parsed, validated against the schema, and any valid new specs are appended.

  4. pbi-tools.core compiles. The visual specs, semantic model (BIM JSON), and Power Query M expression are written to a project tree on disk, then pbi-tools.core compiles the tree into a .pbit file.

  5. Browser downloads .pbit. Double-click to open in Power BI Desktop. The UI status line tells you which path ran: llm:qwen for a successful Qwen generation, llm:qwen-error if Ollama was unreachable.

Total time from clicking Generate to a downloadable .pbit: 20–60 seconds. Most of that is the pbi-tools.core compile step, not the LLM call.

Troubleshooting the Qwen Path

A few things that tripped me up during development:

Prompt path shows llm:qwen-error

Ollama is not reachable. Either it is not running (check if ollama.exe is in your process list), or the model download from first use is still in progress. The installer pulls qwen2.5:3b on first Qwen generation, which can take a few minutes on a slow connection. Wait and retry.

Qwen returns malformed JSON

The 3B model occasionally forgets to close a bracket or includes markdown fences around the JSON. ReportForge has a cleanup step that strips json / code fences and attempts to extract a JSON array even from partially malformed output. If the cleanup fails, the Qwen path falls back to deterministic-only and surfaces llm:qwen-empty in the status banner.

Generated visuals duplicate existing ones

This usually means the “visuals already on report” context did not get through to the model cleanly. Check that your prompt is not excessively long (keep it under 200 characters for the 3B model). Shorter, more specific prompts produce better results with smaller models.

Changing the model

If you want to try a larger Qwen variant (7B, 14B) or a different locally-hosted model, set the QWEN_MODEL or OLLAMA_MODEL environment variable before launching ReportForge. The Ollama URL defaults to 127.0.0.1:11434 but can be overridden with QWEN_OLLAMA_URL if your Ollama server runs on another machine.

Why Local-First Matters for BI

I want to close with the reason I built the Qwen path at all, not just the Claude and OpenAI paths.

A lot of the most interesting BI use cases live inside corporate firewalls. A manufacturing plant tracking sensor data, a hospital monitoring bed occupancy, a bank running internal P&L reports. These organizations cannot send even anonymized column names to an external API. The legal and security review alone would take months.

A local language model changes the calculus entirely. Nothing leaves the network perimeter. The model runs on the same machine (or the same LAN) as the data. And for the specific task of producing chart specs from column names, a 3B model is genuinely sufficient.

This is not a pitch for Qwen specifically. It is a pitch for the pattern: small, capable local models as a privacy-safe AI layer in data tooling. The same architecture would work with Llama 3.2:3b, Phi-3:mini, or whatever model is small and fast enough to run on your hardware.

ReportForge just happened to be the context where I needed to solve this problem. I built the Qwen path because I had customers who needed it. Maybe you do too.

Originally published at https://medium.com on May 24, 2026.


메타데이터
post_id
c68e24b5963c
slug
how-i-used-qwen2-5-locally-to-generate-power-bi-dashboards-automatically-c68e24b5963c
url
https://medium.com/@twilize5/how-i-used-qwen2-5-locally-to-generate-power-bi-dashboards-automatically-c68e24b5963c
canonical_url
https://medium.com/@twilize5/how-i-used-qwen2-5-locally-to-generate-power-bi-dashboards-automatically-c68e24b5963c
author_url
https://medium.com/@twilize5
status
ok
fetched_at
2026-07-10 11:40:45