
文章目录RAG在KES里到底怎么跑混合检索不止是向量相似度嵌入模型导入和大模型缓存真实落地案例某央企的智能体建设DeepSeek私有化部署中的向量角色关于性能基准数据写在最后兼容是对前人努力的尊重是确保业务平稳过渡的基石然而这仅仅是故事的起点上篇聊了烟囱式架构的痛点和KingbaseES融合架构的基本概念这篇我打算聊点更实在的——怎么在KES里把RAG跑起来混合检索到底怎么用MCP Server是怎么让AI直接操作数据库的还有几个我接触过的真实案例。先说句题外话上篇发出去之后有个朋友私信我说我把一体化架构吹得太狠了专用向量数据库在性能上还是有明显优势的。这个意见我接受所以下篇我会尽量客观一点不光说好听的也聊聊我遇到的一些限制和需要注意的地方。RAG在KES里到底怎么跑RAG这个词现在已经烂大街了随便参加个技术沙龙都有人在聊。但说真的真正把RAG从demo做到生产可用的团队并不多。大部分demo都是拿个LangChain连个Milvus塞几篇文档进去问答能跑通就完事了。到了生产环境数据更新、权限控制、延迟、准确率全是问题。RAG的基本流程其实不复杂。用户提问之后先把问题转成向量embedding然后在向量库里做相似度检索找到最相关的文档片段把这些片段塞进prompt里最后让大模型基于这些片段生成回答。整个流程的核心瓶颈其实在检索这一步——检索到的内容质量直接决定了回答质量。在KES里跑RAG和在专用向量数据库里跑流程上大同小异但有几个关键区别。先看建表和数据导入-- 文档表存元数据和原文CREATETABLEdocuments(id BIGSERIALPRIMARYKEY,titleVARCHAR(500)NOTNULL,departmentVARCHAR(100),security_levelINTDEFAULT1,contentTEXT,file_typeVARCHAR(20),created_atTIMESTAMPDEFAULTCURRENT_TIMESTAMP,updated_atTIMESTAMPDEFAULTCURRENT_TIMESTAMP);-- 文档切片表存向量和切片文本CREATETABLEdoc_chunks(id BIGSERIALPRIMARYKEY,doc_idBIGINTNOTNULLREFERENCESdocuments(id),chunk_indexINTNOTNULL,chunk_textTEXTNOTNULL,embedding vector(1024),token_countINT,created_atTIMESTAMPDEFAULTCURRENT_TIMESTAMP);-- 建HNSW向量索引CREATEINDEXONdoc_chunksUSINGhnsw(embedding vector_cosine_ops)WITH(m16,ef_construction64);-- 给doc_id建个普通B-tree索引JOIN的时候用CREATEINDEXONdoc_chunks(doc_id);数据导入的过程你可以用Python来做。把文档读进来、切片、调embedding模型生成向量然后批量写入KESimportkingbasefromsentence_transformersimportSentenceTransformer# 初始化embedding模型modelSentenceTransformer(BAAI/bge-large-zh-v1.5)# 连接KESconnkingbase.connect(hostlocalhost,port54321,databaseai_app,userai_user)curconn.cursor()defimport_document(title,department,security_level,content):导入一篇文档自动切片、向量化、写入# 先写文档表cur.execute( INSERT INTO documents (title, department, security_level, content) VALUES (%s, %s, %s, %s) RETURNING id ,(title,department,security_level,content))doc_idcur.fetchone()[0]# 简单按500字切片实际项目建议用更智能的切片策略chunks[content[i:i500]foriinrange(0,len(content),400)]# 批量生成向量embeddingsmodel.encode(chunks,normalize_embeddingsTrue)# 批量写入foridx,(chunk,emb)inenumerate(zip(chunks,embeddings)):cur.execute( INSERT INTO doc_chunks (doc_id, chunk_index, chunk_text, embedding, token_count) VALUES (%s, %s, %s, %s, %s) ,(doc_id,idx,chunk,emb.tolist(),len(chunk)))conn.commit()returndoc_id这就是导入部分。跟用Milvus比起来最大的区别是你不用同时往两个数据库写数据了——文档元数据和切片向量都在一个库里一个事务搞定。检索的时候更能体现一体化的优势。一个带权限控制的RAG检索-- 用户提问的向量由应用层生成这里用:query_vec占位WITHrelevant_chunksAS(SELECTc.id,c.doc_id,c.chunk_text,d.title,d.department,1-(c.embedding:query_vec)ASsimilarityFROMdoc_chunks cJOINdocuments dONc.doc_idd.idWHEREd.security_level:user_clearanceAND(d.departmentANY(:user_depts)ORd.departmentISNULL-- 公开文档)ORDERBYc.embedding:query_vecLIMIT20)SELECT*FROMrelevant_chunksWHEREsimilarity0.75-- 相似度阈值过滤ORDERBYsimilarityDESCLIMIT5;这条SQL把向量检索、JOIN、权限过滤全做了。在专用向量数据库里你至少要分两步先向量检索拿到候选再去关系库过滤权限。两步之间的窗口期可能导致权限变更不生效而且如果候选结果被过滤掉太多回答质量会下降。我之前做过一个对比测试。同样的数据集50万篇文档约800万个切片同样的embedding模型同样的查询集合。Milvus方案的P95延迟是230毫秒Milvus检索80ms MySQL权限查询40ms MongoDB拿内容110msKES一体化方案的P95延迟是45毫秒一条SQL在库内全部完成。差了5倍而且KES方案的准确率还更高一些因为权限过滤在检索阶段就做了不会出现检索到10条被过滤掉7条的问题。不过这里我得说句公道话这个对比测试是我自己项目的数据不代表所有场景。如果你的数据量到了十亿级或者查询QPS特别高专用向量数据库的分布式架构可能更有优势。KES的分布式能力也在持续增强目前看亿级以下的数据量一体化方案的性能完全够用。混合检索不止是向量相似度RAG最常见的一个问题是语义检索找不到精确匹配。比如用户搜KES V8R6版本的安装要求向量检索可能返回一堆关于安装的文档但未必包含V8R6这个精确版本号。这时候就需要混合检索——把向量相似度检索和全文检索结合起来。KES本身就支持全文检索和向量检索在同一个库里做混合检索非常方便-- 先给chunk_text加全文索引CREATEINDEXONdoc_chunksUSINGgin(to_tsvector(simple,chunk_text));-- 混合检索向量相似度 全文检索关键词匹配WITHvector_resultsAS(SELECTid,doc_id,chunk_text,1-(embedding:query_vec)ASv_score,ROW_NUMBER()OVER(ORDERBYembedding:query_vec)ASv_rankFROMdoc_chunksORDERBYembedding:query_vecLIMIT50),text_resultsAS(SELECTid,doc_id,chunk_text,ts_rank(to_tsvector(simple,chunk_text),plainto_tsquery(simple,:query_text))ASt_score,ROW_NUMBER()OVER(ORDERBYts_rank(to_tsvector(simple,chunk_text),plainto_tsquery(simple,:query_text))DESC)ASt_rankFROMdoc_chunksWHEREto_tsvector(simple,chunk_text) plainto_tsquery(simple,:query_text)LIMIT50)SELECTCOALESCE(v.id,t.id)ASid,COALESCE(v.doc_id,t.doc_id)ASdoc_id,COALESCE(v.chunk_text,t.chunk_text)ASchunk_text,COALESCE(v.v_score,0)ASvector_score,COALESCE(t.t_score,0)AStext_score,-- RRF融合倒数排名融合(1.0/(60COALESCE(v.v_rank,999))1.0/(60COALESCE(t.t_rank,999)))ASrrf_scoreFROMvector_results vFULLOUTERJOINtext_results tONv.idt.idORDERBYrrf_scoreDESCLIMIT10;这段SQL看着有点长但逻辑其实不复杂。它分别做了向量检索和全文检索然后用RRFReciprocal Rank Fusion倒数排名融合算法把两个结果集合并。RRF的好处是你不用操心向量分数和全文分数的量纲不同——它只看排名不看绝对分值简单有效。在实际项目中混合检索的效果提升是很明显的。我之前做过一个企业知识库项目纯向量检索的回答准确率大概是72%加上全文检索做混合之后提升到了86%。尤其是涉及版本号、错误代码、产品名称这类精确词的查询全文检索的补充作用非常关键。KES还支持向量和其他数据模型的融合检索比如GIS。我在资料里看到一个城市管理的场景把交通事故数据的三个维度——事故类型、天气情况、道路类型——编码成一个3维向量同时用GIS类型存储事故位置。查询的时候同时做空间范围过滤和向量相似度匹配-- 事故表GIS位置 事故特征向量CREATETABLEaccident_reports(id BIGSERIALPRIMARYKEY,locationGEOMETRY(Point,4326),accident_timeTIMESTAMP,feature_vector vector(3),-- [事故类型, 天气, 道路类型]descriptionTEXT,severityINT);-- 空间索引CREATEINDEXONaccident_reportsUSINGgist(location);-- 向量索引CREATEINDEXONaccident_reportsUSINGhnsw(feature_vector vector_l2_ops);-- 查询指定区域内、雨天分支道路追尾相似的事故SELECTid,accident_time,description,ST_Distance(location,ST_MakePoint(116.4,39.9)::geography)ASdistance_meters,feature_vector-[1,2,3]ASfeature_distanceFROMaccident_reportsWHEREST_DWithin(location::geography,ST_MakePoint(116.4,39.9)::geography,5000-- 5公里范围内)ANDaccident_time2025-01-01ORDERBYfeature_vector-[1,2,3]LIMIT20;这个查询同时用到了三种数据类型——GIS空间数据、向量数据、时间戳三种索引协同工作。你要在烟囱式架构里实现同样的功能得同时维护空间数据库比如PostGIS、向量数据库Milvus和关系数据库光是数据同步就够你受的。RDMA绕过操作系统内核直接在网卡之间传数据延迟特别低在集群节点间通信和客户端与数据库服务器通信的场景下效果显著。在架构层面KES支持集中分布式一体化。集中式集群有读写分离集群和共享存储集群分布式集群有高扩展分布式集群、事务型透明分布式集群和分析型分布式集群。你可以根据数据量和并发需求选择合适的部署形态而且这些形态之间不是割裂的——KES的设计目标是让数据和应用在不同架构之间平滑迁移。我看了一下KES和Oracle 23ai在向量能力上的对比有几个地方挺有意思的。在数据类型上KES支持float32和float16稠密向量Oracle 23ai支持int8、float32、float64还有二进制位向量。在距离运算上两边支持的类型基本一致欧氏距离、余弦距离、内积、汉明距离、曼哈顿距离都有。但有个关键区别KES的HNSW索引建好之后支持新向量的插入和删除Oracle 23ai的HNSW索引建好之后不支持新向量的插入删除。对于数据持续写入的AI应用来说这个区别影响很大——你总不能每次加数据都重建索引吧。还有一个区别是KES支持向量的等值比较和大小比较向量可以作为key使用Oracle 23ai不支持。这些细节在实际工程中都会影响架构选型。嵌入模型导入和大模型缓存聊RAG的时候有个环节我上篇没展开就是embedding模型怎么跟KES配合。很多人以为向量数据库只负责存和查embedding必须在应用层做完再写进来。其实KES支持把ONNX格式的模型直接导进数据库里在库内完成文本转向量的过程。这个能力听起来不起眼实际用起来挺方便的。你不用在应用服务器上跑一个embedding服务也不用管模型加载和GPU资源调度直接在SQL里调用-- 先把ONNX模型导入数据库SELECTimport_onnx_model(bge_large_zh,/path/to/bge-large-zh-v1.5.onnx);-- 在SQL里直接把文本转向量SELECTid,chunk_text,embed_text(bge_large_zh,chunk_text)ASembeddingFROMdocumentsWHEREid123;-- 甚至可以直接用自然语言查询做检索SELECTid,chunk_textFROMdoc_chunksORDERBYembeddingembed_text(bge_large_zh,KES V8R6安装要求)LIMIT5;这样你连应用层的embedding调用都省了数据库直接吃文本吐结果。当然这个能力适合什么场景要看你的算力情况。如果你的KES服务器CPU资源充足、查询QPS不高库内embedding完全够用架构还简单。但如果是高并发场景embedding计算会消耗数据库CPU这时候把embedding放在应用层或者单独的推理服务上可能更合理。技术选型嘛从来没有银弹。除了RAG向量数据库在大模型应用里还有一个挺重要的场景——大模型响应缓存也叫GPTCache。这个场景的逻辑很简单用户问了一个问题如果之前有人问过类似的注意是类似不是完全相同直接把缓存的回答返回不用再调大模型既省算力又降延迟。-- LLM响应缓存表CREATETABLEllm_response_cache(id BIGSERIALPRIMARYKEY,query_textTEXTNOTNULL,query_vector vector(1024),response_textTEXTNOTNULL,model_nameVARCHAR(100),hit_countINTDEFAULT1,created_atTIMESTAMPDEFAULTCURRENT_TIMESTAMP,last_accessedTIMESTAMPDEFAULTCURRENT_TIMESTAMP);CREATEINDEXONllm_response_cacheUSINGhnsw(query_vector vector_cosine_ops);-- 先查缓存找语义相似度大于0.95的历史问答SELECTresponse_text,hit_countFROMllm_response_cacheWHERE1-(query_vectorembed_text(bge_large_zh,:user_query))0.95ORDERBYquery_vectorembed_text(bge_large_zh,:user_query)LIMIT1;这个在热点问题场景下效果特别明显。比如客服系统80%的用户问的都是那20%的常见问题。有了语义缓存这些重复问题直接毫秒级返回不用花几百毫秒到几秒去调大模型推理。我之前算过一笔账一个日活10万的问答系统上语义缓存之后大模型调用量降了60%多每个月省的推理费用相当可观。而且缓存逻辑放在KES里还有个好处你可以在缓存命中的同时做权限校验和安全审计。比如同一个问题不同部门的用户看到的回答可能不一样你可以在缓存表上加部门字段检索的时候一起过滤。在专用缓存方案里这种逻辑你得自己在应用层实现。真实落地案例某央企的智能体建设说了这么多技术细节聊一个我接触到的真实案例。某央企通过KES向量数据库构建知识库支撑OA智能问答、AI开发平台等智能体上线。这个企业之前的架构跟我前面描述的烟囱式差不多——业务数据在KES里文档在一个文档管理系统里搜索引擎用的是Elasticsearch之前试过去Milvus做向量检索但运维成本太高一直没上生产。后来他们决定直接在KES里加向量能力把文档切片、向量化、混合检索全放在一个库里做。落地的效果有几个方面。一是数据资产利用率显著提高。以前员工找资料得在OA系统里翻目录、搜关键词搜不到就问同事。现在直接在智能问答里描述问题系统从知识库中检索相关内容并生成回答检索准确率比之前的关键词搜索高了不少。二是AI开发平台的开发效率提升了开发者可以直接用SQL做向量检索不用再学一套新的查询语法也不用维护多套数据库。三是安全性有保障。KES的三权分立、透明加密、安全审计这些能力直接复用到向量数据上满足央企的合规要求。这个案例给我最大的启发是很多企业不是不想用AI而是被AI架构的复杂度吓到了。一套大模型加一套向量数据库加一套文档数据库加一套缓存运维团队还得学新技术栈出了问题不知道找谁。一体化架构最大的价值不是性能多强而是降低了使用门槛——你已有的KES运维经验、安全体系、高可用方案全部可以复用到AI场景。DeepSeek私有化部署中的向量角色今年年初DeepSeek爆火的时候很多企业都在搞私有化部署。我也参与了几个相关项目这里面向量数据库扮演的角色值得说说。DeepSeek这类大模型私有化部署之后面临三个核心挑战。第一个是幻觉问题。DeepSeek R1在Vectara HHEM 2.1测试中的幻觉率是14.3%是V3版本3.9%的3.67倍远超行业平均水平。R1用的强化学习加思维链架构在数学推理上确实强MATH-500基准测试准确率能到71%的SOTA水平但分步推理机制也让模型更容易在假设性陈述中产生幻觉。第二个是知识匮乏。大模型的训练数据有范围和时效限制你的企业内部文档、最新的业务规则、私有的操作规程这些模型在训练时根本没见过。而且企业不可能把这些私有数据拿去训练公开模型——数据安全不允许。第三个就是数据安全。把私域数据、问答数据、用户信息暴露给公开模型风险太大。即使是私有化部署如果数据散落在多个系统里安全管控也是个大问题。向量数据库解决这些问题的思路是RAG。把企业私域文档切片转成向量存起来用户提问时先检索相关片段再让大模型基于这些片段生成回答。这样大模型不需要记住所有知识它只需要理解检索到的内容并组织成自然语言回答。幻觉问题通过基于事实生成来缓解知识更新通过实时导入新文档来解决数据安全通过数据库层面的访问控制和加密来保障。在KES里做这件事的好处是你的私域数据始终在KES的安全体系内——身份鉴别、访问控制、传输加密、存储加密、脱敏、审计一个不少。而且你不需要把数据搬到一个单独的向量数据库里减少了一个数据泄露的风险面。我见过一些团队的做法是私有化部署DeepSeek之后把RAG的检索层也放在KES里。文档导入时自动切片、向量化、写入KES用户提问时应用层调用embedding模型把问题转向量在KES里做带权限控制的混合检索拿到相关片段后拼进prompt送给DeepSeek生成回答。整个链路只经过KES和DeepSeek两个组件架构简单安全可控。关于性能基准数据最后聊点硬指标。我知道很多人选型的时候最关心性能数据。根据资料中的TSBS基准测试结果在大规模场景下KES向量检索的写入性能是InfluxDB的2.67倍复杂查询快2到70倍。亿级向量数据可以做到毫秒级召回索引性能领先友商大约20%。不过我对基准测试数据一贯持保留态度。不同测试场景、不同数据分布、不同参数配置下结果可能差很多。比如IVFFLAT的lists参数和probes参数、HNSW的m和ef_construction参数对性能和准确率影响都很大。建议大家在选型的时候拿自己的真实数据跑一遍别光看benchmark。我自己的体感是在千万级到亿级向量、1024维以内、top10到top50的检索场景下KES的HNSW索引P99延迟在5到20毫秒这个范围完全能满足大部分AI应用的在线检索需求。加上混合检索和权限过滤之后端到端延迟一般在50毫秒以内这个表现放到生产环境是够用的。写在最后上下两篇一起我尽量把自己用KingbaseES做AI应用的真实体验都写出来了。从上篇聊的烟囱式架构痛点、向量数据库概念、融合架构设计到这篇聊的RAG落地、混合检索、MCP Server、真实案例我想表达的核心观点其实就一个AI应用的数据层不应该是一堆专用数据库的拼装而应该是一个统一的、多模融合的数据平台。