Skip to content

Commit

Permalink
Merge branch 'main' into dallin/chat-symbols
Browse files Browse the repository at this point in the history
  • Loading branch information
sestinj committed Nov 20, 2024
2 parents eb40302 + e603416 commit 1426f80
Show file tree
Hide file tree
Showing 49 changed files with 193 additions and 63 deletions.
6 changes: 4 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ codeql
.tiktoken_cache


# IntelliJ Plugin
# IntelliJ Plugin
**/**/.gradle
**/**/.qodana
**/**/build
Expand All @@ -168,4 +168,6 @@ extensions/intellij/.idea/**
**/.idea/shelf/

extensions/intellij/bin
extensions/.continue-debug/
extensions/.continue-debug/

*.vsix
1 change: 1 addition & 0 deletions core/autocomplete/CompletionProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const autocompleteCache = AutocompleteLruCache.get();
const ERRORS_TO_IGNORE = [
// From Ollama
"unexpected server status",
"operation was aborted"
];

export type GetLspDefinitionsFunction = (
Expand Down
6 changes: 3 additions & 3 deletions core/autocomplete/generation/CompletionStreamer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ export class CompletionStreamer {
// Try to reuse pending requests if what the user typed matches start of completion
const generator = this.generatorReuseManager.getGenerator(
prefix,
() =>
(abortSignal: AbortSignal) =>
llm.supportsFim()
? llm.streamFim(prefix, suffix, completionOptions)
: llm.streamComplete(prompt, {
? llm.streamFim(prefix, suffix, abortSignal, completionOptions)
: llm.streamComplete(prompt, abortSignal, {
...completionOptions,
raw: true,
}),
Expand Down
2 changes: 1 addition & 1 deletion core/autocomplete/generation/GeneratorReuseManager.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { GeneratorReuseManager } from "./GeneratorReuseManager";
function createMockGenerator(
data: string[],
delay: number = 0,
): () => AsyncGenerator<string> {
): (abortSignal: AbortSignal) => AsyncGenerator<string> {
const mockGenerator = async function* () {
for (const chunk of data) {
yield chunk;
Expand Down
8 changes: 5 additions & 3 deletions core/autocomplete/generation/GeneratorReuseManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@ export class GeneratorReuseManager {
constructor(private readonly onError: (err: any) => void) {}

private _createListenableGenerator(
abortController: AbortController,
gen: AsyncGenerator<string>,
prefix: string,
) {
this.currentGenerator?.cancel();

const listenableGen = new ListenableGenerator(gen, this.onError);
const listenableGen = new ListenableGenerator(gen, this.onError, abortController);
listenableGen.listen((chunk) => (this.pendingCompletion += chunk ?? ""));

this.pendingGeneratorPrefix = prefix;
Expand All @@ -35,13 +36,14 @@ export class GeneratorReuseManager {

async *getGenerator(
prefix: string,
newGenerator: () => AsyncGenerator<string>,
newGenerator: (abortSignal: AbortSignal) => AsyncGenerator<string>,
multiline: boolean,
): AsyncGenerator<string> {
// If we can't reuse, then create a new generator
if (!this.shouldReuseExistingGenerator(prefix)) {
// Create a wrapper over the current generator to fix the prompt
this._createListenableGenerator(newGenerator(), prefix);
const abortController = new AbortController();
this._createListenableGenerator(abortController, newGenerator(abortController.signal), prefix);
}

// Already typed characters are those that are new in the prefix from the old generator
Expand Down
4 changes: 4 additions & 0 deletions core/autocomplete/generation/ListenableGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,20 @@ export class ListenableGenerator<T> {
private _buffer: T[] = [];
private _listeners: Set<(value: T) => void> = new Set();
private _isEnded = false;
private _abortController: AbortController

constructor(
source: AsyncGenerator<T>,
private readonly onError: (e: any) => void,
abortController: AbortController
) {
this._source = source;
this._abortController = abortController;
this._start();
}

public cancel() {
this._abortController.abort();
this._isEnded = true;
}

Expand Down
2 changes: 1 addition & 1 deletion core/commands/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export function slashFromCustomCommand(
}
}

for await (const chunk of llm.streamChat(messages)) {
for await (const chunk of llm.streamChat(messages, new AbortController().signal)) {
yield stripImages(chunk.content);
}
},
Expand Down
4 changes: 3 additions & 1 deletion core/commands/slash/cmd.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ const GenerateTerminalCommand: SlashCommand = {
"${input}"
Please write a shell command that will do what the user requested. Your output should consist of only the command itself, without any explanation or example output. Do not use any newlines. Only output the command that when inserted into the terminal will do precisely what was requested. Here is the command:`);
Please write a shell command that will do what the user requested. Your output should consist of only the command itself, without any explanation or example output. Do not use any newlines. Only output the command that when inserted into the terminal will do precisely what was requested. Here is the command:`,
new AbortController().signal
);

const lines = streamLines(gen);
let cmd = "";
Expand Down
2 changes: 1 addition & 1 deletion core/commands/slash/commit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const CommitMessageCommand: SlashCommand = {
const prompt = `${diff}\n\nGenerate a commit message for the above set of changes. First, give a single sentence, no more than 80 characters. Then, after 2 line breaks, give a list of no more than 5 short bullet points, each no more than 40 characters. Output nothing except for the commit message, and don't surround it in quotes.`;
for await (const chunk of llm.streamChat([
{ role: "user", content: prompt },
])) {
], new AbortController().signal)) {
yield stripImages(chunk.content);
}
},
Expand Down
4 changes: 2 additions & 2 deletions core/commands/slash/draftIssue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const DraftIssueCommand: SlashCommand = {
return;
}
let title = await llm.complete(
`Generate a title for the GitHub issue requested in this user input: '${input}'. Use no more than 20 words and output nothing other than the title. Do not surround it with quotes. The title is: `,
`Generate a title for the GitHub issue requested in this user input: '${input}'. Use no more than 20 words and output nothing other than the title. Do not surround it with quotes. The title is: `, new AbortController().signal,
{ maxTokens: 20 },
);

Expand All @@ -43,7 +43,7 @@ const DraftIssueCommand: SlashCommand = {
{ role: "user", content: PROMPT(input, title) },
];

for await (const chunk of llm.streamChat(messages)) {
for await (const chunk of llm.streamChat(messages, new AbortController().signal)) {
body += chunk.content;
yield stripImages(chunk.content);
}
Expand Down
6 changes: 3 additions & 3 deletions core/commands/slash/edit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,7 @@ const EditSlashCommand: SlashCommand = {
messages = rendered;
}

const completion = llm.streamComplete(rendered as string, {
const completion = llm.streamComplete(rendered as string, new AbortController().signal, {
maxTokens: Math.min(maxTokens, Math.floor(llm.contextLength / 2), 4096),
raw: true,
});
Expand All @@ -494,7 +494,7 @@ const EditSlashCommand: SlashCommand = {
);
} else {
async function* gen() {
for await (const chunk of llm.streamChat(messages, {
for await (const chunk of llm.streamChat(messages, new AbortController().signal,{
temperature: 0.5, // TODO
maxTokens: Math.min(
maxTokens,
Expand Down Expand Up @@ -609,7 +609,7 @@ ${lines.join("\n")}
Please briefly explain the changes made to the code above. Give no more than 2-3 sentences, and use markdown bullet points:`;

for await (const update of llm.streamComplete(prompt)) {
for await (const update of llm.streamComplete(prompt, new AbortController().signal)) {
yield update;
}
}
Expand Down
2 changes: 1 addition & 1 deletion core/commands/slash/multifileEdit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ const MultiFileEditSlashCommand: SlashCommand = {

const content = createPrompt(filesToEditStr, additionalContextStr, input);

for await (const chunk of llm.streamChat([{ role: "user", content }])) {
for await (const chunk of llm.streamChat([{ role: "user", content }], new AbortController().signal)) {
yield stripImages(chunk.content);
}
},
Expand Down
4 changes: 2 additions & 2 deletions core/commands/slash/onboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ const OnboardSlashCommand: SlashCommand = {

for await (const chunk of llm.streamChat([
{ role: "user", content: prompt },
])) {
], new AbortController().signal)) {
yield stripImages(chunk.content);
}
},
Expand Down Expand Up @@ -134,7 +134,7 @@ function createOnboardingPrompt(context: string): string {
Your response should be structured, clear, and focused on giving the new developer both a detailed understanding of individual components and a high-level overview of the project as a whole.
Here is an example of a valid response:
## Important folders
### /folder1
Expand Down
2 changes: 1 addition & 1 deletion core/commands/slash/review.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ const ReviewMessageCommand: SlashCommand = {

for await (const chunk of llm.streamChat([
{ role: "user", content: content },
])) {
], new AbortController().signal)) {
yield stripImages(chunk.content);
}
},
Expand Down
2 changes: 1 addition & 1 deletion core/config/promptFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ export function slashCommandFromPromptFile(
systemMessage,
);

for await (const chunk of context.llm.streamChat(messages)) {
for await (const chunk of context.llm.streamChat(messages, new AbortController().signal)) {
yield stripImages(chunk.content);
}

Expand Down
9 changes: 5 additions & 4 deletions core/context/rerankers/llm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const RERANK_PROMPT = (
documentId: string,
document: string,
) => `You are an expert software developer responsible for helping detect whether the retrieved snippet of code is relevant to the query. For a given input, you need to output a single word: "Yes" or "No" indicating the retrieved snippet is relevant to the query.
Query: Where is the FastAPI server?
Snippet:
\`\`\`/Users/andrew/Desktop/server/main.py
Expand All @@ -17,7 +17,7 @@ const RERANK_PROMPT = (
return {{"Hello": "World"}}
\`\`\`
Relevant: Yes
Query: Where in the documentation does it talk about the UI?
Snippet:
\`\`\`/Users/andrew/Projects/bubble_sort/src/lib.rs
Expand All @@ -32,13 +32,13 @@ const RERANK_PROMPT = (
}}
\`\`\`
Relevant: No
Query: ${query}
Snippet:
\`\`\`${documentId}
${document}
\`\`\`
Relevant:
Relevant:
`;

export class LLMReranker implements Reranker {
Expand All @@ -49,6 +49,7 @@ export class LLMReranker implements Reranker {
async scoreChunk(chunk: Chunk, query: string): Promise<number> {
const completion = await this.llm.complete(
RERANK_PROMPT(query, getBasename(chunk.filepath), chunk.content),
new AbortController().signal,
{
maxTokens: 1,
model:
Expand Down
2 changes: 1 addition & 1 deletion core/context/retrieval/repoMapRequest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ This is the question that you should select relevant files for: "${input}"`;
const response = await llm.chat([
{ role: "user", content: prompt },
{ role: "assistant", content: "<reasoning>" },
]);
], new AbortController().signal);
const content = stripImages(response.content);
console.debug("Repo map retrieval response: ", content);

Expand Down
3 changes: 3 additions & 0 deletions core/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,7 @@ export class Core {
const model = await configHandler.llmFromTitle(msg.data.title);
const gen = model.streamChat(
msg.data.messages,
new AbortController().signal,
msg.data.completionOptions,
);
let next = await gen.next();
Expand Down Expand Up @@ -434,6 +435,7 @@ export class Core {
const model = await configHandler.llmFromTitle(msg.data.title);
const gen = model.streamComplete(
msg.data.prompt,
new AbortController().signal,
msg.data.completionOptions,
);
let next = await gen.next();
Expand Down Expand Up @@ -466,6 +468,7 @@ export class Core {
const model = await this.configHandler.llmFromTitle(msg.data.title);
const completion = await model.complete(
msg.data.prompt,
new AbortController().signal,
msg.data.completionOptions,
);
return completion;
Expand Down
2 changes: 1 addition & 1 deletion core/edit/lazy/replace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ export async function* getReplacementWithLlm(
const completion = await llm.streamChat([
{ role: "user", content: userPrompt },
{ role: "assistant", content: assistantPrompt },
]);
], new AbortController().signal);

let lines = streamLines(completion);
lines = filterLeadingNewline(lines);
Expand Down
2 changes: 1 addition & 1 deletion core/edit/lazy/streamLazyApply.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export async function* streamLazyApply(
}

const promptMessages = promptFactory(oldCode, filename, newCode);
const lazyCompletion = llm.streamChat(promptMessages);
const lazyCompletion = llm.streamChat(promptMessages, new AbortController().signal);

// Do find and replace over the lazy edit response
async function* replacementFunction(
Expand Down
4 changes: 2 additions & 2 deletions core/edit/streamDiffLines.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ export async function* streamDiffLines(

const completion =
typeof prompt === "string"
? llm.streamComplete(prompt, { raw: true, prediction })
: llm.streamChat(prompt, {
? llm.streamComplete(prompt, new AbortController().signal, { raw: true, prediction })
: llm.streamChat(prompt, new AbortController().signal, {
prediction,
});

Expand Down
12 changes: 11 additions & 1 deletion core/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,26 +79,34 @@ export interface ILLM extends LLMOptions {
region?: string;
projectId?: string;

complete(prompt: string, options?: LLMFullCompletionOptions): Promise<string>;
complete(
prompt: string,
signal: AbortSignal,
options?: LLMFullCompletionOptions
): Promise<string>;

streamComplete(
prompt: string,
signal: AbortSignal,
options?: LLMFullCompletionOptions,
): AsyncGenerator<string, PromptLog>;

streamFim(
prefix: string,
suffix: string,
signal: AbortSignal,
options?: LLMFullCompletionOptions,
): AsyncGenerator<string, PromptLog>;

streamChat(
messages: ChatMessage[],
signal: AbortSignal,
options?: LLMFullCompletionOptions,
): AsyncGenerator<ChatMessage, PromptLog>;

chat(
messages: ChatMessage[],
signal: AbortSignal,
options?: LLMFullCompletionOptions,
): Promise<ChatMessage>;

Expand Down Expand Up @@ -395,11 +403,13 @@ export interface CustomLLMWithOptionals {
options: LLMOptions;
streamCompletion?: (
prompt: string,
signal: AbortSignal,
options: CompletionOptions,
fetch: (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>,
) => AsyncGenerator<string>;
streamChat?: (
messages: ChatMessage[],
signal: AbortSignal,
options: CompletionOptions,
fetch: (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>,
) => AsyncGenerator<string>;
Expand Down
Loading

0 comments on commit 1426f80

Please sign in to comment.