Link Search Menu Expand Document Documentation Menu

构建计划-执行-反思智能体

这是一项实验性功能,不建议在生产环境中使用。有关该功能的进度更新或如果您想留下反馈,请参阅相关的GitHub 问题

本教程描述了如何构建和使用计划-执行-反思代理。此代理可用于解决受益于多步骤执行和推理的复杂问题。在本示例中,您将要求代理分析 OpenSearch 索引中的航班数据。有关此代理的更多信息,请参阅计划-执行-反思代理

将以 your_ 为前缀的占位符替换为您自己的值。

先决条件

登录 OpenSearch Dashboards 主页,选择添加示例数据,并添加示例航班数据

步骤 1:准备 LLM

计划-执行-反思代理需要大型语言模型(LLM)才能运行。本教程使用托管在 Amazon Bedrock 上的 Anthropic Claude 3.7 模型。您也可以使用其他支持的 LLM

步骤 1(a):创建连接器

为模型创建连接器

POST /_plugins/_ml/connectors/_create
{
    "name": "Amazon Bedrock Claude 3.7-sonnet connector",
    "description": "Connector to Amazon Bedrock service for the Claude model",
    "version": 1,
    "protocol": "aws_sigv4",
    "parameters": {
      "region": "your_aws_region",
      "service_name": "bedrock",
      "model": "us.anthropic.claude-3-7-sonnet-20250219-v1:0"
    },
    "credential": {
      "access_key": "your_aws_access_key",
      "secret_key": "your_aws_secret_key",
      "session_token": "your_aws_session_token"
    },
    "actions": [
      {
        "action_type": "predict",
        "method": "POST",
        "url": "https://bedrock-runtime.${parameters.region}.amazonaws.com/model/${parameters.model}/converse",
        "headers": {
          "content-type": "application/json"
        },
        "request_body": "{ \"system\": [{\"text\": \"${parameters.system_prompt}\"}], \"messages\": [${parameters._chat_history:-}{\"role\":\"user\",\"content\":[{\"text\":\"${parameters.prompt}\"}]}${parameters._interactions:-}]${parameters.tool_configs:-} }"
      }
    ]
}

记下连接器 ID;您将使用它来注册模型。

步骤 1(b):注册模型

注册模型

POST /_plugins/_ml/models/_register
{
    "name": "Bedrock Claude Sonnet model",
    "function_name": "remote",
    "description": "Bedrock Claude 3.7 sonnet model for Plan, Execute and Reflect Agent",
    "connector_id": "your_connector_id"
}

记下模型 ID;您将在后续步骤中使用它。

步骤 1(c):配置重试策略

由于代理是一个执行多个步骤的长时间运行代理,因此我们强烈建议为您的模型配置重试策略。有关更多信息,请参阅配置参数中的client_config参数。例如,要配置无限重试,请将max_retry_times设置为-1

PUT /_plugins/_ml/models/your_model_id
{
  "connector": {
    "client_config": {
      "max_retry_times": -1,
      "retry_backoff_millis": 300,
      "retry_backoff_policy": "exponential_full_jitter"
    }
  }
}

步骤 2:创建代理

创建配置了以下信息的plan_execute_and_reflect代理

  • 元信息:nametypedescription
  • LLM 信息:代理使用 LLM 来进行推理,设计完成任务的计划,使用适当的工具执行计划中的步骤,并反思中间结果以优化计划。
  • 工具:工具是代理可以执行的函数。每个工具都可以定义自己的namedescriptionparametersattributes
  • 内存:存储聊天消息。OpenSearch 当前仅支持一种内存类型:conversation_index

有关所有请求字段的更多信息,请参阅注册代理 API

要注册代理,请发送以下请求。在此示例中,您将创建一个包含ListIndexToolSearchIndexToolIndexMappingTool的代理

POST _plugins/_ml/agents/_register
{
  "name": "My Plan Execute and Reflect agent with Claude 3.7",
  "type": "plan_execute_and_reflect",
  "description": "this is a test agent",
  "llm": {
    "model_id": "your_llm_model_id_from_step1",
    "parameters": {
      "prompt": "${parameters.question}"
  }},
  "memory": {
    "type": "conversation_index"
  },
  "parameters": {
    "_llm_interface": "bedrock/converse/claude"
  },
  "tools": [
    {
      "type": "ListIndexTool"
    },
    {
      "type": "SearchIndexTool"
    },
    {
      "type": "IndexMappingTool"
    }
  ],
}

记下代理 ID;您将在下一步中使用它。

您可以根据需要配置其他与您的用例相关的工具。要配置其他工具,请确保为工具提供attributes字段。这至关重要,因为attributes用于告知 LLM 执行工具所需的输入模式。

ListIndexToolSearchIndexToolIndexMappingToolWebSearchTool包含预定义属性。例如,ListIndexTool提供以下属性

tools: [{
    "type": "ListIndexTool",
    "attributes": {
        "input_schema": {
            "type": "object",
            "properties": {
                "indices": {
                    "type": "array",
                    "items": {
                        "type": "string"
                    },
                    "description": "OpenSearch index name list, separated by comma. for example: [\"index1\", \"index2\"], use empty array [] to list all indices in the cluster"
                }
            },
        },
        "strict": false
    }
}]

测试代理

使用以下提示有效测试您的plan_execute_and_reflect代理

  • 跟踪代理执行:使用获取消息跟踪 API 查看详细的执行步骤
    GET _plugins/_ml/memory/message/your_message_id/traces
    
  • 减轻幻觉:LLM 可能会“幻觉”,选择错误的工具或错误地解释任务,特别是当代理配置了太多工具时。为避免幻觉,请尝试以下选项
    • 限制代理中配置的工具数量。
    • 为每个工具提供清晰、具体的描述。
    • 确保代理可以访问任务所需的所有工具。
    • 在提示中包含有关集群的相关上下文;例如,Can you identify the error in my cluster by analyzing the "spans" and "logs" indexes?
  • 配置重试:LLM 调用偶尔会失败。设置重试以提高可靠性。有关更多信息,请参阅配置参数中的client_config参数。

