View a markdown version of this page

LlamaIndex - 亚马逊基岩 AgentCore

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

LlamaIndex

本页介绍如何对LlamaIndex代理进行仪器测量、如何识别跨度以及如何提取评估字段。最后,它介绍了构建 LlamaIndex 代理LlamaIndex 代理最佳实践的最佳实践,以便对其进行可靠评估。

主题

为您的代理提供仪器

您可以使用两个仪器库中的任何一个来对 LlamaIndex 代理进行仪器:OpenTelemetry(opentelemetry-instrumentation-llamaindex) 或 OpenInference (openinference-instrumentation-llama-index)。亚马逊基岩 AgentCore 评估支持这两个库。这些库发出不同的范围名称并使用不同的跨度属性。评估服务从每种方法中提取相同的值。

当您的代理使用 AWS 发行版 OpenTelemetry (ADOT) 运行时,例如在 Amazon Bedrock AgentCore Runtime 上,您无需添加显式的检测代码。将仪器库添加到项目的依赖项中就足够了。ADOT 在启动时发现它并自动将其激活。

为你想要的依赖项路径添加工具库。除非你有理由固定,否则请使用最新的可用版本。

例
OpenTelemetry

注意:使用版本0.61.0或更高版本。这是使用评估服务测试的最早版本。

将 opentelemetry-instrumentation-llamaindex 添加到依赖项。发出的范围名称是。opentelemetry.instrumentation.llamaindex

requirements.txt:

opentelemetry-instrumentation-llamaindex>=0.61.0

pyproject.toml:

[project] dependencies = [ "opentelemetry-instrumentation-llamaindex>=0.61.0", ]
OpenInference

注意:使用版本4.4.1或更高版本。这是使用评估服务测试的最早版本。

将 openinference-instrumentation-llama-index 添加到依赖项。发出的范围名称是。openinference.instrumentation.llama_index

requirements.txt:

openinference-instrumentation-llama-index>=4.4.1

pyproject.toml:

[project] dependencies = [ "openinference-instrumentation-llama-index>=4.4.1", ]
注意

仪器仪表是设置可观测性的一个步骤。要导出遥测数据进行评估,请在设置可观测性中完成完整设置。

如何识别跨度

两个仪器库中用于对跨度进行分类的属性有所不同。

例
OpenTelemetry

OpenTelemetry 仪器库使用该属性对跨度进行分类。traceloop.span.kind因为将推理和工具操作都 LlamaIndex 标记为task,因此 AgentCore 评估通过traceloop.entity.name属性来消除它们的歧义:实体名称结尾的Tool.task是一个执行工具跨度;任何其他task都是推理跨度。task

跨度类型 识别属性

调用代理

traceloop.span.kind = workflow

执行工具

traceloop.span.kind=tool,或 traceloop.span.kind = task 以结traceloop.entity.name尾为 Tool.task

推理

traceloop.span.kind=task(不是工具任务)

OpenInference

OpenInference 仪器库使用该属性对跨度进行分类。openinference.span.kind LlamaIndex 发射CHAINLLM、和TOOL跨度;它不发射AGENT跨度。根工作流跨度 (aCHAIN) 充当调用代理跨度。

跨度类型 识别属性

调用代理

openinference.span.kind=CHAIN(根工作流跨度)

执行工具

openinference.span.kind = TOOL

推理

openinference.span.kind = LLM

注意

LlamaIndex 发出多个中间CHAIN跨度(例如,用于输出解析和工具路由)。 AgentCore 评估仅将根工作流跨度视为调用代理跨度,并根据跟踪中的推断 (LLM) 跨度重建用户提示和代理响应。

如何提取评估字段

LlamaIndex 代理是一个工作流程,其顶层跨度在其子跨度之前发出。该工作流程跨度本身没有可用的对话内容,因此 AgentCore 评估会从子跨度(推断和工具跨度)重建用户提示和代理响应,并将其附加到调用代理跨度。

