mirror of
https://github.com/cosmicoptima/loom.git
synced 2026-07-22 07:40:25 +00:00
Added a way to use azure openai api.
This commit is contained in:
parent
f00159d695
commit
213426d58f
3 changed files with 88 additions and 9 deletions
82
main.ts
82
main.ts
|
|
@ -28,13 +28,14 @@ import * as cohere from "cohere-ai";
|
|||
import * as fs from "fs";
|
||||
import GPT3Tokenizer from "gpt3-tokenizer";
|
||||
import { Configuration, OpenAIApi } from "openai";
|
||||
import { Configuration as AzureConfiguration, OpenAIApi as AzureOpenAiApi} from "azure-openai";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
const dialog = require("electron").remote.dialog;
|
||||
const untildify = require("untildify") as any;
|
||||
|
||||
const tokenizer = new GPT3Tokenizer({ type: "codex" }); // TODO depends on model
|
||||
|
||||
const PROVIDERS = ["cohere", "textsynth", "ocp", "openai", "openai-chat"];
|
||||
const PROVIDERS = ["cohere", "textsynth", "ocp", "openai", "openai-chat", "azure", "azure-chat"];
|
||||
type Provider = (typeof PROVIDERS)[number];
|
||||
|
||||
interface LoomSettings {
|
||||
|
|
@ -42,6 +43,10 @@ interface LoomSettings {
|
|||
cohereApiKey: string;
|
||||
textsynthApiKey: string;
|
||||
|
||||
azureApiKey: string;
|
||||
azureEndpoint: string;
|
||||
|
||||
|
||||
ocpApiKey: string;
|
||||
ocpUrl: string;
|
||||
|
||||
|
|
@ -68,6 +73,9 @@ const DEFAULT_SETTINGS: LoomSettings = {
|
|||
cohereApiKey: "",
|
||||
textsynthApiKey: "",
|
||||
|
||||
azureApiKey: "",
|
||||
azureEndpoint: "",
|
||||
|
||||
ocpApiKey: "",
|
||||
ocpUrl: "",
|
||||
|
||||
|
|
@ -110,6 +118,7 @@ export default class LoomPlugin extends Plugin {
|
|||
statusBarItem: HTMLElement;
|
||||
|
||||
openai: OpenAIApi;
|
||||
azureopenai: AzureOpenAiApi;
|
||||
|
||||
withFile<T>(callback: (file: TFile) => T): T | null {
|
||||
const file = this.app.workspace.getActiveFile();
|
||||
|
|
@ -152,6 +161,19 @@ export default class LoomPlugin extends Plugin {
|
|||
cohere.init(this.settings.cohereApiKey);
|
||||
}
|
||||
|
||||
setAzureOpenAI() {
|
||||
const configuration = new AzureConfiguration({
|
||||
apiKey: this.settings.azureApiKey,
|
||||
// add azure info into configuration
|
||||
azure: {
|
||||
apiKey: this.settings.azureApiKey,
|
||||
endpoint: this.settings.azureEndpoint
|
||||
}
|
||||
});
|
||||
this.azureopenai = new AzureOpenAiApi(configuration);
|
||||
}
|
||||
|
||||
|
||||
async onload() {
|
||||
await this.loadSettings();
|
||||
await this.loadState();
|
||||
|
|
@ -160,6 +182,7 @@ export default class LoomPlugin extends Plugin {
|
|||
|
||||
this.setOpenAI();
|
||||
this.setCohere();
|
||||
this.setAzureOpenAI();
|
||||
|
||||
this.statusBarItem = this.addStatusBarItem();
|
||||
this.statusBarItem.setText("Completing...");
|
||||
|
|
@ -180,6 +203,12 @@ export default class LoomPlugin extends Plugin {
|
|||
!this.settings.openaiApiKey
|
||||
)
|
||||
return false;
|
||||
if (
|
||||
["azure", "azure-chat"].includes(this.settings.provider) &&
|
||||
!this.settings.azureApiKey
|
||||
)
|
||||
return false;
|
||||
|
||||
if (this.settings.provider === "cohere" && !this.settings.cohereApiKey)
|
||||
return false;
|
||||
if (
|
||||
|
|
@ -189,7 +218,7 @@ export default class LoomPlugin extends Plugin {
|
|||
return false;
|
||||
if (this.settings.provider === "ocp" && !this.settings.ocpApiKey)
|
||||
return false;
|
||||
|
||||
|
||||
if (!checking) {
|
||||
if (file.extension === "md")
|
||||
this.mdComplete(file);
|
||||
|
|
@ -1067,7 +1096,7 @@ export default class LoomPlugin extends Plugin {
|
|||
// complete, or visually display an error and return if that fails
|
||||
let rawCompletions;
|
||||
try {
|
||||
if (this.settings.provider === "openai-chat") {
|
||||
if (["openai-chat"].includes(this.settings.provider)) {
|
||||
rawCompletions = (
|
||||
await this.openai.createChatCompletion({
|
||||
model: this.settings.model,
|
||||
|
|
@ -1078,7 +1107,7 @@ export default class LoomPlugin extends Plugin {
|
|||
top_p: this.settings.topP,
|
||||
})
|
||||
).data.choices.map((choice) => choice.message?.content);
|
||||
} else if (this.settings.provider === "openai") {
|
||||
} else if (["openai"].includes(this.settings.provider)) {
|
||||
rawCompletions = (
|
||||
await this.openai.createCompletion({
|
||||
model: this.settings.model,
|
||||
|
|
@ -1089,18 +1118,40 @@ export default class LoomPlugin extends Plugin {
|
|||
top_p: this.settings.topP,
|
||||
})
|
||||
).data.choices.map((choice) => choice.text);
|
||||
} else if (["azure-chat"].includes(this.settings.provider)) {
|
||||
rawCompletions = (
|
||||
await this.azureopenai.createChatCompletion({
|
||||
model: this.settings.model,
|
||||
messages: [{ role: "assistant", content: prompt }],
|
||||
max_tokens: this.settings.maxTokens,
|
||||
n: this.settings.n,
|
||||
temperature: this.settings.temperature,
|
||||
top_p: this.settings.topP,
|
||||
})
|
||||
).data.choices.map((choice) => choice.message?.content);
|
||||
} else if (["azure"].includes(this.settings.provider)) {
|
||||
rawCompletions = (
|
||||
await this.azureopenai.createCompletion({
|
||||
model: this.settings.model,
|
||||
prompt,
|
||||
max_tokens: this.settings.maxTokens,
|
||||
n: this.settings.n,
|
||||
temperature: this.settings.temperature,
|
||||
top_p: this.settings.topP,
|
||||
})
|
||||
).data.choices.map((choice) => choice.text);
|
||||
}
|
||||
} catch (e) {
|
||||
if (
|
||||
e.response.status === 401 &&
|
||||
["openai", "openai-chat"].includes(this.settings.provider)
|
||||
["openai", "openai-chat", "azure", "azure-chat"].includes(this.settings.provider)
|
||||
)
|
||||
new Notice(
|
||||
"OpenAI API key is invalid. Please provide a valid key in the settings."
|
||||
);
|
||||
else if (
|
||||
e.response.status === 429 &&
|
||||
["openai", "openai-chat"].includes(this.settings.provider)
|
||||
["openai", "openai-chat", "azure", "azure-chat"].includes(this.settings.provider)
|
||||
)
|
||||
new Notice("OpenAI API rate limit exceeded.");
|
||||
else new Notice("Unknown API error: " + e.response.data.error.message);
|
||||
|
|
@ -1203,7 +1254,7 @@ export default class LoomPlugin extends Plugin {
|
|||
completion = completion.replace(/</g, "\\<"); // escape < for obsidian
|
||||
completion = completion.replace(/\[/g, "\\["); // escape [ for obsidian
|
||||
|
||||
if (this.settings.provider === "openai-chat") {
|
||||
if (["azure-chat", "openai-chat"].includes(this.settings.provider)) {
|
||||
if (!trailingSpace) completion = " " + completion;
|
||||
} else if (trailingSpace && completion[0] === " ")
|
||||
completion = completion.slice(1);
|
||||
|
|
@ -1621,6 +1672,8 @@ class LoomView extends ItemView {
|
|||
{ name: "OpenAI code-davinci-002 proxy", value: "ocp" },
|
||||
{ name: "OpenAI (Completion)", value: "openai" },
|
||||
{ name: "OpenAI (Chat)", value: "openai-chat" },
|
||||
{ name: "Azure (Completion)", value: "azure" },
|
||||
{ name: "Azure (Chat)", value: "azure-chat" },
|
||||
];
|
||||
providerOptions.forEach((option) => {
|
||||
const optionEl = providerSelect.createEl("option", {
|
||||
|
|
@ -2238,6 +2291,8 @@ class LoomSettingTab extends PluginSettingTab {
|
|||
dropdown.addOption("ocp", "OpenAI code-davinci-002 proxy");
|
||||
dropdown.addOption("openai", "OpenAI (Completion)");
|
||||
dropdown.addOption("openai-chat", "OpenAI (Chat)");
|
||||
dropdown.addOption("azure", "Azure (Completion)");
|
||||
dropdown.addOption("azure-chat", "Azure (Chat)");
|
||||
dropdown.setValue(this.plugin.settings.provider);
|
||||
dropdown.onChange(async (value) => {
|
||||
if (PROVIDERS.find((provider) => provider === value))
|
||||
|
|
@ -2276,6 +2331,19 @@ class LoomSettingTab extends PluginSettingTab {
|
|||
|
||||
apiKeySetting("OpenAI", "openaiApiKey");
|
||||
|
||||
apiKeySetting("Azure", "azureApiKey")
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName("Azure-Openai Resource Endpoint")
|
||||
.setDesc("Required if using Azure")
|
||||
.addText((text) =>
|
||||
text.setValue(this.plugin.settings.azureEndpoint).onChange(async (value) => {
|
||||
this.plugin.settings.azureEndpoint = value;
|
||||
await this.plugin.save();
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
// TODO: reduce duplication of other settings
|
||||
|
||||
new Setting(containerEl).setName("Model").addText((text) =>
|
||||
|
|
|
|||
14
package-lock.json
generated
14
package-lock.json
generated
|
|
@ -1,17 +1,18 @@
|
|||
{
|
||||
"name": "obsidian-loom",
|
||||
"version": "0.1.0",
|
||||
"version": "1.3.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "obsidian-loom",
|
||||
"version": "0.1.0",
|
||||
"version": "1.3.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/state": "^6.2.0",
|
||||
"@codemirror/view": "^6.9.3",
|
||||
"@types/lodash": "^4.14.191",
|
||||
"azure-openai": "^0.9.4",
|
||||
"cohere-ai": "^6.1.0",
|
||||
"gpt3-tokenizer": "^1.1.5",
|
||||
"openai": "^3.2.0",
|
||||
|
|
@ -497,6 +498,15 @@
|
|||
"follow-redirects": "^1.14.8"
|
||||
}
|
||||
},
|
||||
"node_modules/azure-openai": {
|
||||
"version": "0.9.4",
|
||||
"resolved": "https://registry.npmjs.org/azure-openai/-/azure-openai-0.9.4.tgz",
|
||||
"integrity": "sha512-7uii4ZInxzu2zjLg45PdvgOaw3ps18tEAw0Yux9mo8anX4PwnCMSS9xdlKNiNQyyEKPogvAcxH2PIufHXFLx6Q==",
|
||||
"dependencies": {
|
||||
"axios": "^0.26.0",
|
||||
"form-data": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
"@codemirror/state": "^6.2.0",
|
||||
"@codemirror/view": "^6.9.3",
|
||||
"@types/lodash": "^4.14.191",
|
||||
"azure-openai": "^0.9.4",
|
||||
"cohere-ai": "^6.1.0",
|
||||
"gpt3-tokenizer": "^1.1.5",
|
||||
"openai": "^3.2.0",
|
||||
|
|
|
|||
Loading…
Reference in a new issue