Merge pull request #549 from devchat-ai/optimize_code_completion_240605
Refactor code for performance optimization and bug fixes
This commit is contained in:
commit
826806edad
2
gui
2
gui
@ -1 +1 @@
|
|||||||
Subproject commit 750874981accb3c02d765557f0bd81fa6a2f220b
|
Subproject commit 808bf945e263cebfdcbbd60696bae84f2a6d594d
|
@ -277,8 +277,8 @@ export class LLMStreamComplete {
|
|||||||
|
|
||||||
// whether lines are repeated some block before
|
// whether lines are repeated some block before
|
||||||
async removeRepeatBlock(lines: string[]): Promise< string[] > {
|
async removeRepeatBlock(lines: string[]): Promise< string[] > {
|
||||||
if (lines.length === 0) {
|
if (lines.length <= 1) {
|
||||||
return [];
|
return lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
// find first match line in before 50 lines
|
// find first match line in before 50 lines
|
||||||
|
@ -206,7 +206,7 @@ export async function * devchatComplete(prompt: string) : AsyncGenerator<CodeCom
|
|||||||
model: model,
|
model: model,
|
||||||
prompt: prompt,
|
prompt: prompt,
|
||||||
stream: true,
|
stream: true,
|
||||||
stop: ["<|endoftext|>", "<|EOT|>", "<file_sep>", "```", "/", "\n\n"],
|
stop: ["<|endoftext|>", "<|EOT|>", "<file_sep>", "```", "//", "\n\n"],
|
||||||
temperature: 0.2
|
temperature: 0.2
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -42,16 +42,17 @@ function countTokens(
|
|||||||
// defaults to llama2 because the tokenizer tends to produce more tokens
|
// defaults to llama2 because the tokenizer tends to produce more tokens
|
||||||
modelName: string = "llama2",
|
modelName: string = "llama2",
|
||||||
): number {
|
): number {
|
||||||
const encoding = encodingForModel(modelName);
|
return content.length;
|
||||||
if (Array.isArray(content)) {
|
// const encoding = encodingForModel(modelName);
|
||||||
return content.reduce((acc, part) => {
|
// if (Array.isArray(content)) {
|
||||||
return acc + part.type === "imageUrl"
|
// return content.reduce((acc, part) => {
|
||||||
? countImageTokens(part)
|
// return acc + part.type === "imageUrl"
|
||||||
: encoding.encode(part.text ?? "", "all", []).length;
|
// ? countImageTokens(part)
|
||||||
}, 0);
|
// : encoding.encode(part.text ?? "", "all", []).length;
|
||||||
} else {
|
// }, 0);
|
||||||
return encoding.encode(content, "all", []).length;
|
// } else {
|
||||||
}
|
// return encoding.encode(content, "all", []).length;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
function flattenMessages(msgs: ChatMessage[]): ChatMessage[] {
|
function flattenMessages(msgs: ChatMessage[]): ChatMessage[] {
|
||||||
|
@ -27,7 +27,6 @@ import { findIdentifiersInAstNodeRange } from './ast/findIdentifiers';
|
|||||||
import { DevChatConfig } from '../../util/config';
|
import { DevChatConfig } from '../../util/config';
|
||||||
|
|
||||||
|
|
||||||
const CONTEXT_LIMITED_SIZE: number = 6000;
|
|
||||||
const CONTEXT_SIMILAR_LIMITED_SIZE: number = 400;
|
const CONTEXT_SIMILAR_LIMITED_SIZE: number = 400;
|
||||||
|
|
||||||
const variableCache: MemoryCacheManager = new MemoryCacheManager(4);
|
const variableCache: MemoryCacheManager = new MemoryCacheManager(4);
|
||||||
@ -40,7 +39,7 @@ export async function currentFileContext(
|
|||||||
curColumn: number
|
curColumn: number
|
||||||
) : Promise< { prefix: string, suffix: string } > {
|
) : Promise< { prefix: string, suffix: string } > {
|
||||||
const contentTokens = countTokens(contents);
|
const contentTokens = countTokens(contents);
|
||||||
if (contentTokens < CONTEXT_LIMITED_SIZE*0.35) {
|
if (contentTokens < DevChatConfig.getInstance().get("complete_context_limit", 3000)*0.5) {
|
||||||
return curfilePrompt(filepath, contents, curRow, curColumn);
|
return curfilePrompt(filepath, contents, curRow, curColumn);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,7 +50,7 @@ export async function currentFileContext(
|
|||||||
|
|
||||||
const functionRanges = await findFunctionRanges(filepath, ast.rootNode);
|
const functionRanges = await findFunctionRanges(filepath, ast.rootNode);
|
||||||
return await collapseCodeBlock(functionRanges, filepath, contents, curRow, curColumn);
|
return await collapseCodeBlock(functionRanges, filepath, contents, curRow, curColumn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export async function collapseCodeBlock(functions: FunctionRange[], filepath: string, contents: string, curRow: number, curColumn: number) {
|
export async function collapseCodeBlock(functions: FunctionRange[], filepath: string, contents: string, curRow: number, curColumn: number) {
|
||||||
@ -186,7 +185,7 @@ async function curfilePrompt(filePath: string, fileContent: string, line: number
|
|||||||
}
|
}
|
||||||
|
|
||||||
const lineTokenCount = countTokens(lineText);
|
const lineTokenCount = countTokens(lineText);
|
||||||
if (prefixTokenCount + lineTokenCount > CONTEXT_LIMITED_SIZE*0.7*0.35) {
|
if (prefixTokenCount + lineTokenCount > DevChatConfig.getInstance().get("complete_context_limit", 3000)*0.7*0.35) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,7 +194,7 @@ async function curfilePrompt(filePath: string, fileContent: string, line: number
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 从光标所在行下一行开始,向下构建后缀
|
// 从光标所在行下一行开始,向下构建后缀
|
||||||
const suffixMaxToken = CONTEXT_LIMITED_SIZE*0.35 - prefixTokenCount;
|
const suffixMaxToken = DevChatConfig.getInstance().get("complete_context_limit", 3000)*0.35 - prefixTokenCount;
|
||||||
for (let i = line; i < lines.length; i++) {
|
for (let i = line; i < lines.length; i++) {
|
||||||
let lineText = lines[i] + '\n';
|
let lineText = lines[i] + '\n';
|
||||||
if (i === line) {
|
if (i === line) {
|
||||||
@ -551,17 +550,10 @@ export async function createPrompt(filePath: string, fileContent: string, line:
|
|||||||
|
|
||||||
let { prefix, suffix } = await currentFileContext(filePath, fileContent, line, column);
|
let { prefix, suffix } = await currentFileContext(filePath, fileContent, line, column);
|
||||||
|
|
||||||
let tokenCount = countTokens(prefix);
|
let tokenCount = countTokens(prefix) + countTokens(suffix);
|
||||||
|
|
||||||
const suffixTokenCount = countTokens(suffix);
|
|
||||||
if (tokenCount + suffixTokenCount < CONTEXT_LIMITED_SIZE) {
|
|
||||||
tokenCount += suffixTokenCount;
|
|
||||||
} else {
|
|
||||||
suffix = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
let taskDescriptionContextWithCommentPrefix = "";
|
let taskDescriptionContextWithCommentPrefix = "";
|
||||||
if (tokenCount < CONTEXT_LIMITED_SIZE) {
|
if (tokenCount < DevChatConfig.getInstance().get("complete_context_limit", 3000)) {
|
||||||
const taskDescriptionContext = await createTaskDescriptionContext();
|
const taskDescriptionContext = await createTaskDescriptionContext();
|
||||||
if (taskDescriptionContext) {
|
if (taskDescriptionContext) {
|
||||||
taskDescriptionContext.split("\n").forEach(line => {
|
taskDescriptionContext.split("\n").forEach(line => {
|
||||||
@ -572,7 +564,7 @@ export async function createPrompt(filePath: string, fileContent: string, line:
|
|||||||
}
|
}
|
||||||
|
|
||||||
const taskDescriptionContextToken = countTokens(taskDescriptionContextWithCommentPrefix);
|
const taskDescriptionContextToken = countTokens(taskDescriptionContextWithCommentPrefix);
|
||||||
if (tokenCount + taskDescriptionContextToken < CONTEXT_LIMITED_SIZE) {
|
if (tokenCount + taskDescriptionContextToken < DevChatConfig.getInstance().get("complete_context_limit", 3000)) {
|
||||||
tokenCount += taskDescriptionContextToken;
|
tokenCount += taskDescriptionContextToken;
|
||||||
} else {
|
} else {
|
||||||
taskDescriptionContextWithCommentPrefix = "";
|
taskDescriptionContextWithCommentPrefix = "";
|
||||||
@ -580,9 +572,9 @@ export async function createPrompt(filePath: string, fileContent: string, line:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// let gitDiffContext = GitDiffWatcher.getInstance().getGitDiffResult();
|
// let gitDiffContext = GitDiffWatcher.getInstance().getGitDiffResult();
|
||||||
// if (tokenCount < CONTEXT_LIMITED_SIZE && gitDiffContext.length > 0) {
|
// if (tokenCount < DevChatConfig.getInstance().get("complete_context_limit", 3000) && gitDiffContext.length > 0) {
|
||||||
// const gitDiffContextToken = countTokens(gitDiffContext);
|
// const gitDiffContextToken = countTokens(gitDiffContext);
|
||||||
// if (tokenCount + gitDiffContextToken < CONTEXT_LIMITED_SIZE) {
|
// if (tokenCount + gitDiffContextToken < DevChatConfig.getInstance().get("complete_context_limit", 3000)) {
|
||||||
// tokenCount += gitDiffContextToken;
|
// tokenCount += gitDiffContextToken;
|
||||||
// gitDiffContext = "<git_diff_start>" + gitDiffContext + "<git_diff_end>\n\n\n\n";
|
// gitDiffContext = "<git_diff_start>" + gitDiffContext + "<git_diff_end>\n\n\n\n";
|
||||||
// } else {
|
// } else {
|
||||||
@ -592,11 +584,11 @@ export async function createPrompt(filePath: string, fileContent: string, line:
|
|||||||
let gitDiffContext = "";
|
let gitDiffContext = "";
|
||||||
|
|
||||||
let callDefContext = "";
|
let callDefContext = "";
|
||||||
if (tokenCount < CONTEXT_LIMITED_SIZE) {
|
if (tokenCount < DevChatConfig.getInstance().get("complete_context_limit", 3000)) {
|
||||||
const callCodeBlocks = await createContextCallDefine(filePath, fileContent, posoffset);
|
const callCodeBlocks = await createContextCallDefine(filePath, fileContent, posoffset);
|
||||||
for (const callCodeBlock of callCodeBlocks) {
|
for (const callCodeBlock of callCodeBlocks) {
|
||||||
const callBlockToken = countTokens(callCodeBlock.codeblock);
|
const callBlockToken = countTokens(callCodeBlock.codeblock);
|
||||||
if (tokenCount + callBlockToken > CONTEXT_LIMITED_SIZE) {
|
if (tokenCount + callBlockToken > DevChatConfig.getInstance().get("complete_context_limit", 3000)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -607,18 +599,18 @@ export async function createPrompt(filePath: string, fileContent: string, line:
|
|||||||
}
|
}
|
||||||
|
|
||||||
let similarBlockContext = "";
|
let similarBlockContext = "";
|
||||||
if (tokenCount < CONTEXT_LIMITED_SIZE) {
|
if (tokenCount < DevChatConfig.getInstance().get("complete_context_limit", 3000)) {
|
||||||
let similarTokens = 0;
|
let similarTokens = 0;
|
||||||
const similarContexts: {file: string, text: string}[] = await findSimilarCodeBlock(filePath, fileContent, line, column);
|
const similarContexts: {file: string, text: string}[] = await findSimilarCodeBlock(filePath, fileContent, line, column);
|
||||||
|
|
||||||
for (const similarContext of similarContexts) {
|
for (const similarContext of similarContexts) {
|
||||||
const blockToken = countTokens(similarContext.text);
|
const blockToken = countTokens(similarContext.text);
|
||||||
if (tokenCount + blockToken > CONTEXT_LIMITED_SIZE) {
|
if (tokenCount + blockToken > DevChatConfig.getInstance().get("complete_context_limit", 3000)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
similarTokens += blockToken;
|
similarTokens += blockToken;
|
||||||
if (similarTokens > CONTEXT_SIMILAR_LIMITED_SIZE) {
|
if (similarTokens > CONTEXT_SIMILAR_LIMITED_SIZE) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
tokenCount += blockToken;
|
tokenCount += blockToken;
|
||||||
@ -628,11 +620,11 @@ export async function createPrompt(filePath: string, fileContent: string, line:
|
|||||||
}
|
}
|
||||||
|
|
||||||
let symbolContext = "";
|
let symbolContext = "";
|
||||||
if (tokenCount < CONTEXT_LIMITED_SIZE) {
|
if (tokenCount < DevChatConfig.getInstance().get("complete_context_limit", 3000)) {
|
||||||
const symbolDefines: { filepath: string, node: Parser.SyntaxNode, codeblock: string }[] = await symbolDefinesContext(filePath, fileContent, line, column);
|
const symbolDefines: { filepath: string, node: Parser.SyntaxNode, codeblock: string }[] = await symbolDefinesContext(filePath, fileContent, line, column);
|
||||||
for (const symbolDefine of symbolDefines ) {
|
for (const symbolDefine of symbolDefines ) {
|
||||||
const countSymboleToken = countTokens(symbolDefine.codeblock);
|
const countSymboleToken = countTokens(symbolDefine.codeblock);
|
||||||
if (tokenCount + countSymboleToken > CONTEXT_LIMITED_SIZE) {
|
if (tokenCount + countSymboleToken > DevChatConfig.getInstance().get("complete_context_limit", 3000)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -644,11 +636,11 @@ export async function createPrompt(filePath: string, fileContent: string, line:
|
|||||||
}
|
}
|
||||||
|
|
||||||
let recentEditContext = "";
|
let recentEditContext = "";
|
||||||
if (tokenCount < CONTEXT_LIMITED_SIZE) {
|
if (tokenCount < DevChatConfig.getInstance().get("complete_context_limit", 3000)) {
|
||||||
recentEditContext = await createRecentEditContext(recentEdits, filePath);
|
recentEditContext = await createRecentEditContext(recentEdits, filePath);
|
||||||
|
|
||||||
const countRecentToken = countTokens(recentEditContext);
|
const countRecentToken = countTokens(recentEditContext);
|
||||||
if (tokenCount + countRecentToken < CONTEXT_LIMITED_SIZE) {
|
if (tokenCount + countRecentToken < DevChatConfig.getInstance().get("complete_context_limit", 3000)) {
|
||||||
tokenCount += countRecentToken;
|
tokenCount += countRecentToken;
|
||||||
} else {
|
} else {
|
||||||
recentEditContext = "";
|
recentEditContext = "";
|
||||||
@ -660,7 +652,7 @@ export async function createPrompt(filePath: string, fileContent: string, line:
|
|||||||
const neighborFiles = await findNeighborFileContext(filePath, fileContent, line, column);
|
const neighborFiles = await findNeighborFileContext(filePath, fileContent, line, column);
|
||||||
if (neighborFiles.length > 0) {
|
if (neighborFiles.length > 0) {
|
||||||
const countFileToken = countTokens(neighborFiles[0].text);
|
const countFileToken = countTokens(neighborFiles[0].text);
|
||||||
if (tokenCount + countFileToken < CONTEXT_LIMITED_SIZE) {
|
if (tokenCount + countFileToken < DevChatConfig.getInstance().get("complete_context_limit", 3000)) {
|
||||||
tokenCount += countFileToken;
|
tokenCount += countFileToken;
|
||||||
neighborFileContext += `${commentPrefix}<filename>neighbor files:\n\n ${neighborFiles[0].file}\n\n`;
|
neighborFileContext += `${commentPrefix}<filename>neighbor files:\n\n ${neighborFiles[0].file}\n\n`;
|
||||||
neighborFileContext += `${neighborFiles[0].text}\n\n\n\n`;
|
neighborFileContext += `${neighborFiles[0].text}\n\n\n\n`;
|
||||||
|
@ -54,7 +54,7 @@ export class DevChatConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public get(key: string | string[]): any {
|
public get(key: string | string[], defaultValue: any = undefined): any {
|
||||||
// check if the config file has been modified
|
// check if the config file has been modified
|
||||||
const currentModifyTime = fs.statSync(this.configFilePath).mtimeMs;
|
const currentModifyTime = fs.statSync(this.configFilePath).mtimeMs;
|
||||||
if (currentModifyTime > this.lastModifyTime) {
|
if (currentModifyTime > this.lastModifyTime) {
|
||||||
@ -68,7 +68,18 @@ export class DevChatConfig {
|
|||||||
} else {
|
} else {
|
||||||
keys = key;
|
keys = key;
|
||||||
}
|
}
|
||||||
return keys.reduce((prev, curr) => prev ? prev[curr] : undefined, this.data);
|
|
||||||
|
let value = this.data;
|
||||||
|
for (const k of keys) {
|
||||||
|
if (value && typeof value === 'object' && k in value) {
|
||||||
|
value = value[k];
|
||||||
|
} else {
|
||||||
|
// If the key is not found or value is not an object, return the default value
|
||||||
|
return defaultValue || undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public set(key: string | string[], value: any): void {
|
public set(key: string | string[], value: any): void {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user