This is an automated email from the ASF dual-hosted git repository. wenjin272 pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/flink-agents.git
commit 911a9ae68bdd12fe6d6fbdfe8b596bb30abca816 Author: WenjinXie <[email protected]> AuthorDate: Tue Oct 20 11:12:53 2026 +0800 [examples][python] Handle review windows with no valid scores Return zero percentages when a window contains no valid ratings while retaining review reasons. Add aggregation regression coverage and update the quickstart example. Generated-by: Codex CLI 0.153.4 (GPT-6) Co-authored-by: Codex <[email protected]> --- .../quickstart/create-agent/multiple-agents.md | 7 +++- .../tests/test_multiple_agent_example.py | 47 ++++++++++++++++++++++ .../quickstart/workflow_multiple_agent_example.py | 4 +- 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/docs/content/docs/get-started/quickstart/create-agent/multiple-agents.md b/docs/content/docs/get-started/quickstart/create-agent/multiple-agents.md index 2162fce51..0adecb9b9 100644 --- a/docs/content/docs/get-started/quickstart/create-agent/multiple-agents.md +++ b/docs/content/docs/get-started/quickstart/create-agent/multiple-agents.md @@ -274,7 +274,8 @@ One review is too little to suggest an improvement, so the job groups the per-re product id in a one-minute tumbling window and reduces each group to a `ProductReviewSummary`. That type is declared in the shared types file and carries the product id, the score distribution, and the collected unsatisfied reasons. Python returns the summary object, and Java emits it as JSON -text, because the next stage reads it back with Jackson. +text, because the next stage reads it back with Jackson. Scores outside 1–5 are excluded from +the distribution; if none are valid, all five percentages are `0.0%`. The reasons are still retained. {{< tabs "Aggregate in a Window" >}} @@ -298,7 +299,9 @@ class AggregateScoreDistributionAndDislikeReasons(ProcessWindowFunction): rating_counts[rating - 1] += 1 reason_list = reason_list + element.reasons total = sum(rating_counts) - percentages = [round((x / total) * 100, 1) for x in rating_counts] + percentages = [ + round((x / total) * 100, 1) if total else 0.0 for x in rating_counts + ] formatted_percentages = [f"{p}%" for p in percentages] return [ ProductReviewSummary( diff --git a/python/flink_agents/examples/quickstart/tests/test_multiple_agent_example.py b/python/flink_agents/examples/quickstart/tests/test_multiple_agent_example.py new file mode 100644 index 000000000..d17ef6619 --- /dev/null +++ b/python/flink_agents/examples/quickstart/tests/test_multiple_agent_example.py @@ -0,0 +1,47 @@ +################################################################################ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +################################################################################# +"""Regression tests for score aggregation in the multi-agent example.""" + +import pytest + +from flink_agents.examples.quickstart.agents.custom_types_and_resources import ( + ProductReviewAnalysisRes, +) +from flink_agents.examples.quickstart.workflow_multiple_agent_example import ( + AggregateScoreDistributionAndDislikeReasons, +) + + [email protected]( + ("scores", "expected"), + [ + ([0, 6], ["0.0%"] * 5), + ([1, 5, 0, 6], ["50.0%", "0.0%", "0.0%", "0.0%", "50.0%"]), + ([3, 3], ["0.0%", "0.0%", "100.0%", "0.0%", "0.0%"]), + ], +) +def test_score_distribution_ignores_out_of_range_scores(scores, expected): + reviews = [ + ProductReviewAnalysisRes(id="product", score=score, reasons=[str(score)]) + for score in scores + ] + summary, = AggregateScoreDistributionAndDislikeReasons().process( + "product", None, reviews + ) + assert summary.score_hist == expected + assert summary.unsatisfied_reasons == [str(score) for score in scores] diff --git a/python/flink_agents/examples/quickstart/workflow_multiple_agent_example.py b/python/flink_agents/examples/quickstart/workflow_multiple_agent_example.py index b9bc3e6d5..a2cc16360 100644 --- a/python/flink_agents/examples/quickstart/workflow_multiple_agent_example.py +++ b/python/flink_agents/examples/quickstart/workflow_multiple_agent_example.py @@ -66,7 +66,9 @@ class AggregateScoreDistributionAndDislikeReasons(ProcessWindowFunction): rating_counts[rating - 1] += 1 reason_list = reason_list + element.reasons total = sum(rating_counts) - percentages = [round((x / total) * 100, 1) for x in rating_counts] + percentages = [ + round((x / total) * 100, 1) if total else 0.0 for x in rating_counts + ] formatted_percentages = [f"{p}%" for p in percentages] return [ ProductReviewSummary(
