2026-09-23·by Sijie Wang#lucerna#software#architecture

linguistic-two-engines

两套语言引擎(TS-LLM 与 Python-spaCy)

上级:key-designs

词元(lemma)、词性、动词变位表、可分动词还原、语法结构——这些概念上相同的输出,是由两套并行引擎分别算出来的,而不是一条生产者/消费者式的流水线。客户端的实际路径以 LLM 为先,查词时并不会调用 Python 服务。

TS 核心(@lucerna/core)——客户端里始终在场的大脑,覆盖任意语言。 负责分词/省音(elision)、全形式匹配、动词形式的采集、原始文本与显示形式之间的几何映射,以及词性分类体系/配色/11 种语言的标签。所有内容生成都委托给一个用户自行配置的 LLMapi/llmLookup.ts):基础查词、动词变位表、完整的变形集合、句子分析(那串语法 structure 字符串)、词性配色。这里真正棘手的地方在于不能信任 LLM 的输出cleanLLMJson 从第一个 {/[ 切到最后一个 }/],取出 JSON 子串(把代码围栏、前导文字都砍掉),再跑一遍 jsonrepair(处理多余逗号、单引号、截断),并配合宽容的数组提取(sentences|result|analysis|data|items,或任意顶层数组)以及 HTTP 状态码到本地化错误信息的映射。

Python 的 nlp-api——确定性的离线引擎,只覆盖德语和英语。 spaCy(de_core_news_lg / en_core_web_lg)负责分词加词形还原;一个依存句法分析器infrastructure/grammar/dep_parse_analyzer.py)产出真正丰富的语法信息:从句类型(Hauptsatz 还是 Nebensatz,靠从属连词 / cp/rc 依存关系判断)、时态推断(从 Partizip II 加助动词的形态推出 Perfekt/Plusquamperfekt/Futur/Präteritum)、语序(Inversion / 动词后置)、各类特征(被动态 Passiv、虚拟式二式 Konjunktiv II、情态、否定、反身),再往下是主语/第四格/第三格成分的拆解——最终呈现为一串带中文标注的文字。再配上一个 Wiktionary/Postgres 词典(优先取有中文释义的行)和一个按语言对分发的 CompositeTranslator(NLLB / Opus-MT)。

为什么两者都要保留(设计逻辑)。 LLM 引擎能处理任意语言、给出丰富的目标语言释义,但需要用户自备 API key,还得做 JSON 修复;spaCy 引擎是确定性的、离线的、不需要 key,但被锁死在德语加英语这两种语言里。德语可分动词是这个分裂最清楚的例证:TS 这边是一个前缀剥离的启发式做法(separableVerbService.ts),Python 那边则是真正的依存句法 svp 还原spacy_tokenizer.py——找到依存关系为 svp、其head是该动词的那个 token,重新拼出 前缀+词元,并把德语名词词元首字母大写)。同一个问题,两种保真度——客户端永远能给出答案,服务端只在它覆盖的这两种语言上给出正确答案。

about this entry

One of sijie's wiki entries. The AI on this site is grounded in the same corpus and answers in sijie's voice, with citations back to entries like this one — answering costs sijie money, so it waits behind a code: enter an access code →