当前位置: 首页 > news >正文

带有 Elasticsearch 和 Langchain 的 Agentic RAG

作者:来自 Elastic Han Xiang Choong

讨论并实现 Elastic RAG 的代理流程,其中 LLM 选择调用 Elastic KB。

更多阅读:Elasticsearch:基于 Langchain 的 Elasticsearch Agent 对文档的搜索。

简介

代理是将 LLM 应用于实际用例的合乎逻辑的下一步。本文旨在介绍代理在 RAG 工作流中的概念和用法。总而言之,代理代表了一个极其令人兴奋的领域,具有许多雄心勃勃的应用程序和用例的可能性。

我希望在未来的文章中涵盖更多这些想法。现在,让我们看看如何使用 Elasticsearch 作为我们的知识库,使用 LangChain 作为我们的代理框架来实现 Agentic RAG。

背景

LLMs 的使用始于简单地提示 LLM 执行诸如回答问题和简单计算之类的任务。

但是,现有模型知识的不足意味着 LLMs 无法应用于需要专业技能的领域,例如企业客户服务和商业智能。

很快,提示过渡到检索增强生成 (RAG),这是 Elasticsearch 的天然优势。RAG 是一种有效而简单的方法,可以在查询时快速向 LLM 提供上下文和事实信息。另一种方法是漫长而昂贵的再培训过程,而成功率远不能得到保证。

RAG 的主要操作优势是允许近乎实时地向 LLM 应用程序提供更新的信息。

实施涉及采购向量数据库(例如 Elasticsearch)、部署嵌入模型(例如 ELSER)以及调用 search API 来检索相关文档。

检索到文档后,可以将其插入 LLM 的提示中,并根据内容生成答案。这提供了背景和事实,而 LLM 本身可能缺乏这两者。

直接调用 LLM、使用 RAG 和使用代理之间的区别

但是,标准 RAG 部署模型有一个缺点 - 它很死板。LLM 无法选择从哪个知识库中提取信息。它也无法选择使用其他工具,例如 Google 或 Bing 等网络搜索引擎 API。它无法查看当前天气,无法使用计算器,也无法考虑除给定知识库之外的任何工具的输出。

Agentic 模型的不同之处在于选择。

术语说明

工具使用(Tool usage),即 Langchain 上下文中使用的术语,也称为函数调用。无论出于何种目的,这两个术语都是可以互换的 - 两者都指 LLM 被赋予一组函数或工具,它可以用来补充其能力或影响世界。请耐心等待,因为我在本文的其余部分都使用了 “工具使用 - Tool Usage”。

选择

赋予 LLM 决策能力,并为其提供一套工具。根据对话的状态和历史,LLM 将选择是否使用每个工具,并将工具的输出纳入其响应中。

这些工具可能是知识库、计算器、网络搜索引擎和爬虫 - 种类繁多,没有限制或结束。LLM 能够执行复杂的操作和任务,而不仅仅是生成文本。

个用于研究特定主题的 agentic 流程示例

让我们实现一个代理的简单示例。Elastic 的核心优势在于我们的知识库。因此,此示例将重点介绍如何使用相对较大且复杂的知识库,方法是制作比简单的向量搜索更复杂的查询。

设置

首先,在项目目录中定义一个 .env 文件,并填写这些字段。我使用带有 GPT-4o 的 Azure OpenAI 部署来学习我的 LLM,并使用 Elastic Cloud 部署来学习我的知识库。我的 Python 版本是 Python 3.12.4,我使用 Macbook 进行操作。

ELASTIC_ENDPOINT="YOUR ELASTIC ENDPOINT"
ELASTIC_API_KEY="YOUR ELASTIC API KEY"OPENAI_API_TYPE="azure"
AZURE_OPENAI_ENDPOINT="YOUR AZURE ENDPOINT"
AZURE_OPENAI_API_VERSION="2024-06-01"
AZURE_OPENAI_API_KEY="YOUR AZURE API KEY"
AZURE_OPENAI_GPT4O_MODEL_NAME="gpt-4o"
AZURE_OPENAI_GPT4O_DEPLOYMENT_NAME="YOUR AZURE OPENAI GPT-4o DEPLOYMENT NAME"

你可能必须在终端中安装以下依赖项。

pip install langchain elasticsearch 

在你的项目目录中创建一个名为 chat.py 的 python 文件,并粘贴此代码片段以初始化你的 LLM 和与 Elastic Cloud 的连接:

import os
from dotenv import load_dotenv
load_dotenv()from langchain.chat_models import AzureChatOpenAI
from langchain.agents import initialize_agent, AgentType, Tool
from langchain.tools import StructuredTool  # Import StructuredTool
from langchain.memory import ConversationBufferMemory
from typing import Optional
from pydantic import BaseModel, Field# LLM setup
llm = AzureChatOpenAI(openai_api_version=os.getenv("AZURE_OPENAI_API_VERSION"),azure_deployment=os.getenv("AZURE_OPENAI_GPT4O_DEPLOYMENT_NAME"),temperature=0.5,max_tokens=4096
)from elasticsearch import Elasticsearch
# Elasticsearch Setup
try:# Elasticsearch setupes_endpoint = os.environ.get("ELASTIC_ENDPOINT")es_client = Elasticsearch(es_endpoint,api_key=os.environ.get("ELASTIC_API_KEY"))
except Exception as e:es_client = None

Hello World!我们的第一个工具

初始化并定义我们的 LLM 和 Elastic 客户端后,让我们来做一个 Elastic 版的 Hello World。我们将定义一个函数来检查与 Elastic Cloud 的连接状态,并定义一个简单的代理对话链来调用它。

