当前位置: 首页 > news >正文

llm-universe

1 问题解决

1.1 效果不好

原代码如下:

# #######################################################################
# # 1 数据读取
# # 对于PDF 文档,我们可以使用 LangChain 的 PyMuPDFLoader 来读取知识库的 PDF 文件。
# # PyMuPDFLoader 是 PDF 解析器中速度最快的一种,结果会包含 PDF 及其页面的详细元数据,并且每页返回一个文档。
# # pip install -i https://mirrors.aliyun.com/pypi/simple PyMuPDF
# from langchain_community.document_loaders import PyMuPDFLoader
# # 创建一个 PyMuPDFLoader Class 实例,输入为待加载的 pdf 文档路径
# loader = PyMuPDFLoader("./pumpkin_book.pdf")
# # 调用 PyMuPDFLoader Class 的函数 load 对 pdf 文件进行加载
# pdf_pages = loader.load()
# print(f"载入后的变量类型为:{type(pdf_pages)},",  f"该 PDF 一共包含 {len(pdf_pages)} 页")
# # 载入后的变量类型为:<class 'list'>, 该 PDF 一共包含 196 页
# # 查看第2页内容
# pdf_page = pdf_pages[1]
# print(f"每一个元素的类型:{type(pdf_page)}.", 
#     f"该文档的描述性数据:{pdf_page.metadata}", 
#     f"查看该文档的内容:\n{pdf_page.page_content}", 
#     sep="\n------\n")# ###################################
# # 也可以读markdown文档
# # from langchain_community.document_loaders.markdown import UnstructuredMarkdownLoader
# # loader = UnstructuredMarkdownLoader("../data_base/knowledge_db/prompt_engineering/1. 简介 Introduction.md")
# # md_pages = loader.load()
# ###################################
# #######################################################################
# # 2 数据清洗
# # 读取的pdf文件不仅将一句话按照原文的分行添加了换行符`\n`,
# # 也在原本两个符号中间插入了`\n`,我们可以使用正则表达式匹配并删除掉`\n`。
# import re
# pattern = re.compile(r'[^\u4e00-\u9fff](\n)[^\u4e00-\u9fff]', re.DOTALL)
# pdf_page.page_content = re.sub(pattern, lambda match: match.group(0).replace('\n', ''), pdf_page.page_content)
# # print(pdf_page.page_content)# # 进一步分析数据,我们发现数据中还有不少的`•`和空格,我们使用replace方法去掉即可。
# pdf_page.page_content = pdf_page.page_content.replace('•', '')
# pdf_page.page_content = pdf_page.page_content.replace(' ', '')
# # print(pdf_page.page_content)
# # 在检索时,我们会以 chunk 作为检索的元单位,也就是每一次检索到 k 个 chunk 作为模型可以参考来回答用户问题的知识,这个 k 是我们可以自由设定的。
# # Langchain 中文本分割器都根据 `chunk_size` (块大小)和 `chunk_overlap` (块与块之间的重叠大小)进行分割。
# #######################################################################
# # 3 文档分割
# # 单个文档的长度会超过模型支持的上下文,导致检索到的知识太长超出模型的处理能力,
# # 因此,在构建向量知识库的过程中,需要对文档进行分割,将单个文档按长度或者按固定的规则分割成若干个 chunk,
# # 然后将每个 chunk 转化为词向量,存储到向量数据库中。
# # 在检索时,我们会以 chunk 作为检索的元单位,
# # 也就是每一次检索到 k 个 chunk 作为模型可以参考来回答用户问题的知识,
# # 这个 k 是我们可以自由设定的。
# # 可以按分隔符分割、按字符分割、基于指定的标题分割、按token分割、使用NLTK或者Spacy按句子分割
# ''' 
# * RecursiveCharacterTextSplitter 递归字符文本分割
# RecursiveCharacterTextSplitter 将按不同的字符递归地分割(按照这个优先级["\n\n", "\n", " ", ""]),
#     这样就能尽量把所有和语义相关的内容尽可能长时间地保留在同一位置
# RecursiveCharacterTextSplitter需要关注的是4个参数:# * separators - 分隔符字符串数组
# * chunk_size - 每个文档的字符数量限制
# * chunk_overlap - 两份文档重叠区域的长度
# * length_function - 长度计算函数
# '''
# #导入文本分割器
# from langchain_text_splitters import RecursiveCharacterTextSplitter
# # 知识库中单段文本长度
# CHUNK_SIZE = 500
# # 知识库中相邻文本重合长度
# OVERLAP_SIZE = 50# # 使用递归字符文本分割器
# text_splitter = RecursiveCharacterTextSplitter(
#     chunk_size=CHUNK_SIZE,
#     chunk_overlap=OVERLAP_SIZE
# )
# split_docs = text_splitter.split_documents(pdf_pages)
# print(f"切分后的文件数量:{len(split_docs)}")
# # OVERLAP_SIZE = 100 时可以看到两块的重叠
# # print("-----------------------")
# # print(split_docs[1])
# # print("-----------------------")
# # print(split_docs[2])
# print(f"切分后的字符数(可以用来大致评估 token 数):{sum([len(doc.page_content) for doc in split_docs])}")
# # 不同的业务、不同的源数据,往往需要设定个性化的文档分割方式。因此,在本章,我们仅简单根据 chunk_size 对文档进行分割。
######################################################################
# 4 搭建/使用向量数据库
from ollama_embedding import OllamaEmbeddings
from langchain_community.vectorstores import Chroma
import os
embedding = OllamaEmbeddings()
persist_directory = './chroma'
# 加载文件
# 获取folder_path下所有文件路径,储存在file_paths里
file_paths = []
folder_path = './knowledge_db'
for root, dirs, files in os.walk(folder_path):for file in files:file_path = os.path.join(root, file)file_paths.append(file_path)
print(file_paths[:3])
from langchain_community.document_loaders import PyMuPDFLoader
from langchain_community.document_loaders import UnstructuredMarkdownLoader # pip install "unstructured[all-docs]"
# 遍历文件路径并把实例化的loader存放在loaders里
loaders = []for file_path in file_paths:file_type = file_path.split('.')[-1]if file_type == 'pdf':loaders.append(PyMuPDFLoader(file_path))elif file_type == 'md':loaders.append(UnstructuredMarkdownLoader(file_path))# 下载文件并存储到text
texts = []
for loader in loaders: texts.extend(loader.load())
# text = texts[1]
# print(f"每一个元素的类型:{type(text)}.", 
#     f"该文档的描述性数据:{text.metadata}", 
#     f"查看该文档的内容:\n{text.page_content[0:]}", 
#     sep="\n------\n")from langchain_text_splitters import RecursiveCharacterTextSplitter
# 切分文档
text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
split_docs = text_splitter.split_documents(texts)
# 判断是否已有数据库
if os.path.exists(persist_directory):# 加载已有数据库vectordb = Chroma(persist_directory=persist_directory,embedding_function=embedding)print("加载已有向量数据库")
else:# 新建数据库vectordb = Chroma.from_documents(documents=split_docs,embedding=embedding,persist_directory=persist_directory  # 允许我们将persist_directory目录保存到磁盘上)print("新建向量数据库")
print(f"向量库中存储的数量:{vectordb._collection.count()}")
# 5 向量检索
# Chroma的相似度搜索使用的是余弦距离
# 需要数据库返回严谨的按余弦相似度排序的结果时可以使用`similarity_search`函数。
question="大语言模型"
sim_docs = vectordb.similarity_search(question,k=10)
print(f"检索到的内容数:{len(sim_docs)}")for i, sim_doc in enumerate(sim_docs):print(f"检索到的第{i}个内容: \n{sim_doc.page_content[:200]}", end="\n--------------\n")