LlamaIndex 还将内容序列化为嵌套的 JSON。工具参数包装为{"kwargs": {…​}},工具结果包装为{"blocks": [{"text": "…​"}], …​}。 AgentCore 评估可以解开这些表格。当 LlamaIndex ReAct 代理在表单中生成输出时Thought: …​ Answer: <response>, AgentCore 评估将之后的文本提取Answer:为代理响应。

此内容的位置取决于遥测数据的收集方式。在这两种情况下,识别属性(traceloop.span.kind或openinference.span.kind)都处于跨度内。有关更多信息,请参阅遥测设置和交付。

来自事件记录

使用分离式遥测, AgentCore 评估从与每个跨度相关的事件记录中读取内容:

  • 用户提示和代理响应:根据推理跨度的事件记录重建而成,中。body.output在 OpenTelemetry 库中,用户提示来自聊天历史内容,代理响应来自模型结果内容。在 OpenInference 库中,用户提示是纯文本输入消息,代理响应是模型输出(包括Answer:用于 ReAct 代理之后的文本)。

  • 工具调用:执行工具跨度中的工具名称。工具参数和结果来自该跨度的事件记录,在body.input(从中解包{"kwargs": {…​}})和body.output(从中解包)。{"blocks": […​]}

有关更多信息,请参见分割遥测中的跨度示例。

来自跨度属性

使用统一的遥测技术,相同的内容将作为属性保留在跨度上。这些属性取决于仪器库:

  • OpenTelemetry: 内容位于每个跨度的traceloop.entity.input和traceloop.entity.output属性上。 AgentCore 评估将相同的聊天历史记录、结果和工具解析应用于这些值。

  • OpenInference: 推理内容基于索引的消息属性(llm.input_messages.*和llm.output_messages.*)。工具参数来自input.value(解包自{"kwargs": {…​}}),工具结果来自output.value(解包自{"blocks": […​]})。

有关更多信息,请参阅统一遥测中的跨度示例。

分体遥测中的跨度示例

使用分离式遥测,跨度携带识别属性,内容存在于相关的事件记录中。以下示例来自在亚马逊 Bedro AgentCore ck LlamaIndex ReAct Runtime 上部署的旅行计划代理。每个仪器库下方显示相同的代理。

注意

这些例子并不完整。它们显示来自真实代理交互的代表性数据,为了便于阅读,省略了一些字段并截断了长值。

OpenTelemetry

例
Invoke agent span

traceloop.span.kind属性 (workflow) 将其标识为调用代理跨度。工作流程跨度不包含对话内容; AgentCore 评估会重构来自子跨度的用户提示和代理响应。

{ "traceId": "6a01eef11066751d68f90def0da1f80a", "spanId": "ba1833fa7f097041", "name": "ReActAgent.workflow", "kind": "INTERNAL", "scope": { "name": "opentelemetry.instrumentation.llamaindex", "version": "0.61.0" }, "attributes": { "traceloop.span.kind": "workflow", "traceloop.entity.name": "ReActAgent.workflow", "session.id": "sea-nyc-trip-2-turns-llamaindex-otel" }, "status": { "code": "OK" } }
Execute tool span

以traceloop.entity.name结尾的traceloop.span.kind属性 (task) 将其Tool.task标识为执行工具跨度。相关事件记录包含工具参数(包入kwargs)和工具结果(包入blocks)以及工具名称。

{ "traceId": "6a01eefa5c52f3d86a35038f35f5ba30", "spanId": "5b332f3cd15ace04", "name": "FunctionTool.task", "kind": "INTERNAL", "scope": { "name": "opentelemetry.instrumentation.llamaindex", "version": "0.61.0" }, "attributes": { "traceloop.span.kind": "task", "traceloop.entity.name": "FunctionTool.task", "session.id": "sea-nyc-trip-2-turns-llamaindex-otel" }, "status": { "code": "OK" } }
{ "spanId": "5b332f3cd15ace04", "traceId": "6a01eefa5c52f3d86a35038f35f5ba30", "scope": { "name": "opentelemetry.instrumentation.llamaindex" }, "body": { "input": { "messages": [ { "role": "user", "content": "{\"kwargs\": {\"origin\": \"SEA\", \"destination\": \"NYC\", \"date\": \"2025-03-15\"}}" } ] }, "output": { "messages": [ { "content": "{\"blocks\": [{\"block_type\": \"text\", \"text\": \"{\\\"origin\\\": \\\"SEA\\\", \\\"destination\\\": \\\"NYC\\\", \\\"flights\\\": [ ... ]}\"}], \"tool_name\": \"search_flights\"}" } ] } } }
Inference span

