agentscope-ai / agentscope-ai/agentscope-java

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

Offen
#767 1 Kommentar 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen
area/ext/integration enhancement
Vorherrschende Sprache
Java
Sterne
5.6k
Forks
1.3k
Ø Merge
4 T. 12 Std.
Gemergte PRs (30 T.)
77

Beschreibung

## 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)

Beitragsleitfaden

Beitragsleitfaden öffnen

Bewertung

Dieses Issue wurde noch nicht bewertet.

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.