Elastic AI agent builder 介绍(五)- 备份 tools 及 agents

Elastic AI Agent 备份与恢复工具

我经常会在我自己的电脑里重新安装我的 Elasticsearch 及 Kibana。如果我之前已经创建好的 agents 及 tools 不能保存下来,那么我在每次重新安装的时候,就需要手动一个一个地恢复原来的 tools 及 agents。这将是一个很大的工作。.在今天的文章里,我来介绍一下我创建的的一个小工具。它用来备份我们已经创建好的 agents 及 tools,并且可以把备份好的 tools 及 agents 恢复到 AI Agents Builder 里去。我还可以一次性地删除所有的 tools 及 agents。

安装

如果你还没有安装好 Elasticsearch 及 Kibana,还没有创建自己的 agents,那么请参考我之前的文章 “Elastic AI agent builder 介绍(一)”。这里就不再赘述。

接下来,我们下载已经写好的代码:

git clone https://github.com/liu-xiao-guo/es_agents_dump

在运行上面的应用之前,我们必须做如下的配置。在根目录下,创建如下的一个叫做 .env 的文件:

.env

ES_AGENT_URL=http://localhost:5601/api/agent_builder
KIBANA_URL=http://localhost:5601
ES_URL=https://localhost:9200
ES_API_KEY=WnJwR3RKb0JGQVVCVjdnb29yUkI6RHotbGZBTmJzMDJWUWszbTAtbDVjQQ==

你需要根据自己的配置进行相应的修改。

备份 tools 及 agents

es_agents_dump.py 

from dotenv import load_dotenv
import os
import requests
import json

load_dotenv()

ES_AGENT_URL = os.getenv("ES_AGENT_URL")
ES_API_KEY = os.getenv("ES_API_KEY")
KIBANA_URL = os.getenv("KIBANA_URL")
ES_URL = os.getenv("ES_URL")

# --- Setup Headers ---
HEADERS = {
    "Content-Type": "application/json",
    "kbn-xsrf": "true",
    "Authorization": f"ApiKey {ES_API_KEY}",
}

def make_http_request(url, method="GET", headers=None, data=None, params=None):
    """
    Make an HTTP request to the specified URL.
    
    Args:
        url (str): The URL to make the request to
        method (str): HTTP method (GET, POST, PUT, DELETE, etc.)
        headers (dict): Optional headers to include in the request
        data (dict): Optional data to send in the request body
        params (dict): Optional query parameters
    
    Returns:
        requests.Response: The response object
    """
    try:
        response = requests.request(
            method=method.upper(),
            url=url,
            headers=headers,
            json=data,
            params=params
        )
        response.raise_for_status()
        return response
    except requests.exceptions.RequestException as e:
        print(f"Error making request: {e}")
        return None


# Get all of the tools from the agent builder
def get_agent_builder_tools():  
    url = f"{ES_AGENT_URL}/tools"
    response = make_http_request(url, method="GET", headers=HEADERS)
    if response:
        return response.json()
    return None  


response = get_agent_builder_tools()
if response:
    print(json.dumps(response, indent=2))

    # Dump the response.results to a file
    if response and 'results' in response:
        with open('agent_tools.json', 'w') as f:
            json.dump(response['results'], f, indent=2)
        print("\nAgent tools dumped to agent_tools.json")


# Get all of the agents from the agent builder
def get_agent_builder_agents():  
    url = f"{ES_AGENT_URL}/agents"
    response = make_http_request(url, method="GET", headers=HEADERS)
    if response:
        return response.json()
    return None

response = get_agent_builder_agents()
if response:
    print(json.dumps(response, indent=2))

    # Dump the response.results to a file
    if response and 'results' in response:
        with open('agent_agents.json', 'w') as f:
            json.dump(response['results'], f, indent=2)
        print("\nAgent agents dumped to agent_agents.json")

进入到项目的根目录中,然后运行如下的命令:

 python es_agents_dump.py 

我们可以在当前的目录下看到一个生成的 agent_tools.json 文件:

