Zum Hauptinhalt springen
tsecurity.de LIVE
Echtzeit-Radar & Feeds
Alle RSS Feeds
👥 Community & Social
Web Security TippsIntroducing the new Confluence integration with Google Chat(22.09.2026 um 19:40 Uhr)
Web Security TippsQuick notes in Take notes for me(22.09.2026 um 21:31 Uhr)
Sichere ProgrammierungSecurity improvements for SSH(22.09.2026 um 16:11 Uhr)
Sichere ProgrammierungKI-Akzeptanz: Wie Rewe digital einfach nur den Chatbot umbenannte(22.09.2026 um 18:00 Uhr)
Sichere ProgrammierungClaude Opus 5.5: Keeping safety ahead of capabilities(22.09.2026 um 20:59 Uhr)
Sichere ProgrammierungYour Terraform Monolith Isn't Too Big. It's Tightly Coupled.(22.09.2026 um 21:00 Uhr)
Sichere ProgrammierungMy PR got merged into Mike — OSS Legal AI Platform 🎉(22.09.2026 um 21:34 Uhr)
Sichere ProgrammierungStop Writing JavaScript To Fix `100vh` On Mobile(22.09.2026 um 21:35 Uhr)
Sichere ProgrammierungNext.js proxy.ts Explained (with Cheat Sheet)(22.09.2026 um 21:36 Uhr)
Web Security TippsIntroducing the new Confluence integration with Google Chat(22.09.2026 um 19:40 Uhr)
Web Security TippsQuick notes in Take notes for me(22.09.2026 um 21:31 Uhr)
Sichere ProgrammierungSecurity improvements for SSH(22.09.2026 um 16:11 Uhr)
Sichere ProgrammierungKI-Akzeptanz: Wie Rewe digital einfach nur den Chatbot umbenannte(22.09.2026 um 18:00 Uhr)
Sichere ProgrammierungClaude Opus 5.5: Keeping safety ahead of capabilities(22.09.2026 um 20:59 Uhr)
Sichere ProgrammierungYour Terraform Monolith Isn't Too Big. It's Tightly Coupled.(22.09.2026 um 21:00 Uhr)
Sichere ProgrammierungMy PR got merged into Mike — OSS Legal AI Platform 🎉(22.09.2026 um 21:34 Uhr)
Sichere ProgrammierungStop Writing JavaScript To Fix `100vh` On Mobile(22.09.2026 um 21:35 Uhr)
Sichere ProgrammierungNext.js proxy.ts Explained (with Cheat Sheet)(22.09.2026 um 21:36 Uhr)
Intelligence View
⚡ tsecurity.de Intelligence

Update of “Fun project of the week, Mermaid flowcharts generator!” — V2 and more…

