langchain+通义千问,实现简单地RAG应用
说在前面
大模型应用,尤其是RAG技术十分火热,通过实现一个简单的RAG应用,可以帮助我们更好的理解这门技术,也能更好的理解使用过程中可能得一些局限性,目前实现了一个最基础的版本:
读取本地文件,入库,然后检索。
技术选型
开发框架:
langchain
嵌入模型:
text-embedding-v4
数据库
chroma
准备
申请百炼大模型的api-key
,新用户一般都会赠送一些的,足够日常测试用了
准备几个需要向量化的文档,比如markdown
,pdf
,不要是扫描件,需要可复制的那种。
代码
说几个注意的点:
TONGYI_API_KEY
是要定义在.env
文件中的embedding
模型,langchain
对阿里社区支持还是不错的,如果选择其他不支持的模型,需要自己实现一些关键的方法- 源文件的路径和持久化的路径需要按照实际修改
- 之所以定义
batch_size
并使用for
循环进行入库,是因为嵌入模型最多支持10
行
from langchain_community.embeddings import DashScopeEmbeddings
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.document_loaders import PyMuPDFLoader
from langchain_community.document_loaders import UnstructuredMarkdownLoaderimport os
from dotenv import load_dotenv, find_dotenv
_ = load_dotenv(find_dotenv())
def main():
# 获取folder_path下所有文件路径,储存在file_paths里file_paths = []folder_path = '../../data_base/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])# 遍历文件路径并把实例化的loader存放在loaders里loaders = []texts = []os.environ["DASHSCOPE_API_KEY"] = os.environ["TONGYI_API_KEY"] embedding = DashScopeEmbeddings(model="text-embedding-v4")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))for loader in loaders: texts.extend(loader.load())text = texts[1]print(f"每一个元素的类型:{type(text)}.", #<class 'langchain_core.documents.base.Document'>f"该文档的描述性数据:{text.metadata}", # {'source': '../../data_base/knowledge_db\\prompt_engineering\\3. 迭代优化 Iterative.md'}f"查看该文档的内容:\n{text.page_content[0:]}", sep="\n------\n")# 切分文档,每个块大小为 500 个字符,重叠部分为 50 个字符。text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)split_docs = text_splitter.split_documents(texts)# 定义持久化路径persist_directory = '../../data_base/vector_db/chroma'from langchain_community.vectorstores import Chroma# 分批处理文档batch_size = 10for i in range(0, len(split_docs), batch_size):batch_docs = split_docs[i:i+batch_size]if i == 0:# 第一批文档创建数据库vectordb = Chroma.from_documents(documents=batch_docs,embedding=embedding,persist_directory=persist_directory)else:# 后续批次添加到数据库vectordb.add_documents(batch_docs)if __name__ == "__main__":main()
测试
from langchain_community.embeddings import DashScopeEmbeddingsfrom dotenv import find_dotenv, load_dotenv
from langchain_chroma import Chroma
import os
_ = load_dotenv(find_dotenv())# 1. 设置你的API Key(环境变量方式更安全)
os.environ["DASHSCOPE_API_KEY"] = os.environ["TONGYI_API_KEY"] def main():embedding = DashScopeEmbeddings(model="text-embedding-v4")# 向量数据库持久化路径persist_directory = '../../data_base/vector_db/chroma'# 加载数据库vectordb = Chroma(persist_directory=persist_directory,embedding_function=embedding)question="提供几个设计 Prompt 的技巧"sim_docs = vectordb.similarity_search(question,k=3)print(f"检索到的内容数:{len(sim_docs)}")if __name__ == "__main__":main()
通过打印的内容,可以发现已经将三个最相关的片段检索出来了。
说到最后
以上。