LlamaIndex
이 페이지에서는 LlamaIndex 에이전트를 계측하는 방법, 스팬을 식별하는 방법, 평가 필드를 추출하는 방법을 설명합니다. LlamaIndex 에이전트를 안정적으로 평가할 수 있도록 구성하는 모범 사례와 함께 종료됩니다.
주제
에이전트 계측
OpenTelemetry() 또는 OpenInOpenInference()의 두 가지 계측 라이브러리 중 하나를 사용하여 LlamaIndex 에이전트를 계측할 수 있습니다openinference-instrumentation-llama-index.opentelemetry-instrumentation-llamaindex Amazon Bedrock AgentCore Evaluations는 두 라이브러리를 모두 지원합니다. 라이브러리는 서로 다른 범위 이름을 내보내고 서로 다른 스팬 속성을 사용합니다. 평가 서비스는 각각에서 동일한 값을 추출합니다.
Amazon Bedrock AgentCore 런타임에서와 같이 에이전트가 AWS Distro for OpenTelemetry(ADOT)를 사용하여 실행되는 경우 명시적 계측 코드를 추가할 필요가 없습니다. 프로젝트의 종속성에 계측 라이브러리를 추가하면 충분합니다. 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 Evaluations는 traceloop.entity.name 속성으로 이를 명확하게 구분합니다. task 개체 이름이 로 끝나는 Tool.task는 실행 도구 범위이고 다른는 추론 범위task입니다.
| 범위 유형 |
속성 식별 |
|
에이전트 호출
|
traceloop.span.kind = workflow
|
|
도구 실행
|
traceloop.span.kind = 또는 traceloop.entity.name task로 끝나는 tool traceloop.span.kind = Tool.task
|
|
Inference
|
traceloop.span.kind = task (도구 작업이 아님)
|
- OpenInference
-
OpenInference 계측 라이브러리는 openinference.span.kind 속성을 사용하여 스팬을 분류합니다. LlamaIndex는 CHAIN, LLM및 스TOOL팬을 방출하지만 AGENT스팬은 방출하지 않습니다. 루트 워크플로 범위(CHAIN)는 호출 에이전트 범위 역할을 합니다.
| 범위 유형 |
속성 식별 |
|
에이전트 호출
|
openinference.span.kind = CHAIN (루트 워크플로 범위)
|
|
도구 실행
|
openinference.span.kind = TOOL
|
|
Inference
|
openinference.span.kind = LLM
|
LlamaIndex는 여러 중간 CHAIN 범위를 내보냅니다(예: 출력 구문 분석 및 도구 라우팅). AgentCore Evaluations는 루트 워크플로 스팬만 호출 에이전트 스팬으로 처리하고 추적의 추론(LLM) 스팬에서 사용자 프롬프트 및 에이전트 응답을 재구성합니다.
평가 필드 추출 방법
LlamaIndex 에이전트는 워크플로이며 하위 스팬 전에 최상위 스팬이 발생합니다. 이 워크플로 범위에는 사용 가능한 대화 콘텐츠가 포함되어 있지 않으므로 AgentCore Evaluations는 하위 범위(추론 및 도구 범위)에서 사용자 프롬프트와 에이전트 응답을 재구성하고 이를 호출 에이전트 범위에 연결합니다.
또한 LlamaIndex는 콘텐츠를 중첩 JSON으로 직렬화합니다. 도구 인수는 로 래핑{"kwargs": {…}}되고 도구 결과는 로 래핑됩니다{"blocks": [{"text": "…"}], …}. AgentCore Evaluations는 이러한 양식을 언래핑합니다. LlamaIndex ReAct 에이전트가 형식으로 출력을 생성하면 Thought: … Answer: <response> AgentCore Evaluations는 이후 텍스트를 에이전트 응답Answer:으로 추출합니다.
이 콘텐츠의 위치는 원격 측정이 수집된 방식에 따라 달라집니다. 식별 속성(traceloop.span.kind 또는 openinference.span.kind)은 두 경우 모두 스팬에 있습니다. 자세한 내용은 스팬, 이벤트 레코드 및 원격 측정 신호를 참조하세요.
이벤트 레코드에서
원격 측정이 분할되면 AgentCore Evaluations는 각 범위와 상관관계가 있는 이벤트 레코드에서 콘텐츠를 읽습니다.
-
사용자 프롬프트 및 에이전트 응답:의 추론 스팬의 이벤트 레코드에서 재구성됩니다body.output. OpenTelemetry 라이브러리를 사용하면 채팅 기록 콘텐츠에서 사용자 프롬프트를 가져오고 모델 결과 콘텐츠에서 에이전트 응답을 가져옵니다. OpenInference 라이브러리에서 사용자 프롬프트는 일반 텍스트 입력 메시지이고 에이전트 응답은 모델 출력(ReAct 에이전트에 Answer: 사용된 후의 텍스트 포함)입니다.
-
도구 호출: 실행 도구 범위의 도구 이름입니다. 도구 인수와 결과는 (에서 래핑되지 않음{"kwargs": {…}}) 및 body.input (에서 래핑되지 않음)의 해당 스팬의 이벤트 레코드body.output에서 가져옵니다{"blocks": […]}.
예제는 이벤트 레코드가 있는 스팬 예제를 참조하세요.
스팬 속성에서
원격 측정이 분할되지 않으면 속성과 동일한 콘텐츠가 스팬에 유지됩니다. 속성은 계측 라이브러리에 따라 다릅니다.
-
OpenTelemetry: 콘텐츠는 각 스팬의 traceloop.entity.input 및 traceloop.entity.output 속성에 있습니다. AgentCore Evaluations는 동일한 채팅 기록, 결과 및 도구 언래핑을 이러한 값에 적용합니다.
-
OpenInference: 추론 콘텐츠는 인덱싱된 메시지 속성(llm.input_messages. 및 )에 있습니다llm.output_messages.. 도구 인수는에서 가져오고input.value(에서 래핑 해제됨{"kwargs": {…}}) 도구 결과는에서 가져옵니다output.value(에서 래핑 해제됨{"blocks": […]}).
예제는 이벤트 레코드가 없는 스팬 예제를 참조하세요.
이벤트 레코드가 있는 스팬의 예
원격 측정이 분할되면 스팬은 식별 속성을 전달하고 콘텐츠는 상관관계가 있는 이벤트 레코드에 있습니다. 다음 예제는 Amazon Bedrock AgentCore 런타임에 배포된 LlamaIndex ReAct 여행 계획 에이전트에서 가져온 것입니다. 각 계측 라이브러리 아래에 동일한 에이전트가 표시됩니다.
이 예제는 완전한 범위가 아닙니다. 실제 에이전트 상호 작용의 대표 데이터를 표시하며, 일부 필드는 생략되고 긴 값은 가독성을 위해 잘립니다.
OpenTelemetry
예
- Invoke agent span
-
traceloop.span.kind 속성(workflow)은 이를 호출 에이전트 범위로 식별합니다. 워크플로 스팬에는 대화 콘텐츠가 없습니다. AgentCore Evaluations는 하위 스팬의 사용자 프롬프트와 에이전트 응답을 재구성합니다.
{
"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 Evaluations는 첫 번째 추론 범위의 채팅 기록 문자열({"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역할 텍스트입니다.
{
"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역할 텍스트입니다.
{
"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 Evaluations는 추론 스팬의 사용자 프롬프트와 에이전트 응답을 재구성합니다.
{
"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 보유합니다. 도구 인수와 결과는 상관관계가 있는 이벤트 레코드에 각각 kwargs 및 로 래핑되어 있습니다blocks.
{
"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 Evaluations는 마지막 일반 텍스트 입력 메시지를 사용자 프롬프트로 사용합니다. LlamaIndex는 중복 assistant:접두사가 붙은 출력 메시지를 내보냅니다.이 출력 메시지는 AgentCore Evaluations가 클린 복사를 위해 건너뜁니다.
{
"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 Evaluations가 사용자 프롬프트를 읽는 채팅 기록이 들어 있습니다. 응답은 마지막 추론 범위의 모델 결과에서 나옵니다.
{
"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 Evaluations는 이후 텍스트를 에이전트 응답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 Evaluations는 이러한 하위 스팬에서 호출 에이전트 스팬을 재구성합니다.
-
도구를 FunctionTool 객체로 등록합니다. 각 도구를 LlamaIndex로 정의합니다FunctionTool(또는 하나를 생성하는 @tool스타일 헬퍼 사용). 도구 범위는 개체 이름으로 식별되며 인수와 결과는 AgentCore 평가 언래핑의 kwargs 및 blocks 구조에서 직렬화됩니다.
-
도구 결과를 텍스트 직렬화 가능 상태로 유지합니다. 도구 결과를 문자열 또는 JSON 직렬화 가능 값으로 반환합니다. LlamaIndex는 이들을 텍스트 블록으로 래핑합니다. 직렬화 가능한 상태로 유지하면 도구 결과가 깔끔하게 캡처됩니다.
-
ReAct 에이전트의 경우 표준 출력 형식을 사용합니다. AgentCore Evaluations는 ReAct 에이전트 출력의 Answer: 섹션에서 최종 답변을 추출합니다. 표준 ReAct 프롬프트(LlamaIndex 기본값)를 사용하면 에이전트 응답을 복구할 수 있습니다.