AI: 告别过时信息, 用RAG和一份PDF 为LLM打造一个随需更新的“外脑”

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

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

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

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

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

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

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

这个流程可以用下面的 PlantUML 图清晰地表示:

技术实现深度解析

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

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

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

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

python 复制代码
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 模型。这个模型能将文本块转换成一个包含几百个数字的向量,神奇的是,语义上相似的文本块,其对应的向量在多维空间中的距离也更近。

python 复制代码
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 链。

python 复制代码
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 函数将所有部分串联起来,并用一个具体问题来测试系统:

python 复制代码
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

相关推荐
Wendy14411 小时前
【边缘填充】——图像预处理(OpenCV)
人工智能·opencv·计算机视觉
钱彬 (Qian Bin)1 小时前
《使用Qt Quick从零构建AI螺丝瑕疵检测系统》——8. AI赋能(下):在Qt中部署YOLOv8模型
人工智能·qt·yolo·qml·qt quick·工业质检·螺丝瑕疵检测
星月昭铭2 小时前
Spring AI调用Embedding模型返回HTTP 400:Invalid HTTP request received分析处理
人工智能·spring boot·python·spring·ai·embedding
大千AI助手3 小时前
直接偏好优化(DPO):原理、演进与大模型对齐新范式
人工智能·神经网络·算法·机器学习·dpo·大模型对齐·直接偏好优化
ReinaXue3 小时前
大模型【进阶】(四)QWen模型架构的解读
人工智能·神经网络·语言模型·transformer·语音识别·迁移学习·audiolm
静心问道3 小时前
Deja Vu: 利用上下文稀疏性提升大语言模型推理效率
人工智能·模型加速·ai技术应用
小妖同学学AI3 小时前
deepseek+飞书多维表格 打造小红书矩阵
人工智能·矩阵·飞书
阿明观察3 小时前
再谈亚马逊云科技(AWS)上海AI研究院7月22日关闭事件
人工智能
zzywxc7874 小时前
AI 驱动的软件测试革新:框架、检测与优化实践
人工智能·深度学习·机器学习·数据挖掘·数据分析
WSSWWWSSW4 小时前
华为昇腾NPU卡 文生视频[T2V]大模型WAN2.1模型推理使用
人工智能·大模型·音视频·显卡·文生视频·文生音频·文生音乐