agentscope-ai / agentscope-ai/agentscope-java

[Feature]: Trace does not record temperature parameter in span attributes

Đang mở
#767 1 bình luận 0 reaction 0 người được giao Xem trên GitHub
area/ext/integration enhancement
Ngôn ngữ chính
Java
Star
5.6k
Fork
1.3k
Merge trung bình
4 ngày 12 giờ
Pull request đã merge (30 ngày)
77

Mô tả

## Describe the bug

When using AgentScope-Java's tracing feature with TelemetryTracer, the `gen_ai.request.temperature` attribute is not being recorded in the trace spans, even when the model is configured with temperature or when users expect temperature to be tracked.

According to the [OpenTelemetry GenAI Semantic Conventions](https://opentelemetry.io/docs/specs/semconv/gen-ai/gen-ai-spans/), the `gen_ai.request.temperature` attribute should be captured for LLM requests.

### Expected attributes that are missing:
- `gen_ai.request.temperature` - The temperature parameter for text generation
- `agentscope.function.input.temperature` (if applicable in the function input JSON)

## Root Cause Analysis

After investigating the code, the root cause has been identified:

### 1. ReActAgent.buildGenerateOptions() does not include temperature

In [`ReActAgent.java:787-794`](agentscope-core/src/main/java/io/agentscope/core/ReActAgent.java:787-794):

```java
@Override
protected GenerateOptions buildGenerateOptions() {
GenerateOptions.Builder builder = GenerateOptions.builder();
if (modelExecutionConfig != null) {
builder.executionConfig(modelExecutionConfig);
}
return builder.build(); // ❌ No temperature, topP, maxTokens, etc.
}
```

The `buildGenerateOptions()` method only sets `executionConfig` (timeout/retry settings), but does **NOT** set any generation parameters like `temperature`, `topP`, `maxTokens`, etc.

### 2. ReActAgent.Builder lacks generateOptions configuration

In [`ReActAgent.Builder`](agentscope-core/src/main/java/io/agentscope/core/ReActAgent.java:971-1555), there is no `generateOptions(GenerateOptions)` method to configure generation parameters at the agent level.

Available configurations:
- ✅ `modelExecutionConfig(ExecutionConfig)` - timeout, retry, backoff
- ❌ `generateOptions(GenerateOptions)` - **MISSING** - temperature, topP, maxTokens, etc.

### 3. Flow of options in reasoning phase

In [`ReActAgent.reasoning()`](agentscope-core/src/main/java/io/agentscope/core/ReActAgent.java:406-487) method:

```java
private Mono reasoning(int iter, boolean ignoreMaxIters) {
// ...
return checkInterruptedAsync()
.then(notifyPreReasoningEvent(prepareMessages()))
.flatMapMany(
event -> {
GenerateOptions options =
event.getEffectiveGenerateOptions() != null
? event.getEffectiveGenerateOptions()
: buildGenerateOptions(); // ← Returns options WITHOUT temperature
return model.stream(
event.getInputMessages(),
toolkit.getToolSchemas(),
options) // ← Options passed to model.stream()
.concatMap(chunk -> checkInterruptedAsync().thenReturn(chunk));
})
// ...
}
```

The `options` passed to `model.stream()` comes from `buildGenerateOptions()`, which returns a `GenerateOptions` object with `temperature = null`.

### 4. TelemetryTracer correctly checks for temperature

In [`AttributesExtractors.getLLMRequestAttributes()`](agentscope-extensions/agentscope-extensions-studio/src/main/java/io/agentscope/core/tracing/telemetry/AttributesExtractors.java:166-204):

```java
static Attributes getLLMRequestAttributes(..., GenerateOptions options) {
// ...
if (options != null) {
internalSet(builder, GEN_AI_REQUEST_TEMPERATURE, options.getTemperature()); // ← null
// ...
}
// ...
}
```

Since `options.getTemperature()` returns `null`, the attribute is not set (due to `internalSet` skipping null values).

## To Reproduce

Steps to reproduce the behavior:

1. **Setup TelemetryTracer with Langfuse:**

```java
TelemetryTracer tracer = TelemetryTracer.builder()
.endpoint("https://us.cloud.langfuse.com/api/public/otel/v1/traces")
.addHeader("Authorization", "Basic " + Base64.getEncoder()
.encodeToString((publicKey + ":" + secretKey).getBytes()))
.build();
TracerRegistry.register(tracer);
```

2. **Create an agent (no way to set temperature):**

```java
// Note: There is no generateOptions() method in the Builder!
ReActAgent agent = ReActAgent.builder()
.name("TestAgent")
.model(chatModel)
// .generateOptions(GenerateOptions.builder().temperature(0.7).build()) // ❌ This method doesn't exist!
.build();

agent.call(Msg.userMsg("Hello")).block();
```

3. **Check the trace in Langfuse/Jaeger/etc.:**
- Navigate to the trace viewer
- Inspect the `chat` span attributes
- **Observe that `gen_ai.request.temperature` is not present**

## Expected behavior

1. ReActAgent.Builder should have a `generateOptions(GenerateOptions)` method
2. ReActAgent.buildGenerateOptions() should return the configured generation options
3. The trace span for model calls should include:

```
gen_ai.request.temperature: 0.7
gen_ai.request.top_p: 0.9
gen_ai.request.max_tokens: 1000
```

## Suggested Fix

### Option 1: Add generateOptions to ReActAgent.Builder

```java
// In ReActAgent.Builder
private GenerateOptions generateOptions;

public Builder generateOptions(GenerateOptions generateOptions) {
this.generateOptions = generateOptions;
return this;
}
```

```java
// In ReActAgent
private final GenerateOptions generateOptions;

@Override
protected GenerateOptions buildGenerateOptions() {
GenerateOptions.Builder builder = GenerateOptions.builder();

// Merge with user-provided generateOptions
if (generateOptions != null) {
if (generateOptions.getTemperature() != null) {
builder.temperature(generateOptions.getTemperature());
}
if (generateOptions.getTopP() != null) {
builder.topP(generateOptions.getTopP());
}
if (generateOptions.getMaxTokens() != null) {
builder.maxTokens(generateOptions.getMaxTokens());
}
// ... other options
}

if (modelExecutionConfig != null) {
builder.executionConfig(modelExecutionConfig);
}

return builder.build();
}
```

### Option 2: Use Model's default options

Alternatively, retrieve default options from the Model itself if configured there.

## Environment

- **AgentScope-Java Version**: [e.g. 1.0.8]
- **Java Version**: 17
- **OS**: macOS

## Additional context

### Related code references:

| File | Location | Description |
|------|----------|-------------|
| [`ReActAgent.java`](agentscope-core/src/main/java/io/agentscope/core/ReActAgent.java:787-794) | `buildGenerateOptions()` | Returns GenerateOptions without temperature |
| [`ReActAgent.java`](agentscope-core/src/main/java/io/agentscope/core/ReActAgent.java:418-425) | `reasoning()` | Where options are built and passed to model |
| [`ReActAgent.java`](agentscope-core/src/main/java/io/agentscope/core/ReActAgent.java:971-1555) | `Builder` class | Missing `generateOptions()` method |
| [`TelemetryTracer.java`](agentscope-extensions/agentscope-extensions-studio/src/main/java/io/agentscope/core/tracing/telemetry/TelemetryTracer.java:109-151) | `callModel()` | Options passed to `getLLMRequestAttributes()` |
| [`AttributesExtractors.java`](agentscope-extensions/agentscope-extensions-studio/src/main/java/io/agentscope/core/tracing/telemetry/AttributesExtractors.java:176) | Line 176 | Temperature attribute extraction (skipped when null) |
| [`GenAiIncubatingAttributes.java`](agentscope-extensions/agentscope-extensions-studio/src/main/java/io/agentscope/core/tracing/telemetry/GenAiIncubatingAttributes.java:80-81) | Attribute key | `gen_ai.request.temperature` definition |

### References:

- [OpenTelemetry GenAI Semantic Conventions](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/gen-ai/gen-ai-spans.md)
- [Langfuse OpenTelemetry Integration](https://langfuse.com/docs/integrations/opentelemetry)

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Đánh giá

Issue này chưa được đánh giá.

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.