← 返回技术深读

源码深读 · 2019

金融检索与语义扩展源码深读

还原多源金融文档从采集、PDF 结构化到同义词扩展、组合过滤、时间衰减排序和段落高亮的完整执行链。

金融搜索Elasticsearch自然语言处理排序

结论先行

这不是一个给数据库加搜索框的项目,而是一条“异构资料加工管线 + 研究型检索引擎”。采集端覆盖公告、研报、新闻、专利、工商、政策、社交内容和证券元数据;在线端把查询理解、字段过滤、来源卡片、知识关系和文内定位组合成一次研究动作。

最有价值的设计,是复用全文引擎的分析器完成中文分词和同义词扩展,并把短语命中、资料类型与新鲜度共同纳入排序。最需要警惕的设计,也是这种深度绑定:代码通过解析全文引擎的内部诊断字符串取得同义词,升级后极易失效。

从原始资料到可检索文档

采集仓按来源拆分 Spider,并通过 Middleware、Pipeline 和分段调度脚本运行。全局配置限制并发为 4、同域并发为 4、请求间隔 5 秒;个别高吞吐任务覆盖这些参数。公告文件下载后以来源地址摘要命名,保存文件路径、原地址和校验标识。

PDF 加工不是简单抽文本。处理器调用 PDF 转 HTML 工具,将页面内容转为段落结构,同时尝试生成图片信息和表格中间结果;耗时工作通过事件循环的线程池执行,完成后再进入索引管线。键值存储保存已抓取标记、转换结果和失败文件,扫描器与重建脚本负责补偿。这解释了仓库中“采集、失败扫描、重抓、重建索引”并存的原因。

索引文档围绕公告类型、发布时间、证券名称与代码、标题、文件、段落数组、分类、机构、作者和评级组织。段落保留文本、页码、锚点、类型和总数,使搜索结果能够继续下钻到 PDF 内部。

查询执行链

一次搜索可还原为以下步骤:

  1. 控制器接收查询文字、位置范围、词距、证券、行业、板块、市值、来源、时间和语义选项。
  2. 智能扩展开启时,先分词,再把每个词与同义词组对齐;双引号包围的词不扩展。
  3. 扩展结果被改写为“词或同义词”组,各组之间使用并且关系。
  4. 主查询默认同时搜索标题与正文段落,默认要求各查询组均命中;标题或正文范围可单独选择。
  5. 多个证券集合、行业映射集合取交集,再与时间、板块、来源等条件一起放入过滤上下文。
  6. 精确短语副查询使用固定大词距与 20 倍提升,作为主查询的可选加分项。
  7. 函数评分将文本分数乘以资料类型因子和发布时间高斯衰减。
  8. 结果按相关度优先、时间次之返回;无关键词时顺序反转为时间优先。

资料类型因子在代码中明确:年报与日常经营类为 1.2,研报为 0.68,专利为 0.36,其余为 1。时间衰减以当前时间为中心,7 天内不衰减,约 30 天为尺度。因此最终分数可以概括为:文本相关度 × 类型权重 × 时间衰减,再叠加精确短语的高提升信号。

自然语言处理细节

分词适配器向专用索引的分析接口提交文本,使用区分大小写的智能分析器。智能扩展则向同一索引执行带诊断信息的查询,从第一分片、第一条查询描述中匹配同义词表达式,再与分词序列对齐。

这一方案的工程价值在于:词典、分词和同义词都由搜索集群统一管理,应用无需部署独立语言服务;用户还可以在接口层更新自定义词典。代价是应用依赖诊断文本格式,而不是稳定的结构化协议。诊断信息、分片布局或分析器输出稍有变化,扩展列表就可能静默为空。

高亮不是装饰

列表查询请求完整段落高亮,但列表只返回命中段落数。打开文档时,系统按文档标识重新执行仅正文的高亮查询,把去掉标记后的文本映射回原段落;隐藏段落被跳过。

若命中多个段落,每段分数等于不同高亮片段字符长度之和。随后以首个和最后一个命中为中心向两侧寻找句号,在最大长度附近截取上下文,再按“命中强度降序、原文位置升序”排列。研报锚点还会增加专用前缀,以适配另一种 HTML 结构。

缺陷与重建重点

  • 同义词提取解析内部诊断字符串,只读取第一分片,属于高脆弱耦合。
  • 一处分支把布尔常量拼错,可能使查询改写状态判断失真;分词异常时列表变量也可能未初始化。
  • 筛选接口先读缓存又立即强制未命中,等于关闭缓存;文内查询允许调试参数绕过缓存。
  • 通用多列排序用动态求值拼接表达式,重建时应改为固定比较器。
  • 类型权重、短语提升和时间尺度写死在代码中,既无法版本化,也不能解释某次排序使用了哪套参数。
  • 结果分数按当页最高分归一到 100,不同查询或不同页之间不能直接比较。

重建时应把查询改写结果、分析器版本、过滤集合、原始分数和各评分因子作为可观察信息保存;同义词改用稳定接口,排序参数进入版本化配置,并用固定语料覆盖引号、证券交集、空扩展、中文标点和跨页分数回归。

证据边界

上述链路由控制器、查询工具、采集管线、PDF 处理器和移动端页面相互印证。代码能证明算法与接口意图,但不能证明历史索引中的全部文档都成功加工,也不能证明写死的评分参数经过离线评测。