Skip to content

Commit

Permalink
Merge pull request #692 from epfml/691-ui-tweaks-julien
Browse files Browse the repository at this point in the history
UI tweaks
  • Loading branch information
JulienVig authored Jul 11, 2024
2 parents ea8e63c + 7741d84 commit 921fe05
Show file tree
Hide file tree
Showing 56 changed files with 526 additions and 377 deletions.
2 changes: 1 addition & 1 deletion DEV.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ npm ci

**4.** Build the projects

Then we need to builds the packages meaning compile TypeScript into JavaScript.
Then we need to build the packages, which means to compile TypeScript into JavaScript.

Disco is split in multiple packages, called workspaces in NPM, which are described in the [Structure Section](#structure).
You can add `--workspaces` (or shorter as `-ws`) to many `npm` commands to act on all packages.
Expand Down
13 changes: 8 additions & 5 deletions discojs/src/client/decentralized/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export class Base extends Client {

// Wait for peers to be connected before sending any update information
try {
const receivedMessage = await waitMessageWithTimeout(this.server, type.PeersForRound)
const receivedMessage = await waitMessageWithTimeout(this.server, type.PeersForRound, undefined, "Timeout waiting for the round's peer list")
if (this.nodes.size > 0) {
throw new Error('got new peer list from server but was already received for this round')
}
Expand Down Expand Up @@ -190,14 +190,16 @@ export class Base extends Client {
throw new Error('error while sending weights')
}
}

if (this.aggregationResult === undefined) {
throw new TypeError('aggregation result promise is undefined')
}

// Wait for aggregation before proceeding to the next communication round.
// The current result will be used as payload for the eventual next communication round.
result = await Promise.race([this.aggregationResult, timeout()])
result = await Promise.race([
this.aggregationResult,
timeout(undefined, "Timeout waiting on the aggregation result promise to resolve")
])

// There is at least one communication round remaining
if (r < this.aggregator.communicationRounds - 1) {
Expand All @@ -216,14 +218,15 @@ export class Base extends Client {
let receivedPayloads = 0
do {
try {
const message = await waitMessageWithTimeout(connection, type.Payload)
const message = await waitMessageWithTimeout(connection, type.Payload,
undefined, "Timeout waiting for a contribution from peer " + peerId)
const decoded = serialization.weights.decode(message.payload)

if (!this.aggregator.add(peerId, decoded, round, message.round)) {
console.warn(`[${this.ownId}] Failed to add contribution from peer ${peerId}`)
}
} catch (e) {
console.warn(e instanceof Error ? e.message : e)
console.error(e instanceof Error ? e.message : e)
}
} while (++receivedPayloads < this.aggregator.communicationRounds)
})
Expand Down
8 changes: 6 additions & 2 deletions discojs/src/client/event_connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,12 @@ export async function waitMessage<T extends type> (connection: EventConnection,
})
}

