Table of Contents

Local AI Stack - Part 1: Base Setup (LM Studio + Open WebUI + ComfyUI)

Scope: install the three core components on a Nobara system and connect them. Everything runs locally, no cloud access.

Components and their roles:

Component Role Port Where it runs
LM Studio loads and serves the LLM, provides the lms CLI 1234 AppImage on the host
Open WebUI chat interface, user accounts, knowledge base (RAG) 3000 Podman container
ComfyUI image generation with Z-Image 8188 Python venv on the host
Qwen3 27B (GGUF) the LLM weights, about 16 GB - stored in ~/.lmstudio

Important principle: LM Studio and the model live on the host. Open WebUI only talks to LM Studio over the network (port 1234). That means updating or replacing the LM Studio AppImage never breaks the WebUI connection - only the model files in ~/.lmstudio matter, and those are not part of the AppImage.

1. Prerequisites

Requirement Details Check command
GPU NVIDIA card with 16 to 19 GB VRAM (needed for Qwen3 27B) nvidia-smi
NVIDIA driver current driver, working nvidia-smi shows card, driver and CUDA version
RAM 32 GB comfortable, 16 GB minimum free -h
Disk space about 25 GB free for model + container + documents df -h /home
Podman installed, used for Open WebUI podman –version
User account rootai, home directory /home/rootai whoami
Ports 1234, 3000, 8188 must be free sudo lsof -i :1234 -i :3000 -i :8188

If nvidia-smi is not found, install the driver first.

2. Install LM Studio (AppImage)

Why AppImage: it is one self-contained file. Updating later means replacing the file - your models, settings and scripts are not inside it.

Step 2.1 - Download:

Download the latest LM Studio AppImage and store it in /home/rootai/Downloads.

Step 2.2 - Make it executable:

  chmod +x /home/rootai/Downloads/lm-studio-*.AppImage

Step 2.3 - Run it (Nobara/Fedora FUSE workaround):

Fedora-based systems do not enable FUSE for normal users by default, so the AppImage may fail with a FUSE or mount error. If that happens:

  cd /home/rootai/Downloads
  ./lm-studio-*.AppImage --appimage-extract
  ./lm-studio-*/AppRun

This unpacks the AppImage into a folder and starts it via AppRun. It behaves exactly like the normal AppImage.

Step 2.4 - Load the model:

In LM Studio: Models tab, search for Qwen3 27B, download the GGUF variant (about 16 GB). Models are stored in ~/.lmstudio - this directory survives every AppImage update.

Step 2.5 - Link the lms CLI globally:

LM Studio provides the lms command (used by start-ai.sh). Create a stable symlink so scripts do not depend on the exact AppImage filename:

  sudo ln -sf /home/rootai/Downloads/lm-studio-*.AppImage /usr/local/bin/lms

Note: after updating LM Studio to a new version (new filename), recreate this symlink - otherwise lms breaks. This is the only update-sensitive part of the whole stack.

Step 2.6 - Verify:

  lms ls

Expected: the command runs and lists the model.

3. Start the LM Studio Server and test the API

Step 3.1 - Start the server:

In LM Studio: Developer tab, set port 1234, click Start Server. (The lms load command below also starts the server automatically.)

Step 3.2 - Load the model:

  lms load qwen/qwen3.8-27b

Wait until the load finishes (about 16 GB into VRAM, takes a few seconds).

Step 3.3 - Test the OpenAI-compatible API:

  curl -s http://127.0.0.1:1234/v1/models

Expected: JSON output that contains qwen3.8-27b. If this works, the LLM side is done.

4. Open WebUI (Podman container)

Step 4.1 - Pull the image:

  podman pull ghcr.io/open-webui/open-webui

Step 4.2 - Create and start the container:

  podman run -d --name open-webui -p 3000:8080 -v open-webui-data:/app/backend/data --restart unless-stopped ghcr.io/open-webui/open-webui

Explanation of the flags:

* –name open-webui - fixed name, used by start-ai.sh (podman restart open-webui) * -p 3000:8080 - host port 3000 mapped to container port 8080 * -v open-webui-data:/app/backend/data - all settings, users and knowledge base live in this volume and survive container updates * –restart unless-stopped - restart automatically after a reboot

