Skip to content

Initial language model configuration management #6878

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
Mar 21, 2025

Conversation

timtmok
Copy link
Contributor

@timtmok timtmok commented Mar 19, 2025

First PR for #6612

Adds a new dialog for configuring language models. The dialog is hidden behind a preference positron.assistant.newModelConfiguration, which shows the new dialog when true.

This also removes the other models that are not initially supported from the selection list. The pared down list is Anthropic and Gemini. There are a few others added when in dev mode (AWS Bedrock [Configured by environment variables], Echo, and Error [test models]).

Adding an Anthropic or Gemini model is not expected to work properly. It can add but the UI will not be a good workflow. It doesn't handle adding it properly as a chat or completion model and this will be addressed in #6613 and #6614.

For now, the Echo test model is available to show that a model can be signed in and signed out. The dialog now has an action callback so that the extension can perform a save or delete on the model. Another callback is added to signal to the extension that it can clean up the action callback.

image

Release Notes

New Features

  • N/A

Bug Fixes

  • N/A

QA Notes

Not much to test here at this point.

@timtmok timtmok requested review from jmcphers and sharon-wang March 19, 2025 20:08
Copy link

github-actions bot commented Mar 19, 2025

E2E Tests 🚀
This PR will run tests tagged with: @:critical

readme  valid tags

Copy link
Member

@sharon-wang sharon-wang left a comment

Choose a reason for hiding this comment

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

Works for me on Desktop and Server Web on Mac 👍

Recognizing that this is the initial modal implementation -- a couple questions on the UI/UX:

  • Do we have a plan for accessibility? In particular, I noticed the modal is not yet keyboard-navigable
  • Do we intend to move the feedback messages from notification toasts to feedback within the modal?
image

if (!onSave) {
async $responseLanguageModelConfig(id: string, config: IPositronLanguageModelConfig, action: string): Promise<void> {
const onAction = this._languageModelRequestRegistry.get(id);
if (!onAction) {
throw new Error('No matching language model configuration request found');
Copy link
Member

Choose a reason for hiding this comment

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

Could it be helpful to log some part of the id/config and the action for a bit more info in the error?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This part is pretty weird code TBH. The extension wants to pass a callback to Positron but it really caches it here. When Positron wants to do something with the extension, its callback leads back here to execute what to do for the action. In theory, this would never happen and, if it did, something really went wrong. Hopefully, a reprex would show what happened as this structure would only hold one item at a time.

I think eventually, part of the extension code should move into Positron so this weird stuff isn't needed just to save or delete a model configuration.

Comment on lines 1507 to 1521
// < --- Positron Icon Button --- >
export const POSITRON_ICON_BUTTON_BORDER = registerColor('positronIconButton.border', {
dark: '#175ab5',
light: '#70a6e0',
hcDark: '#ff0000',
hcLight: '#ff0000'
}, localize('positronIconButton.border', "Positron icon button border color."));

export const POSITRON_ICON_BUTTON_BACKGROUND = registerColor('positronIconButton.background', {
dark: '#214984',
light: '#a1c5ef',
hcDark: '#ff0000',
hcLight: '#ff0000'
}, localize('positronIconButton.background', "Positron icon button background color."));

Copy link
Member

Choose a reason for hiding this comment

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

Should we match the colours from the project wizard above, for consistency?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good idea. I kind of picked something that looked decent initially when trying to find colours.

import * as React from 'react';
import type { SVGProps } from 'react';

export const Anthropic = (props: SVGProps<SVGSVGElement>) => (
Copy link
Member

Choose a reason for hiding this comment

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

Are there any copyright/license notices to include with these logos?

// Get the configuration option listing enabled providers
let enabledProviders: string[] =
vscode.workspace.getConfiguration('positron.assistant').get('enabledProviders') || [];
const supportedProviders = await positron.ai.getSupportedProviders();
enabledProviders.push(...supportedProviders);
Copy link
Member

Choose a reason for hiding this comment

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

any chance we could get duplicate providers?

Positron Assistant is an AI copilot, designed to help you with data science and visualization tasks.

Always verify results. AI assistants can sometimes produce **incorrect or misleading information**.
To use Positron Assistant you must first select and authenticate with a language model provider.
Copy link
Member

Choose a reason for hiding this comment

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

The messaging here has changed quite a bit from the existing text, in particular, the disclaimer about verifying results. Is it intentional to change the messaging here?

Another thought is to match the text with the link to Add a Language Model that appears below. Maybe we can use "Select a Language Model" everywhere?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, this was intentional from the design spec. There will be another change coming to make the link a Sign-in with provider button.

Comment on lines 248 to 252
let { name, model, baseUrl, apiKey, ...otherConfig } = userConfig;
name = name.trim();
model = model.trim();
baseUrl = baseUrl?.trim();
apiKey = apiKey?.trim();
Copy link
Member

Choose a reason for hiding this comment

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

nit to do the trimming in a separate function, so these variables can all be consts in here


// Register the new model
const registered = await registerModel(newConfig, context, storage);
async function deleteConfigurationByProvider(context: vscode.ExtensionContext, storage: SecretStorage, providerId: string) {
Copy link
Member

Choose a reason for hiding this comment

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

For my understanding, when do we use this method of deletion a config via provider versus deleteConfiguration?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I do want to clean this up in subsequent PR's. The initial implementation can add multiple models from a single provider. deleteConfiguration deletes by the UUID generated when configuring the model. deleteConfigurationByProvider removes by the provider id. My intent is to register once with a provider and it will create a model configuration for chat and completion when possible. When that happens, the UUID would no longer be required.

jmcphers
jmcphers previously approved these changes Mar 20, 2025

getSupportedProviders(): string[] {
const providers = ['anthropic', 'google', 'copilot'];
if (IsDevelopmentContext.getValue(this._contextKeyService)) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could you add a config value that would cause this to happen in release builds too? Then you could close #6876 with this change, too.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Will do!

Co-authored-by: sharon <sharon-wang@users.noreply.github.com>
Signed-off-by: Tim Mok <timtmok@users.noreply.github.com>
timtmok and others added 4 commits March 21, 2025 10:38
Co-authored-by: sharon <sharon-wang@users.noreply.github.com>
Signed-off-by: Tim Mok <timtmok@users.noreply.github.com>
@timtmok timtmok merged commit dcc1568 into main Mar 21, 2025
8 checks passed
@timtmok timtmok deleted the 6612-model-provider-management branch March 21, 2025 17:43
@github-actions github-actions bot locked and limited conversation to collaborators Mar 21, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants