嘿,各位技术同学!今天,我们来聊一个大家在使用大语言模型(LLM)时都会遇到的痛点:知识过时

无论是像我一样,用 Gemini Pro 学习日新月异的以太坊,还是希望它能精确掌握某个特定工具的最新用法,我们都可能被它“记忆”里的旧知识所困扰。比如,我让它生成 PlantUML 图时,它偶尔会“穿越”回过去,使用一些已经被废弃的旧语法,这无疑增加了我们的学习和开发成本。

为了解决这个问题,我动手开发了一个小项目:一个基于**检索增强生成(RAG)**的智能问答系统。它能读取最新的官方文档(比如 PlantUML 的语言参考指南),并让 Gemini 模型在回答问题前,先查阅这些最新资料。今天,我就和大家分享这个项目的技术实现,希望能给大家带来一些启发。
在这里插入图片描述

项目核心理念:RAG如何解决问题?

在我们深入代码之前,先花一分钟理解一下 RAG 的工作原理。

想象一下,我们让一位非常聪明的实习生(LLM)写一份报告,但他对某个特定领域的最新进展不太了解。我们会怎么做?我们不会让他凭空想象,而是会把最新的行业报告、研究论文(外部知识库)丢给他,说:“看,根据这些资料来写。”

RAG 就是这个过程的自动化版本。它通过一个“检索”步骤,从我们的知识库(PDF、文档、网站等)中找到与用户问题最相关的信息,然后将这些信息连同原始问题一起打包,交给 LLM,让它基于这些“新鲜出炉”的材料来“生成”答案。

这个流程可以用下面的 PlantUML 图清晰地表示:
在这里插入图片描述

技术实现深度解析

现在,让我们深入 main.py 文件,看看这个 RAG 系统是如何一步步构建起来的。

第一步:知识库的建立与“保鲜”

万丈高楼平地起,我们的第一步是建立一个可靠的知识库。在这个项目中,知识来源于一份PDF文档。但我们做了一个非常实用的优化:自动检测文档更新

代码通过 get_pdf_hash 函数计算 PDF 文件的 SHA256 哈希值。

def get_pdf_hash(file_path):"""计算文件的 SHA256 哈希值"""sha256_hash = hashlib.sha256()with open(file_path, "rb") as f:for byte_block in iter(lambda: f.read(4096), b""):sha256_hash.update(byte_block)return sha256_hash.hexdigest()

load_or_create_vectorstore 函数中,系统启动时会检查持久化目录 chroma_db 中存储的旧哈希值与当前 PDF 文件的哈希值是否一致。

  • 如果一致:太棒了!说明文档没变,直接从磁盘加载已经处理好的向量数据库,秒级启动。
  • 如果不一致或首次运行:说明知识需要更新!系统会自动删除旧的数据库,然后使用 PyPDFLoader 加载新的 PDF,并用 RecursiveCharacterTextSplitter 将其分割成更小的、易于检索的文本块。

这个设计非常关键,它确保了我们的“外脑”永远存储的是最新信息,同时避免了每次运行都重复处理文档的昂贵开销。

第二步:将知识向量化 (Embedding)

计算机不理解文字,只理解数字。为了让机器能够“理解”并比较文本片段的相似度,我们需要将它们转换成向量,这个过程叫做嵌入(Embedding)

我们使用了 HuggingFace 的 sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2 模型。这个模型能将文本块转换成一个包含几百个数字的向量,神奇的是,语义上相似的文本块,其对应的向量在多维空间中的距离也更近。

def setup_embeddings():"""初始化并返回嵌入模型"""print("正在初始化嵌入模型...")embeddings = HuggingFaceEmbeddings(model_name=EMBEDDING_MODEL_NAME,model_kwargs={'device': 'cpu'},encode_kwargs={'normalize_embeddings': False})return embeddings

所有从 PDF 中分割出来的文本块都会经过这个模型处理,然后连同它们的向量表示一起存入 Chroma 向量数据库中。

第三步:搭建检索与生成的核心链

现在,我们有了存储知识的数据库和负责回答问题的 LLM,是时候把它们“链接”起来了。这里我们借助了 LangChain 框架的 RetrievalQA 链。

def create_qa_chain(llm, vectorstore):"""基于LLM和向量数据库创建并返回问答链"""retriever = vectorstore.as_retriever(search_kwargs={"k": 2})qa_chain = RetrievalQA.from_chain_type(llm=llm,chain_type="stuff",retriever=retriever,return_source_documents=True)return qa_chain

这个链条的工作流程如下:

  1. 设置检索器(Retriever)vectorstore.as_retriever(search_kwargs={"k": 2}) 这行代码创建了一个检索器,当用户提问时,它会去 Chroma 数据库中检索出最相似的 k=2 个文档片段。
  2. 选择链类型(Chain Type)chain_type="stuff" 是一种简单直接的策略。它会把检索到的所有文档片段(stuff them)一股脑地塞进一个提示词模板中,和用户的原始问题一起发送给 LLM。
  3. 返回源文档return_source_documents=True 是一个非常有用的调试和验证工具。它让 LLM 在给出答案的同时,也告诉我们它参考了哪些原文片段。这大大增强了结果的透明度和可信度。

实践与效果

一切准备就绪后,main 函数将所有部分串联起来,并用一个具体问题来测试系统:

def main():"""主执行函数,编排整个RAG流程"""embeddings = setup_embeddings()vectorstore = load_or_create_vectorstore(PDF_FILE_PATH, PERSIST_DIRECTORY, embeddings)llm = setup_llm()qa_chain = create_qa_chain(llm, vectorstore)query = "如何绘制 JSON 数据图?"ask_question(qa_chain, query)

当运行这个脚本时,它会:

  1. 初始化模型和向量数据库。
  2. 接收问题 如何绘制 JSON 数据图?
  3. 在数据库中找到关于 JSON 数据可视化的相关片段。
  4. 将这些片段和问题一起发给 Gemini。
  5. Gemini 基于最新的 PlantUML 语法(来自PDF)生成答案,并附上参考来源。

这样,我们就得到了一个既有 Gemini 强大推理能力,又有最新、最准确领域知识的 AI 助手。

实用建议与未来展望

这个项目虽然简单,但扩展性很强:

  1. 更换知识源:我们可以轻易地将 PDF_FILE_PATH 换成任何我们想要的 PDF 文档,比如以太坊的白皮书、某个开源库的API文档,甚至是我们的学习笔记。
  2. 支持更多格式:通过使用 LangChain 提供的其他 DocumentLoader,我们可以让系统读取 .txt, .md 文件,甚至直接爬取网站内容。
  3. 部署为服务:使用 FastAPI 或 Flask 将这个问答系统包装成一个 API 服务,让其他人也能方便地使用。
  4. 优化检索:对于非常大的文档,可以探索更高级的检索策略,如 Parent Document Retriever,以获得更相关的上下文。

结论

通过 RAG,我们为大语言模型安装了一个可随时更新、可定制的“外脑”。这个方法不仅有效解决了 LLM 知识滞后的问题,还通过引入可验证的信源,大大提高了生成内容的可信度。最棒的是,实现这一切的技术门槛并不高。

希望这篇文章能激励大家动手尝试,为自己的学习和工作场景打造一个专属的、永远不会“过时”的AI伙伴。
https://github.com/xilu0/plantuml-agent/blob/main/main.py

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深度学习(鱼书)day08--误差反向传播(后三节)

