Skip to content

Commit 80965ec

Browse files
author
Hee, Tyan Huey
committed
add more finetuning tests
Signed-off-by: Hee, Tyan Huey <[email protected]>
1 parent 493350c commit 80965ec

File tree

5 files changed

+194
-1
lines changed

5 files changed

+194
-1
lines changed

tests/playwright/studio-e2e/005_test_funetuning_rerank.spec.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,8 @@ test('005_test_funetuning_rerank', async ({ browser, baseURL }) => {
6161
await expect(page.getByRole('cell', { name: 'running' })).toHaveText('running');
6262
await expect(page.locator('div').filter({ hasText: 'Fine-tuning JobsCreate New' }).nth(3)).toContainText('rerank');
6363
await waitForStatusText(page, 'td.MuiTableCell-root div.MuiChip-root', 'succeeded', 20, 60000);
64+
65+
await page.locator('button').nth(5).click();
66+
await page.getByRole('menuitem', { name: 'Delete Job' }).click();
67+
6468
});
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import { test, expect } from '@playwright/test';
2+
import { waitForStatusText } from '../utils';
3+
import path from 'path';
4+
5+
const trainDataset = path.resolve(__dirname, '../../test-files/toy_finetune_data.jsonl');
6+
7+
async function setupResponseListener(page, apiResponse) {
8+
page.on('response', async (response) => {
9+
if (response.url().includes('/v1/app-backend') && response.request().method() === 'POST') {
10+
const contentType = response.headers()['content-type'];
11+
if (contentType.includes('text/event-stream')) {
12+
const responseBody = await response.text();
13+
// Parse SSE stream
14+
const events = responseBody.split('\n\n');
15+
for (const event of events) {
16+
const lines = event.split('\n');
17+
for (const line of lines) {
18+
if (line.startsWith('data: ')) {
19+
const cleanedData = line.slice(6, -1).trim(); // Remove 'data: ' prefix
20+
apiResponse.value += cleanedData + " ";
21+
}
22+
}
23+
}
24+
} else {
25+
console.error('Response is not SSE');
26+
}
27+
}
28+
});
29+
}
30+
31+
test('006_test_funetuning_embedding', async ({ browser, baseURL }) => {
32+
test.setTimeout(1200000);
33+
let apiResponse = { value: '' };
34+
const context = await browser.newContext({
35+
ignoreHTTPSErrors: true,
36+
recordVideo: {
37+
dir: './videos/',
38+
size: { width: 1280, height: 720 }
39+
}
40+
});
41+
const page = await context.newPage();
42+
const IDC_URL = baseURL || ""
43+
await page.goto(IDC_URL);
44+
await page.getByLabel('Username or email').fill('[email protected]');
45+
await page.getByLabel('Password', { exact: true }).click();
46+
await page.getByLabel('Password', { exact: true }).fill('test');
47+
await page.getByRole('button', { name: 'Sign In' }).click();
48+
await page.getByRole('button', { name: 'Fine-tuning' }).click();
49+
await page.getByRole('button', { name: 'Create New Job' }).click();
50+
await page.getByRole('combobox', { name: 'Base Model' }).click();
51+
await page.getByRole('option', { name: 'BAAI/bge-base-en-v1.5' }).click();
52+
await page.getByText('Instruction Tuning').click();
53+
await page.getByRole('option', { name: 'Embedding' }).click();
54+
let fileChooserPromise = page.waitForEvent('filechooser');
55+
await page.getByRole('button', { name: 'Choose File' }).click();
56+
let fileChooser = await fileChooserPromise;
57+
await fileChooser.setFiles(trainDataset);
58+
await page.waitForTimeout(5000);
59+
await page.getByRole('button', { name: 'Create Job' }).click();
60+
await page.waitForTimeout(20000);
61+
await expect(page.getByRole('cell', { name: 'running' })).toHaveText('running');
62+
await expect(page.locator('div').filter({ hasText: 'Fine-tuning JobsCreate New' }).nth(3)).toContainText('embedding');
63+
await waitForStatusText(page, 'td.MuiTableCell-root div.MuiChip-root', 'succeeded', 20, 60000);
64+
65+
await page.locator('button').nth(5).click();
66+
await page.getByRole('menuitem', { name: 'Delete Job' }).click();
67+
68+
});
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import { test, expect } from '@playwright/test';
2+
import { waitForStatusText } from '../utils';
3+
import path from 'path';
4+
5+
const trainDataset = path.resolve(__dirname, '../../test-files/medical_o1_sft_50.json');
6+
7+
async function setupResponseListener(page, apiResponse) {
8+
page.on('response', async (response) => {
9+
if (response.url().includes('/v1/app-backend') && response.request().method() === 'POST') {
10+
const contentType = response.headers()['content-type'];
11+
if (contentType.includes('text/event-stream')) {
12+
const responseBody = await response.text();
13+
// Parse SSE stream
14+
const events = responseBody.split('\n\n');
15+
for (const event of events) {
16+
const lines = event.split('\n');
17+
for (const line of lines) {
18+
if (line.startsWith('data: ')) {
19+
const cleanedData = line.slice(6, -1).trim(); // Remove 'data: ' prefix
20+
apiResponse.value += cleanedData + " ";
21+
}
22+
}
23+
}
24+
} else {
25+
console.error('Response is not SSE');
26+
}
27+
}
28+
});
29+
}
30+
31+
test('007_test_funetuning_reasoning', async ({ browser, baseURL }) => {
32+
test.setTimeout(1200000);
33+
let apiResponse = { value: '' };
34+
const context = await browser.newContext({
35+
ignoreHTTPSErrors: true,
36+
recordVideo: {
37+
dir: './videos/',
38+
size: { width: 1280, height: 720 }
39+
}
40+
});
41+
const page = await context.newPage();
42+
const IDC_URL = baseURL || ""
43+
await page.goto(IDC_URL);
44+
await page.getByLabel('Username or email').fill('[email protected]');
45+
await page.getByLabel('Password', { exact: true }).click();
46+
await page.getByLabel('Password', { exact: true }).fill('test');
47+
await page.getByRole('button', { name: 'Sign In' }).click();
48+
await page.getByRole('button', { name: 'Fine-tuning' }).click();
49+
await page.getByRole('button', { name: 'Create New Job' }).click();
50+
await page.getByRole('combobox', { name: 'Base Model' }).click();
51+
await page.getByRole('option', { name: 'Qwen/Qwen2.5-7B' }).click();
52+
await page.getByText('Instruction Tuning').click();
53+
await page.getByRole('option', { name: 'Reasoning' }).click();
54+
let fileChooserPromise = page.waitForEvent('filechooser');
55+
await page.getByRole('button', { name: 'Choose File' }).click();
56+
let fileChooser = await fileChooserPromise;
57+
await fileChooser.setFiles(trainDataset);
58+
await page.waitForTimeout(5000);
59+
await page.getByRole('button', { name: 'Create Job' }).click();
60+
await page.waitForTimeout(20000);
61+
await expect(page.getByRole('cell', { name: 'running' })).toHaveText('running');
62+
await expect(page.locator('div').filter({ hasText: 'Fine-tuning JobsCreate New' }).nth(3)).toContainText('reasoning');
63+
await waitForStatusText(page, 'MuiChip-label MuiChip-labelSmall css-cxrmjv', 'succeeded', 20, 60000);
64+
65+
await page.locator('button').nth(5).click();
66+
await page.getByRole('menuitem', { name: 'Delete Job' }).click();
67+
68+
69+
});

tests/playwright/utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ export async function waitForStatusText(page: any, selector: string, statusText:
44
for (let i = 0; i < maxAttempts; i++) {
55
try {
66
const text = await page.locator(selector).first().innerText();
7-
if (text === 'Error') {
7+
if (text === 'Error' ||text === 'failed') {
88
throw new Error(`Encountered unwanted status text "Error" in element "${selector}"`);
99
}
1010
await expect(page.locator(selector).first()).toHaveText(statusText, { timeout: intervalTimeout });

0 commit comments

Comments
 (0)