fix: 护栏拒绝时保留原始转写,不再输出空串 - #97
Merged
Merged
Conversation
The deferred instant-insert path calls process(allowsGuardFallback: false), and a guard rejection then returned an empty string, so the background Smart Format was marked failed even though the dictation was valid. Guard rejections are reachable in normal use via protected_token_change, excessive_deletion, excessive_expansion and content_drift. rejectedOutputFallback now always returns the prepared source transcript. The rejected candidate is still discarded, so no hallucinated content can enter, and the source equals the text already inserted by instant insert, so the deferred replacement is content-preserving. Guard heuristics and their decisions are unchanged; the rejection log now records the reason and both lengths. Co-authored-by: multica-agent <github@multica.ai>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
背景
TextProcessor.process在TranscriptFidelityGuard.violation(...)命中时调用rejectedOutputFallback(cleanedText, allowsGuardFallback:);当allowsGuardFallback == false时原实现返回空串(TextProcessor+Output.swift:95-100)。可达性确认
可达。 唯一传
allowsGuardFallback: false的调用点是延迟智能整理路径VoicePipeline+Replacement.swift:234-236(即时插入后后台重排)。该路径先通过immediateInsertText插入了prepareForFormatting(raw)的结果,再由后台 LLM 重排;fidelityPolicy默认为.faithfulCorrection,护栏启用完整语义校验。以下拒绝原因在正常使用中都能触发(测试逐条复现):excessive_deletionexcessive_expansionprotected_token_changecontent_drift原行为:
process返回""→finishDeferredSmartFormat的guard !formattedText.isEmpty判定为失败,标记pipeline.formatting_failed,用户看到「整理失败」。转写本身完好,但结果被整段清空/判失败。改动
Sources/Processing/TextProcessor+Output.swift:rejectedOutputFallback不再返回空串,恒定返回cleanedText(已做词典替换与规范化的原始转写)。cleanedText与即时插入的quickText同为prepareForFormatting(raw),因此延迟替换是内容保持的(把同一段文字标记为已整理,而不是清空)。allowsGuardFallback参数保留,用于表达调用点意图;文档注明它不再抑制来源回退。TranscriptFidelityGuard的所有启发式与判定完全未改。仅把拒绝日志从单行扩展为记录原因 + source/candidate 字数(只做记录)。allowsPreparedFallback处理。测试
Tests/OpenTypeTests/TextProcessorFallbackTests.swift:testRejectedOutputFallbackRespectsPreparedFallbackPolicy(断言 false → 空串)按新语义改写为testRejectedOutputFallbackAlwaysKeepsSourceTranscript。excessive_deletion、protected_token_change、excessive_expansion三种护栏拒绝下,allowsGuardFallback: false的输出非空、等于来源转写、且不含被拒候选的内容(不引入幻觉)。结果:
swift build→Build complete! (3.72 secs)swift test --filter 'TextProcessorFallbackTests'→ 14 passed / 0 failuresswift test --filter 'Processing|Prompt|Fidelity|Sanitizer|Dictionary|Lexicon|Text|Translation|QualityProbe|Guard|Output|Replacement'→ 327 passed / 2 skipped / 0 failures范围
仅 3 个文件;未改护栏判定、未改阈值、未改其它回退语义。