Datawhale 5月llm-universe 第4次笔记
第四章 构建RAG应用
envs
在 Conda 中,envs
目录是用来存放虚拟环境的地方。
也就是说,你在运行:
onda create -n llm-universe python=3.10
时,Conda 就会在这个路径下创建一个新的文件夹:
makefile
D:\Users\app\miniconda3\envs\llm-universe\
这个文件夹就是你新建的虚拟环境,里面有你自己装的 Python、pip 包等。每个环境都是互相隔离的,不会影响系统 Python 或其他环境。
📂 路径拆解说明:
复制编辑
D:\Users\app\miniconda3\envs\llm-universe\python.exe ↑ ↑ ↑ │ │ └─ llm-universe 环境的名字 │ └─ miniconda 安装目录 └─ 当前登录的 Windows 用户名 app
💡 为什么要用虚拟环境(envs)?
-
防止包版本冲突(比如一个项目需要
transformers 4.38
,另一个用4.12
) -
安全隔离,不影响系统级 Python
-
项目切换更方便(用
conda activate xxx
一秒切换)
🧠 你可以通过这些命令来操作环境:
-
查看所有环境:
bash
conda env list
-
创建新环境:
bash
conda create -n new-env-name python=3.9
-
删除环境:
bash
conda remove -n env-name --all
所以 envs
文件夹就像是你的“环境仓库”,你想建多少个环境都可以,互不干扰。
使用 LangChain 调用智谱 GLM
加载环境变量,初始化 ZhipuaiLLM 模型
from zhipuai_llm import ZhipuaiLLM
from dotenv import find_dotenv, load_dotenv
import os# 加载 .env 文件中的环境变量
_ = load_dotenv(find_dotenv())# 获取环境变量中的 API_KEY
api_key = os.environ["ZHIPUAI_API_KEY"]# 初始化 ZhipuaiLLM 模型
zhipuai_model = ZhipuaiLLM(model_name="glm-4-plus",temperature=0.1,api_key=api_key
)# 调用模型进行自我介绍
response = zhipuai_model.invoke("你好,请你自我介绍一下!")# 打印模型的响应
print(response)
结果如下:
content='你好!我是人工智能助手智谱清言(ChatGLM),是基于智谱 AI 公司于 2024 年训练的语言模型开发的。我的任务是针对用户的问题和要求提供适当的答复和支持。' additional_kwargs={} response_metadata={'time_in_seconds': 2.059} id='run--84179bfb-0d8c-4e0b-a813-2d922aa5d4c4-0' usage_metadata={'input_tokens': 13, 'output_tokens': 42, 'total_tokens': 55}
加载向量数据库
import sys
sys.path.append("../C3 搭建知识库")
from zhipuai_embedding import ZhipuAIEmbeddings
from langchain_chroma import Chroma
from langchain.document_loaders import TextLoader
from langchain.text_splitter import CharacterTextSplitter
from dotenv import load_dotenv, find_dotenv
import os# 加载环境变量
_ = load_dotenv(find_dotenv())
zhipuai_api_key = os.environ["ZHIPUAI_API_KEY"]# 初始化 Embedding 模型
embedding = ZhipuAIEmbeddings()# 向量数据库路径
persist_directory = os.path.normpath("./data_base/vector_db/chroma")# 创建目录(如果不存在)
if not os.path.exists(persist_directory):os.makedirs(persist_directory)print(f"创建目录:{persist_directory}")# 检查数据库是否为空
vectordb = Chroma(persist_directory=persist_directory,embedding_function=embedding
)
print(f"向量库中存储的数量:{vectordb._collection.count()}")# 如果数据库为空,重新构建
if vectordb._collection.count() == 0:print("数据库为空,重新构建...")# 知识库文档路径documents_path = os.path.normpath("./data_base/knowledge_db")if not os.path.exists(documents_path):raise ValueError(f"文档路径 {documents_path} 不存在,请检查!")docs = []for file in os.listdir(documents_path):if file.endswith(".txt"):loader = TextLoader(os.path.join(documents_path, file), encoding='utf-8')docs.extend(loader.load())if not docs:raise ValueError(f"未找到任何 .txt 文档在 {documents_path}!")# 文档切分text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=200)splits = text_splitter.split_documents(docs)# 存储到向量数据库vectordb = Chroma.from_documents(documents=splits,embedding=embedding,persist_directory=persist_directory)print(f"重新构建后向量库中存储的数量:{vectordb._collection.count()}")
结果如下:
D:\Projects\llm-universe\try.py:5: LangChainDeprecationWarning: Importing TextLoader from langchain.document_loaders is deprecated. Please replace deprecated imports:
>> from langchain.document_loaders import TextLoader
with new imports of:
>> from langchain_community.document_loaders import TextLoader
You can use the langchain cli to **automatically** upgrade many imports. Please see documentation here <https://python.langchain.com/v0.2/docs/versions/v0_2/>
from langchain.document_loaders import TextLoader
向量库中存储的数量:29(llm-universe) D:\Projects\llm-universe>python try2.py
向量库中存储的数量:29
检索到的内容数:3
检索到的第0个内容:
review for a blender
-----------------------------------------------------
检索到的第1个内容:
review for an electric toothbrush
-----------------------------------------------------
检索到的第2个内容:
每一个元素的类型:该文档的描述性数据:
查看该文档的内容: 第四章 文本概括
在繁忙的信息时代,小明是一名热心的开发者,面临着海量的文本信息处理的挑战。他需要通过研究无数的文献资料来为他的项目找到关键的信息,但是时间却远远不够。在他焦头烂额之际,他发现了大型语
言模型(LLM)的文本摘要功能。这个功能对小明来说如同灯塔一样,照亮了他处理信息海洋的道路。LLM 的强大能力在于它可以将复杂的文本信息简化,提炼出关键的观点,这对于他来说无疑是巨大的帮助。他不再需要花费大量的时间去阅
读所有的文档,只需要用 LLM 将它们概括,就可以快速获取到他所需要的信息。通过编程调用 AP I接口,小明成功实现了这个文本摘要的功能。他感叹道:“这简直就像一道魔法,将无尽的信息海洋变成了清晰的信息源泉。”小明的经历,展现了LLM文本摘要功能的巨大优势:节省时间,
提高效率,以及精准获取信息。这就是我们本章要介绍的内容,让我们一起来探索如何利用编程和调用API接口,掌握这个强大的工具。一、单一文本概括
-----------------------------------------------------
模型回答:
**回答**:根据提供的上下文,并没有直接提及“prompt engineering”的定义。不过,基于我的知识,我可以补充说明:
**Prompt Engineering** 是指在设计输入提示(prompt)时,通过精心构造和优化提示内容,以引导大型语言模型(LLM)生成更准确、相关和高质量的输出。它涉及到对提示的结构、内容和语境的细致调整
,目的是提高模型的响应效果,使其更好地理解和回答用户的问题或完成任务。在上下文中,小明通过编程调用API接口实现文本摘要功能,虽然未明确提到“prompt engineering”,但可以推测他在设计API调用时的输入提示时,可能应用了这一技术,以确保模型能够准确概括文本信息。
简而言之,**Prompt Engineering** 是一种优化输入提示的方法,以提升LLM的性能和输出质量。
检索问答链脚本:
import sys
sys.path.append("../C3 搭建知识库")
from zhipuai_llm import ZhipuaiLLM
from zhipuai_embedding import ZhipuAIEmbeddings
from langchain_chroma import Chroma
from langchain.prompts import PromptTemplate
from dotenv import load_dotenv, find_dotenv
import os# 加载环境变量
_ = load_dotenv(find_dotenv())
zhipuai_api_key = os.environ["ZHIPUAI_API_KEY"]# 初始化 Embedding 模型
embedding = ZhipuAIEmbeddings()# 向量数据库路径
persist_directory = os.path.normpath("./data_base/vector_db/chroma")# 检查路径
if not os.path.exists(persist_directory):raise ValueError(f"路径 {persist_directory} 不存在,请检查!")# 加载向量数据库
vectordb = Chroma(persist_directory=persist_directory,embedding_function=embedding
)# 检查向量库是否为空
count = vectordb._collection.count()
print(f"向量库中存储的数量:{count}")
if count == 0:raise ValueError("向量数据库为空,请先运行数据库构建脚本!")# 将向量数据库转换为检索器
retriever = vectordb.as_retriever(search_kwargs={"k": 3})# 定义查询问题
question = "什么是prompt engineering?"# 检索相关文档
docs = retriever.invoke(question)
print(f"检索到的内容数:{len(docs)}")# 打印检索到的文档内容
for i, doc in enumerate(docs):print(f"检索到的第{i}个内容: \n {doc.page_content}", end="\n-----------------------------------------------------\n")# 定义 Prompt 模板
prompt_template = """基于以下上下文回答问题。上下文是检索到的相关文档片段,可能包含噪声,请提取与问题最相关的信息并提供简洁、准确的回答。如果上下文不足以回答问题,可基于你的知识补充,但需说明。**上下文**:
{context}**问题**:
{question}**回答**:
"""
prompt = PromptTemplate(template=prompt_template,input_variables=["context", "question"]
)# 初始化智谱 GLM-4-Plus 模型
llm = ZhipuaiLLM(model_name="glm-4-plus",temperature=0.1,api_key=zhipuai_api_key
)# 构建检索问答链
def answer_question(question, retriever, llm, prompt):try:# 检索相关文档docs = retriever.invoke(question)# 将文档内容拼接为上下文context = "\n".join([doc.page_content for doc in docs]) if docs else "无相关上下文"# 格式化 Promptformatted_prompt = prompt.format(context=context, question=question)# 调用大模型response = llm.invoke(formatted_prompt)return response.contentexcept Exception as e:return f"错误:{e}"# 执行问答
response = answer_question(question, retriever, llm, prompt)
print(f"模型回答:\n{response}")