Files
learn-languages/src/lib/bigmodel/dictionary/README.md
2026-01-13 23:02:07 +08:00

5.9 KiB
Raw Blame History

词典查询模块化架构

本目录包含词典查询系统的多阶段 LLM 调用实现,将查询过程拆分为 4 个独立的 LLM 调用,每个阶段之间有代码层面的数据验证,只要有一环失败,直接返回错误。

目录结构

dictionary/
├── index.ts                    # 主导出文件
├── orchestrator.ts             # 主编排器,串联所有阶段
├── types.ts                    # 类型定义
├── stage1-inputAnalysis.ts     # 阶段1输入解析与语言识别
├── stage2-semanticMapping.ts   # 阶段2跨语言语义映射决策
├── stage3-standardForm.ts      # 阶段3standardForm 生成与规范化
└── stage4-entriesGeneration.ts # 阶段4释义与词条生成

工作流程

用户输入
    ↓
[阶段1] 输入分析 → 代码验证 → 失败则返回错误
    ↓
[阶段2] 语义映射 → 代码验证 → 失败则保守处理(不映射)
    ↓
[阶段3] 标准形式 → 代码验证 → 失败则返回错误
    ↓
[阶段4] 词条生成 → 代码验证 → 失败则返回错误
    ↓
最终结果

各阶段详细说明

阶段 1输入分析

文件: stage1-inputAnalysis.ts

目的:

  • 判断输入是否有效
  • 判断是「单词」还是「短语」
  • 识别输入语言

返回: InputAnalysisResult

代码验证:

  • isValid 必须是 boolean
  • 输入为空或无效时立即返回错误

阶段 2语义映射

文件: stage2-semanticMapping.ts

目的:

  • 决定是否启用"语义级查询"
  • 严格条件:只有输入符合"明确、基础、可词典化的语义概念"且语言不一致时才映射
  • 不符合条件则直接失败(快速失败)

返回: SemanticMappingResult

代码验证:

  • shouldMap 必须是 boolean
  • 如果 shouldMap=true,必须有 mappedQuery
  • 如果不应该映射,抛出异常(不符合条件直接失败)
  • 失败则直接返回错误响应,不继续后续阶段

映射条件(必须同时满足): a) 输入语言 ≠ 查询语言 b) 输入是明确、基础、可词典化的语义概念(如常见动词、名词、形容词)

不符合条件的例子

  • 复杂句子:"我喜欢吃苹果"
  • 专业术语
  • 无法确定语义的词汇

阶段 3标准形式生成

文件: stage3-standardForm.ts

目的:

  • 确定最终词条的"标准形"(整个系统的锚点)
  • 修正拼写错误
  • 还原为词典形式(动词原形、辞书形等)
  • 如果进行了语义映射:基于映射结果生成标准形式,同时参考原始输入的语义上下文

参数:

  • inputText: 用于生成标准形式的文本(可能是映射后的结果)
  • queryLang: 查询语言
  • originalInput: (可选)原始用户输入,用于语义参考

返回: StandardFormResult

代码验证:

  • standardForm 不能为空
  • confidence 必须是 "high" | "medium" | "low"
  • 失败时使用原输入作为标准形式

特殊逻辑:

  • 当进行了语义映射时(即提供了 originalInput),阶段 3 会:
    1. 基于 inputText(映射结果)生成标准形式
    2. 参考 originalInput 的语义上下文,确保标准形式符合用户的真实查询意图
    3. 例如:原始输入 "吃"(中文)→ 映射为 "to eat"(英语)→ 标准形式 "eat"

阶段 4词条生成

文件: stage4-entriesGeneration.ts

目的:

  • 生成真正的词典内容
  • 根据类型生成单词或短语条目

返回: EntriesGenerationResult

代码验证:

  • entries 必须是非空数组
  • 每个条目必须有 definitionexample
  • 单词条目必须有 partOfSpeech
  • 失败则抛出异常(核心阶段)

使用方式

基本使用

import { lookUp } from "@/lib/server/bigmodel/dictionaryActions";

const result = await lookUp({
    text: "hello",
    queryLang: "English",
    definitionLang: "中文"
});

高级使用(直接调用编排器)

import { executeDictionaryLookup } from "@/lib/server/bigmodel/dictionary";

const result = await executeDictionaryLookup(
    "hello",
    "English",
    "中文"
);

单独测试某个阶段

import { analyzeInput } from "@/lib/server/bigmodel/dictionary";

const analysis = await analyzeInput("hello");
console.log(analysis);

设计优势

1. 代码层面的数据验证

每个阶段完成后都有严格的类型检查和数据验证,确保数据质量。

2. 快速失败

只要有一个阶段失败,立即返回错误,不浪费后续的 LLM 调用。

3. 可观测性

每个阶段都有 console.log 输出,方便调试和追踪问题。

4. 模块化

每个阶段独立文件,可以单独测试、修改或替换。

5. 容错性

非核心阶段阶段2、3失败时有降级策略不会导致整个查询失败。

日志示例

[阶段1] 开始输入分析...
[阶段1] 输入分析完成: { isValid: true, inputType: 'word', inputLanguage: 'English' }
[阶段2] 开始语义映射...
[阶段2] 语义映射完成: { shouldMap: false }
[阶段3] 开始生成标准形式...
[阶段3] 标准形式生成完成: { standardForm: 'hello', confidence: 'high' }
[阶段4] 开始生成词条...
[阶段4] 词条生成完成: { entries: [...] }
[完成] 词典查询成功

扩展建议

添加缓存

对阶段1、3的结果进行缓存避免重复调用 LLM。

添加指标

记录每个阶段的耗时和成功率,用于性能优化。

并行化

某些阶段可以并行执行(如果有依赖关系允许的话)。

A/B 测试

为某个阶段创建不同版本的实现,进行效果对比。

注意事项

  • 每个阶段都是独立的 LLM 调用,会增加总耗时
  • 需要控制 token 使用量,避免成本过高
  • 错误处理要完善,避免某个阶段卡住整个流程
  • 日志记录要清晰,方便问题排查