Skip to content

Commit 86ba656

Browse files
committed
ChatModel: throw ToolExecutionLimitExceededException when over limit tool calling
Signed-off-by: lambochen <[email protected]>
1 parent ee79d7b commit 86ba656

File tree

14 files changed

+139
-7
lines changed

14 files changed

+139
-7
lines changed

models/spring-ai-anthropic/src/main/java/org/springframework/ai/anthropic/AnthropicChatModel.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import io.micrometer.observation.contextpropagation.ObservationThreadLocalAccessor;
3131
import org.slf4j.Logger;
3232
import org.slf4j.LoggerFactory;
33+
import org.springframework.ai.model.tool.ToolExecutionLimitExceededException;
3334
import reactor.core.publisher.Flux;
3435
import reactor.core.publisher.Mono;
3536
import reactor.core.scheduler.Schedulers;
@@ -223,6 +224,9 @@ public ChatResponse internalCall(Prompt prompt, ChatResponse previousChatRespons
223224
response, iterations + 1);
224225
}
225226
}
227+
else if (this.toolExecutionEligibilityPredicate.isLimitExceeded(prompt.getOptions(), iterations)) {
228+
throw new ToolExecutionLimitExceededException(iterations);
229+
}
226230

227231
return response;
228232
}
@@ -287,6 +291,8 @@ public Flux<ChatResponse> internalStream(Prompt prompt, ChatResponse previousCha
287291
chatResponse, iterations + 1);
288292
}
289293
}).subscribeOn(Schedulers.boundedElastic());
294+
} else if(this.toolExecutionEligibilityPredicate.isLimitExceeded(prompt.getOptions(), iterations)){
295+
throw new ToolExecutionLimitExceededException(iterations);
290296
}
291297

292298
return Mono.just(chatResponse);

models/spring-ai-azure-openai/src/main/java/org/springframework/ai/azure/openai/AzureOpenAiChatModel.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
import io.micrometer.observation.contextpropagation.ObservationThreadLocalAccessor;
6363
import org.slf4j.Logger;
6464
import org.slf4j.LoggerFactory;
65+
import org.springframework.ai.model.tool.ToolExecutionLimitExceededException;
6566
import reactor.core.publisher.Flux;
6667
import reactor.core.scheduler.Schedulers;
6768

@@ -291,6 +292,9 @@ public ChatResponse internalCall(Prompt prompt, ChatResponse previousChatRespons
291292
response, iterations + 1);
292293
}
293294
}
295+
else if (this.toolExecutionEligibilityPredicate.isLimitExceeded(prompt.getOptions(), iterations)) {
296+
throw new ToolExecutionLimitExceededException(iterations);
297+
}
294298

295299
return response;
296300
}
@@ -408,6 +412,9 @@ public Flux<ChatResponse> internalStream(Prompt prompt, ChatResponse previousCha
408412
}
409413
}).subscribeOn(Schedulers.boundedElastic());
410414
}
415+
else if (this.toolExecutionEligibilityPredicate.isLimitExceeded(prompt.getOptions(), iterations)) {
416+
throw new ToolExecutionLimitExceededException(iterations);
417+
}
411418

412419
Flux<ChatResponse> flux = Flux.just(chatResponse)
413420
.doOnError(observation::error)

models/spring-ai-bedrock-converse/src/main/java/org/springframework/ai/bedrock/converse/BedrockProxyChatModel.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import io.micrometer.observation.contextpropagation.ObservationThreadLocalAccessor;
3434
import org.slf4j.Logger;
3535
import org.slf4j.LoggerFactory;
36+
import org.springframework.ai.model.tool.ToolExecutionLimitExceededException;
3637
import reactor.core.publisher.Flux;
3738
import reactor.core.publisher.Sinks;
3839
import reactor.core.publisher.Sinks.EmitFailureHandler;
@@ -262,6 +263,10 @@ private ChatResponse internalCall(Prompt prompt, ChatResponse perviousChatRespon
262263
chatResponse, iterations + 1);
263264
}
264265
}
266+
else if (this.toolExecutionEligibilityPredicate.isLimitExceeded(prompt.getOptions(), iterations)) {
267+
throw new ToolExecutionLimitExceededException(iterations);
268+
}
269+
265270
return chatResponse;
266271
}
267272

@@ -711,6 +716,9 @@ private Flux<ChatResponse> internalStream(Prompt prompt, ChatResponse perviousCh
711716
}
712717
}).subscribeOn(Schedulers.boundedElastic());
713718
}
719+
else if (this.toolExecutionEligibilityPredicate.isLimitExceeded(prompt.getOptions(), iterations)) {
720+
throw new ToolExecutionLimitExceededException(iterations);
721+
}
714722
else {
715723
return Flux.just(chatResponse);
716724
}

