【AI大模型应用开发】【LangChain系列】实战案例3:深入LangChain源码,你不知道的WebResearchRetriever与RAG联合之力

这篇具有很好参考价值的文章主要介绍了【AI大模型应用开发】【LangChain系列】实战案例3:深入LangChain源码,你不知道的WebResearchRetriever与RAG联合之力。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

  • 大家好,我是同学小张,日常分享AI知识和实战案例
  • 欢迎 点赞 + 关注 👏,持续学习持续干货输出
  • +v: jasper_8017 一起交流💬,一起进步💪。
  • 微信公众号也可搜【同学小张】 🙏

本站文章一览:

langchain 获取源码,大模型,学习,人工智能,gpt,笔记,经验分享,langchain,agi


上篇文章我们学习了如何利用 LangChain 通过 URL 获取网页内容。本文我们继续学习利用 LangChain 进行网络数据抓取:我们将利用 LangChain 抓取网络数据来回答我们指定的问题(也就是类似 网络 + RAG)。

本文参考教程:https://python.langchain.com/docs/use_cases/web_scraping

0. 环境准备

要想成功运行本文所示的代码,需要做一下准备。

0.1 获取Google API key

首先,需要获取一个 Google API key。

(1)打开链接,登录你的Google账号(没有Google账号的请自行注册):

https://console.cloud.google.com/apis/api/customsearch.googleapis.com/credentials

langchain 获取源码,大模型,学习,人工智能,gpt,笔记,经验分享,langchain,agi

(2)创建一个Project

langchain 获取源码,大模型,学习,人工智能,gpt,笔记,经验分享,langchain,agi

(3)在你创建的 Project 页面(创建完后会自动跳转),点 API key,创建API key即可

langchain 获取源码,大模型,学习,人工智能,gpt,笔记,经验分享,langchain,agi

(4)配置API key到你的代码中:将这个API key放到你的程序 .env 文件中作为环境变量加载。

GOOGLE_API_KEY = "YOUR GOOGLE API KEY"

0.2 获取 Google CSE ID

(1)登录链接,创建一个新的 Search Engine

https://programmablesearchengine.google.com/

langchain 获取源码,大模型,学习,人工智能,gpt,笔记,经验分享,langchain,agi
(2)创建完后,Search engine ID 即为所需的 CSE ID。
langchain 获取源码,大模型,学习,人工智能,gpt,笔记,经验分享,langchain,agi
(3)配置 CSE ID 到你的代码中:将这个 CSE ID 放到你的程序 .env 文件中作为环境变量加载。

GOOGLE_CSE_ID = "xxxxxxx"

0.3 安装依赖Python包

我的安装以下两个基本就够了,因为之前安装过 langchain、openai之类的。

pip install google-api-core==2.11.1
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple google-api-python-client==2.95.0

完整的安装依赖参考:

streamlit==1.25.0
langchain==0.0.244
chromadb==0.4.3
openai==0.27.8
html2text==2020.1.16
google-api-core==2.11.1
google-api-python-client==2.95.0
google-auth==2.22.0
google-auth-httplib2==0.1.0
googleapis-common-protos==1.59.1
tiktoken==0.4.0
faiss-cpu==1.7.4

1. 完整代码及解释

1.1 完整代码

from langchain.retrievers.web_research import WebResearchRetriever
from langchain_community.utilities import GoogleSearchAPIWrapper
from langchain_community.vectorstores import Chroma
from langchain_openai import ChatOpenAI, OpenAIEmbeddings

# Vectorstore
vectorstore = Chroma(
    embedding_function=OpenAIEmbeddings(), persist_directory="./chroma_db_oai"
)

# LLM
llm = ChatOpenAI(temperature=0)

# Search
search = GoogleSearchAPIWrapper()

# Initialize
web_research_retriever = WebResearchRetriever.from_llm(
    vectorstore=vectorstore, llm=llm, search=search
)

# Run
import logging

logging.basicConfig()
logging.getLogger("langchain.retrievers.web_research").setLevel(logging.INFO)
from langchain.chains import RetrievalQAWithSourcesChain

user_input = "How do LLM Powered Autonomous Agents work?"
qa_chain = RetrievalQAWithSourcesChain.from_chain_type(
    llm, retriever=web_research_retriever
)
result = qa_chain({"question": user_input})
print(result)

