AI Portfolio Lab Tools Games Blog Feedback
All Posts

My AI Hint Sometime Gave Away the Secret Word

I built a browser party game with local ML hints. The model worked perfectly. It just didn't understand what it was supposed to be hinting at.

2 min read
gamesaibrowsermachine-learningside-projects

My party game had one design problem: the AI kept spoiling its own secret.

The game is called Impostr. Pass the phone around a table, each player taps to see a secret word. Everyone gets the same one, except one person, who sees ”???” and has to fake it. Give clues, vote, catch the liar.

Simple social deduction. The kind of thing you explain in thirty seconds and play for an hour. I built it for the /games section of my site because I wanted a real use case for browser-native embeddings.

The mechanic I had in mind: a hint mode where the game shows each player a subtle semantic clue when they get stuck. Not the word itself. Something close. If the secret word is “piano,” a good hint is “keyboard” or maybe “recital.” Not “piano” obviously. Not “instrument” either. That feels too broad, gives the imposter too much cover. Right in the sweet spot between useful and free.

I loaded a quantized all-MiniLM-L6-v2 via Transformers.js and had it pull the nearest neighbors to the secret word from the word bank. Fast, private, no API calls. First test: worked great. Second test: worked great. Third test: the secret word was “cactus” and the hint it surfaced was “cacti.”

The model has no concept of spoiling the bit. It does cosine similarity and returns whatever is closest. “Cacti” is extremely close to “cactus.” They’re the same word in different clothes. The model is correct. The game is broken.

The fix was a single filter: drop any candidate that appears inside the secret word, or that contains the secret word as a substring. Four lines of JavaScript. The simplicity felt almost embarrassing, but it crystallized something I keep bumping into with local ML. The model has genuine capability, real semantic understanding, and absolutely zero awareness of the game it’s playing.

It knows “cacti” is near “cactus.” It doesn’t know that’s the wrong option to provide as a hint.

That gap closes with a large hosted model. Tell Claude or GPT-4 “give me a hint but not the word itself” and it reasons about the social function of the request, not just the token proximity math. It gets the assignment.

With a tiny local model, you write that context as code. Every guardrail is explicit. Every edge case is a rule.

I’m not complaining. The model does what it was trained to do, fast and free, with nothing leaving the device. But if I told younger-me one thing about building with local ML: the model is a function. The behavior is yours to define.

If you’re getting weird output, it probably isn’t hallucinating. It’s doing exactly what you asked. Write a better ask.