控制 LLM 应用对话历史采集行为

默认情况下,探针会在 LLM 相关调用(如 LLM 调用、agent 调用)中记录对话历史,对话历史内容格式遵循 OpenTelemetry 规范。本文介绍如何配置 LLM 应用的对话历史采集行为。

为适配多种记录场景,当前ARMS探针支持以下三种对话历史采集与记录模式:

  • 将对话历史记录在 Span Attributes 中(默认)。

  • 停止记录对话历史。

  • 将对话历史记录在日志中。

您可以通过调整配置,修改 LLM 应用对话历史采集行为,以满足不同的采集需求。

前提条件

  • 安装 Python 探针Java 探针

  • 框架版本与探针版本要求如下:

    Python 应用

    组件/框架名

    组件版本支持范围

    支持场景

    探针版本要求

    OpenAI Python SDK

    1.X

    • ChatCompletion

    • Completion

    • Embedding

    2.0.0 及以上版本

    Java 应用

    组件/框架名

    组件版本支持范围

    支持场景

    探针版本要求

    OpenAI Java SDK

    1.1.0+

    • ChatCompletion

    • Completion

    • Embedding

    4.6.0 及以上版本

    Spring AI

    1.0.0+

    • OpenAI ChatModel

    • ChatClient (Default)

    • ToolManager (Default)

    4.6.0 及以上版本

    Spring AI Alibaba

    1.0.0.3+

    • DashScope ChatModel

    4.6.0 及以上版本

示例

本文以一次包含 function 的 React Agent 调用过程为例,LLM 应用会携带工具定义调用大模型,模型会返回一次 tool_call 要求。在应用侧完成工具调用后,应用会携带工具调用结果再次调用大模型并生成最终结果。调用过程时序图如下所示:

image

对话历史记录到 Span Attributes 中

采集行为与数据格式

该模式为默认行为,探针会将输入消息、输出消息、系统指令、工具定义等以 JSON 格式记录在 Span 的 Attributes 中。

Attributes 名称

含义

Schema

内容完整性

gen_ai.input.messages

输入消息

gen_ai.input.messages

完整记录

gen_ai.output.messages

输出消息

gen_ai.output.messages

完整记录

gen_ai.system_instructions

系统指令

gen_ai.system_instructions

完整记录

gen_ai.tool.definitions

工具定义

-

  • type

  • name

  • description

配置方式

  • 通过以下环境变量配置:

    环境变量名

    OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT

    True

    OTEL_INSTRUMENTATION_GENAI_MESSAGE_CONTENT_CAPTURE_STRATEGY

    "span-attributes"

  • 对于 Java 应用,您也可以通过在启动命令中添加 System Properties 的方式配置,如:

    -Dotel.instrumentation.genai.capture-message-content=true \
    -Dotel.instrumentation.genai.message-content.capture-strategy=span-attributes

示例

GenAI Client Span 1

属性

Span 名称

"chat gpt-4"

gen_ai.provider.name

"openai"

gen_ai.operation.name

"chat"

gen_ai.request.model

"gpt-4"

gen_ai.request.max_tokens

200

gen_ai.request.top_p

1.0

gen_ai.response.id

"chatcmpl-9J3uIL87gldCFtiIbyaOvTeYBRA3l"

gen_ai.response.model

"gpt-4-0613"

gen_ai.usage.output_tokens

17

gen_ai.usage.input_tokens

47

gen_ai.response.finish_reasons

["tool_calls"]

gen_ai.input.messages

[
  {
    "role": "user",
    "parts": [
      {
        "type": "text",
        "content": "Weather in Paris?"
      }
    ]
  }
]

gen_ai.output.messages

[
  {
    "role": "assistant",
    "parts": [
      {
        "type": "tool_call",
        "id": "call_VSPygqKTWdrhaFErNvMV18Yl",
        "name": "get_weather",
        "arguments": {
          "location": "Paris"
        }
      }
    ],
    "finish_reason": "tool_call"
  }
]

gen_ai.tool.definitions

[
  {
    "type": "function",
    "name": "get_weather",
    "description": "Get the current temperature for a specific location."
  }
]

GenAI Client Span 2

属性

Span name

"chat gpt-4"

gen_ai.provider.name

