为了账号安全,请及时绑定邮箱和手机立即绑定

掌握RAG:网络爬虫抓取信息的RAG应用技巧

将检索增强生成(RAG)应用于网络爬虫获取的信息,涉及将网络爬虫与高级AI模型相结合,从海量在线数据中提取、处理并生成有意义的信息。网络爬虫可以从互联网上的各种来源收集结构化和非结构化数据,而RAG模型通过检索相关信息并生成连贯且上下文感知的响应,进一步增强这些数据。这种方法使得能够高效地导航和解释大型数据集的智能系统得以创建,为用户提供针对其特定查询量身定制的洞察性和高质量结果。

导入设置:

     导入 os  

    from dotenv import load_dotenv  
    from langchain.text_splitter import CharacterTextSplitter  
    from langchain_community.document_loaders import WebBaseLoader  
    from langchain_community.vectorstores import Chroma  
    from langchain_openai import OpenAIEmbeddings

代码开始时导入了必要的库。这些库包括用于处理环境变量的处理、将文本分割成可管理块、加载网页数据以及使用向量存储来管理嵌入。

加载环境设置:

# 从 `.env` 文件加载环境变量  
load_dotenv()

从 .env 文件中加载环境变量。这有助于安全存储 API 密钥或其他配置信息。

定义持久目录如下:

    # 定义持久化目录如下:
    current_dir = os.path.dirname(os.path.abspath(__file__))  # 获取当前目录的绝对路径
    db_dir = os.path.join(current_dir, "db")
    persistent_directory = os.path.join(db_dir, "chroma_db_apple")  # 持久化路径

创建用于存储数据的目录,确保应用程序能持久保存向量数据。

从网站上获取内容:

    # 第一步:
    # 使用 WebBaseLoader 从 apple.com 抓取网页内容
    # WebBaseLoader 用于加载网页并提取内容
    urls = ["https://www.apple.com/"]

    # 创建一个加载器来加载网页内容
    loader = WebBaseLoader(urls)
    documents = loader.load()  # 加载完成后保存为 documents

使用网页加载器(WebBaseLoader)从 Apple 网站抓取后加载内容。这些内容存储在名为 documents 的变量中,以便后续处理。

    # 步骤 2:将抓取的内容分割成段落  
    # CharacterTextSplitter 将文本分割成较小的块  
    text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)  
    docs = text_splitter.split_documents(documents)  

    # 显示分割后的文档信息  
    print("\n--- 分割文档信息 ---")  
    print(f"文档段落的数量:{len(docs)}")  
    print(f"示例段落:\n{docs[0].page_content}\n")

网站上的内容使用 CharacterTextSplitter 切分成更小且易于管理的小块,这使得处理和索引变得更简单。脚本还会输出这些块的信息。

为文档片段创建嵌入向量。

    # 步骤三:为文档的部分内容创建嵌入
    # OpenAIEmbeddings 可以将文本转换成捕捉语义意义的数值向量
    embeddings = OpenAIEmbeddings(model="text-embedding-3-small")

将文本块转换为数值向量,使用OpenAIEmbeddings。这些嵌入捕捉了文本的语义,使后续搜索更容易进行。

创建并向持久化向量数据库

    # 步骤4:Chroma 保存嵌入以实现高效的搜索
    # Chroma 存储嵌入以实现高效的搜索
    if not os.path.exists(persistent_directory):  
        print(f"\n--- 在 {persistent_directory} 创建向量存储库 ---")  
        db = Chroma.from_documents(docs, embeddings, persist_directory=persistent_directory)  
        print(f"--- 在 {persistent_directory} 创建完成 ---")  
    else:  
        print(f"向量存储 {persistent_directory} 已存在,无需初始化。")  
        db = Chroma(persist_directory=persistent_directory, embedding_function=embeddings)

检查向量数据库目录是否存在。如果不存在,则创建一个新的向量数据库文件夹,将文档的嵌入向量保存到指定目录。如果已存在,则加载现有的向量数据库文件夹。

查询向量数据库的内容:

    # 步骤5:查询向量库
    # 定义检索器,用于基于相似度搜索向量库
    retriever = db.as_retriever(  
        search_type="相似度",  
        search_kwargs={"k": 3},  
    )  

    # 定义用户的问题
    query = "苹果官网最近发布了哪些新产品?"  

    # 检索相关文档
    relevant_docs = retriever.invoke(query)  # 调用检索器根据查询获取相关文档

