Sina1138 commited on
Commit ·
b0fbb48
1
Parent(s): d2ab04b
Enhance interactive review processing: support up to 6 reviews, improve metadata handling, and update UI for review inputs
Browse files- interface/Demo.py +197 -197
- interface/interactive_processor.py +27 -26
interface/Demo.py
CHANGED
|
@@ -65,6 +65,14 @@ def get_preprocessed_scores(year):
|
|
| 65 |
return scored_reviews
|
| 66 |
|
| 67 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 68 |
# -----------------------------------
|
| 69 |
# Interactive Tab Configuration
|
| 70 |
# -----------------------------------
|
|
@@ -113,7 +121,7 @@ Use this tab to explore reviews from ICLR ({year_range_str}):
|
|
| 113 |
- **Topic**: Highlights comments by discussion topic using color-coded labels.
|
| 114 |
#### Interactive Tab
|
| 115 |
Use this tab to analyze your own review text:
|
| 116 |
-
1. **Enter
|
| 117 |
2. **Click "Process"** to analyze the input (average processing time: ~42 seconds).
|
| 118 |
3. **Explore the results** using the same highlighting options as above (Agreement, Polarity, Topic).
|
| 119 |
"""
|
|
@@ -172,35 +180,40 @@ def get_interactive_processor():
|
|
| 172 |
return _interactive_processor
|
| 173 |
|
| 174 |
|
| 175 |
-
|
|
|
|
|
|
|
|
|
|
| 176 |
"""
|
| 177 |
Fetch reviews from OpenReview link and populate the textboxes.
|
| 178 |
|
| 179 |
Returns:
|
| 180 |
-
Tuple of (review1,
|
| 181 |
"""
|
| 182 |
print(f"\n[DEMO] fetch_openreview_reviews called with link: {link}")
|
| 183 |
|
|
|
|
|
|
|
| 184 |
if not link.strip():
|
| 185 |
-
return (
|
| 186 |
|
| 187 |
try:
|
| 188 |
from interface.interactive_processor import fetch_reviews_from_openreview_link
|
| 189 |
reviews, title = fetch_reviews_from_openreview_link(link)
|
| 190 |
print(f"[DEMO] Got {len(reviews)} reviews from fetch function")
|
| 191 |
|
| 192 |
-
while len(reviews) <
|
| 193 |
reviews.append("")
|
| 194 |
-
reviews = reviews[:
|
| 195 |
|
| 196 |
num_reviews = len([r for r in reviews if r.strip()])
|
| 197 |
status = _status_html(f"Fetched {num_reviews} reviews for: {title}", "success")
|
| 198 |
-
return (reviews
|
| 199 |
|
| 200 |
except ValueError as e:
|
| 201 |
error_msg = str(e)
|
| 202 |
print(f"[DEMO] ValueError caught: {error_msg}")
|
| 203 |
-
return (
|
| 204 |
except Exception as e:
|
| 205 |
error_msg = str(e)
|
| 206 |
print(f"[DEMO] Exception caught: {type(e).__name__}: {error_msg}")
|
|
@@ -212,18 +225,20 @@ def fetch_openreview_reviews(link: str) -> Tuple[str, str, str, str, str]:
|
|
| 212 |
else:
|
| 213 |
suggestion = ""
|
| 214 |
|
| 215 |
-
return (
|
| 216 |
|
| 217 |
|
| 218 |
-
def process_interactive_reviews(text1: str, text2: str, text3: str, focus: str, progress=gr.Progress()) -> Tuple:
|
| 219 |
"""
|
| 220 |
-
Process reviews through the interactive pipeline with progress tracking.
|
| 221 |
"""
|
| 222 |
from dependencies.Glimpse_tokenizer import glimpse_tokenizer
|
| 223 |
|
| 224 |
-
|
| 225 |
-
|
| 226 |
-
|
|
|
|
|
|
|
| 227 |
|
| 228 |
# Step 1: Load models
|
| 229 |
progress(0.0, desc="Loading models...")
|
|
@@ -231,14 +246,13 @@ def process_interactive_reviews(text1: str, text2: str, text3: str, focus: str,
|
|
| 231 |
|
| 232 |
# Step 2: Tokenize
|
| 233 |
progress(0.10, desc="Tokenizing reviews...")
|
| 234 |
-
|
| 235 |
-
|
| 236 |
-
text3_sentences = [s for s in glimpse_tokenizer(text3) if s.strip()]
|
| 237 |
|
| 238 |
-
if
|
| 239 |
-
raise ValueError("
|
| 240 |
|
| 241 |
-
all_sentences = list(set(
|
| 242 |
|
| 243 |
# Step 3: Polarity
|
| 244 |
progress(0.20, desc="Predicting polarity...")
|
|
@@ -250,12 +264,11 @@ def process_interactive_reviews(text1: str, text2: str, text3: str, focus: str,
|
|
| 250 |
|
| 251 |
# Step 5: Consensuality (RSA) - the slow one
|
| 252 |
progress(0.55, desc="Computing agreement (RSA reranking)...")
|
| 253 |
-
consensuality_map = processor.predict_consensuality(
|
| 254 |
|
| 255 |
# Step 6: Format results
|
| 256 |
progress(0.90, desc="Formatting results...")
|
| 257 |
|
| 258 |
-
# Most common / unique
|
| 259 |
if consensuality_map:
|
| 260 |
import pandas as _pd
|
| 261 |
scores_series = _pd.Series(consensuality_map)
|
|
@@ -265,31 +278,48 @@ def process_interactive_reviews(text1: str, text2: str, text3: str, focus: str,
|
|
| 265 |
most_common_text = ""
|
| 266 |
most_unique_text = ""
|
| 267 |
|
| 268 |
-
# Format highlighted outputs
|
| 269 |
fmt = processor.format_highlighted_output
|
| 270 |
-
|
| 271 |
-
|
| 272 |
-
|
| 273 |
-
|
| 274 |
-
|
| 275 |
-
|
| 276 |
-
|
| 277 |
-
|
| 278 |
-
|
|
|
|
|
|
|
| 279 |
|
| 280 |
progress(1.0, desc="Done!")
|
| 281 |
|
| 282 |
return (
|
| 283 |
-
|
| 284 |
most_common_text, most_unique_text,
|
| 285 |
-
|
| 286 |
-
|
|
|
|
| 287 |
)
|
| 288 |
|
| 289 |
|
| 290 |
|
| 291 |
|
| 292 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 293 |
# gr.Markdown("# ReView Interface")
|
| 294 |
|
| 295 |
with gr.Tab("Introduction"):
|
|
@@ -307,6 +337,7 @@ with gr.Blocks(title="ReView") as demo:
|
|
| 307 |
initial_review_ids = list(initial_scored_reviews.keys())
|
| 308 |
initial_review = initial_scored_reviews[initial_review_ids[0]]
|
| 309 |
number_of_displayed_reviews = len(initial_scored_reviews[initial_review_ids[0]])
|
|
|
|
| 310 |
initial_state = {
|
| 311 |
"year_choice": initial_year,
|
| 312 |
"scored_reviews_for_year": initial_scored_reviews,
|
|
@@ -314,6 +345,7 @@ with gr.Blocks(title="ReView") as demo:
|
|
| 314 |
"current_review_index": 0,
|
| 315 |
"current_review": initial_review,
|
| 316 |
"number_of_displayed_reviews": number_of_displayed_reviews,
|
|
|
|
| 317 |
}
|
| 318 |
state = gr.State(initial_state)
|
| 319 |
|
|
@@ -350,7 +382,7 @@ with gr.Blocks(title="ReView") as demo:
|
|
| 350 |
review_updates = []
|
| 351 |
consensuality_dict = {}
|
| 352 |
|
| 353 |
-
for i in range(
|
| 354 |
if i < number_of_displayed_reviews:
|
| 355 |
review_item = list(current_review[i].items())
|
| 356 |
|
|
@@ -410,6 +442,14 @@ with gr.Blocks(title="ReView") as demo:
|
|
| 410 |
)
|
| 411 |
)
|
| 412 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 413 |
# Set most consensual / unique sentences
|
| 414 |
if show_consensuality and consensuality_dict:
|
| 415 |
scores = pd.Series(consensuality_dict)
|
|
@@ -451,6 +491,8 @@ with gr.Blocks(title="ReView") as demo:
|
|
| 451 |
most_common_visibility,
|
| 452 |
most_unique_visibility,
|
| 453 |
topic_color_map_visibility,
|
|
|
|
|
|
|
| 454 |
state
|
| 455 |
)
|
| 456 |
|
|
@@ -458,7 +500,7 @@ with gr.Blocks(title="ReView") as demo:
|
|
| 458 |
|
| 459 |
# Precompute the initial outputs so something is shown on load.
|
| 460 |
init_display = update_review_display(initial_state, score_type="Original")
|
| 461 |
-
# init_display returns: (review_id, review1,
|
| 462 |
|
| 463 |
with gr.Row():
|
| 464 |
|
|
@@ -502,67 +544,26 @@ with gr.Blocks(title="ReView") as demo:
|
|
| 502 |
show_legend=True,
|
| 503 |
)
|
| 504 |
|
| 505 |
-
|
| 506 |
-
|
| 507 |
-
|
| 508 |
-
|
| 509 |
-
|
| 510 |
-
|
| 511 |
-
)
|
| 512 |
-
|
| 513 |
-
|
| 514 |
-
|
| 515 |
-
|
| 516 |
-
|
| 517 |
-
|
| 518 |
-
)
|
| 519 |
-
review3 = gr.HighlightedText(
|
| 520 |
-
show_legend=False,
|
| 521 |
-
label="Review 3",
|
| 522 |
-
visible= number_of_displayed_reviews >= 3,
|
| 523 |
-
key="initial_review3"
|
| 524 |
-
# color_map={"Positive": "#d4fcd6", "Negative": "#fcd6d6"}
|
| 525 |
-
)
|
| 526 |
-
review4 = gr.HighlightedText(
|
| 527 |
-
show_legend=False,
|
| 528 |
-
label="Review 4",
|
| 529 |
-
visible= number_of_displayed_reviews >= 4,
|
| 530 |
-
key="initial_review4"
|
| 531 |
-
# color_map={"Positive": "#d4fcd6", "Negative": "#fcd6d6"}
|
| 532 |
-
)
|
| 533 |
-
review5 = gr.HighlightedText(
|
| 534 |
-
show_legend=False,
|
| 535 |
-
label="Review 5",
|
| 536 |
-
visible= number_of_displayed_reviews >= 5,
|
| 537 |
-
key="initial_review5"
|
| 538 |
-
# color_map={"Positive": "#d4fcd6", "Negative": "#fcd6d6"}
|
| 539 |
-
)
|
| 540 |
-
review6 = gr.HighlightedText(
|
| 541 |
-
show_legend=False,
|
| 542 |
-
label="Review 6",
|
| 543 |
-
visible= number_of_displayed_reviews >= 6,
|
| 544 |
-
key="initial_review6"
|
| 545 |
-
# color_map={"Positive": "#d4fcd6", "Negative": "#fcd6d6"}
|
| 546 |
-
)
|
| 547 |
-
review7 = gr.HighlightedText(
|
| 548 |
-
show_legend=False,
|
| 549 |
-
label="Review 7",
|
| 550 |
-
visible= number_of_displayed_reviews >= 7,
|
| 551 |
-
key="initial_review7"
|
| 552 |
-
# color_map={"Positive": "#d4fcd6", "Negative": "#fcd6d6"}
|
| 553 |
-
)
|
| 554 |
-
review8 = gr.HighlightedText(
|
| 555 |
-
show_legend=False,
|
| 556 |
-
label="Review 8",
|
| 557 |
-
visible= number_of_displayed_reviews >= 8,
|
| 558 |
-
key="initial_review8"
|
| 559 |
-
# color_map={"Positive": "#d4fcd6", "Negative": "#fcd6d6"}
|
| 560 |
-
)
|
| 561 |
|
| 562 |
# Callback functions that update state.
|
| 563 |
def year_change(year, state, score_type):
|
| 564 |
state["year_choice"] = year
|
| 565 |
state["scored_reviews_for_year"] = get_preprocessed_scores(year)
|
|
|
|
| 566 |
state["review_ids"] = list(state["scored_reviews_for_year"].keys())
|
| 567 |
state["current_review_index"] = 0
|
| 568 |
state["current_review"] = state["scored_reviews_for_year"][state["review_ids"][0]]
|
|
@@ -579,26 +580,11 @@ with gr.Blocks(title="ReView") as demo:
|
|
| 579 |
return update_review_display(state, score_type)
|
| 580 |
|
| 581 |
# Hook up the callbacks with the session state.
|
| 582 |
-
|
| 583 |
-
|
| 584 |
-
|
| 585 |
-
|
| 586 |
-
)
|
| 587 |
-
score_type.change(
|
| 588 |
-
fn=update_review_display,
|
| 589 |
-
inputs=[state, score_type],
|
| 590 |
-
outputs=[review_id, review1, review2, review3, review4, review5, review6, review7, review8, most_common_sentences, most_unique_sentences, topic_text_box, state]
|
| 591 |
-
)
|
| 592 |
-
next_button.click(
|
| 593 |
-
fn=next_review,
|
| 594 |
-
inputs=[state, score_type],
|
| 595 |
-
outputs=[review_id, review1, review2, review3, review4, review5, review6, review7, review8, most_common_sentences, most_unique_sentences, topic_text_box, state]
|
| 596 |
-
)
|
| 597 |
-
previous_button.click(
|
| 598 |
-
fn=previous_review,
|
| 599 |
-
inputs=[state, score_type],
|
| 600 |
-
outputs=[review_id, review1, review2, review3, review4, review5, review6, review7, review8, most_common_sentences, most_unique_sentences, topic_text_box, state]
|
| 601 |
-
)
|
| 602 |
|
| 603 |
|
| 604 |
|
|
@@ -619,10 +605,15 @@ with gr.Blocks(title="ReView") as demo:
|
|
| 619 |
|
| 620 |
with gr.Tabs():
|
| 621 |
with gr.Tab("Paste Reviews"):
|
| 622 |
-
review1_textbox = gr.Textbox(lines=5, value=EXAMPLES[0], label="Review 1", interactive=True)
|
| 623 |
-
review2_textbox = gr.Textbox(lines=5, value=EXAMPLES[1], label="Review 2", interactive=True)
|
| 624 |
-
review3_textbox = gr.Textbox(lines=5, value=EXAMPLES[2], label="Review 3", interactive=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 625 |
with gr.Row():
|
|
|
|
| 626 |
submit_button = gr.Button("Process", variant="primary", interactive=True)
|
| 627 |
clear_button = gr.Button("Clear", variant="secondary", interactive=True)
|
| 628 |
|
|
@@ -660,44 +651,38 @@ with gr.Blocks(title="ReView") as demo:
|
|
| 660 |
lines=4, label="Most Common Opinions", visible=True, value="", container=True
|
| 661 |
)
|
| 662 |
|
| 663 |
-
agreement_text1 = gr.HighlightedText(
|
| 664 |
-
|
| 665 |
-
)
|
| 666 |
-
|
| 667 |
-
|
| 668 |
-
)
|
| 669 |
-
|
| 670 |
-
|
| 671 |
-
)
|
| 672 |
-
|
| 673 |
-
|
| 674 |
-
|
| 675 |
-
|
| 676 |
-
|
| 677 |
-
|
| 678 |
-
|
| 679 |
-
|
| 680 |
-
)
|
| 681 |
-
|
| 682 |
-
|
| 683 |
-
color_map={"➕": "#d4fcd6", "➖": "#fcd6d6"}
|
| 684 |
-
)
|
| 685 |
-
|
| 686 |
-
topic_text1 = gr.HighlightedText(
|
| 687 |
-
show_legend=False, label="Topic in Review 1", visible=False, value=None,
|
| 688 |
-
color_map=topic_color_map
|
| 689 |
-
)
|
| 690 |
-
topic_text2 = gr.HighlightedText(
|
| 691 |
-
show_legend=False, label="Topic in Review 2", visible=False, value=None,
|
| 692 |
-
color_map=topic_color_map
|
| 693 |
-
)
|
| 694 |
-
topic_text3 = gr.HighlightedText(
|
| 695 |
-
show_legend=False, label="Topic in Review 3", visible=False, value=None,
|
| 696 |
-
color_map=topic_color_map
|
| 697 |
-
)
|
| 698 |
|
| 699 |
# ---- CALLBACKS ----
|
| 700 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 701 |
# Fetch OpenReview reviews → show timer → process → swap to results
|
| 702 |
fetch_reviews_button.click(
|
| 703 |
fn=lambda: (
|
|
@@ -709,31 +694,30 @@ with gr.Blocks(title="ReView") as demo:
|
|
| 709 |
).then(
|
| 710 |
fn=fetch_openreview_reviews,
|
| 711 |
inputs=[openreview_link_input],
|
| 712 |
-
outputs=[review1_textbox, review2_textbox, review3_textbox,
|
|
|
|
| 713 |
).then(
|
| 714 |
-
fn=lambda title: (
|
| 715 |
gr.update(visible=bool(title.strip())),
|
| 716 |
gr.update(value=PROCESSING_TIMER_HTML, visible=True),
|
|
|
|
|
|
|
|
|
|
| 717 |
),
|
| 718 |
-
inputs=[openreview_title],
|
| 719 |
-
outputs=[openreview_title, status_html]
|
| 720 |
).then(
|
| 721 |
fn=process_interactive_reviews,
|
| 722 |
-
inputs=
|
| 723 |
-
outputs=
|
| 724 |
-
agreement_text1, agreement_text2, agreement_text3,
|
| 725 |
-
most_common, most_divergent,
|
| 726 |
-
polarity_text1, polarity_text2, polarity_text3,
|
| 727 |
-
topic_text1, topic_text2, topic_text3
|
| 728 |
-
]
|
| 729 |
).then(
|
| 730 |
fn=lambda: (
|
| 731 |
-
gr.update(visible=False),
|
| 732 |
-
gr.update(visible=True),
|
| 733 |
-
gr.update(value="", visible=False),
|
| 734 |
-
gr.update(interactive=True),
|
| 735 |
-
gr.update(visible=True),
|
| 736 |
-
gr.update(visible=False),
|
| 737 |
),
|
| 738 |
inputs=[],
|
| 739 |
outputs=[input_section, results_section, status_html, fetch_reviews_button, back_to_input_btn, view_results_btn]
|
|
@@ -749,21 +733,16 @@ with gr.Blocks(title="ReView") as demo:
|
|
| 749 |
outputs=[status_html, submit_button]
|
| 750 |
).then(
|
| 751 |
fn=process_interactive_reviews,
|
| 752 |
-
inputs=
|
| 753 |
-
outputs=
|
| 754 |
-
agreement_text1, agreement_text2, agreement_text3,
|
| 755 |
-
most_common, most_divergent,
|
| 756 |
-
polarity_text1, polarity_text2, polarity_text3,
|
| 757 |
-
topic_text1, topic_text2, topic_text3
|
| 758 |
-
]
|
| 759 |
).then(
|
| 760 |
fn=lambda: (
|
| 761 |
-
gr.update(visible=False),
|
| 762 |
-
gr.update(visible=True),
|
| 763 |
-
gr.update(value="", visible=False),
|
| 764 |
-
gr.update(interactive=True),
|
| 765 |
-
gr.update(visible=True),
|
| 766 |
-
gr.update(visible=False),
|
| 767 |
),
|
| 768 |
inputs=[],
|
| 769 |
outputs=[input_section, results_section, status_html, submit_button, back_to_input_btn, view_results_btn]
|
|
@@ -795,34 +774,55 @@ with gr.Blocks(title="ReView") as demo:
|
|
| 795 |
|
| 796 |
# Clear button
|
| 797 |
clear_button.click(
|
| 798 |
-
fn=lambda: (
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 799 |
inputs=[],
|
| 800 |
outputs=[
|
| 801 |
-
review1_textbox, review2_textbox, review3_textbox,
|
|
|
|
| 802 |
most_common, most_divergent,
|
| 803 |
-
agreement_text1, agreement_text2, agreement_text3
|
|
|
|
|
|
|
| 804 |
]
|
|
|
|
|
|
|
|
|
|
|
|
|
| 805 |
)
|
| 806 |
|
| 807 |
# Toggle display mode (Agreement / Polarity / Topic)
|
| 808 |
-
def toggle_display_mode(focus):
|
| 809 |
-
|
| 810 |
-
|
| 811 |
-
|
| 812 |
-
|
| 813 |
-
gr.update(visible=agreement_visible), gr.update(visible=agreement_visible), gr.update(visible=agreement_visible),
|
| 814 |
-
gr.update(visible=polarity_visible), gr.update(visible=polarity_visible), gr.update(visible=polarity_visible),
|
| 815 |
-
gr.update(visible=topic_visible), gr.update(visible=topic_visible), gr.update(visible=topic_visible),
|
| 816 |
)
|
| 817 |
|
| 818 |
focus_radio.change(
|
| 819 |
fn=toggle_display_mode,
|
| 820 |
-
inputs=[focus_radio],
|
| 821 |
outputs=[
|
| 822 |
-
agreement_text1, agreement_text2, agreement_text3,
|
| 823 |
-
polarity_text1, polarity_text2, polarity_text3,
|
| 824 |
-
topic_text1, topic_text2, topic_text3,
|
| 825 |
]
|
| 826 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 827 |
|
| 828 |
demo.launch(share=False)
|
|
|
|
| 65 |
return scored_reviews
|
| 66 |
|
| 67 |
|
| 68 |
+
def get_preprocessed_metadata(year):
|
| 69 |
+
row = all_scored_reviews_df[all_scored_reviews_df["year"] == year]
|
| 70 |
+
if "metadata" in row.columns and not row.empty:
|
| 71 |
+
meta = row["metadata"].iloc[0]
|
| 72 |
+
return meta if isinstance(meta, dict) else {}
|
| 73 |
+
return {}
|
| 74 |
+
|
| 75 |
+
|
| 76 |
# -----------------------------------
|
| 77 |
# Interactive Tab Configuration
|
| 78 |
# -----------------------------------
|
|
|
|
| 121 |
- **Topic**: Highlights comments by discussion topic using color-coded labels.
|
| 122 |
#### Interactive Tab
|
| 123 |
Use this tab to analyze your own review text:
|
| 124 |
+
1. **Enter 2–6 reviews** in the input fields. Use the **➕ Add Review** button to add up to 6 reviews.
|
| 125 |
2. **Click "Process"** to analyze the input (average processing time: ~42 seconds).
|
| 126 |
3. **Explore the results** using the same highlighting options as above (Agreement, Polarity, Topic).
|
| 127 |
"""
|
|
|
|
| 180 |
return _interactive_processor
|
| 181 |
|
| 182 |
|
| 183 |
+
MAX_INTERACTIVE_REVIEWS = 6
|
| 184 |
+
|
| 185 |
+
|
| 186 |
+
def fetch_openreview_reviews(link: str):
|
| 187 |
"""
|
| 188 |
Fetch reviews from OpenReview link and populate the textboxes.
|
| 189 |
|
| 190 |
Returns:
|
| 191 |
+
Tuple of (review1..6, title, status_html)
|
| 192 |
"""
|
| 193 |
print(f"\n[DEMO] fetch_openreview_reviews called with link: {link}")
|
| 194 |
|
| 195 |
+
empty = [""] * MAX_INTERACTIVE_REVIEWS
|
| 196 |
+
|
| 197 |
if not link.strip():
|
| 198 |
+
return (*empty, "", _status_html("Please paste a valid OpenReview link", "error"))
|
| 199 |
|
| 200 |
try:
|
| 201 |
from interface.interactive_processor import fetch_reviews_from_openreview_link
|
| 202 |
reviews, title = fetch_reviews_from_openreview_link(link)
|
| 203 |
print(f"[DEMO] Got {len(reviews)} reviews from fetch function")
|
| 204 |
|
| 205 |
+
while len(reviews) < MAX_INTERACTIVE_REVIEWS:
|
| 206 |
reviews.append("")
|
| 207 |
+
reviews = reviews[:MAX_INTERACTIVE_REVIEWS]
|
| 208 |
|
| 209 |
num_reviews = len([r for r in reviews if r.strip()])
|
| 210 |
status = _status_html(f"Fetched {num_reviews} reviews for: {title}", "success")
|
| 211 |
+
return (*reviews, title, status)
|
| 212 |
|
| 213 |
except ValueError as e:
|
| 214 |
error_msg = str(e)
|
| 215 |
print(f"[DEMO] ValueError caught: {error_msg}")
|
| 216 |
+
return (*empty, "", _status_html(error_msg, "warning"))
|
| 217 |
except Exception as e:
|
| 218 |
error_msg = str(e)
|
| 219 |
print(f"[DEMO] Exception caught: {type(e).__name__}: {error_msg}")
|
|
|
|
| 225 |
else:
|
| 226 |
suggestion = ""
|
| 227 |
|
| 228 |
+
return (*empty, "", _status_html(f"{error_msg}{suggestion}", "error"))
|
| 229 |
|
| 230 |
|
| 231 |
+
def process_interactive_reviews(text1: str, text2: str, text3: str, text4: str, text5: str, text6: str, focus: str, progress=gr.Progress()) -> Tuple:
|
| 232 |
"""
|
| 233 |
+
Process up to 6 reviews through the interactive pipeline with progress tracking.
|
| 234 |
"""
|
| 235 |
from dependencies.Glimpse_tokenizer import glimpse_tokenizer
|
| 236 |
|
| 237 |
+
all_texts = [text1, text2, text3, text4, text5, text6]
|
| 238 |
+
active_texts = [t for t in all_texts if t and t.strip()]
|
| 239 |
+
|
| 240 |
+
if len(active_texts) < 2:
|
| 241 |
+
raise ValueError("Please enter at least two reviews")
|
| 242 |
|
| 243 |
# Step 1: Load models
|
| 244 |
progress(0.0, desc="Loading models...")
|
|
|
|
| 246 |
|
| 247 |
# Step 2: Tokenize
|
| 248 |
progress(0.10, desc="Tokenizing reviews...")
|
| 249 |
+
sentence_lists = [[s for s in glimpse_tokenizer(t) if s.strip()] for t in active_texts]
|
| 250 |
+
sentence_lists = [sl for sl in sentence_lists if sl]
|
|
|
|
| 251 |
|
| 252 |
+
if len(sentence_lists) < 2:
|
| 253 |
+
raise ValueError("At least two reviews must have valid sentences")
|
| 254 |
|
| 255 |
+
all_sentences = list(set(s for sl in sentence_lists for s in sl))
|
| 256 |
|
| 257 |
# Step 3: Polarity
|
| 258 |
progress(0.20, desc="Predicting polarity...")
|
|
|
|
| 264 |
|
| 265 |
# Step 5: Consensuality (RSA) - the slow one
|
| 266 |
progress(0.55, desc="Computing agreement (RSA reranking)...")
|
| 267 |
+
consensuality_map = processor.predict_consensuality(*active_texts)
|
| 268 |
|
| 269 |
# Step 6: Format results
|
| 270 |
progress(0.90, desc="Formatting results...")
|
| 271 |
|
|
|
|
| 272 |
if consensuality_map:
|
| 273 |
import pandas as _pd
|
| 274 |
scores_series = _pd.Series(consensuality_map)
|
|
|
|
| 278 |
most_common_text = ""
|
| 279 |
most_unique_text = ""
|
| 280 |
|
|
|
|
| 281 |
fmt = processor.format_highlighted_output
|
| 282 |
+
# Build per-review outputs (pad inactive reviews with empty/hidden)
|
| 283 |
+
agree_out, polar_out, topic_out = [], [], []
|
| 284 |
+
for i in range(MAX_INTERACTIVE_REVIEWS):
|
| 285 |
+
if i < len(sentence_lists):
|
| 286 |
+
agree_out.append(gr.update(visible=True, value=fmt(sentence_lists[i], consensuality_map, "consensuality")))
|
| 287 |
+
polar_out.append(gr.update(visible=True, value=fmt(sentence_lists[i], polarity_map, "polarity")))
|
| 288 |
+
topic_out.append(gr.update(visible=True, value=fmt(sentence_lists[i], topic_map, "topic")))
|
| 289 |
+
else:
|
| 290 |
+
agree_out.append(gr.update(visible=False, value=None))
|
| 291 |
+
polar_out.append(gr.update(visible=False, value=None))
|
| 292 |
+
topic_out.append(gr.update(visible=False, value=None))
|
| 293 |
|
| 294 |
progress(1.0, desc="Done!")
|
| 295 |
|
| 296 |
return (
|
| 297 |
+
*agree_out,
|
| 298 |
most_common_text, most_unique_text,
|
| 299 |
+
*polar_out,
|
| 300 |
+
*topic_out,
|
| 301 |
+
len(sentence_lists), # active review count → interactive_review_count
|
| 302 |
)
|
| 303 |
|
| 304 |
|
| 305 |
|
| 306 |
|
| 307 |
+
CUSTOM_CSS = """
|
| 308 |
+
.review-section-header h3 {
|
| 309 |
+
color: #1e40af;
|
| 310 |
+
border-left: 4px solid #3b82f6;
|
| 311 |
+
padding-left: 10px;
|
| 312 |
+
margin-top: 16px;
|
| 313 |
+
}
|
| 314 |
+
.rebuttal-section-header h3 {
|
| 315 |
+
color: #92400e;
|
| 316 |
+
border-left: 4px solid #f59e0b;
|
| 317 |
+
padding-left: 10px;
|
| 318 |
+
margin-top: 16px;
|
| 319 |
+
}
|
| 320 |
+
"""
|
| 321 |
+
|
| 322 |
+
with gr.Blocks(title="ReView", css=CUSTOM_CSS) as demo:
|
| 323 |
# gr.Markdown("# ReView Interface")
|
| 324 |
|
| 325 |
with gr.Tab("Introduction"):
|
|
|
|
| 337 |
initial_review_ids = list(initial_scored_reviews.keys())
|
| 338 |
initial_review = initial_scored_reviews[initial_review_ids[0]]
|
| 339 |
number_of_displayed_reviews = len(initial_scored_reviews[initial_review_ids[0]])
|
| 340 |
+
initial_metadata = get_preprocessed_metadata(initial_year)
|
| 341 |
initial_state = {
|
| 342 |
"year_choice": initial_year,
|
| 343 |
"scored_reviews_for_year": initial_scored_reviews,
|
|
|
|
| 345 |
"current_review_index": 0,
|
| 346 |
"current_review": initial_review,
|
| 347 |
"number_of_displayed_reviews": number_of_displayed_reviews,
|
| 348 |
+
"metadata_for_year": initial_metadata,
|
| 349 |
}
|
| 350 |
state = gr.State(initial_state)
|
| 351 |
|
|
|
|
| 382 |
review_updates = []
|
| 383 |
consensuality_dict = {}
|
| 384 |
|
| 385 |
+
for i in range(10):
|
| 386 |
if i < number_of_displayed_reviews:
|
| 387 |
review_item = list(current_review[i].items())
|
| 388 |
|
|
|
|
| 442 |
)
|
| 443 |
)
|
| 444 |
|
| 445 |
+
# Rebuttal display
|
| 446 |
+
current_forum_id = review_ids[current_index]
|
| 447 |
+
paper_metadata = state.get("metadata_for_year", {}).get(current_forum_id, {})
|
| 448 |
+
rebuttal_text = paper_metadata.get("rebuttal", "") or ""
|
| 449 |
+
has_rebuttal = bool(rebuttal_text.strip())
|
| 450 |
+
rebuttal_header_update = gr.update(visible=has_rebuttal)
|
| 451 |
+
rebuttal_display_update = gr.update(visible=has_rebuttal, value=rebuttal_text if has_rebuttal else "")
|
| 452 |
+
|
| 453 |
# Set most consensual / unique sentences
|
| 454 |
if show_consensuality and consensuality_dict:
|
| 455 |
scores = pd.Series(consensuality_dict)
|
|
|
|
| 491 |
most_common_visibility,
|
| 492 |
most_unique_visibility,
|
| 493 |
topic_color_map_visibility,
|
| 494 |
+
rebuttal_header_update,
|
| 495 |
+
rebuttal_display_update,
|
| 496 |
state
|
| 497 |
)
|
| 498 |
|
|
|
|
| 500 |
|
| 501 |
# Precompute the initial outputs so something is shown on load.
|
| 502 |
init_display = update_review_display(initial_state, score_type="Original")
|
| 503 |
+
# init_display returns: (review_id, review1..10, most_common, most_unique, topic_box, rebuttal_header, rebuttal_display, state)
|
| 504 |
|
| 505 |
with gr.Row():
|
| 506 |
|
|
|
|
| 544 |
show_legend=True,
|
| 545 |
)
|
| 546 |
|
| 547 |
+
gr.Markdown("### 📝 Reviews", elem_classes=["review-section-header"])
|
| 548 |
+
review1 = gr.HighlightedText(show_legend=False, label="📝 Review 1", visible=number_of_displayed_reviews >= 1, key="initial_review1")
|
| 549 |
+
review2 = gr.HighlightedText(show_legend=False, label="📝 Review 2", visible=number_of_displayed_reviews >= 2, key="initial_review2")
|
| 550 |
+
review3 = gr.HighlightedText(show_legend=False, label="📝 Review 3", visible=number_of_displayed_reviews >= 3, key="initial_review3")
|
| 551 |
+
review4 = gr.HighlightedText(show_legend=False, label="📝 Review 4", visible=number_of_displayed_reviews >= 4, key="initial_review4")
|
| 552 |
+
review5 = gr.HighlightedText(show_legend=False, label="📝 Review 5", visible=number_of_displayed_reviews >= 5, key="initial_review5")
|
| 553 |
+
review6 = gr.HighlightedText(show_legend=False, label="📝 Review 6", visible=number_of_displayed_reviews >= 6, key="initial_review6")
|
| 554 |
+
review7 = gr.HighlightedText(show_legend=False, label="📝 Review 7", visible=number_of_displayed_reviews >= 7, key="initial_review7")
|
| 555 |
+
review8 = gr.HighlightedText(show_legend=False, label="📝 Review 8", visible=number_of_displayed_reviews >= 8, key="initial_review8")
|
| 556 |
+
review9 = gr.HighlightedText(show_legend=False, label="📝 Review 9", visible=number_of_displayed_reviews >= 9, key="initial_review9")
|
| 557 |
+
review10 = gr.HighlightedText(show_legend=False, label="📝 Review 10", visible=number_of_displayed_reviews >= 10, key="initial_review10")
|
| 558 |
+
|
| 559 |
+
rebuttal_header = gr.Markdown("### 💬 Author Rebuttal", elem_classes=["rebuttal-section-header"], visible=False)
|
| 560 |
+
rebuttal_display = gr.Textbox(label="Author Rebuttal", interactive=False, lines=8, visible=False)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 561 |
|
| 562 |
# Callback functions that update state.
|
| 563 |
def year_change(year, state, score_type):
|
| 564 |
state["year_choice"] = year
|
| 565 |
state["scored_reviews_for_year"] = get_preprocessed_scores(year)
|
| 566 |
+
state["metadata_for_year"] = get_preprocessed_metadata(year)
|
| 567 |
state["review_ids"] = list(state["scored_reviews_for_year"].keys())
|
| 568 |
state["current_review_index"] = 0
|
| 569 |
state["current_review"] = state["scored_reviews_for_year"][state["review_ids"][0]]
|
|
|
|
| 580 |
return update_review_display(state, score_type)
|
| 581 |
|
| 582 |
# Hook up the callbacks with the session state.
|
| 583 |
+
_review_outputs = [review_id, review1, review2, review3, review4, review5, review6, review7, review8, review9, review10, most_common_sentences, most_unique_sentences, topic_text_box, rebuttal_header, rebuttal_display, state]
|
| 584 |
+
year.change(fn=year_change, inputs=[year, state, score_type], outputs=_review_outputs)
|
| 585 |
+
score_type.change(fn=update_review_display, inputs=[state, score_type], outputs=_review_outputs)
|
| 586 |
+
next_button.click(fn=next_review, inputs=[state, score_type], outputs=_review_outputs)
|
| 587 |
+
previous_button.click(fn=previous_review, inputs=[state, score_type], outputs=_review_outputs)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 588 |
|
| 589 |
|
| 590 |
|
|
|
|
| 605 |
|
| 606 |
with gr.Tabs():
|
| 607 |
with gr.Tab("Paste Reviews"):
|
| 608 |
+
review1_textbox = gr.Textbox(lines=5, value=EXAMPLES[0], label="📝 Review 1", interactive=True)
|
| 609 |
+
review2_textbox = gr.Textbox(lines=5, value=EXAMPLES[1], label="📝 Review 2", interactive=True)
|
| 610 |
+
review3_textbox = gr.Textbox(lines=5, value=EXAMPLES[2], label="📝 Review 3", interactive=True)
|
| 611 |
+
review4_textbox = gr.Textbox(lines=5, value="", label="📝 Review 4", interactive=True, visible=False)
|
| 612 |
+
review5_textbox = gr.Textbox(lines=5, value="", label="📝 Review 5", interactive=True, visible=False)
|
| 613 |
+
review6_textbox = gr.Textbox(lines=5, value="", label="📝 Review 6", interactive=True, visible=False)
|
| 614 |
+
interactive_review_count = gr.State(3)
|
| 615 |
with gr.Row():
|
| 616 |
+
add_review_btn = gr.Button("➕ Add Review", variant="secondary", interactive=True)
|
| 617 |
submit_button = gr.Button("Process", variant="primary", interactive=True)
|
| 618 |
clear_button = gr.Button("Clear", variant="secondary", interactive=True)
|
| 619 |
|
|
|
|
| 651 |
lines=4, label="Most Common Opinions", visible=True, value="", container=True
|
| 652 |
)
|
| 653 |
|
| 654 |
+
agreement_text1 = gr.HighlightedText(show_legend=True, label="Agreement in 📝 Review 1", visible=True, value=None)
|
| 655 |
+
agreement_text2 = gr.HighlightedText(show_legend=True, label="Agreement in 📝 Review 2", visible=True, value=None)
|
| 656 |
+
agreement_text3 = gr.HighlightedText(show_legend=True, label="Agreement in 📝 Review 3", visible=True, value=None)
|
| 657 |
+
agreement_text4 = gr.HighlightedText(show_legend=True, label="Agreement in 📝 Review 4", visible=False, value=None)
|
| 658 |
+
agreement_text5 = gr.HighlightedText(show_legend=True, label="Agreement in 📝 Review 5", visible=False, value=None)
|
| 659 |
+
agreement_text6 = gr.HighlightedText(show_legend=True, label="Agreement in 📝 Review 6", visible=False, value=None)
|
| 660 |
+
|
| 661 |
+
polarity_text1 = gr.HighlightedText(show_legend=True, label="Polarity in 📝 Review 1", visible=False, value=None, color_map={"➕": "#d4fcd6", "➖": "#fcd6d6"})
|
| 662 |
+
polarity_text2 = gr.HighlightedText(show_legend=True, label="Polarity in 📝 Review 2", visible=False, value=None, color_map={"➕": "#d4fcd6", "➖": "#fcd6d6"})
|
| 663 |
+
polarity_text3 = gr.HighlightedText(show_legend=True, label="Polarity in 📝 Review 3", visible=False, value=None, color_map={"➕": "#d4fcd6", "➖": "#fcd6d6"})
|
| 664 |
+
polarity_text4 = gr.HighlightedText(show_legend=True, label="Polarity in 📝 Review 4", visible=False, value=None, color_map={"➕": "#d4fcd6", "➖": "#fcd6d6"})
|
| 665 |
+
polarity_text5 = gr.HighlightedText(show_legend=True, label="Polarity in 📝 Review 5", visible=False, value=None, color_map={"➕": "#d4fcd6", "➖": "#fcd6d6"})
|
| 666 |
+
polarity_text6 = gr.HighlightedText(show_legend=True, label="Polarity in 📝 Review 6", visible=False, value=None, color_map={"➕": "#d4fcd6", "➖": "#fcd6d6"})
|
| 667 |
+
|
| 668 |
+
topic_text1 = gr.HighlightedText(show_legend=False, label="Topic in 📝 Review 1", visible=False, value=None, color_map=topic_color_map)
|
| 669 |
+
topic_text2 = gr.HighlightedText(show_legend=False, label="Topic in 📝 Review 2", visible=False, value=None, color_map=topic_color_map)
|
| 670 |
+
topic_text3 = gr.HighlightedText(show_legend=False, label="Topic in 📝 Review 3", visible=False, value=None, color_map=topic_color_map)
|
| 671 |
+
topic_text4 = gr.HighlightedText(show_legend=False, label="Topic in 📝 Review 4", visible=False, value=None, color_map=topic_color_map)
|
| 672 |
+
topic_text5 = gr.HighlightedText(show_legend=False, label="Topic in 📝 Review 5", visible=False, value=None, color_map=topic_color_map)
|
| 673 |
+
topic_text6 = gr.HighlightedText(show_legend=False, label="Topic in 📝 Review 6", visible=False, value=None, color_map=topic_color_map)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 674 |
|
| 675 |
# ---- CALLBACKS ----
|
| 676 |
|
| 677 |
+
_interactive_inputs = [review1_textbox, review2_textbox, review3_textbox, review4_textbox, review5_textbox, review6_textbox, focus_radio]
|
| 678 |
+
_interactive_outputs = [
|
| 679 |
+
agreement_text1, agreement_text2, agreement_text3, agreement_text4, agreement_text5, agreement_text6,
|
| 680 |
+
most_common, most_divergent,
|
| 681 |
+
polarity_text1, polarity_text2, polarity_text3, polarity_text4, polarity_text5, polarity_text6,
|
| 682 |
+
topic_text1, topic_text2, topic_text3, topic_text4, topic_text5, topic_text6,
|
| 683 |
+
interactive_review_count,
|
| 684 |
+
]
|
| 685 |
+
|
| 686 |
# Fetch OpenReview reviews → show timer → process → swap to results
|
| 687 |
fetch_reviews_button.click(
|
| 688 |
fn=lambda: (
|
|
|
|
| 694 |
).then(
|
| 695 |
fn=fetch_openreview_reviews,
|
| 696 |
inputs=[openreview_link_input],
|
| 697 |
+
outputs=[review1_textbox, review2_textbox, review3_textbox, review4_textbox, review5_textbox, review6_textbox,
|
| 698 |
+
openreview_title, status_html]
|
| 699 |
).then(
|
| 700 |
+
fn=lambda r4, r5, r6, title: (
|
| 701 |
gr.update(visible=bool(title.strip())),
|
| 702 |
gr.update(value=PROCESSING_TIMER_HTML, visible=True),
|
| 703 |
+
gr.update(visible=bool(r4.strip())),
|
| 704 |
+
gr.update(visible=bool(r5.strip())),
|
| 705 |
+
gr.update(visible=bool(r6.strip())),
|
| 706 |
),
|
| 707 |
+
inputs=[review4_textbox, review5_textbox, review6_textbox, openreview_title],
|
| 708 |
+
outputs=[openreview_title, status_html, review4_textbox, review5_textbox, review6_textbox]
|
| 709 |
).then(
|
| 710 |
fn=process_interactive_reviews,
|
| 711 |
+
inputs=_interactive_inputs,
|
| 712 |
+
outputs=_interactive_outputs
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 713 |
).then(
|
| 714 |
fn=lambda: (
|
| 715 |
+
gr.update(visible=False),
|
| 716 |
+
gr.update(visible=True),
|
| 717 |
+
gr.update(value="", visible=False),
|
| 718 |
+
gr.update(interactive=True),
|
| 719 |
+
gr.update(visible=True),
|
| 720 |
+
gr.update(visible=False),
|
| 721 |
),
|
| 722 |
inputs=[],
|
| 723 |
outputs=[input_section, results_section, status_html, fetch_reviews_button, back_to_input_btn, view_results_btn]
|
|
|
|
| 733 |
outputs=[status_html, submit_button]
|
| 734 |
).then(
|
| 735 |
fn=process_interactive_reviews,
|
| 736 |
+
inputs=_interactive_inputs,
|
| 737 |
+
outputs=_interactive_outputs
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 738 |
).then(
|
| 739 |
fn=lambda: (
|
| 740 |
+
gr.update(visible=False),
|
| 741 |
+
gr.update(visible=True),
|
| 742 |
+
gr.update(value="", visible=False),
|
| 743 |
+
gr.update(interactive=True),
|
| 744 |
+
gr.update(visible=True),
|
| 745 |
+
gr.update(visible=False),
|
| 746 |
),
|
| 747 |
inputs=[],
|
| 748 |
outputs=[input_section, results_section, status_html, submit_button, back_to_input_btn, view_results_btn]
|
|
|
|
| 774 |
|
| 775 |
# Clear button
|
| 776 |
clear_button.click(
|
| 777 |
+
fn=lambda: (
|
| 778 |
+
"", "", "", "", "", "", # clear all textboxes
|
| 779 |
+
3, # reset count
|
| 780 |
+
"", "", # clear most common/divergent
|
| 781 |
+
*([None] * 6), *([None] * 6), *([None] * 6), # clear all output panels
|
| 782 |
+
),
|
| 783 |
inputs=[],
|
| 784 |
outputs=[
|
| 785 |
+
review1_textbox, review2_textbox, review3_textbox, review4_textbox, review5_textbox, review6_textbox,
|
| 786 |
+
interactive_review_count,
|
| 787 |
most_common, most_divergent,
|
| 788 |
+
agreement_text1, agreement_text2, agreement_text3, agreement_text4, agreement_text5, agreement_text6,
|
| 789 |
+
polarity_text1, polarity_text2, polarity_text3, polarity_text4, polarity_text5, polarity_text6,
|
| 790 |
+
topic_text1, topic_text2, topic_text3, topic_text4, topic_text5, topic_text6,
|
| 791 |
]
|
| 792 |
+
).then(
|
| 793 |
+
fn=lambda: (gr.update(visible=False), gr.update(visible=False), gr.update(visible=False)),
|
| 794 |
+
inputs=[],
|
| 795 |
+
outputs=[review4_textbox, review5_textbox, review6_textbox]
|
| 796 |
)
|
| 797 |
|
| 798 |
# Toggle display mode (Agreement / Polarity / Topic)
|
| 799 |
+
def toggle_display_mode(focus, active_count):
|
| 800 |
+
return tuple(
|
| 801 |
+
gr.update(visible=(mode == focus and i < active_count))
|
| 802 |
+
for mode in ["Agreement", "Polarity", "Topic"]
|
| 803 |
+
for i in range(MAX_INTERACTIVE_REVIEWS)
|
|
|
|
|
|
|
|
|
|
| 804 |
)
|
| 805 |
|
| 806 |
focus_radio.change(
|
| 807 |
fn=toggle_display_mode,
|
| 808 |
+
inputs=[focus_radio, interactive_review_count],
|
| 809 |
outputs=[
|
| 810 |
+
agreement_text1, agreement_text2, agreement_text3, agreement_text4, agreement_text5, agreement_text6,
|
| 811 |
+
polarity_text1, polarity_text2, polarity_text3, polarity_text4, polarity_text5, polarity_text6,
|
| 812 |
+
topic_text1, topic_text2, topic_text3, topic_text4, topic_text5, topic_text6,
|
| 813 |
]
|
| 814 |
)
|
| 815 |
+
|
| 816 |
+
# Add Review button: show next hidden textbox (reviews 4-6)
|
| 817 |
+
def add_review(count):
|
| 818 |
+
new_count = min(count + 1, MAX_INTERACTIVE_REVIEWS)
|
| 819 |
+
vis = [gr.update(visible=(i + 4 <= new_count)) for i in range(MAX_INTERACTIVE_REVIEWS - 3)]
|
| 820 |
+
return (new_count, *vis)
|
| 821 |
+
|
| 822 |
+
add_review_btn.click(
|
| 823 |
+
fn=add_review,
|
| 824 |
+
inputs=[interactive_review_count],
|
| 825 |
+
outputs=[interactive_review_count, review4_textbox, review5_textbox, review6_textbox]
|
| 826 |
+
)
|
| 827 |
|
| 828 |
demo.launch(share=False)
|
interface/interactive_processor.py
CHANGED
|
@@ -115,23 +115,24 @@ class InteractiveReviewProcessor:
|
|
| 115 |
|
| 116 |
def predict_consensuality(
|
| 117 |
self,
|
| 118 |
-
|
| 119 |
-
text2: str,
|
| 120 |
-
text3: str,
|
| 121 |
rationality: float = 1.0,
|
| 122 |
iterations: int = 1
|
| 123 |
) -> Dict[str, float]:
|
| 124 |
"""
|
| 125 |
Predict consensuality using RSA reranking.
|
|
|
|
| 126 |
Returns: {sentence: consensuality_score}
|
| 127 |
"""
|
| 128 |
-
|
| 129 |
-
|
| 130 |
-
|
| 131 |
-
|
|
|
|
|
|
|
| 132 |
|
| 133 |
# Get unique sentences
|
| 134 |
-
sentences = list(set(
|
| 135 |
|
| 136 |
if not sentences:
|
| 137 |
return {}
|
|
@@ -141,7 +142,7 @@ class InteractiveReviewProcessor:
|
|
| 141 |
self.rsa_model,
|
| 142 |
self.rsa_tokenizer,
|
| 143 |
candidates=sentences,
|
| 144 |
-
source_texts=
|
| 145 |
device=str(self.device),
|
| 146 |
rationality=rationality,
|
| 147 |
)
|
|
@@ -187,46 +188,46 @@ class InteractiveReviewProcessor:
|
|
| 187 |
|
| 188 |
def process_reviews(
|
| 189 |
self,
|
| 190 |
-
|
| 191 |
-
review2: str,
|
| 192 |
-
review3: str,
|
| 193 |
focus: str = "Agreement"
|
| 194 |
) -> Dict:
|
| 195 |
"""
|
| 196 |
-
Process
|
| 197 |
|
| 198 |
Args:
|
| 199 |
-
|
| 200 |
focus: "Agreement", "Polarity", or "Topic"
|
| 201 |
|
| 202 |
Returns:
|
| 203 |
-
Dictionary with formatted output for all
|
| 204 |
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
| 205 |
# Tokenize reviews
|
| 206 |
-
|
| 207 |
-
text2_sentences = [s for s in glimpse_tokenizer(review2) if s.strip()]
|
| 208 |
-
text3_sentences = [s for s in glimpse_tokenizer(review3) if s.strip()]
|
| 209 |
|
| 210 |
-
if
|
| 211 |
-
raise ValueError("One or more reviews
|
| 212 |
|
| 213 |
# Get unique sentences for scoring
|
| 214 |
-
all_sentences = list(set(
|
| 215 |
|
| 216 |
# Predict scores
|
| 217 |
polarity_map = self.predict_polarity(all_sentences)
|
| 218 |
topic_map = self.predict_topic(all_sentences)
|
| 219 |
-
consensuality_map = self.predict_consensuality(
|
| 220 |
|
| 221 |
# Prepare output based on focus
|
| 222 |
result = {
|
| 223 |
-
"
|
| 224 |
-
|
| 225 |
-
|
| 226 |
"consensuality_scores": consensuality_map,
|
| 227 |
"polarity_scores": polarity_map,
|
| 228 |
"topic_scores": topic_map,
|
| 229 |
-
}
|
| 230 |
|
| 231 |
# Calculate most common and unique sentences
|
| 232 |
if consensuality_map:
|
|
|
|
| 115 |
|
| 116 |
def predict_consensuality(
|
| 117 |
self,
|
| 118 |
+
*texts: str,
|
|
|
|
|
|
|
| 119 |
rationality: float = 1.0,
|
| 120 |
iterations: int = 1
|
| 121 |
) -> Dict[str, float]:
|
| 122 |
"""
|
| 123 |
Predict consensuality using RSA reranking.
|
| 124 |
+
Accepts 2+ review texts.
|
| 125 |
Returns: {sentence: consensuality_score}
|
| 126 |
"""
|
| 127 |
+
texts = [t for t in texts if t and t.strip()]
|
| 128 |
+
if len(texts) < 2:
|
| 129 |
+
return {}
|
| 130 |
+
|
| 131 |
+
# Tokenize all reviews
|
| 132 |
+
all_sentence_lists = [[s for s in glimpse_tokenizer(t) if s.strip()] for t in texts]
|
| 133 |
|
| 134 |
# Get unique sentences
|
| 135 |
+
sentences = list(set(s for lst in all_sentence_lists for s in lst))
|
| 136 |
|
| 137 |
if not sentences:
|
| 138 |
return {}
|
|
|
|
| 142 |
self.rsa_model,
|
| 143 |
self.rsa_tokenizer,
|
| 144 |
candidates=sentences,
|
| 145 |
+
source_texts=list(texts),
|
| 146 |
device=str(self.device),
|
| 147 |
rationality=rationality,
|
| 148 |
)
|
|
|
|
| 188 |
|
| 189 |
def process_reviews(
|
| 190 |
self,
|
| 191 |
+
*reviews: str,
|
|
|
|
|
|
|
| 192 |
focus: str = "Agreement"
|
| 193 |
) -> Dict:
|
| 194 |
"""
|
| 195 |
+
Process 2-6 reviews and return scored output.
|
| 196 |
|
| 197 |
Args:
|
| 198 |
+
reviews: Review texts (at least 2 required)
|
| 199 |
focus: "Agreement", "Polarity", or "Topic"
|
| 200 |
|
| 201 |
Returns:
|
| 202 |
+
Dictionary with formatted output for all reviews
|
| 203 |
"""
|
| 204 |
+
reviews = [r for r in reviews if r and r.strip()]
|
| 205 |
+
if len(reviews) < 2:
|
| 206 |
+
raise ValueError("At least two non-empty reviews are required")
|
| 207 |
+
|
| 208 |
# Tokenize reviews
|
| 209 |
+
sentence_lists = [[s for s in glimpse_tokenizer(r) if s.strip()] for r in reviews]
|
|
|
|
|
|
|
| 210 |
|
| 211 |
+
if any(len(sl) == 0 for sl in sentence_lists):
|
| 212 |
+
raise ValueError("One or more reviews have no valid sentences")
|
| 213 |
|
| 214 |
# Get unique sentences for scoring
|
| 215 |
+
all_sentences = list(set(s for sl in sentence_lists for s in sl))
|
| 216 |
|
| 217 |
# Predict scores
|
| 218 |
polarity_map = self.predict_polarity(all_sentences)
|
| 219 |
topic_map = self.predict_topic(all_sentences)
|
| 220 |
+
consensuality_map = self.predict_consensuality(*reviews)
|
| 221 |
|
| 222 |
# Prepare output based on focus
|
| 223 |
result = {
|
| 224 |
+
f"review{i+1}_sentences": sl for i, sl in enumerate(sentence_lists)
|
| 225 |
+
}
|
| 226 |
+
result.update({
|
| 227 |
"consensuality_scores": consensuality_map,
|
| 228 |
"polarity_scores": polarity_map,
|
| 229 |
"topic_scores": topic_map,
|
| 230 |
+
})
|
| 231 |
|
| 232 |
# Calculate most common and unique sentences
|
| 233 |
if consensuality_map:
|