-
Notifications
You must be signed in to change notification settings - Fork 251
fix: Merging of events in rearrangeEventsForAsyncFunctionResponsesInHistory #682
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -203,27 +203,81 @@ public void rearrangeHistory_asyncFR_returnsRearrangedList() { | |||||||||
| public void rearrangeHistory_multipleFRsForSameFC_returnsMergedFR() { | ||||||||||
| Event fcEvent = createFunctionCallEvent("fc1", "tool1", "call1"); | ||||||||||
| Event frEvent1 = | ||||||||||
| createFunctionResponseEvent("fr1", "tool1", "call1", ImmutableMap.of("status", "running")); | ||||||||||
| createFunctionResponseEvent("fr1", "tool1", "call1", ImmutableMap.of("status", "pending")); | ||||||||||
| Event frEvent2 = | ||||||||||
| createFunctionResponseEvent("fr2", "tool1", "call1", ImmutableMap.of("status", "done")); | ||||||||||
| createFunctionResponseEvent("fr2", "tool1", "call1", ImmutableMap.of("status", "running")); | ||||||||||
| Event frEvent3 = | ||||||||||
| createFunctionResponseEvent("fr3", "tool1", "call1", ImmutableMap.of("status", "done")); | ||||||||||
| ImmutableList<Event> inputEvents = | ||||||||||
| ImmutableList.of( | ||||||||||
| createUserEvent("u1", "Query"), | ||||||||||
| fcEvent, | ||||||||||
| createUserEvent("u2", "Wait"), | ||||||||||
| frEvent1, | ||||||||||
| createUserEvent("u3", "Done?"), | ||||||||||
| frEvent2); | ||||||||||
| frEvent2, | ||||||||||
| frEvent3, | ||||||||||
| createUserEvent("u4", "Follow up query")); | ||||||||||
|
|
||||||||||
| List<Content> result = runContentsProcessor(inputEvents); | ||||||||||
|
|
||||||||||
| assertThat(result).hasSize(3); // u1, fc1, merged_fr | ||||||||||
| assertThat(result).hasSize(4); // u1, fc1, merged_fr, u4 | ||||||||||
| assertThat(result.get(0)).isEqualTo(inputEvents.get(0).content().get()); | ||||||||||
| assertThat(result.get(1)).isEqualTo(inputEvents.get(1).content().get()); // Check merged event | ||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The comment
Suggested change
|
||||||||||
| Content mergedContent = result.get(2); | ||||||||||
| assertThat(mergedContent.parts().get()).hasSize(1); | ||||||||||
| assertThat(mergedContent.parts().get().get(0).functionResponse().get().response().get()) | ||||||||||
| .containsExactly("status", "done"); // Last FR wins | ||||||||||
| .containsExactly("status", "done"); // Last FR wins (frEvent3) | ||||||||||
| assertThat(result.get(3)).isEqualTo(inputEvents.get(7).content().get()); // u4 | ||||||||||
| } | ||||||||||
|
|
||||||||||
| @Test | ||||||||||
| public void rearrangeHistory_multipleFRsForMultipleFC_returnsMergedFR() { | ||||||||||
| Event fcEvent1 = createFunctionCallEvent("fc1", "tool1", "call1"); | ||||||||||
| Event fcEvent2 = createFunctionCallEvent("fc2", "tool1", "call2"); | ||||||||||
|
|
||||||||||
| Event frEvent1 = | ||||||||||
| createFunctionResponseEvent("fr1", "tool1", "call1", ImmutableMap.of("status", "pending")); | ||||||||||
| Event frEvent2 = | ||||||||||
| createFunctionResponseEvent("fr2", "tool1", "call1", ImmutableMap.of("status", "done")); | ||||||||||
|
|
||||||||||
| Event frEvent3 = | ||||||||||
| createFunctionResponseEvent("fr3", "tool1", "call2", ImmutableMap.of("status", "pending")); | ||||||||||
| Event frEvent4 = | ||||||||||
| createFunctionResponseEvent("fr4", "tool1", "call2", ImmutableMap.of("status", "done")); | ||||||||||
|
|
||||||||||
| ImmutableList<Event> inputEvents = | ||||||||||
| ImmutableList.of( | ||||||||||
| createUserEvent("u1", "I"), | ||||||||||
| fcEvent1, | ||||||||||
| createUserEvent("u2", "am"), | ||||||||||
| frEvent1, | ||||||||||
| createUserEvent("u3", "waiting"), | ||||||||||
| frEvent2, | ||||||||||
| createUserEvent("u4", "for"), | ||||||||||
| fcEvent2, | ||||||||||
| createUserEvent("u5", "you"), | ||||||||||
| frEvent3, | ||||||||||
| createUserEvent("u6", "to"), | ||||||||||
| frEvent4, | ||||||||||
| createUserEvent("u7", "Follow up query")); | ||||||||||
|
|
||||||||||
| List<Content> result = runContentsProcessor(inputEvents); | ||||||||||
|
|
||||||||||
| assertThat(result).hasSize(7); // u1, fc1, merged_fr, u4, fc2, merged_fr2, u7 | ||||||||||
| assertThat(result.get(0)).isEqualTo(inputEvents.get(0).content().get()); // fc1 | ||||||||||
| assertThat(result.get(1)).isEqualTo(inputEvents.get(1).content().get()); // merged_fr | ||||||||||
|
Comment on lines
+268
to
+269
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These comments are incorrect.
Suggested change
|
||||||||||
| Content mergedContent = result.get(2); | ||||||||||
| assertThat(mergedContent.parts().get()).hasSize(1); | ||||||||||
| assertThat(mergedContent.parts().get().get(0).functionResponse().get().response().get()) | ||||||||||
| .containsExactly("status", "done"); // Last FR wins (frEvent2) | ||||||||||
| assertThat(result.get(3)).isEqualTo(inputEvents.get(6).content().get()); // u4 | ||||||||||
| assertThat(result.get(4)).isEqualTo(inputEvents.get(7).content().get()); // fc2 | ||||||||||
| Content mergedContent2 = result.get(5); | ||||||||||
| assertThat(mergedContent2.parts().get()).hasSize(1); | ||||||||||
| assertThat(mergedContent2.parts().get().get(0).functionResponse().get().response().get()) | ||||||||||
| .containsExactly("status", "done"); // Last FR wins (merged_fr2) | ||||||||||
| assertThat(result.get(6)).isEqualTo(inputEvents.get(12).content().get()); // u7 | ||||||||||
| } | ||||||||||
|
|
||||||||||
| @Test | ||||||||||
|
|
||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change correctly skips intermediate events. However, I've noticed a potential logic issue in the surrounding method. The
functionCallIdToResponseEventIndexmap only stores the index of the last function response for a given call ID. This prevents merging of multiple responses for a single function call, as only the last response is ever processed.mergeFunctionResponseEventsis not called in this case.For example, in the
rearrangeHistory_multipleFRsForSameFC_returnsMergedFRtest,fr1,fr2, andfr3should be merged, but with the current logic, onlyfr3is picked up and added to the results.To properly support merging, you might consider changing
functionCallIdToResponseEventIndexto aMap<String, List<Integer>>to track all responses for a function call. This seems like a significant issue, so I've marked it as high severity.