Skip to content

Add MPQ/deploy dashboard history export, visualization, and live search plotting - #39

Open
Jzjerry with Copilot wants to merge 25 commits into
mainfrom
copilot/create-dashboard-webui
Open

Add MPQ/deploy dashboard history export, visualization, and live search plotting#39
Jzjerry with Copilot wants to merge 25 commits into
mainfrom
copilot/create-dashboard-webui

Conversation

Copilot AI commented Apr 2, 2026

Copy link
Copy Markdown
Contributor

This PR introduces a reusable MiCoDashboard utility for MPQ/deploy history export and visualization, standardizes searcher best-trace tracking, and adds opt-in real-time plot updates during search.

What’s included

  • Added centralized dashboard APIs in MiCoDashboard to:
    • build run histories from search traces
    • save/load dashboard JSON
    • render accuracy-vs-constraint plots
    • print top configurations
  • Integrated dashboard history export into MPQ search and deploy flows.
  • Refactored searcher flow to keep best_trace and best_scheme_trace aligned via shared recording logic.
  • Added validation and clearer error handling around dashboard trace alignment and hook behavior.
  • Added optional live plotting during search in examples/mpq_search.py:
    • --live-plot
    • --live-plot-every
    • live plots update per configured record-best interval.
  • Updated README usage for dashboard generation/rendering and live plotting options.

Validation

  • Ran targeted validation (py_compile) on touched files.
  • Ran review/security validation iterations and addressed actionable feedback.

@sourcery-ai

sourcery-ai Bot commented Apr 2, 2026

Copy link
Copy Markdown

Reviewer's Guide

Introduces a reusable MiCoDashboard utility and CLI to export, aggregate, and visualize MPQ search/deploy history (accuracy vs constraint), and refactors all searchers to track both best objective values and corresponding schemes in a consistent way that can be serialized for dashboard consumption.

Sequence diagram for MPQ search with dashboard history export

sequenceDiagram
  actor User
  participant MPQSearchScript as mpq_search_py
  participant Searcher as QSearcher_subclass
  participant Evaluator as MiCoEval
  participant Dashboard as MiCoDashboard
  participant FS as FileSystem

  User->>MPQSearchScript: run mpq_search_py(model_name, mode, constr_ratio)
  MPQSearchScript->>Searcher: search(n_iter, target, constr, constr_value)
  activate Searcher
  Searcher->>Searcher: start_search(target, constr, constr_value)
  Searcher->>Evaluator: set_eval(target)
  alt has_constraint
    Searcher->>Evaluator: set_constraint(constr)
  end

  loop search_iterations
    Searcher->>Evaluator: evaluate(candidate_scheme)
    Evaluator-->>Searcher: metric_value
    Searcher->>Searcher: record_best(best_scheme, best_value)
    note over Searcher: Append to best_trace
    note over Searcher: Append to best_scheme_trace
  end
  Searcher-->>MPQSearchScript: best_scheme, best_value
  deactivate Searcher

  MPQSearchScript->>Dashboard: build_run_history(Searcher, Evaluator, constraint_name)
  activate Dashboard
  Dashboard->>Evaluator: eval_dict()
  Evaluator-->>Dashboard: eval_map
  loop over best_trace
    Dashboard->>Evaluator: constr_eval(scheme)
    Evaluator-->>Dashboard: constr_value
    Dashboard->>Dashboard: append {iter, accuracy, constraint, scheme}
  end
  Dashboard-->>MPQSearchScript: history
  deactivate Dashboard

  MPQSearchScript->>Dashboard: build_run_entry(method, seed, objective, constraint_name, constraint_limit, history)
  Dashboard-->>MPQSearchScript: run_entry

  MPQSearchScript->>Dashboard: save_runs(history_json_path, [run_entry,...])
  Dashboard->>FS: write_json(path, {runs: [...]})
  FS-->>Dashboard: ok
  Dashboard-->>MPQSearchScript: done
  MPQSearchScript-->>User: print("Dashboard history JSON saved")
Loading

