diff --git a/packages/dashboard/index.html b/packages/dashboard/index.html
index ace08aa..2796668 100644
--- a/packages/dashboard/index.html
+++ b/packages/dashboard/index.html
@@ -1206,6 +1206,99 @@
+
+
+
+
+
+ π€ Blog Generation LLM
+ loadingβ¦
+
+
+
+
+
+
+ Active model:
+ β
+ β
+
+
+
+
+
+
+
+
+
+ π§
+ claude-sonnet-4-6
+ RECOMMENDED
+
+
+
β
β
β
β
β
Blog quality
+
β
β
β
β
β Speed (API latency)
+
β Multi-constraint prompts
+
β No mode collapse
+
β 4096 token output
+
Provider: Anthropic API
+
+
+ BLOG_LLM_PROVIDER=anthropic
ANTHROPIC_MODEL=claude-sonnet-4-6
+
+
checkingβ¦
+
+
+
+
+
+ π―
+ fo-blog-v3-qwen7b
+ ACTIVE
+
+
+
β
β
β
β
β Blog quality
+
β
β
β
β
β
Speed (local GPU)
+
β Fine-tuned on TIP style
+
β Privacy (runs locally)
+
β Occasional mode collapse
+
Provider: Ollama / Mac Studio
+
+
+ BLOG_LLM_PROVIDER=ollama
OLLAMA_LLM_MODEL=fo-blog-v3-qwen7b
+
+
checkingβ¦
+
+
+
+
+
+ β‘
+ qwen2.5:14b
+
+
+
β
β
β
ββ Blog quality
+
β
β
β
β
β Speed (local GPU)
+
β General purpose
+
β No API cost
+
β Mode collapse on complex prompts
+
Provider: Ollama / Mac Studio
+
+
+ BLOG_LLM_PROVIDER=ollama
OLLAMA_LLM_MODEL=qwen2.5:14b
+
+
local model
+
+
+
+
+
+
+ Modell wechseln:
+ SSH β Erik β nano /opt/tip/ecosystem.config.js β BLOG_LLM_PROVIDER + ANTHROPIC_API_KEY setzen β pm2 restart tip-api --update-env
+
+
+
Hot Topics auto-discovered from market data + conferences
@@ -1874,7 +1967,7 @@ function goToTab(tabName) {
if (tabName === 'news') loadNews(1);
if (tabName === 'vendors') loadVendors();
if (tabName === 'standards') loadStandardsList();
- if (tabName === 'blog') { loadBlogDrafts(); loadSLLInsights(); }
+ if (tabName === 'blog') { loadBlogDrafts(); loadSLLInsights(); loadBlogLLMStatus(); }
if (tabName === 'finder') document.getElementById('finder-switch-input').focus();
if (tabName === 'crawlers') loadCrawlerStatus();
if (tabName === 'procurement') loadProcurement();
@@ -4301,6 +4394,69 @@ async function runFinder() {
+async function loadBlogLLMStatus() {
+ try {
+ var data = await api('/api/blog/llm/status');
+ var llm = data.llm || {};
+ var badge = document.getElementById('blog-llm-status-badge');
+ var activeModel = document.getElementById('blog-llm-active-model');
+ var activeProvider = document.getElementById('blog-llm-active-provider');
+ var queueEl = document.getElementById('blog-llm-queue');
+
+ if (badge) {
+ badge.textContent = llm.ok ? 'online' : 'offline';
+ badge.style.background = llm.ok ? 'rgba(34,197,94,0.2)' : 'rgba(193,18,31,0.2)';
+ badge.style.color = llm.ok ? '#86efac' : '#f87171';
+ }
+ if (activeModel) activeModel.textContent = llm.model || 'β';
+ if (activeProvider) {
+ activeProvider.textContent = llm.provider || 'β';
+ activeProvider.style.background = llm.provider === 'anthropic' ? 'rgba(124,92,252,0.2)' : 'rgba(34,197,94,0.15)';
+ activeProvider.style.color = llm.provider === 'anthropic' ? '#a78bfa' : '#86efac';
+ }
+ if (queueEl) {
+ var q = data.queue_depth || 0;
+ queueEl.textContent = q > 0 ? 'Queue: ' + q + ' jobs' : 'Queue: idle';
+ }
+
+ // Mark active model card
+ var foActive = document.getElementById('blog-model-fo-active');
+ var foCard = document.getElementById('blog-model-card-fo');
+ var claudeCard = document.getElementById('blog-model-card-claude');
+
+ if (llm.provider === 'anthropic') {
+ if (claudeCard) claudeCard.style.border = '1px solid rgba(124,92,252,0.6)';
+ claudeCard.style.background = 'rgba(124,92,252,0.1)';
+ var claudeStatusEl = document.getElementById('blog-model-claude-status');
+ if (claudeStatusEl) {
+ claudeStatusEl.textContent = 'β ACTIVE β API key configured';
+ claudeStatusEl.style.color = '#a78bfa';
+ }
+ document.getElementById('blog-model-fo-status').textContent = 'available (not active)';
+ } else {
+ // Ollama active
+ if (foActive) foActive.style.display = 'inline';
+ if (foCard) {
+ foCard.style.border = '1px solid rgba(34,197,94,0.5)';
+ foCard.style.background = 'rgba(34,197,94,0.08)';
+ }
+ var foStatusEl = document.getElementById('blog-model-fo-status');
+ if (foStatusEl) {
+ foStatusEl.textContent = llm.ok ? 'β ACTIVE β Ollama reachable' : 'β Ollama unreachable: ' + (llm.error || 'check connection');
+ foStatusEl.style.color = llm.ok ? '#86efac' : '#fbbf24';
+ }
+ var claudeStatusEl2 = document.getElementById('blog-model-claude-status');
+ if (claudeStatusEl2) {
+ claudeStatusEl2.textContent = 'available β set BLOG_LLM_PROVIDER=anthropic + ANTHROPIC_API_KEY';
+ claudeStatusEl2.style.color = 'var(--text-dim)';
+ }
+ }
+ } catch(e) {
+ var b = document.getElementById('blog-llm-status-badge');
+ if (b) { b.textContent = 'error'; b.style.color = '#f87171'; }
+ }
+}
+
async function loadBlogDrafts() {
var data = await api('/api/blog');
// Check which drafts are still generating (in-progress pipelines)