最终效果只有第一个检索结果与大模型有关系。原因:deepseek-llm:7b-chat-q4_0 是通用对话模型,不是专用嵌入模型。使用了智谱AI的Embedding模型后,效果明显变好了很多,代码修改部分如下:

from zhipuai_embedding import ZhipuAIEmbeddings
from langchain_community.vectorstores import Chroma
import os
from dotenv import load_dotenv, find_dotenv
_ = load_dotenv(find_dotenv())
embedding = ZhipuAIEmbeddings()
http://www.wuyegushi.com/news/218.html

相关文章:

  • 2025.7.27
  • 切比雪夫距离和曼哈顿距离
  • Godot中用C#脚本自定义信号
  • zookper笔记
  • ABC 416 F
  • 除法取模需使用费马小定理或者欧拉函数
  • LLaMA Factory:一站式大模型微调框架的技术介绍
  • 2025727
  • 读《大道至简》有感
  • Datawhale AI夏令营-DeepSeek数学推理蒸馏:轻量化模型的高效推理优化
  • Windows操作QEMU安装ARM架构的操作系统
  • 34th@202508工作清单@20250726
  • 用 Go 与 Tesseract 构建验证码识别 HTTP 服务
  • CS144 Lab2: TCPReceiver实现全解析
  • windows操作QEMU安装ARM架构操作系统
  • 使用 Go 构建基于 Tesseract 的命令行验证码识别工具
  • SpringCloud微服务架构-Gateway服务网关
  • 暑期生活学习笔记
  • 好的调试
  • 20250726 之所思 - 人生如梦
  • Day15 面向对象编程
  • if语句
  • 使用 Go 调用 Tesseract 实现验证码图片文字提取
  • 最长有效括号子串问题
  • 数组练习试题2
  • 7.26 训练总结
  • AirSim基础使用【Python】
  • 7.25
  • SQLAlchemy
  • GPT-SoVITS初探