Skip to content

Commit 22b2b91

Browse files
authored
Merge pull request #3187 from bghira/bugfix/3185
Fix metrics layout with many validation samples
2 parents 4b575f6 + 2c9e2e1 commit 22b2b91

2 files changed

Lines changed: 43 additions & 26 deletions

File tree

simpletuner/static/css/metrics.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,6 +1012,7 @@
10121012
.training-metrics-layout {
10131013
display: grid;
10141014
grid-template-columns: minmax(0, 3fr) minmax(18rem, 2fr);
1015+
align-items: start;
10151016
gap: 1rem;
10161017
}
10171018

tests/test_webui_e2e.py

Lines changed: 42 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -787,11 +787,13 @@ def test_training_run_metrics_and_validation_media(self) -> None:
787787
encoding="utf-8",
788788
)
789789
first_step_image_path = validation_dir / "step_10_prompt_0_64x64.png"
790-
image_path = validation_dir / "step_20_prompt_0_64x64.png"
791-
second_image_path = validation_dir / "step_20_second_0_64x64.png"
792790
Image.new("RGB", (64, 64), color=(16, 96, 180)).save(first_step_image_path, format="PNG")
793-
Image.new("RGB", (64, 64), color=(32, 160, 120)).save(image_path, format="PNG")
794-
Image.new("RGB", (64, 64), color=(120, 80, 220)).save(second_image_path, format="PNG")
791+
latest_step_image_paths = []
792+
for index in range(10):
793+
image_path = validation_dir / f"step_20_prompt_{index}_64x64.png"
794+
color = ((32 + index * 17) % 255, (160 + index * 11) % 255, (120 + index * 23) % 255)
795+
Image.new("RGB", (64, 64), color=color).save(image_path, format="PNG")
796+
latest_step_image_paths.append(image_path)
795797
media_records = [
796798
{
797799
"step": 10,
@@ -801,23 +803,18 @@ def test_training_run_metrics_and_validation_media(self) -> None:
801803
"resolution": "64x64",
802804
"path": first_step_image_path.relative_to(output_dir).as_posix(),
803805
},
804-
{
805-
"step": 20,
806-
"type": "image",
807-
"label": "A green square",
808-
"index": 0,
809-
"resolution": "64x64",
810-
"path": image_path.relative_to(output_dir).as_posix(),
811-
},
812-
{
813-
"step": 20,
814-
"type": "image",
815-
"label": "A violet square",
816-
"index": 0,
817-
"resolution": "64x64",
818-
"path": second_image_path.relative_to(output_dir).as_posix(),
819-
},
820806
]
807+
for index, image_path in enumerate(latest_step_image_paths):
808+
media_records.append(
809+
{
810+
"step": 20,
811+
"type": "image",
812+
"label": "A green square" if index == 0 else f"Validation prompt {index + 1:02d}",
813+
"index": 0,
814+
"resolution": "64x64",
815+
"path": image_path.relative_to(output_dir).as_posix(),
816+
}
817+
)
821818
(output_dir / "validation_media.jsonl").write_text(
822819
"".join(f"{json.dumps(media)}\n" for media in media_records),
823820
encoding="utf-8",
@@ -889,10 +886,25 @@ def scenario(driver, _browser):
889886
self.assertTrue(any("train_loss" in label for label in hover_result["labels"]), hover_result)
890887
self.assertTrue(hover_result["tooltipInsideChart"], hover_result)
891888

889+
driver.set_window_size(1280, 900)
892890
images = WebDriverWait(driver, 10).until(
893-
lambda _driver: driver.find_elements(By.CSS_SELECTOR, ".training-media-grid figure img")
891+
lambda _driver: (
892+
driver.find_elements(By.CSS_SELECTOR, ".training-media-grid figure img")
893+
if len(driver.find_elements(By.CSS_SELECTOR, ".training-media-grid figure img")) == 10
894+
else False
895+
)
894896
)
895-
self.assertEqual(len(images), 2)
897+
layout_sizing = driver.execute_script(
898+
"""
899+
const chartWorkspace = document.querySelector('.training-chart-workspace').getBoundingClientRect();
900+
const mediaPanel = document.querySelector('.training-media-tool').getBoundingClientRect();
901+
return {
902+
chartHeight: chartWorkspace.height,
903+
mediaHeight: mediaPanel.height,
904+
};
905+
"""
906+
)
907+
self.assertLess(layout_sizing["chartHeight"], layout_sizing["mediaHeight"] - 100, layout_sizing)
896908
media_step_slider = driver.find_element(By.CSS_SELECTOR, "input[aria-label='Validation checkpoint step']")
897909
self.assertEqual(media_step_slider.get_attribute("max"), "1")
898910
self.assertEqual(media_step_slider.get_attribute("value"), "1")
@@ -916,7 +928,7 @@ def scenario(driver, _browser):
916928
images = WebDriverWait(driver, 5).until(
917929
lambda _driver: (
918930
driver.find_elements(By.CSS_SELECTOR, ".training-media-grid figure img")
919-
if len(driver.find_elements(By.CSS_SELECTOR, ".training-media-grid figure img")) == 2
931+
if len(driver.find_elements(By.CSS_SELECTOR, ".training-media-grid figure img")) == 10
920932
else False
921933
)
922934
)
@@ -925,7 +937,7 @@ def scenario(driver, _browser):
925937
self.assertEqual(media_response.status_code, 200, media_response.text)
926938
self.assertEqual(media_response.headers["content-type"], "image/png")
927939
self.assertEqual(Image.open(BytesIO(media_response.content)).size, (64, 64))
928-
image.click()
940+
driver.execute_script("arguments[0].closest('.training-media-image-button').click();", image)
929941
lightbox = WebDriverWait(driver, 10).until(
930942
EC.visibility_of_element_located((By.CSS_SELECTOR, ".training-media-lightbox"))
931943
)
@@ -951,7 +963,11 @@ def scenario(driver, _browser):
951963
lightbox.find_element(By.CSS_SELECTOR, ".training-media-lightbox-toolbar button[title='Close image']").click()
952964
WebDriverWait(driver, 5).until(EC.invisibility_of_element_located((By.CSS_SELECTOR, ".training-media-lightbox")))
953965

954-
driver.find_element(By.CSS_SELECTOR, ".training-chart-actions button[title='Select metrics']").click()
966+
metric_selector_button = driver.find_element(
967+
By.CSS_SELECTOR,
968+
".training-chart-actions button[title='Select metrics']",
969+
)
970+
driver.execute_script("arguments[0].click();", metric_selector_button)
955971
smoothing_slider = WebDriverWait(driver, 5).until(
956972
EC.presence_of_element_located((By.CSS_SELECTOR, "input[aria-label='Chart smoothing']"))
957973
)
@@ -972,7 +988,7 @@ def scenario(driver, _browser):
972988
By.XPATH,
973989
"//div[contains(@class, 'training-metric-picker')]//label[span[text()='train_loss']]/input",
974990
)
975-
loss_toggle.click()
991+
driver.execute_script("arguments[0].click();", loss_toggle)
976992
WebDriverWait(driver, 5).until(lambda _driver: not loss_toggle.is_selected())
977993

978994
timestep_toggle = driver.find_element(

0 commit comments

Comments
 (0)