async function main()

in packages/gguf/scripts/generate-llm.ts [126:259]


async function main() {
	const cppSources = await Promise.all(
		SOURCE_CPP_URLS.map(async (url) => {
			const res = await fetch(url);
			return await res.text();
		})
	);
	const cppSource = cppSources.join("\n");

	/////////////////////////////////////
	// extract list of all architectures
	const archList: Arch[] = [];
	const RE_ARCH_NAME = /LLM_ARCH_[A-Z0-9_]+/;
	const matchedArchList = cppSource.match(/LLM_ARCH_NAMES = (?<names>[^;]+)/)?.groups?.names.split("\n");
	if (!matchedArchList?.length) {
		throw new Error("LLM_ARCH_NAMES is empty");
	}
	for (const line of matchedArchList) {
		const matched = line.match(/(?<cppConst>LLM_ARCH_[A-Z0-9_]+),\s+"(?<name>.+?)"/);
		if (matched?.groups && !matched.groups.name.match(/unknown/)) {
			archList.push({
				cppConst: matched.groups.cppConst,
				name: matched.groups.name,
				tsName: snakeToPascal(matched.groups.cppConst.replace("LLM_", "")),
				tensorNames: [],
				hparams: [],
			});
		}
	}

	/////////////////////////////////////
	// extract map constant name to kv name
	// for example: LLM_KV_ATTENTION_LAYERNORM_RMS_EPS ==> "%s.attention.layer_norm_rms_epsilon"
	const constToKVName: { [cppConst: string]: string } = {};
	const matchedKVList = cppSource.match(/LLM_KV_NAMES = (?<names>[^;]+)/)?.groups?.names.split("\n");
	if (!matchedKVList?.length) {
		throw new Error("LLM_KV_NAMES is empty");
	}
	for (const line of matchedKVList) {
		const matched = line.match(/(?<cppConst>LLM_KV_[A-Z0-9_]+)[,\s]+"(?<name>.+?)"/);
		if (matched?.groups) {
			constToKVName[matched.groups.cppConst] = matched.groups.name;
		}
	}
	console.log("constToKVName", constToKVName);

	/////////////////////////////////////
	// extract list of tensor names based on architecture
	// TODO: unused for now
	const matchedTensorList = cppSource.match(/LLM_TENSOR_NAMES = (?<names>[^;]+)/)?.groups?.names.split("\n");
	if (!matchedTensorList?.length) {
		throw new Error("LLM_TENSOR_NAMES is empty");
	}
	let currCppConst = "";
	for (const line of matchedTensorList) {
		// check if current line has LLM_ARCH_*
		const cppConst = line.match(RE_ARCH_NAME)?.[0];
		if (cppConst) {
			currCppConst = cppConst;
			continue;
		}
		// check if current line has LLM_TENSOR_*
		const tensorMatched = line.match(/LLM_TENSOR_[A-Z0-9_]+[,\s]+"(?<name>.+?)"/);
		if (tensorMatched?.groups) {
			const arch = archList.find((a) => a.cppConst === currCppConst);
			if (arch) arch.tensorNames.push(tensorMatched.groups.name);
		}
	}

	/////////////////////////////////////
	// extract list of hyper params based on architecture
	let insideLoadHParamsFn = false;
	currCppConst = "";
	for (const line of cppSource.split("\n")) {
		// check if current line is function llama_model::load_hparams()
		if (line.startsWith("void llama_model::load_hparams")) {
			insideLoadHParamsFn = true;
		}
		if (!insideLoadHParamsFn) {
			continue;
		}
		// check if current line has LLM_ARCH_*
		const RE_CASE = new RegExp(`case (${RE_ARCH_NAME.source})`);
		const cppConst = line.match(RE_CASE)?.[1];
		if (cppConst) {
			currCppConst = cppConst;
			continue;
		}
		// check if current line has get_key(...)
		const keyConst = line.match(/LLM_KV_[A-Z0-9_]+/)?.[0];
		if (keyConst) {
			const arch = archList.find((a) => a.cppConst === currCppConst);
			if (arch) {
				arch.hparams.push(keyConst);
			}
		}
		// check if current line is end-of-function
		if (line === "}") {
			break;
		}
	}

	/////////////////////////////////////
	// write result to file
	const content = [
		DEST_COMMON_SOURCE,
		"export const LLM_ARCHITECTURES = [",
		...archList.map((a) => `\t${JSON.stringify(a.name)},`),
		"] as const;",
		"type LLMArchitecture = (typeof LLM_ARCHITECTURES)[number];",
		...archList.map((a) => {
			let code = `export type ${a.tsName} = TransformerLLMBase<${JSON.stringify(a.name)}>`;
			if (a.hparams.length) {
				code += [
					" & {",
					...a.hparams.map((k) => {
						if (!KV_TYPE[k]) {
							throw new Error(`Cannot find type definition of ${k}`);
						}
						return `\t${JSON.stringify(constToKVName[k].replace("%s", a.name))}: ${KV_TYPE[k]},`;
					}),
					"};",
				].join("\n");
			} else {
				code += ";";
			}
			return code;
		}),
		"",
		`export type TransformerLLM = ${archList.map((a) => a.tsName).join(" | ")};`,
	].join("\n");

	writeFileSync(DEST_FILE_PATH, content);
}