将以下函数定义为 langchain Tool。名称和描述是提示(prompt)工程的关键部分。LLM 依靠它们来确定是否在对话期间使用该工具。

# Define a function to check ES status
def es_ping(*args, **kwargs):if es_client is None:return "ES client is not initialized."else:try:if es_client.ping():return "ES ping returning True, ES is connected."else:return "ES is not connected."except Exception as e:return f"Error pinging ES: {e}"es_status_tool = Tool(name="ES Status",func=es_ping,description="Checks if Elasticsearch is connected.",
)tools = [es_status_tool]

现在,让我们初始化一个对话记忆组件来跟踪对话以及我们的 agent 本身。

# Initialize memory to keep track of the conversation
memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)# Initialize agent
agent_chain = initialize_agent(tools,llm,agent=AgentType.CONVERSATIONAL_REACT_DESCRIPTION,memory=memory,verbose=True,
)

最后,让我们用这个代码片段运行对话循环:

# Interactive conversation with the agent
def main():print("Welcome to the chat agent. Type 'exit' to quit.")while True:user_input = input("You: ")if user_input.lower() in ['exit', 'quit']:print("Goodbye!")breakresponse = agent_chain.run(input=user_input)print("Assistant:", response)if __name__ == "__main__":main()

在终端中,运行 python chat.py 来初始化对话。

python chat.py 

以下是我的操作:

You: Hello
Assistant: Hello! How can I assist you today?
You: Is Elastic search connected?> Entering new AgentExecutor chain...
Thought: Do I need to use a tool? Yes
Action: ES Status
Action Input: Observation: ES ping returning True, ES is connected.
Thought:Do I need to use a tool? No
AI: Yes, Elasticsearch is connected. How can I assist you further?

当我询问 Elasticsearch 是否已连接时,LLM 使用 ES Status 工具,ping 了我的 Elastic Cloud 部署,返回 True,然后确认 Elastic Cloud 确实已连接。

恭喜!这是一个成功的 Hello World :)

请注意,观察结果是 es_ping 函数的输出。此观察结果的格式和内容是我们快速工程的关键部分,因为这是 LLM 用来决定下一步的内容。

让我们看看如何针对 RAG 修改此工具。

Agentic RAG

我最近在我的 Elastic Cloud 部署中使用 POLITICS 数据集构建了一个大型而复杂的知识库(knowledge base)。该数据集包含从美国新闻来源抓取的大约 246 万篇政治文章。我将其导入 Elastic Cloud 并将其嵌入 elser_v2 推理端点,遵循上一篇博客中定义的流程。

要部署 elser_v2 推理端点,请确保启用了 ML 节点自动扩展,然后在 Elastic Cloud 控制台中运行以下命令。

PUT _inference/sparse_embedding/elser_v2
{"service": "elser","service_settings": {"num_allocations": 4,"num_threads": 8}
}

现在,让我们定义一个新工具,对我们的政治知识库索引进行简单的语义搜索。我将其称为 bignews_embedded。此函数接受搜索查询,将其添加到标准语义搜索查询模板,然后使用 Elasticsearch 运行查询。一旦获得搜索结果,它就会将文章内容连接成一个文本块,并将其作为 LLM 观察(observation)返回。

我们将搜索结果的数量限制为 3。这种 Agentic RAG 风格的一个优点是我们可以通过多个对话步骤来制定答案。换句话说,可以使用引导性问题来设置阶段和上下文来回答更复杂的查询。问答变成了基于事实的对话,而不是一次性的答案生成。

日期

为了突出使用代理的重要优势,RAG 搜索函数除了查询之外还包含 dates 参数。在搜索新闻文章时,我们可能希望将搜索结果限制在特定的时间范围内,例如“In 2020”或 “Between 2008 and 2012”。通过添加日期以及解析器,我们允许 LLM 指定搜索的日期范围。

简而言之,如果我指定 “California wildfires in 2020” 之类的内容,我不希望看到 2017 年或任何其他年份的新闻。

此 rag_search 函数是一个日期解析器(从输入中提取日期并将其添加到查询中)和一个 Elastic semantic_search 查询。

# Define the RAG search function
def rag_search(query: str, dates: str):if es_client is None:return "ES client is not initialized."else:try:# Build the Elasticsearch querymust_clauses = []# If dates are provided, parse and include in queryif dates:# Dates must be in format 'YYYY-MM-DD' or 'YYYY-MM-DD to YYYY-MM-DD'date_parts = dates.strip().split(' to ')if len(date_parts) == 1:# Single datestart_date = date_parts[0]end_date = date_parts[0]elif len(date_parts) == 2:start_date = date_parts[0]end_date = date_parts[1]else:return "Invalid date format. Please use YYYY-MM-DD or YYYY-MM-DD to YYYY-MM-DD."date_range = {"range": {"date": {"gte": start_date,"lte": end_date}}}must_clauses.append(date_range)# Add the main query clausemain_query = {"nested": {"path": "text.inference.chunks","query": {"sparse_vector": {"inference_id": "elser_v2","field": "text.inference.chunks.embeddings","query": query}},"inner_hits": {"size": 2,"name": "bignews_embedded.text","_source": False}}}must_clauses.append(main_query)es_query = {"_source": ["text.text", "title", "date"],"query": {"bool": {"must": must_clauses}},"size": 3}response = es_client.search(index="bignews_embedded", body=es_query)hits = response["hits"]["hits"]if not hits:return "No articles found for your query."result_docs = []for hit in hits:source = hit["_source"]title = source.get("title", "No Title")text_content = source.get("text", {}).get("text", "")date = source.get("date", "No Date")doc = f"Title: {title}\nDate: {date}\n{text_content}\n"result_docs.append(doc)return "\n".join(result_docs)except Exception as e:return f"Error during RAG search: {e}"

