Skip to content

Commit

Permalink
Merge branch 'justinmilner1-MakeArrowsScroll' into preview
Browse files Browse the repository at this point in the history
  • Loading branch information
sestinj committed Jun 4, 2024
2 parents 6b902a4 + 52bed16 commit 81cddec
Show file tree
Hide file tree
Showing 32 changed files with 2,984 additions and 2,468 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -163,4 +163,7 @@ continue_server.dist
Icon
Icon?

.continue
.continue

# Sandbox env default file
extensions/vscode/manual-testing-sandbox/example.ts
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ nvm use
1. The new VS Code window with the extension is referred to as the _Host VS Code_
2. The window you started debugging from is referred to as the _Main VS Code_

4. To package the extension, run `npm package` in the `extensions/vscode` directory. This will generate `extensions/vscode/build/continue-patch.vsix`, which you can install by right-clicking and selecting "Install Extension VSIX".
4. To package the extension, run `npm run package` in the `extensions/vscode` directory. This will generate `extensions/vscode/build/continue-{VERSION}.vsix`, which you can install by right-clicking and selecting "Install Extension VSIX".

##### Debugging

Expand Down
1 change: 1 addition & 0 deletions binary/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

55 changes: 29 additions & 26 deletions core/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,27 +1,30 @@
{
"root": true,
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 6,
"sourceType": "module"
},
"extends": ["plugin:require-extensions/recommended"],
"plugins": ["@typescript-eslint", "import", "require-extensions"],
"rules": {
"quotes": ["warn", "double", {}],
"import/extensions": ["error", "always", {
"js": "never",
"jsx": "never",
"ts": "never",
"tsx": "never"
}],
"@typescript-eslint/naming-convention": "warn",
"@typescript-eslint/semi": "warn",
"curly": "warn",
"eqeqeq": "warn",
"no-throw-literal": "warn",
"semi": "off"
},
"ignorePatterns": ["out", "dist", "**/*.d.ts"]
}