Using LLMs to generate Mermaid flowcharts and don’t pay fees to sites! Introduction Following a previous post on how to generate Mermaid charts using Ollama and local LLMs (because I get really bored with sites which ask me t…

0
↗ Quelle (dev.to)
Reagiere als Erste:r — dein Feedback zählt!

Using LLMs to generate Mermaid flowcharts and don’t pay fees to sites!








Introduction



Following a previous post on how to generate Mermaid charts using Ollama and local LLMs (because I get really bored with sites which ask me to subscribe and pay a fee), I decided to enhance and update my application. There are two essential reasons for that;




  • My first app was containing hard-coded information regarding the LLM I want to use.

  • The application was not iterative.






🛠️ Essential Enhancements



The core of your enhancement should involve abstracting the LLM choice and creating a clean, repeatable workflow.






Dynamic LLM Selection (Addressing Hardcoded Info)



Instead of having a single hardcoded model, your application should dynamically discover and utilize any model available via your local Ollama instance.




  • Implement Model Discovery: The application must send a request to the Ollama API’s /api/tags endpoint (http://localhost:11434/api/tags). This endpoint returns a JSON list of all locally installed models.

  • Create a Selection Interface-CLI: Present the discovered list of models with numbered indices and prompt the user to choose one by number.

  • Create a Selection Interface-CLI with a GUI (Streamlit/other): Use a dropdown or radio button group populated by the retrieved model names.

  • Pass the Model Name: The chosen model name (e.g., llama3:8b-instruct-q4_0) must then be used as a variable in the payload for all subsequent API calls to the /api/chat endpoint.






Iterative Workflow and Error Handling (Addressing Iterativeness)



A non-iterative application forces a restart for every chart, which is frustrating. Iterativeness isn’t just about looping; it’s about handling success/failure gracefully within the same session.




  • Main Execution Loop: Wrap your primary logic (prompt user > call LLM > generate image) in a while True loop that only breaks when the user explicitly chooses to quit.

  • Session State (GUI): If you use a GUI framework like Streamlit (as we discussed previously), we must use Session State (st.session_state) to preserve the generated Mermaid code and the image path across button clicks and re-renders. This maintains the context of the user's current diagram.

  • Error Prevention/Debugging-Input Validation: Check if the user’s prompt is empty.

  • Error Prevention/Debugging-Connection Check: Check if the Ollama server is running before trying to fetch models or generate code.

  • File Handling Safety: Since it is creating temporary files for mmdc, ensure the cleanup logic is debuggable (e.g., only delete temp files if DEBUG_MODE is disabled).






And my ideas for V3… (to be continued)






| Enhancement                 | Description                                                  | Value Proposition                                            |
| --------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
| **Code Review/Repair Mode** | If `mmdc` fails to render (due to a syntax error), automatically send the Mermaid code *and* the `mmdc` error log back to the LLM (with a specific system prompt) to ask it to fix the syntax. | Reduces user frustration and automatically fixes common LLM-induced syntax errors. |
| **Diagram History** | Store the generated text prompt, the output code, and the corresponding image file path in a simple local database (like SQLite) or a structured file (like JSON/YAML). | Allows users to easily revisit and reuse past diagrams without regenerating them. |
| **Output Format Options** | Add options to output the diagram in formats other than PNG, such as **SVG** (better for scaling) or **PDF**. | Increases versatility for users needing high-quality vector graphics. |
| **Persistent Settings** | Save the last used LLM model to a configuration file (e.g., `config.json`). | Saves the user time by automatically selecting their preferred model upon startup. |









Code(s) and Implementation(s)






1 — The console version




  • Let’s jump into the first console mode application. As usual build a virtual Python environment.




pip install --upgrade pip
pip install requests

npm install -g @mermaid-js/mermaid-cli







  • And the code 🧑‍💻




# app_V3.py
import subprocess
import os
import requests
import json
import re
import glob
import sys
import time
from pathlib import Path

DEBUG_MODE = True

OLLAMA_BASE_URL = "http://localhost:11434"
OLLAMA_CHAT_URL = f"{OLLAMA_BASE_URL}/api/chat"
OLLAMA_TAGS_URL = f"{OLLAMA_BASE_URL}/api/tags"

INPUT_DIR = Path("./input")
OUTPUT_DIR = Path("./output")

def check_mmdc_installed():
"""Checks if 'mmdc' is installed."""
try:
subprocess.run(['mmdc', '--version'], check=True, capture_output=True, timeout=5)
return True
except (FileNotFoundError, subprocess.TimeoutExpired, subprocess.CalledProcessError):
print("Error: Mermaid CLI (mmdc) not found or misconfigured.")
print("Try: npm install -g @mermaid-js/mermaid-cli")
return False

# MODEL SELECTION
def get_installed_models():
"""Fetches locally installed Ollama models."""
try:
response = requests.get(OLLAMA_TAGS_URL, timeout=5)
response.raise_for_status()
return sorted([m['name'] for m in response.json().get('models', [])])
except:
return []

def select_model_interactive():
"""Interactive menu to choose a model."""
print("\n--- Ollama Model Selection ---")
models = get_installed_models()

if not models:
return input("No models found. Enter model name manually (e.g., llama3): ").strip() or "llama3"

for idx, model in enumerate(models, 1):
print(f"{idx}. {model}")

while True:
choice = input(f"\nSelect a model (1-{len(models)}) or type custom name: ").strip()
if choice.isdigit() and 1 <= int(choice) <= len(models):
return models[int(choice) - 1]
elif choice:
return choice

def clean_mermaid_code(code_string):
"""Clean common LLM formatting errors from Mermaid code."""
cleaned = code_string.replace(u'\xa0', ' ').replace(u'\u200b', '')

cleaned = cleaned.replace("```

mermaid
", "").replace("

```
", "")

cleaned = re.sub(r'[ \t\r\f\v]+', ' ', cleaned)

lines = cleaned.splitlines()
rebuilt = []
for line in lines:
s_line = line.strip()
if s_line:
rebuilt.append(s_line)

final = '\n'.join(rebuilt)
final = re.sub(r'(\])([A-Za-z0-9])', r'\1\n\2', final)
return final.strip()

def generate_mermaid_code(user_prompt, model_name):
"""Calls Ollama to generate the code."""
system_msg = (
"You are a Mermaid Diagram Generator. Output ONLY valid Mermaid code. "
"Do not include explanations. Start with 'graph TD' or 'flowchart LR'. "
"Use simple ASCII characters for node IDs."
)

payload = {
"model": model_name,
"messages": [{"role": "system", "content": system_msg}, {"role": "user", "content": user_prompt}],
"stream": False,
"options": {"temperature": 0.1}
}

try:
print(f"Thinking ({model_name})...")
response = requests.post(OLLAMA_CHAT_URL, json=payload, timeout=60)
response.raise_for_status()
content = response.json().get("message", {}).get("content", "").strip()

match = re.search(r"```

mermaid\n(.*?)\n

```
", content, re.DOTALL)
code = match.group(1) if match else content
return clean_mermaid_code(code)

except Exception as e:
print(f"Error communicating with Ollama: {e}")
return None

def translate_mermaid_to_image(mermaid_definition, output_path_base, output_format='png'):
"""Generates image from Mermaid code."""
if not check_mmdc_installed(): return False

output_path_base.parent.mkdir(parents=True, exist_ok=True)
output_file = output_path_base.with_suffix(f'.{output_format}')

temp_file = f"debug_{int(time.time())}.mmd"

try:
with open(temp_file, "w", encoding='utf-8') as f:
f.write(mermaid_definition)

command = ['mmdc', '-i', temp_file, '-o', str(output_file)]

process = subprocess.run(command, capture_output=True, text=True)

if process.returncode != 0:
print(f"\n❌ ERROR: mmdc failed for {output_file.name}")
print(f"--- STDERR ---\n{process.stderr}\n--------------")
if DEBUG_MODE:
print(f"⚠️ DEBUG MODE: Kept temporary file at: {os.path.abspath(temp_file)}")
print(" Open this file in a text editor to check for syntax errors.")
return False

print(f"✅ Saved: {output_file}")
return True

except Exception as e:
print(f"Unexpected error: {e}")
return False
finally:
if not DEBUG_MODE and os.path.exists(temp_file):
os.remove(temp_file)

def main():
print("Welcome to the Ollama Mermaid Generator (Debug Mode)")
if not check_mmdc_installed(): return

selected_model = select_model_interactive()
OUTPUT_DIR.mkdir(exist_ok=True)

while True:
choice = input("\n(1) Describe flowchart (2) Process files (q) Quit\n> ").strip().lower()

mermaid_codes = []

if choice == '1':
desc = input("Describe flowchart: ")
if not desc: continue
code = generate_mermaid_code(desc, selected_model)
if code:
name = f"chart_{int(time.time())}"
mermaid_codes.append((code, OUTPUT_DIR / name))

elif choice == '2':
if not INPUT_DIR.exists(): INPUT_DIR.mkdir(); print(f"Created {INPUT_DIR}"); continue
files = list(INPUT_DIR.glob('**/*.mmd'))
if not files: print("No files found."); continue
for f in files:
try:
code = clean_mermaid_code(f.read_text(encoding='utf-8'))
mermaid_codes.append((code, OUTPUT_DIR / f.relative_to(INPUT_DIR).with_suffix('')))
except Exception as e: print(f"Error reading {f}: {e}")

elif choice == 'q': break

for code, path in mermaid_codes:
print(f"\nProcessing {path.name}...")
if DEBUG_MODE:
print(f"--- Code Preview ---\n{code[:100]}...\n--------------------")

success = translate_mermaid_to_image(code, path)

if not success:
input("\n⚠️ Generation failed. Read errors above and press Enter to continue...")

if __name__ == "__main__":
main()







  • The output 📤




 python app_V3.py
Welcome to the Ollama Mermaid Generator (Debug Mode)

--- Ollama Model Selection ---
1. all-minilm:latest
2. deepseek-r1:latest
3. embeddinggemma:latest
4. granite-embedding:278m
5. granite-embedding:latest
6. granite3.2-vision:2b
7. granite3.3:latest
8. granite4:latest
9. granite4:micro-h
10. ibm/granite4:latest
11. ibm/granite4:micro
12. ibm/granite4:tiny-h
13. llama3.2-vision:latest
14. llama3:8b-instruct-q4_0
15. llama3:latest
16. ministral-3:latest
17. mistral:7b
18. mxbai-embed-large:latest
19. nomic-embed-text:latest
20. qwen3-vl:235b-cloud

Select a model (1-20) or type custom name: 8

(1) Describe flowchart (2) Process files (q) Quit
>







  • The generated sample result if you want to generate a flowchart mermaid (.mmd) file ☕




flowchart TD
subgraph Client_Application [Your_main2]
A[Input_Document_e_g_PDF] --> B[Docling_DocumentConverter_convert]
B --> C{Docling_Internal_Pipelines_and_Parser_Backends}
C -- PDF_Image_Processing --> D[OCR_Engine_e_g_EasyOCR]
C -- Layout_Analysis --> E[Layout_Model]
C -- Table_Recognition --> F[TableFormer_Model]
D & E & F --> G[Docling_Document_Object_Structured_Data]
G --> H[Iterate_Document_Elements]
H --> I{Text_Table_Item}
I -- Yes --> J[Call_translate_function]
J --> K[Ollama_Client_Python_ollama_library]
K -- REST_API_Call --> L[Ollama_Server]
L -- Loads --> M[Granite3_Dense_LLM]
M -- Translated_Text --> K
K --> J
J --> N[Update_Docling_Document_Object]
N --> H
H -- No_More_Elements --> O[Docling_Document_save_as_markdown]
O --> P[Translated_Markdown_Output]
end
subgraph Ollama_Service
L --- M
end
style A fill:#e0f7fa,stroke:#333,stroke-width:2px
style P fill:#e0f7fa,stroke:#333,stroke-width:2px
style B fill:#b3e5fc,stroke:#333,stroke-width:2px
style C fill:#c7eafc,stroke:#333,stroke-width:2px
style D fill:#dbeefc,stroke:#333,stroke-width:2px
style E fill:#dbeefc,stroke:#333,stroke-width:2px
style F fill:#dbeefc,stroke:#333,stroke-width:2px
style G fill:#e0f7fa,stroke:#333,stroke-width:2px
style H fill:#a7d9f7,stroke:#333,stroke-width:2px
style I fill:#b7e2f7,stroke:#333,stroke-width:2px
style J fill:#c7eafc,stroke:#333,stroke-width:2px
style K fill:#d7f1fc,stroke:#333,stroke-width:2px
style L fill:#e7f7fd,stroke:#333,stroke-width:2px
style M fill:#f7fcfd,stroke:#333,stroke-width:2px
style N fill:#a7d9f7,stroke:#333,stroke-width:2px
style O fill:#b3e5fc,stroke:#333,stroke-width:2px







  • Or if you want to give a definition and generate a visual flow;








2 — The GUI version using Streamlit




  • This version uses Streamlit to provide an enhanced interactive interface. Inside the virtual environment, we need to install the additional package.




# already done above
pip install --upgrade pip
pip install requests
npm install -g @mermaid-js/mermaid-cli
# new installation
pip install streamlit







  • And the code 🆓




# appST.py
import streamlit as st
import subprocess
import requests
import json
import re
import os
import time
from pathlib import Path

# --- Configuration ---
OLLAMA_BASE_URL = "http://localhost:11434"
OLLAMA_CHAT_URL = f"{OLLAMA_BASE_URL}/api/chat"
OLLAMA_TAGS_URL = f"{OLLAMA_BASE_URL}/api/tags"
OUTPUT_DIR = Path("./output")
OUTPUT_DIR.mkdir(exist_ok=True)

st.set_page_config(
page_title="Ollama Mermaid Architect",
page_icon="🎨",
layout="wide"
)

if 'mermaid_code' not in st.session_state:
st.session_state['mermaid_code'] = ""
if 'generated_image_path' not in st.session_state:
st.session_state['generated_image_path'] = None


def check_mmdc_installed():
"""Checks if mmdc is available."""
try:
subprocess.run(['mmdc', '--version'], check=True, capture_output=True, timeout=5)
return True
except:
return False

def get_installed_models():
"""Fetches models from Ollama."""
try:
response = requests.get(OLLAMA_TAGS_URL, timeout=2)
if response.status_code == 200:
return [m['name'] for m in response.json().get('models', [])]
return []
except:
return []

def clean_mermaid_code(code_string):
"""Cleans up LLM output."""
clean = re.sub(r'```

mermaid
', '', code_string, flags=re.IGNORECASE)
clean = re.sub(r'

```
', '', clean)

clean = clean.replace(u'\xa0', ' ').replace(u'\u200b', '')

lines = [line.strip() for line in clean.splitlines() if line.strip()]
return '\n'.join(lines)

def generate_code(prompt, model):
"""Calls Ollama API."""
system_msg = (
"You are a Mermaid Diagram Generator. "
"Output ONLY valid Mermaid code. Start with 'graph TD' or 'flowchart LR'. "
"Do NOT include explanations or markdown ticks."
)

payload = {
"model": model,
"messages": [
{"role": "system", "content": system_msg},
{"role": "user", "content": prompt}
],
"stream": False,
"options": {"temperature": 0.2}
}

try:
response = requests.post(OLLAMA_CHAT_URL, json=payload, timeout=60)
if response.status_code == 200:
content = response.json()['message']['content']
return clean_mermaid_code(content)
else:
st.error(f"Ollama Error: {response.text}")
return None
except Exception as e:
st.error(f"Connection Error: {e}")
return None

def render_diagram(mermaid_code):
"""Runs mmdc to generate an SVG for display."""
timestamp = int(time.time())
temp_mmd = OUTPUT_DIR / f"temp_{timestamp}.mmd"
output_svg = OUTPUT_DIR / f"diagram_{timestamp}.svg"

try:
with open(temp_mmd, "w", encoding='utf-8') as f:
f.write(mermaid_code)

cmd = ['mmdc', '-i', str(temp_mmd), '-o', str(output_svg), '-b', 'transparent']
result = subprocess.run(cmd, capture_output=True, text=True)

if result.returncode == 0:
return str(output_svg)
else:
st.error("Mermaid Compilation Failed:")
st.code(result.stderr)
return None

except Exception as e:
st.error(f"System Error: {e}")
return None
finally:
if temp_mmd.exists():
temp_mmd.unlink()

# --- GUI Layout ---

# Sidebar
with st.sidebar:
st.header("⚙️ Configuration")

if check_mmdc_installed():
st.success("Mermaid CLI: Detected ✅")
else:
st.error("Mermaid CLI: Not Found ❌")
st.info("Run: `npm install -g @mermaid-js/mermaid-cli`")
st.stop()

models = get_installed_models()
if models:
selected_model = st.selectbox("Select Ollama Model", models, index=0)
else:
st.warning("Ollama not detected or no models found.")
selected_model = st.text_input("Manually enter model name", "llama3")

st.markdown("---")
st.markdown("### Tips")
st.markdown("- Be specific about direction (Top-Down vs Left-Right).")
st.markdown("- Mention specific node shapes if needed.")

st.title("🎨 Ollama Mermaid Architect")
st.markdown("Generate, Visualize, and Edit flowcharts using local LLMs.")

user_prompt = st.text_area("Describe your flowchart:", height=100, placeholder="e.g. Create a flowchart for a login process including password reset...")

col1, col2 = st.columns([1, 5])
with col1:
generate_btn = st.button("🚀 Generate", type="primary")

if generate_btn and user_prompt:
with st.spinner(f"Asking {selected_model} to design your chart..."):
generated_code = generate_code(user_prompt, selected_model)

if generated_code:
st.session_state['mermaid_code'] = generated_code
svg_path = render_diagram(generated_code)
st.session_state['generated_image_path'] = svg_path

if st.session_state['mermaid_code']:
st.markdown("---")

tab_visual, tab_code = st.tabs(["🖼️ Diagram Visualization", "📝 Edit Code"])

with tab_visual:
if st.session_state['generated_image_path'] and os.path.exists(st.session_state['generated_image_path']):
st.image(st.session_state['generated_image_path'], use_container_width=True)

with open(st.session_state['generated_image_path'], "rb") as file:
btn = st.download_button(
label="📥 Download SVG",
data=file,
file_name="flowchart.svg",
mime="image/svg+xml"
)
else:
st.warning("No image generated yet or generation failed.")

with tab_code:
st.info("You can edit the code below and press 'Update' to re-render.")
edited_code = st.text_area("Mermaid Code", st.session_state['mermaid_code'], height=300)

if st.button("🔄 Update Diagram"):
st.session_state['mermaid_code'] = edited_code
new_svg_path = render_diagram(edited_code)
if new_svg_path:
st.session_state['generated_image_path'] = new_svg_path
st.rerun() # Refresh to show new image







  • Run the code 🏃‍➡️




streamlit run appST.py

You can now view your Streamlit app in your browser.

Local URL: http://localhost:8501
Network URL: http://192.168.1.148:8501












That’s a wrap, thanks for reading 😅






🎯 Conclusion: Empowering Local Diagram Generation



In summary, we’ve successfully developed a powerful, fully local and iterative application for generating Mermaid flowcharts using Ollama and local Large Language Models (LLMs). This process demonstrates that tasks such as diagram generation — can be achieved effectively and flexibly using open-source tools and local computation, entirely eliminating the need for subscription-based services.






Links



Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Update of “Fun project of the week, Mermaid flowcharts generator!” — V2 and more…

Thematisch verwandte Begriffe: Update, project, week, Mermaid · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-77259 | MCP Atlassian is a Model Context Protocol (MCP) server for Atlassian pro…
Advisory →
TTS Reader • tsecurity.de Voice
tsecurity.de Icon
tsecurity.de App
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag
Themen-Radar & Intelligence Matrix
Echtzeit-Taxonomie nach Angriffsvektoren & Plattformen

tsecurity.de Live Threat Radar

🔴 LIVE RADAR
MONITORING
AKTIV
CVE-DATENBANK
LIVE
🔍
Community Radar & Live Chat
Sentinel Bot online • Live-Stream
Dein Cluster: Security Explorer
Match:
lädt…
Verbindung zum Community-Stream wird aufgebaut...
Bearbeitungsmodus — Senden überschreibt deine Nachricht
Community-Puls — was gerade passiert
lädt…
Aktivitäten deiner Analysten
lädt…
Neues Thema oder Eilmeldung einreichen

Reiche interessante Links, Zero-Days oder Debatten ein. Die Community entscheidet per Upvote über die Veröffentlichung.

Heiß diskutierte Einreichungen
🔖 Gespeicherte Artikel
📂 Keine gespeicherten Artikel vorhanden.
Zurück Ziehen Vor
Links: vorheriger Artikel Rechts: nächster Artikel unten: schließen
News NIS-2 Frühwarnung Tier-1 Intel ⏱️ 3 Min vor 10 Min
Artikeldaten werden geladen...

Zurück: vorheriger Vor: nächster
↗ Original-Quelle
Social Reaktionen Deine Reaktion zählt
Einstufung & Relevanz-Poll 0 Stimmen
In sozialen Netzwerken teilen 1-Klick