☰
第三单元 —— 第三课:持续运行的 RAG 问答程序
2026/10/3 13:00:52 网站建设 项目流程

上课程序运行慢在三个环节:

  1. 加载本地 Embedding 模型
    每次执行脚本都会启动新的 Python 进程,并把 BGE 模型从磁盘加载到内存。模型虽然已经缓存,不再重复下载,但仍需重新加载。

  2. 重新生成知识库向量
    InMemoryVectorStore每次启动都会重新计算资料的向量。当前只有三条资料,影响较小;资料很多时会明显变慢。

  3. 等待 DeepSeek 网络响应
    检索结束后还需要调用一次 DeepSeek API,速度受网络和服务状态影响。

上一课运行时,HF_TOKEN是下载限速提示,不是错误。模型已缓存后,可以避免联网检查:

embeddings = HuggingFaceEmbeddings( model_name="BAAI/bge-small-zh-v1.5", model_kwargs={ "device": "cpu", "local_files_only": True, }, encode_kwargs={"normalize_embeddings": True}, )

实际项目不会为每个问题重新启动脚本,而是:

程序启动一次 → 加载模型一次 → 建立向量库一次 → 连续回答多个问题

因此第一次启动可能较慢,但同一程序中的后续提问会快很多。

这一课可以把它改造成一个持续运行的知识库聊天程序。所以本课目标:Embedding 模型和向量库只初始化一次,然后连续回答问题。

保存为unit3_lesson3_rag_chat.py:

import os import time from langchain_openai import ChatOpenAI from langchain_huggingface import HuggingFaceEmbeddings from langchain_core.vectorstores import InMemoryVectorStore from langchain_core.prompts import ChatPromptTemplate from langchain_core.output_parsers import StrOutputParser start_time = time.perf_counter() # 1. 知识库 texts = [ "星河书店的注册用户,也称为会员,购买图书可以享受九折优惠。", "星河书店周一至周五营业到晚上八点。", "星河书店周六和周日营业到晚上十点。", "星河书店支持七天内凭购物小票退货。", ] # 2. 加载已经下载到本地的 Embedding 模型 embeddings = HuggingFaceEmbeddings( model_name="BAAI/bge-small-zh-v1.5", model_kwargs={ "device": "cpu", "local_files_only": True, }, encode_kwargs={"normalize_embeddings": True}, ) # 3. 建立向量库和检索器 vector_store = InMemoryVectorStore.from_texts( texts=texts, embedding=embeddings, ) retriever = vector_store.as_retriever( search_kwargs={"k": 1} ) # 4. 创建回答链 model = ChatOpenAI( model="deepseek-v4-flash", base_url="https://api.deepseek.com", api_key=os.environ["DEEPSEEK_API_KEY"], ) prompt = ChatPromptTemplate.from_template(""" 请根据资料简洁回答问题。 可以识别常见的同义表达,但不能添加资料中没有的事实。 找不到答案时,请回答“资料中没有相关信息”。 资料: {context} 问题: {question} """) answer_chain = prompt | model | StrOutputParser() initialization_time = time.perf_counter() - start_time print(f"初始化完成,耗时 {initialization_time:.2f} 秒。") print("输入 exit 可以结束程序。") # 5. 持续接收问题 while True: question = input("\n你:").strip() if question.lower() == "exit": print("程序已结束。") break if not question: continue question_start = time.perf_counter() documents = retriever.invoke(question) context = "\n".join( document.page_content for document in documents ) answer = answer_chain.invoke({ "context": context, "question": question, }) question_time = time.perf_counter() - question_start print("检索资料:", context) print("AI:", answer) print(f"本次耗时:{question_time:.2f} 秒")

运行:

.venv\Scripts\activate python unit3_lesson3_rag_chat.py

可以连续测试:

会员买书有优惠吗? 周日几点关门? 买书后可以退货吗? 书店提供送货服务吗? exit

这次 Embedding 模型只在程序启动时加载一次。后续每个问题主要耗时会来自 DeepSeek API,而不是重复加载本地模型。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询