· Marc Morel · Architecture · 5 min read

10,000 mobile app reviews: how a decision model and an LLM split the work

A decision model classifies 10,000 mobile app reviews for cents, an LLM writes only the synthesis, and self-hosted Laya keeps the data inside the company.

System One decision models (Laya, KEV, Décider, typesafe ai) and LLMs (Claude, OpenAI, Mistral, Gemini) exchanging work

The case: Ten thousands free-form comments on a mobile app (store reviews, in-app feedback, surveys):

Since the last update I can’t log in with Face ID, I have to re-enter my passcode every time. And the instant transfer to my sister took 2 hours.

The questions are always the same: what do customers talk about, how do they feel, what changed since the last release, and what can’t wait for a monthly report?

The default is one LLM call per comment ending in “return JSON”. At 10,000+ comments that is slow, costly and fragile:

  • The output is generated text, not a guaranteed answer: the same comment can come back as clean JSON, JSON behind a preamble, or a category nobody declared. Every call needs parsing, validation and a retry path.
  • Categories drift with every prompt edit, and pasted IBANs go to the provider.

Split the work

A decision model (a System One model: Jev, or open alternatives such as Decider, Kev and Laya) takes a text and typed questions: a Choice among your options, a Score on your scale, a Noul (the probability a statement is true). It returns values with calibrated probabilities, not prose to parse.

StepDone by
Draft the taxonomy from a redacted sample of ~300 commentsLLM, then ratified by product and customer relations
Classify all 10,000 commentsDecision model
Escalate fraud reports, aggregate trends per releaseCode
Explain what moved, with redacted quotesLLM, a few dozen comments per topic
Propose new topics from the other bucket after each releaseLLM

The LLM runs a few hundred times, only where writing is the job.

One call, eight questions

Each comment gets one call with eight questions, answered in parallel:

  • topic: a Choice over ten versioned categories (login and authentication, app stability, transfers, cards, account opening, fees, support, savings, features, other);
  • sentiment: a Score;
  • six Nouls: actionable, churn_risk, fraud_or_scam, complaint, contains_personal_data, is_spam.

Extra questions add almost no latency and cost only their own tokens.

For the quoted review, the answers are: topic = login_auth, with part of the probability on transfers; very negative sentiment; actionable; no fraud. It really is about both.

Then code, never the model, applies policy and counts:

  • Escalate what can’t wait. fraud_or_scam ≥ 0.5 goes to the fraud team the same day. The low threshold is deliberate: a missed fraud report is the expensive error. Whether in-app complaints enter the formal complaint process is decided by compliance, not the model.
  • Trend by release. Summing probabilities gives expected counts with uncertainty bands, instead of hard labels. The report can say: “login_auth rose from 6% to 19% of comments on 5.12.0, iOS only.” That is a release-regression signal.
  • Keep personal data away from the LLM. Comments flagged contains_personal_data are redacted before the LLM writes any synthesis.

The gains over one LLM call per comment

  • Cost. About 5M input tokens at Jev’s $0.042/M, with output free, comes to about $0.20. A frontier LLM costs tens of dollars for the same volume (illustrative prices). At that ratio, re-running after every release, or re-classifying the whole history when the taxonomy changes, is a non-decision.
  • Speed. Vendor-reported latency is 70 to 500 ms per call, so the full set runs in minutes and the pipeline can process the live stream. Verify under load.
  • No parsing. Answers can only be your declared options, your scale, or a probability: no invented category, no preamble, no malformed JSON, no retry loop. The validation layer that wraps every LLM call disappears, and so do its failures at 10,000 calls. An LLM’s structured-output mode fixes the shape of the answer, but not the value: a valid label can still change from one run to the next. Here the question itself sets what the answer can be.
  • Stable categories. With versioned criteria and a pinned model version, “before and after 5.12” is a fair comparison.
  • Arithmetic on probabilities. Expected counts, noise-aware alerts, per-risk thresholds and review queues all come from the same numbers. Check calibration on a labelled sample first.

Privacy: Laya, self-hosted

Mobile app comments might contain very private and sensitive information (health, financial, etc.). Sending them to a hosted API outside the EU raises GDPR transfer.

Laya (Convai Innovations, Apache 2.0) answers them. It has a multilingual checkpoint, runs on infrastructure you control, and serves the same /v1/systemone wire format as Jev. Point the SDK’s base URL at laya-serve, set model="multilingual", and no comment leaves the company. Open weights also settle the DORA exit strategy.

Before trusting it:

  • Keep options short. A question’s option descriptions share a 192-token budget. Past about 20 categories, go two-level.
  • Chunk long survey verbatims.
  • Re-calibrate thresholds, starting with fraud.

The LLM steps only ever see a few hundred redacted comments, and can run on a model hosted inside the company if policy requires.

What changes

Customer feedback analysis is one small judgment repeated thousands of times, plus a little synthesis. Give the repetition to a decision model: fast, cheap, stable, and able to spot the fraud report hidden in a one-star review.

Give the synthesis to the LLM. When the customers are a regulated company’s, run the decision model on Laya, without changing a line of classification code.

Share:
Back