带有 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 本身可能缺乏这两者。

但是,标准 RAG 部署模型有一个缺点 - 它很死板。LLM 无法选择从哪个知识库中提取信息。它也无法选择使用其他工具,例如 Google 或 Bing 等网络搜索引擎 API。它无法查看当前天气,无法使用计算器,也无法考虑除给定知识库之外的任何工具的输出。
Agentic 模型的不同之处在于选择。
术语说明
工具使用(Tool usage),即 Langchain 上下文中使用的术语,也称为函数调用。无论出于何种目的,这两个术语都是可以互换的 - 两者都指 LLM 被赋予一组函数或工具,它可以用来补充其能力或影响世界。请耐心等待,因为我在本文的其余部分都使用了 “工具使用 - Tool Usage”。
选择
赋予 LLM 决策能力,并为其提供一套工具。根据对话的状态和历史,LLM 将选择是否使用每个工具,并将工具的输出纳入其响应中。
这些工具可能是知识库、计算器、网络搜索引擎和爬虫 - 种类繁多,没有限制或结束。LLM 能够执行复杂的操作和任务,而不仅仅是生成文本。

让我们实现一个代理的简单示例。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 应用于实际用例的…...

Jenkins持续集成部署——jenkins安装
前言 Jenkins 是一个开源的自动化服务器,主要用于持续集成(CI)和持续交付(CD)。它为软件开发团队提供了一个易于使用的平台来自动化构建、测试和部署应用程序的过程。 Jenkins 主要功能 1. 持续集成 (CI) 自动构建…...

微信小程序开发入门
实现滚动 需要设置高度和边框 轮播图 差值表达式( {{表达式的值}} ),info数据要写到js文件的data数据中 小程序中常用的事件...

深度学习中自适应学习率调度器
传统观点认为,太大的学习率不利于优化深度神经网络,而相比固定的学习率而言,变化的学习率更能提供快速的收敛。基于此,本文作者基于理论基础提出了一个计算深度神经网络学习率的新方法。实验结果证明了该方法的有效性。 训练神经…...

Phono3py hdf5文件数据读取与处理
Phono3py是一个主要用python写的声子-声子相互作用相关性质的模拟包,可以基于有限位移算法实现三阶力常数和晶格热导率的计算过程,同时输出包括声速,格林奈森常数,声子寿命和累积晶格热导率等参量。 相关介绍和安装请参考往期推荐…...

React 底部加载组件(基于antd)
底部加载组件的意义在于提供一种流畅的用户体验,以便在用户滚动到页面底部时自动加载更多内容。这样可以让用户无需离开当前页面,就能够无缝地浏览更多的内容.通过底部加载组件,可以分批加载页面内容,减少一次性加载大量数据对页面…...

将HTML转换为PDF:使用Spire.Doc的详细指南(一) 试用版
目录 引言 1. 为什么选择 Spire.Doc? 1.1 主要特点 1.2 适用场景 2. 准备工作 2.1 引入 Spire.Doc 依赖 2.2 禁用 SSL 证书验证 3. 实现功能 3.1 主类结构 3.2 代码解析 4. 处理图像 5. 性能优化 5.1 异步下载图像 示例代码 5.2 批量处理优化 示例代…...