运行完整的搜索查询后,结果将连接成一个文本块并作为 “observation” 返回,供 LLM 使用。

为了考虑多个可能的参数,请使用 pydantic 的 BaseModel 定义有效的输入格式:

class RagSearchInput(BaseModel):query: str = Field(..., description="The search query for the knowledge base.")dates: str = Field(...,description="Date or date range for filtering results. Specify in format YYYY-MM-DD or YYYY-MM-DD to YYYY-MM-DD.")

我们还需要利用 StructuredTool 定义一个多输入函数,使用上面定义的输入格式:

# Define the RAG search tool using StructuredTool
rag_search_tool = StructuredTool(name="RAG_Search",func=rag_search,description=("Use this tool to search for information about American politics from the knowledge base. ""**Input must include a search query and a date or date range.** ""Dates must be specified in this format YYYY-MM-DD or YYYY-MM-DD to YYYY-MM-DD."),args_schema=RagSearchInput
)

描述是工具定义的关键要素,也是你快速工程的一部分。它应该全面而详细,并为 LLM 提供足够的背景信息,以便它知道何时使用该工具以及出于什么目的。

描述还应包括 LLM 必须提供的输入类型,以便正确使用该工具。指定格式和期望在这里会产生巨大影响。

不具信息性的描述可能会严重影响 LLM 使用该工具的能力!

请记住将新工具添加到代理要使用的工具列表中:

tools = [es_status_tool, rag_search_tool]

我们还需要使用系统提示进一步修改代理,以提供对代理行为的额外控制。系统提示对于确保不会发生与格式错误的输出和函数输入相关的错误至关重要。我们需要明确说明每个函数的期望以及模型应输出的内容,因为如果 langchain 看到格式不正确的 LLM 响应,它将抛出错误。

我们还需要设置 agent=AgentType.OPENAI_FUNCTIONS 以使用 OpenAI 的函数调用功能。这允许 LLM 根据我们指定的结构化模板与函数交互。

请注意,系统提示包括 LLM 应生成的输入的确切格式的规定,以及具体示例。

LLM 不仅应该检测应该使用哪种工具,还应该检测工具期望的输入! Langchain 只负责函数调用/工具使用,但是否正确使用取决于 LLM。

agent_chain = initialize_agent(tools,llm,agent=AgentType.OPENAI_FUNCTIONS,memory=memory,verbose=True,handle_parsing_errors=True,system_message="""You are an AI assistant that helps with questions about American politics using a knowledge base. Be concise, sharp, to the point, and respond in one paragraph.You have access to the following tools:- **ES_Status**: Checks if Elasticsearch is connected.- **RAG_Search**: Use this to search for information in the knowledge base. **Input must include a search query and a date or date range.** Dates must be specified in this format YYYY-MM-DD or YYYY-MM-DD to YYYY-MM-DD.**Important Instructions:**- **Extract dates or date ranges from the user's question.**- **If the user does not provide a date or date range, politely ask them to provide one before proceeding.**When you decide to use a tool, use the following format *exactly*:Thought: [Your thought process about what you need to do next]Action: [The action to take, should be one of [ES_Status, RAG_Search]]Action Input: {"query": "the search query", "dates": "the date or date range"}If you receive an observation after an action, you should consider it and then decide your next step. If you have enough information to answer the user's question, respond with:Thought: [Your thought process]Assistant: [Your final answer to the user]**Examples:**- **User's Question:** "Tell me about the 2020 California wildfires."Thought: I need to search for information about the 2020 California wildfires.Action: RAG_SearchAction Input: {"query" : "California wildfires", "dates" : "2020-01-01 to 2020-12-31"}- **User's Question:** "What happened during the presidential election?"Thought: The user didn't specify a date. I should ask for a date range.Assistant: Could you please specify the date or date range for the presidential election you're interested in?Always ensure that your output strictly follows one of the above formats, and do not include any additional text or formatting.Remember:- **Do not** include any text before or after the specified format.- **Do not** add extra explanations.- **Do not** include markdown, bullet points, or numbered lists unless it is part of the Assistant's final answer.Your goal is to assist the user by effectively using the tools when necessary and providing clear and concise answers."""
)

现在,在你的终端中运行 python chat.py 并让我们测试一下!

测试 Agentic RAG

让我们通过询问以下查询来测试它:

Summarize the federal response to california wildfires in 2020

有帮助的是,langchain 将输出中间步骤,包括 RAG_Search 函数的输入、搜索结果和最终输出。

> Entering new AgentExecutor chain...Invoking: `RAG_Search` with `{'query': 'federal response to California wildfires', 'dates': '2020-01-01 to 2020-12-31'}`Title: California federal wildfire aid: Newsom says Trump changed mind
Date: 2020-10-16T00:00:00.000Z
President Donald Trump abruptly changed course...Title: California governor declares state of emergency in multiple counties as wildfires rage
Date: 2020-09-07T00:00:00.000Z
In a statement, Newsom noted that tens...Title: Trump approves disaster declaration for California, reversing course
Date: 2020-10-16T00:00:00.000Z
California secured a Major Disaster Declaration ...> Finished chain.Assistant: The federal response to the California wildfires in 2020 included several key actions and moments:1. **Initial Denial and Reversal of Federal Aid**: President Trump initially denied California's request for federal aid for the wildfires. However, after Governor Gavin Newsom vowed to appeal the decision, Trump reversed course and approved the Major Disaster Declaration. This declaration allowed California to receive hundreds of millions of dollars in federal aid.2. **Statewide Emergency Declarations**: Governor Newsom declared a statewide emergency due to the widespread fires and extreme weather conditions. The state worked closely with federal authorities to secure assistance, including Fire Management Assistance Grants from FEMA.3. **Presidential Major Disaster Declarations**: Newsom secured a Presidential Major Disaster Declaration to bolster the state's emergency response to the Northern California wildfires. This declaration made people in impacted counties eligible for various forms of federal support, including crisis counseling, housing, unemployment assistance, and legal services.4. **Federal and State Collaboration**: Despite ongoing tensions and disagreements between the state and the Trump administration, particularly over forest management and climate change, federal agencies such as the National Park Service, U.S. Forest Service, and Bureau of Land Management were involved in managing and supporting firefighting efforts in California.5. **Impact and Scale of Wildfires**: The 2020 wildfire season in California was historically devastating, with more than 8,500 blazes scorching 6,400 square miles, destroying thousands of structures, and claiming lives. The federal aid and disaster declarations were crucial in supporting the state's response and recovery efforts.Overall, the federal response involved a combination of initial resistance followed by critical support and collaboration to address the unprecedented wildfire crisis in California.

