LlamaIndex
Cette page explique comment instrumenter un LlamaIndexagent, comment les intervalles sont identifiés et comment les champs d'évaluation sont extraits. Il se termine par les meilleures pratiques pour structurer un LlamaIndex agent afin qu'il puisse être évalué de manière fiable.
Rubriques
Instrumez votre agent
Vous pouvez instrumenter un LlamaIndex agent avec l'une des deux bibliothèques d'instrumentation suivantes : OpenTelemetry(opentelemetry-instrumentation-llamaindex) ou OpenInference(openinference-instrumentation-llama-index). Amazon Bedrock AgentCore Evaluations prend en charge les deux bibliothèques. Les bibliothèques émettent des noms de portée différents et utilisent des attributs d'étendue différents. Le service d'évaluation extrait les mêmes valeurs de chacun d'entre eux.
Lorsque votre agent s'exécute avec le AWS Distro for OpenTelemetry (ADOT), par exemple sur Amazon Bedrock AgentCore Runtime, vous n'avez pas besoin d'ajouter de code d'instrumentation explicite. Il suffit d'ajouter la bibliothèque d'instrumentation aux dépendances de votre projet. ADOT le découvre au démarrage et l'active automatiquement.
Ajoutez la bibliothèque d'instrumentation correspondant au chemin que vous souhaitez accéder à vos dépendances. Utilisez la dernière version disponible, sauf si vous avez une raison de l'épingler.
Exemple
- OpenTelemetry
-
REMARQUE : Utilisez la version 0.61.0 ou une version ultérieure. Il s'agit de la première version testée avec le service d'évaluation.
Ajoutez opentelemetry-instrumentation-llamaindex à vos dépendances. Le nom de la portée émis estopentelemetry.instrumentation.llamaindex.
requirements.txt:
opentelemetry-instrumentation-llamaindex>=0.61.0
pyproject.toml:
[project]
dependencies = [
"opentelemetry-instrumentation-llamaindex>=0.61.0",
]
- OpenInference
-
REMARQUE : Utilisez la version 4.4.1 ou une version ultérieure. Il s'agit de la première version testée avec le service d'évaluation.
Ajoutez openinference-instrumentation-llama-index à vos dépendances. Le nom de la portée émis estopeninference.instrumentation.llama_index.
requirements.txt:
openinference-instrumentation-llama-index>=4.4.1
pyproject.toml:
[project]
dependencies = [
"openinference-instrumentation-llama-index>=4.4.1",
]
L'instrumentation est l'une des étapes de la mise en place de l'observabilité. Pour exporter la télémétrie à des fins d'évaluation, effectuez la configuration complète dans Configurer l'observabilité.
Comment les travées sont identifiées
L'attribut utilisé pour classer les intervalles diffère entre les deux bibliothèques d'instrumentation.
Exemple
- OpenTelemetry
-
La bibliothèque OpenTelemetry d'instrumentation classe les travées à l'aide de l'traceloop.span.kindattribut. Étant donné que les inférences et les opérations d'outil sont LlamaIndex étiquetées comme AgentCore tellestask, Evaluations les distingue par l'traceloop.entity.nameattribut suivant : a task dont le nom de l'entité se termine par une plage d'outils d'exécution ; toute autre task est une plage d'inférence. Tool.task
| Type de travée |
Attribut d'identification |
|
Invoquer l'agent
|
traceloop.span.kind = workflow
|
|
Exécuter l'outil
|
traceloop.span.kind=tool, ou traceloop.span.kind = task avec traceloop.entity.name se terminant par Tool.task
|
|
Inférence
|
traceloop.span.kind= task (il ne s'agit pas d'une tâche d'outil)
|
- OpenInference
-
La bibliothèque OpenInference d'instrumentation classe les travées à l'aide de l'openinference.span.kindattribut. LlamaIndex émet CHAINLLM, et s'TOOLétend ; il n'émet AGENT pas de spans. L'intervalle du flux de travail racine (aCHAIN) agit comme le span de l'agent d'appel.
| Type de travée |
Attribut d'identification |
|
Invoquer l'agent
|
openinference.span.kind= CHAIN (durée du flux de travail racine)
|
|
Exécuter l'outil
|
openinference.span.kind = TOOL
|
|
Inférence
|
openinference.span.kind = LLM
|
LlamaIndex émet plusieurs intervalles intermédiaires CHAIN (par exemple, pour l'analyse des sorties et le routage des outils). AgentCore Evaluations traite uniquement la durée du flux de travail racine comme la durée d'appel de l'agent et reconstruit l'invite de l'utilisateur et la réponse de l'agent à partir des intervalles d'inférence (LLM) de la trace.
Comment les champs d'évaluation sont extraits
L' LlamaIndex agent est un flux de travail, et son intervalle de niveau supérieur est émis avant que son enfant ne s'étende. Ce flux de travail ne contient aucun contenu de conversation utilisable en soi. AgentCore Evaluations reconstruit l'invite de l'utilisateur et la réponse de l'agent à partir des intervalles enfants (l'inférence et les intervalles d'outils) et les associe à l'intervalle d'appel de l'agent.
LlamaIndex sérialise également le contenu sous forme de JSON imbriqué. Les arguments de l'outil sont encapsulés sous forme {"kwargs": {…}} et les résultats de l'outil sont encapsulés sous forme{"blocks": [{"text": "…"}], …}. AgentCore Les évaluations déballent ces formulaires. Lorsqu'un LlamaIndex ReAct agent produit une sortie dans le formulaireThought: … Answer: <response>, AgentCore Evaluations extrait le texte qui suit Answer: en tant que réponse de l'agent.
L'emplacement de ce contenu dépend de la manière dont la télémétrie a été collectée. L'attribut d'identification (traceloop.span.kindouopeninference.span.kind) se trouve sur la plage dans les deux cas. Pour plus d'informations, voir Spans, enregistrements d'événements et signaux de télémétrie.
À partir des enregistrements d'événements
Lorsque la télémétrie est divisée, AgentCore Evaluations lit le contenu de l'enregistrement d'événements corrélé à chaque période :
-
Demande de l'utilisateur et réponse de l'agent : reconstruite à partir des enregistrements d'événements des intervalles d'inférence, dans. body.output Avec la OpenTelemetry bibliothèque, l'invite de l'utilisateur provient du contenu de l'historique des discussions et la réponse de l'agent provient du contenu des résultats du modèle. Avec la OpenInference bibliothèque, l'invite de l'utilisateur est le message d'entrée en texte brut et la réponse de l'agent est la sortie du modèle (avec le texte une fois Answer: utilisé pour un ReAct agent).
-
Appel à l'outil : nom de l'outil issu de la plage d'outils d'exécution. Les arguments et le résultat de l'outil proviennent de l'enregistrement d'événements de cette plage, dans body.input (déballé de{"kwargs": {…}}) et body.output (déballé de{"blocks": […]}).
Pour des exemples, voir Exemples de périodes avec enregistrements d'événements.
À partir des attributs span
Lorsque la télémétrie n'est pas divisée, le même contenu reste sur la plage que les attributs. Les attributs dépendent de la bibliothèque d'instrumentation :
-
OpenTelemetry: le contenu se trouve sur les traceloop.entity.output attributs traceloop.entity.input et de chaque intervalle. AgentCore Les évaluations appliquent à ces valeurs l'historique des discussions, les mêmes résultats et le même déballage des outils.
-
OpenInference: le contenu de l'inférence se trouve sur les attributs du message indexé (llm.input_messages.
etllm.output_messages.). Les arguments de l'outil proviennent de input.value (déballé de{"kwargs": {…}}) et l'outil résulte de output.value (déballé de{"blocks": […]}).
Pour des exemples, voir Exemples de périodes sans enregistrement d'événements.
Exemples de périodes avec des enregistrements d'événements
Lorsque la télémétrie est divisée, la plage contient les attributs d'identification et le contenu est enregistré dans un enregistrement d'événements corrélé. Les exemples suivants proviennent d'un agent de LlamaIndex ReAct planification de voyages déployé sur Amazon AgentCore Bedrock Runtime. Le même agent est affiché sous chaque bibliothèque d'instruments.
Ces exemples ne sont pas des étendues complètes. Ils présentent des données représentatives d'une interaction réelle avec un agent, certains champs étant omis et les valeurs longues tronquées pour des raisons de lisibilité.
OpenTelemetry
Exemple
- Invoke agent span
-
L'traceloop.span.kindattribut (workflow) l'identifie comme un span d'agent d'appel. La durée du flux de travail ne contient aucun contenu de conversation ; AgentCore Evaluations reconstitue l'invite de l'utilisateur et la réponse de l'agent à partir des étapes secondaires.
{
"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
-
L'traceloop.span.kindattribut (task) traceloop.entity.name terminé par l'Tool.taskidentifie comme une plage d'outils d'exécution. L'enregistrement d'événements corrélé contient les arguments de l'outil (encapsuléskwargs) et le résultat de l'outil (encapsulésblocks), ainsi que le nom de l'outil.
{
"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
-
L'traceloop.span.kindattribut (task), dont le caractère traceloop.entity.name ne se termine pas parTool.task, l'identifie comme une plage d'inférence. Un LlamaIndex agent produit plusieurs de ces intervalles par tour. Dans chacune d'elles, le contenu est compressé body.output (il n'y en a pasbody.input), sous forme de chaîne JSON sérialisée. AgentCore Evaluations lit l'invite de l'utilisateur à partir de la chaîne d'historique des discussions (un {"input": […]} objet) sur la première période d'inférence, et la réponse de l'agent à partir de la chaîne de résultats du modèle (un {"result": {"response": …}} objet) sur la dernière période d'inférence.
Ce qui suit est la durée d'inférence elle-même.
{
"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"
}
}
Lors de la première période d'inférence, le body.output contenu de l'enregistrement de l'événement est l'historique des discussions. L'invite utilisateur est le texte user -role contenu dans le tableau imbriqué. input
{
"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\"}"
}
]
}
}
}
Lors de la dernière période d'inférence, le body.output contenu de l'enregistrement d'événement est le résultat du modèle. La réponse de l'agent est le texte assistant -role contenu dans l'objet imbriqué. result.response
{
"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
Exemple
- Invoke agent span
-
L'openinference.span.kindattribut (CHAIN) sur la plage de flux de travail racine l'identifie comme une étendue d'agent d'appel. Le span ne contient aucun contenu de conversation utilisable ; AgentCore Evaluations reconstruit l'invite de l'utilisateur et la réponse de l'agent à partir des intervalles d'inférence.
{
"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
-
L'openinference.span.kindattribut (TOOL) l'identifie comme une plage d'outils d'exécution ; tool.name contient le nom de l'outil. Les arguments et le résultat de l'outil se trouvent dans l'enregistrement d'événements corrélé, blocks respectivement encapsulés dans kwargs et.
{
"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
-
L'openinference.span.kindattribut (LLM) l'identifie comme une plage d'inférence. Les rôles des messages se trouvent sur les attributs span ; le contenu se trouve dans l'enregistrement d'événements corrélé. ADOT ajuste les rôles de saisie àuser, de sorte qu' AgentCore Evaluations utilise le dernier message de saisie en texte brut comme demande de l'utilisateur. LlamaIndex émet un message de sortie assistant: préfixé en double, qu' AgentCore Evaluations ignore au profit de la copie propre.
{
"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 ..." }
]
}
}
}
Exemples de périodes sans enregistrement d'événements
Lorsque la télémétrie n'est pas divisée, le même contenu reste dans les attributs span et aucun enregistrement d'événement distinct n'est produit. Les exemples suivants proviennent d'un agent de LlamaIndex ReAct planification de voyages. Le même agent est affiché sous chaque bibliothèque d'instruments.
Ces exemples ne sont pas des étendues complètes. Ils présentent des données représentatives d'une interaction réelle avec un agent, certains champs étant omis et les valeurs longues tronquées pour des raisons de lisibilité.
OpenTelemetry
Exemple
- Execute tool span
-
L'traceloop.entity.inputattribut contient les arguments de l'outil (encapsuléskwargs) et l'traceloop.entity.outputattribut contient le résultat de l'outil (encapsulé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
-
L'traceloop.entity.outputattribut contient l'historique des discussions, à partir duquel AgentCore Evaluations lit l'invite de l'utilisateur. La réponse provient du résultat du modèle sur la dernière période d'inférence.
{
"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
Exemple
- Execute tool span
-
L'input.valueattribut contient les arguments de l'outil (encapsuléskwargs) et l'output.valueattribut contient le résultat de l'outil (encapsulé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
-
Le contenu du message est intégré aux attributs indexés. Les llm.input_messages.
attributs contiennent l'invite du système et l'invite de l'utilisateur, et les llm.output_messages. attributs contiennent le résultat du modèle, à partir duquel AgentCore Evaluations extrait le texte en Answer: tant que réponse de l'agent.
{
"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"
}
}
Bonnes pratiques pour les LlamaIndex agents
La façon dont vous créez et invoquez un LlamaIndex agent influe sur ce qui apparaît dans sa télémétrie, et donc sur la fiabilité de l'évaluation de l'agent. Les pratiques suivantes permettent de garantir que l'invite de l'utilisateur, la réponse de l'agent et l'activité de l'outil sont récupérables.
-
Utilisez un flux de travail d' LlamaIndex agent. Concevez votre agent en tant que flux de travail d' LlamaIndex agent (par exemple, un ReActAgent ouFunctionAgent) afin que le framework émette une durée de flux de travail de haut niveau avec inférence et intervalles d'utilisation des outils. AgentCore Evaluations reconstruit l'intervalle de l'agent invoqué à partir de ces intervalles enfants.
-
Enregistrez les outils en tant qu'FunctionToolobjets. Définissez chaque outil comme un LlamaIndex FunctionTool (ou utilisez des aides de @tool style -style qui en produisent un). Les étendues d'outils sont identifiées par leur nom d'entité, et leurs arguments et résultats sont sérialisés dans les structures kwargs et les blocks structures qu' AgentCore Evaluations dévoile.
-
Gardez les résultats de l'outil sérialisables par texte. Renvoie les résultats de l'outil sous forme de chaînes ou de JSON-serializable valeurs. LlamaIndex les enveloppe dans un bloc de texte ; en les gardant sérialisables, le résultat de l'outil est capturé correctement.
-
Pour les ReAct agents, utilisez le format de sortie standard. AgentCore Les évaluations extraient la réponse finale de la Answer: section du résultat d'un ReAct agent. L'utilisation de l' ReAct invite standard ( LlamaIndex valeur par défaut) permet de récupérer la réponse de l'agent.