Context
Options considered
Decision
Trade-offs
Revisit trigger
Takeaways
Push cheap filtering to the edge; reserve the expensive path for traffic that deserves it.
Crude-but-instant often beats correct-but-costly for a first-line guard, as long as a real backstop (rate limit) sits behind it.
Don't spend a model call to decide whether to spend a model call.
Full write-up
Why a filter at all
An open chat box on a public site gets used as a free LLM. Each off-topic message costs tokens and burns the rate limit meant to stop abuse. The cheapest possible defense is to never send the request in the first place.
Why keywords, not a classifier
A server-side classifier would be more accurate, but it means a model call to decide whether to make a model call. A keyword check in the browser is free and instant. It's crude, so it sits in front of, not instead of, the server rate limit and input validation that are the actual backstop.