From 1fdc36fea254f352a9a6f8e64c5a759a29463b97 Mon Sep 17 00:00:00 2001 From: Simon Larsen Date: Mon, 8 Jul 2024 19:56:27 +0100 Subject: [PATCH] refactor: Update logging in Llama class for better debugging --- Common/Utils/API.ts | 3 +- Copilot/Init.ts | 3 + .../CopilotActions/CopilotActionsBase.ts | 45 +++++++++- .../Service/CopilotActions/ImproveComments.ts | 86 +++++++++++-------- Copilot/Utils/Init.ts | 21 ++++- docker-compose.copilot.yml | 2 +- 6 files changed, 121 insertions(+), 39 deletions(-) diff --git a/Common/Utils/API.ts b/Common/Utils/API.ts index 6dd0ea0e25..44a338d231 100644 --- a/Common/Utils/API.ts +++ b/Common/Utils/API.ts @@ -341,6 +341,7 @@ export default class API { let result: AxiosResponse | null = null; while (currentRetry <= maxRetries) { + currentRetry++; try { result = await axios({ method: method, @@ -349,7 +350,7 @@ export default class API { data: finalBody, }); } catch (e) { - currentRetry++; + if (currentRetry <= maxRetries) { if (exponentialBackoff) { await Sleep.sleep(2 ** currentRetry * 1000); diff --git a/Copilot/Init.ts b/Copilot/Init.ts index 1f653f32ce..ea7bfead29 100644 --- a/Copilot/Init.ts +++ b/Copilot/Init.ts @@ -24,6 +24,9 @@ import CopilotActionProcessingException from "./Exceptions/CopilotActionProcessi let currentFixCount: number = 1; const init: PromiseVoidFunction = async (): Promise => { + + debugger; + await CodeRepositoryUtil.setAuthorIdentity({ email: "copilot@oneuptime.com", name: "OneUptime Copilot", diff --git a/Copilot/Service/CopilotActions/CopilotActionsBase.ts b/Copilot/Service/CopilotActions/CopilotActionsBase.ts index 09f01ffe06..06eada9474 100644 --- a/Copilot/Service/CopilotActions/CopilotActionsBase.ts +++ b/Copilot/Service/CopilotActions/CopilotActionsBase.ts @@ -172,8 +172,9 @@ If you have any feedback or suggestions, please let us know. We would love to h protected async _getPrompt( data: CopilotProcess, + inputCode: string, ): Promise { - const prompt: CopilotActionPrompt | null = await this._getPrompt(data); + const prompt: CopilotActionPrompt | null = await this._getPrompt(data, inputCode); if (!prompt) { return null; @@ -184,6 +185,7 @@ If you have any feedback or suggestions, please let us know. We would love to h public async getPrompt( _data: CopilotProcess, + _inputCode: string, ): Promise { throw new NotImplementedException(); } @@ -193,4 +195,45 @@ If you have any feedback or suggestions, please let us know. We would love to h ): Promise { return await LLM.getResponse(prompt); } + + public async getInputCode(data: CopilotProcess): Promise { + return data.input.files[data.input.currentFilePath]?.fileContent as string; + } + + public async splitInputCode(data: { + copilotProcess: CopilotProcess, + itemSize: number, + }): Promise { + const inputCode: string = await this.getInputCode(data.copilotProcess); + + const items: Array = []; + + const linesInInputCode: Array = inputCode.split("\n"); + + let currentItemSize = 0; + const maxItemSize = data.itemSize; + + let currentItem = ''; + + for(const line of linesInInputCode) { + const words: Array = line.split(" "); + + // check if the current item size is less than the max item size + if(currentItemSize + words.length < maxItemSize) { + currentItem += line + '\n'; + currentItemSize += words.length; + } else { + // start a new item + items.push(currentItem); + currentItem = line + '\n'; + currentItemSize = words.length; + } + } + + if(currentItem) { + items.push(currentItem); + } + + return items; + } } diff --git a/Copilot/Service/CopilotActions/ImproveComments.ts b/Copilot/Service/CopilotActions/ImproveComments.ts index 00949868a5..ff27aa0a5c 100644 --- a/Copilot/Service/CopilotActions/ImproveComments.ts +++ b/Copilot/Service/CopilotActions/ImproveComments.ts @@ -27,43 +27,63 @@ export default class ImproveComments extends CopilotActionBase { ): Promise { // Action Prompt - const actionPrompt: CopilotActionPrompt = await this.getPrompt(data); - debugger; - const copilotResult: CopilotPromptResult = - await this.askCopilot(actionPrompt); - - const newContent: string = await this.cleanup({ - inputCode: await this.getInputCode(data), - outputCode: copilotResult.output as string, + const codeParts: string[] = await this.splitInputCode({ + copilotProcess: data, + itemSize: 500 }); - if (await this.isFileAlreadyWellCommented(newContent)) { + let newContent: string = ""; + + let isWellCommented = true; + let didPassFileValidation = false; + + for (const codePart of codeParts) { + + const actionPrompt: CopilotActionPrompt = await this.getPrompt(data, codePart); + + const copilotResult: CopilotPromptResult = + await this.askCopilot(actionPrompt); + + const newCodePart: string = await this.cleanup({ + inputCode: codePart, + outputCode: copilotResult.output as string, + }); + + if (!await this.isFileAlreadyWellCommented(newCodePart)) { + isWellCommented = false; + } + + const validationPrompt: CopilotActionPrompt = + await this.getValidationPrompt({ + oldCode: codePart, + newCode: newCodePart, + }); + + const validationResponse: CopilotPromptResult = + await this.askCopilot(validationPrompt); + + const didPassValidation: boolean = + await this.didPassValidation(validationResponse); + + if (!didPassValidation) { + newContent = codePart; + break; + } else { + didPassFileValidation = true; + newContent += newCodePart + '\n'; + } + } + + if (isWellCommented) { this.isRequirementsMet = true; return data; } - // ask copilot again if the requirements are met. + newContent = newContent.trim(); - const oldCode: string = data.input.files[data.input.currentFilePath] - ?.fileContent as string; - - const newCode: string = newContent; - - const validationPrompt: CopilotActionPrompt = - await this.getValidationPrompt({ - oldCode, - newCode, - }); - - const validationResponse: CopilotPromptResult = - await this.askCopilot(validationPrompt); - - const didPassValidation: boolean = - await this.didPassValidation(validationResponse); - - if (didPassValidation) { + if (didPassFileValidation) { // add to result. data.result.files[data.input.currentFilePath] = { ...data.input.files[data.input.currentFilePath], @@ -74,8 +94,6 @@ export default class ImproveComments extends CopilotActionBase { return data; } - // TODO: if the validation is not passed then ask copilot to improve the comments again. - return data; } @@ -138,17 +156,15 @@ export default class ImproveComments extends CopilotActionBase { }; } - public async getInputCode(data: CopilotProcess): Promise { - return data.input.files[data.input.currentFilePath]?.fileContent as string; - } + public override async getPrompt( data: CopilotProcess, + inputCode: string, ): Promise { const fileLanguage: ServiceLanguage = data.input.files[ data.input.currentFilePath ]?.fileLanguage as ServiceLanguage; - const code: string = await this.getInputCode(data); const prompt: string = `Please improve the comments in this code. Please only comment code that is hard to understand. @@ -157,7 +173,7 @@ export default class ImproveComments extends CopilotActionBase { Here is the code. This is in ${fileLanguage}: - ${code} + ${inputCode} `; const systemPrompt: string = await this.getSystemPrompt(); diff --git a/Copilot/Utils/Init.ts b/Copilot/Utils/Init.ts index abcf942dab..c9bb5e8444 100644 --- a/Copilot/Utils/Init.ts +++ b/Copilot/Utils/Init.ts @@ -1,10 +1,29 @@ -import { GetCodeRepositoryPassword, GetRepositorySecretKey } from "../Config"; +import { GetCodeRepositoryPassword, GetLlamaServerUrl, GetLlmType, GetRepositorySecretKey } from "../Config"; import CodeRepositoryUtil, { CodeRepositoryResult } from "./CodeRepository"; import CodeRepositoryType from "Common/Types/CodeRepository/CodeRepositoryType"; import BadDataException from "Common/Types/Exception/BadDataException"; +import URL from "Common/Types/API/URL"; +import LlmType from "../Types/LlmType"; +import API from "Common/Utils/API"; +import HTTPErrorResponse from "Common/Types/API/HTTPErrorResponse"; +import HTTPResponse from "Common/Types/API/HTTPResponse"; +import { JSONObject } from "Common/Types/JSON"; export default class InitUtil { public static async init(): Promise { + + const llamaServerUrl: URL = GetLlamaServerUrl(); + + if(GetLlmType() === LlmType.Llama){ + // check status of llama server + const result: HTTPErrorResponse | HTTPResponse = await API.get(URL.fromString(llamaServerUrl.toString())); + + if(result instanceof HTTPErrorResponse){ + throw new BadDataException("Llama server is not reachable. Please check the server URL in the environment variables."); + } + + } + if (!GetRepositorySecretKey()) { throw new BadDataException("Repository Secret Key is required"); } diff --git a/docker-compose.copilot.yml b/docker-compose.copilot.yml index 902d2d78ec..c3269efeca 100644 --- a/docker-compose.copilot.yml +++ b/docker-compose.copilot.yml @@ -20,7 +20,7 @@ services: file: ./docker-compose.base.yml service: copilot environment: - - LOG_LEVEL=DEBUG + - LOG_LEVEL=INFO build: network: host context: .