First upload version 0.0.1

This commit is contained in:
Neyra
2026-02-05 15:27:49 +08:00
commit 8e9b7201ed
4182 changed files with 593136 additions and 0 deletions

View File

@@ -0,0 +1,11 @@
import { LlamaGrammar } from "../../LlamaGrammar.js";
import { ChatModelFunctions } from "../../../types.js";
import { ChatWrapper } from "../../../ChatWrapper.js";
import { Llama } from "../../../bindings/Llama.js";
export declare class FunctionCallNameGrammar<const Functions extends ChatModelFunctions> extends LlamaGrammar {
private readonly _functions;
private readonly _chatWrapper;
constructor(llama: Llama, functions: Functions, chatWrapper: ChatWrapper);
parseFunctionName(generatedFunctionName: string): keyof Functions & string;
private _validateFunctions;
}

View File

@@ -0,0 +1,55 @@
import { LlamaGrammar } from "../../LlamaGrammar.js";
import { LlamaText } from "../../../utils/LlamaText.js";
import { GbnfGrammarGenerator } from "../../../utils/gbnfJson/GbnfGrammarGenerator.js";
import { GbnfGrammar } from "../../../utils/gbnfJson/terminals/GbnfGrammar.js";
import { GbnfOr } from "../../../utils/gbnfJson/terminals/GbnfOr.js";
import { GbnfVerbatimText } from "../../../utils/gbnfJson/terminals/GbnfVerbatimText.js";
import { LlamaFunctionCallValidationError } from "./LlamaFunctionCallValidationError.js";
export class FunctionCallNameGrammar extends LlamaGrammar {
_functions;
_chatWrapper;
constructor(llama, functions, chatWrapper) {
const grammar = getGbnfGrammarForFunctionName(functions, chatWrapper);
super(llama, {
grammar,
stopGenerationTriggers: [LlamaText("\n")],
trimWhitespaceSuffix: true
});
this._functions = functions;
this._chatWrapper = chatWrapper;
this._validateFunctions();
}
parseFunctionName(generatedFunctionName) {
if (this._chatWrapper.settings.functions.call.optionalPrefixSpace && generatedFunctionName[0] === " ")
generatedFunctionName = generatedFunctionName.slice(1);
const newlineIndex = generatedFunctionName.indexOf("\n");
const functionName = generatedFunctionName.slice(0, newlineIndex < 0
? generatedFunctionName.length
: newlineIndex);
if (!Object.hasOwn(this._functions, functionName))
throw new LlamaFunctionCallValidationError(`Function name "${functionName}" is not in the supplied functions object`, this._functions, this._chatWrapper, generatedFunctionName);
return functionName;
}
_validateFunctions() {
for (const functionsName of Object.keys(this._functions)) {
if (functionsName.includes(" ") || functionsName.includes("\n") || functionsName.includes("\t"))
throw new Error(`Function name "${functionsName}" contains spaces, new lines or tabs`);
else if (functionsName === "")
throw new Error("Function name cannot be an empty string");
}
}
}
function getGbnfGrammarForFunctionName(functions, chatWrapper) {
const grammarGenerator = new GbnfGrammarGenerator();
const functionNameGrammars = [];
for (const functionName of Object.keys(functions))
functionNameGrammars.push(new GbnfVerbatimText(functionName));
const callGrammar = new GbnfOr(functionNameGrammars);
const rootTerminal = new GbnfGrammar([
...(chatWrapper.settings.functions.call.optionalPrefixSpace ? ["[ ]?"] : []),
callGrammar.resolve(grammarGenerator)
]);
const rootGrammar = rootTerminal.getGrammar();
return grammarGenerator.generateGbnfFile(rootGrammar + " [\\n]");
}
//# sourceMappingURL=FunctionCallNameGrammar.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"FunctionCallNameGrammar.js","sourceRoot":"","sources":["../../../../src/evaluator/LlamaChat/utils/FunctionCallNameGrammar.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,16 @@
import { LlamaGrammar } from "../../LlamaGrammar.js";
import { ChatModelFunctions } from "../../../types.js";
import { ChatWrapper } from "../../../ChatWrapper.js";
import { Llama } from "../../../bindings/Llama.js";
import { GbnfJsonSchema } from "../../../utils/gbnfJson/types.js";
export declare class FunctionCallParamsGrammar<const Functions extends ChatModelFunctions> extends LlamaGrammar {
private readonly _functions;
private readonly _chatWrapper;
private readonly _functionName;
private readonly _paramsSchema;
constructor(llama: Llama, functions: Functions, chatWrapper: ChatWrapper, functionName: string, paramsSchema: GbnfJsonSchema);
parseParams(callText: string): {
params: any;
raw: string;
};
}

View File

@@ -0,0 +1,45 @@
import { LlamaGrammar } from "../../LlamaGrammar.js";
import { LlamaText } from "../../../utils/LlamaText.js";
import { validateObjectAgainstGbnfSchema } from "../../../utils/gbnfJson/utils/validateObjectAgainstGbnfSchema.js";
import { GbnfGrammarGenerator } from "../../../utils/gbnfJson/GbnfGrammarGenerator.js";
import { getGbnfJsonTerminalForGbnfJsonSchema } from "../../../utils/gbnfJson/utils/getGbnfJsonTerminalForGbnfJsonSchema.js";
import { LlamaFunctionCallValidationError } from "./LlamaFunctionCallValidationError.js";
export class FunctionCallParamsGrammar extends LlamaGrammar {
_functions;
_chatWrapper;
_functionName;
_paramsSchema;
constructor(llama, functions, chatWrapper, functionName, paramsSchema) {
const grammar = getGbnfGrammarForFunctionParams(paramsSchema);
super(llama, {
grammar,
stopGenerationTriggers: [LlamaText("\n".repeat(4))],
trimWhitespaceSuffix: true
});
this._functions = functions;
this._chatWrapper = chatWrapper;
this._functionName = functionName;
this._paramsSchema = paramsSchema;
}
parseParams(callText) {
const endIndex = callText.lastIndexOf("\n".repeat(4));
if (endIndex < 0)
throw new LlamaFunctionCallValidationError(`Expected function call params for function "${this._functionName}" to end with stop generation trigger`, this._functions, this._chatWrapper, callText);
const paramsString = callText.slice(0, endIndex);
if (paramsString.trim().length === 0)
throw new LlamaFunctionCallValidationError(`Expected function call params for function "${this._functionName}" to not be empty`, this._functions, this._chatWrapper, callText);
const params = JSON.parse(paramsString);
validateObjectAgainstGbnfSchema(params, this._paramsSchema);
return {
params: params, // prevent infinite TS type instantiation
raw: paramsString
};
}
}
function getGbnfGrammarForFunctionParams(paramsSchema) {
const grammarGenerator = new GbnfGrammarGenerator();
const rootTerminal = getGbnfJsonTerminalForGbnfJsonSchema(paramsSchema, grammarGenerator);
const rootGrammar = rootTerminal.resolve(grammarGenerator, true);
return grammarGenerator.generateGbnfFile(rootGrammar + ` "${"\\n".repeat(4)}"`);
}
//# sourceMappingURL=FunctionCallParamsGrammar.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"FunctionCallParamsGrammar.js","sourceRoot":"","sources":["../../../../src/evaluator/LlamaChat/utils/FunctionCallParamsGrammar.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAC,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAC,SAAS,EAAC,MAAM,6BAA6B,CAAC;AACtD,OAAO,EAAC,+BAA+B,EAAC,MAAM,kEAAkE,CAAC;AAEjH,OAAO,EAAC,oBAAoB,EAAC,MAAM,iDAAiD,CAAC;AACrF,OAAO,EAAC,oCAAoC,EAAC,MAAM,uEAAuE,CAAC;AAI3H,OAAO,EAAC,gCAAgC,EAAC,MAAM,uCAAuC,CAAC;AAGvF,MAAM,OAAO,yBAAsE,SAAQ,YAAY;IAClF,UAAU,CAAY;IACtB,YAAY,CAAc;IAC1B,aAAa,CAAS;IACtB,aAAa,CAAiB;IAE/C,YAAmB,KAAY,EAAE,SAAoB,EAAE,WAAwB,EAAE,YAAoB,EAAE,YAA4B;QAC/H,MAAM,OAAO,GAAG,+BAA+B,CAAC,YAAY,CAAC,CAAC;QAE9D,KAAK,CAAC,KAAK,EAAE;YACT,OAAO;YACP,sBAAsB,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;YACnD,oBAAoB,EAAE,IAAI;SAC7B,CAAC,CAAC;QAEH,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;QAC5B,IAAI,CAAC,YAAY,GAAG,WAAW,CAAC;QAChC,IAAI,CAAC,aAAa,GAAG,YAAY,CAAC;QAClC,IAAI,CAAC,aAAa,GAAG,YAAY,CAAC;IACtC,CAAC;IAEM,WAAW,CAAC,QAAgB;QAC/B,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAEtD,IAAI,QAAQ,GAAG,CAAC;YACZ,MAAM,IAAI,gCAAgC,CACtC,+CAA+C,IAAI,CAAC,aAAa,uCAAuC,EACxG,IAAI,CAAC,UAAU,EACf,IAAI,CAAC,YAAY,EACjB,QAAQ,CACX,CAAC;QAEN,MAAM,YAAY,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;QAEjD,IAAI,YAAY,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;YAChC,MAAM,IAAI,gCAAgC,CACtC,+CAA+C,IAAI,CAAC,aAAa,mBAAmB,EACpF,IAAI,CAAC,UAAU,EACf,IAAI,CAAC,YAAY,EACjB,QAAQ,CACX,CAAC;QAEN,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QAExC,+BAA+B,CAAC,MAAM,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;QAE5D,OAAO;YACH,MAAM,EAAE,MAAa,EAAE,yCAAyC;YAChE,GAAG,EAAE,YAAY;SACpB,CAAC;IACN,CAAC;CACJ;AAED,SAAS,+BAA+B,CAAC,YAA4B;IACjE,MAAM,gBAAgB,GAAG,IAAI,oBAAoB,EAAE,CAAC;IACpD,MAAM,YAAY,GAAG,oCAAoC,CAAC,YAAY,EAAE,gBAAgB,CAAC,CAAC;IAC1F,MAAM,WAAW,GAAG,YAAY,CAAC,OAAO,CAAC,gBAAgB,EAAE,IAAI,CAAC,CAAC;IAEjE,OAAO,gBAAgB,CAAC,gBAAgB,CAAC,WAAW,GAAG,KAAK,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;AACpF,CAAC"}

