Team Ai
Apppublic

JetBrains-Research/commit-message-editing-visualization

sourceHugging Faceupdated 3y agoView on Hugging Face
0likes
change_visualizer.py354 linesDownload Raw Back to root
1import gradio as gr2import numpy as np3import pandas as pd4import plotly.graph_objects as go5from datasets import load_dataset6from evaluate.utils import parse_readme7from scipy.stats import gaussian_kde, spearmanr8 9import generate_annotated_diffs10from api_wrappers import hf_data_loader11from generation_steps.metrics_analysis import AGGR_METRICS, edit_distance_fn12 13colors = {14    "Expert-labeled": "#C19C0B",15    "Synthetic Backward": "#913632",16    "Synthetic Forward": "#58136a",17    "Full": "#000000",18}19 20METRICS = {21    "Edit Distance": "editdist",22    "Edit Similarity": "editsim",23    "BLEU": "bleu",24    "METEOR": "meteor",25    "ROUGE-1": "rouge1",26    "ROUGE-2": "rouge2",27    "ROUGE-L": "rougeL",28    "BERTScore": "bertscore",29    "ChrF": "chrF",30}31 32 33df_related = generate_annotated_diffs.data_with_annotated_diffs()34 35 36def golden():37    return df_related.loc[(df_related["G_type"] == "initial") & (df_related["E_type"] == "expert_labeled")].reset_index(38        drop=True39    )40 41 42def backward():43    return df_related.loc[44        (df_related["G_type"] == "synthetic_backward") & (df_related["E_type"] == "expert_labeled")45    ].reset_index(drop=True)46 47 48def forward():49    return df_related.loc[50        (df_related["G_type"] == "initial") & (df_related["E_type"] == "synthetic_forward")51    ].reset_index(drop=True)52 53 54def forward_from_backward():55    return df_related.loc[56        (df_related.G_type == "synthetic_backward")57        & (df_related.E_type.isin(["synthetic_forward", "synthetic_forward_from_backward"]))58    ].reset_index(drop=True)59 60 61n_diffs_manual = len(golden())62n_diffs_synthetic_backward = len(backward())63n_diffs_synthetic_forward = len(forward())64n_diffs_synthetic_forward_backward = len(forward_from_backward())65 66 67def update_dataset_view(diff_idx, df):68    diff_idx -= 169    return (70        df.iloc[diff_idx]["annotated_diff"],71        df.iloc[diff_idx]["commit_msg_start"] if "commit_msg_start" in df.columns else df.iloc[diff_idx]["G_text"],72        df.iloc[diff_idx]["commit_msg_end"] if "commit_msg_end" in df.columns else df.iloc[diff_idx]["E_text"],73        f"https://github.com/{df.iloc[diff_idx]['repo']}/commit/{df.iloc[diff_idx]['hash']}",74    )75 76 77def update_dataset_view_manual(diff_idx):78    return update_dataset_view(diff_idx, golden())79 80 81def update_dataset_view_synthetic_backward(diff_idx):82    return update_dataset_view(diff_idx, backward())83 84 85def update_dataset_view_synthetic_forward(diff_idx):86    return update_dataset_view(diff_idx, forward())87 88 89def update_dataset_view_synthetic_forward_backward(diff_idx):90    return update_dataset_view(diff_idx, forward_from_backward())91 92 93def number_of_pairs_plot():94    related_plot_dict = {95        "Full": df_related,96        "Synthetic Backward": backward(),97        "Synthetic Forward": pd.concat([forward(), forward_from_backward()], axis=0, ignore_index=True),98        "Expert-labeled": golden(),99    }100 101    df_unrelated = hf_data_loader.load_synthetic_as_pandas()102    df_unrelated = df_unrelated.loc[~df_unrelated.is_related].copy()103    unrelated_plot_dict = {104        "Full": df_unrelated,105        "Synthetic Backward": df_unrelated.loc[106            (df_unrelated["G_type"] == "synthetic_backward")107            & (~df_unrelated.E_type.isin(["synthetic_forward", "synthetic_forward_from_backward"]))108        ],109        "Synthetic Forward": df_unrelated.loc[110            ((df_unrelated["G_type"] == "initial") & (df_unrelated["E_type"] == "synthetic_forward"))111            | (112                (df_unrelated["G_type"] == "synthetic_backward")113                & (df_unrelated["E_type"].isin(["synthetic_forward", "synthetic_forward_from_backward"]))114            )115        ],116        "Expert-labeled": df_unrelated.loc[117            (df_unrelated.G_type == "initial") & (df_unrelated.E_type == "expert_labeled")118        ],119    }120 121    traces = []122 123    for split in related_plot_dict.keys():124        related_count = len(related_plot_dict[split])125        unrelated_count = len(unrelated_plot_dict[split])126 127        traces.append(128            go.Bar(129                name=f"{split} - Related pairs",130                x=[split],131                y=[related_count],132                marker=dict(133                    color=colors[split],134                ),135            )136        )137 138        traces.append(139            go.Bar(140                name=f"{split} - Conditionally independent pairs",141                x=[split],142                y=[unrelated_count],143                marker=dict(144                    color=colors[split],145                    pattern=dict(146                        shape="/",  # Crosses147                        fillmode="overlay",148                        solidity=0.5,149                    ),150                ),151            )152        )153 154    fig = go.Figure(data=traces)155 156    fig.update_layout(157        barmode="stack",158        bargap=0.2,159        xaxis=dict(title="Split", showgrid=True, gridcolor="lightgrey"),160        yaxis=dict(title="Number of Examples", showgrid=True, gridcolor="lightgrey"),161        legend=dict(title="Pair Type", orientation="h", yanchor="bottom", y=1.02, xanchor="right", x=1),162        plot_bgcolor="rgba(0,0,0,0)",163        paper_bgcolor="rgba(0,0,0,0)",164        width=1100,165    )166    return fig167 168 169def edit_distance_plot():170    df_edit_distance = {171        "Full": [edit_distance_fn(pred=row["G_text"], ref=row["E_text"]) for _, row in df_related.iterrows()],172        "Synthetic Backward": [173            edit_distance_fn(pred=row["G_text"], ref=row["E_text"]) for _, row in backward().iterrows()174        ],175        "Synthetic Forward": [176            edit_distance_fn(pred=row["G_text"], ref=row["E_text"])177            for _, row in pd.concat([forward(), forward_from_backward()], axis=0, ignore_index=True).iterrows()178        ],179        "Expert-labeled": [edit_distance_fn(pred=row["G_text"], ref=row["E_text"]) for _, row in golden().iterrows()],180    }181    traces = []182 183    for key in df_edit_distance:184        kde_x = np.linspace(0, 1200, 1000)185        kde = gaussian_kde(df_edit_distance[key])186        kde_line = go.Scatter(x=kde_x, y=kde(kde_x), mode="lines", name=key, line=dict(color=colors[key], width=5))187        traces.append(kde_line)188 189    fig = go.Figure(data=traces)190 191    fig.update_layout(192        bargap=0.1,193        xaxis=dict(title=dict(text="Edit Distance"), range=[0, 1200], showgrid=True, gridcolor="lightgrey"),194        yaxis=dict(195            title=dict(text="Probability Density"),196            range=[0, 0.004],197            showgrid=True,198            gridcolor="lightgrey",199            tickvals=[0.0005, 0.001, 0.0015, 0.002, 0.0025, 0.003, 0.0035, 0.004],200            tickformat=".4f",201        ),202        plot_bgcolor="rgba(0,0,0,0)",203        paper_bgcolor="rgba(0,0,0,0)",204        width=1100,205    )206    return fig207 208 209def get_correlations_table(online_metric_name: str) -> pd.DataFrame:210    df = load_dataset(211        "JetBrains-Research/synthetic-commit-msg-edits", "all_pairs_with_metrics_other_online_metrics", split="train"212    ).to_pandas()213    corr_df = (214        df.loc[~df.is_related]215        .groupby(["G_text", "G_type", "hash", "repo"] + [f"online_{online_metric_name}"])216        .apply(lambda g: g.to_dict(orient="records"), include_groups=False)217        .reset_index(name="unrelated_pairs")218        .copy()219    )220    _ = corr_df.copy()221    for metric in AGGR_METRICS:222        if metric in ["editdist"]:223            _[metric] = _.unrelated_pairs.apply(lambda pairs: min(pair[metric] for pair in pairs))224        else:225            _[metric] = _.unrelated_pairs.apply(lambda pairs: max(pair[metric] for pair in pairs))226 227    results = []228 229    for metric in AGGR_METRICS:230        x = _[metric].to_numpy()231        y = _[f"online_{online_metric_name}"].to_numpy()232        corr, p_value = spearmanr(x, y)233        results.append({"metric": metric, "corr": corr, "p_value": p_value})234 235    __ = pd.DataFrame(results)236    __["p_value"] = ["< 0.05" if p < 0.05 else p for p in __.p_value]237    __["corr_abs"] = abs(__["corr"])238    __["corr"] = __["corr"].round(2)239    __["metric"] = __["metric"].map({v: k for k, v in METRICS.items()})240    return (241        __.sort_values(by=["corr_abs"], ascending=False)242        .drop(columns=["corr_abs"])243        .rename(columns={"metric": "Metric m", "corr": "Correlation Q(m, m*)", "p_value": "p-value"})244    )245 246 247force_light_theme_js_func = """248function refresh() {249    const url = new URL(window.location);250 251    if (url.searchParams.get('__theme') !== 'light') {252        url.searchParams.set('__theme', 'light');253        window.location.href = url.href;254    }255}256"""257 258if __name__ == "__main__":259    with gr.Blocks(theme=gr.themes.Soft(), js=force_light_theme_js_func) as application:260        gr.Markdown(parse_readme("README.md"))261 262        def dataset_view_tab(n_items):263            slider = gr.Slider(minimum=1, maximum=n_items, step=1, value=1, label=f"Sample number (total: {n_items})")264 265            diff_view = gr.Highlightedtext(combine_adjacent=True, color_map={"+": "green", "-": "red"})266            start_view = gr.Textbox(interactive=False, label="Initial message G", container=True)267            end_view = gr.Textbox(interactive=False, label="Edited message E", container=True)268            link_view = gr.Markdown()269 270            view = [diff_view, start_view, end_view, link_view]271 272            return slider, view273 274        with gr.Tab("Examples Exploration"):275            with gr.Tab("Manual"):276                slider_manual, view_manual = dataset_view_tab(n_diffs_manual)277 278                slider_manual.change(update_dataset_view_manual, inputs=slider_manual, outputs=view_manual)279 280            with gr.Tab("Synthetic Backward"):281                slider_synthetic_backward, view_synthetic_backward = dataset_view_tab(n_diffs_synthetic_backward)282 283                slider_synthetic_backward.change(284                    update_dataset_view_synthetic_backward,285                    inputs=slider_synthetic_backward,286                    outputs=view_synthetic_backward,287                )288 289            with gr.Tab("Synthetic Forward (from initial)"):290                slider_synthetic_forward, view_synthetic_forward = dataset_view_tab(n_diffs_synthetic_forward)291 292                slider_synthetic_forward.change(293                    update_dataset_view_synthetic_forward,294                    inputs=slider_synthetic_forward,295                    outputs=view_synthetic_forward,296                )297 298            with gr.Tab("Synthetic Forward (from backward)"):299                slider_synthetic_forward_backward, view_synthetic_forward_backward = dataset_view_tab(300                    n_diffs_synthetic_forward_backward301                )302 303                slider_synthetic_forward_backward.change(304                    update_dataset_view_synthetic_forward_backward,305                    inputs=slider_synthetic_forward_backward,306                    outputs=view_synthetic_forward_backward,307                )308 309        with gr.Tab("Dataset Statistics"):310            gr.Markdown("## Number of examples per split")311 312            number_of_pairs_gr_plot = gr.Plot(number_of_pairs_plot, label=None)313 314            gr.Markdown("## Edit Distance Distribution (w/o PyCharm Logs)")315 316            edit_distance_gr_plot = gr.Plot(edit_distance_plot(), label=None)317 318        with gr.Tab("Experimental Results"):319            gr.Markdown(320                "Here, we provide the additional experimental results with different text similarity metrics used as the target online metric, "321                "in addition to edit distance between generated messages G and their edited counterparts E."322            )323 324            gr.Markdown(325                "Please, select one of the available metrics **m*** below to see the correlations **Q(m, m\*)** of offline text similarity metrics with **m*** as an online metric."326            )327 328            for metric in METRICS:329                with gr.Tab(metric):330                    gr.Markdown(331                        f"The table below presents the correlation coefficients **Q(m, m\*)** where {metric} is used as an online metric **m***."332                    )333 334                    result_df = get_correlations_table(METRICS[metric])335                    gr.DataFrame(result_df)336 337        application.load(update_dataset_view_manual, inputs=slider_manual, outputs=view_manual)338 339        application.load(340            update_dataset_view_synthetic_backward, inputs=slider_synthetic_backward, outputs=view_synthetic_backward341        )342 343        application.load(344            update_dataset_view_synthetic_forward, inputs=slider_synthetic_forward, outputs=view_synthetic_forward345        )346 347        application.load(348            update_dataset_view_synthetic_forward_backward,349            inputs=slider_synthetic_forward_backward,350            outputs=view_synthetic_forward_backward,351        )352 353    application.launch()354