"openai"

gen_ai.request.model

"gpt-4"

gen_ai.request.max_tokens

200

gen_ai.request.top_p

1.0

gen_ai.response.id

"chatcmpl-call_VSPygqKTWdrhaFErNvMV18Yl"

gen_ai.response.model

"gpt-4-0613"

gen_ai.usage.output_tokens

52

gen_ai.usage.input_tokens

97

gen_ai.response.finish_reasons

["stop"]

gen_ai.input.messages

[
  {
    "role": "user",
    "parts": [
      {
        "type": "text",
        "content": "Weather in Paris?"
      }
    ]
  },
  {
    "role": "assistant",
    "parts": [
      {
        "type": "tool_call",
        "id": "call_VSPygqKTWdrhaFErNvMV18Yl",
        "name": "get_weather",
        "arguments": {
          "location": "Paris"
        }
      }
    ]
  },
  {
    "role": "tool",
    "parts": [
      {
        "type": "tool_call_response",
        "id": " call_VSPygqKTWdrhaFErNvMV18Yl",
        "response": "rainy, 57°F"
      }
    ]
  }
]

gen_ai.output.messages

[
  {
    "role": "assistant",
    "parts": [
      {
        "type": "text",
        "content": "The weather in Paris is currently rainy with a temperature of 57°F."
      }
    ],
    "finish_reason": "stop"
  }
]

停止采集对话历史

采集行为与数据格式

在该模式下,探针不会记录输入消息、输出消息、系统指令等详细内容,工具定义仅会以 JSON 格式记录基本信息。

Attributes 名称

含义

Schema

内容完整性

gen_ai.input.messages

输入消息

gen_ai.input.messages

不会记录

gen_ai.output.messages

输出消息

gen_ai.output.messages

不会记录

gen_ai.system_instructions

系统指令

gen_ai.system_instructions

不会记录

gen_ai.tool.definitions

工具定义

-

  • type

  • name

配置方式

  • 通过以下环境变量配置:

    环境变量名

    OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT

    False

  • 对于 Java 应用,您也可以通过在启动命令中添加 System Properties 的方式配置,如:

    -Dotel.instrumentation.genai.capture-message-content=false

示例

GenAI Client Span 1

属性

Span 名称

"chat gpt-4"

gen_ai.provider.name

"openai"

gen_ai.operation.name

"chat"

gen_ai.request.model

"gpt-4"

gen_ai.request.max_tokens

200

gen_ai.request.top_p

1.0

gen_ai.response.id

"chatcmpl-9J3uIL87gldCFtiIbyaOvTeYBRA3l"

gen_ai.response.model

"gpt-4-0613"

gen_ai.usage.output_tokens

17

gen_ai.usage.input_tokens

47

gen_ai.response.finish_reasons

["tool_calls"]

gen_ai.tool.definitions

[
  {
    "type": "function",
    "name": "get_weather"
  }
]

GenAI Client Span 2

属性

Span name

"chat gpt-4"

gen_ai.provider.name

"openai"

gen_ai.request.model

"gpt-4"

gen_ai.request.max_tokens

200

gen_ai.request.top_p

1.0

gen_ai.response.id

"chatcmpl-call_VSPygqKTWdrhaFErNvMV18Yl"

gen_ai.response.model

"gpt-4-0613"

gen_ai.usage.output_tokens

52

gen_ai.usage.input_tokens

97

gen_ai.response.finish_reasons

["stop"]

对话历史记录到本地日志中

采集行为与数据格式

在该模式下,Span 的 Attributes 中仅会保留基本信息,探针会将输入消息、输出消息、系统指令、工具定义等以 JSON 格式记录在单行日志中,并保存在本地日志文件下。

Attributes 名称

含义

Schema

内容完整性

gen_ai.input.messages

输入消息

gen_ai.input.messages

完整记录

gen_ai.output.messages

输出消息

gen_ai.output.messages

完整记录

gen_ai.system_instructions

系统指令

gen_ai.system_instructions

完整记录

gen_ai.tool.definitions

工具定义

-

  • type

  • name

  • description