View File

@@ -0,0 +1,8 @@
import { ChatModelFunctions } from "../../../types.js";
import { ChatWrapper } from "../../../ChatWrapper.js";
export declare class LlamaFunctionCallValidationError<const Functions extends ChatModelFunctions> extends Error {
readonly functions: Functions;
readonly chatWrapper: ChatWrapper;
readonly callText: string;
constructor(message: string, functions: Functions, chatWrapper: ChatWrapper, callText: string);
}

View File

@@ -0,0 +1,12 @@
export class LlamaFunctionCallValidationError extends Error {
functions;
chatWrapper;
callText;
constructor(message, functions, chatWrapper, callText) {
super(message);
this.functions = functions;
this.chatWrapper = chatWrapper;
this.callText = callText;
}
}
//# sourceMappingURL=LlamaFunctionCallValidationError.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"LlamaFunctionCallValidationError.js","sourceRoot":"","sources":["../../../../src/evaluator/LlamaChat/utils/LlamaFunctionCallValidationError.ts"],"names":[],"mappings":"AAIA,MAAM,OAAO,gCAA6E,SAAQ,KAAK;IACnF,SAAS,CAAY;IACrB,WAAW,CAAc;IACzB,QAAQ,CAAS;IAEjC,YAAmB,OAAe,EAAE,SAAoB,EAAE,WAAwB,EAAE,QAAgB;QAChG,KAAK,CAAC,OAAO,CAAC,CAAC;QAEf,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/B,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC7B,CAAC;CACJ"}