ER diagram for dashboard JSON schema (runs and history)

erDiagram
  RUN {
    string method
    int seed
    string objective
    string constraint_name
    float constraint_limit
  }

  HISTORY_POINT {
    int iter
    float accuracy
    float constraint
    string scheme
  }

  DASHBOARD_FILE {
    json runs
  }

  RUN ||--o{ HISTORY_POINT : has_history
  DASHBOARD_FILE ||--o{ RUN : contains_runs
Loading

Class diagram for updated searchers and MiCoDashboard

classDiagram

class QSearcher {
  +int n_inits
  +list qtypes
  +list best_trace
  +list best_scheme_trace
  +str target
  +str constr_name
  +float constr_value
  +__init__(MiCoEval evaluator, int n_inits, list qtypes)
  +start_search(str target, str constr, float constr_value)
  +record_best(list best_scheme, float best_value)
  +search(int n_iter, str target, str constr, float constr_value): Tuple
}

class BayesSearcher {
  +list sampled_X
  +list sampled_y
  +search(int n_iter, str target, str constr, float constr_value): Tuple
}

class MiCoSearcher {
  +list sampled_X
  +list sampled_y
  +search(int n_iter, str target, str constr, float constr_value): Tuple
}

class RegressionSearcher {
  +list sampled_X
  +list sampled_y
  +search(int n_iter, str target, str constr, float constr_value): Tuple
}

class HAQSearcher {
  +list best_trace
  +float best_acc
  +list best_res
  +search(int n_iter, str target, str constr, float constr_value): Tuple
}

class NLPSearcher {
  +list best_trace
  +list best_scheme_trace
  +search(int n_iter, str target, str constr, float constr_value): Tuple
}

class MiCoEval {
  +int n_layers
  +int dim
  +set_eval(str target)
  +set_constraint(str constr)
  +dict eval_dict()
}

class MiCoDashboard {
  +build_run_history(QSearcher searcher, MiCoEval evaluator, str constraint_name): list
  +build_run_entry(str method, int seed, str objective, str constraint_name, float constraint_limit, list history): dict
  +save_runs(str path, list runs)
  +load_runs(str path): list
  +run_label(dict run): str
  +plot_acc_vs_constr(list runs, str objective, str constraint, str output_path)
  +print_top_configs(list runs, int topk)
}

QSearcher <|-- BayesSearcher
QSearcher <|-- MiCoSearcher
QSearcher <|-- RegressionSearcher
QSearcher <|-- HAQSearcher
QSearcher <|-- NLPSearcher

QSearcher --> MiCoEval : uses
BayesSearcher --> MiCoEval : uses
MiCoSearcher --> MiCoEval : uses
RegressionSearcher --> MiCoEval : uses
HAQSearcher --> MiCoEval : uses
NLPSearcher --> MiCoEval : uses

MiCoDashboard --> QSearcher : reads_best_trace_and_best_scheme_trace
MiCoDashboard --> MiCoEval : uses_eval_dict_for_constraint
Loading

Flow diagram for mpq_dashboard CLI visualization pipeline

flowchart LR
  User([User])
  A["Run mpq_dashboard_py with input_json"]
  B["MiCoDashboard_load_runs"]
  C["MiCoDashboard_plot_acc_vs_constr"]
  D["MiCoDashboard_print_top_configs"]
  E["Read dashboard JSON file"]
  F["Runs list (history per run)"]
  G["Generate accuracy vs constraint plot"]
  H["Save PNG to output path"]
  I["Print top K configurations to console"]

  User --> A
  A --> B
  B --> E
  E --> F
  F --> C
  F --> D
  C --> G
  G --> H
  D --> I
Loading

File-Level Changes

Change Details Files
Add generic search session state and best-scheme tracking to QSearcher and update concrete searchers to use it.
  • Extend QSearcher with best_scheme_trace, target, constraint name/value fields and initialize them in init.
  • Add start_search() helper to centralize evaluator target/constraint setup and reset traces at the beginning of each search.
  • Add record_best() helper to atomically capture best value and corresponding scheme for each iteration.
  • Refactor all concrete searchers (HAQSearcher, BayesSearcher, MiCoSearcher, RegressionSearcher, NLPSearcher) to call start_search() instead of manually configuring evaluators and to use record_best() when updating best_trace, including populating a dummy best_scheme_trace in NLPSearcher.
searchers/QSearcher.py
searchers/HAQSearcher.py
searchers/BayesSearcher.py
searchers/MiCoSearcher.py
searchers/RegressionSearcher.py
searchers/NLPSearcher.py
Introduce MiCoDashboard utility for building, saving, loading, plotting, and summarizing MPQ run histories.
  • Implement MiCoDashboard.build_run_history() to derive iteration-wise accuracy, constraint values, and schemes from searcher traces using evaluator eval_dict().
  • Implement MiCoDashboard.build_run_entry() and save_runs()/load_runs() to standardize the JSON schema and IO for dashboard data.
  • Add plotting (plot_acc_vs_constr) and ranking (print_top_configs) helpers to visualize accuracy vs constraint and print top configurations.
MiCoDashboard.py
Wire dashboard history export into MPQ search and deploy workflows and add a CLI to visualize it.
  • In mpq_search.py, accumulate run_history per method/seed using MiCoDashboard.build_run_history(), build structured run entries, and save them as a history JSON file via MiCoDashboard.save_runs().
  • In deploy_on_bf.py and deploy_on_mico.py, build a single run history for the deployment search, write dashboards JSONs, and print the output path.
  • Add examples/mpq_dashboard.py as a CLI that loads a dashboard JSON, renders an accuracy-vs-constraint plot, and prints top-k configurations using MiCoDashboard.
  • Update README with MPQ dashboard usage instructions (how to generate history JSON and render the dashboard).
examples/mpq_search.py
deploy/deploy_on_bf.py
deploy/deploy_on_mico.py
examples/mpq_dashboard.py
readme.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@Jzjerry

Jzjerry commented Apr 2, 2026

Copy link
Copy Markdown
Contributor

@copilot I think it's changing too many loc. Try some abstraction. Get me a Class like MiCoDashboard to hold some universal APIs, and re-use it for minimal changes on mpq_search / deploy / searchers. Current changes involve too many changes.

@Jzjerry

Jzjerry commented Apr 2, 2026

Copy link
Copy Markdown
Contributor

@gemini-code-assist review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a dashboarding system for Mixed Precision Quantization (MPQ) search results. It includes a new MiCoDashboard class for managing and visualizing search history, updates to deployment and search scripts to capture this data, and a new example script for generating plots. Additionally, the searcher classes were refactored to use standardized methods for tracking the best results and their corresponding schemes. Feedback focuses on maintaining synchronization between accuracy and scheme traces in mpq_search.py, ensuring consistent file encoding for JSON operations, and optimizing data processing in the plotting logic.

Comment thread examples/mpq_search.py Outdated
@@ -120,6 +123,17 @@
print(f"Final QAT Accuracy: {final_acc}")
searcher.best_trace.append(final_acc)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Directly appending to searcher.best_trace breaks the synchronization with searcher.best_scheme_trace. This causes the final QAT result to be associated with a None scheme in the dashboard history, which leads to it being excluded from plots in MiCoDashboard.plot_acc_vs_constr. Use searcher.record_best() to keep both traces in sync.

Suggested change
searcher.best_trace.append(final_acc)
searcher.record_best(res_x, final_acc)

Comment thread MiCoDashboard.py

@staticmethod
def save_runs(path: str, runs: list):
output_dir = os.path.dirname(path)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

It is recommended to specify the encoding when opening files for writing to ensure consistency across different platforms. Using utf-8 is generally preferred for JSON files.

Suggested change
output_dir = os.path.dirname(path)
with open(path, "w", encoding="utf-8") as f:

Comment thread MiCoDashboard.py
os.makedirs(output_dir, exist_ok=True)
with open(path, "w") as f:
json.dump({"runs": runs}, f, indent=2)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

It is recommended to specify the encoding when opening files for reading to ensure consistency across different platforms.

Suggested change
with open(path, "r", encoding="utf-8") as f:

Comment thread MiCoDashboard.py
Comment on lines +72 to +73
color_idx = 0
for run in runs:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

These list comprehensions iterate over the points list twice and perform the same filtering logic. This can be optimized by filtering once and then extracting the values.

            valid_points = [p for p in points if p.get("constraint") is not None and p.get("accuracy") is not None]
            xs = [p.get("constraint") for p in valid_points]
            ys = [p.get("accuracy") for p in valid_points]

Copilot AI commented Apr 2, 2026

Copy link
Copy Markdown
Contributor Author

@copilot I think it's changing too many loc. Try some abstraction. Get me a Class like MiCoDashboard to hold some universal APIs, and re-use it for minimal changes on mpq_search / deploy / searchers...

Refactored to a single MiCoDashboard abstraction and reused it across mpq_search, deploy_on_mico, deploy_on_bf, and searcher flow helpers to reduce duplicated LOC. Addressed in commit 5fade41 (with core abstraction introduced in 62abfac).

UI screenshot:
mpq dashboard example

@Jzjerry

Jzjerry commented Apr 2, 2026

Copy link
Copy Markdown
Contributor

@copilot address the reviews from gemini-code-assist

Copilot AI commented Apr 2, 2026

Copy link
Copy Markdown
Contributor Author

@copilot address the reviews from gemini-code-assist

Addressed Gemini review items in f5f5cf9.

UI screenshot:
mpq dashboard example

@Jzjerry
Jzjerry marked this pull request as ready for review April 2, 2026 07:03

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 2 issues, and left some high level feedback:

  • In HAQSearcher.search, self.best_res is reset to None and passed into record_best, but from the shown code it’s never updated when a new best policy is found, which means best_scheme_trace (and thus dashboard constraint values) will be None unless you explicitly set self.best_res whenever self.best_acc is updated.
  • In MiCoDashboard.plot_acc_vs_constr, consider calling plt.close() after saving the figure to avoid accumulating open figures and memory usage when plotting multiple dashboards in the same process.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `HAQSearcher.search`, `self.best_res` is reset to `None` and passed into `record_best`, but from the shown code it’s never updated when a new best policy is found, which means `best_scheme_trace` (and thus dashboard constraint values) will be `None` unless you explicitly set `self.best_res` whenever `self.best_acc` is updated.
- In `MiCoDashboard.plot_acc_vs_constr`, consider calling `plt.close()` after saving the figure to avoid accumulating open figures and memory usage when plotting multiple dashboards in the same process.

## Individual Comments

### Comment 1
<location path="MiCoDashboard.py" line_range="8-27" />
<code_context>
+
+class MiCoDashboard:
+    @staticmethod
+    def build_run_history(searcher, evaluator, constraint_name: str):
+        history = []
+        eval_map = evaluator.eval_dict()
+        if constraint_name not in eval_map:
+            valid_names = ", ".join(sorted(eval_map.keys()))
+            raise ValueError(
+                f"Unsupported constraint name '{constraint_name}'. Must be one of: {valid_names}"
+            )
+        constr_eval = eval_map[constraint_name]
+        for idx, best_acc in enumerate(searcher.best_trace):
+            scheme = searcher.best_scheme_trace[idx] if idx < len(searcher.best_scheme_trace) else None
+            constr_val = constr_eval(scheme) if scheme is not None else None
+            history.append({
+                "iter": idx + 1,
+                "accuracy": float(best_acc) if best_acc is not None else None,
</code_context>
<issue_to_address>
**suggestion:** Guard against mismatched `best_trace` / `best_scheme_trace` lengths more explicitly.

`build_run_history` currently indexes `best_scheme_trace` with `idx` and falls back to `None` when `idx >= len(best_scheme_trace)`. If a `searcher` implementation updates `best_trace` and `best_scheme_trace` at different times, this will silently drop or misalign schemes in the history. Instead of quietly returning `None`, consider asserting equal lengths (or otherwise validating alignment) and logging or raising when they differ so inconsistencies are surfaced early.

```suggestion
    @staticmethod
    def build_run_history(searcher, evaluator, constraint_name: str):
        history = []
        eval_map = evaluator.eval_dict()
        if constraint_name not in eval_map:
            valid_names = ", ".join(sorted(eval_map.keys()))
            raise ValueError(
                f"Unsupported constraint name '{constraint_name}'. Must be one of: {valid_names}"
            )

        # Validate that best_trace and best_scheme_trace are aligned
        if not hasattr(searcher, "best_trace") or not hasattr(searcher, "best_scheme_trace"):
            raise AttributeError(
                "Searcher must define both 'best_trace' and 'best_scheme_trace' attributes "
                "for MiCoDashboard.build_run_history to work."
            )

        if len(searcher.best_trace) != len(searcher.best_scheme_trace):
            raise ValueError(
                "Mismatched lengths for 'best_trace' and 'best_scheme_trace'. "
                f"Got len(best_trace)={len(searcher.best_trace)}, "
                f"len(best_scheme_trace)={len(searcher.best_scheme_trace)}. "
                "These traces must be kept in sync by the searcher implementation."
            )

        constr_eval = eval_map[constraint_name]
        for idx, best_acc in enumerate(searcher.best_trace):
            scheme = searcher.best_scheme_trace[idx]
            constr_val = constr_eval(scheme) if scheme is not None else None
            history.append({
                "iter": idx + 1,
                "accuracy": float(best_acc) if best_acc is not None else None,
                "constraint": float(constr_val) if constr_val is not None else None,
                "scheme": scheme
            })
        return history
```
</issue_to_address>

### Comment 2
<location path="examples/mpq_dashboard.py" line_range="9-16" />
<code_context>
+    parser = argparse.ArgumentParser(description="Simple dashboard for MPQ search histories.")
+    parser.add_argument("input_json", type=str, help="Dashboard JSON file (from mpq_search/deploy scripts).")
+    parser.add_argument("--output", type=str, default="output/figs/mpq_dashboard_acc_vs_constraint.png")
+    parser.add_argument("--objective", type=str, default="accuracy")
+    parser.add_argument("--constraint", type=str, default="constraint")
+    parser.add_argument("--topk", type=int, default=10)
+    args = parser.parse_args()
+
+    runs = MiCoDashboard.load_runs(args.input_json)
+    MiCoDashboard.plot_acc_vs_constr(runs, args.objective, args.constraint, args.output)
+    MiCoDashboard.print_top_configs(runs, args.topk)
</code_context>
<issue_to_address>
**suggestion:** Consider coupling the CLI `--objective/--constraint` names with the run metadata fields.

Currently these flags only affect axis labels in `plot_acc_vs_constr`; the data always comes from the fixed `"accuracy"` and `"constraint"` history keys. This can mislead users who pass a different metric name expecting it to change which values are plotted/sorted. To make this clearer, either derive the labels from run metadata (e.g. `run["objective"]` / `run["constraint_name"]`), or let `--objective`/`--constraint` choose which history fields are used for x/y and validate those against the history structure.

Suggested implementation:

```python
    args = parser.parse_args()

    runs = MiCoDashboard.load_runs(args.input_json)

    # Validate that the requested objective/constraint metrics exist in the run history
    if not runs:
        parser.error("No runs loaded from input JSON; cannot build dashboard.")

    sample_run = runs[0]
    history = sample_run.get("history", {})
    if not isinstance(history, dict):
        parser.error(
            "Run history has unexpected format; expected a dict of metric_name -> values.\n"
            f"Got type={type(history)} for history in first run."
        )

    available_metrics = set(history.keys())

    if args.objective not in available_metrics:
        parser.error(
            f'Unknown objective metric "{args.objective}". '
            f"Available metrics in history: {sorted(available_metrics)}"
        )

    if args.constraint not in available_metrics:
        parser.error(
            f'Unknown constraint metric "{args.constraint}". '
            f"Available metrics in history: {sorted(available_metrics)}"
        )

    MiCoDashboard.plot_acc_vs_constr(runs, args.objective, args.constraint, args.output)
    MiCoDashboard.print_top_configs(runs, args.topk)

```

`).

Here are the concrete edits:

<file_operations>
<file_operation operation="edit" file_path="examples/mpq_dashboard.py">
<<<<<<< SEARCH
    args = parser.parse_args()

    runs = MiCoDashboard.load_runs(args.input_json)
    MiCoDashboard.plot_acc_vs_constr(runs, args.objective, args.constraint, args.output)
    MiCoDashboard.print_top_configs(runs, args.topk)
=======
    args = parser.parse_args()

    runs = MiCoDashboard.load_runs(args.input_json)

    # Validate that the requested objective/constraint metrics exist in the run history
    if not runs:
        parser.error("No runs loaded from input JSON; cannot build dashboard.")

    sample_run = runs[0]
    history = sample_run.get("history", {})
    if not isinstance(history, dict):
        parser.error(
            "Run history has unexpected format; expected a dict of metric_name -> values.\n"
            f"Got type={type(history)} for history in first run."
        )

    available_metrics = set(history.keys())

    if args.objective not in available_metrics:
        parser.error(
            f'Unknown objective metric "{args.objective}". '
            f"Available metrics in history: {sorted(available_metrics)}"
        )

    if args.constraint not in available_metrics:
        parser.error(
            f'Unknown constraint metric "{args.constraint}". '
            f"Available metrics in history: {sorted(available_metrics)}"
        )

    MiCoDashboard.plot_acc_vs_constr(runs, args.objective, args.constraint, args.output)
    MiCoDashboard.print_top_configs(runs, args.topk)
>>>>>>> REPLACE
</file_operation>
</file_operations>

<additional_changes>
To fully implement the behavior described in your review comment, `MiCoDashboard.plot_acc_vs_constr` (and any related logic) should be updated so that:

1. It uses the `objective` and `constraint` arguments as *history field names* (e.g. `history[objective]`, `history[constraint]`) rather than always reading from hard-coded `"accuracy"` / `"constraint"` keys.
2. Axis labels in the plot are derived from these names (or from more descriptive metadata fields if available), so that the plot and CLI options are consistent.
3. Any sorting/selection in `print_top_configs` that currently assumes `"accuracy"` / `"constraint"` keys should similarly be parameterized or documented, potentially by passing `objective` and `constraint` through to that function as well.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread MiCoDashboard.py
Comment thread examples/mpq_dashboard.py Outdated
@Jzjerry

Jzjerry commented Apr 2, 2026

Copy link
Copy Markdown
Contributor

@copilot address sourcery review

Copilot AI and others added 6 commits April 2, 2026 07:09

Copilot AI commented Apr 2, 2026

Copy link
Copy Markdown
Contributor Author

@copilot address sourcery review

Addressed Sourcery review updates in 378f643 (with related fixes in 1fd1154, f462e9f, ad1ceeb, ac727bb, and 3fac18e).

UI screenshot:
mpq dashboard example

@Jzjerry

Jzjerry commented Apr 2, 2026

Copy link
Copy Markdown
Contributor

@copilot I want something more real-time I guess. Something that can be displayed during the search (like scatters, curves that updates per iterations)...

Copilot AI and others added 7 commits April 2, 2026 07:27

Copilot AI commented Apr 2, 2026

Copy link
Copy Markdown
Contributor Author

@copilot I want something more real-time I guess. Something that can be displayed during the search (like scatters, curves that updates per iterations)...

Implemented this in d7c2622 (core feature landed in f3b2aee): MPQ search now supports opt-in live-updating accuracy-vs-constraint plots during search via --live-plot and --live-plot-every, reusing MiCoDashboard APIs.

UI screenshot:
mpq dashboard example

Copilot AI changed the title Add MPQ/deploy dashboard history export and visualization Add MPQ/deploy dashboard history export, visualization, and live search plotting Apr 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants