Skip to content

Commit bcfd86e

Browse files
committed
feat: chat session response prefix
1 parent 8145c94 commit bcfd86e

File tree

2 files changed

+52
-3
lines changed

2 files changed

+52
-3
lines changed

src/evaluator/LlamaChatSession/LlamaChatSession.ts

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,14 @@ export type LLamaChatPromptOptions<Functions extends ChatSessionModelFunctions |
148148
*/
149149
trimWhitespaceSuffix?: boolean,
150150

151+
/**
152+
* Force a given text prefix to be the start of the model response, to make the model follow a specific path.
153+
*
154+
* May cause some models to not use the given functions in some scenarios where they would have been used otherwise,
155+
* so avoid using it together with function calling if you notice unexpected behavior.
156+
*/
157+
responsePrefix?: string,
158+
151159
/**
152160
* See the parameter `evaluationPriority` on the `LlamaContextSequence.evaluate()` function for more information.
153161
*/
@@ -403,6 +411,7 @@ export class LlamaChatSession {
403411
seed,
404412
grammar,
405413
trimWhitespaceSuffix = false,
414+
responsePrefix,
406415
repeatPenalty,
407416
tokenBias,
408417
customStopTriggers
@@ -415,7 +424,7 @@ export class LlamaChatSession {
415424
maxParallelFunctionCalls: maxParallelFunctionCalls as undefined,
416425

417426
onTextChunk, onToken, signal, stopOnAbortSignal, maxTokens, temperature, minP, topK, topP, seed, grammar, trimWhitespaceSuffix,
418-
repeatPenalty, tokenBias, customStopTriggers
427+
responsePrefix, repeatPenalty, tokenBias, customStopTriggers
419428
});
420429

421430
return responseText;
@@ -441,6 +450,7 @@ export class LlamaChatSession {
441450
seed,
442451
grammar,
443452
trimWhitespaceSuffix = false,
453+
responsePrefix,
444454
repeatPenalty,
445455
tokenBias,
446456
customStopTriggers,
@@ -467,17 +477,30 @@ export class LlamaChatSession {
467477
? undefined
468478
: appendUserMessageToChatHistory(lastEvaluation?.contextWindow, prompt);
469479

480+
const resolvedResponsePrefix = (responsePrefix != null && responsePrefix !== "")
481+
? responsePrefix
482+
: undefined;
483+
470484
newChatHistory.push({
471485
type: "model",
472-
response: []
486+
response: resolvedResponsePrefix != null
487+
? [resolvedResponsePrefix]
488+
: []
473489
});
474490

475491
if (newContextWindowChatHistory != null)
476492
newContextWindowChatHistory.push({
477493
type: "model",
478-
response: []
494+
response: resolvedResponsePrefix != null
495+
? [resolvedResponsePrefix]
496+
: []
479497
});
480498

499+
if (resolvedResponsePrefix != null) {
500+
safeEventCallback(onToken)?.(this.model.tokenize(resolvedResponsePrefix));
501+
safeEventCallback(onTextChunk)?.(resolvedResponsePrefix);
502+
}
503+
481504
// eslint-disable-next-line no-constant-condition
482505
while (true) {
483506
const functionCallsAndResults: Array<Promise<null | {

test/modelDependent/llama3/chatSession.test.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,32 @@ describe("llama 3", () => {
107107
});
108108
expect(completion).to.eql(" it is.");
109109
});
110+
test("using response prefix", {timeout: 1000 * 60 * 60 * 2}, async () => {
111+
const modelPath = await getModelFile("Meta-Llama-3-8B-Instruct-Q4_K_M.gguf");
112+
const llama = await getTestLlama();
113+
114+
const model = await llama.loadModel({
115+
modelPath
116+
});
117+
const context = await model.createContext({
118+
contextSize: 2048
119+
});
120+
const chatSession = new LlamaChatSession({
121+
contextSequence: context.getSequence()
122+
});
123+
124+
expect(chatSession.chatWrapper).to.be.an.instanceof(Llama3ChatWrapper);
125+
126+
const prompt = "Describe the appearance of a llama";
127+
const responsePrefix = "Of course! A llama is";
128+
const res = await chatSession.prompt(prompt, {
129+
responsePrefix,
130+
maxTokens: 10
131+
});
132+
133+
expect(res.startsWith(responsePrefix)).to.eql(true);
134+
expect(res).toMatchInlineSnapshot('"Of course! A llama is a domesticated mammal that belongs to the camel"');
135+
});
110136

111137
// disabled due to getting timeout in the CI due to taking too long
112138
test.skip("context shift works correctly", {timeout: 1000 * 60 * 60 * 2}, async () => {

0 commit comments

Comments
 (0)