最值得注意的是,LLM 创建了一个搜索查询,然后添加了从 2020 年初到年末的日期范围。通过将搜索结果限制在指定年份,我们确保只有相关文档才会传递给 LLM。

我们可以用它做更多的事情,例如根据类别、某些实体的外观或与其他事件的关系进行约束。

可能性无穷无尽,我认为这很酷!

关于错误处理的注意事项

在某些情况下,LLM 可能无法在需要时使用正确的工具/功能。例如,它可能选择使用自己的知识而不是使用可用的知识库来回答有关当前事件的问题。

必须仔细测试和调整系统提示和工具/功能描述。

另一种选择可能是增加可用工具的种类,以增加基于知识库内容而不是 LLM 的固有知识生成答案的可能性。

请注意,LLMs 偶尔会失败,这是其概率性质的自然结果。有用的错误消息或免责声明也可能是用户体验的重要组成部分。

结论和未来前景

对我来说,主要的收获是创建更高级的搜索应用程序的可能性。LLM 可能能够在自然语言对话的背景下即时制作非常复杂的搜索查询。这为大幅提高搜索应用程序的准确性和相关性开辟了道路,也是我兴奋地探索的领域。

通过 LLM 媒介,知识库与其他工具(例如 Web 搜索引擎和监控工具 API)的交互也可以实现一些令人兴奋且复杂的用例。来自 KB 的搜索结果可能会补充实时信息,从而使 LLM 能够执行有效且时间敏感的即时推理。

还有多代理工作流的可能性。在 Elastic 上下文中,这可能是多个代理探索不同的知识库集,以协作构建复杂问题的解决方案。也许是一个联合搜索模型,其中多个组织构建协作、共享的应用程序,类似于联合学习(federated learning)的想法?

多代理流程示例

我想探索 Elasticsearch 的一些用例,希望你也能这样做。

下次见!

附录:chat.py 的完整代码

