Goal: Show how to solve product configuration challenges with a pragmatic, privacy-friendly setup: n8n for orchestration, Qwen as a local LLM, and SQL with JSON for data storage.
Use Case: A door configurator

Why We Took This Approach

Most companies jump straight to vector databases and RAG (Retrieval Augmented Generation). But for structured catalogs and clear configuration rules, that’s overkill.

Our reasoning:

  • Speed to production: Everything stays in SQL. No additional vector layer.
  • Privacy by design: Local Qwen model means no customer data leaves the environment. A big win for GDPR and enterprise compliance.
  • Control where it matters: Matching, scoring, and merging are handled deterministically with code.
  • n8n as the glue: Perfect tool to connect AI agents, SQL, and business logic into one clean workflow.

The Architecture in a Nutshell

  1. User sends request → n8n workflow
  2. AI Agent #1 (Qwen, local): Parse intent and parameters from the request
  3. Validation Node: Normalize and validate JSON
  4. SQL Query: Fetch top 3 candidate configurations
  5. Deterministic Scoring: Compare candidates with user’s request, calculate scores
  6. AI Agent #2 (Qwen, local): Turn scores into a human-readable recommendation
  7. Final Assembly: Pull chosen configuration from SQL, overlay user preferences, deliver final JSON

Step by Step: How We Built It

1) Parsing the User’s Request

  • First AI agent powered by Qwen running locally.
  • Task: Extract structured data like width, height, color, lock type, budget, delivery priority.
  • Example output:

{
“width_mm”: 900,
“height_mm”: 2100,
“color”: “anthracite”,
“lock_type”: “multipoint”,
“budget”: 1200,
“delivery_priority”: “high”
}

2) JSON Validation

We run the agent’s output through a code node with a JSON schema validator. That keeps everything strict and predictable:

// Roh-Output vom AI Agent (z.B. in $json.output als String)
let raw = ($json.output ?? ”).trim();

// Entferne evtl. Codefences (json ...)
raw = raw
.replace(/^(?:json)?\s*/i, '') .replace(/$/i, ”)
.trim();

let parsed;
try {
parsed = JSON.parse(raw);
} catch (e) {
throw new Error(‘AI-Agent hat kein gültiges JSON geliefert: ‘ + e.message + ‘ | raw=’ + raw);
}

// Gib alles so zurück, wie es ist
return [{ json: parsed }];

3) SQL: Grab the Top 3 Candidates

All configurations live in a SQL table with jsonb fields for specs.
Example query (Postgres):

SELECT * FROM doors
WHERE breite_mm BETWEEN $1-150 AND $1+150
AND hoehe_mm BETWEEN $2-150 AND $2+150
AND lagerbestand > 0
— AND lower(farbe) = lower($3)
LIMIT 3;

4) Deterministic Scoring

We calculate a transparent score for each candidate. Example:

// nimmt alle Items vom PG-Node
const req = {
prompt: $(‘When chat message received’).first().json.chatInput // optional: Originalprompt
};

function line(c) {
// kompakt, deterministisch, eine Zeile pro Tür
return [${c.id}] ${c.name||''} | ${c.breite_mm}x${c.hoehe_mm}x${c.dicke_mm} | Farbe:${c.farbe} | B:${c.brandschutz} | RC:${c.sicherheitsklasse} | Glas:${c.glasanteil_prozent}% | Drueckergarnitur:${c.druekergarnitur} | Oeffnungsart:${c.oeffnungsart} | Anschlag:${c.anschlag} | Oberflaeche:${c.oberflaeche} | Matierial:${c.material} | dB:${c.schallschutz_db} | €:${c.preis_eur} | LZ:${c.lieferzeit_wochen};
}

const candidates = items.map(i => i.json);
return [{
json: {
request: req,
lines: candidates.map(line),
ids: candidates.map(c => c.id)
}
}];

This gives us a ranking that’s explainable and reproducible.

5) Human-Friendly Recommendation

The second AI agent takes:

  • User’s request
  • Candidate list + scores
  • Key differences

And produces a short explanation like:

“Option B is the closest match to your request. The size fits within tolerance, the lock type is correct, and it stays within budget. The only compromise is a slightly longer delivery time.”

6) Final Configuration Assembly

  • Fetch the chosen door config from SQL.
  • Merge user’s custom preferences into the JSON.
  • Return a clean output ready for downstream systems or APIs.

Why We Skipped RAG

  • Faster and simpler: SQL already handles structured lookups perfectly.
  • Clear logic: Deterministic scoring beats opaque retrieval metrics.
  • Lower cost: No need for vector databases or embedding pipelines.

When RAG makes sense: If the catalog grows more complex, with lengthy descriptions, installation rules, or unstructured data. We’ll cover this in Part 2 with a more advanced furniture doors example.

Operations & Compliance

Running the LLM locally doesn’t automatically solve compliance, but it removes the risk of uncontrolled third-party data transfers. Combined with n8n’s transparent workflows, this setup is easier to defend in audits and DPIAs.

Lessons Learned

  • Validate JSON before writing anything into the database.
  • Use a hybrid schema: core attributes as columns, variable features as jsonb.
  • Keep score explanations — they’re useful both for users and debugging.
  • Always build a fallback: if nothing matches perfectly, return the closest fit with a clear “why not.”
  • Test with a small set of real-world cases — 20–30 scenarios surface most bugs early.

Here you can see how the final product looks like:

Pros and Cons of This Approach

Pros

  • Privacy-friendly (no cloud data transfer)
  • Simple, fast, cost-effective
  • Deterministic and explainable
  • Easy to operate in production

Cons

  • Limited without RAG (no text-heavy knowledge)
  • Scoring formulas require maintenance
  • JSON schema drift can creep in
  • No automatic learning — improvements require rule/code updates

Final Thoughts

For structured product catalogs, this setup — SQL + local Qwen + n8n — is a pragmatic sweet spot. AI handles parsing and explanations, while code keeps scoring deterministic and predictable.

In Part 2, we’ll look at a more advanced case with RAG, validation rules, and complex configurations.

Thinking about digitizing your product configurations or making your process smarter with AI?
Reach out — I can help you design the architecture, implement the workflow, and bring it to life.


Leave a Reply

Your email address will not be published. Required fields are marked *