Step 4.3 - Verify it is running:

  podman ps | grep open-webui
  curl -sI http://127.0.0.1:3000 | head -1

Expected: an HTTP 200 or 302 line from curl.

Step 4.4 - Configure in the browser:

Open http://<server-ip>:3000 and log in as admin, then:

# Settings, Connections, add OpenAI API

# Settings, Models: set nomic-embed-text-v1.5 as the embedding model (needed for RAG, see Part 2)

5. ComfyUI (Z-Image)

Step 5.1 - Start in the background with logging:

  nohup ~/comfyui-env/bin/python ~/comfyui/main.py --listen --port 8188 >> ~/comfyui.log 2>&1 &

Step 5.2 - Verify:

  curl -s http://127.0.0.1:8188/system_stats

Expected: JSON with system statistics. For problems:

  tail -f ~/comfyui.log

Step 5.3 - Connect in Open WebUI:

Settings, Connections, add ComfyUI:

* URL: http://host.docker.internal:8188 (same reason as above - Open WebUI runs in a container) * Model: Z-Image

6. Auto-start on boot

File: /home/rootai/start-ai.sh (this is the existing script, unchanged)

  #!/bin/bash
  # wait for system services and the LM Studio server to come up
  sleep 15
  # load the Qwen model into LM Studio (also starts the server)
  lms load qwen/qwen3.8-27b
  # give the model a few seconds to fully initialize
  sleep 10
  # restart Open WebUI so it reconnects to the LM Studio API
  podman restart open-webui

Make it executable:

  chmod +x /home/rootai/start-ai.sh

Order matters: LM Studio first, then the model, then Open WebUI.

After an LM Studio update: only step 2.5 (recreate the lms symlink) is needed. The script, the container and the WebUI configuration are untouched.

7. Final smoke test

Run all three checks:

  # 1. LM Studio API
  curl -s http://127.0.0.1:1234/v1/models
  # 2. Open WebUI reachable
  curl -sI http://127.0.0.1:3000 | head -1
  # 3. ComfyUI reachable
  curl -s http://127.0.0.1:8188/system_stats | head -c 100

Then in the browser:

# Open http://<server-ip>:3000, log in as artz # Start a chat with qwen3.8-27b, ask a simple question without a knowledge base # Expected: a normal answer, no citations (citations come with RAG, see Part 2)

8. Troubleshooting

Symptom Likely cause Fix
AppImage will not start FUSE not enabled for the user (Fedora default) use –appimage-extract and AppRun (step 2.3)
lms: command not found symlink points to an old AppImage filename redo step 2.5 with the new path
WebUI cannot find the model wrong base URL from the container use http://host.docker.internal:1234/v1, not localhost
podman restart fails wrong container name check the real name with podman ps -a
Port already in use an old process still holds the port sudo lsof -i :1234 (same for 3000 and 8188), kill the process
Slow first answer after boot model still loading wait for the full load, watch the LM Studio status bar

Local AI Stack - Part 2: RAG Knowledge Base (Zahnarztabrechnung)

Scope: load the five billing documents into the knowledge base Zahnarztabrechnung, create the model Zahn-Abrechnungs-Assistent, and verify that answers come from the documents with correct sources.

Prerequisite: Part 1 is complete - LM Studio serves qwen3.8-27b on port 1234 and Open WebUI is reachable on port 3000.

1. Set the embedding model (must be first)

RAG works in two steps:

# The document text is split into chunks and converted into vectors (embeddings) by the embedding model. # At chat time, the question is embedded the same way and the most similar chunks are retrieved and shown as citations.

Without an embedding model, step one cannot happen and the knowledge base stays empty.

# Open WebUI, Settings, Models # Embedding model: set nomic-embed-text-v1.5 (built-in, no Ollama or extra LM Studio model needed) # Verify: the model list shows the embedding model as active

Fallback: if German retrieval quality is poor, install bge-m3 via Ollama and switch the embedding model to it.

2. Prepare the PDFs

# Document Source Note
1 SGB V (full text) gesetze-im-internet.de 577 pages, includes unrelated areas (pharmacy, hospital) - see step 2.1
2 KZBV FZ-Kompendium 2025 KZBV statutory co-payments (Festzuschüsse)
3 GOÄ/GOZ pkv.de private fee schedules
4 BEL-Preisliste 2025 kvzbw.de billing positions for dental labs
5 BEB-Preisliste 2024 itzgmbh.de image-based (scanned) - OCR required, see step 3

