<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>HHYurdagul</title>
    <subtitle>Personal website of Hasan Hüseyin Yurdagül — ML Engineer &amp; R&amp;D Consultant.</subtitle>
    <link rel="self" type="application/atom+xml" href="https://hhyurdagul.com/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://hhyurdagul.com"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-07-07T00:00:00+00:00</updated>
    <id>https://hhyurdagul.com/atom.xml</id>
    <entry xml:lang="en">
        <title>MLStudio — From a 30-Company Desktop Tool to a Web ML Platform</title>
        <published>2026-07-07T00:00:00+00:00</published>
        <updated>2026-07-07T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hhyurdagul.com/projects/mlstudio/"/>
        <id>https://hhyurdagul.com/projects/mlstudio/</id>
        
        <content type="html" xml:base="https://hhyurdagul.com/projects/mlstudio/">&lt;p&gt;I created MLStudio to make practical machine-learning workflows usable without
model-specific code. Its original Tkinter version grew out of real customer
requirements and was deployed to more than 30 companies. I was the sole engineer
behind its modernization into the current deployed Streamlit application,
supported by two testers and retaining full technical ownership of the product.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;30+ predecessor deployments&lt;&#x2F;strong&gt; · &lt;strong&gt;Separate backend and UI&lt;&#x2F;strong&gt; · &lt;strong&gt;14 supervised
and time-series model choices&lt;&#x2F;strong&gt; · &lt;strong&gt;Current Streamlit version deployed&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The rewrite was not a cosmetic interface change. It was a product-engineering
decision: preserve the trusted modeling workflows, separate them from the UI,
and make customer-specific customization and deployment easier than it was in a
packaged desktop application.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;from-desktop-product-to-web-platform&quot;&gt;From Desktop Product to Web Platform&lt;&#x2F;h2&gt;
&lt;p&gt;The Tkinter application proved the need. Companies could train and compare
models through a guided interface, but each deployment made the desktop
architecture’s limits clearer: UI logic and modeling behavior were harder to
evolve independently, environment differences complicated delivery, and
customer-specific changes increased maintenance cost.&lt;&#x2F;p&gt;
&lt;p&gt;The Streamlit replacement keeps the workflow familiar while changing the system
boundary. A browser-based interface is easier to deploy centrally, and Streamlit
makes it faster to add or rearrange controls for different use cases. More
importantly, the modeling layer is now independent of Streamlit, so the same
workflows can be tested or reused without rendering a page.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;mermaid&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;flowchart LR&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    DATA[&amp;quot;CSV &#x2F; XLSX data&amp;quot;] --&amp;gt; UI[&amp;quot;Streamlit workspace&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    UI --&amp;gt; CONFIG[&amp;quot;Typed workflow configuration&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    CONFIG --&amp;gt; BACKEND[&amp;quot;Framework-independent ML backend&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    BACKEND --&amp;gt; PREP[&amp;quot;Preprocessing + feature selection&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    PREP --&amp;gt; MODEL[&amp;quot;Regression or time-series model&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    MODEL --&amp;gt; RESULT[&amp;quot;Metrics + predictions + processed preview&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    MODEL --&amp;gt; BUNDLE[&amp;quot;Downloadable versioned model bundle&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    BUNDLE --&amp;gt; TEST[&amp;quot;Independent test workflow&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;architecture-that-protects-the-rewrite&quot;&gt;Architecture That Protects the Rewrite&lt;&#x2F;h2&gt;
&lt;p&gt;MLStudio has two explicit layers:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;mlstudio&#x2F;backend&#x2F;&lt;&#x2F;code&gt; owns data validation, preprocessing, estimator
definitions, feature selection, evaluation, artifact serialization, and
train&#x2F;validate&#x2F;predict workflows. It has no Streamlit dependency.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;mlstudio&#x2F;frontend&#x2F;&lt;&#x2F;code&gt; gathers user choices, constructs typed configurations,
invokes one backend workflow, and renders the returned result.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The entry point only starts the application. An architecture test parses every
backend module and fails if it imports Streamlit or the frontend package. That
small constraint prevents the new application from slowly collapsing back into
the tightly coupled structure it replaced.&lt;&#x2F;p&gt;
&lt;p&gt;The current repository contains approximately 5,860 lines of Python and defines
49 automated checks covering data validation, model registration, artifact round
trips, feature selection, time-aware splits, recursive forecasting, lag
selection, and architectural boundaries.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;supervised-modeling-workspace&quot;&gt;Supervised Modeling Workspace&lt;&#x2F;h2&gt;
&lt;p&gt;The supervised workspace supports three distinct jobs rather than hiding them
behind one ambiguous button:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Training:&lt;&#x2F;strong&gt; fit a preprocessing-and-model pipeline on selected rows,
optionally score a separate test dataset, inspect processed features, and
download the fitted bundle.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Validation:&lt;&#x2F;strong&gt; use a random split, ordered last split, or cross-validation;
optionally run grid search and feature selection; then inspect metrics and
out-of-sample predictions.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Testing:&lt;&#x2F;strong&gt; upload a trusted MLStudio bundle and new data, validate the
required feature contract, generate predictions, and calculate metrics only
when the saved target column is present.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Numeric, categorical, string, and boolean features can share one dataset. The
saved artifact keeps preprocessing and regression together so training-time
transformations are reused during prediction. Current regressors include Random
Forest, Gradient Boosting, Support Vector Regression, Extreme Learning Machine,
XGBoost, CatBoost, and Voting Regression.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;neural-time-series-workspace&quot;&gt;Neural Time-Series Workspace&lt;&#x2F;h2&gt;
&lt;p&gt;Time series are handled as ordered data, not as ordinary shuffled regression.
The PyTorch workspace trains MLP, CNN, RNN, GRU, LSTM, Bi-LSTM, and ConvLSTM
models over lagged windows from one numeric target series.&lt;&#x2F;p&gt;
&lt;p&gt;Users can inspect autocorrelation diagnostics and select every available lag,
explicit indices, the strongest absolute ACF values, or all lags above a
threshold. Layer sizes, activations, learning rate, epochs, batch size, and
target scaling are configurable. An optional second dataset provides a recursive
backtest: predictions are fed back into the model rather than replaced with the
actual future values.&lt;&#x2F;p&gt;
&lt;p&gt;Saved &lt;code&gt;.pt&lt;&#x2F;code&gt; bundles include the target, training history, lag contract,
architecture, scaling configuration, and model state. A bundle can forecast an
arbitrary future horizon or compare that horizon with an optional actual-target
dataset.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;evaluation-and-safety-decisions&quot;&gt;Evaluation and Safety Decisions&lt;&#x2F;h2&gt;
&lt;p&gt;MLStudio calculates R², MAE, RMSE, and MAPE when labels are available. MAPE
excludes rows whose actual target is zero and is not reported when every actual
value is zero, avoiding a metric that would otherwise be undefined.&lt;&#x2F;p&gt;
&lt;p&gt;Ordered lookback workflows reject random row selection. Their cross-validation
and grid-search paths use time-series folds, and recursive validation resets
prediction history correctly between evaluations. These restrictions reduce
convenient but misleading evaluation choices.&lt;&#x2F;p&gt;
&lt;p&gt;Model bundles use Python serialization, so the application explicitly treats
them as trusted artifacts: users should not upload bundles from unknown sources,
and producers and consumers must use compatible dependency versions.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;current-boundaries&quot;&gt;Current Boundaries&lt;&#x2F;h2&gt;
&lt;p&gt;The platform does not yet implement missing-value imputation; uploaded data must
satisfy the selected workflow’s input contract. Cross-environment model
compatibility also depends on Python and library versions. The current public
environment also exposes two Voting Regressor test failures caused by a nested
MLP layer-size value being reapplied as a string; the other 47 checks pass.
These are visible engineering constraints rather than details hidden behind the
interface.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-this-project-demonstrates&quot;&gt;What This Project Demonstrates&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Product evolution informed by use:&lt;&#x2F;strong&gt; the rewrite follows deployment
experience from more than 30 companies rather than a hypothetical UI exercise.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Architecture as a migration outcome:&lt;&#x2F;strong&gt; the new frontend can change without
forcing model logic into page code.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Evaluation discipline:&lt;&#x2F;strong&gt; ordered splits and recursive forecasts prevent
time-series features from becoming accidental leakage.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Reproducible handoff:&lt;&#x2F;strong&gt; preprocessing, model state, feature contracts, and
forecast history travel with downloadable artifacts.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Engineering beyond the model:&lt;&#x2F;strong&gt; tests, validation, packaging, deployment,
and user-facing constraints are part of the ML product.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Six Years, Thirty Companies, and One Bad Tkinter App</title>
        <published>2026-06-30T00:00:00+00:00</published>
        <updated>2026-06-30T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hhyurdagul.com/articles/six-years-of-consulting-and-one-bad-tkinter-app/"/>
        <id>https://hhyurdagul.com/articles/six-years-of-consulting-and-one-bad-tkinter-app/</id>
        
        <content type="html" xml:base="https://hhyurdagul.com/articles/six-years-of-consulting-and-one-bad-tkinter-app/">&lt;p&gt;My career began with a surprising collaboration with my professor during the
last semester of the year before my final year of my bachelor’s degree in
computer engineering at Çukurova University, around 2020. He had some experience
working with government incentives and grants, especially Tübitak and official
R&amp;amp;D Centers — Turkey’s main public-funding routes for applied research. Machine
learning and AI in general were the hotspots in those years, and grants were
specifically targeting AI work.&lt;&#x2F;p&gt;
&lt;p&gt;He hadn’t been exposed to AI yet and wanted a
workforce that knows what he is dealing with, could tackle and solve those
problems, build the tools, products, and systems, and secure the grant, and he
found the one-man army, which is me, of course.&lt;&#x2F;p&gt;
&lt;p&gt;We started in September 2020
with a modest clothing company, Sefamerve, which wanted demand forecasting for
their products’ future sales, which, of course, needs no explanation. By
December that year we’d added Comdata, one of the well-known call centers, which
wanted to forecast future call volumes to optimize call agents’ schedules and
create a system they could use productively. And by January 2021, an
international car parts manufacturer, Teknorot, came on with the same problem:
demand forecasting.&lt;&#x2F;p&gt;
&lt;p&gt;After a while, it became clear that the industry needs this; forecasting future
values for any given data will eventually occur, so instead of coding everything
manually, we could have created an app that would make it possible for us, and
even for others who are not proficient code writers, to get results using
machine learning and AI in general. So I did that.&lt;&#x2F;p&gt;
&lt;p&gt;There was already a similar
ongoing project called DTReg, which was basic, only limited to Windows, and, of
course, paid, and not free. Being a fresh young developer, I have made terrible
mistakes, design choices, and engineering that will shoot me in the foot several
times in the future. One bad decision was to use tkinter for the UI, since DTReg
was already using it, so I went with the same approach. Don’t get me wrong, I am
not against Tkinter, but it didn’t look good at all, and we weren’t in 1980; it
was the 2020s. Looking at it now, I could have used QT instead of Tkinter, which
would have looked much better.&lt;&#x2F;p&gt;
&lt;p&gt;Not stopping there, I didn’t separate ui and
logic from each other; it was one giant Python class where everything was tied
together, mutable state everywhere, functions not returning, and changing the
state itself, methods calling methods, no private functions, everything is one
giant code. All of these could have been avoided if we had also been taught
functional programming alongside object-oriented programming in our education,
but that is a topic for another time. It started as a one-page LSTM-based time
series tool and became a giant app that packed a bunch of algorithms together
with no modularity, separation of concerns, or anything along those lines taken
into consideration. As I said, I was fresh blood. But we used it well: for every
client, I had to delete some places on one page, some on others, and maybe add a
little something to serve more than 30 customers. I always had the thought of
restructuring it, but I was telling myself, we won’t get any more customers, of
course, I was wrong, people had too many problems to solve.&lt;&#x2F;p&gt;
&lt;p&gt;After a while, I started getting work that is not just predictive modeling.
Times are changing, people have learned what ML&#x2F;DL can do, and they want that. I
had started working with Datakod, which has a large volume of customer data.
They wanted to understand customer behavior, so I studied and implemented
systems such as customer segmentation, campaign recommendation, churn
prediction, association rule mining, and even anomaly detection on customer
data.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;from-one-model-to-understanding-customers&quot;&gt;From One Model to Understanding Customers&lt;&#x2F;h2&gt;
&lt;p&gt;The demand-forecasting approach I’d built for Sefamerve, matching new products
to older ones by image similarity and borrowing their sales history, never
worked as well as I wanted it to. By this point I’d learned to be more upfront
with clients about what a model could and couldn’t promise, instead of just
shipping the cleverest idea I had.&lt;&#x2F;p&gt;
&lt;p&gt;Datakod ended up being one of the broadest engagements I’ve had, running from
January 2022 to December 2024, and it’s the one that pushed me from “build me a
forecast” to “tell me who my customers are.” Alongside segmentation and campaign
recommendation, I built association rule mining with FP-growth and Apriori for
their market-basket data, RFM scoring, and anomaly detection, packaged as BI and
intelligence reports rather than another Tkinter screen.&lt;&#x2F;p&gt;
&lt;p&gt;Albert Solino, a consultancy firm, kept me busy from May 2021 to January 2023.
The core deliverable was a churn and lifetime value system wired directly into
their CRM, but the part I remember best is mentoring two of their mid-level
engineers, who ended up rebuilding the MLStudio idea from scratch in Flask, a
framework I’d never touched myself. Watching someone take the concept and remake
it cleanly was a good sign that the idea itself, even if my implementation of it
was a mess, had been sound the whole time.&lt;&#x2F;p&gt;
&lt;p&gt;Two more from this stretch are worth a mention. Unsped Customs Consultancy got
funded through Tübitak 1511, the same government R&amp;amp;D grant track from the intro,
off a churn and CLTV model I built for them, which is the kind of validation
that matters more to me than any accuracy number. And HepsiEmlak, the real
estate marketplace, had me spend most of my hours writing R&amp;amp;D Center
registration and Tübitak proposal material rather than shipping models, with
recommendation and duplicate-photo-detection work happening underneath.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;teaching-others-to-fish&quot;&gt;Teaching Others to Fish&lt;&#x2F;h2&gt;
&lt;p&gt;Somewhere in this stretch the work started changing shape again. I wasn’t just
being hired to build something anymore, I was being hired to teach other people
how to build it.&lt;&#x2F;p&gt;
&lt;p&gt;Protel, the hospitality and restaurant-tech company, had me lead and mentor five
people, from juniors to seniors plus one MSc student, on demand forecasting
using ARIMA, LightGBM, XGBoost, and Random Forest — the first time I was
responsible for other people’s output instead of just my own. At Nano I taught
ML&#x2F;DL fundamentals and guided the team toward building their own MLStudio
equivalent, except in C#, which proved the idea wasn’t tied to my stack at all,
it was tied to the workflow. Gtech, CukurovaMakine, and JForce rounded out this
period: three more data scientists mentored into their own forecasting interface
at Gtech, and straightforward ML&#x2F;DL courses for engineering teams at the other
two, one eight modules long, the other reaching more than ten engineers.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;taking-a-real-job-while-still-consulting&quot;&gt;Taking a Real Job While Still Consulting&lt;&#x2F;h2&gt;
&lt;p&gt;While all of this was going on, I also started taking on work that wasn’t
consulting at all. OxyAI brought me on as a contractor from May 2021 to January
2023 to build recommender systems for their clients. For Collectors, an online
art gallery, I built a hybrid multi-modal recommender that combined a user’s
text preferences with CNN-extracted visual features from the artwork itself. For
Dinlebi, an Audible-style audiobook app, I built collaborative filtering with
matrix factorization, plus an onboarding data-collection flow specifically
designed to take the edge off the cold-start problem. Both are apparently still
running in production.&lt;&#x2F;p&gt;
&lt;p&gt;In April 2021 I joined Universal Software full time, a company that builds
software for municipalities, ministries, and the utility companies that work
closely with them, like water administrations and energy providers. This is
where the work stopped being purely about a single client’s forecast and started
touching physical infrastructure. The two projects that stuck with me most: a
route optimization system for municipal garbage trucks, built on IoT sensors
mounted on the bins themselves reporting fullness and flagging fire or flood
events, routed through heuristic algorithms instead of a fixed schedule; and a
real-time object detector for Enerjisa, the country’s largest electricity
provider, that ran on the phones field workers used to photograph inventory, so
blurry, duplicate, or empty shots never made it into the database in the first
place. Around the same time I also built a predictive maintenance classifier for
a client’s CNC assembly line, LSTM forecasting pipelines for electricity and gas
consumption under a project called GAM-GAD (short for Geographic Analysis
Modules and Geographic Analysis Tools), and an LSTM pipeline forecasting future
water demand for the Istanbul Water Administration.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;leading-a-team-and-chasing-grants&quot;&gt;Leading a Team and Chasing Grants&lt;&#x2F;h2&gt;
&lt;p&gt;Universal Yazılım also runs the support software a lot of municipalities use,
and two of the projects I’m most proud of came out of that side of the business.
The first is a ticketing classifier that uses TF-IDF and sentiment embeddings to
route incoming citizen complaints to the right department automatically, now
running across every municipality the company works with and fully replacing the
person whose job it used to be to read and route those tickets by hand. The
second is a support-ticket system for the municipalities themselves — when
something breaks or needs adding in the software we’ve deployed to them, or they
just have a reproducible support question or an event to log, they open a ticket
here. It was generating fifty to a hundred messages a day, many of them repeats
of questions already answered, buried in typos and miscategorization. I shipped
a first version that uses embeddings and clustering to find the underlying
topics, an LLM to clean the raw text into something legible, and a
sentence-similarity layer to auto-answer anything already solved before. It cut
response time by roughly half, and it’s still one of the most exhausting and
most satisfying projects I’ve shipped.&lt;&#x2F;p&gt;
&lt;p&gt;I’m still on it, too. I’ve since been handed years more of that same ticket
history, profiled it properly, and sketched out nine more directions worth
building on top of version one — category prediction, time-to-resolution, SLA
risk, routing, duplicate detection, clustering, process mining, response
suggestion, anomaly detection. Haven’t committed to which one’s next.&lt;&#x2F;p&gt;
&lt;p&gt;In January 2024 I was promoted to lead Universal’s AI R&amp;amp;D team. Since then I’ve
been the technical lead on two Horizon Europe consortium proposals: FloodGuard,
a flood prediction project Universal manages end-to-end, and Pre-act, a fire
prediction project Universal only participates in. FloodGuard alone was a 3.5
million euro consortium. Neither was funded in the end, but putting them
together taught me more about scoping a multinational research project than a
funded one probably would have.&lt;&#x2F;p&gt;
&lt;p&gt;Around the same time, I picked up a project funded under Tübitak’s 1832 program:
forecasting future river discharge across Turkey. I started with the obvious
approaches first, supervised regression models, then autoregressive deep
learning models, and all of them performed badly. What ended up working was a
custom seq2seq LSTM with attention built in, which is now running across eight
regions and sixteen river basins around the country. I’m leading the project
together with our hydraulics engineer, which has been its own kind of education,
explaining to a domain expert why the model is doing what it’s doing, and
learning enough hydrology from him to know which features were worth engineering
in the first place.&lt;&#x2F;p&gt;
&lt;p&gt;In the middle of all this I also went back to school. I started a master’s at
Çukurova University in August 2023 and finished in February 2026, with a thesis
on estimating an object’s length from a photo without any physical reference
point in frame, using depth estimation and attention-driven vision models. It’s
a narrower, more academic kind of problem than anything I’d been paid to solve,
which was exactly the point of doing it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;where-the-consultancy-work-stands-today&quot;&gt;Where the Consultancy Work Stands Today&lt;&#x2F;h2&gt;
&lt;p&gt;The consultancy side never stopped while all of this was happening, it just kept
compounding. Four engagements are still active as I’m writing this. Inveon, an
e-commerce technology company, has me building product search that works off
titles and descriptions without needing exact matches, a
mixture-of-experts-style image classifier across more than fifty product
subcategories, and similarity and recommendation systems that can take an image,
a description, or a title as input, all shipped through Tkinter, Streamlit, and
FastAPI. Ikas, an e-commerce SaaS platform, is running the full three-route
pattern I eventually settled on for app delivery — Tkinter for model-building,
Streamlit for people who need to use a model without touching code, an API for
everything that needs to live inside their own systems — all deployed and
actually in use, which is a long way from the single overloaded Tkinter file I
was patching by hand for Comdata six years earlier. Moka, a fintech and payments
company, has me on price prediction, churn, lifetime value, and forecasting,
deployed on Azure with Docker and Kubernetes, working inside an actual team with
git pull requests instead of being the only name on the commit log, which still
feels new after years of working alone. Robokobi, a CRM platform for SMEs, has
me on financial forecasting using the same Tkinter-plus-Streamlit pattern.&lt;&#x2F;p&gt;
&lt;p&gt;Smartiks, a software company, was a similarly long-running consultancy: three
years working with their R&amp;amp;D center, eventually leading a small team of three
there. Most of that time went into writing and leading the technical side of
ITEA consortium proposals, the same kind of grant-scoping work I was doing for
Universal, just for a different company’s portfolio. Underneath that sat a
handful of smaller deliverables — a Basal Metabolic Rate model for a health
client, e-commerce customer segmentation, a bird-detection model for drone
safety. That engagement wrapped up in May 2026.&lt;&#x2F;p&gt;
&lt;p&gt;Underneath those is a long tail of shorter, narrower engagements. Badem is the
one with the most history — regression and churn&#x2F;LTV models since 2022 for a
company serving more than a thousand doctor-customers. Past that, it’s a dozen
more SME, fintech, and energy clients running the same handful of recurring
problems: forecasting, churn, fraud, feasibility. The full roster, with dates
and tech stacks, is on the &lt;a href=&quot;&#x2F;work&quot;&gt;&#x2F;work&lt;&#x2F;a&gt; page if you want the long version.&lt;&#x2F;p&gt;
&lt;p&gt;Looking back at all of it, the throughline isn’t really the algorithms, it’s
that I started out as one person patching a single overgrown Tkinter file by
hand for every new client, and somewhere along the way that turned into leading
teams, writing European grant consortium proposals, and mentoring other
engineers into building their own versions of the same idea in languages I don’t
even write. I’d still rewrite that first app from scratch if I had the time. I’m
not sure I’d change much else.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>How Linux Changed the Way I Think</title>
        <published>2026-03-18T00:00:00+00:00</published>
        <updated>2026-03-18T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hhyurdagul.com/articles/how-linux-changed-the-way-i-think/"/>
        <id>https://hhyurdagul.com/articles/how-linux-changed-the-way-i-think/</id>
        
        <content type="html" xml:base="https://hhyurdagul.com/articles/how-linux-changed-the-way-i-think/">&lt;p&gt;This is one of those things that sounds small when stated plainly, but stayed
with me because of what it revealed. On the surface, this is a story about
controlling my monitor through software on Linux. But that is only the example,
not the point.&lt;&#x2F;p&gt;
&lt;p&gt;What really interests me is the kind of experience Linux gives over time. After
enough years of using it, tinkering with it, breaking things and fixing them
again, you start to carry a certain instinct with you. You begin to feel that
most things on a computer are not fixed objects to be accepted as they are, but
systems that can be questioned, inspected, and maybe bent a little.&lt;&#x2F;p&gt;
&lt;p&gt;That instinct matters more than any single tool. It changes not only what you
know how to do, but what you think to try in the first place. This article is
really about that, and the monitor is only the example that reminded me of it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-other-systems-taught-me&quot;&gt;What Other Systems Taught Me&lt;&#x2F;h2&gt;
&lt;p&gt;Like everybody in the world I was introduced to computing through Windows. Due
to my interests in computers, I became proficient in it but not at a Windows
system admin level. Like every old school PC user, I’ve played games, cracked
applications, and used Internet Download Manager. I learned that if something
isn’t working, fix the .dll issue; it’s fixable but not magical. When I
discovered Linux in my first year of bachelor’s, I switched immediately. I
became attached to it. The freedom, the customization, the shell, and even Vim
all added up to the kind of ecosystem I wanted. Using and tinkering with Linux
taught me a special way of thinking, which I’ll discuss after my OS timeline.&lt;&#x2F;p&gt;
&lt;p&gt;After spending a long time with Linux, I needed a new device around the time
Apple’s M1 machines were getting attention. They were impressive, had literal
infinite battery life, great hardware, and were solid. So I bought one, and for
many things, it was a great device.&lt;&#x2F;p&gt;
&lt;p&gt;Still, using macOS gave me a very different relationship with the machine. By
that point, Linux had already taught me enough of the Unix side of things that
using a shell on macOS did not feel new or revealing. What stood out to me
instead were the inconsistencies, the keyboard shortcuts that felt arbitrary,
and the general feeling that the system did not want me to change too much. It
was polished, but also distant. MacOS did not make me feel incapable, but it did
make me feel like the machine was no longer open to negotiation. It presented
the device as a finished object rather than something I could interrogate.
Because of that, even after three years on a Mac, my old computer, ancient as it
was, still called back to me. On macOS, I often felt that I had lost the freedom
to shape the machine around the way I actually wanted to use it.&lt;&#x2F;p&gt;
&lt;p&gt;I think the same is often true of Windows as well, even if I cannot say that
with complete certainty. My impression is that these systems usually do not
teach the user to think in that direction. They may allow certain things, but
they do not cultivate the habit of asking whether deeper control is possible.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-actual-problem&quot;&gt;The Actual Problem&lt;&#x2F;h2&gt;
&lt;p&gt;Meanwhile, I had a small but surprisingly persistent problem: The brightness of
my external monitor. Like any sensible software person, I eventually bought
myself an external monitor, though it came with one annoying quirk. I use my
computer both in the mornings and at night which of course gave me the need to
change the brightness of my devices constantly. For the laptop it was fine, just
push a key and voila it changed, but the only way to do for the external monitor
was through the monitor’s physical controls.&lt;&#x2F;p&gt;
&lt;p&gt;That meant getting up, reaching for the little control dongle, pushing it in one
direction, waiting for the brightness to move, then pushing again, and repeating
that process until the screen was finally where I wanted it. Then I would do it
all over again later in the day. Sometimes, at night, I would even reset the
monitor back to a more neutral state just so I would not have to think about it
as much the next morning. Even that brought a small but real amount of mental
overhead.&lt;&#x2F;p&gt;
&lt;figure&gt;
  &lt;video width=&quot;300&quot; height=&quot;533&quot; controls preload=&quot;none&quot; aria-label=&quot;Physical monitor brightness control dongle&quot;&gt;
    &lt;source src=&quot;dongle.mp4&quot; type=&quot;video&#x2F;mp4&quot;&gt;
    &lt;a href=&quot;dongle.mp4&quot;&gt;Download the dongle video.&lt;&#x2F;a&gt;
  &lt;&#x2F;video&gt;
  &lt;figcaption&gt;The monitor’s physical control dongle.&lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
&lt;p&gt;It was not a dramatic problem, but it was exactly the kind of repetitive
friction that slowly makes a setup feel worse than it should.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-linux-taught-me&quot;&gt;What Linux Taught Me&lt;&#x2F;h2&gt;
&lt;p&gt;Eventually, I bought a PC, installed Arch Linux immediately, and returned to the
environment I had missed. The monitor problem was still there, but Linux had
already taught me something important over the years: Easy or hard, but there is
always a solution, if you are willing to investigate enough you can always find
that solution.&lt;&#x2F;p&gt;
&lt;p&gt;That belief did not come from a single discovery, but from years of tinkering
across Linux distributions, desktop environments, and window managers.&lt;span class=&quot;sn-wrap&quot;&gt;&lt;label for=&quot;sn-linux-distros&quot; class=&quot;margin-toggle sidenote-number&quot;&gt;&lt;&#x2F;label&gt;&lt;input type=&quot;checkbox&quot; id=&quot;sn-linux-distros&quot; class=&quot;margin-toggle&quot; &#x2F;&gt;&lt;span class=&quot;sidenote&quot;&gt;I used Mint, Ubuntu, Debian, Fedora, PopOS, Manjaro, Arch, NixOS, and even one distribution that marketed itself as very close to macOS, though I cannot remember its name now. On the desktop and window-manager side, I went through GNOME, KDE, LXQt, Deepin, Xfce, i3, bspwm, Qtile, Awesome, something written by Haskell, Suckless Stuff and eventually Hyprland.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;Over time, that kind of experience teaches patience, curiosity, and a deeper
instinct: that almost everything in Linux can be inspected, configured, or
scripted. After a while, possibility stops feeling exceptional and starts
feeling expected.&lt;&#x2F;p&gt;
&lt;p&gt;That is the real point. Linux did not just give me a tool. It gave me the
mindset to ask the question in the first place.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;finding-the-tool&quot;&gt;Finding the Tool&lt;&#x2F;h2&gt;
&lt;p&gt;Once I started thinking that way again, the solution was not far away. I
searched a bit and found &lt;code&gt;ddcutil&lt;&#x2F;code&gt;. I did not even need to build something from
scratch. The tool already did exactly what I needed: it let me control my
external monitor directly through software.&lt;&#x2F;p&gt;
&lt;p&gt;That changed the whole experience immediately. Instead of standing up and
working through physical controls every morning and every night, I could script
brightness and RGB adjustments precisely the way I wanted. Some people might
mention the &lt;code&gt;backlight&lt;&#x2F;code&gt; utility, but that is not really the same thing because
it adjusts the system backlight rather than controlling an external monitor
itself.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-it-matters&quot;&gt;Why It Matters&lt;&#x2F;h2&gt;
&lt;p&gt;Now I have a setup that responds to me instead of forcing me into awkward little
rituals throughout the day. I can change brightness and color settings without
touching the monitor at all. The problem itself was small, but solving it
reminded me of something much bigger.&lt;&#x2F;p&gt;
&lt;p&gt;Experience does more than help you solve problems. It shapes what kinds of
solutions you are even capable of imagining. On macOS, and maybe on Windows too,
I lived with the monitor as though its buttons were the only option. Linux, and
years of tinkering with it, had taught me otherwise.&lt;&#x2F;p&gt;
&lt;p&gt;To be fair, this problem can probably be solved on macOS or Windows as well. The
difference is not pure capability, but what each system teaches you to imagine.
On Linux, it feels natural to ask where the system exposes the device&lt;span class=&quot;sn-wrap&quot;&gt;&lt;label for=&quot;sn-linux-dev&quot; class=&quot;margin-toggle sidenote-number&quot;&gt;&lt;&#x2F;label&gt;&lt;input type=&quot;checkbox&quot; id=&quot;sn-linux-dev&quot; class=&quot;margin-toggle&quot; &#x2F;&gt;&lt;span class=&quot;sidenote&quot;&gt;As a literal file under directory &amp;#x2F;dev.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
, how
to talk to it, and whether it can be scripted. After enough time in that
environment, exploration becomes instinct.&lt;&#x2F;p&gt;
&lt;p&gt;That is why this matters to me. The value of Linux is not only that it gives you
control. It is that, after enough time with it, it teaches you to see control as
something that might exist everywhere, even in places where most people would
never think to look. It shapes your life as well. After enough time with Linux,
that way of thinking does not stay confined to the computer. You begin to carry
it into other parts of life too: the sense that things are not always as fixed
as they first appear, that constraints can be questioned, and that with enough
patience and effort, more is possible than you initially assumed.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Small Example of Real Agentic Benchmarks</title>
        <published>2026-02-22T00:00:00+00:00</published>
        <updated>2026-02-22T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hhyurdagul.com/articles/real-agentic-ai-benchmark/"/>
        <id>https://hhyurdagul.com/articles/real-agentic-ai-benchmark/</id>
        
        <content type="html" xml:base="https://hhyurdagul.com/articles/real-agentic-ai-benchmark/">&lt;p&gt;Everybody I know who actually works with LLMs hates benchmarks. They’re biased,
gamed, and rarely translate to real-world utility. But there is no escape from
them because benchmarks are the only proofs we have of what these models can do.&lt;&#x2F;p&gt;
&lt;p&gt;Since leaderboards can’t be trusted completely when I want to choose a model to
work with, the only real solution to select correctly is to test them myself
extensively. But that’s as you have probably done it before knows is very
tedious. New models drop weekly, each with different pricing, latency, and
capabilities, and keeping up feels impossible. So we tend to stick with what we
know, like Opus or Codex models.&lt;&#x2F;p&gt;
&lt;p&gt;Now of course, there is the opinions of other people, and it constantly changes
but you can get the general idea following others and understand which models
are good for which tasks. For example, you might know that Gemini is pretty good
in generating UI than other models, and in the past Opus models was very bad at
generating UIs especially compared with Codex, but now it is swapped, when
followed general knowledge, it seems the roles reversed, for UI Opus is better
and for engineering tasks Codex is better.&lt;&#x2F;p&gt;
&lt;p&gt;What is great about going with collective ideas of humans is that they are much
more trustable than leaderboards because the knowledge comes from real life, but
those real life usages biased towards vibe-coding. What I mean by this is,
people use and have most of their ideas come from using models in one-shot or
vibe coding scenarious, where understanding of the codebase has no value at all,
because they are always telling AI to do any of the job. But this is very
overhyped, in a case of losing an access to big models or cleaning the context
would create much much more work to do, because it should understand all the
codebase from very beginning because you don’t know what the codebase looks like
and it grow bigger much faster than you expected.&lt;&#x2F;p&gt;
&lt;p&gt;So evaluations should come from humans yes, but it should be done in a way that
it is not biased towards vibe-coding. The real strength of the models can be
understood if it is really used as a pair programmer, where you have the
absolute idea of what the code does and you don’t want to write every bit of the
code for reasons like repeating, or knowing the logic but having the ai write it
will be much faster etc. This should be the form of benchmarking of these
models, this way they can’t be bechmaxed and would have a real impact of helping
people.&lt;&#x2F;p&gt;
&lt;p&gt;To showcase what I am talking about in a practical sense, I want to talk about a
problem, and laziness of mine, which is redesigning my personal website, and
really start publishing some content this time. There is some steps to this:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Use AI (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;gemini.google.com&#x2F;&quot;&gt;Gemini&lt;&#x2F;a&gt;) to generate the CSS of the
website.&lt;&#x2F;li&gt;
&lt;li&gt;Use some sort of static site generator (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;soupault.net&quot;&gt;Soupault&lt;&#x2F;a&gt;) to
generate the HTML of the website.
&lt;ul&gt;
&lt;li&gt;Create the basic template of the site to make AI understand the structure
of the website. Because soupault is very odd and unused site generator,
AI’s are not happy about it, they just know its name, and don’t know how to
operate it.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Get the raw code of the design file from AI as HTML.&lt;&#x2F;li&gt;
&lt;li&gt;Prompt the agentic framework using the template and the raw HTML to generate
the final project.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;This is actually very easy, and this idea came to me in the middle of doing
things manually so I have a pretty good template for AI to work with. And I have
a design too.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-example&quot;&gt;The example&lt;&#x2F;h2&gt;
&lt;p&gt;Soupault uses a &lt;code&gt;soupault.toml&lt;&#x2F;code&gt; file to configure the site. It creates some
index pages based on the template you provide in that file. It is that easy.&lt;&#x2F;p&gt;
&lt;p&gt;My problem is that, I want to implement a &lt;code&gt;blog-entry&lt;&#x2F;code&gt;, and &lt;code&gt;project-card&lt;&#x2F;code&gt;
component for my indexes, as entry points to real pages, and I have the design
as HTML code. And like I said before, I have a already created the template for
blog entry and I just want AI to copy the exact same thing for &lt;code&gt;project-card&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Here is the template for &lt;code&gt;blog-entry&lt;&#x2F;code&gt; in &lt;code&gt;soupault.toml&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;index&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;views&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;writing&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;  index_selector&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.writing-list&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;  section&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;writing&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;  include_subsections&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;  exclude_page&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;writing&#x2F;index.html&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;  sort_by&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;date&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;  sort_type&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;calendar&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;  sort_descending&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;  index_template&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    {% for e in entries %}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    &amp;lt;a href=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{{e.url}}&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;      &amp;lt;article class=&amp;quot;blog-post&amp;quot;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;lt;div class=&amp;quot;blog-meta&amp;quot;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;          &amp;lt;span&amp;gt;{{e.date_display}}&amp;lt;&#x2F;span&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;          &amp;lt;div class=&amp;quot;dot&amp;quot;&amp;gt;&amp;lt;&#x2F;div&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;          &amp;lt;span&amp;gt;{{e.reading_time}}&amp;lt;&#x2F;span&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;lt;&#x2F;div&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;lt;h3&amp;gt;{{e.title}}&amp;lt;&#x2F;h3&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        {% if e.excerpt %}&amp;lt;p&amp;gt;{{e.excerpt}}&amp;lt;&#x2F;p&amp;gt;{% endif %}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;lt;div class=&amp;quot;read-more&amp;quot;&amp;gt;Read Log&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;          &amp;lt;svg&amp;gt;&amp;lt;use href=&amp;quot;#icon-arrow-right&amp;quot;&amp;gt;&amp;lt;&#x2F;use&amp;gt;&amp;lt;&#x2F;svg&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;lt;&#x2F;div&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;      &amp;lt;&#x2F;article&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    &amp;lt;&#x2F;a&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    {% endfor %}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;  &amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I don’t want to repeat myself, but this above code ensures that the AI agent
have some example that it can work with. The thing that I want to do is pretty
much the same thing, but I don’t want to copy and paste the code by hand, AI
should be able to generate the code for me.&lt;&#x2F;p&gt;
&lt;p&gt;Also in the template code above, there some variables like {{e.title}}, and if I
needs to understand it, can just look the other parts of the file and understand
easily. This is the separation between copying the code to web app, pasting
answer to the editor and agentic AI. It should just do it automatically.&lt;&#x2F;p&gt;
&lt;p&gt;Let’s stay on the topic, so here is the example design of the project card:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;hhyurdagul.com&#x2F;articles&#x2F;real-agentic-ai-benchmark&#x2F;.&#x2F;example-project-card.png&quot; alt=&quot;Example Project Card Image&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;And here is the code for that example project card:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;div&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; class&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;project-card&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;div&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; class&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;project-header&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;h3&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;Causal Inference Engine&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;h3&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; href&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;svg&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; href&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;#icon-arrow-right&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;use&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;svg&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;div&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;p&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    A distributed system designed to separate correlation from causation in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    massive datasets. Built to strip away noise and reveal underlying truths.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;p&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;div&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; class&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;tech-tags&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;span&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;Python&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;span&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;span&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;PyTorch&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;span&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;span&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;C++&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;span&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;span&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;CUDA&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;span&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;div&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;div&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It is pretty basic stuff, what the llms have to do is to extract the code and
insert it as a template.&lt;&#x2F;p&gt;
&lt;p&gt;Here there is already a toml entries for the project view, the AI only needs to
write the template and nothing more.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;index&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;views&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;projects&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;  index_selector&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.projects-grid&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;  section&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;projects&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;  include_subsections&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;  exclude_page&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;projects&#x2F;index.html&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;  sort_by&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;title&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;  sort_type&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;lexicographic&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;  sort_descending&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; false&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There are some catches that will make us to evaluate the llms.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;It has to figure out how will it get the tags from soupualts internal
variables. (They do not know it and have to figure it out.)
&lt;ul&gt;
&lt;li&gt;Example of {{e.title}} in the above example.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;They should not generate unknown template codes thing of the air.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I will not give them any documentation to understand how it is done, this can be
done just by looking at the example code.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-results&quot;&gt;The results&lt;&#x2F;h2&gt;
&lt;p&gt;The prompt is pretty simple: I want you to take a look at @soupault.toml and
create a &lt;code&gt;project view&lt;&#x2F;code&gt; inside it based on the design in
@site&#x2F;projects&#x2F;index.html. You can use the template of &lt;code&gt;writing view&lt;&#x2F;code&gt; as an
example of how templating language works. Don’t create meaningles syntax.&lt;&#x2F;p&gt;
&lt;p&gt;All the agents are used within &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;opencode.ai&#x2F;&quot;&gt;Opencode&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;codex-5-3&quot;&gt;Codex 5.3&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;hhyurdagul.com&#x2F;articles&#x2F;real-agentic-ai-benchmark&#x2F;.&#x2F;codex.png&quot; alt=&quot;Codex Result&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{% for e in entries %}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;div class=&amp;quot;project-card&amp;quot;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;lt;div class=&amp;quot;project-header&amp;quot;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;h3&amp;gt;{{e.title}}&amp;lt;&#x2F;h3&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;a href=&amp;quot;{{e.url}}&amp;quot;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;svg&amp;gt;&amp;lt;use href=&amp;quot;#icon-arrow-right&amp;quot;&amp;gt;&amp;lt;&#x2F;use&amp;gt;&amp;lt;&#x2F;svg&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;&#x2F;a&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;lt;&#x2F;div&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  {% if e.excerpt %}&amp;lt;p&amp;gt;{{e.excerpt}}&amp;lt;&#x2F;p&amp;gt;{% endif %}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  {% if e.project_tags %}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;lt;div class=&amp;quot;tech-tags&amp;quot;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;span&amp;gt;{{e.project_tag}}&amp;lt;&#x2F;span&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;lt;&#x2F;div&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  {% endif %}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&#x2F;div&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{% endfor %}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ul&gt;
&lt;li&gt;It finely did what it needs to do, but went over its head to manipulate the
code outside of the templates a bit, not too much but a bit.&lt;&#x2F;li&gt;
&lt;li&gt;It took too much for this basic task in my opinion.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;gemini-3-1-pro&quot;&gt;Gemini 3.1 Pro&lt;&#x2F;h3&gt;
&lt;!-- ![Gemini Result](.&#x2F;gemini.png) --&gt;
&lt;p&gt;Empty&lt;&#x2F;p&gt;
&lt;h3 id=&quot;minimax-m2-5&quot;&gt;Minimax M2.5&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;hhyurdagul.com&#x2F;articles&#x2F;real-agentic-ai-benchmark&#x2F;.&#x2F;minimax.png&quot; alt=&quot;Minimax Result&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;It did create perfectly, did go overboard, but I have one more index page that
I will prompt eventualy to do it, it already have done it, didn’t change
anything other than templates.&lt;&#x2F;li&gt;
&lt;li&gt;It was fast enough.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{% for e in entries %}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;div class=&amp;quot;project-card&amp;quot;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;lt;div class=&amp;quot;project-header&amp;quot;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;h3&amp;gt;{{e.title}}&amp;lt;&#x2F;h3&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;a href=&amp;quot;{{e.url}}&amp;quot;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;svg&amp;gt;&amp;lt;use href=&amp;quot;#icon-arrow-right&amp;quot;&amp;gt;&amp;lt;&#x2F;use&amp;gt;&amp;lt;&#x2F;svg&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;&#x2F;a&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;lt;&#x2F;div&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  {% if e.excerpt %}&amp;lt;p&amp;gt;{{e.excerpt}}&amp;lt;&#x2F;p&amp;gt;{% endif %}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  {% if e.project_tags %}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;lt;div class=&amp;quot;tech-tags&amp;quot;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;span&amp;gt;{{e.project_tag}}&amp;lt;&#x2F;span&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;lt;&#x2F;div&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  {% endif %}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&#x2F;div&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{% endfor %}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;glm5&quot;&gt;GLM5&lt;&#x2F;h3&gt;
&lt;!-- ![GLM Result](.&#x2F;glm.png) --&gt;
&lt;p&gt;Empty&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{% for e in entries %}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;div class=&amp;quot;project-card&amp;quot;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;lt;div class=&amp;quot;project-header&amp;quot;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;h3&amp;gt;{{e.title}}&amp;lt;&#x2F;h3&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;a href=&amp;quot;{{e.url}}&amp;quot;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;svg&amp;gt;&amp;lt;use href=&amp;quot;#icon-arrow-right&amp;quot;&amp;gt;&amp;lt;&#x2F;use&amp;gt;&amp;lt;&#x2F;svg&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;&#x2F;a&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;lt;&#x2F;div&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  {% if e.excerpt %}&amp;lt;p&amp;gt;{{e.excerpt}}&amp;lt;&#x2F;p&amp;gt;{% endif %}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  {% if e.project_tags %}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;lt;div class=&amp;quot;tech-tags&amp;quot;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    {% for tag in e.project_tags:split(&amp;quot;,&amp;quot;) %}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;span&amp;gt;{{tag}}&amp;lt;&#x2F;span&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    {% endfor %}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;lt;&#x2F;div&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  {% endif %}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&#x2F;div&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{% endfor %}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;GLM coulnd’t do it the first time, because eventhough I stated it it created a
syntax from thing air &lt;code&gt;project_tags:split(&quot;,&quot;)&lt;&#x2F;code&gt; which there is a zero evidence
that code will work but GLM went ahead and did it. It tried to be smart about
project tags, and yes the end results should really be like that, split by
commas maybe, it could work out but the syntax is wrong. There is no &lt;code&gt;:split&lt;&#x2F;code&gt; in
the template that I am using and Soupalt screaming that it can’t build, I make
it work in the second time because I know where the error is. I just told it the
split can’t be used here and it fixed itself but it is really baffling to see
the AI create a syntax eventhough it is said to not do it.&lt;&#x2F;p&gt;
&lt;p&gt;This shows that when working with niche projects and tools that are not React or
Next.js or Javascript or even Python, the AI may not be able to create the best
results immediately. At my examples AI’s didn’t need to know how soupault worked
because the example is already solveable if you have a knowledge of coding,
because there are immediate examples to follow. And there may come a time
wherethe big companies will not be able to provide cheap coding plans and you
might have to use open source ones, or this may not happen but in the end, a
little bit of smart model, can do the things you want to do, we just need to
know how smart are they and not how they can one shot a website or app or
anything. Don’t buy the benchmaxing and don’t try to create using that way, this
will be the optimal usage of AI, and our benchmarks need to be able align with
real use cases like these ones.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Fishometry — Measuring Fish Without a Reference Object</title>
        <published>2026-01-13T00:00:00+00:00</published>
        <updated>2026-01-13T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hhyurdagul.com/projects/fishometry/"/>
        <id>https://hhyurdagul.com/projects/fishometry/</id>
        
        <content type="html" xml:base="https://hhyurdagul.com/projects/fishometry/">&lt;p&gt;Fishometry is my completed master’s-thesis research pipeline for estimating fish
length from a single image without a ruler, calibration target, or other
physical reference. I designed the data workflow, computer-vision pipeline,
experiment matrix, and analysis application end to end. The written thesis and
public results package are now being prepared.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;3 dataset variants&lt;&#x2F;strong&gt; · &lt;strong&gt;Controlled and outdoor imagery&lt;&#x2F;strong&gt; · &lt;strong&gt;Held-out test
design&lt;&#x2F;strong&gt; · &lt;strong&gt;Research complete&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The project began with a difficult question: &lt;em&gt;how much physical-length
information can a model recover when an image contains no explicit scale?&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-scientific-constraint&quot;&gt;The Scientific Constraint&lt;&#x2F;h2&gt;
&lt;p&gt;Absolute size from one ordinary monocular image is fundamentally ambiguous. A
small fish close to the camera can occupy the same number of pixels as a larger
fish farther away. Relative depth estimators can describe which parts of a scene
appear nearer or farther, but they do not automatically provide centimeters.&lt;&#x2F;p&gt;
&lt;p&gt;Fishometry therefore studies learned estimation within defined data
distributions: controlled laboratory photographs, zoom-derived versions, and
heterogeneous outdoor images spanning multiple fish types and scene conditions.&lt;&#x2F;p&gt;
&lt;p&gt;The evaluation asks whether geometry, relative depth, segmentation, species, and
scene context improve held-out estimates beyond simple baselines—and whether
those signals survive changes in scale and environment.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;research-pipeline&quot;&gt;Research Pipeline&lt;&#x2F;h2&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;mermaid&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;flowchart LR&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    RAW[&amp;quot;Raw image + measured length&amp;quot;] --&amp;gt; SPLIT[&amp;quot;Persisted train &#x2F; validation &#x2F; test split&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    SPLIT --&amp;gt; DETECT[&amp;quot;YOLO detection&amp;lt;br&#x2F;&amp;gt;head · tail · eye · fish&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    DETECT --&amp;gt; ALIGN[&amp;quot;Head-to-tail rotation&amp;lt;br&#x2F;&amp;gt;and second detection&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ALIGN --&amp;gt; SEGMENT[&amp;quot;SAM mask + blackout image&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ALIGN --&amp;gt; DEPTH[&amp;quot;Depth Anything V2&amp;lt;br&#x2F;&amp;gt;relative-depth features&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    RAW --&amp;gt; CONTEXT[&amp;quot;Gemini scene context&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    SEGMENT --&amp;gt; FEATURES[&amp;quot;Geometry and image artifacts&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    DEPTH --&amp;gt; FEATURES&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    CONTEXT --&amp;gt; FEATURES&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    FEATURES --&amp;gt; MODELS[&amp;quot;Baselines · tabular ML · CNN · embeddings&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    MODELS --&amp;gt; PREDICTIONS[&amp;quot;Split-aware prediction table&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    PREDICTIONS --&amp;gt; APP[&amp;quot;Streamlit research explorer&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Each stage writes an explicit artifact consumed by the next, making image
losses, derived features, and experiment outputs inspectable.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;protecting-the-experimental-split&quot;&gt;Protecting the Experimental Split&lt;&#x2F;h2&gt;
&lt;p&gt;The first stage persists mutually exclusive training, validation, and test
assignments before preprocessing or fitting. Test targets are not used for model
selection.&lt;&#x2F;p&gt;
&lt;p&gt;Each controlled photograph produces an original, zoom-in, and zoom-out image.
Fishometry inherits the source image’s assignment across the family, preventing
a model from training on one version and being tested on a near-duplicate.&lt;&#x2F;p&gt;
&lt;p&gt;Three dataset variants serve different research questions:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Dataset&lt;&#x2F;th&gt;&lt;th&gt;Purpose&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Controlled&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Establish what can be learned from consistent laboratory images with measured lengths&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Controlled + zoom&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Test sensitivity to apparent scale without changing the underlying fish or target length&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Outdoor multi-species&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Test a more heterogeneous setting with different fish types, backgrounds, lighting, placement, and surrounding objects&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h2 id=&quot;turning-an-image-into-measurements&quot;&gt;Turning an Image Into Measurements&lt;&#x2F;h2&gt;
&lt;p&gt;The preprocessing pipeline combines multiple views of the same evidence:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Detection and alignment:&lt;&#x2F;strong&gt; YOLO identifies the fish and available
anatomical landmarks. Head and tail centers define a horizontal rotation,
followed by a second detection pass on the aligned image.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Segmentation:&lt;&#x2F;strong&gt; Segment Anything produces a binary fish mask. From it, the
pipeline derives mask area, perimeter, major and minor axes, solidity, and a
fish-only image on a standardized canvas.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Relative depth:&lt;&#x2F;strong&gt; Depth Anything V2 estimates depth at the head, body, and
tail, together with raw and absolute gradients. These remain relative scene
features, not metric distance.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Scene context:&lt;&#x2F;strong&gt; Gemini extracts structured descriptions such as fish
placement, orientation, lighting, nearby objects, and whether the fish
appears inside a net.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Geometric features:&lt;&#x2F;strong&gt; Bounding boxes and masks produce relative width,
height, area, aspect, eye dimensions, and other normalized measurements.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;This design isolates whether anatomical measurements, segmentation geometry,
depth, species, or original-scene context contribute signal.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;controlled-model-matrix&quot;&gt;Controlled Model Matrix&lt;&#x2F;h2&gt;
&lt;p&gt;Every dataset begins with a training-only mean baseline. The main experiment
families then progress from interpretable tabular models to image
representations:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Model family&lt;&#x2F;th&gt;&lt;th&gt;Evidence used&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Mean and linear baselines&lt;&#x2F;td&gt;&lt;td&gt;Training-set length distribution and selected engineered features&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;XGBoost&lt;&#x2F;td&gt;&lt;td&gt;Nonlinear relationships among geometry, context, species, and optional depth features&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Tabular MLP&lt;&#x2F;td&gt;&lt;td&gt;Learned interactions over the same structured feature groups&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;ResNet-18 CNN&lt;&#x2F;td&gt;&lt;td&gt;Fish-only blackout image combined with auxiliary tabular features&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;EfficientNet-B3 + Ridge&lt;&#x2F;td&gt;&lt;td&gt;Frozen rotated-image embeddings joined with structured features, with global and fish-type-specific estimators&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;Controlled experiments compare eye and coordinate feature groups with and
without depth. Outdoor experiments compare geometry against richer segmentation
and scene features, again with and without depth, and evaluate global versus
fish-type-specific modeling.&lt;&#x2F;p&gt;
&lt;p&gt;Validation data controls XGBoost early stopping and neural checkpoint selection
where required. The test split remains held out during fitting and selection.
Predictions are joined by image name so the analysis layer can compare aligned
rows across models.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;analysis-application&quot;&gt;Analysis Application&lt;&#x2F;h2&gt;
&lt;p&gt;A Streamlit research application explores results rather than reducing the study
to one leaderboard number. It supports split-specific metrics, global and
per-fish-type comparisons, correlation views, model-to-model analysis, and
image-level inspection of predictions and processed artifacts.&lt;&#x2F;p&gt;
&lt;p&gt;MAE, MAPE, and R² are calculated in the visualization layer. Reporting must
explicitly select the test split; unfiltered metrics would mix training,
validation, and test rows and would not represent held-out performance.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;publication-status&quot;&gt;Publication Status&lt;&#x2F;h2&gt;
&lt;p&gt;The pipeline and experimental implementation are complete. Quantitative thesis
results, final comparison tables, and representative prediction images are being
prepared as part of the written thesis and are &lt;strong&gt;not claimed on this page yet&lt;&#x2F;strong&gt;.
This page documents the completed research design without substituting
preliminary or unverified numbers for the final held-out analysis.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;current-boundaries&quot;&gt;Current Boundaries&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;A single uncalibrated image cannot provide universally identifiable physical
scale; conclusions are distribution-dependent.&lt;&#x2F;li&gt;
&lt;li&gt;Depth Anything supplies relative depth, not camera-to-object distance in
physical units.&lt;&#x2F;li&gt;
&lt;li&gt;Detection, segmentation, or missing-image failures can reduce the number of
rows that reach later experiments, so model comparisons must use aligned
surviving samples.&lt;&#x2F;li&gt;
&lt;li&gt;Outdoor generalization must be judged by held-out species and scene behavior,
not by performance on controlled photographs.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;what-this-project-demonstrates&quot;&gt;What This Project Demonstrates&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Research design before model selection:&lt;&#x2F;strong&gt; persisted splits and family-safe
augmentation protect the central comparison from leakage.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Multi-stage computer vision:&lt;&#x2F;strong&gt; detection, alignment, segmentation, depth,
context, and learned image features contribute distinct evidence.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Baseline discipline:&lt;&#x2F;strong&gt; simple mean and linear estimators remain part of the
same experiment matrix as deep models.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Honest problem framing:&lt;&#x2F;strong&gt; the work tests learned monocular estimation
without claiming that a reference-free image removes physical scale ambiguity.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Reproducible analysis:&lt;&#x2F;strong&gt; named artifacts and split-aware predictions connect
each displayed result to the pipeline that produced it.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>MdsAI — A Human-Reviewed LLM Platform for Support</title>
        <published>2025-05-19T00:00:00+00:00</published>
        <updated>2025-05-19T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hhyurdagul.com/projects/mdsai/"/>
        <id>https://hhyurdagul.com/projects/mdsai/</id>
        
        <content type="html" xml:base="https://hhyurdagul.com/projects/mdsai/">&lt;p&gt;I lead MdsAI’s AI and data work across the full lifecycle: support-data
strategy, corpus preparation, retrieval and model research, evaluation, and
integration with production software. I work directly with support experts to
define useful behavior and with software engineers to place that behavior inside
the ticket workflow.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Deployed platform&lt;&#x2F;strong&gt; · &lt;strong&gt;29,118 tickets&lt;&#x2F;strong&gt; · &lt;strong&gt;15,404 training-grade cases&lt;&#x2F;strong&gt; ·
&lt;strong&gt;Human approval before action&lt;&#x2F;strong&gt; · &lt;strong&gt;Active production and R&amp;amp;D&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The platform uses four years of real support history to retrieve relevant solved
cases, draft answers with an LLM, suggest operational decisions, and expose
process patterns. It is decision support, not autonomous support: an expert
reviews, edits, accepts, or rejects every generated answer before it reaches a
customer.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-production-problem&quot;&gt;The Production Problem&lt;&#x2F;h2&gt;
&lt;p&gt;The existing Redmine-style system contained valuable solutions, but they were
trapped in years of event logs. Keyword search missed semantically equivalent
issues, duplicate problems were solved repeatedly, and categorization,
assignment, and deadline-risk decisions depended on individual experience.&lt;&#x2F;p&gt;
&lt;p&gt;The raw source contained &lt;strong&gt;132,497 process-log rows&lt;&#x2F;strong&gt; representing &lt;strong&gt;29,118
tickets&lt;&#x2F;strong&gt; from 2022–2025. A ticket could appear many times as comments, status
changes, and reassignments accumulated, while fields mixed missing values,
inconsistent types, placeholders, SQL fragments, Turkish domain terminology, and
product-specific error codes.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;hhyurdagul.com&#x2F;projects&#x2F;mdsai&#x2F;assets&#x2F;yearly_volume.svg&quot; alt=&quot;New support tickets per year, with the highest recorded volume in 2025&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;My first responsibility was therefore not prompting an LLM. It was building a
trustworthy knowledge source.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;building-the-knowledge-corpus&quot;&gt;Building the Knowledge Corpus&lt;&#x2F;h2&gt;
&lt;p&gt;A Polars and Parquet pipeline standardizes identifiers and timestamps, converts
placeholder values to nulls, preserves technical tokens, and aggregates event
histories into ticket-level records. The normalized analysis snapshot contains
&lt;strong&gt;130,168 process rows&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: left&quot;&gt;Corpus measure&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Verified value&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;Raw process-log rows&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;132,497&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;Normalized analysis rows&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;130,168&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;Unique tickets&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;29,118&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;Closed &#x2F; resolution known&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;28,369&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;Closed with a written solution&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;27,188&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;Training-grade after semantic review&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;15,404&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;The cleaned history also quantified why better decision support matters. Median
resolution time was approximately seven days, 28.7% of resolved tickets took
longer than four weeks, and only 20.6% were resolved within one day. Among
20,282 tickets with both a planned and actual closing date, 98.5% closed after
the planned date—evidence that the planning field was not a dependable estimate.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;hhyurdagul.com&#x2F;projects&#x2F;mdsai&#x2F;assets&#x2F;resolution_dist.svg&quot; alt=&quot;Distribution of eligible closed tickets by resolution time&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;semantic-filtering-with-humans-in-the-loop&quot;&gt;Semantic filtering with humans in the loop&lt;&#x2F;h3&gt;
&lt;p&gt;Syntactically valid tickets were not automatically useful training examples.
Test records, thanks-only replies, template answers, and solutions without
technical content could all poison retrieval or supervised learning.&lt;&#x2F;p&gt;
&lt;p&gt;I embedded ticket text with &lt;code&gt;google&#x2F;embeddinggemma-300m&lt;&#x2F;code&gt;, reduced the vectors
with UMAP, and grouped dense semantic patterns with HDBSCAN. The clustering did
&lt;strong&gt;not&lt;&#x2F;strong&gt; decide what was good or bad. It changed the scale of review: support
experts and I could inspect coherent groups instead of auditing 29,000 rows
individually, then label clusters as useful knowledge or low-value material.&lt;&#x2F;p&gt;
&lt;p&gt;That review retained &lt;strong&gt;79 corpus-quality clusters&lt;&#x2F;strong&gt; containing &lt;strong&gt;15,404
tickets&lt;&#x2F;strong&gt;, or 52.9% of the original ticket set.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;hhyurdagul.com&#x2F;projects&#x2F;mdsai&#x2F;assets&#x2F;data_funnel.svg&quot; alt=&quot;Human-reviewed data funnel from raw tickets to the training-grade corpus&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;These 79 groups are quality-control clusters. They are separate from the &lt;strong&gt;281
topic-model clusters&lt;&#x2F;strong&gt; later produced by BERTopic to analyze support themes and
trends.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;choosing-the-retrieval-foundation&quot;&gt;Choosing the Retrieval Foundation&lt;&#x2F;h2&gt;
&lt;p&gt;Retrieval, duplicate detection, clustering, and text classification all depend
on the embedding layer. I compared four model families with three downstream
classifiers on 4,500 labeled tickets, measuring predictive quality alongside
memory and encoding time.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;hhyurdagul.com&#x2F;projects&#x2F;mdsai&#x2F;assets&#x2F;embedding_benchmark.svg&quot; alt=&quot;Embedding benchmark balancing downstream score, memory use, and encoding time&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: left&quot;&gt;Model&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Memory&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Encode time&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Mean downstream score&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;TRModel&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;~384 MB&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;8 s&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;0.892&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;Qwen&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;2,274 MB&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;45 s&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;0.892&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;strong&gt;EmbeddingGemma&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;&lt;strong&gt;578 MB&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;&lt;strong&gt;16 s&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;&lt;strong&gt;0.914&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;E5-Large&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;2,136 MB&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;24 s&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;0.937&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;E5-Large produced the highest score, but EmbeddingGemma became the production
workhorse: it remained within 2.3 points while using roughly one quarter of the
memory and encoding 33% faster.&lt;&#x2F;p&gt;
&lt;p&gt;The same evaluation exposed a taxonomy problem. The source system had 194
category labels, including near-duplicates and classes with fewer than ten
examples. Predicting those raw labels produced approximately 0.14 macro-F1.
Support-led consolidation created seven operationally coherent groups, on which
the model reached 0.46 macro-F1 and 0.67 accuracy. These are different
prediction tasks, so the comparison is evidence for redesigning the taxonomy—not
a claim that the model itself improved threefold.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-deployed-llm-workflow&quot;&gt;The Deployed LLM Workflow&lt;&#x2F;h2&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;mermaid&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;flowchart LR&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    A[&amp;quot;New support ticket&amp;quot;] --&amp;gt; B[&amp;quot;Normalized ticket context&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    B --&amp;gt; C[&amp;quot;EmbeddingGemma retrieval&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    C --&amp;gt; D[&amp;quot;Relevant solved tickets&amp;lt;br&#x2F;&amp;gt;and approved solutions&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    D --&amp;gt; E[&amp;quot;Gemini answer draft&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    B --&amp;gt; F[&amp;quot;Category and routing suggestions&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    E --&amp;gt; G[&amp;quot;Support-expert review&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    F --&amp;gt; G&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    G --&amp;gt;|&amp;quot;approve or edit&amp;quot;| H[&amp;quot;Ticket workflow&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    G --&amp;gt;|&amp;quot;reject&amp;quot;| I[&amp;quot;Feedback for evaluation&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The deployed assistant retrieves semantically similar solved tickets and
supplies their approved solutions as grounded context to Gemini. The resulting
draft appears with supporting cases inside the support workflow. An expert
remains responsible for the final answer, turning the LLM into an accelerator
whose evidence can be inspected rather than an autonomous responder.&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: left&quot;&gt;State&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: left&quot;&gt;Capability&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;strong&gt;Deployed&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Hybrid retrieval, evidence-backed LLM answer drafts, expert approval workflow, and support-facing integration&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;strong&gt;Measured research&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Corpus-quality filtering, embedding benchmarking, taxonomy redesign, classification experiments, and 281-cluster topic analysis&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;strong&gt;Active development&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;Retrieval tuning, production model APIs, assignee and resolution-time models, SLA-risk signals, anomaly detection, and richer trend reporting&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h2 id=&quot;evidence-and-targets&quot;&gt;Evidence and Targets&lt;&#x2F;h2&gt;
&lt;p&gt;Measured results and rollout targets remain deliberately separate.&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: left&quot;&gt;Measured result&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Value&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;Training-grade corpus&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;15,404 tickets&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;Low-value corpus identified before training&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;47.1%&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;Selected embedding model&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;EmbeddingGemma, 0.914 mean downstream score&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;Consolidated-category experiment&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;0.46 macro-F1 &#x2F; 0.67 accuracy&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;Topic-model granularity&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;281 thematic clusters&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: left&quot;&gt;Production target&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Target value&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;Reduction in per-ticket handling time&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;&lt;strong&gt;40%&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;Expert acceptance of LLM answer drafts&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;&lt;strong&gt;Above 80%&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;Human-reviewed SLA warning coverage&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;&lt;strong&gt;Every eligible new ticket&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;Pilot measurement will determine whether those targets are achieved; they are
not presented as current outcomes.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-this-demonstrates&quot;&gt;What This Demonstrates&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;LLM systems begin with knowledge quality.&lt;&#x2F;strong&gt; Retrieval can only be as
trustworthy as the solved cases behind it.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Human review belongs in the architecture.&lt;&#x2F;strong&gt; Support experts govern both
corpus quality and every customer-facing answer.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Operational taxonomies matter as much as models.&lt;&#x2F;strong&gt; Redesigning an unusable
label space created a prediction task the team could act on.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Production trade-offs beat leaderboard choices.&lt;&#x2F;strong&gt; The selected embedding
model balanced quality, memory, latency, and continual ingestion.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Deployment is part of the research loop.&lt;&#x2F;strong&gt; Expert decisions provide the
feedback needed to evaluate retrieval, prompts, routing, and future model
services against real support work.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Electricity Consumption Forecasting for the Turkish Grid</title>
        <published>2025-03-20T00:00:00+00:00</published>
        <updated>2025-03-20T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hhyurdagul.com/projects/electricity-forecasting/"/>
        <id>https://hhyurdagul.com/projects/electricity-forecasting/</id>
        
        <content type="html" xml:base="https://hhyurdagul.com/projects/electricity-forecasting/">&lt;p&gt;I led the AI and data work on this completed forecasting application, working
with Universal Software’s energy team to turn live Turkish electricity-market
data into reproducible forecasts, rolling backtests, and distributor-level
analysis.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;24 h and 168 h horizons&lt;&#x2F;strong&gt; · &lt;strong&gt;~1,800 scored hours per reported horizon&lt;&#x2F;strong&gt; ·
&lt;strong&gt;21 distribution companies&lt;&#x2F;strong&gt; · &lt;strong&gt;Status: completed&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The central question was deliberately practical: &lt;em&gt;can a zero-shot time-series
foundation model compete with the official hourly load-estimation plan published
by EPİAŞ, without training a custom model or engineering calendar and weather
features?&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-i-built&quot;&gt;What I Built&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;Data pipeline&lt;&#x2F;strong&gt; — A client for the EPİAŞ Transparency Platform, including CAS
ticket authentication and incremental updates, that retrieves hourly real-time
consumption back to 2020, EPİAŞ’s published load-estimation plan, and meter data
for all 21 Turkish distribution companies. The pipeline stores analysis-ready
Parquet datasets and processes them with Polars.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Forecasting engine&lt;&#x2F;strong&gt; — TimesFM 2.5 (200M, PyTorch) running zero-shot with a
1,024-hour context window and quantile heads. Forecasts are generated in rolling
24-hour windows and support both day-ahead and week-ahead analysis.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Streamlit application&lt;&#x2F;strong&gt; — A single interface for live forecasts, rolling
backtests, and distributor analysis:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Forecast:&lt;&#x2F;strong&gt; compare a generated forecast with observed demand and EPİAŞ’s
published plan.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Backtest:&lt;&#x2F;strong&gt; evaluate 24-hour and 168-hour horizons over multiple forecast
origins with MAE, RMSE, and MAPE. Every backtest uses only information that
was available when its forecast would have been issued; cached artifacts make
repeated analysis immediate.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Distributor dashboard:&lt;&#x2F;strong&gt; explore hourly meter multipliers across
distributors, profile groups, and meter-reading types.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;hhyurdagul.com&#x2F;projects&#x2F;electricity-forecasting&#x2F;assets&#x2F;dashboard-backtest.png&quot; alt=&quot;Complete backtest view showing horizon and month controls, headline metrics, hourly forecasts, the EPİAŞ baseline, observed demand, and scored rows&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;The complete backtest application view. The metric cards and overlaid series
make model-versus-baseline performance auditable down to the underlying hourly
rows.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;hhyurdagul.com&#x2F;projects&#x2F;electricity-forecasting&#x2F;assets&#x2F;dashboard-distributor.png&quot; alt=&quot;Complete distributor analysis view with company, date, profile-group, and meter-type controls alongside time-series and aggregate comparisons&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;The full distributor workspace. Energy specialists can move from system-level
forecasting to operational comparisons across companies and customer profiles
without leaving the application.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;verified-result-competitive-until-the-calendar-changes&quot;&gt;Verified Result: Competitive Until the Calendar Changes&lt;&#x2F;h2&gt;
&lt;p&gt;Rolling-origin backtests across April–June 2026 used multiple forecast dates at
both horizons. Each forecast was evaluated against the actual consumption later
observed and the EPİAŞ plan that was available at forecast time.&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;MAPE (lower is better)&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;TimesFM zero-shot&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;EPİAŞ published plan&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;24 h — all reported hours&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;3.47%&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;&lt;strong&gt;3.13%&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;24 h — excluding public holidays&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;&lt;strong&gt;2.39%&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;2.92%&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;24 h — April 2026&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;&lt;strong&gt;1.89%&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;2.89%&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;168 h — April 2026&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;&lt;strong&gt;2.59%&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;2.96%&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;24 h — public holidays only&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;12.67%&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;&lt;strong&gt;4.89%&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;hhyurdagul.com&#x2F;projects&#x2F;electricity-forecasting&#x2F;assets&#x2F;backtest-daily-mae.png&quot; alt=&quot;Daily mean absolute error across the rolling evaluation, with Turkish public-holiday periods highlighted&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;The failure mode is visible rather than hidden: TimesFM’s largest errors
coincide with public holidays, particularly Eid al-Adha.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The result is useful precisely because it is not a universal win. On ordinary
days, the zero-shot model beat the EPİAŞ baseline: &lt;strong&gt;2.39% versus 2.92% MAPE&lt;&#x2F;strong&gt;.
During public holidays, the ranking reversed sharply: &lt;strong&gt;12.67% versus 4.89%&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;That gap is explainable. A purely historical model can learn daily and weekly
demand rhythms, but it cannot know that a national holiday will abruptly change
them. At the 168-hour horizon, the effect can also persist after a holiday
because the depressed demand remains inside the context window.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-this-project-matters&quot;&gt;Why This Project Matters&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;It tests a foundation model against a meaningful operational baseline rather
than an artificially weak benchmark.&lt;&#x2F;li&gt;
&lt;li&gt;Its rolling evaluation uses multiple issue dates, two horizons, and
prediction-time-available information.&lt;&#x2F;li&gt;
&lt;li&gt;It joins data ingestion, model inference, reproducible evaluation, and
domain-facing analysis in one application.&lt;&#x2F;li&gt;
&lt;li&gt;Its main failure produced a concrete conclusion: calendar awareness is the
highest-value next modeling improvement, not a larger univariate model.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Earlier experiments included ARIMA, gradient boosting, and custom PyTorch
models. The completed system reflects the engineering decision that followed:
use the zero-shot model where it is competitive, measure it honestly against
EPİAŞ, and make the remaining limitation explicit.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Teus — Forecasting Flash Floods Before They Happen</title>
        <published>2024-09-21T00:00:00+00:00</published>
        <updated>2024-09-21T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hhyurdagul.com/projects/teus/"/>
        <id>https://hhyurdagul.com/projects/teus/</id>
        
        <content type="html" xml:base="https://hhyurdagul.com/projects/teus/">&lt;p&gt;I led Teus’s R&amp;amp;D and analytics from raw station data through event-based
evaluation and model-serving design. The analytics phase is complete; the
project is now with the software team for application development. I continue to
coordinate the technical handoff with the hydrologists who validate flood
definitions, station behavior, rainfall weighting, and every model considered
for operational use.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;72 h forecast horizon&lt;&#x2F;strong&gt; · &lt;strong&gt;3 regions&lt;&#x2F;strong&gt; · &lt;strong&gt;8 stations (5 Shown)&lt;&#x2F;strong&gt; ·
&lt;strong&gt;Hydrologist-validated flood events&lt;&#x2F;strong&gt; · &lt;strong&gt;Analytics complete&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;hhyurdagul.com&#x2F;projects&#x2F;teus&#x2F;assets&#x2F;d22a114-flood-forecast.png&quot; alt=&quot;Selected 24-hour flood-event forecast at station D22A114&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Selected validated event, July 4, 2023, D22A114. Discharge rose from
approximately 5 m³&#x2F;s to 72 m³&#x2F;s in four hours. The model matched the peak
magnitude closely and reached it within an hour; this event’s R² was 0.95 and
flood-window error was approximately 10%.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The charts retain their original Turkish dashboard labels because the system’s
users and data are Turkish: &lt;strong&gt;Debi&lt;&#x2F;strong&gt; = discharge, &lt;strong&gt;Yağış&lt;&#x2F;strong&gt; = rainfall,
&lt;strong&gt;Taşkın&lt;&#x2F;strong&gt; = flood, &lt;strong&gt;Değer&lt;&#x2F;strong&gt; = value, &lt;strong&gt;Tarih&lt;&#x2F;strong&gt; = date.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;why-early-warning-matters&quot;&gt;Why Early Warning Matters&lt;&#x2F;h2&gt;
&lt;p&gt;Flood forecasting is not an abstract benchmark. The World Meteorological
Organization reports that weather-, climate-, and water-related disasters caused
more than two million deaths and US$4.3 trillion in economic losses between 1970
and 2021; countries with limited-to-moderate early-warning coverage have a
disaster-mortality ratio nearly six times higher than countries with substantial
coverage.
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;public.wmo.int&#x2F;site&#x2F;science-action&#x2F;weather-forecasts-and-early-warnings&quot;&gt;WMO: Weather forecasts and early warnings&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Türkiye has recent evidence of that risk. AFAD reported &lt;strong&gt;82 deaths&lt;&#x2F;strong&gt; after the
August 2021 floods in Bartın, Kastamonu, and Sinop.
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.afad.gov.tr&#x2F;bartin-kastamonu-ve-sinopta-meydana-gelen-yagislar-hakkinda---1-9-1800&quot;&gt;AFAD: Western Black Sea flood report&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Teus is designed as decision support within that human system: a model can
surface an early signal, but hydrologists decide whether its behavior is
credible enough to inform an operational workflow.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-modeling-problem&quot;&gt;The Modeling Problem&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;hhyurdagul.com&#x2F;projects&#x2F;teus&#x2F;assets&#x2F;d22a114-overview.png&quot; alt=&quot;Five years of discharge and rainfall at D22A114, with hydrologist-validated flood events marked in red&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Flood events occupy roughly 1% of the studied hourly series. That rarity creates
three evaluation traps:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;A model that repeats normal river conditions can score well over the full
series while missing the events that matter.&lt;&#x2F;li&gt;
&lt;li&gt;Flashy basins can move from low baseflow to a severe peak within hours, so
discharge history alone provides little warning.&lt;&#x2F;li&gt;
&lt;li&gt;Random train&#x2F;test splits leak event structure through time, while
normalization over the full series leaks future information.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Ordinary MAPE is also misleading when discharge approaches zero: small absolute
errors become extreme percentages and dominate the average. Teus therefore uses
&lt;strong&gt;flood-window MAPE&lt;&#x2F;strong&gt; only during hours where discharge exceeds a
station-specific, hydrologist-validated event threshold. This preserves an
interpretable percentage error for the high-flow period without allowing quiet
months to overwhelm the result.&lt;&#x2F;p&gt;
&lt;p&gt;The hydrology team defines and validates station-specific floods against
official government values and domain knowledge. The evaluation does not infer
operational floods from a generic statistical cutoff.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;evaluation-that-matches-deployment&quot;&gt;Evaluation That Matches Deployment&lt;&#x2F;h2&gt;
&lt;p&gt;I built the backtest protocol before comparing architectures:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Hydrologists validate flood events and station thresholds using official
values.&lt;&#x2F;li&gt;
&lt;li&gt;Non-overlapping event windows are evaluated in time order with an expanding
training window.&lt;&#x2F;li&gt;
&lt;li&gt;Every forecast is produced by a model that has not seen the event’s future;
normalization is fitted on training rows only and boundaries are purged.&lt;&#x2F;li&gt;
&lt;li&gt;Models are scored with flood-window MAE and MAPE, plus a six-hour peak-window
MAPE that isolates the most operationally important period.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Rainfall is a first-class input. Basin gauges are weighted using contributions
supplied through hydrological studies, while the decoder receives a &lt;strong&gt;three-day
external rainfall forecast produced by meteorologists&lt;&#x2F;strong&gt;. That forecast is
available when Teus issues its discharge prediction—it is not subsequently
observed rainfall introduced during evaluation.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-controlled-architecture-comparison&quot;&gt;A Controlled Architecture Comparison&lt;&#x2F;h2&gt;
&lt;p&gt;The reported experiment compared five strategies under the same event windows,
features, and 24-hour and 72-hour horizons:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Model&lt;&#x2F;th&gt;&lt;th&gt;Forecast strategy&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Seq2Seq encoder–decoder RNN&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Encodes 168 hours of history, then generates the horizon while conditioning on the external rainfall forecast&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;MIMO LSTM &#x2F; MIMO MLP&lt;&#x2F;td&gt;&lt;td&gt;Predicts every horizon step in one operation&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Autoregressive LSTM &#x2F; MLP&lt;&#x2F;td&gt;&lt;td&gt;Predicts one step, feeds it back, and repeats&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;The table below contains &lt;strong&gt;selected validated-event case studies&lt;&#x2F;strong&gt;, each
compared with the strongest baseline on that same event. It illustrates
behavior; it is not presented as aggregate performance across every event.&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Station&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Selected-event Seq2Seq flood MAPE&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Same-event strongest baseline&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;D22A114&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;&lt;strong&gt;8.8%&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;86.4%&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;D13A074&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;&lt;strong&gt;8.2%&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;38.5%&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;D08A115&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;&lt;strong&gt;22.5%&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;65.2%&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;D22A082&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;&lt;strong&gt;22.5%&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;53.7%&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;D08A084&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;&lt;strong&gt;34.7%&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;88.8%&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;The selected cases expose a consistent architectural difference. MIMO models
tended to smooth sharp peaks, while autoregressive models accumulated error
across long horizons. Seq2Seq could generate onset, peak, and recession while
conditioning each future step on the meteorologist’s rainfall sequence.&lt;&#x2F;p&gt;
&lt;p&gt;Two implementation choices were especially important:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Scheduled sampling:&lt;&#x2F;strong&gt; the decoder gradually trains on its own outputs
instead of seeing only ground-truth histories, reducing drift over 72
generated steps.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Forecast rainfall in the decoder:&lt;&#x2F;strong&gt; the architecture matches the operational
information flow—past river and rainfall observations establish the basin
state, then an available rainfall forecast informs the generated discharge
path.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;selected-72-hour-case&quot;&gt;Selected 72-Hour Case&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;hhyurdagul.com&#x2F;projects&#x2F;teus&#x2F;assets&#x2F;d22a082-h72-flood.png&quot; alt=&quot;Selected 72-hour forecast of the August 2020 flood event at D22A082&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Selected validated event, August 2020, D22A082. After two quiet days, observed
discharge rose from approximately 20 to 141 m³&#x2F;s. The 72-hour forecast
identified the event day and recession shape but overshot the peak at
approximately 177 m³&#x2F;s. That is useful evidence for hydrologist review, not
proof of aggregate system accuracy.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;failure-analysis&quot;&gt;Failure Analysis&lt;&#x2F;h2&gt;
&lt;p&gt;The system’s weakest selected case came from D08A084, a small, flashy basin with
low baseflow and limited rainfall lead-in.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;hhyurdagul.com&#x2F;projects&#x2F;teus&#x2F;assets&#x2F;d08a084-hard-event.png&quot; alt=&quot;Selected D08A084 failure case where the event timing was detected but the peak magnitude was underpredicted&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Selected validated event, April 2021. The model identified the timing but
predicted approximately 5 m³&#x2F;s against an observed peak near 20 m³&#x2F;s.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The failure is technically informative: relative error becomes unstable near
zero, the basin has few historical events, and the available inputs do not fully
represent antecedent soil moisture. These findings motivated research into
pooled multi-station training and richer basin-state covariates, while the
application work proceeds with the completed analytics.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;from-analytics-to-a-human-approved-product&quot;&gt;From Analytics to a Human-Approved Product&lt;&#x2F;h2&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;mermaid&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;flowchart TB&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    RAW[&amp;quot;Station discharge + rain gauges&amp;quot;] --&amp;gt; PREP[&amp;quot;Continuous hourly data&amp;lt;br&#x2F;&amp;gt;and basin-weighted rainfall&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    PREP --&amp;gt; EVENTS[&amp;quot;Hydrologist-validated&amp;lt;br&#x2F;&amp;gt;flood events&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    EVENTS --&amp;gt; BACKTEST[&amp;quot;Expanding-window&amp;lt;br&#x2F;&amp;gt;event backtests&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    BACKTEST --&amp;gt; RUNS[&amp;quot;Reproducible run artifacts&amp;lt;br&#x2F;&amp;gt;metrics · plots · models · manifests&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    RUNS --&amp;gt; CANDIDATE[&amp;quot;Candidate registry&amp;lt;br&#x2F;&amp;gt;station · horizon · input contract&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    CANDIDATE --&amp;gt; REVIEW[&amp;quot;Hydrologist review&amp;lt;br&#x2F;&amp;gt;event behavior + suitability&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    REVIEW --&amp;gt;|&amp;quot;approved&amp;quot;| CHAMPION[&amp;quot;Serving champion&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    REVIEW --&amp;gt;|&amp;quot;rejected&amp;quot;| RUNS&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    CHAMPION --&amp;gt; API[&amp;quot;FastAPI forecast service&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    API --&amp;gt; APP[&amp;quot;Turkish operational application&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Every run records its dataset fingerprint, parameters, environment, predictions,
metrics, plots, fitted model, and HTML report. The registry compares technically
valid candidates per station, horizon, and input contract. Rain-dependent
candidates are eligible only when the external rainfall forecast is supplied.&lt;&#x2F;p&gt;
&lt;p&gt;Technical validation does not deploy a model. It creates a candidate.
Hydrologists review its event behavior and operational suitability, and only an
explicitly approved checkpoint can become the serving champion. The FastAPI
layer discovers approved models at runtime and keeps the last working champion
available if a candidate is rejected or fails validation.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-this-project-demonstrates&quot;&gt;What This Project Demonstrates&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Evaluation design determines whether a rare-event model is useful.&lt;&#x2F;strong&gt;
Event-based, time-ordered backtests prevent normal hours from hiding flood
misses.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Inputs and architecture must reflect the real forecasting process.&lt;&#x2F;strong&gt; The
decoder consumes a meteorologist-produced rainfall forecast that is genuinely
available at inference time.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Selected successes and failures belong together.&lt;&#x2F;strong&gt; Both are necessary for
hydrologists to judge where a model is credible.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Human approval is a system boundary.&lt;&#x2F;strong&gt; Model ranking supports domain
experts; it does not replace their operational authority.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Research artifacts must survive the software handoff.&lt;&#x2F;strong&gt; Reproducible runs,
explicit input contracts, and approved checkpoints allow the application team
to build on completed analytics without turning a notebook result into an
opaque service.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
</feed>
