当前位置: 首页 > news >正文

开发记录26_自然语言搜索不是加权求和_结构化查询与AND约束

Memoria 开发记录 26:自然语言搜索不是加权求和——结构化查询与 AND 约束

前言

相册搜索看起来可以用一个简单公式解决:把地点、时间、语义、标签都转成分数,再按总分排序。但真实使用后会发现,这种做法很容易产生反直觉结果。

例如用户搜索“济南的猫”,地点命中很高的济南照片可能排在前面,即使画面里根本没有猫。搜索“夜晚的大明湖”,如果夜晚语义分数高,其他城市的夜景也可能混进来。这不是排序微调能解决的问题,而是检索模型本身错了。

自然语言检索中的多个条件,很多时候不是加权 OR,而是分层 AND。

为什么加权分数会出错

加权求和默认每个条件都可以互相补偿:

总分 = 地点分 + 时间分 + 语义分 + 标签分

这种模型适合推荐,不适合精确搜索。用户明确说了地点、时间和主体时,每个条件都应该有自己的边界。地点分不能补偿主体缺失,语义分也不能补偿时间不匹配。

“济南的猫”的真实语义是:

地点 = 济南
AND
视觉主体 = 猫

如果没有猫,结果就不是完全匹配。它最多可以被放到“可能相关”里,甚至在用户期望很明确时不应该展示。

查询解析要先拆结构

Memoria 当前将自然语言查询拆成几个层次:

时间日期:绝对日期 / 年度日期 / 当地时间段 / 星期
地点:国家 / 省 / 市 / 区 / POI / 景区 / 校区 / 商圈
视觉主体:用于 MobileCLIP 的英文语义
负向语义:用于排除近似错误
属性:人数、笑脸、媒体类型等

这一步必须由 LLM 明确输出结构化 JSON,而不是只输出几个搜索词。客户端再对 JSON 做校验、修正和执行。

结构化的好处是每个条件有自己的执行位置:

  • 时间走 ObjectBox 时间索引;
  • 地点走本地地址字段、POI/AOI、坐标半径;
  • 视觉主体走 embedding;
  • OCR 和 caption 作为文本特征;
  • 结果排序只在候选集合内部发生。

地点只能限定候选,不能替代主体

之前一个关键错误是:当严格地点候选存在但语义没有命中时,系统会把这些地点候选作为 metadata fallback 加进相关结果。这样“济南的猫”就会退化成“济南的照片”。

修复后的规则是:只要查询中存在明确视觉语义,metadata-only fallback 就不能替代它。地点可以缩小候选边界,但不能让没有主体的照片混成相关结果。

有视觉主体:必须过主体语义或文本特征metadata-only 不补位纯机械查询:例如“10月”“青岛”“周末”可以直接返回元数据匹配结果

这让检索从“谁分高谁赢”变成“先满足必要条件,再排序”。

Prompt 也要表达系统能力

如果 prompt 没告诉 LLM 本地有哪些索引,LLM 很容易把一切都写进视觉语义。例如“晚霞”只输出 sunset sky,而忘记它隐含下午到傍晚的时间窗口;“国庆节”只输出 holiday travel,而忘记 10 月 1 日到 7 日这个年度日期范围。

新的 prompt 明确告诉 LLM:

  • 年份明确的日期走绝对日期;
  • 不指定年份的月份、节日、季节走年度 MM-DD;
  • 白天、夜晚、晚霞、朝霞走当地分钟窗口;
  • 地名写入 geo filter;
  • 视觉语义必须是英文;
  • 地点名不能直接塞进 embedding query;
  • 多个条件按 AND 处理。

LLM 不负责算 day-of-year,只输出人类可读的 MM-DD,客户端负责解析。

UI 必须展示检索计划

检索正确不代表用户能理解。如果 UI 只显示结果,不展示“实际用了哪些过滤条件”,用户会误以为系统没有识别时间或地点。

因此搜索页需要展示完整 query plan,包括:

  • 绝对日期;
  • 年度日期范围;
  • 当地时间段;
  • 星期;
  • 地点;
  • 主体语义;
  • 召回语义;
  • 负向语义;
  • 人数、笑脸、媒体类型等属性。

这既是产品解释,也是调试工具。用户看到 time=annual:10-01..10-31,就知道“10月”确实被识别成了时间过滤。

总结

自然语言相册搜索的核心不是把所有线索混成一个分数,而是识别哪些条件是硬边界,哪些条件只是排序信号。

关键经验包括:

  • 多条件搜索应优先建模为分层 AND;
  • 地点、时间和主体不能互相补偿;
  • LLM 输出必须结构化,客户端必须校验;
  • 不指定年份的月份和节日也属于机械时间过滤;
  • metadata fallback 不能替代明确视觉主体;
  • UI 应展示完整 query plan,避免用户误判系统行为。

对应提交:bb19d13ea4638a823466e07c235e89ecfe6