Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -122,18 +122,14 @@ public ChatClientResponse adviseCall(ChatClientRequest chatClientRequest, CallAd

ChatClientResponse chatClientResponse = null;

var repeatCounter = 0;

boolean isValidationSuccess = true;
boolean isValidationSuccess = false;

var processedChatClientRequest = chatClientRequest;

UsageAccumulator usageAccumulator = new UsageAccumulator();

do {
// Before Call
repeatCounter++;

for (var currentAttemptNumber = 1 + this.maxRepeatAttempts; currentAttemptNumber > 0
&& !isValidationSuccess; currentAttemptNumber--) {
// Next Call
chatClientResponse = callAdvisorChain.copy(this).nextCall(processedChatClientRequest);

Expand All @@ -144,8 +140,8 @@ public ChatClientResponse adviseCall(ChatClientRequest chatClientRequest, CallAd
// We should not validate tool call requests, only the content of the final
// response.
if (chatResponse == null || !chatResponse.hasToolCalls()) {

SchemaValidation validationResponse = validateOutputSchema(chatClientResponse);
SchemaValidation validationResponse = validateOutputSchema(chatClientResponse,
currentAttemptNumber - 1);

isValidationSuccess = validationResponse.success();

Expand All @@ -171,18 +167,18 @@ public ChatClientResponse adviseCall(ChatClientRequest chatClientRequest, CallAd

processedChatClientRequest = chatClientRequest.mutate().prompt(augmentedPrompt).build();
}
else if (logger.isDebugEnabled()) {
logger.debug("JSON validation succeeded");
}
}
}
while (!isValidationSuccess && repeatCounter <= this.maxRepeatAttempts);

return usageAccumulator.applyAccumulatedUsage(chatClientResponse);
return usageAccumulator.applyAccumulatedUsage(Objects.requireNonNull(chatClientResponse));
}

@SuppressWarnings("null")
private SchemaValidation validateOutputSchema(ChatClientResponse chatClientResponse) {
private SchemaValidation validateOutputSchema(ChatClientResponse chatClientResponse, int leftAttemptsCounter) {

if (chatClientResponse.chatResponse() == null || chatClientResponse.chatResponse().getResult() == null
|| chatClientResponse.chatResponse().getResult().getOutput() == null
|| chatClientResponse.chatResponse().getResult().getOutput().getText() == null) {

logger.warn("ChatClientResponse is missing required json output for validation.");
Expand All @@ -193,7 +189,7 @@ private SchemaValidation validateOutputSchema(ChatClientResponse chatClientRespo
String json = chatClientResponse.chatResponse().getResult().getOutput().getText();

if (logger.isDebugEnabled()) {
logger.debug("Validating JSON output against schema. Attempts left: " + this.maxRepeatAttempts);
logger.debug("Validating JSON output against schema. Attempts left: " + leftAttemptsCounter);
}

return validateJsonText(json);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
* @author Jewoo Shin
*/
@ExtendWith(MockitoExtension.class)
public class StructuredOutputValidationAdvisorTests {
class StructuredOutputValidationAdvisorTests {

@Mock
private CallAdvisorChain callAdvisorChain;
Expand Down Expand Up @@ -791,10 +791,12 @@ void testValidationWithInvalidListType() {

@Test
void testValidationWithWrongTypeInField() {
int maxRepeatAttempts = 3;
int lastAttemptNumber = maxRepeatAttempts + 1;
StructuredOutputValidationAdvisor advisor = StructuredOutputValidationAdvisor.builder()
.outputType(new TypeReference<Person>() {
})
.maxRepeatAttempts(1)
.maxRepeatAttempts(maxRepeatAttempts)
.build();

ChatClientRequest request = createMockRequest();
Expand All @@ -808,7 +810,7 @@ void testValidationWithWrongTypeInField() {
int[] callCount = { 0 };
CallAdvisor terminalAdvisor = terminalAdvisor((req, chain) -> {
callCount[0]++;
return callCount[0] == 1 ? invalidResponse : validResponse;
return callCount[0] == lastAttemptNumber ? validResponse : invalidResponse;
});

CallAdvisorChain realChain = DefaultAroundAdvisorChain.builder(ObservationRegistry.NOOP)
Expand All @@ -818,7 +820,7 @@ void testValidationWithWrongTypeInField() {
ChatClientResponse result = realChain.nextCall(request);

assertThat(result).isEqualTo(validResponse);
assertThat(callCount[0]).isEqualTo(2);
assertThat(callCount[0]).isEqualTo(lastAttemptNumber);
}

@Test
Expand Down
Loading