Testing and release evidence

Diagnose Garbled On-Device AI Output

Check artifact integrity, tokenizer, prompt template, parser, encoding, and runtime identity in a fixed order.

Review status: Fact and editorial QA complete; owner review pending · 2026-10-04 · Fact IDs: COVE-MODEL-02, BENCHMARK-01

Direct answer

Garbled output is a symptom at a boundary, not a diagnosis of model quality. Compare the earliest observable representation with the next one: native/runtime output, the application string or stream event, assembled final text, parser result, and rendered UI. If text is exposed as Kotlin or Java String values, investigate event ordering, duplicate collection, truncation, normalization, and UI state before assuming a byte-decoding error. If a native bridge returns bytes, record the documented encoding and decode incrementally or at a complete-message boundary; decoding each arbitrary chunk independently can split a multibyte character. Use a fixed fixture containing ASCII, accented characters, CJK, emoji, punctuation, and line breaks. Preserve the expected source and compare code points or escaped output at each boundary. Do not log private prompts or answers in production; synthetic fixtures can reproduce encoding behavior without storing user content. Test both a complete response and streamed chunks, including chunks that end in the middle of a multibyte sequence if that is possible in the transport. An incomplete final output, a repeated chunk, a parser dropping fields, and visible mojibake are separate categories. The model artifact, tokenizer, and template still matter, but do not change them first. If the raw runtime result is already unexpected text, verify exact artifact identity and conversation formatting in separate tests. If the runtime result is correct but the UI shows broken characters, inspect conversion and rendering. If the raw output contains correct characters but duplicated or missing spans, inspect collector lifecycle, buffer append logic, cancellation, and finalization. Keep output token generation separate from text decoding so a fix in one layer does not conceal a defect in another. Apply Unicode normalization only when the product has a documented reason and tests for the expected equivalence; normalization can alter code-point sequences even when the displayed glyph appears similar. Do not strip combining marks or punctuation as a generic “cleanup.” Check that string slicing uses appropriate boundaries and that byte buffers are not interpreted using platform defaults when an explicit charset is required. For JNI, use the documented string conversion path and avoid treating modified UTF-8 as interchangeable with arbitrary UTF-8 data. Record the stage, payload type, encoding contract, stream sequence number, app/runtime version, and fixed fixture ID. If the API does not expose native bytes, say so. The result should be a reproducible boundary where text first differs, plus a regression fixture. Do not report a model correction, language-support claim, or performance number unless separate evidence supports it.

Chinese characters become replacement symbols only in the final screen

A local model response appears correct in a test log, but the production UI sometimes displays replacement glyphs and occasionally duplicates the last words. The response is streamed through a native bridge and collected by a screen-level observer.

Decision

Compare synthetic Unicode output at each observable boundary, preserve stream order and finalization data, and investigate byte decoding only if the bridge actually exposes bytes.

Expected outcome

The team can attribute the symptom to transport, collector, parser, or UI rendering and add a regression case without retaining user conversation content.

Evidence to collect

The claim becomes reviewable only when the following evidence is attached to the same artifact and test run:

  • Configuration manifest
  • Known input-output fixtures
  • Stage-level diagnostics

A release claim is valid only for the recorded configuration and acceptance set. Generalization requires additional records.

Implementation workflow

  1. Classify what “garbled” means. Create separate labels for replacement glyphs, wrong characters, duplicated spans, missing chunks, broken line breaks, and parser-field loss. Save a screenshot or escaped synthetic output, but do not treat the symptom name as the root cause.
  2. Build a Unicode boundary fixture. Use fixed synthetic text with ASCII, diacritics, CJK, emoji, punctuation, and newlines. Define expected string and code-point properties; add a stream case whose chunks can split at known transport boundaries.
  3. Compare runtime, app, parser, and UI representations. Capture each safe observable output in order, plus event ID and sequence. If the runtime gives strings, inspect collector duplication and string transformations. If it gives bytes, confirm the documented encoding and decode at safe boundaries.
  4. Isolate chunking, normalization, or lifecycle defects. Replay complete and streamed responses, cancel and restart observation, recreate the screen, and verify that each event is appended once. Test normalization and substring operations separately; do not remove combining marks or punctuation as a blanket repair.
  5. Add a regression and protect diagnostics. Keep the synthetic fixture in tests, assert exact expected transformations at the failing layer, and store only stage metadata for production incidents. Do not include real prompts, output text, or private identifiers in routine logs.

Keep each transition observable. A failure should identify the stage, artifact, runtime, and recovery action without logging private user content.

Acceptance criteria

  • The failure is categorized as byte/character decoding, stream ordering, transformation, parser, or rendering rather than “model quality” by default.
  • A synthetic Unicode fixture covers complete and streamed responses and asserts the first boundary that changes.
  • Encoding is explicit when bytes cross a native boundary; string events are not re-decoded as arbitrary bytes.
  • Production diagnostics do not retain user prompts or generated text solely to investigate text rendering.

Decision table

DimensionChoice or evidenceHow to interpret it
Mojibake/replacement charactersInspect byte-to-string contract and decode boundaryRelevant when bytes are exposed; not applicable when each layer already carries a valid string.
Duplicate or missing stream spansInspect event sequence, collector lifetime, append and finalization logicOften an application stream-state symptom, distinct from Unicode decoding.
Correct raw output but broken UICompare parser model and rendered string transformationsPlaces the first change after runtime output; model changes are not the first fix.

Failure patterns to prevent

  • Changing several variables together
  • Calling corruption low model quality

Also prevent silent fallback, unpinned artifacts, missing cancellation, and conclusions that combine unlike configurations. Store unsuccessful runs alongside successful ones.

Minimum reproducibility record

LayerRecord
DeviceManufacturer, model, chipset, RAM class, operating-system build
SoftwareApplication version and git commit
ModelFamily, variant, revision, format, file length, hash, quantization
RuntimeName, revision, requested backend, observed backend evidence
WorkloadFixture revision, input hash, prompt hash, output policy
OutcomeCompleted, failed, cancelled, fallback, and privacy-safe diagnostics

Release checklist

  • ☐ The primary query is answered without an unsupported number.
  • ☐ Every artifact and runtime is pinned.
  • ☐ The representative task and failure policy are explicit.
  • ☐ Lifecycle, cancellation, cleanup, and fallback are tested.
  • ☐ User-content and network boundaries are documented.
  • ☐ Result wording applies only to the recorded configuration.
  • ☐ The page links to raw method or evidence when results are added.

Sources and related evidence

Chinese deployment and troubleshooting content is organized in the .奇连 AI 端侧专题.

Frequently asked questions

Should I decode each model stream chunk as UTF-8 separately?

Only if the transport contract guarantees chunks end on valid character boundaries. A multibyte character may span chunks; use a documented incremental decoder or assemble bytes before decoding.

Does mojibake mean the tokenizer is wrong?

Not necessarily. It can occur during bridge conversion, chunk assembly, parsing, or UI rendering. Compare the earliest observable output before changing tokenizer or model configuration.

Can I remove all unusual punctuation to make output readable?

Avoid blanket cleanup. Punctuation and combining marks may be meaningful. Identify the exact transformation boundary and add a fixture for the affected characters before changing normalization.