ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

02-M2-切分向量化索引-让机器看懂城市知识

02-M2-切分向量化索引-让机器看懂城市知识 让机器「看懂」城市知识自研切分器 bge 向量化 Chroma 索引M2系列城市管理 Agentic RAG —— 从零搭建城市管理问答系统本篇M2 · 切分器 向量化 索引源码https://gitee.com/Chester_Xue/city-agentic-rag一、为什么有了文档还不够M1 把 13 份 txt 变成了结构化的文档对象。但你要问「暴雨橙色预警该关注哪些弱势群体」机器还是不知道去哪找答案——它需要的是检索能力把问题变成向量在一堆文档块里找出最相关的几段。这就是 M2 的三步流水线加载文档(M1) → 切分块(splitter) → 向量化(embedder) → 入库索引(vectordb)二、第一步切分器splitter.py长文档不能整篇向量化——一是向量模型有长度上限二是问「暴雨」时你要的是「某一段」不是整篇。所以要切成小块。参数块大小 500 字符相邻块重叠 50 字符。重叠为什么必要想象一段话在「橙色预警」和「响应要求」之间被切断后半块就丢了「橙色及以上」这个上下文。重叠 50 字符让相邻块共享一段尾巴关键信息不丢。中文切分的关键不能像英文那样按空格硬切。我的实现是从粗到细的递归切分# 切分优先级空行段落 换行 句号 逗号 分号 顿号 字符_SEPARATORS[\n\n,\n,。,,,、,]def_split_long_text(text,chunk_size,sep):按当前分隔符切分若某片段仍超长则降级到更细一层。iflen(text)chunk_size:return[text]iftextelse[]ifsep:# 字符级兜底return[text[i:ichunk_size]foriinrange(0,len(text),chunk_size)]parts[pforpintext.split(sep)ifp.strip()]iflen(parts)1:# 当前分隔符没命中降级return_split_long_text(text,chunk_size,_SEPARATORS[_SEPARATORS.index(sep)1])result[]forpartinparts:result.extend(_split_long_text(part,chunk_size,_SEPARATORS[_SEPARATORS.index(sep)1]))returnresult优先在句号、段落这些自然断点切语义保持完整只有极长无标点文本才退到字符硬切。每个块继承父文档的元数据并加上块序号{id:weather_002_1,# 父文档 id 块序号content:...,metadata:{dept:气象局,file:预警等级.txt,doc_id:weather_002,# 溯源用chunk_index:1,}}自检1200 字长文切 3 块、每块 ≤500、相邻块重叠验证通过。三、第二步向量化embedder.py机器不懂文字只懂数字。向量化的意思就是把一段文本变成一个 512 维的数字向量语义相近的文本向量距离也近。选型BAAI/bge-small-zh-v1.5——中文效果好、模型仅约 100MB、512 维单机原型完全够用。封装成一个可替换的Embedder类classEmbedder:def__init__(self,model_nameBAAI/bge-small-zh-v1.5):self.model_namemodel_name# 可外部传入替换换更大模型/国产化模型self._modelNone# 懒加载首次 encode 时才真正加载defencode(self,texts):modelself._ensure_model()vectorsmodel.encode(texts,normalize_embeddingsTrue)# 归一化returnvectors.tolist()两个细节懒加载import 时不加载模型第一次 encode 才下载/加载启动快。归一化normalize_embeddingsTrue后向量范数为 1点积即余弦相似度检索更稳定。 国内网络小坑huggingface.co 被墙模型下载会卡死。解法HF_ENDPOINThttps://hf-mirror.com自动走镜像一次下载后缓存到~/.cache/huggingface之后离线可用。四、第三步向量库vectordb.py选 Chroma——轻量、持久化到本地目录、Python API 简单单机原型首选。核心设计按部门分 collection物理隔离。这是项目三大原则之一「数据隔离」的落地# 部门 - collection 名映射DEPT_COLLECTIONS{气象局:weather,应急局:weather,# 气象/应急卫健委:healthcare,120急救中心:healthcare,民政局:civil,12345热线:hotline,}气象局和应急局共用一个 collection同属应急领域但查询时可以精确到部门resultsdb.query(暴雨,top_k3)# 全部门联合检索resultsdb.query(暴雨,top_k3,dept_filter气象局)# 只查气象局五、串联index.pypython-msrc.index--reset[1/4] 加载文档: 13 份 [2/4] 切分文本块: 13 块 [3/4] 已清空旧索引--reset [4/4] 向量化入库: 13 条耗时 14.24s 当前库总块数: 13 持久化目录: /home/chester/code/city-agentic-rag/chroma_db六、验收query(“暴雨”) 前 3 条全来自气象/应急M2 的验收标准是检索相关性——问「暴雨」返回的必须是气象局/应急局的东西db.query(暴雨,top_k3)1. [气象局] 预警等级.txt score0.6366 2. [应急局] 防汛应急响应预案.txt score0.5229 3. [气象局] 预警信号发布规范.txt score0.4677✅ 前三名全是气象/应急。再看几个跨部门查询query(急救资源) → 卫健委、120急救中心 query(低保老人救助) → 民政局 query(积水投诉) → 12345热线全部命中正确部门。检索链路通了。 插曲最初验收没过——因为数据太少全库 6 块气象只有 2 块top_k3 必然带出别的部门。这是 M0 遗留的欠账每部门 ≥3 份数据。补齐数据到 13 份后一次通过。教训向量检索的区分度依赖数据量数据先喂饱再调参。七、下一步机器现在会「找」了。但找回来的是一堆相关片段不是人话回答。下一步 M3检索 大模型生成让系统真正「开口回答」还要标注引用来源。下一篇M3 基础 RAG检索 大模型让系统开口回答落地实测上一篇M1 文档加载器从 txt 到结构化数据系列目录城市管理 Agentic RAG —— 从零搭建城市管理问答系统想了解更专业的内容本文是项目实战记录。如果你对向量检索的原理、bge 模型的训练方法、RAG 的完整技术栈感兴趣欢迎访问我的 CSDN 专栏喵本喵叁肆的 Agentic RAG 实战专栏阅读完整的技术博客系列含可运行代码、架构图与验收标准。
返回列表