目标:接入 LLM,实现「自然语言 → 本体推理 → 指标查询 → 业务分析」的完整链路。LLM 只做槽位提取和归因分析。
| 环节 | 谁负责 |
|---|---|
| 意图识别 + 槽位提取 | LLM |
| 指标等价对齐(成交额≡GMV) | 本体推理 |
| 维度层级展开(华东区⊇各省) | 本体推理 |
| SQL 生成 | 模板 + 参数填充 |
| 口径校验 | 公理校验 |
| 结果归因分析 | LLM |
// 调用 LLM 做槽位提取(DeepSeek,OpenAI 兼容)
public QueryIntent parseIntent(String question) {
String prompt = """
你是指标查询系统的意图识别器。从用户问题中提取槽位,输出 JSON。
槽位:intent(metric_query/analysis)、metric、region、time、compare。
不要做语义对齐(不要推断"成交额"等于什么指标),只提取原话。
问题:%s
""".formatted(question);
// 返回:{ metric:"成交额", region:"华东区", time:"last_month", compare:"环比" }
}
@Service
public class AiQueryService {
public QueryResponse query(String question) {
// ① LLM 槽位提取
QueryIntent intent = llmService.parseIntent(question);
// ② 本体推理:指标等价对齐(成交额 → GMV)
String metric = ontologyService.resolveEquivalentMetric(intent.metric());
// ③ 本体推理:维度层级展开(华东区 → 7省)
List<String> regions = ontologyService.expandRegion(intent.region());
// ④ 时间解析
TimeRange time = timeParser.parse(intent.time());
// ⑤ 受约束 SQL 生成 + 口径校验
String sql = sqlGenerator.generateSql(metric, regions, time);
caliberValidator.validate(metric, sql);
// ⑥ 查询执行(MaxCompute)
List<Map<String, Object>> result = maxComputeQueryService.query(sql);
// ⑦ LLM 归因分析
String analysis = llmService.analyze(question, metric, result);
return new QueryResponse(result, analysis);
}
}
public String analyze(String question, String metric, List<Map<String,Object>> result) {
String prompt = """
你是数据分析师。以下是用户问题和查询结果,请基于数据做归因分析,
只解释数据反映的事实,不要编造数据里没有的内容。
问题:%s
指标:%s
结果:%s
""".formatted(question, metric, result);
return llmService.call(prompt);
}
用户:「上个月华东区成交额环比下降多少?为什么?」
① LLM 槽位提取 → { metric:"成交额", region:"华东区", time:"last_month", compare:"环比" }
② 本体推理 → 成交额 ≡ GMV
③ 本体推理 → 华东区 = [上海,江苏,浙江,安徽,福建,江西,山东]
④ 时间解析 → 2026-07-01 ~ 2026-07-31(+ 上月同期)
⑤ SQL 生成(GMV 模板,口径固化)
⑥ MaxCompute 查询账单表 → 华东区 GMV=1.2亿,环比 -12.3%
⑦ LLM 归因 → "华东区 GMV 环比下降 12.3%,主因..."