创建一个可以基于相似度搜索向量存储的检索器。然后,该脚本用特定的问题查询向量存储,并获取最相关的文档片段。

显示相关的结果:

    # 显示带有元数据信息的相关文件  
    print("\n--- 相关文件 ---")  
    for i, doc in enumerate(relevant_docs, 1):  
        print(f"文档编号 {i}:\n{doc.page_content}\n")  
        if doc.metadata:  
            print(f"来源: {doc.metadata.get('source', '未指定')}\n")

展示查询结果,包括相关文档的内容及其元数据,例如文档的来源。

此代码提供了一个完整的流程,用于抓取网络内容,将内容切分成块,生成嵌入,将嵌入存储在向量数据库中,然后根据用户提问查询存储以获取相关信息。

请看下面完整代码。

    从 dotenv 导入 load_dotenv()  
    从 langchain.text_splitter 导入 CharacterTextSplitter  
    从 langchain_community.document_loaders 导入 WebBaseLoader  
    从 langchain_community.vectorstores 导入 Chroma  
    从 langchain_openai 导入 OpenAIEmbeddings  

    # 从 .env 文件加载环境变量  
    load_dotenv()  

    # 定义持久化目录  
    current_dir = os.path.dirname(os.path.abspath(__file__))  
    db_dir = os.path.join(current_dir, "db")  
    persistent_directory = os.path.join(db_dir, "chroma_db_apple")  

    # 第一步:使用 WebBaseLoader 从 apple.com 抓取内容  
    # WebBaseLoader 加载网页并提取其内容  
    urls = ["https://www.apple.com/"]  

    # 创建网页内容加载器  
    loader = WebBaseLoader(urls)  
    documents = loader.load()  

    # 第二步:将抓取的内容分割成块  
    # CharacterTextSplitter 将文本分割成更小的块  
    text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)  
    docs = text_splitter.split_documents(documents)  

    # 显示分割文档的信息  
    print("\n--- 文档块信息 ---")  
    print(f"文档块数量: {len(docs)}")  
    print(f"示例块:\n{docs[0].page_content}\n")  

    # 第三步:为文档块创建嵌入向量  
    # OpenAIEmbeddings 将文本转换为捕捉语义意义的数值向量  
    embeddings = OpenAIEmbeddings(model="text-embedding-3-small")  

    # 第四步:创建并持久化嵌入向量存储  
    # Chroma 存储嵌入向量以实现高效的搜索  
    if not os.path.exists(persistent_directory):  
        print(f"\n--- 创建向量存储在 {persistent_directory} ---")  
        db = Chroma.from_documents(docs, embeddings, persist_directory=persistent_directory)  
        print(f"--- 完成创建向量存储在 {persistent_directory} ---")  
    else:  
        print(f"向量存储在 {persistent_directory} 已存在,无需初始化。")  
        db = Chroma(persist_directory=persistent_directory, embedding_function=embeddings)  

    # 第五步:查询向量存储  
    # 创建检索器以查询向量存储  
    retriever = db.as_retriever(  
        search_type="similarity",  
        search_kwargs={"k": 3},  
    )  

    # 定义用户的查询  
    query = "Apple.com 上发布了哪些新产品?"  

    # 根据查询检索相关文档  
    relevant_docs = retriever.invoke(query)  

    # 显示相关结果及其元数据  
    print("\n--- 相关文档 ---")  
    for i, doc in enumerate(relevant_docs, 1):  
        print(f"文档 {i}:\n{doc.page_content}\n")  
        if doc.metadata:  
            print(f"来源: {doc.metadata.get('source', '未知')}\n")

用Firecrawl来爬行

现在让我们来看看如何使用Firecrawl来抓取。你需要在Firecrawl网站上创建一个API密钥,并将它添加到.env文件中。

你可以期待一些改动。

创建向量存储功能:

def 创建向量存储():
    """爬取网站,分割内容,生成嵌入,并保存向量存储。"""
    # 定义FireCrawl API密钥
    api_key = os.getenv("FIRECRAWL_API_KEY")
    if not api_key:
        raise ValueError("环境变量FIRECRAWL_API_KEY未设置或为空")

    # 使用FireCrawlLoader爬取网页
    print("开始爬取网站...")
    loader = FireCrawlLoader(
        api_key=api_key, url="https://apple.com", mode="抓取")
    docs = loader.load()
    print("完成网页爬取。")

