ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Langchain 初学者入门 2025 笔记(二)

Langchain 初学者入门 2025 笔记(二) 总结与下一步以上就是我们如何为每个文本块添加元数据的方法。下一步基本上就是将所有检索到的文本块连同用户的问题一起发送给大语言模型。这样LLM就可以查看那些可能包含该问题答案的文本块并给出答案——在本例中就是“Transylvania”。我们将在下一节中学习如何实现这一步。https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/lngchn-bgr-intro-2025/img/1d5503f124369a7ae37205b2e156af0d_3.pnghttps://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/lngchn-bgr-intro-2025/img/1d5503f124369a7ae37205b2e156af0d_3.png本节课中我们一起学习了如何在RAG系统中为文本块嵌入元数据以追踪信息来源并通过一个查询德古拉城堡位置的实例演示了带元数据的检索过程。这为构建更可靠、可追溯的问答系统奠定了基础。027构建RAG问答系统在本节课中我们将学习如何构建一个完整的检索增强生成RAG系统。我们将把之前章节中获取的相关文档片段与用户问题结合提交给大语言模型LLM从而获得基于特定文档的精确答案。概述与准备https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/lngchn-bgr-intro-2025/img/fa2c6a5038216ec15618cfd509ab4663_1.png上一节我们介绍了如何根据用户问题检索最相关的文档片段。本节中我们将利用这些片段来生成最终答案。我复制了上一节的所有代码到一个新文件中并在此基础上添加了更多功能。让我们逐步来看具体做了什么。构建提示词首先我们有一个用户问题以及根据该问题检索到的相关文档片段。我要做的第一件事很简单准备一个组合提示词提交给LLM。这个提示词的结构如下包含实际用户问题例如“德古拉的城堡位于何处”提供所有相关的文档片段文本。我们筛选出最相关的三个片段并将它们连接在一起。为确保LLM仅基于提供的文档回答我们添加指令“请仅根据提供的文档给出大致答案。如果答案未在文档中找到请回复‘我不确定’。”以下是构建提示词的代码示例# 假设 user_question 和 relevant_chunks 已定义combined_promptf 请根据以下文档回答问题。 用户问题{user_question}相关文档{‘ ‘.join(relevant_chunks)}请仅根据提供的文档给出大致答案。如果答案未在文档中找到请回复‘我不确定’。 调用模型并获取答案接下来我们实例化模型并调用它。这一步我们已经做过多次。以下是调用过程的代码https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/lngchn-bgr-intro-2025/img/fa2c6a5038216ec15618cfd509ab4663_3.pnghttps://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/lngchn-bgr-intro-2025/img/fa2c6a5038216ec15618cfd509ab4663_5.png# 定义消息数组messages[{role:system,content:你是一个乐于助人的助手。},{role:user,content:combined_prompt}]# 调用模型并打印结果仅内容responsemodel.invoke(messages)print(response.content)运行与结果分析现在让我们运行这个文件。几秒钟后我们得到了最终结果。基于提供的文档LLM回答“德古拉的城堡位于特兰西瓦尼亚的最东端就在特兰西瓦尼亚、摩尔达维亚和布科维纳的边界上喀尔巴阡山脉之中。德古拉伯爵命名的邮政城镇是Bistritz。”这非常棒LLM能够基于文档片段中的所有数据识别出这个信息。为了验证我们可以复制“Bistritz”这个词并在片段中搜索会发现它在多个地方出现。尝试另一个问题为了进一步测试让我们问另一个问题。众所周知德古拉讨厌大蒜。那么让我们提问“德古拉最害怕什么”再次运行文件我们得到响应“德古拉害怕很多东西他不能被邀请就不能进入某些地方不喜欢大蒜、圣水……” 它给出了答案甚至包括一些我们原本不知道的信息。让我们确认LLM是否是基于我们发送的片段给出这个答案的。复制“garlic”大蒜这个词并向上滚动搜索可以看到它在片段中被多次提及。例如片段中提到“他受大蒜困扰”以及“他也不喜欢十字架”。通过这种方式我们知道LLM仅基于提供的文档进行回答没有动用其自身知识或进行网络搜索。因此在你的项目中你可以放入LLM无法知晓的私有数据赋予其额外的知识并与之对话。扩展可能性我们甚至可以更进一步。与其进行一次性问答你可以构建一个支持多轮对话的系统。还记得我们在聊天模型模块中已经实现过这个功能吗你可以在这里实现同样的逻辑。总结与展望至此我们已经完成了对RAG的深入探讨。花点时间欣赏一下我们已经走了多远。你现在已经跻身于能够使用Langchain构建RAG系统和智能检索系统的前5%开发者行列了。你现在能够构建智能文档检索系统。创建具有上下文感知能力的对话式AI。将AI连接到你的私有数据。甚至集成网络爬取能力。https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/lngchn-bgr-intro-2025/img/fa2c6a5038216ec15618cfd509ab4663_7.png我们的旅程尚未结束。接下来我们将深入Langchain的最后一个核心组件智能体Agents和工具Tools。想象一下基本上就是赋予你的AI实际使用工具和像真人一样做出决策的能力。如果这让你感到兴奋我们将在下一节中探索这个领域。028智能体与工具介绍 在本节课中我们将要学习Langchain的最后一个核心组件智能体与工具。你可能会觉得“AI智能体”听起来非常复杂但事实上它的核心概念比想象中要简单得多。通过本节的学习你将理解智能体如何自主决策以及工具如何赋予AI执行特定任务的能力。上一节我们学习了链和检索增强生成它们遵循我们设定的特定指令。本节中我们来看看智能体它们将自主决策的能力提升到了一个新的高度。什么是智能体智能体可以被视为AI世界的问题解决者。它们是能够独立思考、自主做出决策的人工智能。你可以将智能体想象成一位厨师。一位优秀的厨师知道在烹饪不同菜肴时何时该用刀、何时该用搅拌器、何时该用烤箱。同样一个AI智能体能够自主决定何时该使用浏览器搜索、何时该调用计算器、何时该向数据库发起API请求。在这里我们注意到一个关键词工具。什么是工具工具是AI用来完成特定任务的函数。就像厨师的厨房工具刀用于切割、烤箱用于烘焙、搅拌器用于混合一样工具是我们赋予AI智能体的特殊能力。例如我们可以给AI一个计算器工具、一个搜索引擎工具或一个日历工具。许多应用程序如Perplexity的核心就是建立在工具之上的。现在你应该对为何要使用智能体有了一些概念。本质上智能体帮助语言模型在解决问题时决定采取何种行动。它们能在合适的时机选择正确的工具而无需我们明确指示使用哪一个。一个简单的工具使用示例 ️让我们看一个使用工具的简单例子。如果我向一个AI智能体提问“巴黎的天气温度加5是多少”这个过程会变得非常有趣。AI智能体并非随机选择工具它实际上在像侦探破案一样思考整个过程。首先智能体识别出问题包含两个部分查询天气和进行数学计算。它知道需要先获取天气因为你无法对一个未知的数值进行加法运算。然后它再使用计算器工具进行加5操作。你可能会问智能体如何知道先做什么、后做什么理解ReAct模式 这就引出了ReAct的概念。这是当今构建AI智能体的最佳模式之一。这里的“ReAct”并非指前端框架而是AI领域的术语代表Reasoning推理 Acting行动。这个概念模拟了人类的思考方式。当我们面对一个问题时首先会思考如何解决它。这正是智能体所做的第一步Think思考。第二步是Act行动。智能体可以使用各种可用的工具来执行任务。第三步是Observe观察行动的结果。最后如果需要重复整个过程。让我们看看“巴黎天气加5”这个问题在ReAct模式下的具体流程https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/lngchn-bgr-intro-2025/img/53ca52f03b1d90763b2d354de73cb85a_1.pnghttps://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/lngchn-bgr-intro-2025/img/53ca52f03b1d90763b2d354de73cb85a_1.png思考我需要先找到巴黎的温度。行动使用天气API工具。观察API返回“巴黎气温20摄氏度”。再次思考现在我可以给这个数值加5。再次行动使用计算器工具。最终观察/答案25摄氏度。https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/lngchn-bgr-intro-2025/img/53ca52f03b1d90763b2d354de73cb85a_3.png可以把这想象成拼图。ReAct模式不是直接展示完成后的图片而是让我们看到每一片拼图是如何被放置到正确位置的。https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/lngchn-bgr-intro-2025/img/53ca52f03b1d90763b2d354de73cb85a_3.png更复杂的场景想象 这是一个非常小的例子。想象一下如果我提出一个更复杂的问题“我下周去伦敦旅行需要带伞吗以及我应该预订哪些餐厅”你可以想象这是一个多步骤的问题。我们的AI智能体可能会通过多次循环思考 - 行动 - 观察的过程来解决它。我希望你现在对智能体和工具有了一个初步的图景。如果你还没有完全理解请不要担心。在下一节中我们将从零开始构建自定义智能体并查看大量实际示例。https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/lngchn-bgr-intro-2025/img/53ca52f03b1d90763b2d354de73cb85a_5.png总结 https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/lngchn-bgr-intro-2025/img/53ca52f03b1d90763b2d354de73cb85a_5.png本节课中我们一起学习了Langchain智能体与工具的核心概念。我们了解到智能体是能够自主决策的AI问题解决者而工具则是它们执行任务的具体手段。通过ReAct推理行动模式智能体能够像人类一样思考步骤、选择工具、观察结果并迭代执行从而解决复杂的多步骤问题。这为AI应用赋予了前所未有的灵活性和自主性。029智能体工具深度解析在本节课中我们将学习如何从零开始构建一个AI智能体。通过本节内容你将掌握为各种业务用例构建智能体的基本方法。由于这是一个新概念我们将循序渐进地进行讲解。首先我们将展示当前大型语言模型存在的一个局限性然后探讨如何通过构建智能体来解决这个问题。初始化环境与提出问题上一节我们介绍了智能体的概念本节中我们来看看如何用代码实现。首先我们需要设置基础环境。以下是初始化步骤的代码# 加载环境变量# 初始化LLM使用GPT-4模型llmChatOpenAI(modelgpt-4)querywhat is the current time?这段代码将问题输入到链中链会将其转换为提示词并发送给LLM。这是一个非常基础的操作。运行这段代码让我们看看GPT-4如何回答当前时间的问题。运行结果会显示LLM无法访问实时信息。这是因为LLM本身无法获取实时数据。它们基于特定数据集进行训练并且通常有一个数据截止日期。如果询问今天早上发生的事情它很可能不知道。这是一个完美的例子展示了我们可以通过创建智能体来增强LLM的能力。智能体可以使用工具来获取当前时间。安装必要包与引入提示模板为了解决上述限制我们需要安装一些额外的包。首先安装langchain-hub包。这个包允许我们从互联网上使用他人创建的提示词模板而无需自己编写。在安装的同时我们深入了解一下这个包。简单来说它让我们能够复用社区中优秀的提示模板。在这个例子中我们需要使用ReAct提示模板。稍后我们会详细查看这个模板的内容但现在我们先使用它。以下是引入模板的代码fromlangchainimporthub prompthub.pull(hwchase17/react)这段代码从LangChain Hub拉取指定的ReAct提示模板。hwchase17是LangChain创建者Harrison Chase的组织空间react是我们需要的模板文件。创建工具与智能体现在让我们创建一些工具供智能体使用。工具是一个列表我们可以为智能体提供多种工具。根据智能体在特定时刻需要解决的问题它会选择合适的工具来完成任务。工具可以是谷歌搜索工具、邮件发送工具等。在这个案例中我们需要创建一个获取系统时间的工具。接下来我们需要创建智能体。为此我们需要从LangChain导入一些类。以下是相关代码fromlangchain.agentsimportcreate_react_agent,AgentExecutor tools[]# 工具列表稍后填充agentcreate_react_agent(llmllm,toolstools,promptprompt)agent_executorAgentExecutor(agentagent,toolstools,verboseTrue)resultagent_executor.invoke({input:query})我们移除了之前的简单链现在声明一个智能体执行器。将verbose参数设置为True这样我们可以看到智能体在每个步骤中的思考和行动便于调试和调整。快速回顾一下我们有查询问题、从Hub拉取的提示模板、工具列表尚未编写以及将这些信息传递给执行器。最后我们用查询来调用智能体。如果现在运行由于LLM没有获取时间的工具显然会失败。运行后我们可以看到智能体逐步执行的日志。ReAct智能体遵循“推理Reason-行动Act-观察Observe-重复”的循环日志清晰地展示了这一过程。首先它进行推理“我需要检查我当前位置的当前时间”。推理出问题或需要做的事情后它需要采取行动“使用工具来找出当前时间”。不幸的是我们尚未为智能体提供时间工具因此它报告没有工具来解决这个问题。最终它给出无法找到当前时间的答案因为它自己不知道如何解决。实现获取时间工具现在让我们修复这个问题为智能体提供一个工具。我们将创建一个简单的Python函数来返回当前时间。我们希望智能体以特定的时间格式给出答案。以下是函数定义importdatetimefromlangchain.agentsimporttooltooldefget_system_time(format:str%Y-%m-%d %H:%M:%S): 以指定格式返回当前的日期和时间。 current_timedatetime.datetime.now()formatted_timecurrent_time.strftime(format)returnformatted_time我们使用了Python标准的datetime库来获取系统时间并按照指定格式进行格式化。如果LLM没有传入特定格式函数将使用默认格式。但是LangChain本身并不知道如何处理这个函数。我们需要为这个函数添加一个Python装饰器tool。这个装饰器会将方法转换为LangChain易于理解的格式并提供一个描述字符串让LLM了解这个方法的上下文信息从而判断是否应该为特定任务使用这个工具。确保始终为工具函数提供清晰、良好的描述或文档字符串。现在剩下的就是将这个工具作为一项添加到工具列表中。tools[get_system_time]智能体工作流程解析在运行文件之前让我们梳理一下控制流程以便更清楚地了解所有部分是如何协同工作的。以下是智能体的工作步骤提示与初始化你向智能体提供一个提示例如ReAct提示。该提示包含对LLM的任务指令、示例、逐步推理说明以及决定何时使用工具的指导。其次提示中还包括可用工具的描述包括它们的名称和使用细节。智能体执行当用户向智能体提供查询时LLM解释查询并生成响应。LLM不直接执行工具而是建议调用哪些工具并可能基于其推理提供参数。工具调用智能体框架LangChain拦截LLM的输出检查它是否建议调用工具。如果建议调用工具LangChain会调用你Python代码中的工具并传入LLM提议的任何参数。工具执行该工具在你的Python环境中运行可以访问你的Python资源如当前时间、文件系统、API等。工具将其结果返回给LangChain。LLM响应LangChain将工具的输出发送回LLM供其进一步推理或为用户生成最终响应。运行与测试智能体理论讲解完毕现在让我们运行代码看看一切是如何协同工作的。运行后智能体现在可以访问工具了。从日志中可以看到它首先进行推理需要访问get_system_time工具。推理完成后第二步是行动。LangChain现在调用我们的函数并传入LLM提供的输入在这个例子中它采用了默认格式。然后生成最终答案接着发生另一个LLM调用LLM根据最终数据给出回答。本质上智能体遍历所有工具找到能帮助它完成任务的那个并使用它。它能够通过我们提供的描述来识别工具。https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/lngchn-bgr-intro-2025/img/e8a65c7f02e583d1a584cc7f391da456_1.png我们不必对查询格式过于严格。可以提出略有不同的问题例如只询问当前时间而不包含日期。再次运行文件可以看到LLM这次向工具提供了略有不同的输入格式最终答案中只显示了时间而没有日期。在推理中它能够识别出只需要调整格式就能给出正确答案。因此LLM建议了一个不同的格式而LangChain为我们执行了工具。在我们的例子中循环只运行了一次因为这是一个单步问题找到当前时间所以它使用工具后就结束了。但对于更复杂的查询这个循环可能会根据用户提示的复杂性运行三次、四次或五次。这就是ReAct智能体的工作原理。让我们再稍微改变一下提示。这次我们让它告诉我们伦敦的当前时间。我们可以告诉它“你在印度”因为我目前在印度。运行后智能体首先推理需要检查印度的系统时间然后将其转换为伦敦时间。它也知道伦敦时间比印度晚大约5.5小时。它思考了这一点然后行动调用get_system_time函数获取了印度的当前时间。它根据查询为工具传入了正确的格式。一旦有了正确的印度时间它再次推理“现在我们有了印度时间需要通过减去5.5小时来计算伦敦时间”。这正是日志中显示的内容。推理后的下一步行动是“从时间中减去5.5小时”然后给出最终答案即当前的伦敦时间。对于数学运算我们可以提供自己的计算工具。大多数时候LLM应该能够自行处理但在生产环境中提供自己的工具总是更安全因为有时它会说找不到数学工具来进行减法运算。这是一个很好的演示说明了工具的重要性。没有get_system_time工具LLM就无法知道我的当前时间。深入ReAct提示模板到目前为止我们已经看到了智能体经历推理、行动、观察循环的日志但LLM究竟是如何做到这一点的呢我们知道这得益于ReAct提示模板。让我们实际看看这个模板包含什么内容使得它能够进行这种重复循环直到得到答案。访问smith.langchain.com/hub/hwchase17可以查看ReAct提示模板。这是我们在应用中使用的系统级提示。模板内容大致如下指令“尽你所能回答以下问题。你可以使用以下工具[工具列表]”。格式要求指示LLM遵循“Thought思考: … Action行动: … Action Input行动输入: … Observation观察: …”的格式。循环机制LLM首先思考下一步该做什么Thought然后决定采取哪个行动Action并提供输入Action Input。框架执行工具后返回结果Observation。LLM观察结果判断是否已得到最终答案或者是否需要再次进入“Thought-Action-Observation”循环。最终答案一旦确信解决了问题的每个部分就进入“Final Answer最终答案: …”。就像在终端中看到的那样“思考-行动-观察”的循环持续进行直到智能体确信它已经解决了你提示中的每个部分。这就像看着侦探一步步破案。https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/lngchn-bgr-intro-2025/img/e8a65c7f02e583d1a584cc7f391da456_3.pnghttps://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/lngchn-bgr-intro-2025/img/e8a65c7f02e583d1a584cc7f391da456_4.png本节课中我们一起学习了如何利用LangChain从零开始构建一个AI智能体。我们了解了LLM在获取实时信息方面的局限性并通过创建工具如获取系统时间来扩展其能力。我们探索了ReAct智能体的工作流程包括其“推理-行动-观察”的循环机制并深入查看了驱动这一过程的提示模板。通过实际代码演示我们看到了智能体如何选择并使用合适的工具来回答复杂问题。这为构建能够处理现实世界任务的AI应用奠定了坚实基础。
返回列表