要测试代理,请使用执行代理 API 运行它。由于此代理执行长时间运行的任务,我们建议异步运行以避免超时。使用async=true查询参数将代理作为单独的任务运行

POST _plugins/_ml/agents/your_agent_id/_execute?async=true
{
  "parameters": {
    "question": "How many flights from Beijing to Seattle?"
  }
}

请注意响应中的task_idmemory_id。您将使用它们来跟踪进度和查看结果。

使用以下请求检查任务是否仍在运行或已完成

GET _plugins/_ml/tasks/your_task_id

任务完成后,它会从代理返回一个响应

{
  "task_type": "AGENT_EXECUTION",
  "function_name": "AGENT",
  "state": "COMPLETED",
  "worker_node": [
    "q5yAqa75RM-rv0I67V1VVQ"
  ],
  "create_time": 1746148548710,
  "last_update_time": 1746148706345,
  "is_async": false,
  "response": {
    "memory_id": "bzWQjpYBKhItn1nNYHtu",
    "inference_results": [
      {
        "output": [
          {
            "result": "bzWQjpYBKhItn1nNYHtu",
            "name": "memory_id"
          },
          {
            "result": "cDWQjpYBKhItn1nNYHuS",
            "name": "parent_interaction_id"
          },
          {
            "result": "dTWQjpYBKhItn1nNbHsw",
            "name": "executor_agent_memory_id"
          },
          {
            "result": "YjWQjpYBKhItn1nN6oYk",
            "name": "executor_agent_parent_interaction_id"
          },
          {
            "name": "response",
            "dataAsMap": {
              "response": """# Comprehensive Analysis Report: Flights from Beijing to Seattle

## Executive Summary
After analyzing the OpenSearch sample flight dataset, I found that there are 0 direct flights from Beijing to Seattle in the dataset.

## Analysis Process

### Step 1: Identify Available Data Sources
I began by examining the indices available in the OpenSearch cluster to locate flight-related data. This search revealed one relevant index: `opensearch_dashboards_sample_data_flights`, which contains 13,059 flight records with comprehensive information including origin and destination cities, flight numbers, carriers, and other flight details.

### Step 2: Data Schema Analysis
I analyzed the index structure and confirmed it contains the necessary fields for this investigation, including:
- Origin/destination city names (`OriginCityName`, `DestCityName`) 
- Airport codes (`Origin`, `Dest`)
- Airport IDs (`OriginAirportID`, `DestAirportID`)
- Geographic information for origins and destinations

### Step 3: Query Construction and Execution
I created and executed a search query to find flights where:
- Origin city is Beijing (also checked for "Beijing Capital International Airport" and airport code "PEK")
- Destination city is Seattle (also checked for "Seattle Tacoma International Airport" and airport code "SEA")

### Step 4: Result Verification
To ensure the search was properly constructed, I verified that:
1. Flights from Beijing to other destinations exist in the dataset
2. Flights to Seattle from other origins exist in the dataset

This confirmed that both cities are represented in the data, but no flights connect them directly.

## Key Findings
- Beijing appears as an origin city in the dataset, with flights to destinations including Warsaw, Pittsburgh, Xi'an, Vienna, and Chicago/Rockford
- Seattle appears as both origin and destination in the dataset, with connections to cities like Vienna, Istanbul, New Orleans, St Louis, and Treviso
- The dataset contains 0 flights from Beijing to Seattle

## Conclusion
Based on a comprehensive search of the OpenSearch flight sample dataset, there are 0 flights from Beijing to Seattle in this dataset. While both cities appear in the dataset with connections to other locations, this specific route is not represented in the sample data."""
            }
          }
        ]
      }
    ]
  }
}

代理执行响应包含几个关键字段

  • memory_id:存储plan_execute_and_reflect代理与 LLM 之间所有交换消息的内存 ID。
  • parent_interaction_id:在规划代理中启动对话的父消息的message_id
  • executor_agent_memory_id:存储内部执行器代理与 LLM 之间交换消息的内存 ID。
  • executor_agent_parent_interaction_id:执行器代理对话中父消息的message_id
  • response:代理执行所有步骤后产生的最终结果。

当您异步执行计划-执行-反思代理时,一旦代理启动,API 将返回规划代理的memory_idparent_interaction_id

在最终响应中,API 还返回executor_agent_memory_idexecutor_agent_parent_interaction_id,它们对应于负责执行计划中每个步骤的内部执行器代理。executor_agent_memory_idexecutor_agent_parent_interaction_id在可用时(甚至在代理完成执行之前)立即在任务中更新。这使得能够实时跟踪执行过程。

要检查代理的消息历史记录,请使用获取内存 API

GET _plugins/_ml/memory/your_memory_id/messages

有关更多信息,请参阅内存 API

记下相关消息的message_id,并用它来获取逐步执行跟踪

GET _plugins/_ml/memory/message/your_message_id/traces

有关更多信息,请参阅获取消息跟踪 API

测试对话内存

要继续相同的对话,请在执行代理时指定对话的memory_id。以前的消息将被提取并作为上下文提供给模型。使用规划代理的memory_id来继续对话

POST _plugins/_ml/agents/your_agent_id/_execute?async=true
{
  "parameters": {
    "question": "your_question",
    "memory_id": "your_memory_id",
  }
}

后续步骤