export async function waitMessageWithTimeout<T extends type> (connection: EventConnection, type: T, timeoutMs?: number): Promise<NarrowMessage<T>> {
return await Promise.race([waitMessage(connection, type), timeout(timeoutMs)])
export async function waitMessageWithTimeout<T extends type>(
connection: EventConnection,
type: T, timeoutMs?: number,
errorMsg: string = 'timeout'): Promise<NarrowMessage<T>> {

return await Promise.race([waitMessage(connection, type), timeout(timeoutMs, errorMsg)])
}

export class PeerConnection extends EventEmitter<{ [K in type]: NarrowMessage<K> }> implements EventConnection {
Expand Down
1 change: 0 additions & 1 deletion discojs/src/client/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ export enum type {

// Decentralized
SignalForPeer,

PeerIsReady,
PeersForRound,

Expand Down
4 changes: 2 additions & 2 deletions discojs/src/client/utils.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// Time to wait for the others in milliseconds.
export const MAX_WAIT_PER_ROUND = 15_000

export async function timeout (ms = MAX_WAIT_PER_ROUND): Promise<never> {
export async function timeout (ms = MAX_WAIT_PER_ROUND, errorMsg: string = 'timeout'): Promise<never> {
return await new Promise((_, reject) => {
setTimeout(() => { reject(new Error('timeout')) }, ms)
setTimeout(() => { reject(new Error(errorMsg)) }, ms)
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ describe('text preprocessing', function () {
it('can tokenize text', async () => {
const { tokens } = await tokenize.apply(Promise.resolve(text), initMockTask()) as { tokens: number[]}
expect(tokens).to.be.deep.equal(expectedTokens)
})
}).timeout(4000)

it('can truncate inputs when tokenizing', async () => {
const truncationTask = initMockTask()
Expand All @@ -42,7 +42,7 @@ describe('text preprocessing', function () {
const expectedLength = truncationTask.trainingInformation.maxSequenceLength + 1 // + 1 because tokenization includes an extra token label for next label prediction
expect(tokens.length).to.be.equal(expectedLength)
expect(tokens).to.be.deep.equal(expectedTokens.slice(0, expectedLength))
})
}).timeout(4000)

it('can left pad tokens', async () => {
// Create a task where output token sequence should all have length 20
Expand Down
5 changes: 0 additions & 5 deletions discojs/src/default_tasks/lus_covid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,6 @@ export const lusCovid: TaskProvider = {
LABEL_LIST: ['COVID-Positive', 'COVID-Negative'],
dataType: 'image',
scheme: 'federated',
noiseScale: undefined,
clippingRadius: 20,
decentralizedSecure: true,
minimumReadyPeers: 2,
maxShareValue: 100,
tensorBackend: 'tfjs'
}
}
Expand Down
2 changes: 1 addition & 1 deletion discojs/src/default_tasks/mnist.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export const mnist: TaskProvider = {
LABEL_LIST: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
scheme: 'decentralized',
noiseScale: undefined,
clippingRadius: 20,
clippingRadius: undefined,
decentralizedSecure: true,
minimumReadyPeers: 3,
maxShareValue: 100,
Expand Down
4 changes: 2 additions & 2 deletions discojs/src/default_tasks/titanic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ export const titanic: TaskProvider = {
},
trainingInformation: {
modelID: 'titanic-model',
epochs: 40,
roundDuration: 10,
epochs: 10,
roundDuration: 2,
validationSplit: 0.2,
batchSize: 30,
preprocessingFunctions: [data.TabularPreprocessing.Sanitize],
Expand Down
2 changes: 1 addition & 1 deletion discojs/src/models/gpt/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export const DEFAULT_CONFIG: Required<GPTConfig> = {
name: 'transformer',
lr: 0.001,
weightDecay: 0,
maxIter: 5,
maxIter: 10,
verbose: 0,
modelType: 'gpt-nano',
evaluate: true,
Expand Down
2 changes: 1 addition & 1 deletion docs/VUEJS.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,6 @@ For now a template that shows how to create tasks can be found.
| ---------------------------------------------------------------------------- | :-------------: | :--------------------------------------------------------------- |
| [vee-validate](https://vee-validate.logaretm.com/v4/) | `Form` | Form Validation for Vue.js |
| [vue-toast-notification](https://github.com/ankurk91/vue-toast-notification) | `Notifications` | Toast notification plugin for Vue.js |
| [tippy](https://atomiks.github.io/tippyjs/) | `Menu` | Plugin to build menu / side bars |
| [vue-tippy](https://vue-tippy.netlify.app/) | `Tooltip` | Show tooltip text on hover |
| [vue-router](https://router.vuejs.org/) | `Routing` | Official router plugin for Vue.js |
| [yup](https://github.com/jquense/yup) | `Form` | Schema builder for runtime value parsing and validation (forms). |
19 changes: 15 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion server/src/router/decentralized/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ export class Decentralized extends Server {
throw new Error(`task ${task.id} doesn't exist in ready buffer`)
}
this.readyNodes = this.readyNodes.set(task.id, peers)

if (peers.size >= minimumReadyPeers) {
this.readyNodes = this.readyNodes.set(task.id, Set())

Expand Down
4 changes: 2 additions & 2 deletions server/tests/validator.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,8 @@ describe('validator', function () {
`Expected ${size} visited samples but got ${validator.visitedSamples}`
)
assert(
validator.accuracy > 0.4,
`Expected random weight init accuracy greater than 0.4 but got ${validator.accuracy}`
validator.accuracy > 0.3,
`Expected random weight init accuracy greater than 0.3 but got ${validator.accuracy}`
)
}).timeout(1000)

Expand Down
8 changes: 4 additions & 4 deletions webapp/cypress/e2e/library.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ describe("model library", () => {
cy.visit("/#/evaluate");
cy.contains("button", "download").click();

cy.get('[data-title="Model Library"]').click();
cy.get('#model-library-btn').click();
cy.contains("titanic-model").get('button[title="Download"]').click();

expectDownloadOfTFJSModelIsTrainable("titanic_titanic-model");
Expand All @@ -103,17 +103,17 @@ describe("model library", () => {
cy.contains("button", "next").click();

cy.contains("button", "train alone").click();
cy.contains("h6", "current round")
cy.contains("h6", "epochs")
.next({ timeout: 10_000 })
.should("have.text", "1");
.should("have.text", "3 / 3");
cy.contains("button", "next").click();

// TODO do not save by default, only via "save model" button

// TODO be reactive
cy.visit("/#/evaluate"); // force refresh

cy.get('[data-title="Model Library"]').click();
cy.get('#model-library-btn').click();
cy.contains("titanic-model").get('button[title="Download"]').click();

expectDownloadOfTFJSModelIsTrainable("titanic_titanic-model");
Expand Down
5 changes: 3 additions & 2 deletions webapp/cypress/e2e/tasks.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ describe("tasks page", () => {
defaultTasks.titanic.getTask(),
defaultTasks.mnist.getTask(),
defaultTasks.lusCovid.getTask(),
defaultTasks.wikitext.getTask(),
]);
cy.visit("/#/list");

// Length 4 = 3 tasks and 1 div for text description
cy.get('div[id="tasks"]').children().should("have.length", 4);
// Length 5 = 4 tasks and 1 div for text description
cy.get('div[id="tasks"]').children().should("have.length", 5);
});

it("redirects to training", () => {
Expand Down
4 changes: 2 additions & 2 deletions webapp/cypress/e2e/training.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,9 @@ describe("training page", () => {
cy.contains("button", "next").click();

cy.contains("button", "train alone").click();
cy.contains("h6", "current round")
cy.contains("h6", "epochs")
.next({ timeout: 40_000 })
.should("have.text", "2");
.should("have.text", "10 / 10");
cy.contains("button", "next").click();

cy.contains("button", "test model").click();
Expand Down
2 changes: 1 addition & 1 deletion webapp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@
"d3": "7",
"immutable": "4",
"pinia": "2",
"tippy.js": "6",
"vee-validate": "4",
"vue": "3",
"vue-router": "4",
"vue-tippy": "6",
"vue-toast-notification": "3",
"vue3-apexcharts": "1",
"yup": "1"
Expand Down
8 changes: 4 additions & 4 deletions webapp/src/assets/css/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,19 @@

.tippy-box[data-theme~="custom-dark"][data-placement^="top"]
> .tippy-arrow::before {
border-top-color: #26323d;
border-top-color: #6f7174;
}
.tippy-box[data-theme~="custom-dark"][data-placement^="bottom"]
> .tippy-arrow::before {
border-bottom-color: #26323d;
border-bottom-color: #6f7174;
}
.tippy-box[data-theme~="custom-dark"][data-placement^="left"]
> .tippy-arrow::before {
border-left-color: #26323d;
border-left-color: #6f7174;
}
.tippy-box[data-theme~="custom-dark"][data-placement^="right"]
> .tippy-arrow::before {
border-right-color: #26323d;
border-right-color: #6f7174;
}

@font-face {
Expand Down
5 changes: 4 additions & 1 deletion webapp/src/assets/gif/DiscoGIF.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
<template>
<img src="https://storage.googleapis.com/deai-313515.appspot.com/gifs/disco_middle.gif">
<img
style="max-height:500px; max-width:500px; height:auto; width:auto;"
src="https://storage.googleapis.com/deai-313515.appspot.com/gifs/disco_middle.gif"
/>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
Expand Down
52 changes: 52 additions & 0 deletions webapp/src/assets/svg/FeedbackIcon.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<template>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="currentColor"
:class="customClass"
:viewBox="viewBox"
>
<g>
<g>
<path d="M197.33,395.905c-54.065,0-98.051-43.98-98.051-98.04c0-54.065,43.985-98.05,98.051-98.05 c11.189,0,22.169,1.875,32.632,5.571c3.972,1.403,6.638,5.144,6.669,9.355c0.24,32.773,21.16,62.115,52.055,73.013 c3.846,1.356,6.482,4.913,6.664,8.986c0.016,0.363,0.02,0.744,0.02,1.125C295.369,351.924,251.389,395.905,197.33,395.905z M197.33,219.815c-43.037,0-78.051,35.013-78.051,78.05c0,43.031,35.014,78.04,78.051,78.04c41.006,0,74.727-31.79,77.81-72.02 c-32.749-14.438-55.187-45.902-58.172-81.578C210.59,220.652,204.009,219.815,197.33,219.815z" fill="#444B54"/>
</g>
<g>
<path d="M314.67,312.185c-11.196,0-22.179-1.875-32.642-5.571c-38.758-13.671-65.021-50.45-65.396-91.552 c-0.011-0.305-0.014-0.616-0.014-0.917c0-54.065,43.985-98.05,98.051-98.05s98.051,43.985,98.051,98.05 C412.721,268.205,368.735,312.185,314.67,312.185z M314.67,136.095c-43.037,0-78.051,35.013-78.051,78.05l0.001,0.216 c0.008,0.153,0.01,0.228,0.011,0.381c0.24,32.773,21.159,62.115,52.055,73.013c8.323,2.94,17.063,4.431,25.984,4.431 c43.037,0,78.051-35.009,78.051-78.04C392.721,171.108,357.707,136.095,314.67,136.095z" fill="#444B54"/>
</g>
<g>
<path d="M167.055,335.666c-2.56,0-5.118-0.976-7.071-2.929c-3.905-3.905-3.905-10.237,0-14.142l51.779-51.778 c3.907-3.905,10.237-3.905,14.143,0s3.905,10.237,0,14.142l-51.779,51.778C172.173,334.689,169.613,335.666,167.055,335.666z" fill="#444B54"/>
</g>
<g>
<path d="M218.834,335.666c-2.56,0-5.118-0.976-7.071-2.929l-51.779-51.78c-3.905-3.905-3.905-10.237,0-14.142 c3.907-3.905,10.237-3.905,14.143,0l51.779,51.78c3.905,3.905,3.905,10.237,0,14.142 C223.952,334.689,221.393,335.666,218.834,335.666z" fill="#444B54"/>
</g>
<g>
<path d="M299.19,252.681c-0.291,0-0.582-0.013-0.873-0.038c-2.944-0.258-5.623-1.805-7.318-4.225l-23.02-32.866 c-3.169-4.523-2.07-10.759,2.453-13.928c4.523-3.168,10.76-2.07,13.928,2.454l16.187,23.109l45.554-45.526 c3.908-3.905,10.238-3.902,14.143,0.004s3.902,10.238-0.004,14.142l-53.98,53.947C304.375,251.636,301.829,252.681,299.19,252.681 z" fill="#444B54"/>
</g>
<g>
<path d="M285.369,297.865c0,48.62-39.42,88.04-88.039,88.04c-48.631,0-88.051-39.42-88.051-88.04 c0-48.63,39.42-88.05,88.051-88.05c10.27,0,20.131,1.76,29.301,5c0.279,38.06,24.709,70.37,58.729,82.37 C285.369,297.405,285.369,297.635,285.369,297.865z" fill="transparent"/>
<path d="M197.33,395.905c-54.065,0-98.051-43.98-98.051-98.04c0-54.065,43.985-98.05,98.051-98.05 c11.189,0,22.169,1.875,32.632,5.571c3.972,1.403,6.638,5.144,6.669,9.355c0.24,32.773,21.16,62.115,52.055,73.013 c3.846,1.356,6.482,4.913,6.664,8.986c0.016,0.363,0.02,0.744,0.02,1.125C295.369,351.924,251.389,395.905,197.33,395.905z M197.33,219.815c-43.037,0-78.051,35.013-78.051,78.05c0,43.031,35.014,78.04,78.051,78.04c41.006,0,74.727-31.79,77.81-72.02 c-32.749-14.438-55.187-45.902-58.172-81.578C210.59,220.652,204.009,219.815,197.33,219.815z" fill="#444B54"/>
</g>
<g>
<path d="M402.721,214.145c0,48.62-39.43,88.04-88.051,88.04c-10.279,0-20.141-1.76-29.311-5 c-34.02-12-58.449-44.31-58.729-82.37c-0.012-0.22-0.012-0.45-0.012-0.67c0-48.63,39.422-88.05,88.051-88.05 C363.291,126.095,402.721,165.515,402.721,214.145z" fill="transparent"/>
<path d="M314.67,312.185c-11.196,0-22.179-1.875-32.642-5.571c-38.758-13.671-65.021-50.45-65.396-91.552 c-0.011-0.305-0.014-0.616-0.014-0.917c0-54.065,43.985-98.05,98.051-98.05s98.051,43.985,98.051,98.05 C412.721,268.205,368.735,312.185,314.67,312.185z M314.67,136.095c-43.037,0-78.051,35.013-78.051,78.05l0.001,0.216 c0.008,0.153,0.01,0.228,0.011,0.381c0.24,32.773,21.159,62.115,52.055,73.013c8.323,2.94,17.063,4.431,25.984,4.431 c43.037,0,78.051-35.009,78.051-78.04C392.721,171.108,357.707,136.095,314.67,136.095z" fill="#444B54"/>
</g>
<g>
<path d="M167.055,335.666c-2.56,0-5.118-0.976-7.071-2.929c-3.905-3.905-3.905-10.237,0-14.142l51.779-51.778 c3.907-3.905,10.237-3.905,14.143,0s3.905,10.237,0,14.142l-51.779,51.778C172.173,334.689,169.613,335.666,167.055,335.666z" fill="#444B54"/>
</g>
<g>
<path d="M218.834,335.666c-2.56,0-5.118-0.976-7.071-2.929l-51.779-51.78c-3.905-3.905-3.905-10.237,0-14.142 c3.907-3.905,10.237-3.905,14.143,0l51.779,51.78c3.905,3.905,3.905,10.237,0,14.142 C223.952,334.689,221.393,335.666,218.834,335.666z" fill="#444B54"/>
</g>
<g>
<path d="M299.19,252.681c-0.291,0-0.582-0.013-0.873-0.038c-2.944-0.258-5.623-1.805-7.318-4.225l-23.02-32.866 c-3.169-4.523-2.07-10.759,2.453-13.928c4.523-3.168,10.76-2.07,13.928,2.454l16.187,23.109l45.554-45.526 c3.908-3.905,10.238-3.902,14.143,0.004s3.902,10.238-0.004,14.142l-53.98,53.947C304.375,251.636,301.829,252.681,299.19,252.681 z" fill="#444B54"/>
</g>
</g>
</svg>
</template>
<script lang="ts">
export default {
name: 'FeedbackIcon',
props: {
customClass: { default: 'w-8 h-8', type: String },
viewBox: { default: '0 0 512 512', type: String }
}
}
</script>
2 changes: 1 addition & 1 deletion webapp/src/assets/svg/InfoIcon.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
fill="currentColor"
:class="customClass"
:viewBox="viewBox"
stroke="currentColor"
Expand Down
Loading

0 comments on commit 921fe05

Please sign in to comment.