import os
from dotenv import load_dotenv
load_dotenv()from langchain.chat_models import AzureChatOpenAI
from langchain.agents import initialize_agent, AgentType, Tool
from langchain.tools import StructuredTool  # Import StructuredTool
from langchain.memory import ConversationBufferMemory
from typing import Optional
from pydantic import BaseModel, Fieldllm = AzureChatOpenAI(openai_api_version=os.getenv("AZURE_OPENAI_API_VERSION"),azure_deployment=os.getenv("AZURE_OPENAI_GPT4O_DEPLOYMENT_NAME"),temperature=0.5,max_tokens=4096
)from elasticsearch import Elasticsearchtry:# Elasticsearch setupes_endpoint = os.environ.get("ELASTIC_ENDPOINT")es_client = Elasticsearch(es_endpoint,api_key=os.environ.get("ELASTIC_API_KEY"))
except Exception as e:es_client = None# Define a function to check ES status
def es_ping(_input):if es_client is None:return "ES client is not initialized."else:try:if es_client.ping():return "ES is connected."else:return "ES is not connected."except Exception as e:return f"Error pinging ES: {e}"# Define the ES status tool
es_status_tool = Tool(name="ES_Status",func=es_ping,description="Checks if Elasticsearch is connected.",
)# Define the RAG search function
def rag_search(query: str, dates: str):if es_client is None:return "ES client is not initialized."else:try:# Build the Elasticsearch querymust_clauses = []# If dates are provided, parse and include in queryif dates:# Dates must be in format 'YYYY-MM-DD' or 'YYYY-MM-DD to YYYY-MM-DD'date_parts = dates.strip().split(' to ')if len(date_parts) == 1:# Single datestart_date = date_parts[0]end_date = date_parts[0]elif len(date_parts) == 2:start_date = date_parts[0]end_date = date_parts[1]else:return "Invalid date format. Please use YYYY-MM-DD or YYYY-MM-DD to YYYY-MM-DD."date_range = {"range": {"date": {"gte": start_date,"lte": end_date}}}must_clauses.append(date_range)# Add the main query clausemain_query = {"nested": {"path": "text.inference.chunks","query": {"sparse_vector": {"inference_id": "elser_v2","field": "text.inference.chunks.embeddings","query": query}},"inner_hits": {"size": 2,"name": "bignews_embedded.text","_source": False}}}must_clauses.append(main_query)es_query = {"_source": ["text.text", "title", "date"],"query": {"bool": {"must": must_clauses}},"size": 3}response = es_client.search(index="bignews_embedded", body=es_query)hits = response["hits"]["hits"]if not hits:return "No articles found for your query."result_docs = []for hit in hits:source = hit["_source"]title = source.get("title", "No Title")text_content = source.get("text", {}).get("text", "")date = source.get("date", "No Date")doc = f"Title: {title}\nDate: {date}\n{text_content}\n"result_docs.append(doc)return "\n".join(result_docs)except Exception as e:return f"Error during RAG search: {e}"class RagSearchInput(BaseModel):query: str = Field(..., description="The search query for the knowledge base.")dates: str = Field(...,description="Date or date range for filtering results. Specify in format YYYY-MM-DD or YYYY-MM-DD to YYYY-MM-DD.")# Define the RAG search tool using StructuredTool
rag_search_tool = StructuredTool(name="RAG_Search",func=rag_search,description=("Use this tool to search for information about American politics from the knowledge base. ""**Input must include a search query and a date or date range.** ""Dates must be specified in this format YYYY-MM-DD or YYYY-MM-DD to YYYY-MM-DD."),args_schema=RagSearchInput
)# List of tools
tools = [es_status_tool, rag_search_tool]# Initialize memory to keep track of the conversation
memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)agent_chain = initialize_agent(tools,llm,agent=AgentType.OPENAI_FUNCTIONS,memory=memory,verbose=True,handle_parsing_errors=True,system_message="""You are an AI assistant that helps with questions about American politics using a knowledge base. Be concise, sharp, to the point, and respond in one paragraph.You have access to the following tools:- **ES_Status**: Checks if Elasticsearch is connected.- **RAG_Search**: Use this to search for information in the knowledge base. **Input must include a search query and a date or date range.** Dates must be specified in this format YYYY-MM-DD or YYYY-MM-DD to YYYY-MM-DD.**Important Instructions:**- **Extract dates or date ranges from the user's question.**- **If the user does not provide a date or date range, politely ask them to provide one before proceeding.**When you decide to use a tool, use the following format *exactly*:Thought: [Your thought process about what you need to do next]Action: [The action to take, should be one of [ES_Status, RAG_Search]]Action Input: {"query": "the search query", "dates": "the date or date range"}If you receive an observation after an action, you should consider it and then decide your next step. If you have enough information to answer the user's question, respond with:Thought: [Your thought process]Assistant: [Your final answer to the user]**Examples:**- **User's Question:** "Tell me about the 2020 California wildfires."Thought: I need to search for information about the 2020 California wildfires.Action: RAG_SearchAction Input: {"query": "California wildfires", "dates": "2020-01-01 to 2020-12-31"}- **User's Question:** "What happened during the presidential election?"Thought: The user didn't specify a date. I should ask for a date range.Assistant: Could you please specify the date or date range for the presidential election you're interested in?Always ensure that your output strictly follows one of the above formats, and do not include any additional text or formatting.Remember:- **Do not** include any text before or after the specified format.- **Do not** add extra explanations.- **Do not** include markdown, bullet points, or numbered lists unless it is part of the Assistant's final answer.Your goal is to assist the user by effectively using the tools when necessary and providing clear and concise answers."""
)# Interactive conversation with the agent
def main():print("Welcome to the chat agent. Type 'exit' to quit.")while True:user_input = input("You: ")if user_input.lower() in ['exit', 'quit']:print("Goodbye!")break# Update method call to address deprecation warningresponse = agent_chain.invoke(input=user_input)print("Assistant:", response['output'])if __name__ == "__main__":main()

Elasticsearch 包含许多新功能,可帮助你针对自己的用例构建最佳搜索解决方案。深入了解我们的示例笔记本以了解更多信息,开始免费云试用,或立即在本地机器上试用 Elastic。

原文:https://www.elastic.co/search-labs/blog/rag-agent-tool-elasticsearch-langchain

相关文章:

带有 Elasticsearch 和 Langchain 的 Agentic RAG

作者:来自 Elastic Han Xiang Choong 讨论并实现 Elastic RAG 的代理流程,其中 LLM 选择调用 Elastic KB。 更多阅读:Elasticsearch:基于 Langchain 的 Elasticsearch Agent 对文档的搜索。 简介 代理是将 LLM 应用于实际用例的…...

【数据结构与算法】深度优先搜索:树与图的路径探寻之道

一、引言 在计算机科学领域,树与图的路径搜索是一个基础且重要的问题,而深度优先搜索算法(Depth First Search,简称 DFS)则是解决此类问题的经典算法之一。深度优先搜索算法通过从起始节点开始,沿着一条路径…...

vue3项目结合Echarts实现甘特图(可拖拽、选中等操作)

效果图: 图一:选中操作 图二:上下左右拖拽操作 本案例在echarts​​​​​​​示例机场航班甘特图的基础上修改​​​​​​​ 封装ganttEcharts组件,测试数据 airport-schedule.jsonganttEcharts代码: 直接复制粘贴可测​​​​…...

【EXCEL 逻辑函数】AND、OR、XOR、NOT、IF、IFS、IFERROR、IFNA、SWITCH

目录 AND:当所有条件都为真时返回 TRUE,否则返回 FALSE OR:当任一条件为真时返回 TRUE,否则返回 FALSE XOR:当奇数个条件为真时返回 TRUE,否则返回 FALSE NOT :反转逻辑值 IF:根…...

单片机长耗时前后台任务优化

代码: void Task_10ms(void) {... }//改 void Task_2ms(void) {static uint8_t s_state 0switch(s_state){case 0:....s_state 1;break;case 1:....s_state 2;break;case 3:....s_state 1;break;default: //此段可以去除s_state 0;break; } } 参考链接 MCU长…...

java引入jedis并且关于开放redis端口问题

博主主页: 码农派大星. 数据结构专栏:Java数据结构 数据库专栏:数据库 JavaEE专栏:JavaEE 软件测试专栏:软件测试 关注博主带你了解更多知识 目录 1. 引入jedis ​编辑 2. 关于java客户端开放redis端口问题 3. 连接redis服务器 redis服务器在官网公开了使用的协议: resp…...

