
KLs webinarserie om generativ AI indeholder forskellige sessioner med fokus på brug og udvikling af AI i kommunale sammenhænge. Et bemærkelsesværdigt casestudie er fra Gladsaxe Kommune, hvor de udforsker den praktiske anvendelse af AI gennem specialiserede chatbots, der hjælper medarbejderne i deres daglige opgaver.
Dette initiativ er en del af en bredere indsats fra Danish Language Model Consortium, ledet af IBM, Erhvervsstyrelsen og Alexandra Instituttet, for at udvikle fremtidens danske sprogmodeller gennem offentligt-privat samarbejde. Læs mere her. Se hele webinaret her (casestudie med Gladsaxe starter ved 53 minutter).
Vi føler os meget beærede over, at Gladsaxe har valgt Applai som deres partner for generativ AI. Under webinaret præsenterede Thomas Lerche (Digitaliseringschef i Gladsaxe Kommune) sine resultater fra de tidlige faser af projektet med Applai. Her er hans vigtigste resultater:
Problemet
Gladsaxe Kommune spurgte deres medarbejder, hvad de manglede fra ChatGPT. Med andre ord, hvilke use cases kunne ikke løses ved hjælp af ChatGPT? Medarbejderne svarede og sagde ting som; "Vi vil gerne have en nem måde at få klar vejledning i, hvordan man bruger AULA." og "vi er 80 sagsbehandlere, der hurtigt skal forstå den nye 'børnelov', så vi kan reducere den tid, der bruges på at søge information."
Fordelene
Kvalitet i svar
Specialiserede AI-assistenter kan levere svar af højere kvalitet, der er skræddersyet og trænet til specifikke områder.
Troværdighed og gennemsigtighed
Assistenterne tilbyder en højere grad af troværdighed ved at citere deres kilder og lave færre gæt.
Strømlining af arbejdsgange
Specialiserede AI-assistenter kan understøtte og strømline specifikke arbejdsgange og hjælpe med at træne nye medarbejdere.
(() => {
const body = document.body;
const navRoot = document.querySelector('._58ce83d8');
if (!body || !navRoot) {
return;
}
const isHomepage = body.classList.contains('promte-nav-home');
const isProductsHeroPage = body.classList.contains('promte-nav-products-hero');
const logos = Array.from(document.querySelectorAll('.promte-navLogoImage'));
const languageLinks = Array.from(document.querySelectorAll('[data-promte-language-link="true"]'));
const hero = document.querySelector('.products-hero');
const heroGrid = hero ? hero.querySelector('.products-heroGrid') : null;
const heroSignals = hero ? hero.querySelector('.products-heroSignals') : null;
const heroCarouselHint = hero ? hero.querySelector('.products-heroCarouselHint') : null;
const heroCarouselCount = hero ? hero.querySelector('[data-products-hero-carousel-count]') : null;
const heroCarouselDots = hero ? Array.from(hero.querySelectorAll('.products-heroCarouselHintDot')) : [];
const heroCarouselArrow = hero ? hero.querySelector('.products-heroCarouselHintArrow') : null;
const heroBackground = hero ? hero.querySelector('.products-heroBackground') : null;
const heroDeviceDesktop = hero ? hero.querySelector('.products-heroDeviceDesktop') : null;
const heroDevicePhone = hero ? hero.querySelector('.products-heroDevicePhone') : null;
const heroLogoRail = hero ? hero.querySelector('.products-logoRail') : null;
const heroLogoViewport = hero ? hero.querySelector('.products-logoMarqueeViewport') : null;
const productsCardsLayout = document.querySelector('.products-scrollLayout');
const productsCardsStack = productsCardsLayout ? productsCardsLayout.querySelector('.products-scrollStack') : null;
const productsCardsHint = productsCardsLayout ? productsCardsLayout.querySelector('.products-cardsCarouselHint') : null;
const productsCardsCount = productsCardsLayout ? productsCardsLayout.querySelector('[data-products-cards-carousel-count]') : null;
const productsCardsDotsRoot = productsCardsLayout ? productsCardsLayout.querySelector('[data-products-cards-carousel-dots]') : null;
const productsCardsArrow = productsCardsLayout ? productsCardsLayout.querySelector('.products-cardsCarouselHintArrow') : null;
const deploymentGrid = document.querySelector('.products-deploymentGrid');
const deploymentHint = document.querySelector('.products-deploymentCarouselHint');
const deploymentCount = document.querySelector('[data-products-deployment-carousel-count]');
const deploymentDotsRoot = document.querySelector('[data-products-deployment-carousel-dots]');
const deploymentArrow = document.querySelector('.products-deploymentCarouselHintArrow');
const casesGrid = document.querySelector('.products-casesGrid');
const casesHint = document.querySelector('.products-casesCarouselHint');
const casesCount = document.querySelector('[data-products-cases-carousel-count]');
const casesDotsRoot = document.querySelector('[data-products-cases-carousel-dots]');
const casesArrow = document.querySelector('.products-casesCarouselHintArrow');
let frame = 0;
const prefetchedLanguages = new Set();
const getHeroDeviceLayout = () => {
if (window.innerWidth <= 520) {
return { shift: 18, scale: 0.72 };
}
if (window.innerWidth <= 720) {
return { shift: 22, scale: 0.78 };
}
if (window.innerWidth <= 860) {
return { shift: 52, scale: 0.88 };
}
if (window.innerWidth <= 920) {
return { shift: 86, scale: 1 };
}
if (window.innerWidth <= 1100) {
return { shift: 96, scale: 1 };
}
if (window.innerHeight <= 900 && window.innerWidth >= 861) {
return { shift: 92, scale: 0.82 };
}
return { shift: 120, scale: 1 };
};
const applyHeroDeviceTransforms = (fitScale) => {
if (!heroDeviceDesktop || !heroDevicePhone) {
return;
}
const { shift, scale } = getHeroDeviceLayout();
const finalScale = Math.max(0.42, scale * fitScale);
heroDeviceDesktop.style.transform = `translate(calc(-50% - ${shift}px + (${shift}px * var(--products-hero-device-progress-local, 0))), -50%) scale(${finalScale.toFixed(4)})`;
heroDevicePhone.style.transform = `translate(calc(-50% + ${shift}px - (${shift}px * var(--products-hero-device-progress-local, 0))), -50%) scale(${finalScale.toFixed(4)})`;
};
const getHeroSignalGutter = () => {
if (!heroSignals) {
return 0;
}
const raw = window.getComputedStyle(heroSignals).paddingLeft;
const parsed = Number.parseFloat(raw || '0');
return Number.isFinite(parsed) ? parsed : 0;
};
const updateHeroCarouselHint = () => {
if (!heroSignals || !heroCarouselHint) {
return;
}
const cards = Array.from(heroSignals.querySelectorAll('.products-heroSignal'));
const canScroll = heroSignals.scrollWidth - heroSignals.clientWidth > 8;
const isCarousel = heroSignals.classList.contains('products-heroSignals--carousel') && cards.length > 1 && canScroll;
heroCarouselHint.hidden = !isCarousel;
if (!isCarousel) {
return;
}
const heroSignalGutter = getHeroSignalGutter();
let activeIndex = 0;
let bestDistance = Number.POSITIVE_INFINITY;
cards.forEach((card, index) => {
const distance = Math.abs((card.offsetLeft - heroSignalGutter) - heroSignals.scrollLeft);
if (distance < bestDistance) {
bestDistance = distance;
activeIndex = index;
}
});
if (heroCarouselCount) {
heroCarouselCount.textContent = `${activeIndex + 1} / ${cards.length}`;
}
heroCarouselDots.forEach((dot, index) => {
dot.classList.toggle('is-active', index === activeIndex);
});
if (heroCarouselArrow instanceof HTMLButtonElement) {
heroCarouselArrow.hidden = activeIndex >= cards.length - 1;
}
};
const syncProductsCardsCarouselDots = (count) => {
if (!productsCardsDotsRoot) {
return;
}
const currentCount = productsCardsDotsRoot.querySelectorAll('.products-cardsCarouselHintDot').length;
if (currentCount === count) {
return;
}
productsCardsDotsRoot.textContent = '';
for (let index = 0; index < count; index += 1) {
const dot = document.createElement('span');
dot.className = `products-cardsCarouselHintDot${index === 0 ? ' is-active' : ''}`;
productsCardsDotsRoot.appendChild(dot);
}
};
const updateProductsCardsCarouselHint = () => {
if (!productsCardsStack || !productsCardsHint) {
return;
}
const cards = Array.from(productsCardsStack.querySelectorAll('.products-scrollCard'));
const canScroll = productsCardsStack.scrollWidth - productsCardsStack.clientWidth > 8;
const isCarousel = window.innerWidth <= 700 && cards.length > 1 && canScroll;
productsCardsHint.hidden = !isCarousel;
if (!isCarousel) {
return;
}
syncProductsCardsCarouselDots(cards.length);
let activeIndex = 0;
let bestDistance = Number.POSITIVE_INFINITY;
cards.forEach((card, index) => {
const distance = Math.abs(card.offsetLeft - productsCardsStack.scrollLeft);
if (distance < bestDistance) {
bestDistance = distance;
activeIndex = index;
}
});
if (productsCardsCount) {
productsCardsCount.textContent = `${activeIndex + 1} / ${cards.length}`;
}
if (productsCardsDotsRoot) {
Array.from(productsCardsDotsRoot.querySelectorAll('.products-cardsCarouselHintDot')).forEach((dot, index) => {
dot.classList.toggle('is-active', index === activeIndex);
});
}
if (productsCardsArrow instanceof HTMLButtonElement) {
productsCardsArrow.hidden = activeIndex >= cards.length - 1;
}
};
const syncDeploymentCarouselDots = (count) => {
if (!deploymentDotsRoot) {
return;
}
const currentCount = deploymentDotsRoot.querySelectorAll('.products-deploymentCarouselHintDot').length;
if (currentCount === count) {
return;
}
deploymentDotsRoot.textContent = '';
for (let index = 0; index < count; index += 1) {
const dot = document.createElement('span');
dot.className = `products-deploymentCarouselHintDot${index === 0 ? ' is-active' : ''}`;
deploymentDotsRoot.appendChild(dot);
}
};
const updateDeploymentCarouselHint = () => {
if (!deploymentGrid || !deploymentHint) {
return;
}
const cards = Array.from(deploymentGrid.querySelectorAll('.products-deploymentCard'));
const canScroll = deploymentGrid.scrollWidth - deploymentGrid.clientWidth > 8;
const isCarousel = window.innerWidth <= 720 && cards.length > 1 && canScroll;
deploymentHint.hidden = !isCarousel;
if (!isCarousel) {
return;
}
syncDeploymentCarouselDots(cards.length);
let activeIndex = 0;
let bestDistance = Number.POSITIVE_INFINITY;
cards.forEach((card, index) => {
const distance = Math.abs(card.offsetLeft - deploymentGrid.scrollLeft);
if (distance < bestDistance) {
bestDistance = distance;
activeIndex = index;
}
});
if (deploymentCount) {
deploymentCount.textContent = `${activeIndex + 1} / ${cards.length}`;
}
if (deploymentDotsRoot) {
Array.from(deploymentDotsRoot.querySelectorAll('.products-deploymentCarouselHintDot')).forEach((dot, index) => {
dot.classList.toggle('is-active', index === activeIndex);
});
}
if (deploymentArrow instanceof HTMLButtonElement) {
deploymentArrow.hidden = activeIndex >= cards.length - 1;
}
};
const syncCasesCarouselDots = (count) => {
if (!casesDotsRoot) {
return;
}
const currentCount = casesDotsRoot.querySelectorAll('.products-casesCarouselHintDot').length;
if (currentCount === count) {
return;
}
casesDotsRoot.textContent = '';
for (let index = 0; index < count; index += 1) {
const dot = document.createElement('span');
dot.className = `products-casesCarouselHintDot${index === 0 ? ' is-active' : ''}`;
casesDotsRoot.appendChild(dot);
}
};
const updateCasesCarouselHint = () => {
if (!casesGrid || !casesHint) {
return;
}
const cards = Array.from(casesGrid.querySelectorAll('.products-caseCard'));
const canScroll = casesGrid.scrollWidth - casesGrid.clientWidth > 8;
const isCarousel = window.innerWidth <= 700 && cards.length > 1 && canScroll;
casesHint.hidden = !isCarousel;
if (!isCarousel) {
return;
}
syncCasesCarouselDots(cards.length);
let activeIndex = 0;
let bestDistance = Number.POSITIVE_INFINITY;
cards.forEach((card, index) => {
const distance = Math.abs(card.offsetLeft - casesGrid.scrollLeft);
if (distance < bestDistance) {
bestDistance = distance;
activeIndex = index;
}
});
if (casesCount) {
casesCount.textContent = `${activeIndex + 1} / ${cards.length}`;
}
if (casesDotsRoot) {
Array.from(casesDotsRoot.querySelectorAll('.products-casesCarouselHintDot')).forEach((dot, index) => {
dot.classList.toggle('is-active', index === activeIndex);
});
}
if (casesArrow instanceof HTMLButtonElement) {
casesArrow.hidden = activeIndex >= cards.length - 1;
}
};
const prefetchLanguagePage = (href) => {
if (!href || prefetchedLanguages.has(href)) {
return;
}
prefetchedLanguages.add(href);
const prefetchLink = document.createElement('link');
prefetchLink.rel = 'prefetch';
prefetchLink.as = 'document';
prefetchLink.href = href;
document.head.appendChild(prefetchLink);
window.fetch(href, { credentials: 'same-origin' }).catch(() => {});
};
const updateState = () => {
const usesTransparentTopState = isHomepage || isProductsHeroPage;
const solid = usesTransparentTopState ? window.scrollY > 8 : true;
body.classList.toggle('promte-nav-solid', solid);
logos.forEach((logo) => {
const nextSrc = solid ? logo.dataset.solidSrc : (logo.dataset.transparentSrc || logo.dataset.solidSrc);
if (nextSrc && logo.getAttribute('src') !== nextSrc) {
logo.setAttribute('src', nextSrc);
}
});
if (hero) {
const progress = Math.min(Math.max((0 - hero.getBoundingClientRect().top) / 260, 0), 1);
document.documentElement.style.setProperty('--products-hero-device-progress', progress.toFixed(4));
}
if (hero && heroBackground && heroDeviceDesktop && heroDevicePhone) {
applyHeroDeviceTransforms(1);
const backgroundRect = heroBackground.getBoundingClientRect();
const heroGridRect = heroGrid ? heroGrid.getBoundingClientRect() : null;
const boundedTrackWidth = heroGridRect ? Math.min(backgroundRect.width, heroGridRect.width) : backgroundRect.width;
const logoRailOffset = heroGridRect ? backgroundRect.left - heroGridRect.left : 0;
if (heroSignals) {
heroSignals.style.width = `${boundedTrackWidth.toFixed(2)}px`;
heroSignals.style.maxWidth = `${boundedTrackWidth.toFixed(2)}px`;
}
if (heroCarouselHint) {
heroCarouselHint.style.width = `${backgroundRect.width.toFixed(2)}px`;
heroCarouselHint.style.maxWidth = `${backgroundRect.width.toFixed(2)}px`;
heroCarouselHint.style.marginLeft = `${logoRailOffset.toFixed(2)}px`;
heroCarouselHint.style.marginRight = '0px';
}
if (heroLogoRail) {
heroLogoRail.style.width = `${backgroundRect.width.toFixed(2)}px`;
heroLogoRail.style.maxWidth = `${backgroundRect.width.toFixed(2)}px`;
heroLogoRail.style.marginLeft = `${logoRailOffset.toFixed(2)}px`;
heroLogoRail.style.transform = 'translateY(0px)';
}
if (heroLogoViewport) {
heroLogoViewport.style.width = '100%';
heroLogoViewport.style.maxWidth = '100%';
}
const desktopRect = heroDeviceDesktop.getBoundingClientRect();
const phoneRect = heroDevicePhone.getBoundingClientRect();
const deviceUnionLeft = Math.min(desktopRect.left, phoneRect.left);
const deviceUnionRight = Math.max(desktopRect.right, phoneRect.right);
const deviceUnionTop = Math.min(desktopRect.top, phoneRect.top);
const deviceUnionBottom = Math.max(desktopRect.bottom, phoneRect.bottom);
const deviceUnionWidth = Math.max(deviceUnionRight - deviceUnionLeft, 1);
const deviceUnionHeight = Math.max(deviceUnionBottom - deviceUnionTop, 1);
const maxDeviceWidth = Math.max(backgroundRect.width - 36, 1);
const maxDeviceHeight = Math.max(backgroundRect.bottom - deviceUnionTop - 20, 1);
const widthFitScale = Math.min(1, maxDeviceWidth / deviceUnionWidth);
const heightFitScale = Math.min(1, maxDeviceHeight / deviceUnionHeight);
const fitScale = Math.min(widthFitScale, heightFitScale);
applyHeroDeviceTransforms(fitScale);
}
if (heroSignals && heroBackground) {
heroSignals.classList.remove('products-heroSignals--carousel');
const signalCards = Array.from(heroSignals.querySelectorAll('.products-heroSignal'));
const backgroundRect = heroBackground.getBoundingClientRect();
const heroSignalGutter = getHeroSignalGutter();
const availableWidth = Math.max(backgroundRect.width - (heroSignalGutter * 2), 1);
const carouselCardWidth = window.innerWidth <= 520
? Math.max(248, availableWidth - 72)
: window.innerWidth <= 720
? Math.max(264, availableWidth - 88)
: Math.max(272, (availableWidth - 12) / 2);
heroSignals.style.setProperty('--products-hero-carousel-card-width', `${carouselCardWidth.toFixed(2)}px`);
const shouldUseCarousel = window.innerWidth <= 720 || signalCards.some((card) => {
const rect = card.getBoundingClientRect();
return rect.left < backgroundRect.left + heroSignalGutter + 1 || rect.right > backgroundRect.right - heroSignalGutter - 1;
});
heroSignals.classList.toggle('products-heroSignals--carousel', shouldUseCarousel);
updateHeroCarouselHint();
if (heroCarouselHint) {
heroCarouselHint.style.transform = 'translateY(0px)';
}
if (heroLogoRail) {
heroLogoRail.style.transform = 'translateY(0px)';
}
}
updateProductsCardsCarouselHint();
updateDeploymentCarouselHint();
updateCasesCarouselHint();
};
const requestUpdate = () => {
if (frame) {
return;
}
frame = window.requestAnimationFrame(() => {
frame = 0;
updateState();
});
};
updateState();
window.addEventListener('scroll', requestUpdate, { passive: true });
window.addEventListener('resize', requestUpdate);
if (heroSignals) {
heroSignals.addEventListener('scroll', updateHeroCarouselHint, { passive: true });
}
if (productsCardsStack) {
productsCardsStack.addEventListener('scroll', updateProductsCardsCarouselHint, { passive: true });
}
if (deploymentGrid) {
deploymentGrid.addEventListener('scroll', updateDeploymentCarouselHint, { passive: true });
}
if (casesGrid) {
casesGrid.addEventListener('scroll', updateCasesCarouselHint, { passive: true });
}
if (heroSignals && heroCarouselArrow instanceof HTMLButtonElement) {
heroCarouselArrow.addEventListener('click', () => {
const cards = Array.from(heroSignals.querySelectorAll('.products-heroSignal'));
if (!cards.length) {
return;
}
const heroSignalGutter = getHeroSignalGutter();
let activeIndex = 0;
let bestDistance = Number.POSITIVE_INFINITY;
cards.forEach((card, index) => {
const distance = Math.abs((card.offsetLeft - heroSignalGutter) - heroSignals.scrollLeft);
if (distance < bestDistance) {
bestDistance = distance;
activeIndex = index;
}
});
const nextCard = cards[Math.min(activeIndex + 1, cards.length - 1)];
heroSignals.scrollTo({ left: Math.max(nextCard.offsetLeft - heroSignalGutter, 0), behavior: 'smooth' });
});
}
if (productsCardsStack && productsCardsArrow instanceof HTMLButtonElement) {
productsCardsArrow.addEventListener('click', () => {
const cards = Array.from(productsCardsStack.querySelectorAll('.products-scrollCard'));
if (!cards.length) {
return;
}
let activeIndex = 0;
let bestDistance = Number.POSITIVE_INFINITY;
cards.forEach((card, index) => {
const distance = Math.abs(card.offsetLeft - productsCardsStack.scrollLeft);
if (distance < bestDistance) {
bestDistance = distance;
activeIndex = index;
}
});
const nextCard = cards[Math.min(activeIndex + 1, cards.length - 1)];
productsCardsStack.scrollTo({ left: nextCard.offsetLeft, behavior: 'smooth' });
});
}
if (deploymentGrid && deploymentArrow instanceof HTMLButtonElement) {
deploymentArrow.addEventListener('click', () => {
const cards = Array.from(deploymentGrid.querySelectorAll('.products-deploymentCard'));
if (!cards.length) {
return;
}
let activeIndex = 0;
let bestDistance = Number.POSITIVE_INFINITY;
cards.forEach((card, index) => {
const distance = Math.abs(card.offsetLeft - deploymentGrid.scrollLeft);
if (distance < bestDistance) {
bestDistance = distance;
activeIndex = index;
}
});
const nextCard = cards[Math.min(activeIndex + 1, cards.length - 1)];
deploymentGrid.scrollTo({ left: nextCard.offsetLeft, behavior: 'smooth' });
});
}
if (casesGrid && casesArrow instanceof HTMLButtonElement) {
casesArrow.addEventListener('click', () => {
const cards = Array.from(casesGrid.querySelectorAll('.products-caseCard'));
if (!cards.length) {
return;
}
let activeIndex = 0;
let bestDistance = Number.POSITIVE_INFINITY;
cards.forEach((card, index) => {
const distance = Math.abs(card.offsetLeft - casesGrid.scrollLeft);
if (distance < bestDistance) {
bestDistance = distance;
activeIndex = index;
}
});
const nextCard = cards[Math.min(activeIndex + 1, cards.length - 1)];
casesGrid.scrollTo({ left: nextCard.offsetLeft, behavior: 'smooth' });
});
}
if ('ResizeObserver' in window) {
const resizeObserver = new ResizeObserver(requestUpdate);
if (hero) {
resizeObserver.observe(hero);
}
if (heroSignals) {
resizeObserver.observe(heroSignals);
}
if (heroBackground) {
resizeObserver.observe(heroBackground);
}
if (productsCardsLayout) {
resizeObserver.observe(productsCardsLayout);
}
if (productsCardsStack) {
resizeObserver.observe(productsCardsStack);
}
if (deploymentGrid) {
resizeObserver.observe(deploymentGrid);
}
if (casesGrid) {
resizeObserver.observe(casesGrid);
}
}
languageLinks.forEach((link) => {
if (!(link instanceof HTMLAnchorElement)) {
return;
}
const href = link.href;
const triggerPrefetch = () => prefetchLanguagePage(href);
link.addEventListener('pointerenter', triggerPrefetch, { passive: true, once: true });
link.addEventListener('focus', triggerPrefetch, { passive: true, once: true });
link.addEventListener('touchstart', triggerPrefetch, { passive: true, once: true });
});
})();