Skip to content

Commit 58ed2e7

Browse files
committed
feat: add support for removing thinking tags from input text in BeanOutputConverter
Signed-off-by: liugddx <liugddx@gmail.com>
1 parent 0fdb911 commit 58ed2e7

File tree

2 files changed

+47
-0
lines changed

2 files changed

+47
-0
lines changed

spring-ai-model/src/main/java/org/springframework/ai/converter/BeanOutputConverter.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,10 @@ public T convert(@NonNull String text) {
169169
// Remove leading and trailing whitespace
170170
text = text.trim();
171171

172+
// Remove thinking tags (e.g., from Amazon Nova models)
173+
// These tags can appear at the beginning of the response
174+
text = text.replaceAll("(?s)<thinking>.*?</thinking>\\s*", "");
175+
172176
// Check for and remove triple backticks and "json" identifier
173177
if (text.startsWith("```") && text.endsWith("```")) {
174178
// Remove the first line if it contains "```json"

spring-ai-model/src/test/java/org/springframework/ai/converter/BeanOutputConverterTest.java

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,49 @@ void convertTypeReferenceArrayWithJsonAnnotations() {
238238
assertThat(testClass.get(0).getSomeString()).isEqualTo("some value");
239239
}
240240

241+
@Test
242+
void convertWithThinkingTags() {
243+
var converter = new BeanOutputConverter<>(TestClass.class);
244+
String textWithThinkingTags = "<thinking>This is my reasoning process...</thinking>{ \"someString\": \"some value\" }";
245+
var testClass = converter.convert(textWithThinkingTags);
246+
assertThat(testClass.getSomeString()).isEqualTo("some value");
247+
}
248+
249+
@Test
250+
void convertWithThinkingTagsMultiline() {
251+
var converter = new BeanOutputConverter<>(TestClass.class);
252+
String textWithThinkingTags = """
253+
<thinking>
254+
This is my reasoning process
255+
spanning multiple lines
256+
</thinking>
257+
{ "someString": "some value" }
258+
""";
259+
var testClass = converter.convert(textWithThinkingTags);
260+
assertThat(testClass.getSomeString()).isEqualTo("some value");
261+
}
262+
263+
@Test
264+
void convertWithThinkingTagsAndMarkdownCodeBlock() {
265+
var converter = new BeanOutputConverter<>(TestClass.class);
266+
String textWithThinkingTags = """
267+
<thinking>This is my reasoning process...</thinking>
268+
```json
269+
{ "someString": "some value" }
270+
```
271+
""";
272+
var testClass = converter.convert(textWithThinkingTags);
273+
assertThat(testClass.getSomeString()).isEqualTo("some value");
274+
}
275+
276+
@Test
277+
void convertWithMultipleThinkingTags() {
278+
var converter = new BeanOutputConverter<>(TestClass.class);
279+
String textWithThinkingTags = "<thinking>First thought</thinking><thinking>Second thought</thinking>{ \"someString\": \"some value\" }";
280+
var testClass = converter.convert(textWithThinkingTags);
281+
assertThat(testClass.getSomeString()).isEqualTo("some value");
282+
}
283+
241284
}
242285

243286
// @checkstyle:off RegexpSinglelineJavaCheck

0 commit comments

Comments
 (0)