测试电脑是否真实多核CPU

测试电脑是否真实多核CPU 在CPU的描述上现在多数看到的是多核心/多内核,看上去就像是多CPU的样子。但核心是有分真实核心和虚拟核心。如果是真实的多核心,多线程是能够并行。如果不是多核心,多线程就只能够并发。 这里就直接采用多线程的应用…...

Ubuntu 安装实时内核指南

在运行需要高精度和低延迟响应的机器人驱动程序时,安装一个具备实时内核(Real-Time Kernel)的 Ubuntu 系统是至关重要的。若缺乏实时系统的支持,高频率的控制指令可能会导致机器人运动轨迹不流畅,甚至产生抖动现象。以…...

LeetCode:1387. 将整数按权重排序(记忆化搜索 Java)

目录 1387. 将整数按权重排序 题目描述: 实现代码与解析: 记忆化搜索 原理思路: 1387. 将整数按权重排序 题目描述: 我们将整数 x 的 权重 定义为按照下述规则将 x 变成 1 所需要的步数: 如果 x 是偶数&#xff…...

某音最新滑块3.5.68(Web/App皆可支持)

某音滑块核心是 captchaBody 参数 难度较大 h5_sdk_version - 代表验证码的版本 如何代表通过验证了呢? 1.web端 fp参数 - verify_m4zafhzb_yARRD6RZ_YwNj_4gjp_AdsL_yxw0thiqv0ub 2.移动端 did参数 - 1997744780462444 当该接口返回如下数据即通过验证码 该设…...

FFmpeg 框架简介和文件解复用

文章目录 ffmpeg框架简介libavformat库libavcodec库libavdevice库 复用(muxers)和解复用(demuxers)容器格式FLVScript Tag Data结构(脚本类型、帧类型)Audio Tag Data结构(音频Tag)V…...

观察者模式(sigslot in C++)

大家,我是东风,今天抽点时间整理一下我很久前关注的一个不错的库,可以支持我们在使用标准C的时候使用信号槽机制进行观察者模式设计,sigslot 官网: http://sigslot.sourceforge.net/ 本文较为详尽探讨了一种观察者模…...

git企业开发的相关理论(二)

目录 git企业开发的相关理论(一) 八.修改文件 九.版本回退 十.撤销修改 情况一(还没有add) 情况二(add后还没有commit) 情况三(commit后还没有push) 十一.删除本地仓库中的文件 方法一 方法二 十二.理解分支 1.常见的分支工作流程 2.合并冲…...

力扣-图论-70【算法学习day.70】

前言 ###我做这类文章一个重要的目的还是给正在学习的大家提供方向和记录学习过程(例如想要掌握基础用法,该刷哪些题?)我的解析也不会做的非常详细,只会提供思路和一些关键点,力扣上的大佬们的题解质量是非…...

jmeter中的prev对象

在jmeter中通过beanshell、JSR223的各种处理器编写脚本时,都会看到页面上有这样的说明 这些ctx、vars、props、OUT、sampler、prev等等都是可以直接在脚本中使用的对象,由jmeter抛出 今天主要讲一下prev的使用 SampleResult prev jmctx.getPreviousRe…...

机器学习中的密度聚类算法:深入解析与应用

在机器学习的广阔领域中,聚类算法作为一种无监督学习方法,扮演着至关重要的角色。其中,密度聚类算法以其独特的优势,在数据挖掘、图像分割、市场细分等多个领域得到了广泛应用。 一、密度聚类算法的基本原理 密度聚类算法是一种…...

简单分析一下 a,b,c=a+1,a+1,b+1 执行原理

在 Go 语言中,赋值表达式 a, b, c x, y, z 是同时进行的,但是其计算顺序是从左到右依次进行的。即在 a, b, c 被赋值之前,先计算 x, y, z 的值,并依次将它们赋值给 a, b, c。 例如:a, b, c a1, a1, b1,其…...

2025年前端面试热门题目——HTML|CSS|Javascript|TS知识

以下是对这些 HTML 面试问题的详细解答&#xff1a; 1. HTML 的 src 和 href 属性有什么区别? src (Source) 属性&#xff1a; 用于嵌入资源&#xff0c;例如图像、脚本或 iframe。加载资源时&#xff0c;当前页面的加载会暂停&#xff0c;直到资源加载完成。常用于 <img&g…...

将4G太阳能无线监控的视频接入电子监控大屏,要考虑哪些方面?

随着科技的飞速发展&#xff0c;4G太阳能无线监控系统以其独特的优势在远程监控领域脱颖而出。这种系统结合了太阳能供电的环保特性和4G无线传输的便捷性&#xff0c;为各种环境尤其是无电或电网不稳定的地区提供了一种高效、可靠的视频监控解决方案。将这些视频流接入大屏显示…...

【102. 二叉树的层序遍历 中等】

题目&#xff1a; 给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09;。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;[[3],[9,20],[15,7]] 示例…...

文件包含tomato靶机通关

靶机地址&#xff1a;192.168.152.152 注&#xff1a;靶机打开后在 kali 中扫描一下就能得到 打开网站 第一步信息收集 将网址放到 dirb 中扫描一下 得到了三个目录 我们挨个访问一下 第一个是主目录 第二个是主页面 第三个报错 第二步 我们在主目录页面继续访问 我们进行…...

oracle dblink 的创建及使用

Oracle Database Link&#xff08;DB Link&#xff09;是Oracle提供的一种功能&#xff0c;允许你在一个数据库中直接访问另一个远程或本地数据库的对象&#xff08;如表、视图、序列等&#xff09;。DB Link的设置简化了跨数据库操作&#xff0c;使得数据的集成和同步变得更加…...

java开发入门学习五-流程控制