数据结构经典算法总复习(下卷)
第五章:树和二叉树 先序遍历二叉树的非递归算法。 void PreOrderTraverse(BiTree T, void (*Visit)(TElemType)) {//表示用于查找的函数的指针Stack S; BiTree p T;InitStack(S);//S模拟工作栈while (p || !StackEmpty(S)) {//S为空且下一个结点为空,意味着结束遍…...

mac 安装graalvm
Download GraalVM 上面链接选择jdk的版本 以及系统的环境下载graalvm的tar包 解压tar包 tar -xzf graalvm-jdk-<version>_macos-<architecture>.tar.gz 移入java的文件夹目录 sudo mv graalvm-jdk-<version> /Library/Java/JavaVirtualMachines 设置环境变…...

【SH】在Ubuntu Server 24中基于Python Web应用的Flask Web开发(实现POST请求)学习笔记
文章目录 Flask开发环境搭建保持Flask运行Debug调试 路由和视图可变路由 请求和响应获取请求信息Request属性响应状态码常见状态码CookieSession 表单GET请求POST请求 Flask 在用户使用浏览器访问网页的过程中,浏览器首先会发送一个请求到服务器,服务器…...

一些经济政治学类书籍推荐 --- 以及与之相关我的经历和理解
我给所开设的兴趣专栏_墨#≯的博客-CSDN博客,的介绍是: 聊聊关于文学、经济(股票等)、法律方面的个人感受与理解。 不过目前已有的两篇以及现在在写的这篇都是经济相关的,其实专栏开设的9月至今,我也看了好几本文学相关的书&#…...

设计模式之 abstract factory
适用场景 一个系统要独立于它的产品的创建、组合和表示时。一个系统要由多个产品系列中的一个来配置时。当你要强调一系列相关的产品对象的设计以便进行联合使用时。当你提供一个产品类库,而只想显示它们的接口而不是实现时 架构演示 首先client这个东西可以接触到…...

汽车IVI中控开发入门及进阶(三十八):手机投屏HiCar开发
手机投屏轻松实现手机与汽车的无缝连接,导航、音乐、通话等功能应有尽有,还支持更多第三方应用,让车载互联生活更加丰富多彩。 HiCar在兼容性和开放性上更具优势。 手机投屏可以说是车机的杀手级应用,大大拓宽了车机的可用性范围。其中华为推出的HiCar就是非常好用的一种。…...

Springmvc,spring ,mybatis,整合,ssm
上一章内容: 1.spring框架:作用 开源的框架--提供IOC和AOPIOC控制反转 把创建对象的权力交于spring创建,并管理对象的生命周期,通过DI完成对象属性的注入。 2. spring配置中<bean>也可以使用注解Component Controller Service Repo…...

《庐山派从入门到...》板载按键启动!
《庐山派从入门到...》板载按键启动! 《庐山派从入门到...》板载按键启动! 视频内容大致如下 我们之前了解了GPIO的输出模式使用方法,并且成功点灯,很明显本篇要来分享的自然是GPIO的输入模式 正好回顾一下之前学的python基础包…...

Mapbox-GL 中 `token` 的使用
Mapbox-GL 是一个开源的 JavaScript 库,允许开发者在网页上渲染交互式地图。token 在 Mapbox 中主要是指 access token,它用于身份验证和授权,确保应用程序能够访问 Mapbox 的地图服务。 下面详细解析 Mapbox GL 中 token 的使用,…...

Flutter组件————PageView
PageView 可以创建滑动页面效果的widget,它允许用户通过水平或垂直滑动手势在多个子页面(child widgets)之间切换。每个子页面通常占据屏幕的全部空间。 参数 参数名类型描述childrenList<Widget>包含在 PageView 中的所有子部件&am…...

c#自定义事件
自定义事件类 定义一个自定义事件参数类 为了传递更多的信息,我们定义一个自定义的事件参数类 public class CustomEventArgs : EventArgs {public string Message { get; set; } } 3. 定义一个发布者类 接下来,我们定义一个发布者类,包含…...

【读书笔记】《论语别裁》寂寞的享受
1.内容摘要 在《论语别裁》中,第一章《学而》探讨了做学问的孤独与坚持。作者强调,真正的学者在追求知识时,必须保持“仁”与“义”的核心价值观,愿意为自己的信念与理想而牺牲。他以孔子为例,描绘了孔子一生的寂寞与…...

Oracle筑基篇-调度算法-LRU的引入
常见的调度算法 图1 调度算法思维导图 一、LRU算法的典型使用场景 1. 操作系统中的页面置换 什么时候用到页面置换算法呢? 当CPU发出指令需要访问某个地址时,若该地址在TLB(Translation Lookaside Buffer,快表)或页…...

单元测试-Unittest框架实践
文章目录 1.Unittest简介1.1 自动化测试用例编写步骤1.2 相关概念1.3 用例编写规则1.4 断言方法 2.示例2.1 业务代码2.2 编写测试用例2.3 生成报告2.3.1 方法12.3.2 方法2 1.Unittest简介 Unittest是Python自带的单元测试框架,适用于:单元测试、Web自动…...

linux驱动:6ull(3)自动分配设备号来创建led驱动
在 linux驱动:6ull(2)的文章代码上进行更改 步骤: 创建入口函数和出口函数定义一个设备结构体和创建一个led设备在入口函数init中添加初始化led的gpio在入口函数init中添加自动分配设备号来创建led字符设备在出口函数中取消led的…...

GM_T 0039《密码模块安全检测要求》题目
单项选择题 根据GM/T 0039《密码模块安全检测要求》,送检单位的密码模块应包括()密码主管角色。 A.一个 B.两个 C.至少一个 D.至少两个 正确答案:C 多项选择题 根据GM/T 0039《密码模块安全检测要求》,关于非入侵式安全,以下属于安全三级密码模块要求的是()。 …...

第四届电气工程与控制科学
重要信息 官网:www.ic2ecs.com 时间:2024年12月27-29日 简介 第四届电气工程与控制科学定于2024年12月27-29日在中国南京召开。主要围绕“电气工程“、”控制科学“、”机械工程“、”自动化”等主题展开,旨在为从电…...

LabVIEW在电液比例控制与伺服控制中的应用
LabVIEW作为一种图形化编程环境,广泛应用于各类控制系统中,包括电液比例控制和伺服控制领域。在这些高精度、高动态要求的控制系统中,LabVIEW的优势尤为突出。以下从多个角度探讨其应用与优势: 1. 灵活的控制架构 LabVIEW为电…...

植物大战僵尸杂交版v3.0.2最新版本(附下载链接)
B站游戏作者潜艇伟伟迷于12月21日更新了植物大战僵尸杂交版3.0.2版本!!!,有b站账户的记得要给作者三连关注一下呀! 不多废话下载链接放上: 夸克网盘链接::https://pan.quark.cn/s/5c…...

车辆重识别代码笔记12.19
1、resnet_ibn_a和resnet网络的区别 ResNet-IBN-A 是在 ResNet 基础上进行了一些改进的变种,具体来说,它引入了 Instance Batch Normalization (IBN) 的概念,这在某些任务中(如图像识别、迁移学习等)有显著的性能提升。…...

linux内核网络分层概述
在开发应用时,我们使用 socket 实现网络数据的收发。以tcp为例,server端通过 socket, bind, listen来创建服务端,然后通过 accept接收客户端连接;客户端通过 socket和 connect系统调用来创建客户端。用于数据收发的系统调用包括 s…...

H3C交换机配置 telnet 服务
使用一个交换机做成 telnet 服务, telnet 可以使用指定端口开启三层交换机, 用于与 pc 互通, 也可以使用自带的 vlan1 设置 ip 然后达到互通, 因为华三的交换机端口默认是 access 口, 默认带 vlan1 , 直接设置 vlan1 的 ip 也就可以实现互通 实现互通 互通的两种方式 设置 vl…...

江苏计算机专转本 技能Mysql知识点总结(二)
三、SQL数据操纵语言(增删改查) 1.insert 语句(增) INSERT INTO 表名 (列1, 列2, 列3) VALUES (值1, 值2, 值3); 2.Delete 语句(删) //1. DELETE FROM 表名 WHERE 条件;//2. truncate table 表名; …...