models/spring-ai-deepseek/src/main/java/org/springframework/ai/deepseek/DeepSeekChatModel.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import io.micrometer.observation.contextpropagation.ObservationThreadLocalAccessor;
2626
import org.slf4j.Logger;
2727
import org.slf4j.LoggerFactory;
28+
import org.springframework.ai.model.tool.ToolExecutionLimitExceededException;
2829
import reactor.core.publisher.Flux;
2930
import reactor.core.publisher.Mono;
3031
import reactor.core.scheduler.Schedulers;
@@ -225,6 +226,9 @@ public ChatResponse internalCall(Prompt prompt, ChatResponse previousChatRespons
225226
response, iterations + 1);
226227
}
227228
}
229+
else if (this.toolExecutionEligibilityPredicate.isLimitExceeded(prompt.getOptions(), iterations)) {
230+
throw new ToolExecutionLimitExceededException(iterations);
231+
}
228232

229233
return response;
230234
}
@@ -311,6 +315,8 @@ public Flux<ChatResponse> internalStream(Prompt prompt, ChatResponse previousCha
311315
response, iterations + 1);
312316
}
313317
}).subscribeOn(Schedulers.boundedElastic());
318+
} else if (this.toolExecutionEligibilityPredicate.isLimitExceeded(prompt.getOptions(), iterations)){
319+
throw new ToolExecutionLimitExceededException(iterations);
314320
}
315321
else {
316322
return Flux.just(response);

models/spring-ai-minimax/src/main/java/org/springframework/ai/minimax/MiniMaxChatModel.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import io.micrometer.observation.contextpropagation.ObservationThreadLocalAccessor;
2727
import org.slf4j.Logger;
2828
import org.slf4j.LoggerFactory;
29+
import org.springframework.ai.model.tool.ToolExecutionLimitExceededException;
2930
import reactor.core.publisher.Flux;
3031
import reactor.core.publisher.Mono;
3132
import reactor.core.scheduler.Schedulers;
@@ -315,6 +316,9 @@ else if (!CollectionUtils.isEmpty(choice.messages())) {
315316
iterations + 1);
316317
}
317318
}
319+
else if (this.toolExecutionEligibilityPredicate.isLimitExceeded(requestPrompt.getOptions(), iterations)) {
320+
throw new ToolExecutionLimitExceededException(iterations);
321+
}
318322

319323
return response;
320324
}
@@ -398,7 +402,10 @@ private Flux<ChatResponse> internalStream(Prompt requestPrompt, int iterations)
398402
return this.internalStream(new Prompt(toolExecutionResult.conversationHistory(), requestPrompt.getOptions()), iterations + 1);
399403
}
400404
}).subscribeOn(Schedulers.boundedElastic());
405+
} else if (this.toolExecutionEligibilityPredicate.isLimitExceeded(requestPrompt.getOptions(), iterations)){
406+
throw new ToolExecutionLimitExceededException(iterations);
401407
}
408+
402409
return Flux.just(response);
403410
})
404411
.doOnError(observation::error)

models/spring-ai-mistral-ai/src/main/java/org/springframework/ai/mistralai/MistralAiChatModel.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import io.micrometer.observation.contextpropagation.ObservationThreadLocalAccessor;
2828
import org.slf4j.Logger;
2929
import org.slf4j.LoggerFactory;
30+
import org.springframework.ai.model.tool.ToolExecutionLimitExceededException;
3031
import reactor.core.publisher.Flux;
3132
import reactor.core.publisher.Mono;
3233
import reactor.core.scheduler.Schedulers;
@@ -246,6 +247,9 @@ public ChatResponse internalCall(Prompt prompt, ChatResponse previousChatRespons
246247
response, iterations + 1);
247248
}
248249
}
250+
else if (this.toolExecutionEligibilityPredicate.isLimitExceeded(prompt.getOptions(), iterations)) {
251+
throw new ToolExecutionLimitExceededException(iterations);
252+
}
249253

250254
return response;
251255
}
@@ -340,6 +344,8 @@ public Flux<ChatResponse> internalStream(Prompt prompt, ChatResponse previousCha
340344
response, iterations + 1);
341345
}
342346
}).subscribeOn(Schedulers.boundedElastic());
347+
} else if (this.toolExecutionEligibilityPredicate.isLimitExceeded(prompt.getOptions(), iterations)){
348+
throw new ToolExecutionLimitExceededException(iterations);
343349
}
344350
else {
345351
return Flux.just(response);

models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/OllamaChatModel.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import io.micrometer.observation.contextpropagation.ObservationThreadLocalAccessor;
2929
import org.slf4j.Logger;
3030
import org.slf4j.LoggerFactory;
31+
import org.springframework.ai.model.tool.ToolExecutionLimitExceededException;
3132
import reactor.core.publisher.Flux;
3233
import reactor.core.scheduler.Schedulers;
3334

@@ -293,6 +294,9 @@ private ChatResponse internalCall(Prompt prompt, ChatResponse previousChatRespon
293294
response, iterations + 1);
294295
}
295296
}
297+
else if (this.toolExecutionEligibilityPredicate.isLimitExceeded(prompt.getOptions(), iterations)) {
298+
throw new ToolExecutionLimitExceededException(iterations);
299+
}
296300