流程控制语句 if&#xff0c; if...else&#xff0c; if..else if..else 与前端相同 略 switch case 与前端不同的是case不能使用表达式&#xff0c;使用表达式会报错 class TestSwitch {public static void main(String[] args) {// switch 表达式只能是特定的数据类型…...

【蓝桥杯——物联网设计与开发】拓展模块3 - 温度传感器模块

一、温度传感器模块 &#xff08;1&#xff09;资源介绍 &#x1f505;原理图 蓝桥杯物联网竞赛实训平台提供了一个拓展接口 CN2&#xff0c;所有拓展模块均可直接安装在 Lora 终端上使用&#xff1b; 图1 拓展接口 温度传感器模块电路原理图如下所示&#xff1a; 图2 …...

Zookeeper 底层原理解析

一、引言 在分布式系统的浩瀚星空中&#xff0c;Zookeeper 宛如一颗最为闪耀的导航星&#xff0c;为众多分布式应用指引方向、保驾护航。无论是大名鼎鼎的 Hadoop、HBase&#xff0c;还是其他各类复杂的分布式架构&#xff0c;Zookeeper 都扮演着不可或缺的关键角色。它如同一…...

面试题整理9----谈谈对k8s的理解1

谈谈对k8s的理解 1. Kubernetes 概念 1.1 Kubernetes是什么 Kubernetes 是一个可移植、可扩展的开源平台&#xff0c;用于管理容器化的工作负载和服务&#xff0c;方便进行声明式配置和自动化。Kubernetes 拥有一个庞大且快速增长的生态系统&#xff0c;其服务、支持和工具的…...

PromptGIP:Unifying lmage Processing as Visual Prompting Question Answering

“Unifying Image Processing as Visual Prompting Question Answering” 文章提出了一种名为 PromptGIP 的通用模型&#xff0c;将图像处理任务统一为视觉提示问答范式&#xff0c;在多个图像处理任务上展现出良好性能&#xff0c;为通用图像处理提供了新的思路和方法。 confe…...

chart文件结构

在 Helm 中&#xff0c;Chart 是一个用于定义、安装和升级 Kubernetes 应用程序的包。Chart 文件结构遵循一定的目录和文件组织方式&#xff0c;以下是典型的 Helm Chart 文件结构&#xff1a; 1. Chart 文件结构示例 mychart/ ├── Chart.yaml # 描述 Chart 的基…...

SQL优化

SQL优化 插入数据 insert优化 批量插入 insert into tb_test 2values(1, Tom), (2, Cat), (3, jerry); 手动提交事务 start transaction; insert into test1 values(4, Tom), (5, Cat), (6, jerry); insert into test1 values(7, Tom), (8, Cat), (9, jerry); insert int…...

输出1-100之间的随机数,控制输出格式,每行10个(注释有详解)

C 随机数生成与格式化输出 在编程中&#xff0c;随机数的生成是一个常见的需求&#xff0c;尤其是在游戏开发、模拟实验和数据分析等领域。本文将通过一个简单的 C 程序来演示如何生成随机数并进行格式化输出。我们将逐步解析代码&#xff0c;并讨论其工作原理及应用场景。 代…...

【数字化】华为数字化转型架构蓝图-2

目录 1、客户联结的架构思路 1.1 ROADS体验设计 1.2 具体应用场景 1.3 统一的数据底座 1.4 案例与成效 2、一线作战平台的架构思路 2.1 核心要素 2.2 关键功能 2.3 实施路径 2.4 案例与成效 3、能力数字化的架构思路 3.1 能力数字化的核心目标 3.2 能力数字化的实…...

MyBatis是什么?为什么有全自动ORM框架还是MyBatis比较受欢迎?

MyBatis是什么&#xff1f; MyBatis是一个半自动的ORM持久层框架&#xff0c;内部封装了JDBC&#xff0c;mybatis是通过XML或注解的方式将需要执行的statement配置&#xff0c;支持定制化sql&#xff0c;存储过程以及高级映射。 解释 所谓的半自动ORM意思就是将JDBC的工作交…...

基础元器件的学习

1、二极管 1.1二极管的符号 ZD是稳压二极管 VD、V、D是普通二极管的符号。 1.2二极管的反向恢复时间 首先交流电为上正下负&#xff0c;然后下正上负。当二极管接到反向电压&#xff0c;二极管存在寄生电容&#xff0c;电压不能立刻突变&#xff0c;当输入频率变高时&#…...

GTID下复制问题和解决

环境介绍 数据库1主2从&#xff0c;mysql版本是v5.19 表结构 一、主库新增记录&#xff0c;从库提示主键冲突 模拟故障 1&#xff0c; master上关闭 sql_log_bin,删除id 103 后打开 2&#xff0c; 确认此时从库有id103,主库没有 3&#xff0c; master insert id103 主从异常…...

Linux 下的 GPT 和 MBR 分区表详解

文章目录 Linux 下的 GPT 和 MBR 分区表详解一、分区表的作用二、MBR&#xff08;Master Boot Record&#xff09;1. **特点**2. **优点**3. **缺点**4. **适用场景** 三、GPT&#xff08;GUID Partition Table&#xff09;1. **特点**2. **优点**3. **缺点**4. **适用场景** 四…...

mysql的事务控制和数据库的备份和恢复

事务控制语句 行锁和死锁 行锁 两个客户端同时对同一索引行进行操作 客户端1正常运行 客户端2想修改&#xff0c;被锁行 除非将事务提交才能继续运行 死锁 客户端1删除第5行 客户端2设置第1行为排他锁 客户端1删除行1被锁 客户端2更新行5被锁 如何避免死锁 mysql的备份和还…...

2014年IMO第4题

