事情是这样的。我最近在折腾一个AI聊天机器人,想让它能记住我说过的话。一开始我用的是MySQL,想着不就是存数据嘛,应该没什么难度。结果写了两天代码,发现一个尴尬的问题:当我问“我之前说过我喜欢吃辣吗”,MySQL只能精确匹配关键词,但我说过“我特别爱吃火锅”和“我喜欢麻辣口味”,它死活关联不上。这就好比你去图书馆找一本书,管理员只会按书名的每个字逐个匹配,你跟他说“我要找那本讲宇宙的”,他愣是听不懂。
这就要说到今天的主角——向量数据库。我得先承认,我第一次听到这个词的时候,觉得是某种高深莫测的数学概念。后来折腾了几个晚上,踩了不少坑,才搞清楚它跟普通数据库的区别。
普通数据库,比如MySQL、PostgreSQL,存东西的方式特别死板。你存一行数据,它就像填表格一样:姓名一栏、年龄一栏、爱好一栏。查询的时候也得按照表格的规则来,比如“where 爱好 = ‘吃辣’”。这就意味着,你必须用一模一样的词去问,它才能找到。我试过存了“喜欢吃辣”,然后问“爱吃辣椒”,结果空手而归。报错倒是没有,就是返回零条记录,气得我差点把键盘摔了。
向量数据库完全不是这个思路。它存的不是文字,而是把文字变成一串数字。这串数字就像是一个人的“特征指纹”。比如“喜欢吃辣”和“爱吃辣椒”,在向量数据库里,这两串数字会非常接近,因为它们表达的意思差不多。我做了一个小实验:用了一个叫Qdrant的向量数据库,把“我喜欢吃火锅”变成了一串384位的数字,然后拿“我热爱麻辣美食”去查询,它居然返回了相似度高达87%的结果。我当时就震惊了,心想这玩意儿比我前女友还懂我,我随便说个意思它就能猜到我想说什么。
但向量数据库也不是万能的神器。我第一次用的时候,遇到一个特别坑爹的问题:怎么把文字变成那串数字?这需要用到一种叫“词嵌入模型”的东西。我选了一个开源的all-MiniLM-L6-v2模型,下载下来只有80MB,不算大。结果我忘了把模型加载到内存里,直接跑查询,等了五分钟没反应,最后发现是因为每次查询都重新加载模型,相当于每次点外卖都重新开一家餐馆。后来我改成启动时一次性加载,查询速度才从五分钟降到了50毫秒。
还有个坑是参数设置。向量数据库有个叫“距离度量”的参数,我当时选了欧氏距离,结果查询“爱跑步”的时候,返回的结果里居然有“讨厌运动”,相似度还显示65%。后来我换成余弦相似度,才把这种“方向相反”的数据过滤掉。这就好比你想找性格相似的人,结果用了身高差距来衡量,当然不准。
普通数据库和向量数据库最大的区别,其实不是技术层面,而是思维方式。普通数据库是“精确匹配”,你问什么它答什么,像个老实巴交的图书管理员。向量数据库是“模糊匹配”,你给个意思它就能联想,像个擅长推理的侦探。我现在的做法是两者混着用:把用户的聊天记录同时存进MySQL和向量数据库。MySQL用来查“用户昨天说了什么”这种精确信息,向量数据库用来查“用户对什么话题感兴趣”这种模糊需求。跑了一个月,效果还挺好,至少没再出现“我明明说过喜欢猫,它却问我养不养狗”的尴尬。
不过说实话,向量数据库目前还不算特别成熟。我试过Milvus、Pinecone和Qdrant三个,每个都有自己的脾气。Milvus安装配置特别繁琐,光依赖包就装了半小时,中间还报了个“libssl版本不兼容”的错误,我查了半天才发现是Ubuntu 20.04的锅。Qdrant相对简单,直接docker pull就能跑,但官方文档写得太简略,有个参数说明只有一句话“控制搜索精度”,我试了十几次才摸清规律——数值设成0.5时召回率80%,设成0.9时降到60%但速度翻倍。Pinecone是云服务,不用自己搭,但免费版只能存5万个向量,我测试数据一多就提示“索引已满”,得付费升级。
如果你也想试,我建议先从Qdrant入手,用docker跑起来就两行命令,然后找几个简单的句子试试。记得别用太长的文本,我一开始塞了一篇5000字的文章进去,结果向量化之后维度爆炸,查询慢得像蜗牛爬。后来发现每个文本控制在200字以内最合适,既不损失语义,速度也能接受。
反正现在我是回不去了。用习惯了向量数据库,再让我用普通数据库做语义搜索,就像用算盘算微积分,不是不行,但何必呢。