feat: add 'coming soon' empty state for projects page & gitignore public dir
All checks were successful
Build and Push Docker Container / build-and-push (push) Successful in 48s

- Add animated coming-soon card when no projects exist
- Add Grafana shortcode and gebrauchtwagen-datenbank project
- Add hugo/eliaskohout.de/public/ to .gitignore and remove from tracking
This commit is contained in:
2026-02-16 23:16:58 +01:00
parent ecd83d9b79
commit 561a04fded
23 changed files with 253 additions and 708 deletions

1
.gitignore vendored
View File

@@ -1,6 +1,7 @@
# ── Hugo ── # ── Hugo ──
.hugo_build.lock .hugo_build.lock
hugo_stats.json hugo_stats.json
hugo/eliaskohout.de/public/
# ── macOS ── # ── macOS ──
.DS_Store .DS_Store

View File

@@ -118,6 +118,62 @@ svg {
gap: 1.5rem; gap: 1.5rem;
} }
.coming-soon {
grid-column: 1 / -1;
text-align: center;
padding: 3rem 2rem;
border: 1px solid rgba(255, 255, 255, 0.08);
border-radius: 12px;
background: rgba(255, 255, 255, 0.03);
-webkit-backdrop-filter: blur(12px);
backdrop-filter: blur(12px);
animation: fadeInUp 0.6s ease-out;
}
.coming-soon-icon {
display: block;
font-size: 2.5rem;
margin-bottom: 1rem;
animation: float 3s ease-in-out infinite;
}
.coming-soon h2 {
font-size: 1.4rem;
letter-spacing: 2px;
margin: 0 0 0.5rem;
color: #fff;
}
.coming-soon p {
color: rgba(255, 255, 255, 0.5);
font-size: 0.95rem;
margin: 0 0 1rem;
}
.coming-soon-dots span {
display: inline-block;
font-size: 1.5rem;
color: #ff3c3c;
animation: blink 1.4s infinite both;
}
.coming-soon-dots span:nth-child(2) { animation-delay: 0.2s; }
.coming-soon-dots span:nth-child(3) { animation-delay: 0.4s; }
@keyframes fadeInUp {
from { opacity: 0; transform: translateY(16px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes float {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-8px); }
}
@keyframes blink {
0%, 80%, 100% { opacity: 0; }
40% { opacity: 1; }
}
.project-card { .project-card {
display: block; display: block;
border: 1px solid rgba(255, 255, 255, 0.1); border: 1px solid rgba(255, 255, 255, 0.1);

View File

@@ -0,0 +1,159 @@
---
title: "2 Million Used Cars and What They Tell Us"
draft: true
date: 2026-02-12
tags: ["Scraping", "Data Engineering", "Grafana", "PostgreSQL"]
summary: "Scraping ~2M used car listings, throwing them into a database, and seeing what shakes out."
code: ""
demo: ""
---
## The Question
Everyone's heard the legend: a VW Passat that just keeps going at 400,000 km. But is it actually the only car that pulls that off? What other models quietly rack up absurd mileage — and what do they cost? In short: what makes a car *last*, and can you get one without overpaying?
Time to find out with data instead of hearsay.
## The Approach
A major used car platform turned out to be surprisingly cooperative when it came to structured data. Their recommendation engine helpfully links to similar listings — so starting from a search, you can just keep crawling through related results.
The haul: roughly **2 million listings** from early 2026, downloaded as JSON and
loaded into a PostgreSQL database. At that point, the recommendation graph
stopped surfacing new entries — a second pass would likely uncover more, since
new listings appear daily. But 2M felt like a solid starting point.
## The Data
**2,046,879 listings**, most of them containing the following fields (among others):
`make` · `model` · `model_variant` · `fuel` · `price` · `mileage` · `power_kw` ·
`transmission_type` · `number_of_cylinders` · `body_type` · `body_color` ·
`first_registration_date` · `number_of_previous_owners` · `is_roadworthy` ·
`is_currently_damaged` · `usage_state` · `type` · `zip_code` · `country_code` ·
`city`
That's enough to get interesting.
About 119,500 listings were missing either price or mileage — not entirely clear
why, but with nearly 2 million records left, it's barely a dent.
---
## Findings
### Price vs. Mileage
The obvious place to start: how does price relate to mileage?
<!-- dashboard on price vs mileage; scatter plot; clipped for 1,000,000 € and 1,000,000 km -->
{{< grafana url="https://gr.eliaskohout.de/public-dashboards/0852019305114cd189aedb67dea27721" height="450" >}}
Two hot spots jump out immediately. One in the low-mileage/high-price corner,
one in the high-mileage/low-price corner — exactly what you'd expect. Expensive
special cars that barely leave the garage, and daily drivers with six-figure
odometers priced to move.
The vast majority of listings, though, cluster in relatively low-price and
low-mileage territory compared to the extremes.
**A note on clipping.** The plot caps at €1,000,000 and 1,000,000 km because the
*tails get absurd. The highest listed price was €999,999,999 — obviously not
*real. Six listings exceeded €10 million, none of them serious. A handful
*between €1M and €10M could be genuine exotics. On the mileage side, the maximum
*was 100,000,000 km. The highest plausible reading I found was an Iveco truck at
*897,000 km on the odometer. The roughly 570 listings beyond that appeared to be
*typos or placeholder values for "mileage unknown."
Across the cleaned dataset, averages land at roughly **€28,400** for price and
**75,600 km** for mileage. The standard deviations are enormous — €731k and 109k
km respectively — which tells you just how wide the spread really is.
That gives an overall average ratio of about **€375 per 1,000 km**. In other
words: for each 1,000 km on the odometer, the average listing costs about €375.
This isn't a depreciation rate in the strict sense — we're looking at a
cross-sectional snapshot of listed prices, not tracking individual cars losing
value over time. But it turns out to be a useful back-of-the-napkin metric for
comparing brands.
### By Brand
The dataset contains **346 distinct makes**. Of those, 72 (~21%) have more than
500 listings — enough for halfway meaningful statistics. The rest are too sparse
to generalize from, so brand-level analysis focuses on these 72.
{{/* dashboard on price per mileage; table with make and euro/km; ordered by price per mileage */}}
{{< grafana url="https://gr.eliaskohout.de/public-dashboards/1777bb018e9b47639b93ef31d97f9c89" height="450" >}}
The ranking roughly mirrors the common perception of luxury brands — makes with
a reputation for being expensive also tend to show up with high price-per-km
values. No surprises there.
But this metric has a blind spot: **age**. Brands with almost no older cars on
the market look disproportionately expensive per km, simply because their
listings haven't had time to depreciate. BYD, for example, ranks just below
Ferrari and Rolls-Royce — not because a BYD is a luxury vehicle, but because the
average BYD listing is only **0.7 years** old, compared to the overall average
of **6.7 years**. Leapmotor is even more extreme at **0.5 years**. Give these
brands a few years to accumulate used inventory at higher mileages, and their
ratios will settle down considerably.
### Depreciation Curves
You'd expect the price-per-km ratio to fall as mileage increases — older,
high-mileage cars are cheaper, and the new-car premium fades fast. You'd also
expect the decline to be roughly exponential: a car loses a percentage of its
current value per additional kilometer, not a fixed euro amount.
Both hold up in the data:
{{/* dashboard on price vs mileage and price/km vs mileage */}}
{{< grafana url="https://gr.eliaskohout.de/public-dashboards/e999ce3c237b4cae95b3331331a26261" height="400" >}}
The curves above show average prices over mileage for BMW, Volkswagen, and Fiat.
The brand-level differences are immediately visible — different starting points,
different values throughout the decay — but the overall shape is the same: steep
early depreciation that gradually flattens out.
* nur zum ende hin verschwimmen die Grenzen, 200k km kann hier als grobe grenze gesehen werden, ab der die daten etwas chaotischer werden
* das könnte auch daran liegen, dass es hier einfach weniger datenpunkte gibt und damit die durchschnittbrechnung schlechter wird
* also lass uns genauer auf die verteilungen an diesem Ende der skala schauen
### The Survivors: Cars Beyond 250k km
{{/*
==============================================
PLAN: Analysis chapters to write
==============================================
1. Price vs. Mileage Relationship
- Scatter/heatmap of price vs. mileage across all listings
- Depreciation curves: how fast do different makes lose value?
- The "sweet spot": best mileage-to-price ratio by model
2. The Survivors: Cars Beyond 300k km
- Which makes/models appear most often at extreme mileage?
- Fuel type breakdown (diesel vs. petrol at high mileage)
- Average price of high-mileage cars — are they dirt cheap or still holding value?
+ ausfallrate abschätzen
4. Fuel & Drivetrain Trends
- Fuel type distribution (diesel/petrol/electric/hybrid/LPG)
- Price and mileage by fuel type
- Are EVs showing up in used markets yet? At what price?
5. Geography
- Listings by country and region (zip code clusters)
- Regional price differences for the same model
- Where are the cheap cars?
==============================================
*/}}

View File

@@ -16,3 +16,6 @@ title = 'Elias Kohout'
[[params.links]] [[params.links]]
name = "[r]ezepte" name = "[r]ezepte"
url = "https://r.eliaskohout.de" url = "https://r.eliaskohout.de"
[markup.goldmark.renderer]
unsafe = true

View File

@@ -5,6 +5,7 @@
<h1>{{ .Title }}</h1> <h1>{{ .Title }}</h1>
<div class="project-grid"> <div class="project-grid">
{{ if .Pages }}
{{ range .Pages.ByDate.Reverse }} {{ range .Pages.ByDate.Reverse }}
<a href="{{ .RelPermalink }}" class="project-card"> <a href="{{ .RelPermalink }}" class="project-card">
{{ with .Params.image }} {{ with .Params.image }}
@@ -19,6 +20,14 @@
<p>{{ .Params.summary }}</p> <p>{{ .Params.summary }}</p>
</a> </a>
{{ end }} {{ end }}
{{ else }}
<div class="coming-soon">
<span class="coming-soon-icon">🚀</span>
<h2>More projects coming soon</h2>
<p>I'm currently working on new things — stay tuned!</p>
<span class="coming-soon-dots"><span>.</span><span>.</span><span>.</span></span>
</div>
{{ end }}
</div> </div>
<div class="back-link"> <div class="back-link">

View File

@@ -0,0 +1,13 @@
<div class="grafana-embed">
<iframe
src="{{ .Get "url" }}"
width="{{ .Get "width" | default "100%" }}"
height="{{ .Get "height" | default "450" }}"
frameborder="0"
scrolling="no"
allowfullscreen
loading="lazy"
style="border: 1px solid rgba(255,255,255,0.1); border-radius: 6px; overflow: hidden;"
>
</iframe>
</div>

View File

@@ -1,50 +0,0 @@
<!DOCTYPE html>
<html lang="de">
<head><script src="/livereload.js?mindelay=10&amp;v=2&amp;port=1313&amp;path=livereload" data-no-instant defer></script><meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Elias Kohout</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Geist+Mono:wght@100..900&display=swap" rel="stylesheet">
<link rel="stylesheet" href="http://localhost:1313/css/style.min.css" />
</head>
<body>
<div class="background">
<svg viewBox="0 0 1600 1200" preserveAspectRatio="xMidYMid slice">
<defs>
<filter id="glow">
<feGaussianBlur stdDeviation="6" result="blur" />
<feMerge>
<feMergeNode in="blur"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
</defs>
<path class="flow-path glow" d="M0,600 Q400,100 800,600 T1600,600" />
<path class="flow-path" d="M0,500 Q400,200 800,500 T1600,500" />
<path class="flow-path glow" d="M0,700 Q400,400 800,700 T1600,700" />
<path class="flow-path" d="M0,300 Q400,0 800,300 T1600,300" />
<path class="flow-path glow" d="M0,900 Q400,800 800,900 T1600,900" />
<path class="flow-path" d="M0,1000 Q400,1000 800,1000 T1600,1000" />
<path class="flow-path glow" d="M0,1100 Q400,1200 800,1100 T1600,1100" />
<path class="flow-path" d="M0,200 Q400,400 800,200 T1600,200" />
<path class="flow-path glow" d="M0,100 Q400,300 800,100 T1600,100" />
</svg>
</div>
<main class="page-content">
<h1>Categories</h1>
<div class="project-grid">
</div>
<div class="back-link">
<a href="/">← back</a>
</div>
</main>
</body>
</html>

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Categories on Elias Kohout</title>
<link>http://localhost:1313/categories/</link>
<description>Recent content in Categories on Elias Kohout</description>
<generator>Hugo</generator>
<language>de</language>
<atom:link href="http://localhost:1313/categories/index.xml" rel="self" type="application/rss+xml" />
</channel>
</rss>

View File

@@ -1 +0,0 @@
html,body{margin:0;padding:0;height:100%;background:#000;font-family:geist mono,sans-serif;color:#fff}.background{position:fixed;width:100%;height:100%;top:0;left:0;z-index:0}svg{width:100%;height:100%;filter:blur(1px)brightness(1.2)}.flow-path{fill:none;stroke:#fff;stroke-width:1;stroke-opacity:.2;stroke-dasharray:1500;stroke-dashoffset:0;animation:flow 12s ease-in-out infinite alternate}.glow{stroke-opacity:.12;animation-duration:18s}.flow-path:nth-child(3n){animation-delay:2s}.flow-path:nth-child(4n){animation-delay:4s}@keyframes flow{0%{stroke-dashoffset:0}100%{stroke-dashoffset:3e3}}.centered{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);text-align:center;z-index:1}.centered h1{font-size:3.5rem;margin-bottom:1.5rem;letter-spacing:4px}.centered nav a{display:block;margin:.3rem 0;color:#ccc;text-decoration:none;font-size:1.1rem}.centered nav a:hover{color:#ff3c3c}.nav-label{display:block;font-size:.7rem;color:#555;text-transform:uppercase;letter-spacing:2px;margin-top:1.2rem;margin-bottom:.3rem}.centered nav a[href^=http]::after{content:" ↗";font-size:.8em;opacity:.5}.centered nav a[href^="/"]::after{content:none}.page-content{position:relative;z-index:1;max-width:800px;margin:4rem auto;padding:0 2rem}.page-content h1{font-size:2.5rem;letter-spacing:3px;margin-bottom:2rem}.project-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(320px,1fr));gap:1.5rem}.project-card{display:block;border:1px solid rgba(255,255,255,.1);border-radius:8px;padding:1.5rem;text-decoration:none;color:#fff;transition:border-color .3s,transform .2s;background:rgba(255,255,255,5%);-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px)}.project-card:hover{border-color:#ff3c3c;transform:translateY(-2px);background:rgba(255,255,255,8%)}.project-card img{width:100%;border-radius:4px;margin-bottom:1rem}.project-card h2{font-size:1.3rem;margin:0 0 .5rem}.project-card p{color:#aaa;font-size:.9rem;margin:.3rem 0}.tags{display:flex;gap:.5rem;flex-wrap:wrap;margin:.5rem 0}.tag{background:rgba(255,255,255,8%);padding:.2rem .6rem;border-radius:4px;font-size:.8rem;color:#ccc}.project-links{margin:1rem 0 2rem}.project-links a{color:#ff3c3c;text-decoration:none;margin-right:1rem}.project-links a:hover{text-decoration:underline}.project-body{line-height:1.8;color:#ddd}.project-body h2{color:#fff;margin-top:2rem;font-size:1.4rem}.back-link{margin-top:3rem}.back-link a{color:#888;text-decoration:none;font-size:.9rem}.back-link a:hover{color:#ff3c3c}@media(max-width:600px){.centered h1{font-size:2rem}.page-content{margin:2rem auto}.project-grid{grid-template-columns:1fr}}

View File

@@ -1,56 +0,0 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta name="generator" content="Hugo 0.155.3"><script src="/livereload.js?mindelay=10&amp;v=2&amp;port=1313&amp;path=livereload" data-no-instant defer></script><meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Elias Kohout</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Geist+Mono:wght@100..900&display=swap" rel="stylesheet">
<link rel="stylesheet" href="/css/style.min.css" />
</head>
<body>
<div class="background">
<svg viewBox="0 0 1600 1200" preserveAspectRatio="xMidYMid slice">
<defs>
<filter id="glow">
<feGaussianBlur stdDeviation="6" result="blur" />
<feMerge>
<feMergeNode in="blur"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
</defs>
<path class="flow-path glow" d="M0,600 Q400,100 800,600 T1600,600" />
<path class="flow-path" d="M0,500 Q400,200 800,500 T1600,500" />
<path class="flow-path glow" d="M0,700 Q400,400 800,700 T1600,700" />
<path class="flow-path" d="M0,300 Q400,0 800,300 T1600,300" />
<path class="flow-path glow" d="M0,900 Q400,800 800,900 T1600,900" />
<path class="flow-path" d="M0,1000 Q400,1000 800,1000 T1600,1000" />
<path class="flow-path glow" d="M0,1100 Q400,1200 800,1100 T1600,1100" />
<path class="flow-path" d="M0,200 Q400,400 800,200 T1600,200" />
<path class="flow-path glow" d="M0,100 Q400,300 800,100 T1600,100" />
</svg>
</div>
<main class="centered">
<h1>Elias Kohout</h1>
<nav>
<span class="nav-label">services</span>
<a href="https://c.eliaskohout.de">[c]rowsnest</a>
<a href="https://g.eliaskohout.de">[g]itea</a>
<a href="https://r.eliaskohout.de">[r]ezepte</a>
<span class="nav-label">pages</span>
<a href="/projects/">projects</a>
</nav>
</main>
</body>
</html>

View File

@@ -1,19 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Elias Kohout</title>
<link>http://localhost:1313/</link>
<description>Recent content on Elias Kohout</description>
<generator>Hugo</generator>
<language>de</language>
<lastBuildDate>Sat, 01 Jun 2024 00:00:00 +0000</lastBuildDate>
<atom:link href="http://localhost:1313/index.xml" rel="self" type="application/rss+xml" />
<item>
<title>LLM Confidence Chat Interface</title>
<link>http://localhost:1313/projects/llm-confidence-chat/</link>
<pubDate>Sat, 01 Jun 2024 00:00:00 +0000</pubDate>
<guid>http://localhost:1313/projects/llm-confidence-chat/</guid>
<description>A chat interface making LLM confidence scores accessible to non-technical users.</description>
</item>
</channel>
</rss>

View File

@@ -1,65 +0,0 @@
<!DOCTYPE html>
<html lang="de">
<head><script src="/livereload.js?mindelay=10&amp;v=2&amp;port=1313&amp;path=livereload" data-no-instant defer></script><meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Elias Kohout</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Geist+Mono:wght@100..900&display=swap" rel="stylesheet">
<link rel="stylesheet" href="/css/style.min.css" />
</head>
<body>
<div class="background">
<svg viewBox="0 0 1600 1200" preserveAspectRatio="xMidYMid slice">
<defs>
<filter id="glow">
<feGaussianBlur stdDeviation="6" result="blur" />
<feMerge>
<feMergeNode in="blur"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
</defs>
<path class="flow-path glow" d="M0,600 Q400,100 800,600 T1600,600" />
<path class="flow-path" d="M0,500 Q400,200 800,500 T1600,500" />
<path class="flow-path glow" d="M0,700 Q400,400 800,700 T1600,700" />
<path class="flow-path" d="M0,300 Q400,0 800,300 T1600,300" />
<path class="flow-path glow" d="M0,900 Q400,800 800,900 T1600,900" />
<path class="flow-path" d="M0,1000 Q400,1000 800,1000 T1600,1000" />
<path class="flow-path glow" d="M0,1100 Q400,1200 800,1100 T1600,1100" />
<path class="flow-path" d="M0,200 Q400,400 800,200 T1600,200" />
<path class="flow-path glow" d="M0,100 Q400,300 800,100 T1600,100" />
</svg>
</div>
<main class="page-content">
<h1>Projects</h1>
<div class="project-grid">
<a href="/projects/llm-confidence-chat/" class="project-card">
<h2>LLM Confidence Chat Interface</h2>
<p class="tags">
<span class="tag">Python</span>
<span class="tag">ML</span>
<span class="tag">Full-Stack</span>
</p>
<p>A chat interface making LLM confidence scores accessible to non-technical users.</p>
</a>
</div>
<div class="back-link">
<a href="/">← back</a>
</div>
</main>
</body>
</html>

View File

@@ -1,19 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Projects on Elias Kohout</title>
<link>http://localhost:1313/projects/</link>
<description>Recent content in Projects on Elias Kohout</description>
<generator>Hugo</generator>
<language>de</language>
<lastBuildDate>Sat, 01 Jun 2024 00:00:00 +0000</lastBuildDate>
<atom:link href="http://localhost:1313/projects/index.xml" rel="self" type="application/rss+xml" />
<item>
<title>LLM Confidence Chat Interface</title>
<link>http://localhost:1313/projects/llm-confidence-chat/</link>
<pubDate>Sat, 01 Jun 2024 00:00:00 +0000</pubDate>
<guid>http://localhost:1313/projects/llm-confidence-chat/</guid>
<description>A chat interface making LLM confidence scores accessible to non-technical users.</description>
</item>
</channel>
</rss>

View File

@@ -1,79 +0,0 @@
<!DOCTYPE html>
<html lang="de">
<head><script src="/livereload.js?mindelay=10&amp;v=2&amp;port=1313&amp;path=livereload" data-no-instant defer></script><meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Elias Kohout</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Geist+Mono:wght@100..900&display=swap" rel="stylesheet">
<link rel="stylesheet" href="/css/style.min.css" />
</head>
<body>
<div class="background">
<svg viewBox="0 0 1600 1200" preserveAspectRatio="xMidYMid slice">
<defs>
<filter id="glow">
<feGaussianBlur stdDeviation="6" result="blur" />
<feMerge>
<feMergeNode in="blur"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
</defs>
<path class="flow-path glow" d="M0,600 Q400,100 800,600 T1600,600" />
<path class="flow-path" d="M0,500 Q400,200 800,500 T1600,500" />
<path class="flow-path glow" d="M0,700 Q400,400 800,700 T1600,700" />
<path class="flow-path" d="M0,300 Q400,0 800,300 T1600,300" />
<path class="flow-path glow" d="M0,900 Q400,800 800,900 T1600,900" />
<path class="flow-path" d="M0,1000 Q400,1000 800,1000 T1600,1000" />
<path class="flow-path glow" d="M0,1100 Q400,1200 800,1100 T1600,1100" />
<path class="flow-path" d="M0,200 Q400,400 800,200 T1600,200" />
<path class="flow-path glow" d="M0,100 Q400,300 800,100 T1600,100" />
</svg>
</div>
<main class="page-content">
<h1>LLM Confidence Chat Interface</h1>
<p class="tags">
<span class="tag">Python</span>
<span class="tag">ML</span>
<span class="tag">Full-Stack</span>
</p>
<div class="project-links">
<a href="https://github.com/yourusername/project">[Code]</a>
<a href="https://demo.example.com">[Live Demo]</a>
</div>
<article class="project-body">
<h2 id="problem">Problem</h2>
<p>Non-technical users have no way to assess how confident an LLM is in its responses.</p>
<h2 id="approach">Approach</h2>
<p>Built an interactive chat interface integrating lm-polygraph for
uncertainty estimation with an intuitive visualization layer.</p>
<h2 id="tech-stack">Tech Stack</h2>
<ul>
<li>Python, FastAPI</li>
<li>lm-polygraph</li>
<li>React</li>
</ul>
<h2 id="challenges--learnings">Challenges &amp; Learnings</h2>
<p>Translating probabilistic outputs into user-friendly visual indicators
while keeping the interface responsive.</p>
</article>
<div class="back-link">
<a href="/projects/">← all projects</a>
</div>
</main>
</body>
</html>

View File

@@ -1,28 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xhtml="http://www.w3.org/1999/xhtml">
<url>
<loc>http://localhost:1313/</loc>
<lastmod>2024-06-01T00:00:00+00:00</lastmod>
</url><url>
<loc>http://localhost:1313/tags/full-stack/</loc>
<lastmod>2024-06-01T00:00:00+00:00</lastmod>
</url><url>
<loc>http://localhost:1313/projects/llm-confidence-chat/</loc>
<lastmod>2024-06-01T00:00:00+00:00</lastmod>
</url><url>
<loc>http://localhost:1313/tags/ml/</loc>
<lastmod>2024-06-01T00:00:00+00:00</lastmod>
</url><url>
<loc>http://localhost:1313/projects/</loc>
<lastmod>2024-06-01T00:00:00+00:00</lastmod>
</url><url>
<loc>http://localhost:1313/tags/python/</loc>
<lastmod>2024-06-01T00:00:00+00:00</lastmod>
</url><url>
<loc>http://localhost:1313/tags/</loc>
<lastmod>2024-06-01T00:00:00+00:00</lastmod>
</url><url>
<loc>http://localhost:1313/categories/</loc>
</url>
</urlset>

View File

@@ -1,67 +0,0 @@
<!DOCTYPE html>
<html lang="de">
<head><script src="/livereload.js?mindelay=10&amp;v=2&amp;port=1313&amp;path=livereload" data-no-instant defer></script><meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Elias Kohout</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Geist+Mono:wght@100..900&display=swap" rel="stylesheet">
<link rel="stylesheet" href="http://localhost:1313/css/style.min.css" />
</head>
<body>
<div class="background">
<svg viewBox="0 0 1600 1200" preserveAspectRatio="xMidYMid slice">
<defs>
<filter id="glow">
<feGaussianBlur stdDeviation="6" result="blur" />
<feMerge>
<feMergeNode in="blur"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
</defs>
<path class="flow-path glow" d="M0,600 Q400,100 800,600 T1600,600" />
<path class="flow-path" d="M0,500 Q400,200 800,500 T1600,500" />
<path class="flow-path glow" d="M0,700 Q400,400 800,700 T1600,700" />
<path class="flow-path" d="M0,300 Q400,0 800,300 T1600,300" />
<path class="flow-path glow" d="M0,900 Q400,800 800,900 T1600,900" />
<path class="flow-path" d="M0,1000 Q400,1000 800,1000 T1600,1000" />
<path class="flow-path glow" d="M0,1100 Q400,1200 800,1100 T1600,1100" />
<path class="flow-path" d="M0,200 Q400,400 800,200 T1600,200" />
<path class="flow-path glow" d="M0,100 Q400,300 800,100 T1600,100" />
</svg>
</div>
<main class="page-content">
<h1>Full-Stack</h1>
<div class="project-grid">
<a href="http://localhost:1313/projects/llm-confidence-chat/" class="project-card">
<img src="/images/llm-chat.png" alt="Full-Stack" />
<h2>LLM Confidence Chat Interface</h2>
<p class="tags">
<span class="tag">Python</span>
<span class="tag">ML</span>
<span class="tag">Full-Stack</span>
</p>
<p>A chat interface making LLM confidence scores accessible to non-technical users.</p>
</a>
</div>
<div class="back-link">
<a href="/">← back</a>
</div>
</main>
</body>
</html>

View File

@@ -1,19 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Full-Stack on Elias Kohout</title>
<link>http://localhost:1313/tags/full-stack/</link>
<description>Recent content in Full-Stack on Elias Kohout</description>
<generator>Hugo</generator>
<language>de</language>
<lastBuildDate>Sat, 01 Jun 2024 00:00:00 +0000</lastBuildDate>
<atom:link href="http://localhost:1313/tags/full-stack/index.xml" rel="self" type="application/rss+xml" />
<item>
<title>LLM Confidence Chat Interface</title>
<link>http://localhost:1313/projects/llm-confidence-chat/</link>
<pubDate>Sat, 01 Jun 2024 00:00:00 +0000</pubDate>
<guid>http://localhost:1313/projects/llm-confidence-chat/</guid>
<description>A chat interface making LLM confidence scores accessible to non-technical users.</description>
</item>
</channel>
</rss>

View File

@@ -1,77 +0,0 @@
<!DOCTYPE html>
<html lang="de">
<head><script src="/livereload.js?mindelay=10&amp;v=2&amp;port=1313&amp;path=livereload" data-no-instant defer></script><meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Elias Kohout</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Geist+Mono:wght@100..900&display=swap" rel="stylesheet">
<link rel="stylesheet" href="http://localhost:1313/css/style.min.css" />
</head>
<body>
<div class="background">
<svg viewBox="0 0 1600 1200" preserveAspectRatio="xMidYMid slice">
<defs>
<filter id="glow">
<feGaussianBlur stdDeviation="6" result="blur" />
<feMerge>
<feMergeNode in="blur"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
</defs>
<path class="flow-path glow" d="M0,600 Q400,100 800,600 T1600,600" />
<path class="flow-path" d="M0,500 Q400,200 800,500 T1600,500" />
<path class="flow-path glow" d="M0,700 Q400,400 800,700 T1600,700" />
<path class="flow-path" d="M0,300 Q400,0 800,300 T1600,300" />
<path class="flow-path glow" d="M0,900 Q400,800 800,900 T1600,900" />
<path class="flow-path" d="M0,1000 Q400,1000 800,1000 T1600,1000" />
<path class="flow-path glow" d="M0,1100 Q400,1200 800,1100 T1600,1100" />
<path class="flow-path" d="M0,200 Q400,400 800,200 T1600,200" />
<path class="flow-path glow" d="M0,100 Q400,300 800,100 T1600,100" />
</svg>
</div>
<main class="page-content">
<h1>Tags</h1>
<div class="project-grid">
<a href="http://localhost:1313/tags/python/" class="project-card">
<h2>Python</h2>
<p class="tags">
</p>
<p></p>
</a>
<a href="http://localhost:1313/tags/ml/" class="project-card">
<h2>ML</h2>
<p class="tags">
</p>
<p></p>
</a>
<a href="http://localhost:1313/tags/full-stack/" class="project-card">
<h2>Full-Stack</h2>
<p class="tags">
</p>
<p></p>
</a>
</div>
<div class="back-link">
<a href="/">← back</a>
</div>
</main>
</body>
</html>

View File

@@ -1,33 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Tags on Elias Kohout</title>
<link>http://localhost:1313/tags/</link>
<description>Recent content in Tags on Elias Kohout</description>
<generator>Hugo</generator>
<language>de</language>
<lastBuildDate>Sat, 01 Jun 2024 00:00:00 +0000</lastBuildDate>
<atom:link href="http://localhost:1313/tags/index.xml" rel="self" type="application/rss+xml" />
<item>
<title>Full-Stack</title>
<link>http://localhost:1313/tags/full-stack/</link>
<pubDate>Sat, 01 Jun 2024 00:00:00 +0000</pubDate>
<guid>http://localhost:1313/tags/full-stack/</guid>
<description></description>
</item>
<item>
<title>ML</title>
<link>http://localhost:1313/tags/ml/</link>
<pubDate>Sat, 01 Jun 2024 00:00:00 +0000</pubDate>
<guid>http://localhost:1313/tags/ml/</guid>
<description></description>
</item>
<item>
<title>Python</title>
<link>http://localhost:1313/tags/python/</link>
<pubDate>Sat, 01 Jun 2024 00:00:00 +0000</pubDate>
<guid>http://localhost:1313/tags/python/</guid>
<description></description>
</item>
</channel>
</rss>

View File

@@ -1,67 +0,0 @@
<!DOCTYPE html>
<html lang="de">
<head><script src="/livereload.js?mindelay=10&amp;v=2&amp;port=1313&amp;path=livereload" data-no-instant defer></script><meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Elias Kohout</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Geist+Mono:wght@100..900&display=swap" rel="stylesheet">
<link rel="stylesheet" href="http://localhost:1313/css/style.min.css" />
</head>
<body>
<div class="background">
<svg viewBox="0 0 1600 1200" preserveAspectRatio="xMidYMid slice">
<defs>
<filter id="glow">
<feGaussianBlur stdDeviation="6" result="blur" />
<feMerge>
<feMergeNode in="blur"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
</defs>
<path class="flow-path glow" d="M0,600 Q400,100 800,600 T1600,600" />
<path class="flow-path" d="M0,500 Q400,200 800,500 T1600,500" />
<path class="flow-path glow" d="M0,700 Q400,400 800,700 T1600,700" />
<path class="flow-path" d="M0,300 Q400,0 800,300 T1600,300" />
<path class="flow-path glow" d="M0,900 Q400,800 800,900 T1600,900" />
<path class="flow-path" d="M0,1000 Q400,1000 800,1000 T1600,1000" />
<path class="flow-path glow" d="M0,1100 Q400,1200 800,1100 T1600,1100" />
<path class="flow-path" d="M0,200 Q400,400 800,200 T1600,200" />
<path class="flow-path glow" d="M0,100 Q400,300 800,100 T1600,100" />
</svg>
</div>
<main class="page-content">
<h1>ML</h1>
<div class="project-grid">
<a href="http://localhost:1313/projects/llm-confidence-chat/" class="project-card">
<img src="/images/llm-chat.png" alt="ML" />
<h2>LLM Confidence Chat Interface</h2>
<p class="tags">
<span class="tag">Python</span>
<span class="tag">ML</span>
<span class="tag">Full-Stack</span>
</p>
<p>A chat interface making LLM confidence scores accessible to non-technical users.</p>
</a>
</div>
<div class="back-link">
<a href="/">← back</a>
</div>
</main>
</body>
</html>

View File

@@ -1,19 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>ML on Elias Kohout</title>
<link>http://localhost:1313/tags/ml/</link>
<description>Recent content in ML on Elias Kohout</description>
<generator>Hugo</generator>
<language>de</language>
<lastBuildDate>Sat, 01 Jun 2024 00:00:00 +0000</lastBuildDate>
<atom:link href="http://localhost:1313/tags/ml/index.xml" rel="self" type="application/rss+xml" />
<item>
<title>LLM Confidence Chat Interface</title>
<link>http://localhost:1313/projects/llm-confidence-chat/</link>
<pubDate>Sat, 01 Jun 2024 00:00:00 +0000</pubDate>
<guid>http://localhost:1313/projects/llm-confidence-chat/</guid>
<description>A chat interface making LLM confidence scores accessible to non-technical users.</description>
</item>
</channel>
</rss>

View File

@@ -1,67 +0,0 @@
<!DOCTYPE html>
<html lang="de">
<head><script src="/livereload.js?mindelay=10&amp;v=2&amp;port=1313&amp;path=livereload" data-no-instant defer></script><meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Elias Kohout</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Geist+Mono:wght@100..900&display=swap" rel="stylesheet">
<link rel="stylesheet" href="http://localhost:1313/css/style.min.css" />
</head>
<body>
<div class="background">
<svg viewBox="0 0 1600 1200" preserveAspectRatio="xMidYMid slice">
<defs>
<filter id="glow">
<feGaussianBlur stdDeviation="6" result="blur" />
<feMerge>
<feMergeNode in="blur"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
</defs>
<path class="flow-path glow" d="M0,600 Q400,100 800,600 T1600,600" />
<path class="flow-path" d="M0,500 Q400,200 800,500 T1600,500" />
<path class="flow-path glow" d="M0,700 Q400,400 800,700 T1600,700" />
<path class="flow-path" d="M0,300 Q400,0 800,300 T1600,300" />
<path class="flow-path glow" d="M0,900 Q400,800 800,900 T1600,900" />
<path class="flow-path" d="M0,1000 Q400,1000 800,1000 T1600,1000" />
<path class="flow-path glow" d="M0,1100 Q400,1200 800,1100 T1600,1100" />
<path class="flow-path" d="M0,200 Q400,400 800,200 T1600,200" />
<path class="flow-path glow" d="M0,100 Q400,300 800,100 T1600,100" />
</svg>
</div>
<main class="page-content">
<h1>Python</h1>
<div class="project-grid">
<a href="http://localhost:1313/projects/llm-confidence-chat/" class="project-card">
<img src="/images/llm-chat.png" alt="Python" />
<h2>LLM Confidence Chat Interface</h2>
<p class="tags">
<span class="tag">Python</span>
<span class="tag">ML</span>
<span class="tag">Full-Stack</span>
</p>
<p>A chat interface making LLM confidence scores accessible to non-technical users.</p>
</a>
</div>
<div class="back-link">
<a href="/">← back</a>
</div>
</main>
</body>
</html>

View File

@@ -1,19 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Python on Elias Kohout</title>
<link>http://localhost:1313/tags/python/</link>
<description>Recent content in Python on Elias Kohout</description>
<generator>Hugo</generator>
<language>de</language>
<lastBuildDate>Sat, 01 Jun 2024 00:00:00 +0000</lastBuildDate>
<atom:link href="http://localhost:1313/tags/python/index.xml" rel="self" type="application/rss+xml" />
<item>
<title>LLM Confidence Chat Interface</title>
<link>http://localhost:1313/projects/llm-confidence-chat/</link>
<pubDate>Sat, 01 Jun 2024 00:00:00 +0000</pubDate>
<guid>http://localhost:1313/projects/llm-confidence-chat/</guid>
<description>A chat interface making LLM confidence scores accessible to non-technical users.</description>
</item>
</channel>
</rss>