说在前面

大模型应用,尤其是RAG技术十分火热,通过实现一个简单的RAG应用,可以帮助我们更好的理解这门技术,也能更好的理解使用过程中可能得一些局限性,目前实现了一个最基础的版本:

读取本地文件,入库,然后检索。

技术选型

开发框架:
langchain

嵌入模型:
text-embedding-v4

数据库
chroma

准备

申请百炼大模型的api-key,新用户一般都会赠送一些的,足够日常测试用了
准备几个需要向量化的文档,比如markdownpdf,不要是扫描件,需要可复制的那种。

代码

说几个注意的点:

  • 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 UnstructuredMarkdownLoader

import 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 = 10
    for 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 DashScopeEmbeddings

from 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()

通过打印的内容,可以发现已经将三个最相关的片段检索出来了。

说到最后

以上。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