View File

@@ -0,0 +1,16 @@
import { ChatHistoryItem, Tokenizer } from "../../../../types.js";
import { ChatWrapper } from "../../../../ChatWrapper.js";
export declare function eraseFirstResponseAndKeepFirstSystemChatContextShiftStrategy({ chatHistory, maxTokensCount, tokenizer, chatWrapper, lastShiftMetadata }: {
chatHistory: ChatHistoryItem[];
maxTokensCount: number;
tokenizer: Tokenizer;
chatWrapper: ChatWrapper;
lastShiftMetadata?: object | null;
}): Promise<{
chatHistory: ChatHistoryItem[];
metadata: CalculationMetadata;
}>;
type CalculationMetadata = {
removedCharactersNumber: number;
};
export {};

View File

@@ -0,0 +1,254 @@
import { isChatModelResponseFunctionCall, isChatModelResponseSegment } from "../../../../types.js";
import { findCharacterRemovalCountToFitChatHistoryInContext } from "../../../../utils/findCharacterRemovalCountToFitChatHistoryInContext.js";
import { truncateLlamaTextAndRoundToWords, truncateTextAndRoundToWords } from "../../../../utils/truncateTextAndRoundToWords.js";
import { LlamaText } from "../../../../utils/LlamaText.js";
export async function eraseFirstResponseAndKeepFirstSystemChatContextShiftStrategy({ chatHistory, maxTokensCount, tokenizer, chatWrapper, lastShiftMetadata }) {
let initialCharactersRemovalCount = 0;
if (isCalculationMetadata(lastShiftMetadata))
initialCharactersRemovalCount = lastShiftMetadata.removedCharactersNumber;
const { removedCharactersCount, compressedChatHistory } = await findCharacterRemovalCountToFitChatHistoryInContext({
chatHistory,
tokensCountToFit: maxTokensCount,
initialCharactersRemovalCount,
tokenizer,
chatWrapper,
failedCompressionErrorMessage: "Failed to compress chat history for context shift due to a too long prompt or system message that cannot be compressed without affecting the generation quality. " +
"Consider increasing the context size or shortening the long prompt or system message.",
compressChatHistory({ chatHistory, charactersToRemove, estimatedCharactersPerToken }) {
const res = chatHistory.map((item) => structuredClone(item));
let charactersLeftToRemove = charactersToRemove;
function compressFunctionCalls() {
for (let i = res.length - 1; i >= 0 && charactersLeftToRemove > 0; i--) {
const historyItem = res[i];
if (historyItem.type !== "model")
continue;
for (let t = historyItem.response.length - 1; t >= 0 && charactersLeftToRemove > 0; t--) {
const item = historyItem.response[t];
if (typeof item === "string" || item.type !== "functionCall")
continue;
if (item.rawCall == null)
continue;
const originalRawCallTokensLength = LlamaText.fromJSON(item.rawCall).tokenize(tokenizer, "trimLeadingSpace").length;
const newRawCallText = chatWrapper.generateFunctionCall(item.name, item.params);
const newRawCallTextTokensLength = newRawCallText.tokenize(tokenizer, "trimLeadingSpace").length;
if (newRawCallTextTokensLength < originalRawCallTokensLength) {
item.rawCall = newRawCallText.toJSON();
charactersLeftToRemove -= ((originalRawCallTokensLength - newRawCallTextTokensLength) * estimatedCharactersPerToken);
}
}
}
}
function removeHistoryThatLedToModelResponseAtIndex(index) {
let removedItems = 0;
for (let i = index - 1; i >= 0; i--) {
const historyItem = res[i];
if (historyItem == null)
continue;
if (historyItem.type === "model")
break; // stop removing history items if we reach another model response
if (i === 0 && historyItem.type === "system")
break; // keep the first system message
if (historyItem.type === "user" || historyItem.type === "system") {
const newText = truncateLlamaTextAndRoundToWords(LlamaText.fromJSON(historyItem.text), charactersLeftToRemove, undefined, false);
const newTextString = newText.toString();
const historyItemString = LlamaText.fromJSON(historyItem.text).toString();
if (newText.values.length === 0) {
res.splice(i, 1);
i++;
removedItems++;
charactersLeftToRemove -= historyItemString.length;
}
else if (newTextString.length < historyItemString.length) {
charactersLeftToRemove -= historyItemString.length - newTextString.length;
if (historyItem.type === "user")
historyItem.text = newText.toString();
else
historyItem.text = newText.toJSON();
}
}
else {
void historyItem;
}
}
return removedItems;
}
function compressHistoryThatLedToModelResponseAtIndex(index, keepTokensCount = 0) {
let removedItems = 0;
let promptStartIndex = undefined;
for (let i = index - 1; i >= 0; i--) {
const historyItem = res[i];
if (historyItem == null)
continue;
if (historyItem.type === "model") {
promptStartIndex = i + 1;
break;
}
if (i === 0 && historyItem.type === "system") {
promptStartIndex = i + 1;
break; // keep the first system message
}
}
if (promptStartIndex == null || promptStartIndex >= index)
return 0;
for (let i = promptStartIndex; i < index && charactersLeftToRemove > 0; i++) {
const historyItem = res[i];
if (historyItem == null || historyItem.type !== "user")
continue;
let removeChars = Math.min(charactersLeftToRemove, historyItem.text.length);
if (keepTokensCount > 0) {
removeChars -= Math.floor(keepTokensCount * estimatedCharactersPerToken);
if (removeChars < 0)
removeChars = 0;
keepTokensCount -= Math.min(keepTokensCount, Math.max(0, historyItem.text.length - removeChars) / estimatedCharactersPerToken);
}
const newText = truncateTextAndRoundToWords(historyItem.text, removeChars, undefined, false);
if (newText.length === 0) {
res.splice(i, 1);
i--;
index--;
removedItems++;
charactersLeftToRemove -= historyItem.text.length;
}
else {
charactersLeftToRemove -= historyItem.text.length - newText.length;
historyItem.text = newText;
}
}
return removedItems;
}
function removeEmptySegmentsFromModelResponse(modelResponse) {
const stack = [];
for (let t = 0; t < modelResponse.length && charactersLeftToRemove > 0; t++) {
const item = modelResponse[t];
const isLastItem = t === modelResponse.length - 1;
if (!isChatModelResponseSegment(item))
continue;
const type = item.segmentType;
const topStack = stack.at(-1);
if (topStack?.type === type) {
if (item.ended && item.text === "" && topStack.canRemove) {
modelResponse.splice(t, 1);
t--;
modelResponse.splice(topStack.startIndex, 1);
t--;
stack.pop();
}
else if (!item.ended && item.text === "" && !isLastItem) {
modelResponse.splice(t, 1);
t--;
}
else if (!item.ended && item.text !== "")
topStack.canRemove = false;
else if (item.ended)
stack.pop();
}
else if (!item.ended)
stack.push({
type,
startIndex: t,
canRemove: item.text === ""
});
}
}
function compressFirstModelResponse() {
for (let i = 0; i < res.length && charactersLeftToRemove > 0; i++) {
const historyItem = res[i];
const isLastHistoryItem = i === res.length - 1;
if (historyItem.type !== "model")
continue;
for (let t = 0; t < historyItem.response.length && charactersLeftToRemove > 0; t++) {
const item = historyItem.response[t];
const isLastText = t === historyItem.response.length - 1;
if (isLastHistoryItem && isLastText)
continue;
if (typeof item === "string") {
const newText = truncateTextAndRoundToWords(item, charactersLeftToRemove, undefined, true);
if (newText === "") {
historyItem.response.splice(t, 1);
t--;
charactersLeftToRemove -= item.length;
}
else if (newText.length < item.length) {
historyItem.response[t] = newText;
charactersLeftToRemove -= item.length - newText.length;
}
}
else if (isChatModelResponseFunctionCall(item)) {
historyItem.response.splice(t, 1);
t--;
const functionCallAndResultTokenUsage = chatWrapper.generateFunctionCallsAndResults([item], true)
.tokenize(tokenizer, "trimLeadingSpace").length;
charactersLeftToRemove -= functionCallAndResultTokenUsage * estimatedCharactersPerToken;
}
else if (isChatModelResponseSegment(item)) {
if (item.text !== "") {
const newText = truncateTextAndRoundToWords(item.text, charactersLeftToRemove, undefined, true);
if (newText === "" && item.ended) {
const emptySegmentTokenUsage = chatWrapper.generateModelResponseText([{ ...item, text: "" }], true)
.tokenize(tokenizer, "trimLeadingSpace").length;
historyItem.response.splice(t, 1);
t--;
charactersLeftToRemove -= item.text.length + emptySegmentTokenUsage * estimatedCharactersPerToken;
}
else {
charactersLeftToRemove -= item.text.length - newText.length;
item.text = newText;
}
}
}
else
void item;
}
removeEmptySegmentsFromModelResponse(historyItem.response);
if (historyItem.response.length === 0) {
// if the model response is removed from the history,
// the things that led to it are not important anymore
i -= removeHistoryThatLedToModelResponseAtIndex(i);
res.splice(i, 1);
i--;
}
}
}
function compressLastModelResponse(minCharactersToKeep = 60) {
const lastHistoryItem = res[res.length - 1];
if (lastHistoryItem == null || lastHistoryItem.type !== "model")
return;
const lastResponseItem = lastHistoryItem.response[lastHistoryItem.response.length - 1];
if (lastResponseItem == null || typeof lastResponseItem !== "string")
return;
compressHistoryThatLedToModelResponseAtIndex(res.length - 1, maxTokensCount / 4);
if (charactersLeftToRemove <= 0)
return;
const nextTextLength = Math.max(Math.min(lastResponseItem.length, minCharactersToKeep), lastResponseItem.length - charactersLeftToRemove);
const charactersToRemoveFromText = lastResponseItem.length - nextTextLength;
const newText = truncateTextAndRoundToWords(lastResponseItem, charactersToRemoveFromText, undefined, true);
if (newText.length < lastResponseItem.length) {
lastHistoryItem.response[lastHistoryItem.response.length - 1] = newText;
charactersLeftToRemove -= lastResponseItem.length - newText.length;
}
if (charactersLeftToRemove <= 0)
return;
compressHistoryThatLedToModelResponseAtIndex(res.length - 1);
}
compressFunctionCalls();
if (charactersLeftToRemove <= 0)
return res;
compressFirstModelResponse();
if (charactersLeftToRemove <= 0)
return res;
compressLastModelResponse();
return res;
}
});
const newMetadata = {
removedCharactersNumber: removedCharactersCount
};
return {
chatHistory: compressedChatHistory,
metadata: newMetadata
};
}
function isCalculationMetadata(metadata) {
return metadata != null && typeof metadata === "object" && typeof metadata.removedCharactersNumber === "number";
}
//# sourceMappingURL=eraseFirstResponseAndKeepFirstSystemChatContextShiftStrategy.js.map