Nomic-Embed-Text-V2-MoE实战:构建智能文档检索系统与MySQL集成

news2026/3/29 18:33:28
Nomic-Embed-Text-V2-MoE实战构建智能文档检索系统与MySQL集成1. 引言想象一下你所在的公司有成千上万份产品手册、技术文档和合同文件它们散落在各个文件夹里格式五花八门。当你想找一份关于“如何解决产品X在低温环境下的启动问题”的文档时只能靠记忆里的文件名或者用关键词在文件夹里大海捞针结果往往不尽如人意。传统的全文搜索比如用“低温”、“启动”这些词去搜可能会漏掉那些用了“寒冷环境”、“开机故障”等不同表述的关键文档。这就是我们今天要解决的问题。借助Nomic-Embed-Text-V2-MoE这个强大的文本向量化模型我们可以让计算机真正“理解”文档的含义而不仅仅是匹配关键词。简单来说这个模型能把一段文字比如一个句子、一个段落甚至一整篇文章转换成一串有意义的数字我们称之为“向量”。语义相近的文字它们的向量在数学空间里的“距离”也会很近。这篇文章我就带你一步步搭建一个智能文档检索系统。我们会把散乱的PDF、Word文档里的文字提取出来用Nomic模型把它们变成向量然后和文档的标题、作者、日期这些信息一起存进大家都很熟悉的MySQL数据库里。最后我们还会做一个简单的搜索接口让你用自然语言提问比如“低温启动故障”系统就能把最相关的文档找出来。整个方案的核心就是让MySQL不仅能存结构化数据还能胜任向量相似度搜索这种“智能”任务。2. 为什么选择Nomic-Embed-Text-V2-MoE与MySQL在开始动手之前你可能会有疑问向量模型那么多数据库选择也很多为什么是这对组合Nomic-Embed-Text-V2-MoE这个模型有几个挺实在的优点。首先它的效果很好在衡量向量模型好坏的多个标准测试集上排名都很靠前这意味着它生成的向量能更精准地捕捉语义。其次它支持很长的文本最多能处理8192个token这对应着大约五六千个汉字处理大多数技术文档、报告章节都足够了。最后它采用了“混合专家”架构在保持高性能的同时对计算资源的要求相对友好部署起来没那么吃力。那为什么用MySQL来存向量呢最大的好处是“简单统一”。很多公司的业务数据早就存在MySQL里了开发团队对它的运维、备份、查询优化都非常熟悉。如果把文档的向量和它们的元数据比如文件名、创建时间、所属部门分开存在两种数据库里查询时会非常麻烦需要跨库关联性能和维护都是挑战。现在我们可以把向量当作一种特殊类型的数据和传统的业务数据放在同一张表里所有查询都可以用标准的SQL来完成架构一下子变得清爽很多。当然专门的向量数据库在极致性能和大规模向量检索上有优势。但对于很多中小型项目或者作为现有业务系统的一个智能增强模块来说基于MySQL的方案能以最小的架构改动和运维成本快速实现一个效果不错的智能检索功能性价比非常高。3. 系统搭建从环境准备到数据入库接下来我们进入实战环节。我会假设你有一台Linux服务器我们从零开始把系统跑起来。3.1 基础环境与MySQL配置首先确保你的服务器上安装了Python。然后我们需要一个能运行Nomic模型的推理环境。这里推荐使用Ollama它能让模型部署和调用变得非常简单。# 安装Ollama curl -fsSL https://ollama.com/install.sh | sh # 拉取Nomic-Embed-Text-V2-MoE模型 ollama pull nomic-embed-text模型就绪后我们来处理数据库。你需要安装MySQL服务器。如果你还没有安装可以参考下面的步骤# 以Ubuntu为例安装MySQL服务器 sudo apt update sudo apt install mysql-server -y # 启动MySQL服务并设置开机自启 sudo systemctl start mysql sudo systemctl enable mysql # 运行安全安装脚本设置root密码等 sudo mysql_secure_installation安装完成后登录MySQL为我们这个项目创建一个专用的数据库和用户。-- 登录MySQL假设root密码已在安全设置时配置 mysql -u root -p -- 创建数据库 CREATE DATABASE smart_doc_search CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- 创建专用用户并授权 CREATE USER doc_search_userlocalhost IDENTIFIED BY YourSecurePassword123; GRANT ALL PRIVILEGES ON smart_doc_search.* TO doc_search_userlocalhost; FLUSH PRIVILEGES; -- 切换到新建的数据库 USE smart_doc_search;3.2 设计存储向量和文档的数据表数据库准备好了我们来设计核心的数据表。这张表需要存储文档的原始信息、处理后的纯文本以及最重要的——文本向量。CREATE TABLE documents ( id INT AUTO_INCREMENT PRIMARY KEY, file_name VARCHAR(255) NOT NULL COMMENT 原始文件名, file_path VARCHAR(500) COMMENT 文件存储路径, file_type VARCHAR(10) COMMENT 文件类型如pdf, docx, title VARCHAR(255) COMMENT 文档标题可从元数据或内容提取, author VARCHAR(100) COMMENT 作者, created_date DATE COMMENT 文档创建日期, extracted_text LONGTEXT COMMENT 从文档中提取的纯文本内容, text_vector JSON COMMENT 存储文本向量的JSON数组, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX idx_created_date (created_date), INDEX idx_title (title(50)) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_unicode_ci COMMENT文档及向量存储表;这里有几个关键点extracted_text字段用了LONGTEXT类型足以容纳很长的文档内容。text_vector字段我们使用了JSON类型来存储。Nomic-Embed-Text-V2-MoE生成的向量是一个浮点数列表例如768维JSON格式在MySQL中查询和操作非常灵活。我们为一些常用的过滤字段如日期、标题创建了索引方便后续结合语义搜索进行筛选。3.3 文档处理与向量生成流水线现在我们来编写Python脚本实现从文档到向量入库的自动化流程。这个流程主要分三步提取文本、生成向量、存入数据库。首先安装必要的Python库。pip install pymysql pymupdf python-docx ollama接下来是核心脚本process_document.pyimport os import json import pymysql import pymupdf # PyMuPDF用于处理PDF import docx # python-docx用于处理Word from ollama import embed from typing import List, Optional class DocumentProcessor: def __init__(self, db_config): self.db_config db_config self.connection pymysql.connect(**db_config) def extract_text(self, file_path: str) - Optional[str]: 从PDF或Word文档中提取纯文本 text try: if file_path.endswith(.pdf): doc pymupdf.open(file_path) for page in doc: text page.get_text() elif file_path.endswith((.docx, .doc)): doc docx.Document(file_path) for para in doc.paragraphs: text para.text \n else: print(f不支持的文件格式: {file_path}) return None return text.strip() except Exception as e: print(f提取文本失败 {file_path}: {e}) return None def generate_embedding(self, text: str) - Optional[List[float]]: 调用Ollama服务生成文本向量 if not text or len(text) 10: # 文本太短可能无意义 return None try: # 这里我们截取前6000字符确保不超过模型上下文限制 text_chunk text[:6000] response embed(modelnomic-embed-text, inputtext_chunk) return response[embeddings][0] # 返回向量列表 except Exception as e: print(f生成向量失败: {e}) return None def store_document(self, file_name: str, file_path: str, text: str, vector: List[float], titleNone, authorNone, created_dateNone): 将文档信息和向量存储到MySQL try: with self.connection.cursor() as cursor: sql INSERT INTO documents (file_name, file_path, file_type, title, author, created_date, extracted_text, text_vector) VALUES (%s, %s, %s, %s, %s, %s, %s, %s) file_type os.path.splitext(file_name)[1][1:] # 提取扩展名 cursor.execute(sql, ( file_name, file_path, file_type, title, author, created_date, text, json.dumps(vector) # 向量转为JSON字符串 )) self.connection.commit() print(f文档入库成功: {file_name}) except Exception as e: print(f存储文档失败 {file_name}: {e}) def process_folder(self, folder_path: str): 批量处理一个文件夹下的所有文档 supported_ext [.pdf, .docx, .doc] for root, dirs, files in os.walk(folder_path): for file in files: if any(file.lower().endswith(ext) for ext in supported_ext): full_path os.path.join(root, file) print(f正在处理: {full_path}) # 1. 提取文本 text self.extract_text(full_path) if not text: continue # 2. 生成向量 vector self.generate_embedding(text) if not vector: continue # 3. 存储到数据库 (这里简化了元数据提取实际可解析文件属性) self.store_document( file_namefile, file_pathfull_path, texttext, vectorvector ) if __name__ __main__: # 数据库配置 db_config { host: localhost, user: doc_search_user, password: YourSecurePassword123, database: smart_doc_search, charset: utf8mb4 } processor DocumentProcessor(db_config) # 指定你的文档文件夹路径 docs_folder /path/to/your/documents processor.process_folder(docs_folder) processor.connection.close()运行这个脚本它就会自动扫描指定文件夹下的PDF和Word文档提取文本调用本地的Ollama服务生成向量然后一股脑儿存进MySQL里。到这一步你的“知识库”就有了雏形。4. 实现智能检索让MySQL执行语义搜索数据有了怎么搜呢我们需要在MySQL里计算向量之间的相似度。最常用的方法是余弦相似度。幸运的是MySQL 8.0提供了JSON函数和数学函数我们可以直接用SQL来实现。4.1 向量相似度搜索的SQL实现假设用户输入了一个查询语句“如何解决设备低温启动困难”。我们首先需要把这个查询语句也转换成向量然后在数据库里找和这个向量最“像”的文档向量。下面是一个搜索函数示例def search_documents(query_text: str, top_k: int 5, db_configNone): 根据查询文本在数据库中搜索最相关的文档 # 1. 将查询文本转换为向量 query_vector generate_embedding(query_text) # 复用前面的生成函数 if not query_vector: return [] # 将向量转为JSON字符串用于SQL查询 query_vector_json json.dumps(query_vector) connection pymysql.connect(**db_config) try: with connection.cursor(pymysql.cursors.DictCursor) as cursor: # 2. 使用SQL计算余弦相似度并排序 sql SELECT id, file_name, title, author, created_date, extracted_text, -- 计算余弦相似度 ( SELECT SUM(v1.value * v2.value) FROM JSON_TABLE(text_vector, $[*] COLUMNS (value DOUBLE PATH $)) AS v1 JOIN JSON_TABLE(%s, $[*] COLUMNS (value DOUBLE PATH $)) AS v2 ON v1.rownum v2.rownum ) / ( SQRT( (SELECT SUM(POW(value, 2)) FROM JSON_TABLE(text_vector, $[*] COLUMNS (value DOUBLE PATH $))) ) * SQRT( (SELECT SUM(POW(value, 2)) FROM JSON_TABLE(%s, $[*] COLUMNS (value DOUBLE PATH $))) ) ) AS similarity_score FROM documents WHERE LENGTH(extracted_text) 50 -- 过滤掉内容太短的文档 ORDER BY similarity_score DESC LIMIT %s cursor.execute(sql, (query_vector_json, query_vector_json, top_k)) results cursor.fetchall() return results finally: connection.close()这个SQL语句看起来有点复杂其实原理很简单它把存储的JSON向量和查询向量拆分成一行行的数字然后计算它们的点积和模长最终得到余弦相似度。分数越接近1表示两个向量方向越一致语义越相似。4.2 构建一个简单的检索API为了让其他系统也能方便地调用这个检索能力我们可以用Flask快速搭建一个REST API。from flask import Flask, request, jsonify import pymysql import json app Flask(__name__) # 加载数据库配置 (实际应用中应从环境变量或配置文件中读取) DB_CONFIG { host: localhost, user: doc_search_user, password: YourSecurePassword123, database: smart_doc_search, charset: utf8mb4 } def get_embedding(text): # 这里简化实际应调用Ollama接口 # 假设有一个函数调用ollama.embed pass app.route(/api/search, methods[POST]) def search(): data request.json query data.get(query, ) top_k data.get(top_k, 5) if not query: return jsonify({error: 查询内容不能为空}), 400 # 生成查询向量 query_vector get_embedding(query) if not query_vector: return jsonify({error: 向量生成失败}), 500 # 执行搜索这里调用上面实现的search_documents函数或类似逻辑 results search_documents(query, top_k, DB_CONFIG) # 格式化返回结果 formatted_results [] for r in results: formatted_results.append({ id: r[id], title: r[title] or r[file_name], author: r[author], score: round(r[similarity_score], 4), snippet: r[extracted_text][:200] ... # 返回文本片段 }) return jsonify({ query: query, count: len(formatted_results), results: formatted_results }) if __name__ __main__: app.run(host0.0.0.0, port5000, debugTrue)启动这个服务后你就可以通过发送一个HTTP POST请求到http://你的服务器IP:5000/api/search来进行智能文档检索了。请求体里带上{query: 你的问题, top_k: 5}就行。5. 性能优化与实践建议当你的文档量从几百份增长到几万份时直接使用上面的SQL进行全表扫描计算相似度速度会变慢。这里有几个优化思路可以帮你提升效率。1. 预计算向量模长上面SQL中每个文档向量的模长SQRT(SUM(POW(value, 2)))在每次查询时都要计算一次。我们可以在入库时就算好存起来。ALTER TABLE documents ADD COLUMN vector_norm FLOAT DEFAULT NULL COMMENT 向量模长; CREATE INDEX idx_vector_norm ON documents(vector_norm); -- 更新历史数据 UPDATE documents SET vector_norm SQRT( (SELECT SUM(POW(value, 2)) FROM JSON_TABLE(text_vector, $[*] COLUMNS (value DOUBLE PATH $))) ) WHERE text_vector IS NOT NULL;这样相似度计算中的分母部分就可以直接用存储的模长省去大量计算。2. 使用近似最近邻搜索对于海量向量比如百万级以上精确计算所有向量的相似度是不现实的。可以考虑使用专门针对MySQL的向量索引插件如果可用或者采用“分桶过滤”的策略先通过关键词或类别等元数据快速筛选出一个较小的候选集比如1000个文档再在这个小集合里进行精确的向量相似度计算。这能极大提升搜索速度。3. 文本预处理与分块策略面对很长的文档比如上百页的PDF直接对整个文档生成一个向量可能丢失细节。一个更好的实践是“分块”。将一篇长文档按章节或固定长度例如每1000字分割成多个文本块为每个块单独生成向量并存储。搜索时先找到最相关的“块”再定位到原文。这样检索粒度更细效果更好。4. 定期更新与监控文档库不是静态的。可以设置一个定时任务定期扫描新增或修改的文档自动处理入库。同时监控向量生成服务的状态和数据库的查询性能确保系统稳定运行。6. 总结走完这一整套流程你会发现构建一个智能文档检索系统并没有想象中那么复杂。核心思路很清晰用强大的开源模型Nomic-Embed-Text-V2-MoE把文本变成有意义的向量然后用最普及的关系型数据库MySQL把它们管起来。这套方案最大的优势在于“平滑集成”。它不需要你推翻现有的技术栈去引入一套全新的、陌生的向量数据库而是巧妙地扩展了MySQL的能力边界。对于很多已经深度依赖MySQL的中小团队或项目来说这是一个风险低、见效快的智能化升级路径。实际用下来效果比单纯的关键词搜索要好上一个档次尤其是处理技术文档、客服问答这种对语义理解要求高的场景。当然它也不是万能的比如在处理极度专业的术语、或者需要多轮对话理解的复杂查询时可能还有提升空间。但这无疑是一个坚实的起点。你可以基于这个基础继续探索更复杂的优化比如结合传统的BM25关键词评分和向量相似度做一个混合搜索或者给搜索结果增加更丰富的过滤和排序维度。希望这个实战指南能帮你打开思路把你从文档的海洋里解放出来。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2462307.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…