297301
return response;
298302
}
@@ -367,6 +371,8 @@ private Flux<ChatResponse> internalStream(Prompt prompt, ChatResponse previousCh
367371
response, iterations + 1);
368372
}
369373
}).subscribeOn(Schedulers.boundedElastic());
374+
} else if (this.toolExecutionEligibilityPredicate.isLimitExceeded(prompt.getOptions(), iterations)){
375+
throw new ToolExecutionLimitExceededException(iterations);
370376
}
371377
else {
372378
return Flux.just(response);

models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiChatModel.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import io.micrometer.observation.contextpropagation.ObservationThreadLocalAccessor;
3030
import org.slf4j.Logger;
3131
import org.slf4j.LoggerFactory;
32+
import org.springframework.ai.model.tool.ToolExecutionLimitExceededException;
3233
import reactor.core.publisher.Flux;
3334
import reactor.core.publisher.Mono;
3435
import reactor.core.scheduler.Schedulers;
@@ -261,6 +262,9 @@ public ChatResponse internalCall(Prompt prompt, ChatResponse previousChatRespons
261262
response, iterations + 1);
262263
}
263264
}
265+
else if (this.toolExecutionEligibilityPredicate.isLimitExceeded(prompt.getOptions(), iterations)) {
266+
throw new ToolExecutionLimitExceededException(iterations);
267+
}
264268

265269
return response;
266270
}
@@ -389,6 +393,8 @@ public Flux<ChatResponse> internalStream(Prompt prompt, ChatResponse previousCha
389393
response, iterations + 1);
390394
}
391395
}).subscribeOn(Schedulers.boundedElastic());
396+
} else if (this.toolExecutionEligibilityPredicate.isLimitExceeded(prompt.getOptions(), iterations)){
397+
throw new ToolExecutionLimitExceededException(iterations);
392398
}
393399
else {
394400
return Flux.just(response);

models/spring-ai-vertex-ai-gemini/src/main/java/org/springframework/ai/vertexai/gemini/VertexAiGeminiChatModel.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
import io.micrometer.observation.contextpropagation.ObservationThreadLocalAccessor;
5050
import org.slf4j.Logger;
5151
import org.slf4j.LoggerFactory;
52+
import org.springframework.ai.model.tool.ToolExecutionLimitExceededException;
5253
import reactor.core.publisher.Flux;
5354
import reactor.core.scheduler.Schedulers;
5455

@@ -446,6 +447,9 @@ private ChatResponse internalCall(Prompt prompt, ChatResponse previousChatRespon
446447
response, iterations + 1);
447448
}
448449
}
450+
else if (this.toolExecutionEligibilityPredicate.isLimitExceeded(prompt.getOptions(), iterations)) {
451+
throw new ToolExecutionLimitExceededException(iterations);
452+
}
449453

450454
return response;
451455

@@ -572,6 +576,8 @@ public Flux<ChatResponse> internalStream(Prompt prompt, ChatResponse previousCha
572576
iterations + 1);
573577
}
574578
}).subscribeOn(Schedulers.boundedElastic());
579+
} else if (this.toolExecutionEligibilityPredicate.isLimitExceeded(prompt.getOptions(), iterations)){
580+
throw new ToolExecutionLimitExceededException(iterations);
575581
}
576582
else {
577583
return Flux.just(response);

models/spring-ai-zhipuai/src/main/java/org/springframework/ai/zhipuai/ZhiPuAiChatModel.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import io.micrometer.observation.contextpropagation.ObservationThreadLocalAccessor;
2828
import org.slf4j.Logger;
2929
import org.slf4j.LoggerFactory;
30+
import org.springframework.ai.model.tool.ToolExecutionLimitExceededException;
3031
import reactor.core.publisher.Flux;
3132
import reactor.core.publisher.Mono;
3233
import reactor.core.scheduler.Schedulers;
@@ -301,6 +302,10 @@ private ChatResponse internalCall(Prompt requestPrompt, int iterations) {
301302
iterations + 1);
302303
}
303304
}
305+
else if (this.toolExecutionEligibilityPredicate.isLimitExceeded(requestPrompt.getOptions(), iterations)) {
306+
throw new ToolExecutionLimitExceededException(iterations);
307+
}
308+
304309
return response;
305310
}
306311

@@ -387,6 +392,8 @@ private Flux<ChatResponse> internalStream(Prompt prompt, int iterations) {
387392
iterations + 1);
388393
}
389394
}).subscribeOn(Schedulers.boundedElastic());
395+
} else if (this.toolExecutionEligibilityPredicate.isLimitExceeded(prompt.getOptions(), iterations)){
396+
throw new ToolExecutionLimitExceededException(iterations);
390397
}
391398
return Flux.just(response);
392399
})

0 commit comments

Comments
 (0)