Skip to content

Commit

Permalink
feat: validate api key before saving config (#126)
Browse files Browse the repository at this point in the history
* feature: validate api key before saving config

* frontend code

* remove print statements from backend api

* cleanup for draft PR

* pass openai error messaging to front-end modal

* allow custom title for ErrorNotification component
  • Loading branch information
NikoRaisanen authored Sep 8, 2023
1 parent d9d2590 commit 58fd9dd
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 28 deletions.
Empty file added backend/config/__init__.py
Empty file.
18 changes: 18 additions & 0 deletions backend/config/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import openai

def is_valid_api_key(openai_api_key: str):
openai.api_key = openai_api_key
try:
openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": "You are a helpful assistant."}
]
)
return { 'validApiKey': True }
except Exception as e:
return {
'validApiKey': False,
'message': e.error.message
}

5 changes: 4 additions & 1 deletion backend/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from schemas.question import Question, Document
from schemas.file import UploadRequestBody
from schemas.prompt import Prompt
from config import utils
from utils import FILE_HANDLERS
from embeddings.index_files import Genie
from loaders.website_loader import extract_text_from_website
Expand Down Expand Up @@ -67,6 +68,9 @@ async def capture_posthog():

return response

@app.post("/config/validate-api-key/")
def validate_api_key(config: Config):
return utils.is_valid_api_key(config.apiKey)

@app.get("/config/")
def get_config():
Expand All @@ -75,7 +79,6 @@ def get_config():
return False
return True


@app.post("/config/")
def add_config(config: Config):
db = Database().get_session()
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/renderer/components/ErrorNotification.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { notifications } from '@mantine/notifications';

export function ErrorNotification(endpoint, method) {
export function ErrorNotification(endpoint, method, customMsg=null, title="Error!") {
notifications.show({
title: "Error!",
message: "An error occurred with the " + method + " request to endpoint " + endpoint,
title: title,
message: customMsg || "An error occurred with the " + method + " request to endpoint " + endpoint,
color: 'red',
autoClose: false,
});
Expand Down
54 changes: 30 additions & 24 deletions frontend/src/renderer/pages/config/Config.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,43 @@ import {connect, disconnect} from '../../store/slices/externalDbSlice';
import {apiCall} from "../../utils/api";
import {useState} from "react";
import PromptConfiguration from "./PromptConfig";

import { ErrorNotification } from "../../../renderer/components/ErrorNotification";

function saveConfig(OPENAI_API_KEY: string, model: string, embeddingsmodel: string) {
const payload = {
apiKey: OPENAI_API_KEY,
model: model,
embeddingsModel: embeddingsmodel
};

// validate api key before saving config
return apiCall('/config/validate-api-key', 'POST', payload).then((response) => {
if (response?.data.validApiKey === false) return ErrorNotification('/config/validate-api-key', 'POST', response?.data.message, 'Invalid OpenAI API Key');

apiCall('/config', 'POST', payload).then((response) => {
const fetchedConfig = response.data;
console.log(fetchedConfig);

if (Object.keys(fetchedConfig).length === 0) {
return false;
}

// The fetched config is not an empty object, save it and return true
localStorage.setItem('config', JSON.stringify(fetchedConfig));
console.log(fetchedConfig);
window.location.reload();

return true;
})
.catch((error) => {
console.log('Error fetching config:', error);
return false;
}
);
}).catch((error) => {
console.log('error:', error)
return false;
});
// return axios.post(`${config.REACT_APP_BACKEND_URL}/config`, payload)
// .then((response) => {
// const fetchedConfig = response.data;
Expand All @@ -38,36 +67,13 @@ function saveConfig(OPENAI_API_KEY: string, model: string, embeddingsmodel: stri
// return false;
// });
// }
return apiCall('/config', 'POST', payload).then((response) => {
const fetchedConfig = response.data;
console.log(fetchedConfig);

if (Object.keys(fetchedConfig).length === 0) {
return false;
}

// The fetched config is not an empty object, save it and return true
localStorage.setItem('config', JSON.stringify(fetchedConfig));
console.log(fetchedConfig);
window.location.reload();

return true;
}
)
.catch((error) => {
console.log('Error fetching config:', error);
return false;
}
);
}

function Config() {
const isConnected = useSelector((state) => state.connectedExternalDb.value);
const dispatch = useDispatch();
const [opened, {open, close}] = useDisclosure(false);
const [focused, setFocused] = useState(false);


const form = useForm({
initialValues: {
OPENAI_API_KEY: '',
Expand Down

1 comment on commit 58fd9dd

@vercel
Copy link

@vercel vercel bot commented on 58fd9dd Sep 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.