默认情况下,探针启动时会按照如下优先级进行尝试,找到第一个可用的目录作为日志地址。

  1. 如果已通过 APSARA_APM_AGENT_WORKSPACE_DIR 环境变量指定目录,日志会记录在指定目录的 .apsara-apm/{language}/logs 目录下。

  2. 探针日志目录:/home/admin/.opt/.apsara-apm/{language}/logs

  3. home目录:~/.apsara-apm/{language}/{agent_version}_{agent_commit_id}/logs

应用启动时,探针会在 stdout 中打印一行提示日志,您可以通过该目录找到日志的存储目录。为了方便目录统一管理,建议您通过 APSARA_APM_AGENT_WORKSPACE_DIR 环境变量指定目录。

image.png

对话历史日志文件名以genai_messages_{ip}_{pid}.log的格式命名,日志文件最大为 256 MB,超出该大小会进行文件轮转。文件系统中仅会保留最近的两个日志文件,过旧的文件会被删除。

配置方式

  • 通过以下环境变量配置:

    环境变量名

    OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT

    True

    OTEL_INSTRUMENTATION_GENAI_MESSAGE_CONTENT_CAPTURE_STRATEGY

    "event"

  • 对于 Java 应用,您也可以通过在启动命令中添加 System Properties 的方式配置,如:

    -Dotel.instrumentation.genai.capture-message-content=true \
    -Dotel.instrumentation.genai.message-content.capture-strategy=event

示例

GenAI Client Span 1

属性

Span 名称

"chat gpt-4"

gen_ai.provider.name

"openai"

gen_ai.operation.name

"chat"

gen_ai.request.model

"gpt-4"

gen_ai.request.max_tokens

200

gen_ai.request.top_p

1.0

gen_ai.response.id

"chatcmpl-9J3uIL87gldCFtiIbyaOvTeYBRA3l"

gen_ai.response.model

"gpt-4-0613"

gen_ai.usage.output_tokens

17

gen_ai.usage.input_tokens

47

gen_ai.response.finish_reasons

["tool_calls"]

GenAI Client Event 1

spanId 对应 GenAI Client Span 1。

{
  "scope": {
    "name": "aliyun.instrumentation.openai",
    "version": "1.0.1"
  },
  "timeUnixNano": 1760080084146812928,
  "severity": "UNSPECIFIED",
  "attributes": {
    "event.name": "gen_ai.client.inference.operation.details",
    "gen_ai.provider.name": "openai",
    "gen_ai.operation.name": "chat",
    "gen_ai.request.model": "gpt-4",
    "gen_ai.request.max_tokens": 200,
    "gen_ai.request.top_p": 1.0,
    "gen_ai.response.id": "chatcmpl-9J3uIL87gldCFtiIbyaOvTeYBRA3l",
    "gen_ai.response.model": "gpt-4-0613",
    "gen_ai.usage.output_tokens": 17,
    "gen_ai.usage.input_tokens": 47,
    "gen_ai.response.finish_reasons": ["tool_calls"],
    "gen_ai.input.messages": "[{\"role\":\"user\",\"parts\":[{\"type\":\"text\",\"content\":\"Weather in Paris?\"}]}]",
    "gen_ai.output.messages": "[{\"role\":\"assistant\",\"parts\":[{\"type\":\"tool_call\",\"id\":\"call_VSPygqKTWdrhaFErNvMV18Yl\",\"name\":\"get_weather\",\"arguments\":{\"location\":\"Paris\"}}],\"finish_reason\":\"tool_call\"}]",
    "gen_ai.tool.definitions": "[{\"type\":\"function\",\"name\":\"get_weather\",\"description\":\"Get the current temperature for a specific location.\"}]"
  },
  "traceId": "0b46a347592ac487ed092ebe802c6818",
  "spanId": "b3c40af8cd1a522c"
}

GenAI Client Span 2

属性

Span name

"chat gpt-4"

gen_ai.provider.name

"openai"

gen_ai.request.model

"gpt-4"

gen_ai.request.max_tokens

200

gen_ai.request.top_p

1.0

gen_ai.response.id

"chatcmpl-call_VSPygqKTWdrhaFErNvMV18Yl"

gen_ai.response.model

"gpt-4-0613"

gen_ai.usage.output_tokens

52

gen_ai.usage.input_tokens

97

gen_ai.response.finish_reasons

["stop"]

GenAI Client Event 2