1.2 代码研读

1.2.1 WebResearchRetriever

首先是代码中最重要的一个封装类:WebResearchRetriever。

它的使用方式如下:

# Initialize
web_research_retriever = WebResearchRetriever.from_llm(
    vectorstore=vectorstore, llm=llm, search=search
)

接收三个主要参数:

  • 向量数据库:用来存储网页数据
  • llm
  • 检索引擎,这里的检索引擎 必须是 Google Search API
class WebResearchRetriever(BaseRetriever):
    """`Google Search API` retriever."""

	search: GoogleSearchAPIWrapper = Field(..., description="Google Search API Wrapper")

再看下其构造过程:from_llm 函数

def from_llm(
        cls,
        vectorstore: VectorStore,
        llm: BaseLLM,
        search: GoogleSearchAPIWrapper,
        prompt: Optional[BasePromptTemplate] = None,
        num_search_results: int = 1,
        text_splitter: RecursiveCharacterTextSplitter = RecursiveCharacterTextSplitter(
            chunk_size=1500, chunk_overlap=150
        ),
    ) -> "WebResearchRetriever":
        """Initialize from llm using default template.

        Args:
            vectorstore: Vector store for storing web pages
            llm: llm for search question generation
            search: GoogleSearchAPIWrapper
            prompt: prompt to generating search questions
            num_search_results: Number of pages per Google search
            text_splitter: Text splitter for splitting web pages into chunks

        Returns:
            WebResearchRetriever
        """

        if not prompt:
            QUESTION_PROMPT_SELECTOR = ConditionalPromptSelector(
                default_prompt=DEFAULT_SEARCH_PROMPT,
                conditionals=[
                    (lambda llm: isinstance(llm, LlamaCpp), DEFAULT_LLAMA_SEARCH_PROMPT)
                ],
            )
            prompt = QUESTION_PROMPT_SELECTOR.get_prompt(llm)

        # Use chat model prompt
        llm_chain = LLMChain(
            llm=llm,
            prompt=prompt,
            output_parser=QuestionListOutputParser(),
        )

        return cls(
            vectorstore=vectorstore,
            llm_chain=llm_chain,
            search=search,
            num_search_results=num_search_results,
            text_splitter=text_splitter,
        )

这个函数用来初始化 WebResearchRetriever,除了上面说的三个主要参数外,其额外提供了默认的Prompt模板text_splitterQuestionListOutputParserRetriever过程所需的工具和内容。

默认的Prompt模板内容如下:

DEFAULT_SEARCH_PROMPT = PromptTemplate(
    input_variables=["question"],
    template="""You are an assistant tasked with improving Google search \
results. Generate THREE Google search queries that are similar to \
this question. The output should be a numbered list of questions and each \
should have a question mark at the end: {question}""",
)

从这个Prompt大致可以看出WebResearchRetriever的工作过程:

(1)根据用户的问题,利用大模型将该问题转化为3个与用户问题相近的Google搜索语句
(2)利用 Google CSE 搜索这几个问题,会得到一系列相关 URL
(3)利用上篇文章我们爬取网页内容的方法,将每个URL中的文本抓取出来
(4)对抓取出来的文本进行分块,向量存储(WebResearchRetriever的工作到这里就结束了)
(5)然后就是其它模块使用RAG的流程:用户提问 —> 查询向量数据库 —> 大模型回答问题

整体流程示意图如下:

langchain 获取源码,大模型,学习,人工智能,gpt,笔记,经验分享,langchain,agi

(1)-(4)步骤的源码如下,可以对照着看一下:

def _get_relevant_documents(
        self,
        query: str,
        *,
        run_manager: CallbackManagerForRetrieverRun,
    ) -> List[Document]:
        """Search Google for documents related to the query input.

        Args:
            query: user query

        Returns:
            Relevant documents from all various urls.
        """

        # Get search questions
        logger.info("Generating questions for Google Search ...")
        result = self.llm_chain({"question": query})
        logger.info(f"Questions for Google Search (raw): {result}")
        questions = result["text"]
        logger.info(f"Questions for Google Search: {questions}")

        # Get urls
        logger.info("Searching for relevant urls...")
        urls_to_look = []
        for query in questions:
            # Google search
            search_results = self.search_tool(query, self.num_search_results)
            logger.info("Searching for relevant urls...")
            logger.info(f"Search results: {search_results}")
            for res in search_results:
                if res.get("link", None):
                    urls_to_look.append(res["link"])

        # Relevant urls
        urls = set(urls_to_look)

        # Check for any new urls that we have not processed
        new_urls = list(urls.difference(self.url_database))

        logger.info(f"New URLs to load: {new_urls}")
        # Load, split, and add new urls to vectorstore
        if new_urls:
            loader = AsyncHtmlLoader(new_urls, ignore_load_errors=True)
            html2text = Html2TextTransformer()
            logger.info("Indexing new urls...")
            docs = loader.load()
            docs = list(html2text.transform_documents(docs))
            docs = self.text_splitter.split_documents(docs)
            self.vectorstore.add_documents(docs)
            self.url_database.extend(new_urls)

        # Search for relevant splits
        # TODO: make this async
        logger.info("Grabbing most relevant splits from urls...")
        docs = []
        for query in questions:
            docs.extend(self.vectorstore.similarity_search(query))

        # Get unique docs
        unique_documents_dict = {
            (doc.page_content, tuple(sorted(doc.metadata.items()))): doc for doc in docs
        }
        unique_documents = list(unique_documents_dict.values())
        return unique_documents

1.2.2 GoogleSearchAPIWrapper

这是 Google CSE 检索API的封装类。

class GoogleSearchAPIWrapper(BaseModel):
    """Wrapper for Google Search API."""

1.2.3 RetrievalQAWithSourcesChain

这是 LangChain 内封装的问答QA链,提问-给出答案,并带有答案来源Sources.

对检索到的文档进行问答,并引用其来源。当您希望答案响应在文本响应中具有来源时,请使用此选项。

使用方法:

qa_chain = RetrievalQAWithSourcesChain.from_chain_type(
    llm, retriever=web_research_retriever
)

接收两个参数:

  • llm:大模型
  • retriver:检索器

其源码定义如下:

class RetrievalQAWithSourcesChain(BaseQAWithSourcesChain):
    """Question-answering with sources over an index."""

    retriever: BaseRetriever = Field(exclude=True)
    """Index to connect to."""
    reduce_k_below_max_tokens: bool = False
    """Reduce the number of results to return from store based on tokens limit"""
    max_tokens_limit: int = 3375
    """Restrict the docs to return from store based on tokens,
    enforced only for StuffDocumentChain and if reduce_k_below_max_tokens is to true"""

2. 总结

本文我们主要学习了利用 LangChain进行网络文档 + RAG 的使用,重点看了 LangChain中WebResearchRetriever的封装和实现原理。里面虽然使用的Google搜索,在国内有诸多限制,但是里面的实现思路是值得借鉴的:

(1)找到与用户问题相关的网页

  • 用户提问转换为相似的搜索语句
  • 通过检索API找到相关的网页URL

(2)文本获取与存储

  • 爬取URL文本内容
  • 分割文本并向量存储

(3)使用以上相关内容进行RAG增强检索,回答用户问题

如果觉得本文对你有帮助,麻烦点个赞和关注呗 ~~~


  • 大家好,我是 同学小张,日常分享AI知识和实战案例
  • 欢迎 点赞 + 关注 👏,持续学习持续干货输出
  • +v: jasper_8017 一起交流💬,一起进步💪。
  • 微信公众号也可搜同学小张 🙏

本站文章一览:

langchain 获取源码,大模型,学习,人工智能,gpt,笔记,经验分享,langchain,agi文章来源地址https://www.toymoban.com/news/detail-854707.html

