Skip to content

Commit 6d7856c

Browse files
JGoP-Lclaude
andauthored
fix(model): auto-generate ChatResponse.id when LLM doesn't provide it (#721)
AgentScope-Java Version 1.0.9-SNAPSHOT Description This PR fixes Issue #708 where OllamaChatModel fails with the AGUI protocol due to missing id field in Ollama API responses. Problem Ollama API doesn't return an id field in its chat completion responses, unlike other LLM providers (OpenAI, Anthropic, DashScope). This causes the AGUI protocol and other components that depend on ChatResponse.getId() to fail with NullPointerException: "messageId cannot be null". Root Cause Chain: Ollama API → no id field ↓ OllamaResponseParser → ChatResponse.id = null ↓ Msg.id = null ↓ Event.getMessage().getId() = null ↓ AguiEvent.TextMessageStart → NullPointerException Solution Modified ChatResponse.Builder.build() to automatically generate a UUID when id is null or empty. This provides a unified solution that: 1. Fixes the Ollama issue - Ollama responses now get auto-generated IDs 2. Benefits all parsers - Any future provider without an id field is handled automatically 3. Maintains backward compatibility - Providers that return an id keep their original value 4. Follows single responsibility principle - The Builder ensures valid object state Changes Modified Files: - ChatResponse.java - Modified build() method to auto-generate UUID when id is null or empty - AnthropicResponseParserTest.java - Updated test assertion to verify auto-generated IDs Code Change: public ChatResponse build() { // Auto-generate id if not set or empty (for providers like Ollama) String responseId = this.id; if (responseId == null || responseId.isEmpty()) { responseId = UUID.randomUUID().toString(); } return new ChatResponse(responseId, content, usage, metadata, finishReason); } Testing Manual Testing: - Created reproduction test using OllamaChatModel with AGUI protocol - Verified that all events now contain valid messageId values - Tested with Ollama model qwen2.5:0.5b running locally Automated Testing: - All existing tests pass (3289 tests, 0 failures, 118 skipped) - Updated AnthropicResponseParserTest to reflect new behavior Checklist - Code has been formatted with mvn spotless:apply - All tests are passing (mvn test) - Javadoc comments are complete and follow project conventions - Related documentation has been updated (e.g. links, examples, etc.) - Code is ready for review Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
1 parent f83ce3c commit 6d7856c

File tree

2 files changed

+14
-2
lines changed

2 files changed

+14
-2
lines changed

agentscope-core/src/main/java/io/agentscope/core/model/ChatResponse.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import io.agentscope.core.message.ContentBlock;
1919
import java.util.List;
2020
import java.util.Map;
21+
import java.util.UUID;
2122

2223
/**
2324
* Represents a chat completion response from a language model.
@@ -176,11 +177,20 @@ public Builder finishReason(String finishReason) {
176177

177178
/**
178179
* Builds a new ChatResponse instance with the set values.
180+
* <p>
181+
* If no id was set (or is empty/blank), a random UUID will be generated
182+
* automatically. This ensures compatibility with LLM providers (like Ollama)
183+
* that don't return an id field in their API responses.
179184
*
180185
* @return a new ChatResponse instance
181186
*/
182187
public ChatResponse build() {
183-
return new ChatResponse(id, content, usage, metadata, finishReason);
188+
// Auto-generate id if not set, empty, or blank (for providers like Ollama)
189+
String responseId = this.id;
190+
if (responseId == null || responseId.trim().isEmpty()) {
191+
responseId = UUID.randomUUID().toString();
192+
}
193+
return new ChatResponse(responseId, content, usage, metadata, finishReason);
184194
}
185195
}
186196
}

agentscope-core/src/test/java/io/agentscope/core/formatter/anthropic/AnthropicResponseParserTest.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package io.agentscope.core.formatter.anthropic;
1717

1818
import static org.junit.jupiter.api.Assertions.assertEquals;
19+
import static org.junit.jupiter.api.Assertions.assertFalse;
1920
import static org.junit.jupiter.api.Assertions.assertNotNull;
2021
import static org.junit.jupiter.api.Assertions.assertNull;
2122
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -324,7 +325,8 @@ void testParseStreamEventUnknownType() throws Exception {
324325
ChatResponse response = invokeParseStreamEvent(event, startTime);
325326

326327
assertNotNull(response);
327-
assertNull(response.getId());
328+
assertNotNull(response.getId()); // Builder auto-generates UUID when id is null
329+
assertFalse(response.getId().isEmpty());
328330
assertTrue(response.getContent().isEmpty());
329331
assertNull(response.getUsage());
330332
}

0 commit comments

Comments
 (0)