Skip to content

Commit

Permalink
fix: max prompt length per model
Browse files Browse the repository at this point in the history
  • Loading branch information
mattzcarey committed Jul 24, 2023
1 parent f656a83 commit 413afe4
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 22 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "code-review-gpt",
"version": "0.0.25",
"version": "0.0.26",
"description": "Your AI code reviewer",
"bin": {
"code-review-gpt": "./dist/index.js"
Expand Down
19 changes: 18 additions & 1 deletion src/review/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,24 @@ Please summarise the review using 3 emojis.
export const signOff =
"#### Powered by [Code Review GPT](https://github.com/mattzcarey/code-review-gpt)";

export const maxPromptLength = 30000; //max is 8k tokens which is about 40k characters
export const modelInfo = [
{
model: "gpt4",
maxPromptLength: 21000, //8k tokens
},
{
model: "gpt-4-32k",
maxPromptLength: 90000, //32k tokens
},
{
model: "gpt-3.5-turbo",
maxPromptLength: 9000, //4k tokens
},
{
model: "gpt-3.5-turbo-16k",
maxPromptLength: 45000, //16k tokens
},
]; // Response needs about 1k tokens ~= 3k characters

export const supportedFiles = new Set([
".js",
Expand Down
7 changes: 5 additions & 2 deletions src/review/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { commentOnPR } from "./ci/commentOnPR";
import { askAI } from "./llm/askAI";
import { constructPromptsArray } from "./prompt/constructPrompt";
import { getFileNames } from "./prompt/getFileNames";
import { askAI } from "./llm/askAI";
import { getMaxPromptLength } from "./prompt/getMaxPromptLength";

interface ReviewArgs {
[x: string]: unknown;
Expand All @@ -14,8 +15,10 @@ export const review = async (yargs: ReviewArgs) => {
const isCi = yargs.ci;
const modelName = yargs.model as string;

const maxPromptLength = getMaxPromptLength(modelName);

const fileNames = await getFileNames(isCi);
const prompts = await constructPromptsArray(fileNames);
const prompts = await constructPromptsArray(fileNames, maxPromptLength);

const response = await askAI(prompts, modelName);

Expand Down
57 changes: 39 additions & 18 deletions src/review/prompt/constructPrompt.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import {
instructionPrompt,
filePromptTemplate,
maxPromptLength,
} from "../constants";
import { readFile } from "fs/promises";
import { filePromptTemplate, instructionPrompt } from "../constants";

const appendToLastPrompt = (prompts: string[], text: string): string[] => {
const appendToLastPrompt = (
prompts: string[],
text: string,
maxPromptLength: number
): string[] => {
const newPrompts = [...prompts];
const lastPromptIndex = newPrompts.length - 1;

Expand All @@ -18,8 +18,20 @@ const appendToLastPrompt = (prompts: string[], text: string): string[] => {
return newPrompts;
};

const splitFileContentsIntoChunks = (
fileContents: string,
maxChunkSize: number
): string[] => {
const chunks = [];
for (let i = 0; i < fileContents.length; i += maxChunkSize) {
chunks.push(fileContents.slice(i, i + maxChunkSize));
}
return chunks;
};

export const constructPromptsArray = async (
fileNames: string[]
fileNames: string[],
maxPromptLength: number
): Promise<string[]> => {
console.info("Constructing prompt...");

Expand All @@ -28,18 +40,27 @@ export const constructPromptsArray = async (
for (const fileName of fileNames) {
try {
const fileContents = await readFile(fileName, "utf8");
const filePrompt = filePromptTemplate
.replace("{fileName}", fileName)
.replace("{fileContents}", fileContents);

if (filePrompt.length > maxPromptLength) {
console.warn(
`The file ${fileName} is too large and may cause unexpected behavior such as cut off responses. Skipping this file.`
);
continue;
}
const fileChunks = splitFileContentsIntoChunks(
fileContents,
maxPromptLength
);

prompts = appendToLastPrompt(prompts, filePrompt);
for (let i = 0; i < fileChunks.length; i++) {
const fileChunk = fileChunks[i];
let chunkFileName = fileName;
if (i !== 0) {
console.warn(
`File ${fileName} is too large to fit in a single prompt. Splitting into ${fileChunks.length} chunks.`
);
chunkFileName += ` Continued part ${i + 1}`;
}

const filePrompt = filePromptTemplate
.replace("{fileName}", chunkFileName)
.replace("{fileContents}", fileChunk);

prompts = appendToLastPrompt(prompts, filePrompt, maxPromptLength);
}
} catch (error) {
console.error(`Failed to process file ${fileName}:`, error);
throw error;
Expand Down
17 changes: 17 additions & 0 deletions src/review/prompt/getMaxPromptLength.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { modelInfo } from "../constants";

export const getMaxPromptLength = (modelName: string): number => {
const maxPromptLength = modelInfo.find(
(info) => info.model === modelName
)?.maxPromptLength;

if (!maxPromptLength) {
throw new Error(
`Model ${modelName} not found. Please choose one of ${modelInfo.map(
(info) => info.model
)} or make a PR to add a new model.`
);
}

return maxPromptLength;
};

0 comments on commit 413afe4

Please sign in to comment.