Pre-check for every PDF (30 seconds each):

# Open it in a browser or PDF viewer # Try to select and copy some text # If text copies - OK # If the page shows only an image - OCR problem (this is the BEB file)

Step 2.1 - Trim SGB V (optional, recommended):

The full SGB V is 577 pages and pulls in pharmacy and hospital content that can show up as citations for dental questions. If you see such noise in the answer sources, replace the document with a trimmed version containing only Part 3, sections 55 to 66 (the dental-related chapters), and re-index (delete the old document first).

3. Enable OCR for the image-based BEB file

Symptom without OCR: BEB citations are missing or wrong, while all other documents work fine. Reason: the BEB PDF pages are scanned images, so text extraction returns nothing.

Fix:

# Open WebUI, Admin, Settings, Documents # Turn ON the option PDF Extract Images (OCR) # Delete the old BEB entry in the knowledge base (important - otherwise the stale empty index stays) # Upload the BEB PDF again # Wait until the status shows processed

OCR is slower than normal extraction - a larger PDF can take several minutes. That is expected.

4. Create the knowledge base

# Open WebUI, Knowledge, create a new knowledge base # Name: Zahnarztabrechnung # Add documents: upload all five PDFs (BEB after the OCR step) # Wait until every document shows the status processed, no errors # Set permissions: user artz, access Read

Quick test (before the model):

# New chat session, attach the knowledge base Zahnarztabrechnung # Ask: What statutory co-payment applies to a crown? # Expected: an answer with visible source citations from the FZ-Kompendium 2025

5. Create the Zahn-Abrechnungs-Assistent model

# Open WebUI, Settings, Models, create # Name: Zahn-Abrechnungs-Assistent # Base model: qwen3.8-27b (from LM Studio) # Attach the knowledge base Zahnarztabrechnung # System prompt (German, direct style):

  Du bist ein Experte fuer die deutsche Zahnarzt- und Zahntechnikerabrechnung
  (GOA/GOZ, KZBV FZ-Kompendium, BEL und BEB, SGB V).
  Antworte direkt auf Basis der bereitgestellten Dokumente.
  Nenne immer:
  - die konkrete Positionsnummer
  - den Preis
  - die Edition der Preisliste (z. B. BEB 2024, BEL 2025)
  - das Quelldokument
  Stelle keine Rueckfragen. Wenn Informationen fehlen, sage das klar,
  statt zu raten.
  Dieses Tool erteilt keine Rechtsberatung.

# Disable the built-in Ask User tool for this model - this is the most common cause of the model asking “which tooth number?” instead of answering

6. End-to-end test

# Browser: http://<server-ip>:3000, log in as artz # Select the model Zahn-Abrechnungs-Assistent # Ask the following questions one by one:

Test question Expected answer elements
What GOZ position applies for a composite filling on an incisor? GOZ 2010, price, source
What does a full ceramic crown cost per BEB? BEB position number, price, edition 2024
What is the statutory co-payment for an inlay? FZ-Kompendium 2025, amount, source
What BEL position covers a partial denture? BEL position, price, edition 2025

Checklist for every answer:

* Source citation visible (document name and section) * Concrete position number and price * Edition stated (BEB 2024 / BEL 2025 / FZ 2025) * For missing information: a clear statement instead of a made-up answer

7. Troubleshooting

Symptom Cause Fix
Answer without sources, content seems made up RAG not connected to the model attach the knowledge base to the model and to the chat session
BEB gives no sensible citations PDF is image-based, no text layer enable OCR (step 3), delete and re-upload the document
SGB V citations show pharmacy or hospital noise 577-page full text is too broad trim to sections 55 to 66 (step 2.1), replace the document, re-index
Model asks questions instead of answering built-in Ask User tool active disable it in the model settings (step 5)
artz cannot see the knowledge base no permission set Knowledge, select the base, set Read access for artz
Slow first answer on a large document indexing and embedding in progress wait until the document shows processed, then retry
After a re-index, old citations still appear stale index entry delete the document from the knowledge base completely before re-uploading