△ A B C \triangle ABC △ABC 中, B C BC BC 上有一点 P P P 满足 ∠ B A P = ∠ A C B \angle BAP=\angle ACB ∠BAP=∠ACB, 还有一点 Q Q Q 满足 ∠ A = Q A C = ∠ A B C \angle A=QAC=\angle ABC ∠A=QAC=∠ABC. 分别延长 A P AP AP, A Q AQ AQ 一倍至 M M M, N …...

如何实现层叠布局

文章目录 1 概念介绍2 使用方法3 示例代码我们在上一章回中介绍了GirdView Widget,本章回中将介绍Stack这种Widget,闲话休提,让我们一起Talk Flutter吧。 1 概念介绍 在Flutter中Stack主要用来叠加显示其它的Widget,类似我们日常生活中的楼层或者说PS中的图层,因此它也是一…...

Qwen2.5-7B-Instruct Lora微调

Qwen2.5-7B-Instruct Lora 微调 本文简要介绍如何基于 transformers、peft 等框架&#xff0c;对 Qwen2.5-7B-Instruct 模型进行 Lora 微调。Lora 是一种高效微调方法。 环境配置 在完成基本环境配置和本地模型部署的情况下&#xff0c;你还需要安装一些第三方库&#xff0c…...

MacOS安装MySQL

官网下载MySQL 苹果芯片选择ARM版本 安装过程中会要求你输入root的密码&#xff08;不少于8位&#xff09;&#xff0c;这里设置为12345678 打开系统设置查看是否成功安装MySQL 配置MySQL环境变量 vi ~/.zshrc加入一行export PATH$PATH:/usr/local/mysql/bin 执行source ~/…...

基础库正则表达式

我们已经可以用requests 库来获取网页的源代码&#xff0c;得到 HTML 代码。但我们真正想要的数据是包含在 HTML代码之中的&#xff0c;要怎样才能从 HTML,代码中获取想要的信息呢?正则表达式就是其中一个有效的方法。 本篇博客我们将了解一下正则表达式的相关用法。正则表达…...

Matlab 和 R 语言的数组索引都是从 1 开始,并且是左闭右闭的

文章目录 一、前言二、主要内容三、小结 &#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 一、前言 在早期的计算机科学中&#xff0c;数组索引从 1 开始是很常见的。例如&#xff0c;Fortran 和 Pascal 等编程语言也采用了从 1 开始的索引。 这种索引…...

选择排序和冒泡排序;MySQL架构

1. 选择排序和冒泡排序 &#xff08;1&#xff09;选择排序 原理&#xff1a; 选择排序有升序和降序两种排序方法。升序排序的原理是&#xff1a;对于一个无序数列&#xff0c;先假定其中一个数为这个数列的最小值&#xff0c;然后让这个假定最小值和其他数依次比较&#xff0…...

蓝桥杯算法训练 黑色星期五

题目描述 有些西方人比较迷信&#xff0c;如果某个月的13号正好是星期五&#xff0c;他们就会觉得不太吉利&#xff0c;用古人的说法&#xff0c;就是“诸事不宜”。请你编写一个程序&#xff0c;统计出在某个特定的年份中&#xff0c;出现了多少次既是13号又是星期五的情形&am…...

Mybatis-Plus快速入门

参考&#xff1a;黑马MyBatisPlus教程全套视频教程&#xff0c;快速精通mybatisplus框架 1.Mapper-plus配置 1.MapperScan("Mapper目录的位置") 2.Mapper层文件需要继承BaseMapper extends BaseMapper<实体类> 3.开启日志 4.配置类 Configuration public cl…...

MySQL库的操作

目录 1. 创建数据库2. 创建数据库案例3. 认识系统编码以及字符集和校验规则4. 操纵数据库4.1 查看数据库4.2 显示创建语句4.3 修改数据库4.4 数据库的删除4.5 备份和恢复4.6 查看连接情况 1. 创建数据库 &#xff08;1&#xff09;语法&#xff1a; create database db_name;…...

JVM性能优化一:初识内存泄露-内存溢出-垃圾回收

本文主要是让你充分的认识到什么叫做内存泄露&#xff0c;什么叫做内存溢出&#xff0c;别再傻傻分不清了&#xff0c;别再动不动的升级服务器的内存了。 文章目录 1.基本概念1.1.内存泄露1.2.内存溢出1.3.垃圾回收1.4.内存泄露-垃圾回收-内存溢出三者的关系关系 2.代码示例2.…...

2024年山东省职业院校技能大赛网络建设与运维X86架构与ARM架构搭建赛题

完整赛题解析主页联系&#xff01; 一、X86架构计算机操作系统安装与管理 1.PC1 系统为 ubuntu-desktop-amd64 系统&#xff08;已安装&#xff0c;语言为英文&#xff09;&#xff0c;登录用户为 ubuntu&#xff0c;密码为Key-1122。配置ubuntu用户能免密使用sudo命令。 sud…...

flask_sqlalchemy event监听查询事件

flask_sqlalchemy event监听查询事件 在Flask-SQLAlchemy中&#xff0c;可以使用事件监听器来监控查询事件。这可以通过listens_for(ModelClass, “event_name”)装饰器来实现&#xff0c;其中ModelClass是你想要监控的模型类&#xff0c;event_name是你想要监控的事件名称&…...

解决vscode ssh远程连接服务器一直卡在下载 vscode server问题

目录 方法1&#xff1a;使用科学上网 方法2&#xff1a;手动下载 方法3 在使用vscode使用ssh远程连接服务器时&#xff0c;一直卡在下载"vscode 服务器"阶段&#xff0c;但MobaXterm可以正常连接服务器&#xff0c;大概率是网络问题&#xff0c;解决方法如下: 方…...