到了这里,关于【AI大模型应用开发】【LangChain系列】实战案例3:深入LangChain源码,你不知道的WebResearchRetriever与RAG联合之力的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • AI 大模型应用开发实战纲要

    初探大模型:起源与发展 预热篇:解码注意力机制(Attention ) 变革里程碑:Transformer 的崛起 走向不同:GPT 与 Bert 的选择 GPT 模型家族:从始至今 GPT 模型家族:从始至今 从 GPT-1 到 GPT-3.5:一路的⻛云变幻 ChatGPT:赢在哪里 GPT-4:一个新的开始 大模型的未来:开源力量

    2024年02月07日
    浏览(32)
  • 【基础篇001】⼤模型理论基础——初探大模型:起源与发展《AI 大模型应用开发实战指南》

      目录 基础篇:⼤模型理论基础 初探大模型:起源与发展 什么是大模型?

    2024年02月09日
    浏览(40)
  • OpenAI开发系列(十五):AI敏捷开发的新范式:利用大模型优化和自动化应用开发流程(上)

    授权声明: 本文基于九天Hector的原创课程资料创作,已获得其正式授权。 原课程出处:九天Hector的B站主页,感谢九天Hector为学习者带来的宝贵知识。 请尊重原创,转载或引用时,请标明来源。 全文共5000余字,预计阅读时间约30~50分钟 | 满满干货(附代码),建议收藏! 本文

    2024年02月03日
    浏览(38)
  • LangChain大型语言模型(LLM)应用开发(五):评估

    LangChain是一个基于大语言模型(如ChatGPT)用于构建端到端语言模型应用的 Python 框架。它提供了一套工具、组件和接口,可简化创建由大型语言模型 (LLM) 和聊天模型提供支持的应用程序的过程。LangChain 可以轻松管理与语言模型的交互,将多个组件链接在一起,以便在不同的

    2024年02月15日
    浏览(39)
  • LangChain大型语言模型(LLM)应用开发(六):Agents

    LangChain是一个基于大语言模型(如ChatGPT)用于构建端到端语言模型应用的 Python 框架。它提供了一套工具、组件和接口,可简化创建由大型语言模型 (LLM) 和聊天模型提供支持的应用程序的过程。LangChain 可以轻松管理与语言模型的交互,将多个组件链接在一起,以便在不同的

    2024年02月16日
    浏览(34)
  • LangChain大型语言模型(LLM)应用开发(三):Chains

    LangChain是一个基于大语言模型(如ChatGPT)用于构建端到端语言模型应用的 Python 框架。它提供了一套工具、组件和接口,可简化创建由大型语言模型 (LLM) 和聊天模型提供支持的应用程序的过程。LangChain 可以轻松管理与语言模型的交互,将多个组件链接在一起,以便在不同的

    2024年02月12日
    浏览(36)
  • 自然语言处理从入门到应用——LangChain:快速入门-[快速开发聊天模型]

    分类目录:《大模型从入门到应用》总目录 LangChain系列文章: 基础知识 快速入门 安装与环境配置 链(Chains)、代理(Agent:)和记忆(Memory) 快速开发聊天模型 模型(Models) 基础知识 大型语言模型(LLMs) 基础知识 LLM的异步API、自定义LLM包装器、虚假LLM和人类输入LLM(

    2024年02月15日
    浏览(31)
  • LangChain大型语言模型(LLM)应用开发(四):Q&A over Documents

    LangChain是一个基于大语言模型(如ChatGPT)用于构建端到端语言模型应用的 Python 框架。它提供了一套工具、组件和接口,可简化创建由大型语言模型 (LLM) 和聊天模型提供支持的应用程序的过程。LangChain 可以轻松管理与语言模型的交互,将多个组件链接在一起,以便在不同的

    2024年02月16日
    浏览(39)
  • LangChain大型语言模型(LLM)应用开发(一):Models, Prompts and Output Parsers

    LangChain是一个基于大语言模型(如ChatGPT)用于构建端到端语言模型应用的 Python 框架。它提供了一套工具、组件和接口,可简化创建由大型语言模型 (LLM) 和聊天模型提供支持的应用程序的过程。LangChain 可以轻松管理与语言模型的交互,将多个组件链接在一起,以便在不同的

    2024年02月16日
    浏览(35)
  • 大模型时代,如何快速开发AI应用

    本文分享自华为云社区 《【云享问答】第3期:大模型时代,如何快速开发AI应用》,作者:华为云社区精选。 大模型快速普及应用的当下,AI浪潮汹涌而至,对于开发者来说,开发一款属于自己的AI应用并不是遥不可及。华为云AI生态技术专家、中科院计算所博士坐阵,从数

    2024年02月08日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包