Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion discojs/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export type {
ModelCardInfo,
BatchLogs,
HellaSwagDataset,
GenerationConfig,
} from "./models/index.js";

export {
Expand All @@ -50,6 +51,7 @@ export {
ONNXModel,
HELLASWAG_URL,
evaluate_hellaswag,
DefaultGenerationConfig,
} from "./models/index.js";
export type { GPTConfig, HellaSwagExample } from "./models/index.js";

Expand All @@ -69,7 +71,7 @@ export {
export type { TaskProvider } from "./task/index.js";

export type { DataType, Network, DataFormat } from "./types/index.js";
export { dataTypeValues } from "./types/index.js";
export { dataTypeValues, isDataType } from "./types/index.js";

export { extractColumn } from "./processing/index.js";

Expand Down
19 changes: 19 additions & 0 deletions discojs/src/models/generation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
export interface GenerationConfig {
// take random token weighted by its probability
// If false, predict the token with the highest probability.
doSample: boolean;
// the generation temperature (higher means more randomness).
// Set to 0 for greedy decoding.
temperature: number;
// only consider the topk most likely tokens for sampling.
// used if doSample is true.
topk: number;
// optional random seed for sampling.
seed?: number;
}

export const DefaultGenerationConfig: GenerationConfig = {
temperature: 1.0,
doSample: true,
topk: 50,
};
23 changes: 1 addition & 22 deletions discojs/src/models/implementations/gpt/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export const DefaultGPTConfig: Required<GPTConfig> = {
nLayer: 3,
nHead: 3,
nEmbd: 48,
seed: Math.random(),
seed: Math.floor(Math.random() * Number.MAX_SAFE_INTEGER),
};

export type ModelSize = {
Expand All @@ -73,24 +73,3 @@ export function getModelSizes(modelType: GPTModelType): Required<ModelSize> {
return { nLayer: 3, nHead: 3, nEmbd: 48 };
}
}

export interface GenerationConfig {
// take random token weighted by its probability
// If false, predict the token with the highest probability.
doSample: boolean;
// the generation temperature (higher means more randomness).
// Set to 0 for greedy decoding.
temperature: number;
// only consider the topk most likely tokens for sampling.
// used if doSample is true.
topk: number;
// random seed for sampling.
seed: number;
}

export const DefaultGenerationConfig: Required<GenerationConfig> = {
temperature: 1.0,
doSample: false,
seed: Math.random(),
topk: 50,
};
2 changes: 1 addition & 1 deletion discojs/src/models/implementations/gpt/gpt.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ describe("gpt-tfjs", () => {
const inputTokens = tokenizer.tokenize(data);

const outputToken = (
await model.predict(List.of(inputTokens), { seed })
await model.predict(List.of(inputTokens), { seed, doSample: false })
).first();
if (outputToken === undefined) throw new Error("empty prediction");
const output = tokenizer.decode([outputToken]);
Expand Down
18 changes: 8 additions & 10 deletions discojs/src/models/implementations/gpt/gpt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,10 @@ import { EpochLogs } from "#models/logs";
import { Model } from "#models/model";
import { GPTModel } from "#models/implementations/gpt/model";
import evaluate from "#models/implementations/gpt/evaluate";
import {
DefaultGPTConfig,
DefaultGenerationConfig,
} from "#models/implementations/gpt/config";
import type {
GPTConfig,
GenerationConfig,
} from "#models/implementations/gpt/config";
import { DefaultGPTConfig } from "#models/implementations/gpt/config";
import type { GPTConfig } from "#models/implementations/gpt/config";
import { DefaultGenerationConfig } from "#models/generation";
import type { GenerationConfig } from "#models/generation";

const debug = createDebug("discojs:models:gpt");

Expand Down Expand Up @@ -199,7 +195,9 @@ export class GPT extends Model<"text"> {
logits
.slice([logits.shape[0] - 1])
.squeeze<tf.Tensor1D>([0])
.div<tf.Tensor1D>(config.temperature)
.div<tf.Tensor1D>(
config.doSample && config.temperature > 0 ? config.temperature : 1,
)
.softmax(),
);
logits.dispose();
Expand Down Expand Up @@ -263,7 +261,7 @@ export class GPT extends Model<"text"> {
return this.model;
}

[Symbol.dispose](): void {
dispose(): void {
if (this.model.optimizer !== undefined) {
this.model.optimizer.dispose();
}
Expand Down
2 changes: 2 additions & 0 deletions discojs/src/models/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ export { Model } from "./model.js";
export type { BatchLogs, ValidationMetrics } from "./logs.js";
export { EpochLogs } from "./logs.js";
export { Tokenizer } from "./tokenizer.js";
export { DefaultGenerationConfig } from "./generation.js";
export type { GenerationConfig } from "./generation.js";

export type {
GPTConfig,
Expand Down
6 changes: 5 additions & 1 deletion discojs/src/models/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,5 +54,9 @@ export abstract class Model<D extends DataType> implements Disposable {
* }
* Calling f() will call the model's dispose method when exiting the function.
*/
abstract [Symbol.dispose](): void;
[Symbol.dispose](): void {
this.dispose();
}

abstract dispose(): void;
}
2 changes: 1 addition & 1 deletion discojs/src/models/onnx.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { describe, expect, it } from "vitest";
import { List } from "immutable";
import { AutoTokenizer } from "@xenova/transformers";
import { ONNXModel } from "#models/onnx";
import { DefaultGenerationConfig } from "#models/implementations/gpt/config";
import { DefaultGenerationConfig } from "#models/generation";

describe("ONNXModel.predict", { timeout: 50_000 }, () => {
it("should generate the next token ID from a prompt", async () => {
Expand Down
10 changes: 5 additions & 5 deletions discojs/src/models/onnx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import { List } from "immutable";
import type { WeightsContainer } from "#weights/index";
import type { Batched } from "#dataset/index";
import type { DataFormat } from "#types/index";
import type { GenerationConfig as TFJSGenerationConfig } from "#models/implementations/gpt/config";
import { Model } from "#models/model";
import { DefaultGenerationConfig } from "#models/implementations/gpt/config";
import { DefaultGenerationConfig } from "#models/generation";
import type { GenerationConfig } from "#models/generation";

export class ONNXModel extends Model<"text"> {
readonly datatype = "text" as const;
Expand All @@ -30,7 +30,7 @@ export class ONNXModel extends Model<"text"> {

override async predict(
batch: Batched<DataFormat.ModelEncoded["text"][0]>,
options?: Partial<TFJSGenerationConfig>,
options?: Partial<GenerationConfig>,
): Promise<Batched<DataFormat.ModelEncoded["text"][1]>> {
const config = Object.assign({}, DefaultGenerationConfig, options);

Expand All @@ -43,7 +43,7 @@ export class ONNXModel extends Model<"text"> {

async #predictSingle(
tokens: DataFormat.ModelEncoded["text"][0],
config: TFJSGenerationConfig,
config: GenerationConfig,
): Promise<DataFormat.ModelEncoded["text"][1]> {
const contextLength =
(this.model.config as { max_position_embeddings?: number })
Expand Down Expand Up @@ -125,7 +125,7 @@ export class ONNXModel extends Model<"text"> {
throw new Error("Weights setting not supported in ONNX models");
}

[Symbol.dispose](): void {
dispose() {
// Dispose of the model to free up memory
void this.model.dispose();
}
Expand Down
2 changes: 1 addition & 1 deletion discojs/src/models/tfjs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ export class TFJS<D extends "image" | "tabular"> extends Model<D> {
return [this.datatype, await ret];
}

[Symbol.dispose](): void {
dispose(): void {
this.model.dispose();
}

Expand Down
7 changes: 7 additions & 0 deletions discojs/src/types/datatype.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,9 @@
export const dataTypeValues = ["image", "tabular", "text"] as const;

export type DataType = (typeof dataTypeValues)[number];

export function isDataType(x: unknown): x is DataType {
return (
typeof x == "string" && (dataTypeValues as readonly string[]).includes(x)
);
}
2 changes: 1 addition & 1 deletion discojs/src/types/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// eslint-disable-next-line no-restricted-syntax -- namespace re-export acceptable here
export * as DataFormat from "./data_format.js";

export { dataTypeValues } from "./datatype.js";
export { dataTypeValues, isDataType } from "./datatype.js";
export type { DataType } from "./datatype.js";

export type { Network } from "./network.js";
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"scripts": {
"lint": "eslint",
"format:check": "prettier -c .",
"format:fix": "prettier -w .",
"format:fix": "prettier -w --list-different .",
"check_cycles": "dpdm --tsconfig discojs/tsconfig.lib.json --circular --exit-code circular:1 'discojs/src/**/*.ts'"
},
"dependencies": {
Expand Down
2 changes: 1 addition & 1 deletion server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
},
"scripts": {
"watch": "nodemon --ext ts --ignore dist --watch ../discojs-node/dist --watch . --exec pnpm run",
"start": "node dist/main.js",
"start": "pnpm run build && node dist/main.js",
"build": "tsc --build",
"test": "cd .. && vitest --run --project=server"
},
Expand Down
5 changes: 4 additions & 1 deletion webapp/.env.development
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
VITE_SERVER_URL=http://localhost:8080
# When set to localhost, the server host is derived from whichever
# host serves the webapp (localhost, or your LAN IP when running `vite --host`).
VITE_SERVER_URL=localhost
VITE_SERVER_PORT=8080
Loading