有优惠券网站 怎么做代理,中国建筑网建筑通,年收入100万要交多少税,仿站网站源码基于LangChain框架搭建知识库 说明流程1.数据加载2.数据清洗3.数据切分4.获取向量5.向量库保存到本地6.向量搜索7.汇总调用 说明
本文使用openai提供的embedding模型作为框架基础模型#xff0c;知识库的搭建目的就是为了让大模型减少幻觉出现#xff0c;实现起来也很简单知识库的搭建目的就是为了让大模型减少幻觉出现实现起来也很简单假如你要做一个大模型的客服问答系统那么就把历史客服问答数据整理好先做数据处理在做数据向量化最后保存到向量库中就可以了下面文章中只是一个简单工作流程只能用来参考希望对大家有所帮助
流程
上传知识库的文档不限于txt,pdf,markdown等数据格式不同的数据格式用不同的方法来处理文章内仅使用pdf文件做测试
1.数据加载
def load_data():from langchain.document_loaders.pdf import PyMuPDFLoader# 本地pdf文档路径loader PyMuPDFLoader(./knowledge_db/pumkin_book/pumpkin_book.pdf)pdf_pages loader.load()print(f载入后的变量类型为{type(pdf_pages)}, f该 PDF 一共包含 {len(pdf_pages)} 页)pdf_page pdf_pages[1]page_content pdf_page.page_contentprint(f每一个元素的类型{type(pdf_page)}.,f该文档的描述性数据{pdf_page.metadata},f查看该文档的内容:\n{pdf_page.page_content},sep\n------\n)return page_content,pdf_pages2.数据清洗
def clean_data(pdf_content):# 匹配非中文字符和换行符pattern re.compile(r[^\u4e00-\u9fff](\n)[^\u4e00-\u9fff], re.DOTALL)# 将匹配到的换行符替换为空字符串new_pdf_content re.sub(pattern, lambda match: match.group(0).replace(\n, ), pdf_content)# 去除。和空格符号new_pdf_content new_pdf_content.replace(。, ).replace( , )return new_pdf_content3.数据切分
def split_data(pdf_pages,new_pdf_content):* RecursiveCharacterTextSplitter 递归字符文本分割RecursiveCharacterTextSplitter 将按不同的字符递归地分割(按照这个优先级[\n\n, \n, , ])这样就能尽量把所有和语义相关的内容尽可能长时间地保留在同一位置RecursiveCharacterTextSplitter需要关注的是4个参数* separators - 分隔符字符串数组* chunk_size - 每个文档的字符数量限制* chunk_overlap - 两份文档重叠区域的长度* length_function - 长度计算函数from langchain.text_splitter import RecursiveCharacterTextSplitter# 知识库中单段文本长度CHUNK_SIZE 500# 知识库中相邻文本重合长度OVERLAP_SIZE 50# 使用递归字符文本分割器text_splitter RecursiveCharacterTextSplitter(chunk_sizeCHUNK_SIZE,chunk_overlapOVERLAP_SIZE)text_splitter.split_text(new_pdf_content[0:1000])split_docs text_splitter.split_documents(pdf_pages)print(f切分后的文件数量{len(split_docs)})print(f切分后的字符数可以用来大致评估 token 数{sum([len(doc.page_content) for doc in split_docs])})return split_docs4.获取向量
def gpt_config():import httpx# 使用httpx设置代理proxy http://127.0.0.1:8080 # 修改为自己的代理地址proxies {http://: proxy, https://: proxy}http_client httpx.Client(proxiesproxies, verifyTrue)return http_clientdef get_vector(split_docs):# from langchain.embeddings import OpenAIEmbeddingsfrom langchain_openai import OpenAIEmbeddingsfrom langchain.vectorstores.chroma import Chromafrom dotenv import load_dotenv, find_dotenv# 获取key_ load_dotenv(find_dotenv()) # 可注释api_key os.environ.get(OPENAI_API_KEY)http_client gpt_config()# 官网有提供3个embedding模型按需选择embedding OpenAIEmbeddings(modeltext-embedding-3-small,openai_api_keyapi_key,http_clienthttp_client)# 保存路径persist_directory ./vector_db/chromavectordb Chroma.from_documents(documentssplit_docs[:20], # 为了速度只选择前 20 个切分的 doc 进行生成embeddingembedding,persist_directorypersist_directory # 允许我们将persist_directory目录保存到磁盘上)return vectordb5.向量库保存到本地
def save_vector(vectordb):vectordb.persist()print(f向量库中存储的数量{vectordb._collection.count()})6.向量搜索
def search_vector(vectordb):question 什么是机器学习# 余弦相似度搜索search_result vectordb.similarity_search(question, k2) # k表示返回的相似文档数量print(f检索到的内容数{len(search_result)})for i, sim_doc in enumerate(search_result):print(f检索到的第{i}个内容: \n{sim_doc.page_content[:200]}, end\n--------------\n)# MMR搜索# 核心思想是在已经选择了一个相关性高的文档之后再选择一个与已选文档相关性较低但是信息丰富的文档。这样可以在保持相关性的同时增加内容的多样性避免过于单一的结果。mmr_docs vectordb.max_marginal_relevance_search(question, k2)for i, sim_doc in enumerate(mmr_docs):print(fMMR 检索到的第{i}个内容: \n{sim_doc.page_content[:200]}, end\n--------------\n)7.汇总调用
def main_task():# 加载数据pdf_content,pdf_pages load_data()# 数据清洗new_pdf_content clean_data(pdf_content)# 切分数据split_docs split_data(pdf_pages,new_pdf_content)# 获取向量vectordb get_vector(split_docs)# 将向量库内容保存到本地文件中# save_vector(vectordb)# 向量搜索search_vector(vectordb)