Span id 对应 GenAI Client Span 2。

{
  "scope": {
    "name": "aliyun.instrumentation.openai",
    "version": "1.0.1"
  },
  "timeUnixNano": 1760080084176812928,
  "severity": "UNSPECIFIED",
  "attributes": {
    "event.name": "gen_ai.client.inference.operation.details",
    "gen_ai.provider.name": "openai",
    "gen_ai.operation.name": "chat",
    "gen_ai.request.model": "gpt-4",
    "gen_ai.request.max_tokens": 200,
    "gen_ai.request.top_p": 1.0,
    "gen_ai.response.id": "chatcmpl-VSPygqKTWdrhaFErNvMV18Yl",
    "gen_ai.response.model": "gpt-4-0613",
    "gen_ai.usage.output_tokens": 52,
    "gen_ai.usage.input_tokens": 97,
    "gen_ai.response.finish_reasons": ["stop"],
    "gen_ai.input.messages": "[{\"role\":\"user\",\"parts\":[{\"type\":\"text\",\"content\":\"Weather in Paris?\"}]},{\"role\":\"assistant\",\"parts\":[{\"type\":\"tool_call\",\"id\":\"call_VSPygqKTWdrhaFErNvMV18Yl\",\"name\":\"get_weather\",\"arguments\":{\"location\": \"Paris\"}}]},{\"role\":\"tool\",\"parts\":[{\"type\":\"tool_call_response\",\"id\":\"call_VSPygqKTWdrhaFErNvMV18Yl\",\"response\":\"rainy, 57°F\"}]}]",
    "gen_ai.output.messages": "[{\"role\":\"assistant\",\"parts\":[{\"type\":\"text\",\"content\":\"The weather in Paris is currently rainy with a temperature of 57°F.\"}],\"finish_reason\":\"sto\"}]"
  },
  "traceId": "0b46a347592ac487ed092ebe802c6818",
  "spanId": "0a706a178bd746c5"
}

对话历史记录到 SLS 中

将对话历史记录到本地日志模式下,您可以使用 LoongCollector 进一步将本地日志采集到 SLS 中,以便进一步实现日志的处理和消费。

步骤1:安装 LoongCollector

如您的环境已经安装过 LoongCollector,则可以跳过该步骤。

环境类型

参考文档

Linux

LoongCollector安装(Linux)

Windows

LoongCollector安装(Linux)

Kubernetes

LoongCollector安装(Kubernetes)

步骤2:创建采集配置

  1. 登录日志服务控制台,单击目标Project,展开需要存储日志的日志库(Logstore),然后单击数据接入右侧的image图标,单击JSON - 文本日志区域的立即接入

  2. 选择已有的机器组或为日志所在机器创建机器组。

    image

  3. 创建采集配置,请将输入配置下的文件路径替换为实际的日志目录,您可以查看应用启动时打印的标准输出来确认具体目录地址,处理配置可以选择常规的 JSON 解析。

    image

    image

  4. 建议至少为日志添加以下索引,以便检索和分析数据。
    image.png

说明

更详细的日志采集操作请参见主机文本日志采集

步骤3:在 SLS 中查看采集的日志

初次配置完成后,日志会在几分钟内被采集到 SLS 中:

image.png

调整消息长度限制

为防止过长的消息长度引起用量过度增加,默认情况下探针会对超长的消息内容进行截断处理,当前默认的长度为每条消息 8192 字符。被截断的消息末尾中会存在...[truncated]的标识符,如:

[
  {
    "role": "assistant",
    "parts": [
      {
        "type": "text",
        "content": "The weather in Paris...[truncated]"
      }
    ],
    "finish_reason": "stop"
  }
]

配置方式

  • 通过以下环境变量配置:

    环境变量名

    OTEL_INSTRUMENTATION_GENAI_MESSAGE_CONTENT_MAX_LENGTH

    8192

  • 对于 Java 应用,您也可以通过在启动命令中添加 System Properties 的方式配置,如:

    -Dotel.instrumentation.genai.message-content.max-length=8192

会被截断的消息体

对话历史类型

消息

gen_ai.input.messages

TextPart.content

gen_ai.output.messages

TextPart.content

gen_ai.system_instructions

TextPart.content