不以结尾traceloop.entity.name的traceloop.span.kind属性 (task) 将其标识为推理跨度。Tool.task LlamaIndex 代理每回合产生几个这样的跨度。在每个文件中,内容都以序列化的 JSON 字符串的形式打包到body.output(没有body.input)中。 AgentCore 评估从第一个推理跨度的聊天历史字符串({"input": […​]}对象)中读取用户提示,在最后一个推理跨度读取来自模型结果字符串({"result": {"response": …​}}对象)的代理响应。

以下是推理跨度本身。

{ "traceId": "6a01eef11066751d68f90def0da1f80a", "spanId": "d9a1f0c7b3e64a20", "name": "BaseWorkflowAgent.task", "kind": "INTERNAL", "scope": { "name": "opentelemetry.instrumentation.llamaindex", "version": "0.61.0" }, "attributes": { "traceloop.span.kind": "task", "traceloop.entity.name": "BaseWorkflowAgent.task", "session.id": "sea-nyc-trip-2-turns-llamaindex-otel" }, "status": { "code": "OK" } }

在第一个推理跨度上,事件记录的body.output内容是聊天记录。用户提示符是嵌套input数组user中的-role 文本。

{ "spanId": "d9a1f0c7b3e64a20", "traceId": "6a01eef11066751d68f90def0da1f80a", "scope": { "name": "opentelemetry.instrumentation.llamaindex" }, "body": { "output": { "messages": [ { "content": "{\"input\": [{\"role\": \"user\", \"blocks\": [{\"block_type\": \"text\", \"text\": \"Hey, how can you help me\"}]}], \"current_agent_name\": \"Agent\"}" } ] } } }

在最后一个推理跨度上,事件记录的body.output内容是模型结果。代理响应是嵌套result.response对象内assistant的-role 文本。

{ "spanId": "826bc829697a9610", "traceId": "6a01eef11066751d68f90def0da1f80a", "scope": { "name": "opentelemetry.instrumentation.llamaindex" }, "body": { "output": { "messages": [ { "content": "{\"result\": {\"response\": {\"role\": \"assistant\", \"blocks\": [{\"block_type\": \"text\", \"text\": \"Here are the available flights from Seattle to New York City ...\"}]}}, \"current_agent_name\": \"Agent\"}" } ] } } }

OpenInference

例
Invoke agent span

根工作流跨度上的openinference.span.kind属性 (CHAIN) 将其标识为调用代理跨度。该跨度没有可用的对话内容; AgentCore 评估根据推理跨度重构用户提示和代理响应。

{ "traceId": "6a387ee61078243c1cc455ed45c6c313", "spanId": "0a7990d804132a9b", "name": "ReActAgent.run", "kind": "INTERNAL", "scope": { "name": "openinference.instrumentation.llama_index", "version": "4.4.1" }, "attributes": { "openinference.span.kind": "CHAIN", "input.mime_type": "application/json", "output.mime_type": "text/plain", "session.id": "sea-nyc-trip-2-turns-llamaindex-oi" }, "status": { "code": "OK" } }
Execute tool span

openinference.span.kind属性 (TOOL) 将其标识为执行工具跨度;tool.name包含工具名称。工具参数和结果存在于相关的事件记录中,blocks分别包裹在kwargs和中。

