实战笔记:把海量商品数据“翻译”成 AI 能看懂的 Markdown 知识库
最近在瞎鼓捣一件事儿:怎么把公司那堆庞杂的工业产品数据,变成 AI 能“吃”得懂的“粮食”,最终目标是搞个智能客服或者产品问答机器人。
手头的数据嘛,主要是两张表:一张是 product
,存着 8000 多种商品 的基本信息;另一张是 prosn
,记录了每个商品下的各种具体型号,合计大约300万个型号,每个型号还带着价格、重量、编号、一堆属性参数等等。
核心需求就是:用户随便问个型号,AI 得能麻溜儿地、准确地把相关信息给掏出来。
琢磨了一圈,感觉用 Markdown 文件来做 AI 的“教材”(也就是知识库)挺靠谱。为啥?Markdown 格式简单,咱们人看着舒服,AI 处理起来也相对轻松些。但问题来了,怎么才能优雅地把数据库里这两张表的数据,妥妥地转换成结构清晰、AI 友好的 Markdown 呢?
这中间确实踩了几个坑,但也摸索出了一些门道,跟大家分享一下我的折腾过程和最终方案。
一开始的想法:简单粗暴,一个商品一个 .md 文件?
凭直觉,最清晰的方案肯定是给每个商品(product
表里的一行)单独创建一个 Markdown 文件。文件名可以像 商品ID_商品名.md
这样,一目了然。
文件里面的结构也想好了,大概长这样:
# 商品:XXX传感器 (ID: 123)
**系列号:** ABC-1000
**分类:** 压力传感器
**品牌:** 大力牌
... (商品的简介、详情、图片链接等基础信息) ...
---
## 该商品下的型号列表
---
### 型号: ABC-1001
* **编号:** ABC-1001
* **价格:** ¥500
* **重量:** 0.2kg
* **属性:**
* 量程: 0-10 Bar
* 输出: 4-20mA
... (这个型号的其他详细信息) ...
---
### 型号: ABC-1002
... (同上结构,列出下一个型号) ...
嗯,看起来挺美的,对吧?结构清晰,逻辑分明。
问题来了:8000+ 文件糊脸,谁顶得住啊!
但现实骨感得很——有 8000 多个商品啊!真要按这个方案来,文件夹里瞬间塞满 8000 多个 .md
文件。想象一下管理这堆文件的场景,简直是灾难片现场,查找、更新、维护都得疯。
这条路子,明显走不通。
换个思路:打包!多个商品塞进一个文件行不行?
那能不能“化零为整”,把多个商品的信息打包塞进一个 Markdown 文件里呢?比如,每 10 个、20 个,甚至 50 个商品的信息合并成一个文件。这样一来,文件数量锐减(比如按 50 个商品一个文件算,8000 / 50 ≈ 160 个文件),这就非常 manageable 了!
这个思路感觉靠谱多了!但新的问题也随之而来:一个文件里塞了这么多内容,AI 怎么知道哪部分信息属于哪个商品?不同的型号信息会不会混在一起让 AI 懵圈?
这就意味着,我们对 Markdown 文件内部的结构设计,必须提出更高的要求——得用非常明确、一致的方式来分隔内容。
关键的“顿悟”:别忘了 AI 是怎么“阅读”文档的!(Embedding & Chunking)
就在这儿,我猛地想起了 AI 处理文档时的一个核心环节:Embedding(嵌入)。简单来说,AI 不是像人一样逐字逐句读 Markdown 的。它通常会先把文档 切块(Chunking),分解成一个个有意义的文本片段(Chunk),然后把每个片段转换成一串数字(也就是向量),这样才能进行相似度计算,从而实现信息检索和问答。
这个认知一下子点醒了我:
- 切块策略(Chunking Strategy)至关重要! 如果切得不好,比如把一个完整型号的信息从中间劈开,分到两个 Chunk 里,或者一个 Chunk 里混杂了两个不相关型号的部分信息,那 AI 在回答问题时就很容易“抓瞎”或者“张冠李戴”。
- 我们设计的 Markdown 结构,必须反过来服务于这个“切块”过程! 目标是让切块工具能够轻松、准确地按照我们的意图(比如,理想情况下每个型号信息是一个独立的、完整的 Chunk)来切分文档。
进一步了解发现,很多 RAG(检索增强生成)框架里的切块工具都支持按照 Markdown 的标题层级(#
, ##
, ###
, ####
等)来切分文档。这简直是瞌睡遇到了枕头!我们可以巧妙地利用标题层级来组织内容结构,引导 AI 正确地“断句”。
最终方案:巧用标题层级,构建结构化的“AI 食粮”
综合了“多商品合并文件”和“利用标题层级辅助切块”这两个想法,最终敲定的方案如下:
- 文件组织策略: 每 N 个商品(比如 10 个或 20 个,这个 N 可以根据后续测试效果调整)合并到一个
.md
文件中。文件名可以规范化,如products_group_001.md
,products_group_002.md
等。 - 文件内部结构(这是核心中的核心!):
- 使用最高级标题
#
来标记每一个新商品的开始。例如:# 商品:二位三通手拉阀 (ID: 270)
。这是区分不同商品的最重要分隔符。 - 使用次级标题
##
来组织商品内部的不同信息区域。比如:## 商品概览
,## 商品图片链接
,## 型号列表 - 二位三通手拉阀
。这样能让商品内部信息更有条理。 - 使用更下一级的标题
###
来标记每一个具体的型号。这是确保 AI 能精准定位并回答型号相关问题的关键!例如:### 型号: 3L110-06 (隶属商品: 二位三通手拉阀, ID: 270)
。- 敲黑板,划重点! 在型号的
###
标题里,或者紧随其后的内容开头,务必、一定、必须要把这个型号所属的商品信息(比如商品名、商品 ID)明确写出来! 这样做的目的是为了给每个可能被切分出来的 Chunk 提供充足的上下文(Context)。否则,AI 单独拿到一个型号的 Chunk,可能根本不知道“我是谁?我从哪里来?”(这个型号是哪个商品的)。
- 敲黑板,划重点! 在型号的
- 如果某个型号的信息本身就特别复杂、字段特别多,还可以考虑使用
####
标题进一步细分,比如#### 详细参数
,#### 价格与库存
。这样可以让切出来的 Chunk 粒度更小,信息更聚焦。
- 使用最高级标题
所以,最终的 Markdown 文件结构看起来大概是这样(基于之前的例子):
# 商品:二位三通手拉阀 (ID: 270)
## 商品概览
* **系列号:** 3L
* **分类:** 手拉阀
* **品牌:** 亚德客
... (其他商品基础信息)
## 商品图片链接
* /path/to/image1.jpg
* /path/to/image2.jpg
## 型号列表 - 二位三通手拉阀
### 型号: 3L110-06 (隶属商品: 二位三通手拉阀, ID: 270)
* **内部ID (prosn.id):** 270
* **型号编号 (Bianhao):** 3L110-06
* **所属商品信息:** 二位三通手拉阀 (Product ID: 270) <-- **看!上下文信息在这里,非常重要!**
* **价格 (Price):** 27.00
* **接口尺寸:** PT1/8
* **状态:** 在售
... (其他型号属性、参数等)
### 型号: 3L210-06 (隶属商品: 二位三通手拉阀, ID: 270)
* **内部ID (prosn.id):** 271
* **型号编号 (Bianhao):** 3L210-06
* **所属商品信息:** 二位三通手拉阀 (Product ID: 270)
* **价格 (Price):** 32.00
* **接口尺寸:** PT1/8
* **状态:** 预售 (货期: 3天内)
...
---
# 商品:高速气缸 (ID: 271)
## 商品概览
... (同上结构) ...
## 型号列表 - 高速气缸
### 型号: HGC-20-100 (隶属商品: 高速气缸, ID: 271)
* **内部ID (prosn.id):** 350
* **型号编号 (Bianhao):** HGC-20-100
* **所属商品信息:** 高速气缸 (Product ID: 271)
* **价格 (Price):** 150.00
* **缸径:** 20mm
* **行程:** 100mm
...
实际操作中的一些“坑”和注意点:
- 数据“翻译”是必须的: 数据库里存的
status
(比如 0, 1, 2)、huoqi
(比如 1, 2, 3, 4 代表不同天数)、pricetype
(比如 1 代表真实价, 2 代表面议)这些代码,在生成 Markdown 时,必须转换成人类和 AI 都能直接理解的文字(例如:“已下架”、“货期3天内”、“真实价格”)。 - 关联信息得查全: 不能只在 Markdown 里放个
category_id
、pinpai_id
,得提前去关联的分类表、品牌表查出对应的名字(如“压力传感器”、“大力牌”)写进去,提供更丰富的上下文。 - 特殊字段格式化: 像
shuxing
字段里那种“一行一个属性,属性名=属性值”的文本,需要写脚本去解析,转换成 Markdown 的无序列表格式。类似地,pic
字段里用逗号分隔的多个图片路径,也最好处理成列表。 - 内容要精简聚焦: 不是所有数据库字段都对问答有用。像
seo_title
,seo_keywords
,views
,buys
这类主要用于网站运营或统计的字段,对 AI 回答用户关于产品本身的问题帮助不大,可以考虑不导出到 Markdown 里,让知识库更“纯粹”。 - 多语言支持: 如果你的产品信息需要支持英文,可以在对应的中文信息块下面,加上英文内容,比如使用数据库里
_en
后缀的字段,同样遵循 Markdown 结构。 - 一致性!一致性!一致性! 重要的事情说三遍!所有商品、所有型号,都必须严格遵循完全相同的标题层级和格式规范。任何一点随意的变动或格式不统一,都可能导致自动切块工具“翻车”,切出乱七八糟的 Chunks。
- 脚本自动化大法好: 这活儿数据量大,手动转换是不可能的,必须写脚本(用 Python、PHP、Node.js 或你擅长的任何语言都行)。脚本的核心逻辑大概是:
- 连接数据库。
- 设定一个计数器
count
和文件句柄file_handler
,决定好每个文件包含 N 个商品。 - 循环遍历
venshop_product
表中的商品记录。 - 对于每个商品,根据
product_id
去venshop_prosn
表查出它名下所有的型号记录。 - 按照上面精心设计的 Markdown 结构,把当前商品的基础信息和它所有型号的详细信息,拼装成符合格式的字符串。
- 记得在每个商品信息前加上
# 商品名 (ID: xxx)
这样的一级标题。 - 在每个型号信息前加上
### 型号: 型号名 (隶属商品: 商品名, ID: xxx)
这样的三级标题,并确保包含了关键的上下文信息。 - 将拼装好的字符串写入当前打开的文件
file_handler
。 - 商品计数器
count
加 1。如果count
达到 N,则关闭当前文件,打开一个新的 Markdown 文件(比如文件名序号加 1),并将count
重置为 0。 - 所有商品处理完毕后,确保关闭最后一个文件。
总结几点关键的经验教训:
- 终局思维: 时刻牢记这些 Markdown 最终是给 AI “消费”的,特别是要能顺利通过 Embedding 和 Chunking 这两关。设计结构时要为下游处理着想。
- 结构为王: 清晰、统一、有逻辑的 Markdown 标题层级,是确保 AI 能正确“断句”(切块)的生命线。
- 上下文不能丢: 每个信息片段(尤其是型号这种细粒度的),都必须包含能识别其归属(属于哪个商品)的上下文信息,防止产生“孤儿”Chunk。
- 自动化是刚需: 数据量稍大,就别想着手动处理了,老老实实写脚本吧,效率和准确性都有保障。
- 测试驱动开发(TDD... sorta): 生成一部分 Markdown 文件后,别急着全量跑。先拿样本文件用你的 Embedding 流程(包括切块那一步)跑一下,检查切出来的 Chunks 是否符合预期。如果切得不对,赶紧调整 Markdown 生成逻辑和结构,直到满意为止,再大规模生成。
总算把这次折腾的过程和想法理清楚了。希望我这点“踩坑”记录能给正在或将要处理类似数据转换问题的朋友们一点启发或参考。实践下来,用这套方法生成的 Markdown 文件,不仅相对容易管理,而且能让 AI 更好地理解和利用其中的结构化信息,相信对提升后续问答系统的准确率会有不小的帮助。