5.9 KiB
5.9 KiB
词典查询模块化架构
本目录包含词典查询系统的多阶段 LLM 调用实现,将查询过程拆分为 4 个独立的 LLM 调用,每个阶段之间有代码层面的数据验证,只要有一环失败,直接返回错误。
目录结构
dictionary/
├── index.ts # 主导出文件
├── orchestrator.ts # 主编排器,串联所有阶段
├── types.ts # 类型定义
├── stage1-inputAnalysis.ts # 阶段1:输入解析与语言识别
├── stage2-semanticMapping.ts # 阶段2:跨语言语义映射决策
├── stage3-standardForm.ts # 阶段3:standardForm 生成与规范化
└── 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 会:- 基于
inputText(映射结果)生成标准形式 - 参考
originalInput的语义上下文,确保标准形式符合用户的真实查询意图 - 例如:原始输入 "吃"(中文)→ 映射为 "to eat"(英语)→ 标准形式 "eat"
- 基于
阶段 4:词条生成
文件: stage4-entriesGeneration.ts
目的:
- 生成真正的词典内容
- 根据类型生成单词或短语条目
返回: EntriesGenerationResult
代码验证:
entries必须是非空数组- 每个条目必须有
definition和example - 单词条目必须有
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 使用量,避免成本过高
- 错误处理要完善,避免某个阶段卡住整个流程
- 日志记录要清晰,方便问题排查