UNPKG

federer

Version:

Experiments in asynchronous federated learning and decentralized learning

134 lines 5.76 kB
/// <reference types="node" /> import * as http from "http"; import * as https from "https"; import * as io from "socket.io"; import { Logger } from "winston"; import { ClientToServerMessages, DownloadMessage, MetadataMessage, RoundSummary, SerializedWeights, ServerToClientMessages, Weights, ServerStartCommonOptions } from "../common"; import { ClientPool } from "./utils/ClientPool"; import { Instrumentation } from "./utils/Instrumentation"; /** Base interface for round states in an FL algorithm. */ export interface FLRoundState { /** * The current round number. * * All implementations need to advance in rounds. This is necessary for our * evaluation and visualization features. */ roundNumber: number; } /** Mapping of event names to event listener callback types. */ export interface FLServerEvents { /** When the round ends, a summary of what happened in the round. */ roundEnd: (summary: RoundSummary) => void; } /** * Abstract base class for a Federated Learning aggregation server. * * This abstract class defines the basic interface that all servers should * respect; most notably, servers should expose an event emitter that informs * code outside of this class of certain server events. * * The class also does some basic bookkeeping. For instance, it maintains * metadata that clients have sent when authenticating, as well as the set of * clients that are ready to train, and some statistics on how the FL process is * advancing. * * Finally, the class offers a few utility methods that subclasses can use. */ export declare abstract class FLServer<RoundState extends FLRoundState = FLRoundState, StartOptions extends ServerStartCommonOptions = ServerStartCommonOptions> { protected readonly options: StartOptions; protected readonly logger: Logger; /** socket.io server used for communicating with clients. */ protected readonly server: io.Server<ClientToServerMessages, ServerToClientMessages>; /** Event emitter notifying outside code of FL events. */ readonly events: import("nanoevents").Emitter<FLServerEvents>; /** Current round state. */ protected currentRound: RoundState; /** * Mapping of socket IDs to metadata about the client represented by this * socket ID. * * The metadata is collected from the clients, which send it through socket.io * when connecting to the server. Note that clients are not considered "ready" * for training until they have sent their metadata. */ private readonly clientsMetadata; /** Client pool, keeping track of ready clients. */ protected readonly clientPool: ClientPool; /** Timer used for round summaries. */ private readonly timer; /** Number of epochs that have been aggregated so far */ private numberEpochs; /** Number of upload messages received so far. */ private numberUploads; /** Helper class to instrument various metrics on the server. */ protected readonly instrumentation: Instrumentation; constructor(server: http.Server | https.Server, initialWeights: Weights, options: StartOptions, logger: Logger); terminate(): void; /** * Whether the FL server implementation expects clients to upload with updates * as full weights (`false`) or as deltas of the change (`true`). * * If a client declares that it will upload the opposite of what the server * expects, an assertion error will be thrown on the server. */ protected abstract readonly expectDeltaUpdates: boolean; /** * Returns the initial round state at round 0. * * @param initialWeights Weights to initialize the state with */ protected abstract getInitialRoundState(initialWeights: Weights): RoundState; /** * Registers listeners to react to events on `this.server`. * * Subclasses are not meant to call this method (doing so could register * listeners twice), so this is marked as private. */ private registerServerListeners; /** * Registers listeners to react to events on the given `socket`. * * Subclasses overriding this method should first call * `super.registerSocketListeners(socket)`. * * @param socket Socket to a client */ protected registerSocketListeners(socket: io.Socket<ClientToServerMessages, ServerToClientMessages>): void; /** Number of currently connected and ready clients. */ protected get numberClients(): number; /** * Readonly map of socket IDs to the metadata we keep about this node. */ protected get metadata(): ReadonlyMap<string, Readonly<MetadataMessage>>; private registerMetadata; private logDisconnect; /** * Gets the client metadata for a socket, or fails if we do not have metadata * for that socket. */ protected getMetadata(socketId: string): Readonly<MetadataMessage>; /** * Returns the socket with ID `id`. * @throws if no socket with ID `id` is connected */ protected getSocketWithID(id: string): io.Socket; /** * Sends a {@link DownloadMessage} to a list of clients * * @param clients List of clients to send to */ protected sendDownloadMessage(clients: io.Socket[], message: DownloadMessage): void; /** * Emit the round summary to the coordinator. */ protected emitRoundSummary(filename: string, finishedRoundNumber: number, serializedWeights: SerializedWeights): void; private createRoundSummary; /** * Given a unique name for the weights, returns the full filepath to save * weights to. */ protected weightsFilepath(name: string): string; private shouldStartTimer; } //# sourceMappingURL=FLServer.d.ts.map