深度学习(鱼书)day08–误差反向传播(后三节)一、激活函数层的实现 这里,我们把构成神经网络的层实现为一个类。先来实现激活函数的ReLU层和Sigmoid层。ReLU层 激活函数ReLU(Rectified Linear Unit&#xff…

C# 中生成随机数的常用方法

1. 使用 Random 类(简单场景) 2. 使用 RandomNumberGenerator 类(安全场景) 3. 生成指定精度的随机小数 C# 中生成随机数的常用方法: 随机数类型实现方式示例代码特点与适用场景随机整数(无范围&#xf…

Flink 算子链设计和源代码实现

1、JobGraph (JobManager) JobGraph 生成时,通过 ChainingStrategy 连接算子,最终在 Task 中生成 ChainedDriver 链表。StreamingJobGraphGeneratorcreateJobGraph() 构建jobGrapch 包含 JobVertex setChaining() 构建算子链isCha…

对接八大应用渠道

背景最近公司想把游戏包上到各个渠道上,因此需要对接各种渠道,渠道如下,oppo、vivo、华为、小米、应用宝、taptap、荣耀、三星等应用渠道 主要就是对接登录、支付接口(后续不知道会不会有其他的)&#x…

学习:入门uniapp Vue3组合式API版本(17)

42.打包发行微信小程序的上线全流程 域名 配置 发行 绑定手机号 上传 提交后等待,上传 43.打包H5并发布上线到unicloud的前端页面托管 完善配置 unicloud 手机号实名信息不一致:请确保手机号的实名信息与开发者姓名、身份证号一致,请前往开…

SOLIDWORKS材料明细表设置,属于自己的BOM表模板

上一期我们了解了如何在SOLIDWORKS工程图中添加材料明细表?接下来,我们将进行对SOLIDWORKS材料明细表的设置、查看缩略图、模板保存的深度讲解。01 材料明细表设置菜单栏生成表格后左侧菜单栏会显示关于材料明细表的相关设置信息。我们先了解一下菜单栏设置详情&am…

全栈:Maven的作用是什么?本地仓库,私服还有中央仓库的区别?Maven和pom.xml配置文件的关系是什么?

Maven和pom.xml配置文件的关系是什么: Maven是一个构建工具和依赖管理工具,而pom.xml(Project Object Model)是Maven的核心配置文件。 SSM 框架的项目不一定是 Maven 项目,但推荐使用 Maven进行管理。 SSM 框架的项目可…

超越 ChatGPT:智能体崛起,开启全自主 AI 时代

引言 短短三年,生成式 AI 已从对话助手跨越到能自主规划并完成任务的“智能体(Agentic AI)”时代。这场演进不仅体现在模型规模的提升,更在于系统架构、交互范式与安全治理的全面革新。本文按时间线梳理关键阶段与核心技术,为您呈现 AI 智能体革命的脉络与未来趋势。 1. …

一杯就够:让大脑瞬间在线、让肌肉满电的 “Kick-out Drink” 全解析

一杯就够:让大脑瞬间在线、让肌肉满电的 “Kick-out Drink” 全解析“每天清晨,当闹钟还在哀嚎,你举杯一饮,睡意像被扔出擂台——这,就是 Kick-out Drink 的全部浪漫。”清晨 30 分钟后,250 mL 常温水里溶解…

系统开机时自动执行指令

使用 systemd 创建一个服务单元可以让系统开机时自动执行指令,假设需要执行的指令如下,运行可执行文件(/home/demo/可执行文件),并输入参数(–input/home/config/demo.yaml): /home/…

Docker 初学者需要了解的几个知识点 (七):php.ini

这段配置是 php.ini 文件中针对 PHP 扩展和 Xdebug 调试工具的设置,主要用于让 PHP 支持数据库连接和代码调试(尤其在 Docker 环境中),具体解释如下:[PHP] extensionpdo_mysql extensionmysqli xdebug.modedebug xdebu…

【高阶版】R语言空间分析、模拟预测与可视化高级应用

随着地理信息系统(GIS)和大尺度研究的发展,空间数据的管理、统计与制图变得越来越重要。R语言在数据分析、挖掘和可视化中发挥着重要的作用,其中在空间分析方面扮演着重要角色,与空间相关的包的数量也达到130多个。在本…

dolphinscheduler中一个脚本用于从列定义中提取列名列表

dolphinscheduler中,我们从一个mysql表导出数据,上传到hdfs, 再创建一个临时表,所以需要用到列名定义和列名列表。 原来定义两个变量,不仅繁锁,还容易出现差错,比如两者列序不对。 所以考虑只定义列定义变量…

JavaWeb(苍穹外卖)--学习笔记16(定时任务工具Spring Task,Cron表达式)

前言 本篇文章是学习B站黑马程序员苍穹外卖的学习笔记📑。我的学习路线是Java基础语法-JavaWeb-做项目,管理端的功能学习完之后,就进入到了用户端微信小程序的开发,用户端开发的流程大致为用户登录—商品浏览(其中涉及…

灵敏度,精度,精确度,精密度,精准度,准确度,分辨率,分辨力——概念

文章目录前提总结前提 我最近在整理一份数据指标要求的时候,总是混淆这几个概念:灵敏度,精度,精确度,精密度,精准度,准确度,分辨率,分辨力,搜了一些文章&…

python-异常(笔记)

#后续代码可以正常运行 try:f open("xxx.txt","r",encodingutf-8)except:print("except error")#捕获指定异常,其他异常报错程序中止,管不到 try:print(name) except NameError as you_call:print("name error"…

[lvgl_player] 用户界面(LVGL) | 播放器核心设计

docs:基于LVGL的音乐播放器 本项目是为嵌入式设备设计的音乐播放系统,采用LVGL图形库构建用户界面。 系统支持播放WAV格式音频文件,具备播放列表管理功能,可实现播放/暂停控制、曲目切换等核心操作。 用户可通过交互界面实时调…

数据赋能(354)——数据分析——多角度分析原则

概述重要性如下:获得全面理解:多角度分析原则避免仅从单一角度解读数据,从不同角度、不同维度对数据进行分析,以获得更全面的理解。发现潜在规律:通过多角度分析,发现数据中的潜在规律和趋势,为…

【华为机试】127. 单词接龙

文章目录127. 单词接龙描述示例 1:示例 2:提示:解题思路算法分析问题本质分析单向BFS算法详解双向BFS算法详解邻居单词生成过程算法流程图边界情况分析各种解法对比时间复杂度分析空间复杂度分析关键优化点实际应用场景图构建策略双向BFS优化…

仿艾莫迅MODBUS调试工具写一个上位机

公司采购了一个夹具,项目负责人想要试探这个夹具的性能,于是想要我这边写一个烤机的程序,小编结合官网资料 https://wiki.amsamotion.com/?title196&doc222查看其pdf说明文档和调试工具并按照其工具写一个烤机上位机根据项目负责人的要求…