第二章:需求分析与架构设计——核心功能模块拆解

好,咱们进入正题。上一章我们把知识库的「为什么」讲清楚了,这一章聊聊「怎么做」。

说实话,我见过不少团队,一上来就撸代码,结果做到一半发现数据源接不进来,或者检索慢得像蜗牛。嗯,这就是典型的「架构没想清楚就动手」。我个人习惯,先花两天时间把需求掰开揉碎,再画图,最后选技术栈。磨刀不误砍柴工嘛。

2.1 核心功能模块拆解

一个金融知识库,说白了就干五件事:采、洗、存、搜、答。我把它拆成五个模块,每个模块都有明确的边界。

核心五模块一览:

  • 数据采集:从外部源(研报、公告、新闻)拉取原始数据
  • 数据清洗:去噪、格式化、实体识别、去重
  • 数据存储:结构化数据 + 非结构化数据 + 向量索引
  • 智能检索:关键词 + 语义 + 混合检索
  • 问答引擎:基于大模型的上下文理解与生成

你可能会问:为什么要把「问答」单独拎出来?我在项目中遇到过,很多人把检索和问答混在一起,结果用户问「茅台2023年营收多少」,系统返回了一堆研报片段,还得用户自己翻。这体验太差了。问答引擎应该直接给出答案,并附上引用来源。

2.2 数据采集模块

数据采集是地基。地基没打好,后面全是白费。

金融数据源五花八门:PDF研报、HTML网页、API接口、甚至扫描件。我建议按数据源类型分策略:

  • 结构化数据(财报、行情):走API定时拉取,用ETL工具(比如Airbyte)
  • 半结构化数据(HTML新闻):用Scrapy或Playwright爬取,注意反爬
  • 非结构化数据(PDF研报):用PyMuPDF或OCR(Tesseract)提取文本

避坑指南:我曾经天真地以为所有PDF都能直接提取文本。结果遇到扫描件,全是图片。后来老老实实加了OCR流水线。记住:永远假设数据源是脏的

2.3 数据清洗模块

清洗这一步,我见过太多人轻视了。金融数据里全是坑:

  • 「贵州茅台」和「贵州茅台酒股份有限公司」是不是同一个实体?
  • 「2023年12月31日」和「2023-12-31」要不要统一?
  • 研报里那些表格,怎么提取成结构化数据?

我的做法是三步走:

  1. 格式标准化:日期、金额、百分比统一格式
  2. 实体对齐:用预训练的金融NER模型(比如FinBERT)识别公司名、人名、产品名
  3. 去重:基于MinHash或SimHash做近似去重,避免同一篇研报被重复收录

注意:金融数据去重不能只看文本相似度。两篇研报可能内容相似但观点相反,都得保留。我一般用「标题+发布时间+来源」做指纹,再辅以语义相似度做二次判断。

2.4 数据存储模块

存储是重头戏。金融知识库需要同时支持三种查询:

  • 精确查询:查某只股票的历史PE
  • 模糊查询:搜「新能源车 研报」
  • 语义查询:问「最近哪些公司发布了超预期财报?」

所以我用了混合存储架构:

数据类型 存储引擎 用途
结构化数据 PostgreSQL 财报、行情、元数据
非结构化文本 Elasticsearch 全文检索、关键词匹配
向量嵌入 Milvus / Qdrant 语义相似度检索
原始文件 MinIO (S3兼容) PDF、图片等原始文件存储

你想想看,如果只用ES做全文检索,用户问「2024年白酒行业毛利率趋势」,ES只能匹配关键词,但理解不了「趋势」这个语义。所以必须上向量检索。

2.5 系统架构图

下面这张图是我画的核心架构。别嫌丑,逻辑清楚最重要。

金融知识库系统架构图 数据采集层 API定时拉取 网页爬虫 PDF/OCR解析 消息队列 数据清洗层 格式标准化 实体识别(NER) 去重/去噪 质量校验 数据存储层 PostgreSQL Elasticsearch Milvus向量库 MinIO对象存储 Redis缓存 检索与问答层 混合检索(ES+向量) RAG上下文构建 LLM问答生成 结果排序

这张图我画了三遍才满意。第一版太复杂,把每个模块的内部细节都画出来了,结果没人看得懂。后来我简化成四层:采集→清洗→存储→检索问答。每一层只标核心组件,够用了。

2.6 技术选型对比

选技术栈这事儿,没有银弹。我列个对比表,你根据自己团队的情况选:

模块 推荐方案 备选方案 我的建议
数据采集 Airbyte + Scrapy Apache Nifi / 自研 小团队用Airbyte,开箱即用
数据清洗 Python (Pandas + SpaCy) Spark NLP / 自研规则 数据量<10G用Pandas足够
结构化存储 PostgreSQL MySQL / TiDB PG的JSON和向量扩展很香
全文检索 Elasticsearch 8.x Meilisearch / Typesense ES生态最成熟,但重资源
向量检索 Milvus Qdrant / Weaviate Milvus性能好,但运维复杂
LLM推理 vLLM + Qwen2.5 Ollama / 文心API 本地部署用vLLM,省钱
编排调度 Airflow / Prefect Dagster / 自研Cron Prefect的Python原生体验更好

个人经验:别一上来就上Kubernetes。我见过一个5人团队,花了两周搭K8s集群,结果业务代码一行没写。前期用Docker Compose + 单机部署,等日均请求量超过1万再说。

2.7 避坑指南汇总

最后,我把这些年踩过的坑总结一下:

  • 数据源变更:金融网站改版是常事。爬虫要加监控,发现异常立刻告警。我曾经因为没监控,数据断供了三天才发现。
  • PDF解析精度:别信100%准确率。表格、公式、页眉页脚都会干扰。我一般保留原始PDF,清洗后的文本只做索引用。
  • 向量维度选择:不是越大越好。768维的text-embedding-3-small够用了,1536维的模型推理慢一倍,效果提升不到5%。
  • 检索召回率:纯向量检索容易漏掉精确匹配。我建议用「ES关键词检索 + 向量检索」的混合模式,权重按场景动态调整。

嗯,架构设计这块就聊到这儿。记住一句话:架构是演进来的,不是设计出来的。先跑通最小闭环,再逐步优化。下一章我们开始动手搭建开发环境,把代码跑起来。


公众号:蓝海资料掘金营,微信deep3321