Use access key set by command while no valid key

This commit is contained in:
bobo.yang 2023-09-13 10:08:16 +08:00
parent 0ff9870cf6
commit a7bb815df5
7 changed files with 145 additions and 80 deletions

View File

@ -365,17 +365,6 @@
"description": "The max number of tokens of a prompt.",
"when": "DevChat.llmModel == 'OpenAI'"
},
"DevChat.Access_Key_DevChat": {
"type": "string",
"default": "",
"description": "DevChat's secret key for accessing multiple LLM models"
},
"DevChat.Api_Key_OpenAI": {
"type": "string",
"default": "",
"description": "OpenAI's secret key for accessing LLM models. (Leave blank if using DevChat's key.)",
"when": "DevChat.llmModel == 'OpenAI'"
},
"DevChat.API_ENDPOINT": {
"type": "string",
"default": "",
@ -489,13 +478,73 @@
"title": "Create Entry"
},
{
"command": "DevChat.Api_Key_OpenAI",
"title": "Input OpenAI Api Key",
"command": "DevChat.AccessKey.OpenAI",
"title": "Input Access Key for OpenAI",
"category": "DevChat"
},
{
"command": "DevChat.Access_Key_DevChat",
"title": "Input DevChat Access Key",
"command": "DevChat.AccessKey.Cohere",
"title": "Input Access Key for Cohere",
"category": "DevChat"
},
{
"command": "DevChat.AccessKey.Anthropic",
"title": "Input Access Key for Anthropic",
"category": "DevChat"
},
{
"command": "DevChat.AccessKey.Replicate",
"title": "Input Access Key for Replicate",
"category": "DevChat"
},
{
"command": "DevChat.AccessKey.HuggingFace",
"title": "Input Access Key for HuggingFace",
"category": "DevChat"
},
{
"command": "DevChat.AccessKey.TogetherAI",
"title": "Input Access Key for TogetherAI",
"category": "DevChat"
},
{
"command": "DevChat.AccessKey.OpenRouter",
"title": "Input Access Key for OpenRouter",
"category": "DevChat"
},
{
"command": "DevChat.AccessKey.VertexAI",
"title": "Input Access Key for VertexAI",
"category": "DevChat"
},
{
"command": "DevChat.AccessKey.AI21",
"title": "Input Access Key for AI21",
"category": "DevChat"
},
{
"command": "DevChat.AccessKey.BaseTen",
"title": "Input Access Key for BaseTen",
"category": "DevChat"
},
{
"command": "DevChat.AccessKey.Azure",
"title": "Input Access Key for Azure",
"category": "DevChat"
},
{
"command": "DevChat.AccessKey.SageMaker",
"title": "Input Access Key for SageMaker",
"category": "DevChat"
},
{
"command": "DevChat.AccessKey.Bedrock",
"title": "Input Access Key for Bedrock",
"category": "DevChat"
},
{
"command": "DevChat.AccessKey.DevChat",
"title": "Input Access Key for DevChat",
"category": "DevChat"
},
{

View File

@ -82,42 +82,39 @@ function registerAskForFileCommand(context: vscode.ExtensionContext) {
context.subscriptions.push(vscode.commands.registerCommand('devchat.askForFile_chinese', callback));
}
export function registerOpenAiApiKeySettingCommand(context: vscode.ExtensionContext) {
const secretStorage: vscode.SecretStorage = context.secrets;
function regAccessKeyCommand(context: vscode.ExtensionContext, provider: string) {
context.subscriptions.push(
vscode.commands.registerCommand('DevChat.Api_Key_OpenAI', async () => {
vscode.commands.registerCommand(`DevChat.AccessKey.${provider}`, async () => {
const passwordInput: string = await vscode.window.showInputBox({
password: true,
title: "Input OpenAi Api Key",
placeHolder: "Set OpenAI Api Key.(Leave blank if clearing stored key.)"
title: `Input ${provider} Access Key`,
placeHolder: `Set ${provider} Access Key.(Leave blank if clearing stored key.)`
}) ?? '';
if (passwordInput.trim() !== "" && !isValidApiKey(passwordInput)) {
UiUtilWrapper.showErrorMessage("Your api key is invalid!");
return ;
}
ApiKeyManager.writeApiKeySecret(passwordInput, "OpenAI");
await ApiKeyManager.writeApiKeySecret(passwordInput, provider);
})
);
}
export function registerDevChatApiKeySettingCommand(context: vscode.ExtensionContext) {
const secretStorage: vscode.SecretStorage = context.secrets;
context.subscriptions.push(
vscode.commands.registerCommand('DevChat.Access_Key_DevChat', async () => {
const passwordInput: string = await vscode.window.showInputBox({
password: true,
title: "Input DevChat Access Key",
placeHolder: "Set DevChat Access Key.(Leave blank if clearing stored key.)"
}) ?? '';
if (passwordInput.trim() !== "" && !isValidApiKey(passwordInput)) {
UiUtilWrapper.showErrorMessage("Your access key is invalid!");
return ;
}
ApiKeyManager.writeApiKeySecret(passwordInput, "DevChat");
})
);
export function registerAccessKeySettingCommand(context: vscode.ExtensionContext) {
regAccessKeyCommand(context, "OpenAI");
regAccessKeyCommand(context, "Cohere");
regAccessKeyCommand(context, "Anthropic");
regAccessKeyCommand(context, "Replicate");
regAccessKeyCommand(context, "HuggingFace");
regAccessKeyCommand(context, "TogetherAI");
regAccessKeyCommand(context, "OpenRouter");
regAccessKeyCommand(context, "VertexAI");
regAccessKeyCommand(context, "AI21");
regAccessKeyCommand(context, "BaseTen");
regAccessKeyCommand(context, "Azure");
regAccessKeyCommand(context, "SageMaker");
regAccessKeyCommand(context, "Bedrock");
regAccessKeyCommand(context, "DevChat");
}
export function registerStatusBarItemClickCommand(context: vscode.ExtensionContext) {
@ -142,7 +139,7 @@ const topicDeleteCallback = async (item: TopicTreeItem) => {
TopicManager.getInstance().deleteTopic(item.id);
}
};
;
export function regTopicDeleteCommand(context: vscode.ExtensionContext) {
context.subscriptions.push(

View File

@ -5,8 +5,7 @@ import {
registerAddContextCommand,
registerAskForCodeCommand,
registerAskForFileCommand,
registerOpenAiApiKeySettingCommand,
registerDevChatApiKeySettingCommand,
registerAccessKeySettingCommand,
regTopicDeleteCommand,
regAddTopicCommand,
regDeleteSelectTopicCommand,
@ -45,8 +44,7 @@ function activate(context: vscode.ExtensionContext) {
regDevChatView(context);
regTopicView(context);
registerOpenAiApiKeySettingCommand(context);
registerDevChatApiKeySettingCommand(context);
registerAccessKeySettingCommand(context);
registerOpenChatPanelCommand(context);
registerAddContextCommand(context);
registerAskForCodeCommand(context);

View File

@ -178,15 +178,7 @@ export async function historyMessagesBase(): Promise<LoadHistoryMessages | undef
}
export async function onApiKeyBase(apiKey: string): Promise<{ command: string, text: string, hash: string, user: string, date: string, isError: boolean }> {
if (!isValidApiKey(apiKey)) {
return { command: 'receiveMessage', text: 'Your API key is invalid. We support OpenAI and DevChat keys. Please reset the key.', hash: '', user: 'system', date: '', isError: false };
}
isApiSet = true;
ApiKeyManager.writeApiKeySecret(apiKey);
const welcomeMessageText = welcomeMessage().response;
return {
command: 'receiveMessage', text: `Your OPENAI_API_KEY is set. Enjoy DevChat!\n${welcomeMessageText}`, hash: '', user: 'system', date: '', isError: false
command: 'receiveMessage', text: `You need config access key for specified llmodel in setting view.`, hash: '', user: 'system', date: '', isError: false
};
}

View File

@ -42,7 +42,7 @@ export function createStatusBarItem(context: vscode.ExtensionContext): vscode.St
if (apiKeyStatus !== 'has valid access key') {
statusBarItem.text = `$(warning)DevChat`;
statusBarItem.tooltip = `${apiKeyStatus}`;
statusBarItem.command = 'DevChat.Access_Key_DevChat';
statusBarItem.command = 'DevChat.AccessKey.DevChat';
progressBar.update(`Checking devchat dependency environment: ${apiKeyStatus}.`, 0);
return;
}

View File

@ -120,7 +120,7 @@ class DevChat {
args.push("-p", options.parent);
}
const llmModelData = ApiKeyManager.llmModel();
const llmModelData = await ApiKeyManager.llmModel();
if (llmModelData && llmModelData.model) {
args.push("-m", llmModelData.model);
}
@ -200,7 +200,7 @@ class DevChat {
}
async chat(content: string, options: ChatOptions = {}, onData: (data: ChatResponse) => void): Promise<ChatResponse> {
const llmModelData = ApiKeyManager.llmModel();
const llmModelData = await ApiKeyManager.llmModel();
if (!llmModelData) {
return {
"prompt-hash": "",

View File

@ -3,8 +3,26 @@
import { UiUtilWrapper } from './uiUtil';
export class ApiKeyManager {
static toProviderKey(provider: string) : string | undefined {
let providerNameMap = {
"openai": "OpenAI",
"cohere": "Cohere",
"anthropic": "Anthropic",
"replicate": "Replicate",
"huggingface": "HuggingFace",
"together_ai": "TogetherAI",
"openrouter": "OpenRouter",
"vertex_ai": "VertexAI",
"ai21": "AI21",
"baseten": "Baseten",
"azure": "Azure",
"sagemaker": "SageMaker",
"bedrock": "Bedrock"
};
return providerNameMap[provider];
}
static async getApiKey(llmType: string = "OpenAI"): Promise<string | undefined> {
const llmModel = this.llmModel();
const llmModel = await this.llmModel();
if (!llmModel) {
return undefined;
}
@ -12,13 +30,13 @@ export class ApiKeyManager {
return llmModel.api_key;
}
static llmModel() {
static async llmModel() {
const llmModel = UiUtilWrapper.getConfiguration('devchat', 'defaultModel');
if (!llmModel) {
return undefined;
}
const modelProperties = (modelPropertyName: string, modelName: string) => {
const modelProperties = async (modelPropertyName: string, modelName: string) => {
const modelConfig = UiUtilWrapper.getConfiguration("devchat", modelPropertyName);
if (!modelConfig) {
return undefined;
@ -29,26 +47,36 @@ export class ApiKeyManager {
const property = modelConfig![key];
modelProperties[key] = property;
}
if (!modelConfig["provider"] || !modelConfig["api_key"]) {
if (!modelConfig["provider"]) {
return undefined;
}
modelProperties['model'] = modelName;
if (!modelConfig["api_key"]) {
const providerName = this.toProviderKey(modelConfig["provider"]);
if (!providerName) {
return undefined;
}
const apiKey = await this.loadApiKeySecret(providerName);
if (!apiKey) {
return undefined;
}
modelProperties["api_key"] = apiKey;
}
modelProperties['model'] = modelName;
return modelProperties;
};
if (llmModel === "gpt-3.5-turbo") {
return modelProperties('Model.gpt-3-5', "gpt-3.5-turbo");
return await modelProperties('Model.gpt-3-5', "gpt-3.5-turbo");
}
if (llmModel === "gpt-3.5-turbo-16k") {
return modelProperties('Model.gpt-3-5-16k', "gpt-3.5-turbo-16k");
return await modelProperties('Model.gpt-3-5-16k', "gpt-3.5-turbo-16k");
}
if (llmModel === "gpt-4") {
return modelProperties('Model.gpt-4', "gpt-4");
return await modelProperties('Model.gpt-4', "gpt-4");
}
if (llmModel === "claude-2") {
return modelProperties('Model.claude-2', "claude-2");
return await modelProperties('Model.claude-2', "claude-2");
}
const customModelConfig: any = UiUtilWrapper.getConfiguration('devchat', 'customModel');
@ -68,13 +96,21 @@ export class ApiKeyManager {
modelProperties[key] = property;
}
if (!model["api_key"]) {
return undefined;
}
const modelProvider = model["model"].split('/')[0];
const modelName = model["model"].split('/').slice(1).join('/');
if (!model["api_key"]) {
const providerName = this.toProviderKey(modelProvider);
if (!providerName) {
return undefined;
}
const apiKey = await this.loadApiKeySecret(providerName);
if (!apiKey) {
return undefined;
}
modelProperties["api_key"] = apiKey;
}
modelProperties["provider"] = modelProvider;
modelProperties["model"] = modelName;
@ -96,17 +132,10 @@ export class ApiKeyManager {
}
static async writeApiKeySecret(apiKey: string, llmType: string = "Unknow"): Promise<void> {
if (apiKey.startsWith("sk-")) {
await UiUtilWrapper.storeSecret("openai_OPENAI_API_KEY", apiKey);
} else if (apiKey.startsWith("DC.")) {
await UiUtilWrapper.storeSecret("devchat_OPENAI_API_KEY", apiKey);
} else {
if (llmType === "OpenAI") {
await UiUtilWrapper.storeSecret("openai_OPENAI_API_KEY", apiKey);
} else if (llmType === "DevChat") {
await UiUtilWrapper.storeSecret("devchat_OPENAI_API_KEY", apiKey);
}
await UiUtilWrapper.storeSecret(`Access_KEY_${llmType}`, apiKey);
}
static async loadApiKeySecret(llmType: string = "Unknow"): Promise<string | undefined> {
return await UiUtilWrapper.secretStorageGet(`Access_KEY_${llmType}`);
}
static getEndPoint(apiKey: string | undefined): string | undefined {