{ "traceId": "6a387ef07b8f4f3732fab45d3c0b51ff", "spanId": "ab105c12cc40048f", "name": "FunctionTool.acall", "kind": "INTERNAL", "scope": { "name": "openinference.instrumentation.llama_index", "version": "4.4.1" }, "attributes": { "openinference.span.kind": "TOOL", "tool.name": "search_flights", "tool.description": "search_flights(origin: str, destination: str, date: str) -> str ...", "session.id": "sea-nyc-trip-2-turns-llamaindex-oi" }, "status": { "code": "OK" } }
{ "spanId": "ab105c12cc40048f", "traceId": "6a387ef07b8f4f3732fab45d3c0b51ff", "scope": { "name": "openinference.instrumentation.llama_index" }, "body": { "input": { "messages": [ { "content": "{\"kwargs\": {\"origin\": \"SEA\", \"destination\": \"NYC\", \"date\": \"2025-03-15\"}}" } ] }, "output": { "messages": [ { "content": "{\"blocks\": [{\"text\": \"{\\\"origin\\\": \\\"SEA\\\", \\\"destination\\\": \\\"NYC\\\", \\\"flights\\\": [ ... ]}\"}], \"tool_name\": \"search_flights\"}" } ] } } }
Inference span

openinference.span.kind属性 (LLM) 将其标识为推理跨度。消息角色位于跨度属性上;内容存在于相关的事件记录中。ADOT 将输入角色扁平化为user,因此 AgentCore 评估使用最后一条纯文本输入消息作为用户提示。 LlamaIndex 发出重复的 assistant:-前缀输出消息, AgentCore 评估会跳过该消息,转而使用干净的副本。

{ "traceId": "6a387ee61078243c1cc455ed45c6c313", "spanId": "1221a062c7f90a8e", "name": "OpenAI.astream_chat", "kind": "INTERNAL", "scope": { "name": "openinference.instrumentation.llama_index", "version": "4.4.1" }, "attributes": { "openinference.span.kind": "LLM", "llm.system": "openai", "llm.model_name": "gpt-4o-mini", "llm.input_messages.0.message.role": "system", "llm.input_messages.1.message.role": "user", "llm.output_messages.0.message.role": "assistant", "session.id": "sea-nyc-trip-2-turns-llamaindex-oi" }, "status": { "code": "OK" } }
{ "spanId": "1221a062c7f90a8e", "traceId": "6a387ee61078243c1cc455ed45c6c313", "scope": { "name": "openinference.instrumentation.llama_index" }, "body": { "input": { "messages": [ { "role": "user", "content": "{\"messages\": [ ... ]}" }, { "role": "user", "content": "You are designed to help with a variety of tasks ..." }, { "role": "user", "content": "Hey, how can you help me" } ] }, "output": { "messages": [ { "role": "assistant", "content": "assistant: Thought: ... Answer: I can help you plan your trip ..." }, { "role": "assistant", "content": "Thought: ... Answer: I can help you plan your trip ..." } ] } } }

统一遥测中的示例跨度

使用统一的遥测技术,跨度属性上的内容相同,不会生成单独的事件记录。以下示例来自 LlamaIndex ReAct 旅行规划机构。每个仪器库下方都显示相同的代理。

注意

这些例子并不完整。它们显示来自真实代理交互的代表性数据,为了便于阅读,省略了一些字段并截断了长值。

OpenTelemetry

例
Execute tool span

该traceloop.entity.input属性保存工具参数(包入kwargs),该traceloop.entity.output属性保存工具结果(包入blocks)。

{ "traceId": "6a4de7c376913db82e6f0f336a16731d", "spanId": "b64c37adefae74f0", "name": "FunctionTool.task", "kind": "INTERNAL", "scope": { "name": "opentelemetry.instrumentation.llamaindex", "version": "0.61.0" }, "attributes": { "traceloop.span.kind": "task", "traceloop.entity.name": "FunctionTool.task", "traceloop.entity.input": "{\"kwargs\": {\"origin\": \"SEA\", \"destination\": \"NYC\", \"date\": \"2025-03-15\"}}", "traceloop.entity.output": "{\"blocks\": [{\"block_type\": \"text\", \"text\": \"{\\\"origin\\\": \\\"SEA\\\", \\\"flights\\\": [ ... ]}\"}], \"tool_name\": \"search_flights\"}", "session.id": "sea-nyc-trip-2-turns-unified" }, "status": { "code": "OK" } }
Inference span

该traceloop.entity.output属性保存聊天记录, AgentCore 评估从中读取用户提示。响应来自最后一个推理跨度的模型结果。

