ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

LifeOS 发音覆盖系统实战指南:用 PRONUNCIATIONS.json 让数字助理把每个词读对

LifeOS 发音覆盖系统实战指南:用 PRONUNCIATIONS.json 让数字助理把每个词读对 LifeOS 发音覆盖系统实战指南用 PRONUNCIATIONS.json 让数字助理把每个词读对【免费下载链接】LifeOS⛰️ The Life Operating System — an intent engineering platform that moves you from your current state to your ideal state, in life and work.项目地址: https://gitcode.com/GitHub_Trending/pe/LifeOS导读本文讲解 LifeOS 内置的 TTS 发音覆盖Pronunciation Overrides机制它通过一份扁平化的PRONUNCIDATIONS.json映射表精确控制 ElevenLabs 语音合成对姓名、专业术语、缩写等词汇的读音同时配套一份仅供人类阅读的PRONUNCIATIONS.md笔记文件用于记录为什么要有这条覆盖。读完本文你将掌握这套双层配置的设计意图、JSON 词条的编写规则与字面匹配陷阱、它在语音合成管线中的底层执行逻辑正则编译、同形异义词消歧、词边界锚定以及如何通过/interview工作流系统化地采集和维护发音词条。一、职责边界为什么要有两个 Pronunciations 文件在 LifeOS 的用户目录中存在一对配套文件LifeOS/install/USER/PRINCIPAL/PRONUNCIATIONS.md —— 人类笔记解释每条覆盖存在的原因LifeOS/install/USER/PRINCIPAL/PRONUNCIATIONS.json —— 机器读取TTS 语音层实际消费的事实来源。PRONUNCIATIONS.md开头用一段引用块把这条边界讲得很清楚The voice layer does NOT read this file.It reads the siblingPRONUNCIATIONS.json, a flattext: spoken formmap. This markdown file is for your own notes onwhyan override exists; every entry you actually want spoken must also exist in the.json.也就是说Markdown 文件里写了什么不会对语音输出产生任何影响你真正想让助理读对的每个词条都必须同步写进 JSON。这一设计把说明文档与机器配置分离Markdown 用于维护者可读的备注与追溯JSON 用于程序的高效解析。PRONUNCIATIONS.json文件头部的_comment字段也明确标注了同样的信息并提示Delete these examples and add your own删除示例、填入你自己的词条。二、核心配置格式扁平映射表Flat MapPRONUNCIATIONS.json是一个扁平的原文 → 口语形式映射{ _comment: Pronunciation overrides for the TTS layer. Flat map: exact text to match - how it should be spoken. Matching is literal, so add each inflection you actually say (is live, went live). The VoiceServer reads THIS file (LIFEOS/USER/PRINCIPAL/PRONUNCIATIONS.json); the sibling PRONUNCIATIONS.md is human notes only. Delete these examples and add your own., LifeOS: LIFE-ohess, is live: is lyve, went live: went lyve }三个示例词条恰好覆盖了三种典型场景词条匹配文本口语形式发音场景说明LifeOSLIFE-ohess产品名默认 TTS 可能读成Life-Oh-Es逐字母拼读需要固化为一个整体读音is liveis lyve短语级词条live读作 /laɪv/广播/上线语义went livewent lyve同一单词的另一种屈折变体需要独立成条2.1 字面匹配必须补齐每个实际说出口的屈折形式JSON 的_comment和 Markdown 文档都反复强调同一条规则匹配是字面的literal。TTS 输入文本中的词条必须与 JSON 键逐字符完全一致才会命中因此不要只写基础词形而是要把你实际会说的每种变化都补上只写live: lyve并不能保证is live、went live被正确改写文档给出的原话是 add each inflection you really say (is live,went live), not just the base word即按真实口语输入补齐变体。这也是为什么示例 JSON 里同时存在is live与went live两条——它们分别对应现在时与过去时两种真实用法。三、源码级机制词条如何变成正则并作用于语音3.1 文件路径解析语音模块从固定位置读取发音文件。在 VoiceServer/voice.ts 的loadPronunciations中默认路径被解析为~/.claude/LIFEOS/USER/PRINCIPAL/PRONUNCIATIONS.json即用户主目录下.claude/LIFEOS/USER/PRINCIPAL/目录中的 JSON。该函数同时接受一个customPath参数允许通过VoiceConfig.pronunciations_path覆盖默认位置。若文件不存在会记录一条 warningTTS will use default pronunciations将使用默认发音若 JSON 解析失败则记录 error两种失败都不会让语音模块崩溃而是静默回退到默认读音。3.2 词条编译正则转义与词边界锚定每条 JSON 词条在加载时都会被编译成一个正则规则CompiledRule { regex, phonetic }。loadPronunciations中的核心逻辑如下pronunciationRules Object.entries(flat).map(([term, phonetic]) { // \b only exists next to a word char: a leading \b before . (.env) // or a trailing \b after . (Live.) never matches, silently killing // the rule. Anchor with \b only where the term boundary is a word char. const lead /^\w/.test(term) ? \\b : const tail /\w$/.test(term) ? \\b : return { regex: new RegExp(${lead}${escapeRegex(term)}${tail}, g), phonetic, } })这里有三个值得注意的实现细节正则转义词条会先经过escapeRegexvoice.ts#L165-L167把.*?^${}()|[]\等正则元字符全部转义因此词条中的标点、点号等都能被安全地当作普通文本匹配词边界条件锚定\b单词边界只在相邻字符是单词字符时才存在。源码注释特别举例词条若以.开头如.env或结尾是.直接加\b会永远匹配不到。因此实现里用/^\w/与/\w$/探测首尾字符仅在首尾是单词字符时才加\b锚定——这保证了PRONUNCIATIONS.json里可以安全地写入带点号的词条全局替换正则带g标志意味着同一词条在文本中多次出现会被全部替换。3.3 应用顺序与 TTS 管线集成替换动作在applyPronunciationsvoice.ts#L199-L205中完成按规则数组顺序逐条对文本做String.replace。真正发语音时generateSpeechvoice.ts#L322-L357在把文本交给 ElevenLabs API 之前会先做预处理const pronouncedText applyPronunciations(disambiguateHomographs(text)) if (pronouncedText ! text) { log(info, Voice pronunciation: ${text} - ${pronouncedText}) }可以看到完整的读音管线是同形异义词消歧homographs→ 自定义发音规则PRONUNCIATIONS.json→ 请求 ElevenLabs。如果改写后的文本与原文不同日志会记录Voice pronunciation: ... - ...方便排查词条是否命中。随后请求https://api.elevenlabs.io/v1/text-to-speech/{voiceId}模型固定为eleven_turbo_v2_5并携带voice_settings参数stability、similarity_boost、style、speed、use_speaker_boost。四、同形异义词消歧live问题的内建解法PRONUNCIATIONS.json里两条live词条并不是孤立的存在它与语音模块内置的 homographs.ts 消歧器形成互补。homographs.ts的注释解释了背景有些词拼写相同、词义不同读音就不同ElevenLabs 偶尔会猜错。最典型的例子是live动词义/lɪv/live freely、where you live是 ElevenLabs 的默认读法通常读得对广播/上线义/laɪv/the site is live、go live经常被误读成动词音。因此消歧器采用高精度上下文匹配而非全量替换——它内置了多组上下文正则homographs.ts#L31-L47只在明确的上线语境中把live改写为lyvego / goes / going / gonna go / went / stay / stays / staying live如 went liveis / are / am / was / were / be / been / its / now / then / currently live如 is livelive on 域名、live in production、live site/deploy/stream/...watch / stream / air / broadcast ... live连字符形式live-verified、live-tested等deploy/ship/push/launch/roll out ... live等动词搭配。disambiguateHomographshomographs.ts#L62-L73对每个上下文正则匹配到的片段只改写其中的live标记本身并通过matchCase保持原始大小写如 Live → Lyve。这样live freely这类动词义句子完全不受影响。这正好解释了为什么PRONUNCIATIONS.json的示例仍要写is live与went live两条词条homographs.ts的内建规则虽然覆盖了这两种语境但它是共享的、写死的用户自定义词条则用于内建规则覆盖不到、或你个人习惯的特殊读法两者是内置兜底 用户扩展的关系。voice.ts的调用顺序先disambiguateHomographs再applyPronunciations保证用户词条拥有最终决定权。五、词条采集用 /interview 工作流建立发音清单Markdown 文档明确给出了词条采集入口运行/interview让数字助理记录它必须读对的词汇或者直接手动编辑 JSON。这条指引对应着仓库中的实际实现Workflows/Interview.md 在第 2 步把 name, pronunciation, timezone, hometown 归入 Principal identity 采集范畴InterviewScan.ts 的采集提示包含Your name (with pronunciation if uncommon)?你的名字若不常见请附发音说明访谈流程会主动询问用户姓名的非常规读音身份层数据结构 identity.ts 中DEFAULT_PRINCIPAL与合并逻辑都带有pronunciation: string字段用户的发音偏好会随 Principal 身份一起持久化。此外仓库还提供了面向语音系统的结构化参考样例 pronunciations.reference.json其 entries 示例为{ key: Schmidt, value: shmit, notes: silent c, soft-t }, { key: LifeOS, value: P-A-I, notes: letters not pie }并带category: voice、kind: reference等元数据含 schemaVersion、pageId、sourceHashes 指向LIFEOS/USER/PRINCIPAL/PRONUNCIATIONS.json、adapterVersion 等说明发音词条已纳入 PULSE 的 Schema 数据模型可作为你设计自己词条表时的参考格式。六、配置生效、健康检查与验证6.1 启动加载与配置覆盖语音模块通过startVoice(config)初始化voice.ts#L623-L658先解析 ElevenLabs API Keyconfig →ELEVENLABS_API_KEY环境变量再调用loadPronunciations(config.pronunciations_path)加载发音规则随后加载 settings.json 中的声音配置。启动日志会输出pronunciationRules: N直接显示已加载的词条数量。VoiceConfig接口voice.ts#L25-L30定义如下export interface VoiceConfig { enabled: boolean elevenlabs_api_key?: string default_voice_id?: string pronunciations_path?: string }其中pronunciations_path即自定义发音文件路径default_voice_id用于指定默认声音未配置时回退到 ElevenLabs 预置声音 Rachel。6.2 健康检查接口语音模块暴露GET /voice/health路由voice.ts#L713-L715voiceHealth()voice.ts#L663-L674返回的字段中包含pronunciation_rules: pronunciationRules.length可直接确认词条是否成功加载。一个典型响应包含initialized、enabled、voice_system: ElevenLabs、default_voice_id、api_key_configured、pronunciation_rules、configured_voices、desktop_notifications。注意该模块不创建自己的 HTTP 服务而是由父进程 pulse 在匹配路由上调用handleVoiceRequest()见 voice.ts#L700-L811。POST 路由/notify、/notify/personality、/voice受 60 秒窗口内 10 次的速率限制。七、最佳实践维护一套可靠的发音词表综合文档规则与源码实现整理出如下实践清单JSON 是唯一事实来源任何你想让 TTS 读对的词条必须写入PRONUNCIATIONS.json仅在PRONUNCIATIONS.md记录为什么来源、语境、特殊说明二者保持同步按真实口语补齐变体字面匹配意味着要写全你实际会说的形式——is live与went live各成一条而不是只写live善用短语级词条JSON 支持任意长度的键不只是单词is live这类短语级词条比单词级更精准误伤其他语境的风险更低注意首尾标点虽然源码对词首/词尾是非单词字符的词条如.env做了智能边界处理但常规词条仍建议保持普通单词或短语形态用 /interview 采集让访谈流程询问姓名等非常规读音并核对identity.ts中pronunciation字段与 JSON 是否一致验证命中启动日志中的pronunciationRules: N与/voice/health的pronunciation_rules字段可确认加载数量TTS 请求前的Voice pronunciation: ... - ...日志可确认具体词条是否在真实文本中命中改写。八、小结LifeOS 的发音覆盖体系是一个典型的双层配置 三级管线设计PRONUNCIATIONS.md负责人类可读的原因记录PRONUNCIATIONS.json负责机器可读的扁平映射运行时文本依次经过内建同形异义词消歧、用户自定义正则替换两道改写最终才送入 ElevenLabs 合成。理解字面匹配的规则、词边界锚定的细节、以及/interview采集链路你就能为数字助理建立一套精准、可追溯、可持续维护的个性化发音词表。【免费下载链接】LifeOS⛰️ The Life Operating System — an intent engineering platform that moves you from your current state to your ideal state, in life and work.项目地址: https://gitcode.com/GitHub_Trending/pe/LifeOS创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表