跪拜 Guibai
← All articles
AI Programming

A Calorie-Counting HarmonyOS App That Keeps the LLM on a Short Leash

By 一只牛博 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

The architecture draws a hard line between what an LLM should do (fuzzy estimation) and what deterministic code should own (summation, state, and safety checks). The fallback mode is a practical pattern for mobile apps that must degrade gracefully when the model endpoint is down, and the prompt-enforced refusal to log dangerous diet plans shows a lightweight safety guard that costs nothing to implement.

Summary

A personal HarmonyOS app called "Slim & Beautiful" logs weight, meals, and exercise from natural-language input. A local Python gateway sends user text to Lanyun's hosted DeepSeek-V3.2, which returns structured JSON with estimated calories and actions. The gateway then writes the journal file, aggregates daily intake against a 1650 kcal budget, and computes trends — all in deterministic code, never trusting the model with arithmetic. The API key lives only in the gateway's environment variables, so the ArkTS client code contains no secrets and can be shared freely. When the model is unavailable, a regex fallback still logs weight but refuses to guess meal calories, explicitly telling the user what it cannot do. A prompt-level rule blocks logging for extreme dieting requests, generating only a dissuasion reply with no data side effects. The developer also hit and fixed an ArkUI @Builder pass-by-value pitfall that caused stale data on the daily report tab.

Takeaways
DeepSeek-V3.2 on Lanyun returned TTFT between 174–194 ms and a 97.9% cache hit rate on repeated large contexts in the developer's own curl benchmarks.
The model name must include the /maas/ prefix (e.g., /maas/deepseek-ai/DeepSeek-V3.2); using deepseek-chat returns a 404.
Lanyun's base URL already contains /v1, so appending /v1/chat/completions creates a double path and a 405 error.
The API key is stored only in the gateway's environment variables; the ArkTS client talks to 127.0.0.1:18090 and never touches the key.
The LLM outputs structured JSON with actions (log_weight, log_meal, log_exercise) and a reply string; all calorie summation and budget math runs in Python on the gateway.
A prompt rule instructs the model to generate no logging actions for extreme dieting requests, only a dissuasion reply.
When the model is unreachable, a regex fallback still logs weight entries but refuses to estimate meal calories, telling the user exactly what failed.
ArkUI @Builder parameters are pass-by-value snapshots; updating @State does not refresh a Builder that received the value as a parameter, causing stale UI on the daily report tab.
At Lanyun's pricing of 2 RMB per million input tokens, a day of check-in calls costs under one cent.
Conclusions

Offloading calorie estimation to an LLM while keeping summation in code is a clean separation of concerns: the model handles ambiguity, and the code guarantees arithmetic correctness.

The fallback design is honest in a way many AI features are not — it explicitly tells the user which capability is missing instead of silently failing or hallucinating a number.

Using prompt engineering as a safety guard (refusing to log extreme dieting) is effective for a personal app but would need stronger enforcement in a multi-tenant or regulated context.

The @Builder pass-by-value behavior is a subtle ArkUI footgun that can produce half-live, half-stale UIs; the fix of reading state directly in the tab is simple once diagnosed.

Concepts & terms
TTFT
Time To First Token — the latency between sending a request to an LLM and receiving the first token of the response. A tight TTFT range indicates consistent, low-latency model serving.
ArkUI @Builder
A HarmonyOS UI framework decorator for constructing reusable UI components. Parameters passed to an @Builder function are captured by value at build time, not by reference, so subsequent state changes do not propagate into the already-built component.
MaaS
Model as a Service — a cloud platform that hosts large language models and exposes them via API, handling inference, scaling, and billing so developers only call the endpoint.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