{ "traceId": "6a4de7b85e61747e6b568a1f4768e89d", "spanId": "31ea3d5882dac680", "name": "BaseWorkflowAgent.task", "kind": "INTERNAL", "scope": { "name": "opentelemetry.instrumentation.llamaindex", "version": "0.61.0" }, "attributes": { "traceloop.span.kind": "task", "traceloop.entity.name": "BaseWorkflowAgent.task", "traceloop.entity.output": "{\"input\": [{\"role\": \"user\", \"blocks\": [{\"block_type\": \"text\", \"text\": \"Hey, how can you help me\"}]}], \"current_agent_name\": \"Agent\"}", "session.id": "sea-nyc-trip-2-turns-unified" }, "status": { "code": "OK" } }

OpenInference

例
Execute tool span

该input.value属性保存工具参数(包入kwargs),该output.value属性保存工具结果(包入blocks)。

{ "traceId": "6a387ef07b8f4f3732fab45d3c0b51ff", "spanId": "d5a1c9e70b46f312", "name": "FunctionTool.acall", "kind": "INTERNAL", "scope": { "name": "openinference.instrumentation.llama_index", "version": "4.4.2" }, "attributes": { "openinference.span.kind": "TOOL", "tool.name": "search_flights", "input.value": "{\"kwargs\": {\"origin\": \"SEA\", \"destination\": \"NYC\", \"date\": \"2025-03-15\"}}", "output.value": "{\"blocks\": [{\"text\": \"{\\\"origin\\\": \\\"SEA\\\", \\\"flights\\\": [ ... ]}\"}], \"tool_name\": \"search_flights\"}", "session.id": "sea-nyc-trip-2-turns-oi" }, "status": { "code": "OK" } }
Inference span

消息内容内嵌在索引属性上。llm.input_messages.*属性保存系统提示和用户提示,llm.output_messages.*属性保存模型输出, AgentCore 评估从中提取后面的文本Answer:作为代理响应。

{ "traceId": "6a387ee61078243c1cc455ed45c6c313", "spanId": "c9f0a2b41d773e88", "name": "OpenAI.astream_chat", "kind": "INTERNAL", "scope": { "name": "openinference.instrumentation.llama_index", "version": "4.4.2" }, "attributes": { "openinference.span.kind": "LLM", "llm.model_name": "gpt-4o-mini", "llm.input_messages.0.message.role": "system", "llm.input_messages.0.message.content": "You are designed to help with a variety of tasks ...", "llm.input_messages.1.message.role": "user", "llm.input_messages.1.message.content": "Hey, how can you help me", "llm.output_messages.0.message.role": "assistant", "llm.output_messages.0.message.content": "Thought: ... Answer: I can help you plan your trip ...", "session.id": "sea-nyc-trip-2-turns-oi" }, "status": { "code": "OK" } }

LlamaIndex 代理最佳实践

构建和调用 LlamaIndex 代理的方式会影响其遥测数据中显示的内容,从而影响评估代理的可靠性。以下做法有助于确保用户提示、代理响应和工具活动均可恢复。

  • 使用 LlamaIndex 代理工作流程。将您的代理构建为 LlamaIndex 代理工作流程(例如,ReActAgent或FunctionAgent),以便框架发出包含推理和工具子跨度的顶级工作流跨度。 AgentCore 评估会从这些子跨度中重建调用代理跨度。

  • 将工具注册为FunctionTool对象。将每个工具定义为 LlamaIndex FunctionTool(或使用生成一个工具的@tool样式助手)。工具跨度由其实体名称标识,其参数和结果在 Evalutions unwraps kwargs 和blocks结构中序列化 AgentCore 。

  • 保持工具结果的文本可序列化。以字符串或 JSON-serializable 值的形式返回工具结果。 LlamaIndex 将它们包装在文本块中;保持它们可序列化可确保清晰地捕获工具结果。

  • 对于 ReAct 代理,使用标准输出格式。 AgentCore 评估从 ReAct 代理产出的Answer:部分中提取最终答案。使用标准提 ReAct 示符( LlamaIndex 默认)可保持代理响应可恢复。