其余代码步骤保持不变。我们现在用Firecrawl来运行整个代码,完整的代码如下。

    从 dotenv 导入 load_dotenv()  
    从 langchain.text_splitter 导入 CharacterTextSplitter  
    从 langchain_community.document_loaders 导入 FireCrawlLoader  
    从 langchain_community.vectorstores 导入 Chroma  
    从 langchain_openai 导入 OpenAIEmbeddings  

    # 从 .env 加载环境变量  
    load_dotenv()  

    # 定义持久化目录  
    current_dir = os.path.dirname(os.path.abspath(__file__))  
    db_dir = os.path.join(current_dir, "db")  
    persistent_directory = os.path.join(db_dir, "chroma_db_firecrawl")  

    def create_vector_store():  
        """使用 FireCrawlLoader 爬取网站,分割内容,创建嵌入,并持久化向量存储"""  
        # 定义 FireCrawl API 密钥  
        api_key = os.getenv("FIRECRAWL_API_KEY")  
        if not api_key:  
            raise ValueError("环境变量 FIRECRAWL_API_KEY 未设置: ")  

        # 步骤1:使用 FireCrawlLoader 爬取网站:  
        print("开始爬取网站...")  
        loader = FireCrawlLoader(  
            api_key=api_key, url="https://apple.com", mode="scrape")  
        docs = loader.load()  
        print("完成网站爬取。")  

        # 将元数据值转换为字符串,如果它们是列表:  
        for doc in docs:  
            for key, value in doc.metadata.items():  
                if isinstance(value, list):  
                    doc.metadata[key] = ", ".join(map(str, value))  

        # 步骤2:将爬取的内容分割成块  
        text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)  
        split_docs = text_splitter.split_documents(docs)  

        # 显示分割文档的信息:  
        print("\n--- 文档块信息 ---")  
        print(f"文档块数量: {len(split_docs)}")  
        print(f"样本块:\n{split_docs[0].page_content}\n")  

        # 步骤3:为文档块创建嵌入:  
        embeddings = OpenAIEmbeddings(model="text-embedding-3-small")  

        # 步骤4:使用嵌入创建并持久化向量存储:  
        print(f"\n--- 在 {persistent_directory} 创建向量存储 ---")  
        db = Chroma.from_documents(  
            split_docs, embeddings, persist_directory=persistent_directory  
        )  
        print(f"--- 在 {persistent_directory} 完成向量存储的创建 ---")  

    # 检查 Chroma 向量存储是否已经存在  
    if not os.path.exists(persistent_directory):  
        create_vector_store()  
    else:  
        print(  
            f"向量存储 {persistent_directory} 已经存在。无需初始化。")  

    # 加载带有嵌入的向量存储:  
    embeddings = OpenAIEmbeddings(model="text-embedding-3-small")  
    db = Chroma(persist_directory=persistent_directory,  
                embedding_function=embeddings)  

    # 步骤5:查询向量存储:  
    def query_vector_store(query):  
        """使用指定的问题查询向量存储: """  
        # 为查询向量存储创建检索器:  
        retriever = db.as_retriever(  
            search_type="similarity",  
            search_kwargs={"k": 3},  
        )  

        # 基于查询检索相关文档:  
        relevant_docs = retriever.invoke(query)  

        # 显示相关结果及其元数据:  
        print("\n--- 相关文档 ---")  
        for i, doc in enumerate(relevant_docs, 1):  
            print(f"文档 {i}:\n{doc.page_content}.\n")  
            if doc.metadata:  
                print(f"来源: {doc.metadata.get('source', '未知')}.\n")  

    # 定义用户的查询:  
    query = "Apple Intelligence?"  

    # 使用用户的查询查询向量存储:  
    query_vector_store(query)

参考文献: 如下

  1. https://python.langchain.com/v0.1/docs/modules/data_connection/document_transformers/?source=post_page-----3225af44e7ea--------------------------------

  2. 文本嵌入文档

3. Python语言链文档 - 聊天集成

4. 布兰登·汉考克的《langchain大师课程》页面 https://brandonhancock.io/langchain-master-class

5、https://platform.openai.com/docs/guides/embeddings/what-are-embeddings 关于嵌入式的介绍

  1. LangChain Python文档中的数据连接检索器模块

7.https://python.langchain.com/v0.2/docs/integrations/document_loaders/web_base/

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消