[
  {
    "id": "platform.core.search",
    "type": "builtin",
    "description": "A powerful tool for searching and analyzing data within your Elasticsearch cluster.\nIt supports both full-text relevance searches and structured analytical queries.\n\nUse this tool for any query that involves finding documents, counting, aggregating, or summarizing data from a known index.\n\nExamples of queries:\n- \"find articles about serverless architecture\"\n- \"search for support tickets mentioning 'billing issue' or 'refund request'\"\n- \"what is our policy on parental leave?\"\n- \"list all products where the category is 'electronics'\"\n- \"show me the last 5 documents from that index\"\n- \"show me the sales over the last year break down by month\"\n\nNote:\n- The 'index' parameter can be used to specify which index to search against.\n If not provided, the tool will decide itself which is the best index to use.\n- It is perfectly fine not to specify the 'index' parameter. It should only be specified when you already\n know about the index and fields you want to search on, e.g. if the user explicitly specified it.\n    ",
    "tags": [],
    "configuration": {},
    "readonly": true
  },
  {
    "id": "platform.core.get_document_by_id",
    "type": "builtin",
    "description": "Retrieve the full content (source) of an Elasticsearch document based on its ID and index name.",
    "tags": [],
    "configuration": {},
    "readonly": true
  },
  {
    "id": "platform.core.execute_esql",
    "type": "builtin",
    "description": "Execute an ES|QL query and return the results in a tabular format.\n\n**IMPORTANT**: This tool only **runs** queries; it does not write them.\nThink of this as the final step after a query has been prepared.\n\nYou **must** get the query from one of two sources before calling this tool:\n1.  The output of the `platform.core.generate_esql` tool (if the tool is available).\n2.  A verbatim query provided directly by the user.\n\nUnder no circumstances should you invent, guess, or modify a query yourself for this tool.\nIf you need a query, use the `platform.core.generate_esql` tool first.",
    "tags": [],
    "configuration": {},
    "readonly": true
  },
 ...
]

它的内容如上。这样我们就把我们所有的 tools 保存下来了。同时,我们可以看见一个生成的 agent_agents.json 文件。它的内容如下:

[
  {
    "id": "elastic-ai-agent",
    "name": "Elastic AI Agent",
    "description": "Elastic AI Agent",
    "configuration": {
      "tools": [
        {
          "tool_ids": [
            "platform.core.search",
            "platform.core.list_indices",
            "platform.core.get_index_mapping",
            "platform.core.get_document_by_id"
          ]
        }
      ]
    },
    "type": "chat",
    "readonly": true
  },
  {
    "id": "find_people_in_age_range",
    "type": "chat",
    "name": "Find people in age range",
    "description": "Find people in age range",
    "labels": [],
    "avatar_color": "",
    "avatar_symbol": "",
    "configuration": {
      "instructions": "Search for the people between ages",
      "tools": [
        {
          "tool_ids": [
            "platform.core.search",
            "platform.core.list_indices",
            "platform.core.get_index_mapping",
            "platform.core.get_document_by_id",
            "find_people_in_ages"
          ]
        }
      ]
    },
    "readonly": false
 ...
]

这样,我们就保存下来我们所有的 agents。

导入 tools 及 agents

es_agents_import.py 

from dotenv import load_dotenv
import os
import requests
import json

load_dotenv()

ES_AGENT_URL = os.getenv("ES_AGENT_URL")
ES_API_KEY = os.getenv("ES_API_KEY")
KIBANA_URL = os.getenv("KIBANA_URL")
ES_URL = os.getenv("ES_URL")

# --- Setup Headers ---
HEADERS = {
    "Content-Type": "application/json",
    "kbn-xsrf": "true",
    "Authorization": f"ApiKey {ES_API_KEY}",
}

def make_http_request(url, method="GET", headers=None, data=None, params=None):
    """
    Make an HTTP request to the specified URL.
    
    Args:
        url (str): The URL to make the request to
        method (str): HTTP method (GET, POST, PUT, DELETE, etc.)
        headers (dict): Optional headers to include in the request
        data (dict): Optional data to send in the request body
        params (dict): Optional query parameters
    
    Returns:
        requests.Response: The response object
    """
    try:
        response = requests.request(
            method=method.upper(),
            url=url,
            headers=headers,
            json=data,
            params=params
        )
        response.raise_for_status()
        return response
    except requests.exceptions.RequestException as e:
        # print(f"Error making request: {e}")
        return None

# Define a list of tool ids to avoid to import
AGENT_TOOLS_TO_AVOID_IMPORT = ["platform.core.search", 
                               "platform.core.execute_esql", 
                               "platform.core.generate_esql",
                               "platform.core.list_indices", 
                               "platform.core.get_index_mapping",
                               "platform.core.index_explorer",
                               "platform.core.get_document_by_id"]
    
# import tools into the agent builder
def import_agent_builder_tool(tool_data): 
    url = f"{ES_AGENT_URL}/tools"
    response = make_http_request(url, method="POST", headers=HEADERS, data=tool_data)
    if response:
        return response.json()
    return None

# Add a function to check whether a tool already exists in the agent builder
def tool_exists_in_agent_builder(tool_id):
    url = f"{ES_AGENT_URL}/tools/{tool_id}"
    response = make_http_request(url, method="GET", headers=HEADERS)
    if response and response.status_code == 200:
        return True
    return False

# Read in agent_tools.json file, and import each tool into the agent builder
with open("agent_tools.json", "r") as f:    
    agent_tools = json.load(f)
    for tool in agent_tools:
        if tool["id"] in AGENT_TOOLS_TO_AVOID_IMPORT:   
            print(f"Skipping import of tool {tool['id']}")
            continue
        
        if tool_exists_in_agent_builder(tool["id"]):
            print(f"Tool {tool['id']} already exists, skipping import")
            continue
            
        print(f"Importing tool {tool['id']}")
        # print(json.dumps(tool, indent=2, ensure_ascii=False))
        tool.pop('readonly', None)
        response = import_agent_builder_tool(tool)
        if response:
            print(f"Successfully imported tool {tool['id']}")
        else:
            print(f"Failed to import tool {tool['id']}")
    

AGENTS_TO_AVOID_IMPORT = ["elastic-ai-agent"]

# import agents into the agent builder
def import_agent_builder_agent(agent_data): 
    url = f"{ES_AGENT_URL}/agents"
    response = make_http_request(url, method="POST", headers=HEADERS, data=agent_data)
    if response:
        return response.json()
    return None

# Add a function to check whether an agent already exists in the agent builder
def agent_exists_in_agent_builder(agent_id):
    url = f"{ES_AGENT_URL}/agents/{agent_id}"
    response = make_http_request(url, method="GET", headers=HEADERS)
    if response and response.status_code == 200:
        return True
    return False

# Read in agent_agents.json file, and import each agent into the agent builder
with open("agent_agents.json", "r") as f:    
    agent_agents = json.load(f)
    for agent in agent_agents:
        if agent["id"] in AGENTS_TO_AVOID_IMPORT:   
            print(f"Skipping import of agent {agent['id']}")
            continue
        
        if agent_exists_in_agent_builder(agent["id"]):
            print(f"Agent {agent['id']} already exists, skipping import")
            continue
            
        print(f"Importing agent {agent['id']}")
        agent.pop('readonly', None)
        agent.pop('type', None)
        # print(json.dumps(agent, indent=2, ensure_ascii=False))        
        response = import_agent_builder_agent(agent)
        if response:
            print(f"Successfully imported agent {agent['id']}")
        else:
            print(f"Failed to import agent {agent['id']}")  

接下来,我们从 agent_agent.json 及 agent_tools.json 中导入我们的 tools 及 agents。我们使用如下的命令:

python es_agents_import.py 
$ pwd
/Users/liuxg/python/es_agents_dump
$ python es_agents_import.py 
Skipping import of tool platform.core.search
Skipping import of tool platform.core.get_document_by_id
Skipping import of tool platform.core.execute_esql
Skipping import of tool platform.core.generate_esql
Skipping import of tool platform.core.get_index_mapping
Skipping import of tool platform.core.list_indices
Skipping import of tool platform.core.index_explorer
Tool search_for_parents already exists, skipping import
Tool software_developers already exists, skipping import
Tool people_profession_search already exists, skipping import
Tool find_people_in_ages already exists, skipping import
Tool find_people_in_time_range already exists, skipping import
Tool find_client_exposure_to_negative_news already exists, skipping import
Tool find_cheapest_ticket_from_cn_us already exists, skipping import
Tool example-esql-tool already exists, skipping import
Tool find_average_age already exists, skipping import
Skipping import of agent elastic-ai-agent
Agent find_people_in_age_range already exists, skipping import
Agent people_profession_search already exists, skipping import
Agent software_developers already exists, skipping import
Agent find_parents already exists, skipping import
Agent find_people_in_time_range already exists, skipping import
Agent financial_assistant already exists, skipping import
Agent find_the_cheapest_ticket_from_cn_us already exists, skipping import
Agent find_out_average_age already exists, skipping import

如果 tools 及 agents 的 ID 已经存在,那么就跳过。同时我们跳过系统自带的 agents 及 tools。

清除所有的 tools 及 agents

es_agents_clear.py 

from dotenv import load_dotenv
import os
import requests
import json

load_dotenv()

ES_AGENT_URL = os.getenv("ES_AGENT_URL")
ES_API_KEY = os.getenv("ES_API_KEY")
KIBANA_URL = os.getenv("KIBANA_URL")
ES_URL = os.getenv("ES_URL")

# --- Setup Headers ---
HEADERS = {
    "Content-Type": "application/json",
    "kbn-xsrf": "true",
    "Authorization": f"ApiKey {ES_API_KEY}",
}

def make_http_request(url, method="GET", headers=None, data=None, params=None):
    """
    Make an HTTP request to the specified URL.
    
    Args:
        url (str): The URL to make the request to
        method (str): HTTP method (GET, POST, PUT, DELETE, etc.)
        headers (dict): Optional headers to include in the request
        data (dict): Optional data to send in the request body
        params (dict): Optional query parameters
    
    Returns:
        requests.Response: The response object
    """
    try:
        response = requests.request(
            method=method.upper(),
            url=url,
            headers=headers,
            json=data,
            params=params
        )
        response.raise_for_status()
        return response
    except requests.exceptions.RequestException as e:
        # print(f"Error making request: {e}")
        return None

# Define a list of tool ids to avoid to import
AGENT_TOOLS_TO_AVOID_DELETE = ["platform.core.search", 
                               "platform.core.execute_esql", 
                               "platform.core.generate_esql",
                               "platform.core.list_indices", 
                               "platform.core.get_index_mapping",
                               "platform.core.index_explorer",
                               "platform.core.get_document_by_id"]

AGENTS_TO_AVOID_DELETE = ["elastic-ai-agent"]


# Delete tools from the agent builder
def delete_agent_builder_tool(tool_id): 
    url = f"{ES_AGENT_URL}/tools/{tool_id}"
    response = make_http_request(url, method="DELETE", headers=HEADERS)
    if response:
        return response.json()
    return None

# Delete all of the tools from the agent builder except those in the avoid list
def clear_agent_builder_tools():  
    url = f"{ES_AGENT_URL}/tools"
    response = make_http_request(url, method="GET", headers=HEADERS)
    if response:
        tools = response.json()
        for tool in tools.get('results', []):
            # print(json.dumps(tool, indent=2, ensure_ascii=False))
            tool_id = tool.get("id")
            if tool_id not in AGENT_TOOLS_TO_AVOID_DELETE:
                delete_response = delete_agent_builder_tool(tool_id)
                if delete_response:
                    print(f"Deleted tool: {tool_id}")
                else:
                    print(f"Failed to delete tool: {tool_id}")
    else:
        print("Failed to retrieve tools.")

clear_agent_builder_tools()


# Delete agents from the agent builder
def delete_agent_builder_agent(agent_id): 
    url = f"{ES_AGENT_URL}/agents/{agent_id}"
    response = make_http_request(url, method="DELETE", headers=HEADERS)
    if response:
        return response.json()
    return None

# Delete all of the agents from the agent builder except those in the avoid list
def clear_agent_builder_agents():   
    url = f"{ES_AGENT_URL}/agents"
    response = make_http_request(url, method="GET", headers=HEADERS)
    if response:
        agents = response.json()
        for agent in agents.get('results', []):
            # print(json.dumps(agent, indent=2, ensure_ascii=False))
            agent_id = agent.get("id")
            if agent_id not in AGENTS_TO_AVOID_DELETE:
                delete_response = delete_agent_builder_agent(agent_id)
                if delete_response:
                    print(f"Deleted agent: {agent_id}")
                else:
                    print(f"Failed to delete agent: {agent_id}")
    else:
        print("Failed to retrieve agents.")      


clear_agent_builder_agents()

我们可以通过如下的命令来清除所有非系统自带的 agents 及 tools:

 python es_agents_clear.py 
$ pwd
/Users/liuxg/python/es_agents_dump
$ python es_agents_clear.py 
Deleted tool: search_for_parents
Deleted tool: software_developers
Deleted tool: people_profession_search
Deleted tool: find_people_in_ages
Deleted tool: find_people_in_time_range
Deleted tool: find_client_exposure_to_negative_news
Deleted tool: find_cheapest_ticket_from_cn_us
Deleted tool: example-esql-tool
Deleted tool: find_average_age
Deleted agent: find_people_in_age_range
Deleted agent: people_profession_search
Deleted agent: software_developers
Deleted agent: find_parents
Deleted agent: find_people_in_time_range
Deleted agent: financial_assistant
Deleted agent: find_the_cheapest_ticket_from_cn_us
Deleted agent: find_out_average_age

一旦运行完上面的命令后,我们可以看到所有定制的 tools 及 agents 都已经被彻底删除了。

注意:在运行上面的命令之前,确保你已经下载了所有的 tools 及 agents。

在清除所有的 tools 及 agents 之后,我们可以再次运行 es_agents_import.py 来看看:

python es_agents_import.py 
$ pwd
/Users/liuxg/python/es_agents_dump
$ python es_agents_import.py 
Skipping import of tool platform.core.search
Skipping import of tool platform.core.get_document_by_id
Skipping import of tool platform.core.execute_esql
Skipping import of tool platform.core.generate_esql
Skipping import of tool platform.core.get_index_mapping
Skipping import of tool platform.core.list_indices
Skipping import of tool platform.core.index_explorer
Importing tool search_for_parents
Successfully imported tool search_for_parents
Importing tool software_developers
Successfully imported tool software_developers
Importing tool people_profession_search
Successfully imported tool people_profession_search
Importing tool find_people_in_ages
Successfully imported tool find_people_in_ages
Importing tool find_people_in_time_range
Successfully imported tool find_people_in_time_range
Importing tool find_client_exposure_to_negative_news
Successfully imported tool find_client_exposure_to_negative_news
Importing tool find_cheapest_ticket_from_cn_us
Successfully imported tool find_cheapest_ticket_from_cn_us
Importing tool example-esql-tool
Successfully imported tool example-esql-tool
Importing tool find_average_age
Successfully imported tool find_average_age
Skipping import of agent elastic-ai-agent
Importing agent find_people_in_age_range
Successfully imported agent find_people_in_age_range
Importing agent people_profession_search
Successfully imported agent people_profession_search
Importing agent software_developers
Successfully imported agent software_developers
Importing agent find_parents
Successfully imported agent find_parents
Importing agent find_people_in_time_range
Successfully imported agent find_people_in_time_range
Importing agent financial_assistant
Successfully imported agent financial_assistant
Importing agent find_the_cheapest_ticket_from_cn_us
Successfully imported agent find_the_cheapest_ticket_from_cn_us
Importing agent find_out_average_age
Successfully imported agent find_out_average_age

我们可以看到它成功地把备份好的 tools 及 agents 都已经导入到系统了。我们查看最新的页面:

最后,祝大家使用 AI Agents Builder 创建更多的 agents!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值