Skip to content

Commit

Permalink
Prepare for 0.5.0 release (#19)
Browse files Browse the repository at this point in the history
Updates to 0.5.0 and include bug fixes associated with the merger of local mode and feedback code

Included bug fixes:
- Updates API endpoints
    - Adds `is_openai` to `/service` return
    - Removes 501 returns for disclaimer endpoints and instead returns "successful" values
    - Adds `is_openai` case to feedback endpoint that returns an "unsupported" message
- Adds a helper function to wipe `lastPrompt` value when the value becomes irrelevant
- Updates model dropdown list to remember the current model and wipes the lastPrompt value on model update
- Saves the `is_openai` value when the service url is set and only shows the feedback UI when `is_openai` is false

Weird UI edge case:
The feedback buttons are not immediately removed when the service UI is switch to an OpenAI one. The status bar is updated when you change tabs and the notebook cell toolbar is updated either when switching cells or running a completion. This is not an issue though since if the user tries to use the feedback during this edge case they will see a "unsupported" notification.
  • Loading branch information
ajbozarth authored Nov 12, 2024
1 parent 8b7d3a7 commit 912e8f1
Show file tree
Hide file tree
Showing 8 changed files with 103 additions and 56 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "qiskit-code-assistant-jupyterlab",
"version": "0.4.0",
"version": "0.5.0",
"description": "AI Autocomplete JupyterLab extension for Qiskit Code Assistant (Beta)",
"keywords": [
"jupyter",
Expand Down
37 changes: 22 additions & 15 deletions qiskit_code_assistant_jupyterlab/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,10 @@ def convert_openai(model):
class ServiceUrlHandler(APIHandler):
@tornado.web.authenticated
def get(self):
self.finish(json.dumps({"url": runtime_configs["service_url"]}))
self.finish(json.dumps({
"url": runtime_configs["service_url"],
"is_openai": runtime_configs["is_openai"]
}))

@tornado.web.authenticated
def post(self):
Expand All @@ -102,7 +105,10 @@ def post(self):
except (requests.exceptions.JSONDecodeError, KeyError):
runtime_configs["is_openai"] = True
finally:
self.finish(json.dumps({"url": runtime_configs["service_url"]}))
self.finish(json.dumps({
"url": runtime_configs["service_url"],
"is_openai": runtime_configs["is_openai"]
}))


class TokenHandler(APIHandler):
Expand Down Expand Up @@ -185,8 +191,7 @@ class DisclaimerHandler(APIHandler):
@tornado.web.authenticated
def get(self, id):
if runtime_configs["is_openai"]:
self.set_status(501, "Not implemented")
self.finish()
self.finish(json.dumps({"accepted": "true"}))
else:
url = url_path_join(runtime_configs["service_url"], "model", id, "disclaimer")

Expand All @@ -204,8 +209,7 @@ class DisclaimerAcceptanceHandler(APIHandler):
@tornado.web.authenticated
def post(self, id):
if runtime_configs["is_openai"]:
self.set_status(501, "Not implemented")
self.finish()
self.finish(json.dumps({"success": "true"}))
else:
url = url_path_join(
runtime_configs["service_url"], "disclaimer", id, "acceptance"
Expand Down Expand Up @@ -283,16 +287,19 @@ def post(self, id):
class FeedbackHandler(APIHandler):
@tornado.web.authenticated
def post(self):
url = url_path_join(runtime_configs["service_url"], "feedback")

try:
r = requests.post(url, headers=get_header(), json=self.get_json_body())
r.raise_for_status()
except requests.exceptions.HTTPError as err:
self.set_status(err.response.status_code)
self.finish(json.dumps(err.response.json()))
if runtime_configs["is_openai"]:
self.finish(json.dumps({"message": "Feedback not supported for this service"}))
else:
self.finish(json.dumps(r.json()))
url = url_path_join(runtime_configs["service_url"], "feedback")

try:
r = requests.post(url, headers=get_header(), json=self.get_json_body())
r.raise_for_status()
except requests.exceptions.HTTPError as err:
self.set_status(err.response.status_code)
self.finish(json.dumps(err.response.json()))
else:
self.finish(json.dumps(r.json()))


def setup_handlers(web_app):
Expand Down
2 changes: 2 additions & 0 deletions src/QiskitCompletionProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ const FEEDBACK_COMMAND = 'qiskit-code-assistant:prompt-feedback';

export let lastPrompt: ICompletionReturn | undefined = undefined;

export const wipeLastPrompt = () => (lastPrompt = undefined);

function getInputText(text: string, widget: Widget): string {
const cellsContents: string[] = [];

Expand Down
6 changes: 5 additions & 1 deletion src/StatusBarWidget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { Message } from '@lumino/messaging';
import { refreshIcon } from '@jupyterlab/ui-components';
import { Widget } from '@lumino/widgets';

import { wipeLastPrompt } from './QiskitCompletionProvider';
import { showDisclaimer } from './service/disclaimer';
import {
getCurrentModel,
Expand Down Expand Up @@ -70,16 +71,19 @@ export class StatusBarWidget extends Widget {
async onClick() {
await checkAPIToken().then(() => {
const modelsList = getModelsList();
const dropDownList = [...modelsList.map(m => m.display_name)];
InputDialog.getItem({
title: 'Select a Model',
items: [...modelsList.map(m => m.display_name)]
items: dropDownList,
current: dropDownList.indexOf(getCurrentModel()?.display_name || '')
}).then(result => {
if (result.button.accept) {
const model = modelsList.find(m => m.display_name === result.value);

if (model) {
showDisclaimer(model._id).then(accepted => {
if (accepted) {
wipeLastPrompt();
setCurrentModel(model);
}
});
Expand Down
29 changes: 22 additions & 7 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ import { StatusBarWidget } from './StatusBarWidget';
import {
lastPrompt,
QiskitCompletionProvider,
QiskitInlineCompletionProvider
QiskitInlineCompletionProvider,
wipeLastPrompt
} from './QiskitCompletionProvider';
import { postServiceUrl } from './service/api';
import { getFeedbackStatusBarWidget, getFeedback } from './service/feedback';
Expand Down Expand Up @@ -73,10 +74,21 @@ const plugin: JupyterFrontEndPlugin<void> = {
const settings = await settingRegistry.load(plugin.id);
console.debug(EXTENSION_ID + ' settings loaded:', settings.composite);

postServiceUrl(settings.composite['serviceUrl'] as string);
let is_openai = false;

postServiceUrl(settings.composite['serviceUrl'] as string).then(
response => {
is_openai = response.is_openai;
wipeLastPrompt();
}
);
settings.changed.connect(() =>
postServiceUrl(settings.composite['serviceUrl'] as string).then(() =>
refreshModelsList()
postServiceUrl(settings.composite['serviceUrl'] as string).then(
response => {
is_openai = response.is_openai;
wipeLastPrompt();
refreshModelsList();
}
)
);

Expand All @@ -87,7 +99,8 @@ const plugin: JupyterFrontEndPlugin<void> = {

statusBar.registerStatusItem(EXTENSION_ID + ':feedback', {
item: getFeedbackStatusBarWidget(),
align: 'left'
align: 'left',
isActive: () => !is_openai
});

const statusBarWidget = new StatusBarWidget();
Expand All @@ -104,11 +117,13 @@ const plugin: JupyterFrontEndPlugin<void> = {
label: 'Give feedback for the Qiskit Code Assistant',
icon: feedbackIcon,
execute: () => getFeedback(),
isEnabled: () => lastPrompt !== undefined,
isEnabled: () => !is_openai && lastPrompt !== undefined,
isVisible: () =>
!is_openai &&
['code', 'markdown'].includes(
notebookTracker.activeCell?.model.type || ''
) && lastPrompt !== undefined
) &&
lastPrompt !== undefined
});

app.commands.addCommand(CommandIDs.updateApiToken, {
Expand Down
10 changes: 7 additions & 3 deletions src/service/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ import {
IModelDisclaimer,
IModelInfo,
IModelPromptResponse,
IResponseMessage
IResponseMessage,
IServiceResponse
} from '../utils/schema';

const AUTH_ERROR_CODES = [401, 403, 422];
Expand All @@ -40,14 +41,17 @@ async function notifyInvalid(response: Response): Promise<void> {
}

// POST /service
export async function postServiceUrl(newUrl: string): Promise<void> {
export async function postServiceUrl(
newUrl: string
): Promise<IServiceResponse> {
return await requestAPI('service', {
method: 'POST',
body: JSON.stringify({ url: newUrl })
}).then(response => {
if (response.ok) {
response.json().then(json => {
return response.json().then(json => {
console.debug('Updated service URL:', json.url);
return json;
});
} else {
console.error(
Expand Down
5 changes: 5 additions & 0 deletions src/utils/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,8 @@ export interface IFeedbackForm {
input?: string;
output?: string;
}

export interface IServiceResponse {
url: string;
is_openai: boolean;
}
68 changes: 39 additions & 29 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1506,8 +1506,8 @@ __metadata:
linkType: hard

"@rjsf/core@npm:^5.13.4":
version: 5.22.3
resolution: "@rjsf/core@npm:5.22.3"
version: 5.22.4
resolution: "@rjsf/core@npm:5.22.4"
dependencies:
lodash: ^4.17.21
lodash-es: ^4.17.21
Expand All @@ -1517,13 +1517,13 @@ __metadata:
peerDependencies:
"@rjsf/utils": ^5.22.x
react: ^16.14.0 || >=17
checksum: 79aba03d150bd5cd1ee7051aa7036e4bdbc80528974bd88e8360f912233cdb64e5fb64f377175eb76894ce3602e8121cbe082a7a0c82d3834f3f1ffe0041d7e4
checksum: cc2d6b51959be277f727a0c8398c699bc4068cb63f3f096ddd051c35e5ba685beb5745c281d81e3906f1c92329e9468bc35f81244e48026794318c98b884dac7
languageName: node
linkType: hard

"@rjsf/utils@npm:^5.13.4":
version: 5.22.3
resolution: "@rjsf/utils@npm:5.22.3"
version: 5.22.4
resolution: "@rjsf/utils@npm:5.22.4"
dependencies:
json-schema-merge-allof: ^0.8.1
jsonpointer: ^5.0.1
Expand All @@ -1532,7 +1532,7 @@ __metadata:
react-is: ^18.2.0
peerDependencies:
react: ^16.14.0 || >=17
checksum: 3acf008c7e655f7b88aa01285e4157289da274c9a39415b8c3dcfd87bd17c1c520660bd4439c6c2ceb7c0914932a8197bd54c042a1ddbb7c4649a7c42a9be778
checksum: 7dddc74b910fb7b87ebddc564879126b100f14eee853c0fbc390faa6c5f944a70023f34925a360aa92915f4e9c56bccf57141db9fe7b3c6a97348d886794bab8
languageName: node
linkType: hard

Expand Down Expand Up @@ -2278,9 +2278,9 @@ __metadata:
linkType: hard

"caniuse-lite@npm:^1.0.30001669":
version: 1.0.30001678
resolution: "caniuse-lite@npm:1.0.30001678"
checksum: b1690df8b306b99a1ec84dc29cbdc893b569fcdc232324a9d3ebd67ce184a353ffdea93270bb6c20e3372bec8b5f6922c04a464fbd1cdeff662d459639f22a53
version: 1.0.30001680
resolution: "caniuse-lite@npm:1.0.30001680"
checksum: 2641d2b18c5ab0a6663cb350c5adc81e5ede1a7677d1c7518a8053ada87bf6f206419e1820a2608f76fa5e4f7bea327cbe47df423783e571569a88c0ea645270
languageName: node
linkType: hard

Expand Down Expand Up @@ -2724,9 +2724,9 @@ __metadata:
linkType: hard

"electron-to-chromium@npm:^1.5.41":
version: 1.5.53
resolution: "electron-to-chromium@npm:1.5.53"
checksum: 4d46bc8a61527fe591b887cb4953c2119709eebe19ae4957293104ce6441134cebe6f20995d813b7b4b3226e5d0f5714cb22e8b28f86431fc4e6bb0b06215dc3
version: 1.5.56
resolution: "electron-to-chromium@npm:1.5.56"
checksum: ef8213e3531715d48ca7c61e4b70532d57616271b56642d212297c72ba984bf57621c32d04eb56c19bfb90cf17d421875e6f334deddd191edf28515bebfb9061
languageName: node
linkType: hard

Expand Down Expand Up @@ -4532,9 +4532,9 @@ __metadata:
linkType: hard

"object-inspect@npm:^1.13.1":
version: 1.13.2
resolution: "object-inspect@npm:1.13.2"
checksum: 9f850b3c045db60e0e97746e809ee4090d6ce62195af17dd1e9438ac761394a7d8ec4f7906559aea5424eaf61e35d3e53feded2ccd5f62fcc7d9670d3c8eb353
version: 1.13.3
resolution: "object-inspect@npm:1.13.3"
checksum: 8c962102117241e18ea403b84d2521f78291b774b03a29ee80a9863621d88265ffd11d0d7e435c4c2cea0dc2a2fbf8bbc92255737a05536590f2df2e8756f297
languageName: node
linkType: hard

Expand Down Expand Up @@ -4736,7 +4736,7 @@ __metadata:
languageName: node
linkType: hard

"picocolors@npm:^1.0.0, picocolors@npm:^1.1.0":
"picocolors@npm:^1.0.0, picocolors@npm:^1.1.0, picocolors@npm:^1.1.1":
version: 1.1.1
resolution: "picocolors@npm:1.1.1"
checksum: e1cf46bf84886c79055fdfa9dcb3e4711ad259949e3565154b004b260cd356c5d54b31a1437ce9782624bf766272fe6b0154f5f0c744fb7af5d454d2b60db045
Expand Down Expand Up @@ -4792,26 +4792,26 @@ __metadata:
linkType: hard

"postcss-modules-local-by-default@npm:^4.0.5":
version: 4.0.5
resolution: "postcss-modules-local-by-default@npm:4.0.5"
version: 4.1.0
resolution: "postcss-modules-local-by-default@npm:4.1.0"
dependencies:
icss-utils: ^5.0.0
postcss-selector-parser: ^6.0.2
postcss-selector-parser: ^7.0.0
postcss-value-parser: ^4.1.0
peerDependencies:
postcss: ^8.1.0
checksum: ca9b01f4a0a3dfb33e016299e2dfb7e85c3123292f7aec2efc0c6771b9955648598bfb4c1561f7ee9732fb27fb073681233661b32eef98baab43743f96735452
checksum: 64ac4803c21dd82e227179cf0a8489c645ea99a8c514475da028c9afe5d5b915485d00d8efbe94295d688a23a172965cc15f20d550168d1fed272dbdbbe053f0
languageName: node
linkType: hard

"postcss-modules-scope@npm:^3.2.0":
version: 3.2.0
resolution: "postcss-modules-scope@npm:3.2.0"
version: 3.2.1
resolution: "postcss-modules-scope@npm:3.2.1"
dependencies:
postcss-selector-parser: ^6.0.4
postcss-selector-parser: ^7.0.0
peerDependencies:
postcss: ^8.1.0
checksum: 2ffe7e98c1fa993192a39c8dd8ade93fc4f59fbd1336ce34fcedaee0ee3bafb29e2e23fb49189256895b30e4f21af661c6a6a16ef7b17ae2c859301e4a4459ae
checksum: 085f65863bb7d8bf08209a979ceb22b2b07bb466574e0e698d34aaad832d614957bb05f2418348a14e4035f65e23b2be2951369d26ea429dd5762c6a020f0f7c
languageName: node
linkType: hard

Expand Down Expand Up @@ -4842,7 +4842,7 @@ __metadata:
languageName: node
linkType: hard

"postcss-selector-parser@npm:^6.0.13, postcss-selector-parser@npm:^6.0.2, postcss-selector-parser@npm:^6.0.4":
"postcss-selector-parser@npm:^6.0.13":
version: 6.1.2
resolution: "postcss-selector-parser@npm:6.1.2"
dependencies:
Expand All @@ -4852,6 +4852,16 @@ __metadata:
languageName: node
linkType: hard

"postcss-selector-parser@npm:^7.0.0":
version: 7.0.0
resolution: "postcss-selector-parser@npm:7.0.0"
dependencies:
cssesc: ^3.0.0
util-deprecate: ^1.0.2
checksum: f906b7449fcbe9fa6ae739b6fc324ee3c6201aaf5224f26da27de64ccba68d878d734dd182a467881e463f7ede08972d0129b0cc4d6b671d78c6492cddcef154
languageName: node
linkType: hard

"postcss-value-parser@npm:^4.1.0, postcss-value-parser@npm:^4.2.0":
version: 4.2.0
resolution: "postcss-value-parser@npm:4.2.0"
Expand All @@ -4860,13 +4870,13 @@ __metadata:
linkType: hard

"postcss@npm:^8.3.11, postcss@npm:^8.4.28, postcss@npm:^8.4.33":
version: 8.4.47
resolution: "postcss@npm:8.4.47"
version: 8.4.49
resolution: "postcss@npm:8.4.49"
dependencies:
nanoid: ^3.3.7
picocolors: ^1.1.0
picocolors: ^1.1.1
source-map-js: ^1.2.1
checksum: f78440a9d8f97431dd2ab1ab8e1de64f12f3eff38a3d8d4a33919b96c381046a314658d2de213a5fa5eb296b656de76a3ec269fdea27f16d5ab465b916a0f52c
checksum: eb5d6cbdca24f50399aafa5d2bea489e4caee4c563ea1edd5a2485bc5f84e9ceef3febf170272bc83a99c31d23a316ad179213e853f34c2a7a8ffa534559d63a
languageName: node
linkType: hard

Expand Down

0 comments on commit 912e8f1

Please sign in to comment.