← All work
Ditto · LLM systems

The Sentiment Loop

Getting a dating product to learn what someone actually wants from a conversation after the date, instead of a form they filled in at signup.

Role
Design + implementation
Scope
Full active user base
Surfaces
Chatbot · Matching
Stack
LLM agents · Classifier design · Evals
Primary signal source Chatbot skill design Safety escalation Shadow testing

The problem

Dating products know what people say they want, because they asked at signup. They are much worse at knowing what people actually respond to, because that evidence shows up after a date, in free text, at an unpredictable hour, from someone with no reason to fill out a form.

Ditto had that gap. Stated preferences went stale almost immediately, and the strongest signal available, which is how the date actually went, wasn't being collected at all.

Part one: a chatbot that asks well

I designed and shipped the post-date feedback system as a chatbot skill. Conversation was the right surface for a specific reason. A star rating gives you a number with nothing attached to it, but a short exchange tells you which part of the date the number is about, and gives people room to bring up things you didn't know to ask.

A 24-hour response window

Feedback goes stale fast. Ask too early and you get adrenaline, ask too late and you get a reconstruction. Bounding it to 24 hours also made the data much easier to work with, because every response ties to one specific date instead of to a vague stretch of time. That is what makes it usable downstream.

Safety escalation, built first

If you invite people to describe how a date went, some of what you get back isn't preference data. That path can't be a classification bucket that gets aggregated with everything else. It has to leave the automated loop immediately and reach a person. I built the escalation route before the normal path, and I would do it in that order again.

Where it ended up

The feedback loop is now the primary signal source for the sentiment system, rather than one input among several.

Part two: the sentiment-flagging system

That signal feeds a production sentiment-flagging system I designed and shipped, which now scores the full active user base.

Per-surface scores, not one blended number

The default design would have been a single sentiment score per user. I argued for separate scores per surface instead, so how someone reads in the chatbot is tracked apart from how they read in matching.

One number would have been simpler and misleading. The two surfaces are watching different things. Chatbot sentiment is what a user says directly, knowing they are being asked. Matching sentiment is inferred from behavior, when they aren't. Average those together and you get a number that doesn't describe anything real. Someone can be enthusiastic in conversation and completely disengaged in the product, and that mismatch is the most useful thing you could know about them. A blended score deletes it.

Splitting them also made the system debuggable. When a score looks wrong you can tell which surface produced it, instead of starting every investigation by trying to un-mix an average.

Results

100%Of the active user base scored in production
PrimarySignal source for the sentiment system
2Independent per-surface scores
← Three-Tier Match Priority Next: The Yearbook →