From 79b4da7e0afe773d161d2e50688dd31791efa1e1 Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Mon, 17 Jul 2023 12:05:03 -0700 Subject: match vscode color theme --- continuedev/src/continuedev/libs/util/dedent.py | 25 ----------- continuedev/src/continuedev/libs/util/strings.py | 49 ++++++++++++++++++++++ continuedev/src/continuedev/steps/chat.py | 8 ++-- continuedev/src/continuedev/steps/core/core.py | 17 ++------ extension/package-lock.json | 4 +- extension/package.json | 2 +- extension/react-app/src/components/ComboBox.tsx | 10 +++-- .../react-app/src/components/InputAndButton.tsx | 10 ++--- extension/react-app/src/components/PillButton.tsx | 9 +++- .../react-app/src/components/StepContainer.tsx | 12 ++++-- extension/react-app/src/components/TextDialog.tsx | 14 ++++--- extension/react-app/src/components/index.ts | 23 ++++++---- extension/react-app/src/index.css | 4 +- extension/react-app/src/pages/gui.tsx | 11 +++-- 14 files changed, 119 insertions(+), 79 deletions(-) delete mode 100644 continuedev/src/continuedev/libs/util/dedent.py create mode 100644 continuedev/src/continuedev/libs/util/strings.py diff --git a/continuedev/src/continuedev/libs/util/dedent.py b/continuedev/src/continuedev/libs/util/dedent.py deleted file mode 100644 index e59c2e97..00000000 --- a/continuedev/src/continuedev/libs/util/dedent.py +++ /dev/null @@ -1,25 +0,0 @@ -from typing import Tuple - - -def dedent_and_get_common_whitespace(s: str) -> Tuple[str, str]: - lines = s.splitlines() - if len(lines) == 0: - return "", "" - - # Longest common whitespace prefix - lcp = lines[0].split(lines[0].strip())[0] - # Iterate through the lines - for i in range(1, len(lines)): - # Empty lines are wildcards - if lines[i].strip() == "": - continue - # Iterate through the leading whitespace characters of the current line - for j in range(0, len(lcp)): - # If it doesn't have the same whitespace as lcp, then update lcp - if j >= len(lines[i]) or lcp[j] != lines[i][j]: - lcp = lcp[:j] - if lcp == "": - return s, "" - break - - return "\n".join(map(lambda x: x.lstrip(lcp), lines)), lcp diff --git a/continuedev/src/continuedev/libs/util/strings.py b/continuedev/src/continuedev/libs/util/strings.py new file mode 100644 index 00000000..f1fb8d0b --- /dev/null +++ b/continuedev/src/continuedev/libs/util/strings.py @@ -0,0 +1,49 @@ +from typing import Tuple + + +def dedent_and_get_common_whitespace(s: str) -> Tuple[str, str]: + lines = s.splitlines() + if len(lines) == 0: + return "", "" + + # Longest common whitespace prefix + lcp = lines[0].split(lines[0].strip())[0] + # Iterate through the lines + for i in range(1, len(lines)): + # Empty lines are wildcards + if lines[i].strip() == "": + continue + # Iterate through the leading whitespace characters of the current line + for j in range(0, len(lcp)): + # If it doesn't have the same whitespace as lcp, then update lcp + if j >= len(lines[i]) or lcp[j] != lines[i][j]: + lcp = lcp[:j] + if lcp == "": + return s, "" + break + + return "\n".join(map(lambda x: x.lstrip(lcp), lines)), lcp + + +def remove_quotes_and_escapes(output: str) -> str: + """ + Clean up the output of the completion API, removing unnecessary escapes and quotes + """ + output = output.strip() + + # Replace smart quotes + output = output.replace("“", '"') + output = output.replace("”", '"') + output = output.replace("‘", "'") + output = output.replace("’", "'") + + # Remove escapes + output = output.replace('\\"', '"') + output = output.replace("\\'", "'") + output = output.replace("\\n", "\n") + output = output.replace("\\t", "\t") + output = output.replace("\\\\", "\\") + if (output.startswith('"') and output.endswith('"')) or (output.startswith("'") and output.endswith("'")): + output = output[1:-1] + + return output diff --git a/continuedev/src/continuedev/steps/chat.py b/continuedev/src/continuedev/steps/chat.py index 3751dec2..7c6b42db 100644 --- a/continuedev/src/continuedev/steps/chat.py +++ b/continuedev/src/continuedev/steps/chat.py @@ -3,6 +3,7 @@ from typing import Any, Coroutine, List from pydantic import Field +from ..libs.util.strings import remove_quotes_and_escapes from .main import EditHighlightedCodeStep from .core.core import MessageStep from ..core.main import FunctionCall, Models @@ -43,11 +44,8 @@ class SimpleChatStep(Step): finally: await generator.aclose() - self.name = (await sdk.models.gpt35.complete( - f"Write a short title for the following chat message: {self.description}")).strip() - - if self.name.startswith('"') and self.name.endswith('"'): - self.name = self.name[1:-1] + self.name = remove_quotes_and_escapes(await sdk.models.gpt35.complete( + f"Write a short title for the following chat message: {self.description}")) self.chat_context.append(ChatMessage( role="assistant", diff --git a/continuedev/src/continuedev/steps/core/core.py b/continuedev/src/continuedev/steps/core/core.py index d5a7cd9a..5b9b9fd5 100644 --- a/continuedev/src/continuedev/steps/core/core.py +++ b/continuedev/src/continuedev/steps/core/core.py @@ -12,7 +12,7 @@ from ...models.filesystem import FileSystem, RangeInFile, RangeInFileWithContent from ...core.observation import Observation, TextObservation, TracebackObservation, UserInputObservation from ...core.main import ChatMessage, ContinueCustomException, Step, SequentialStep from ...libs.util.count_tokens import MAX_TOKENS_FOR_MODEL, DEFAULT_MAX_TOKENS -from ...libs.util.dedent import dedent_and_get_common_whitespace +from ...libs.util.strings import dedent_and_get_common_whitespace, remove_quotes_and_escapes import difflib @@ -157,17 +157,6 @@ class DefaultModelEditCodeStep(Step): _new_contents: str = "" _prompt_and_completion: str = "" - def _cleanup_output(self, output: str) -> str: - output = output.replace('\\"', '"') - output = output.replace("\\'", "'") - output = output.replace("\\n", "\n") - output = output.replace("\\t", "\t") - output = output.replace("\\\\", "\\") - if output.startswith('"') and output.endswith('"'): - output = output[1:-1] - - return output - async def describe(self, models: Models) -> Coroutine[str, None, None]: if self._previous_contents.strip() == self._new_contents.strip(): description = "No edits were made" @@ -183,9 +172,9 @@ class DefaultModelEditCodeStep(Step): Please give brief a description of the changes made above using markdown bullet points. Be concise:""")) name = await models.gpt3516k.complete(f"Write a very short title to describe this requested change (no quotes): '{self.user_input}'. This is the title:") - self.name = self._cleanup_output(name) + self.name = remove_quotes_and_escapes(name) - return f"{self._cleanup_output(description)}" + return f"{remove_quotes_and_escapes(description)}" async def get_prompt_parts(self, rif: RangeInFileWithContents, sdk: ContinueSDK, full_file_contents: str): # We don't know here all of the functions being passed in. diff --git a/extension/package-lock.json b/extension/package-lock.json index 33f81dec..0e0125b0 100644 --- a/extension/package-lock.json +++ b/extension/package-lock.json @@ -1,12 +1,12 @@ { "name": "continue", - "version": "0.0.176", + "version": "0.0.177", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "continue", - "version": "0.0.176", + "version": "0.0.177", "license": "Apache-2.0", "dependencies": { "@electron/rebuild": "^3.2.10", diff --git a/extension/package.json b/extension/package.json index e515ed36..8462bf68 100644 --- a/extension/package.json +++ b/extension/package.json @@ -14,7 +14,7 @@ "displayName": "Continue", "pricing": "Free", "description": "The open-source coding autopilot", - "version": "0.0.176", + "version": "0.0.177", "publisher": "Continue", "engines": { "vscode": "^1.67.0" diff --git a/extension/react-app/src/components/ComboBox.tsx b/extension/react-app/src/components/ComboBox.tsx index dbebd534..0ea8a3e1 100644 --- a/extension/react-app/src/components/ComboBox.tsx +++ b/extension/react-app/src/components/ComboBox.tsx @@ -6,6 +6,7 @@ import { lightGray, secondaryDark, vscBackground, + vscForeground, } from "."; import CodeBlock from "./CodeBlock"; import PillButton from "./PillButton"; @@ -48,7 +49,7 @@ const MainTextInput = styled.textarea` height: auto; width: 100%; background-color: ${secondaryDark}; - color: white; + color: ${vscForeground}; z-index: 1; border: 1px solid transparent; @@ -71,7 +72,7 @@ const Ul = styled.ul<{ position: absolute; background: ${vscBackground}; background-color: ${secondaryDark}; - color: white; + color: ${vscForeground}; max-height: ${UlMaxHeight}px; width: calc(100% - 16px); overflow-y: scroll; @@ -95,6 +96,7 @@ const Li = styled.li<{ selected: boolean; isLastItem: boolean; }>` + background-color: ${secondaryDark}; ${({ highlighted }) => highlighted && "background: #ff000066;"} ${({ selected }) => selected && "font-weight: bold;"} padding: 0.5rem 0.75rem; @@ -218,7 +220,9 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => { ? "Editing such a large range may be slow" : undefined } - onlyShowDelete={highlightedCodeSections.length <= 1} + onlyShowDelete={ + highlightedCodeSections.length <= 1 || section.editing + } editing={section.editing} pinned={section.pinned} index={idx} diff --git a/extension/react-app/src/components/InputAndButton.tsx b/extension/react-app/src/components/InputAndButton.tsx index 0a8592f2..8019d014 100644 --- a/extension/react-app/src/components/InputAndButton.tsx +++ b/extension/react-app/src/components/InputAndButton.tsx @@ -1,6 +1,6 @@ import React, { useRef } from "react"; import styled from "styled-components"; -import { vscBackground } from "."; +import { vscBackground, vscForeground } from "."; interface InputAndButtonProps { onUserInput: (input: string) => void; @@ -16,7 +16,7 @@ const Input = styled.input` padding: 0.5rem; border: 1px solid white; background-color: ${vscBackground}; - color: white; + color: ${vscForeground}; border-radius: 4px; border-top-right-radius: 0; border-bottom-right-radius: 0; @@ -27,7 +27,7 @@ const Button = styled.button` padding: 0.5rem; border: 1px solid white; background-color: ${vscBackground}; - color: white; + color: ${vscForeground}; border-radius: 4px; border-top-left-radius: 0; border-bottom-left-radius: 0; @@ -35,8 +35,8 @@ const Button = styled.button` cursor: pointer; &:hover { - background-color: white; - color: black; + background-color: ${vscForeground}; + color: ${vscBackground}; } `; diff --git a/extension/react-app/src/components/PillButton.tsx b/extension/react-app/src/components/PillButton.tsx index 5a16516e..eba5cf8f 100644 --- a/extension/react-app/src/components/PillButton.tsx +++ b/extension/react-app/src/components/PillButton.tsx @@ -1,6 +1,11 @@ import { useContext, useState } from "react"; import styled from "styled-components"; -import { StyledTooltip, defaultBorderRadius, secondaryDark } from "."; +import { + StyledTooltip, + defaultBorderRadius, + secondaryDark, + vscForeground, +} from "."; import { Trash, PaintBrush, @@ -10,7 +15,7 @@ import { GUIClientContext } from "../App"; const Button = styled.button` border: none; - color: white; + color: ${vscForeground}; background-color: ${secondaryDark}; border-radius: ${defaultBorderRadius}; padding: 8px; diff --git a/extension/react-app/src/components/StepContainer.tsx b/extension/react-app/src/components/StepContainer.tsx index 93bdbc89..26bc8e33 100644 --- a/extension/react-app/src/components/StepContainer.tsx +++ b/extension/react-app/src/components/StepContainer.tsx @@ -6,6 +6,7 @@ import { secondaryDark, vscBackground, vscBackgroundTransparent, + vscForeground, } from "."; import { ChevronDown, @@ -120,20 +121,22 @@ const StyledMarkdownPreview = styled(MarkdownPreview)` } code { - color: #f69292; + color: #f78383; word-wrap: break-word; + border-radius: ${defaultBorderRadius}; + background-color: ${secondaryDark}; } pre > code { background-color: ${secondaryDark}; - color: white; + color: ${vscForeground}; } background-color: ${vscBackground}; font-family: "Lexend", sans-serif; font-size: 13px; padding: 8px; - color: white; + color: ${vscForeground}; `; // #endregion @@ -267,6 +270,9 @@ function StepContainer(props: StepContainerProps) { ) : ( )} diff --git a/extension/react-app/src/components/TextDialog.tsx b/extension/react-app/src/components/TextDialog.tsx index 646d6846..cba3852d 100644 --- a/extension/react-app/src/components/TextDialog.tsx +++ b/extension/react-app/src/components/TextDialog.tsx @@ -1,7 +1,7 @@ // Write a component that displays a dialog box with a text field and a button. import React, { useEffect, useState } from "react"; import styled from "styled-components"; -import { Button, buttonColor, secondaryDark, vscBackground } from "."; +import { Button, secondaryDark, vscBackground, vscForeground } from "."; import { isMetaEquivalentKeyPressed } from "../util"; const ScreenCover = styled.div` @@ -21,13 +21,13 @@ const DialogContainer = styled.div` `; const Dialog = styled.div` - background-color: white; + color: ${vscForeground}; + background-color: ${vscBackground}; border-radius: 8px; padding: 8px; display: flex; flex-direction: column; - /* box-shadow: 0 0 10px 0 rgba(255, 255, 255, 0.5); */ - border: 2px solid ${buttonColor}; + box-shadow: 0 0 10px 0 ${vscForeground}; width: fit-content; margin: auto; `; @@ -38,14 +38,16 @@ const TextArea = styled.textarea` padding: 8px; outline: 1px solid black; resize: none; + background-color: ${secondaryDark}; + color: ${vscForeground}; &:focus { - outline: 1px solid ${buttonColor}; + outline: 1px solid ${vscForeground}; } `; const P = styled.p` - color: black; + color: ${vscForeground}; margin: 8px auto; `; diff --git a/extension/react-app/src/components/index.ts b/extension/react-app/src/components/index.ts index 9ae0f097..cb5e7915 100644 --- a/extension/react-app/src/components/index.ts +++ b/extension/react-app/src/components/index.ts @@ -3,12 +3,16 @@ import styled, { keyframes } from "styled-components"; export const defaultBorderRadius = "5px"; export const lightGray = "rgb(100 100 100)"; -export const secondaryDark = "rgb(45 45 45)"; -export const vscBackground = "rgb(30 30 30)"; +// export const secondaryDark = "rgb(45 45 45)"; +// export const vscBackground = "rgb(30 30 30)"; export const vscBackgroundTransparent = "#1e1e1ede"; export const buttonColor = "rgb(113 28 59)"; export const buttonColorHover = "rgb(113 28 59 0.67)"; +export const secondaryDark = "var(--vscode-textBlockQuote-background)"; +export const vscBackground = "var(--vscode-editor-background)"; +export const vscForeground = "var(--vscode-editor-foreground)"; + export const Button = styled.button` padding: 10px 12px; margin: 8px 0; @@ -46,8 +50,8 @@ export const TextArea = styled.textarea` resize: vertical; padding: 4px; - caret-color: white; - color: white; + caret-color: ${vscForeground}; + color: #{vscForeground}; &:focus { outline: 1px solid ${buttonColor}; @@ -120,7 +124,7 @@ export const MainTextInput = styled.textarea` border: 1px solid #ccc; margin: 8px 8px; background-color: ${vscBackground}; - color: white; + color: ${vscForeground}; outline: 1px solid orange; resize: none; `; @@ -137,8 +141,9 @@ export const appear = keyframes` `; export const HeaderButton = styled.button<{ inverted: boolean | undefined }>` - background-color: ${({ inverted }) => (inverted ? "white" : "transparent")}; - color: ${({ inverted }) => (inverted ? "black" : "white")}; + background-color: ${({ inverted }) => + inverted ? vscForeground : "transparent"}; + color: ${({ inverted }) => (inverted ? vscBackground : vscForeground)}; border: none; border-radius: ${defaultBorderRadius}; @@ -146,7 +151,9 @@ export const HeaderButton = styled.button<{ inverted: boolean | undefined }>` &:hover { background-color: ${({ inverted }) => - typeof inverted === "undefined" || inverted ? lightGray : "transparent"}; + typeof inverted === "undefined" || inverted + ? secondaryDark + : "transparent"}; } display: flex; align-items: center; diff --git a/extension/react-app/src/index.css b/extension/react-app/src/index.css index 6e33c89c..bac7fe97 100644 --- a/extension/react-app/src/index.css +++ b/extension/react-app/src/index.css @@ -14,13 +14,13 @@ html, body, #root { height: 100%; - background-color: var(--vsc-background); + background-color: var(--vscode-editor-background); font-family: "Lexend", sans-serif; } body { padding: 0; - color: white; + color: var(--vscode-editor-foreground); padding: 0px; margin: 0px; height: 100%; diff --git a/extension/react-app/src/pages/gui.tsx b/extension/react-app/src/pages/gui.tsx index 64207487..c35cf21b 100644 --- a/extension/react-app/src/pages/gui.tsx +++ b/extension/react-app/src/pages/gui.tsx @@ -1,5 +1,9 @@ import styled from "styled-components"; -import { defaultBorderRadius } from "../components"; +import { + defaultBorderRadius, + vscBackground, + vscForeground, +} from "../components"; import Loader from "../components/Loader"; import ContinueButton from "../components/ContinueButton"; import { FullState, HighlightedRangeContext } from "../../../schema/FullState"; @@ -371,12 +375,13 @@ function GUI(props: GUIProps) { style={{ position: "fixed", bottom: "50px", - backgroundColor: "white", - color: "black", + backgroundColor: vscBackground, + color: vscForeground, borderRadius: defaultBorderRadius, padding: "16px", margin: "16px", zIndex: 100, + boxShadow: `0px 0px 10px 0px ${vscForeground}`, }} hidden={!showDataSharingInfo} > -- cgit v1.2.3-70-g09d2 From e65a15f50d226acd802ffc580306e1477394ffe0 Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Mon, 17 Jul 2023 12:24:22 -0700 Subject: disambiguate highlighted ranges with dirname --- continuedev/src/continuedev/core/autopilot.py | 17 +++++++++++++++++ extension/react-app/src/components/StepContainer.tsx | 7 +------ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/continuedev/src/continuedev/core/autopilot.py b/continuedev/src/continuedev/core/autopilot.py index 0696c360..fb8da2e8 100644 --- a/continuedev/src/continuedev/core/autopilot.py +++ b/continuedev/src/continuedev/core/autopilot.py @@ -166,6 +166,22 @@ class Autopilot(ContinueBaseModel): if not any(map(lambda x: x.editing, self._highlighted_ranges)): self._highlighted_ranges[0].editing = True + def _disambiguate_highlighted_ranges(self): + """If any files have the same name, also display their folder name""" + name_counts = {} + for rif in self._highlighted_ranges: + if rif.display_name in name_counts: + name_counts[rif.display_name] += 1 + else: + name_counts[rif.display_name] = 1 + + for rif in self._highlighted_ranges: + if name_counts[rif.display_name] > 1: + rif.display_name = os.path.join( + os.path.basename(os.path.dirname(rif.range.filepath)), rif.display_name) + else: + rif.display_name = os.path.basename(rif.range.filepath) + async def handle_highlighted_code(self, range_in_files: List[RangeInFileWithContents]): # Filter out rifs from ~/.continue/diffs folder range_in_files = [ @@ -211,6 +227,7 @@ class Autopilot(ContinueBaseModel): ) for rif in range_in_files] self._make_sure_is_editing_range() + self._disambiguate_highlighted_ranges() await self.update_subscribers() diff --git a/extension/react-app/src/components/StepContainer.tsx b/extension/react-app/src/components/StepContainer.tsx index 26bc8e33..9ab7430c 100644 --- a/extension/react-app/src/components/StepContainer.tsx +++ b/extension/react-app/src/components/StepContainer.tsx @@ -53,12 +53,7 @@ const StepContainerDiv = styled.div<{ open: boolean }>` `; const HeaderDiv = styled.div<{ error: boolean; loading: boolean }>` - background-color: ${(props) => - props.error - ? "#522" - : props.loading - ? vscBackgroundTransparent - : vscBackground}; + background-color: ${(props) => (props.error ? "#522" : vscBackground)}; display: grid; grid-template-columns: 1fr auto auto; grid-gap: 8px; -- cgit v1.2.3-70-g09d2 From 6d5c07240763b985a32bdb554d600c7423698497 Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Mon, 17 Jul 2023 12:48:10 -0700 Subject: float -> int hot fix --- continuedev/src/continuedev/steps/core/core.py | 7 ++++--- extension/package-lock.json | 4 ++-- extension/package.json | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/continuedev/src/continuedev/steps/core/core.py b/continuedev/src/continuedev/steps/core/core.py index ea09f475..2b049ecc 100644 --- a/continuedev/src/continuedev/steps/core/core.py +++ b/continuedev/src/continuedev/steps/core/core.py @@ -162,7 +162,8 @@ class DefaultModelEditCodeStep(Step): if self._previous_contents.strip() == self._new_contents.strip(): description = "No edits were made" else: - changes = '\n'.join(difflib.ndiff(self._previous_contents.splitlines(), self._new_contents.splitlines())) + changes = '\n'.join(difflib.ndiff( + self._previous_contents.splitlines(), self._new_contents.splitlines())) description = await models.gpt3516k.complete(dedent(f"""\ Diff summary: "{self.user_input}" @@ -181,8 +182,8 @@ class DefaultModelEditCodeStep(Step): # We care because if this prompt itself goes over the limit, then the entire message will have to be cut from the completion. # Overflow won't happen, but prune_chat_messages in count_tokens.py will cut out this whole thing, instead of us cutting out only as many lines as we need. model_to_use = sdk.models.default - max_tokens = MAX_TOKENS_FOR_MODEL.get( - model_to_use.name, DEFAULT_MAX_TOKENS) / 2 + max_tokens = int(MAX_TOKENS_FOR_MODEL.get( + model_to_use.name, DEFAULT_MAX_TOKENS) / 2) TOKENS_TO_BE_CONSIDERED_LARGE_RANGE = 1200 if model_to_use.count_tokens(rif.contents) > TOKENS_TO_BE_CONSIDERED_LARGE_RANGE: diff --git a/extension/package-lock.json b/extension/package-lock.json index 0e0125b0..e67fa950 100644 --- a/extension/package-lock.json +++ b/extension/package-lock.json @@ -1,12 +1,12 @@ { "name": "continue", - "version": "0.0.177", + "version": "0.0.178", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "continue", - "version": "0.0.177", + "version": "0.0.178", "license": "Apache-2.0", "dependencies": { "@electron/rebuild": "^3.2.10", diff --git a/extension/package.json b/extension/package.json index 8462bf68..121423ed 100644 --- a/extension/package.json +++ b/extension/package.json @@ -14,7 +14,7 @@ "displayName": "Continue", "pricing": "Free", "description": "The open-source coding autopilot", - "version": "0.0.177", + "version": "0.0.178", "publisher": "Continue", "engines": { "vscode": "^1.67.0" -- cgit v1.2.3-70-g09d2 From 6b708464d76a92e12dac40081cc51ba35f7fc0d0 Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Mon, 17 Jul 2023 13:30:47 -0700 Subject: support for azure endpoints --- continuedev/src/continuedev/core/autopilot.py | 2 +- continuedev/src/continuedev/core/config.py | 8 +++++++- continuedev/src/continuedev/core/sdk.py | 2 +- continuedev/src/continuedev/libs/llm/openai.py | 19 +++++++++++++++---- 4 files changed, 24 insertions(+), 7 deletions(-) diff --git a/continuedev/src/continuedev/core/autopilot.py b/continuedev/src/continuedev/core/autopilot.py index fb8da2e8..4e177ac9 100644 --- a/continuedev/src/continuedev/core/autopilot.py +++ b/continuedev/src/continuedev/core/autopilot.py @@ -36,7 +36,7 @@ def get_error_title(e: Exception) -> str: elif isinstance(e, openai_errors.APIConnectionError): return "The request failed. Please check your internet connection and try again. If this issue persists, you can use our API key for free by going to VS Code settings and changing the value of continue.OPENAI_API_KEY to \"\"" elif isinstance(e, openai_errors.InvalidRequestError): - return 'Your API key does not have access to GPT-4. You can use ours for free by going to VS Code settings and changing the value of continue.OPENAI_API_KEY to ""' + return 'Invalid request sent to OpenAI. Please try again.' elif e.__str__().startswith("Cannot connect to host"): return "The request failed. Please check your internet connection and try again." return e.__str__() or e.__repr__() diff --git a/continuedev/src/continuedev/core/config.py b/continuedev/src/continuedev/core/config.py index 91a47c8e..98615c64 100644 --- a/continuedev/src/continuedev/core/config.py +++ b/continuedev/src/continuedev/core/config.py @@ -67,13 +67,18 @@ DEFAULT_SLASH_COMMANDS = [ ] +class AzureInfo(BaseModel): + endpoint: str + engine: str + api_version: str + + class ContinueConfig(BaseModel): """ A pydantic class for the continue config file. """ steps_on_startup: Optional[Dict[str, Dict]] = {} disallowed_steps: Optional[List[str]] = [] - server_url: Optional[str] = None allow_anonymous_telemetry: Optional[bool] = True default_model: Literal["gpt-3.5-turbo", "gpt-3.5-turbo-16k", "gpt-4", "ggml"] = 'gpt-4' @@ -86,6 +91,7 @@ class ContinueConfig(BaseModel): on_traceback: Optional[List[OnTracebackSteps]] = [ OnTracebackSteps(step_name="DefaultOnTracebackStep")] system_message: Optional[str] = None + azure_openai_info: Optional[AzureInfo] = None # Want to force these to be the slash commands for now @validator('slash_commands', pre=True) diff --git a/continuedev/src/continuedev/core/sdk.py b/continuedev/src/continuedev/core/sdk.py index ac57c122..7e612d3b 100644 --- a/continuedev/src/continuedev/core/sdk.py +++ b/continuedev/src/continuedev/core/sdk.py @@ -56,7 +56,7 @@ class Models: api_key = self.provider_keys["openai"] if api_key == "": return ProxyServer(self.sdk.ide.unique_id, model, system_message=self.system_message) - return OpenAI(api_key=api_key, default_model=model, system_message=self.system_message) + return OpenAI(api_key=api_key, default_model=model, system_message=self.system_message, azure_info=self.sdk.config.azure_openai_info) def __load_hf_inference_api_model(self, model: str) -> HuggingFaceInferenceAPI: api_key = self.provider_keys["hf_inference_api"] diff --git a/continuedev/src/continuedev/libs/llm/openai.py b/continuedev/src/continuedev/libs/llm/openai.py index d973f19e..33d10985 100644 --- a/continuedev/src/continuedev/libs/llm/openai.py +++ b/continuedev/src/continuedev/libs/llm/openai.py @@ -1,30 +1,41 @@ from functools import cached_property -import time from typing import Any, Coroutine, Dict, Generator, List, Union + from ...core.main import ChatMessage import openai from ..llm import LLM -from ..util.count_tokens import DEFAULT_MAX_TOKENS, compile_chat_messages, CHAT_MODELS, DEFAULT_ARGS, count_tokens, prune_raw_prompt_from_top +from ..util.count_tokens import compile_chat_messages, CHAT_MODELS, DEFAULT_ARGS, count_tokens, prune_raw_prompt_from_top +from ...core.config import AzureInfo class OpenAI(LLM): api_key: str default_model: str - def __init__(self, api_key: str, default_model: str, system_message: str = None): + def __init__(self, api_key: str, default_model: str, system_message: str = None, azure_info: AzureInfo = None): self.api_key = api_key self.default_model = default_model self.system_message = system_message + self.azure_info = azure_info openai.api_key = api_key + # Using an Azure OpenAI deployment + if azure_info is not None: + openai.api_type = "azure" + openai.api_base = azure_info.endpoint + openai.api_version = azure_info.api_version + @cached_property def name(self): return self.default_model @property def default_args(self): - return {**DEFAULT_ARGS, "model": self.default_model} + args = {**DEFAULT_ARGS, "model": self.default_model} + if self.azure_info is not None: + args["engine"] = self.azure_info.engine + return args def count_tokens(self, text: str): return count_tokens(self.default_model, text) -- cgit v1.2.3-70-g09d2