"root": true,
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 6,
"sourceType": "module"
},
"extends": ["plugin:require-extensions/recommended"],
"plugins": ["@typescript-eslint", "import", "require-extensions"],
"rules": {
"quotes": ["warn", "double", {}],
"import/extensions": [
"error",
"always",
{
"js": "never",
"jsx": "never",
"ts": "never",
"tsx": "never"
}
],
"@typescript-eslint/naming-convention": "warn",
"@typescript-eslint/semi": "warn",
"curly": "warn",
"eqeqeq": "warn",
"no-throw-literal": "warn",
"semi": "off"
},
"ignorePatterns": ["out", "dist", "**/*.d.ts"]
}
4 changes: 2 additions & 2 deletions core/config/load.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import {
SlashCommand,
} from "../index.js";
import TransformersJsEmbeddingsProvider from "../indexing/embeddings/TransformersJsEmbeddingsProvider.js";
import { AllEmbeddingsProviders } from "../indexing/embeddings/index.js";
import { allEmbeddingsProviders } from "../indexing/embeddings/index.js";
import { BaseLLM } from "../llm/index.js";
import CustomLLMClass from "../llm/llms/CustomLLM.js";
import FreeTrial from "../llm/llms/FreeTrial.js";
Expand Down Expand Up @@ -336,7 +336,7 @@ async function intermediateToFinalConfig(
| undefined;
if (embeddingsProviderDescription?.provider) {
const { provider, ...options } = embeddingsProviderDescription;
const embeddingsProviderClass = AllEmbeddingsProviders[provider];
const embeddingsProviderClass = allEmbeddingsProviders[provider];
if (embeddingsProviderClass) {
if (
embeddingsProviderClass.name === "_TransformersJsEmbeddingsProvider"
Expand Down
1 change: 1 addition & 0 deletions core/config/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,7 @@ declare global {
// Gemini
| "gemini-pro"
| "gemini-1.5-pro-latest"
| "gemini-1.5-flash-latest"
// Mistral
| "mistral-tiny"
| "mistral-small"
Expand Down
3 changes: 2 additions & 1 deletion core/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -688,7 +688,8 @@ export type EmbeddingsProviderName =
| "ollama"
| "openai"
| "cohere"
| "free-trial";
| "free-trial"
| "gemini";

export interface EmbedOptions {
apiBase?: string;
Expand Down
54 changes: 45 additions & 9 deletions core/indexing/embeddings/BaseEmbeddingsProvider.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,60 @@
import { EmbedOptions, EmbeddingsProvider, FetchFunction } from "../../index.js";
import {
EmbedOptions,
EmbeddingsProvider,
FetchFunction,
} from "../../index.js";

class BaseEmbeddingsProvider implements EmbeddingsProvider {
export interface IBaseEmbeddingsProvider extends EmbeddingsProvider {
options: EmbedOptions;
fetch: FetchFunction;
static defaultOptions: Partial<EmbedOptions> | undefined = undefined;
defaultOptions?: EmbedOptions;
maxBatchSize?: number;
}

get id(): string {
throw new Error("Method not implemented.");
}
abstract class BaseEmbeddingsProvider implements IBaseEmbeddingsProvider {
static maxBatchSize: IBaseEmbeddingsProvider["maxBatchSize"];
static defaultOptions: IBaseEmbeddingsProvider["defaultOptions"];

options: IBaseEmbeddingsProvider["options"];
fetch: IBaseEmbeddingsProvider["fetch"];
id: IBaseEmbeddingsProvider["id"];

constructor(options: EmbedOptions, fetch: FetchFunction) {
constructor(
options: IBaseEmbeddingsProvider["options"],
fetch: IBaseEmbeddingsProvider["fetch"],
) {
// Overwrite default options with any runtime options
this.options = {
...(this.constructor as typeof BaseEmbeddingsProvider).defaultOptions,
...options,
};
this.fetch = fetch;
this.id = this.options.model || this.constructor.name;
}

embed(chunks: string[]): Promise<number[][]> {
throw new Error("Method not implemented.");
abstract embed(chunks: string[]): Promise<number[][]>;

static getBatchedChunks(chunks: string[]): string[][] {
if (!this.maxBatchSize) {
console.warn(
`${this.getBatchedChunks.name} should only be called if 'maxBatchSize' is defined`,
);

return [chunks];
}

if (chunks.length > this.maxBatchSize) {
return [chunks];
}

const batchedChunks = [];

for (let i = 0; i < chunks.length; i += this.maxBatchSize) {
const batchSizedChunk = chunks.slice(i, i + this.maxBatchSize);
batchedChunks.push(batchSizedChunk);
}

return batchedChunks;
}
}

Expand Down
4 changes: 0 additions & 4 deletions core/indexing/embeddings/CohereEmbeddingsProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,6 @@ class CohereEmbeddingsProvider extends BaseEmbeddingsProvider {
model: "embed-english-v3.0",
};

get id(): string {
return this.options.model ?? "cohere";
}

async embed(chunks: string[]) {
if (!this.options.apiBase?.endsWith("/")) {
this.options.apiBase += "/";
Expand Down
4 changes: 0 additions & 4 deletions core/indexing/embeddings/DeepInfraEmbeddingsProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@ class DeepInfraEmbeddingsProvider extends BaseEmbeddingsProvider {
model: "sentence-transformers/all-MiniLM-L6-v2",
};

get id(): string {
return this.options.model ?? "deepinfra";
}

async embed(chunks: string[]) {
const fetchWithBackoff = () =>
withExponentialBackoff<Response>(() =>
Expand Down
5 changes: 1 addition & 4 deletions core/indexing/embeddings/FreeTrialEmbeddingsProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,11 @@ import BaseEmbeddingsProvider from "./BaseEmbeddingsProvider.js";

class FreeTrialEmbeddingsProvider extends BaseEmbeddingsProvider {
static maxBatchSize = 128;

static defaultOptions: Partial<EmbedOptions> | undefined = {
model: "voyage-code-2",
};

get id(): string {
return FreeTrialEmbeddingsProvider.defaultOptions?.model!;
}

async embed(chunks: string[]) {
const batchedChunks = [];
for (
Expand Down
72 changes: 72 additions & 0 deletions core/indexing/embeddings/GeminiEmbeddingsProvider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { Response } from "node-fetch";
import { withExponentialBackoff } from "../../util/withExponentialBackoff.js";
import BaseEmbeddingsProvider, {
IBaseEmbeddingsProvider,
} from "./BaseEmbeddingsProvider.js";
import {
EmbedContentRequest,
EmbedContentResponse,
} from "@google/generative-ai";

/**
* [View the Gemini Text Embedding docs.](https://ai.google.dev/gemini-api/docs/models/gemini#text-embedding-and-embedding)
*/
class GeminiEmbeddingsProvider extends BaseEmbeddingsProvider {
static maxBatchSize = 2048;

static defaultOptions = {
apiBase: "https://generativelanguage.googleapis.com/v1/",
model: "models/text-embedding-004",
};

get urlPath(): string {
return `${this.options.model}:embedContent`;
}

async getSingleBatchEmbedding(batch: string[]) {
const body: EmbedContentRequest = {
content: {
/**
* Listed as optional in the [docs](https://ai.google.dev/api/rest/v1/Content)
* but is required in the interface.
*/
role: "user",
parts: batch.map((part) => ({ text: part })),
},
};

const fetchWithBackoff = () =>
withExponentialBackoff<Response>(() =>
this.fetch(new URL(this.urlPath, this.options.apiBase), {
method: "POST",
body: JSON.stringify(body),
headers: {
// eslint-disable-next-line @typescript-eslint/naming-convention
"x-goog-api-key": this.options.apiKey,
// eslint-disable-next-line @typescript-eslint/naming-convention
"Content-Type": "application/json",
},
}),
);

const resp = await fetchWithBackoff();

if (!resp.ok) {
throw new Error(await resp.text());
}

const data = (await resp.json()) as EmbedContentResponse;

return data.embedding.values;
}

async embed(chunks: string[]) {
const batches = GeminiEmbeddingsProvider.getBatchedChunks(chunks);

return await Promise.all(
batches.map((batch) => this.getSingleBatchEmbedding(batch)),
);
}
}

export default GeminiEmbeddingsProvider;
12 changes: 6 additions & 6 deletions core/indexing/embeddings/OllamaEmbeddingsProvider.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { EmbedOptions, FetchFunction } from "../../index.js";
import { withExponentialBackoff } from "../../util/withExponentialBackoff.js";
import BaseEmbeddingsProvider from "./BaseEmbeddingsProvider.js";
import BaseEmbeddingsProvider, {
IBaseEmbeddingsProvider,
} from "./BaseEmbeddingsProvider.js";

async function embedOne(
chunk: string,
Expand All @@ -18,6 +20,7 @@ async function embedOne(
}),
);
const resp = await fetchWithBackoff();

if (!resp.ok) {
throw new Error(`Failed to embed chunk: ${await resp.text()}`);
}
Expand All @@ -26,14 +29,11 @@ async function embedOne(
}

class OllamaEmbeddingsProvider extends BaseEmbeddingsProvider {
static defaultOptions: Partial<EmbedOptions> | undefined = {
static defaultOptions: IBaseEmbeddingsProvider["defaultOptions"] = {
apiBase: "http://localhost:11434/",
model: "nomic-embed-text",
};

get id(): string {
return this.options.model ?? "ollama";
}

async embed(chunks: string[]) {
const results: any = [];
for (const chunk of chunks) {
Expand Down
4 changes: 0 additions & 4 deletions core/indexing/embeddings/OpenAIEmbeddingsProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,6 @@ class OpenAIEmbeddingsProvider extends BaseEmbeddingsProvider {
model: "text-embedding-3-small",
};

get id(): string {
return this.options.model ?? "openai";
}

async embed(chunks: string[]) {
if (!this.options.apiBase?.endsWith("/")) {
this.options.apiBase += "/";
Expand Down
15 changes: 4 additions & 11 deletions core/indexing/embeddings/TransformersJsEmbeddingsProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,10 @@ class EmbeddingsPipeline {
}

export class TransformersJsEmbeddingsProvider extends BaseEmbeddingsProvider {
static MaxGroupSize: number = 4;
static maxGroupSize: number = 4;

constructor(modelPath?: string) {
constructor() {
super({ model: "all-MiniLM-L2-v6" }, () => Promise.resolve(null));
if (modelPath) {
// env.localModelPath = modelPath;
}
}

get id(): string {
return EmbeddingsPipeline.model;
}

async embed(chunks: string[]) {
Expand All @@ -65,11 +58,11 @@ export class TransformersJsEmbeddingsProvider extends BaseEmbeddingsProvider {
for (
let i = 0;
i < chunks.length;
i += TransformersJsEmbeddingsProvider.MaxGroupSize
i += TransformersJsEmbeddingsProvider.maxGroupSize
) {
const chunkGroup = chunks.slice(
i,
i + TransformersJsEmbeddingsProvider.MaxGroupSize,
i + TransformersJsEmbeddingsProvider.maxGroupSize,
);
const output = await extractor(chunkGroup, {
pooling: "mean",
Expand Down
4 changes: 2 additions & 2 deletions core/indexing/embeddings/TransformersJsWorkerThread.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@ parentPort.on("message", async (chunks) => {
for (
let i = 0;
i < chunks.length;
i += TransformersJsEmbeddingsProvider.MaxGroupSize
i += TransformersJsEmbeddingsProvider.maxGroupSize
) {
const chunkGroup = chunks.slice(
i,
i + TransformersJsEmbeddingsProvider.MaxGroupSize,
i + TransformersJsEmbeddingsProvider.maxGroupSize,
);
const output = await extractor(chunkGroup, {
pooling: "mean",
Expand Down
Loading

0 comments on commit 81cddec

Please sign in to comment.