diff --git a/manifest.json b/manifest.json index 1b7fefc0..c7185cf9 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "copilot", "name": "Copilot", - "version": "2.4.6", + "version": "2.4.7", "minAppVersion": "0.15.0", "description": "A ChatGPT Copilot in Obsidian.", "author": "Logan Yang", diff --git a/package-lock.json b/package-lock.json index 2ecd9568..34ae7244 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,16 +1,17 @@ { "name": "obsidian-copilot", - "version": "2.4.6", + "version": "2.4.7", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "obsidian-copilot", - "version": "2.4.6", + "version": "2.4.7", "license": "AGPL-3.0", "dependencies": { "@huggingface/inference": "^1.8.0", "@koa/cors": "^4.0.0", + "@langchain/google-genai": "^0.0.7", "@tabler/icons-react": "^2.14.0", "@types/pouchdb": "^6.4.0", "axios": "^1.3.4", @@ -1197,6 +1198,14 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@google/generative-ai": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@google/generative-ai/-/generative-ai-0.1.3.tgz", + "integrity": "sha512-Cm4uJX1sKarpm1mje/MiOIinM7zdUUrQp/5/qGPAgznbdd/B9zup5ehT6c1qGqycFcSopTA1J1HpqHS5kJR8hQ==", + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@huggingface/inference": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/@huggingface/inference/-/inference-1.8.0.tgz", @@ -1805,9 +1814,9 @@ } }, "node_modules/@langchain/core": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@langchain/core/-/core-0.1.4.tgz", - "integrity": "sha512-Y3/mQLEiQ78ZbsTGYvPRj5bpvrhpTAcsbdyEtlYEvjMLbehEADfjQ41G9zc7U/emkrGtHRmxWO1ISmoeXeDmyQ==", + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/@langchain/core/-/core-0.1.10.tgz", + "integrity": "sha512-vSFPtTkpQ9NT3qqvRh9FN4A16m89npj9KhzZgIh976bseMfI87jS+GK6Rih3qVcB8wsStqp80E5A36ce2egl8Q==", "dependencies": { "ansi-styles": "^5.0.0", "camelcase": "6", @@ -1846,6 +1855,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@langchain/google-genai": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@langchain/google-genai/-/google-genai-0.0.7.tgz", + "integrity": "sha512-0VUrzVRS5PW/HhGVdTelDZd8DJVXdyLj2KqHpUNWdXNNMKaLVV6AY2nwqKLA3I4SV0VfOt1/XoZAgPIpQfn4Ow==", + "dependencies": { + "@google/generative-ai": "^0.1.0", + "@langchain/core": "~0.1.5" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@langchain/openai": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/@langchain/openai/-/openai-0.0.8.tgz", diff --git a/package.json b/package.json index b1ea4115..661bdb81 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "obsidian-copilot", - "version": "2.4.6", + "version": "2.4.7", "description": "ChatGPT integration for Obsidian", "main": "main.js", "scripts": { @@ -38,6 +38,7 @@ "dependencies": { "@huggingface/inference": "^1.8.0", "@koa/cors": "^4.0.0", + "@langchain/google-genai": "^0.0.7", "@tabler/icons-react": "^2.14.0", "@types/pouchdb": "^6.4.0", "axios": "^1.3.4", diff --git a/src/aiState.ts b/src/aiState.ts index 334da29c..d2650455 100644 --- a/src/aiState.ts +++ b/src/aiState.ts @@ -10,6 +10,8 @@ import { COHEREAI, ChatModelDisplayNames, DEFAULT_SYSTEM_PROMPT, + GOOGLE, + GOOGLE_MODELS, HUGGINGFACE, LOCALAI, OPENAI, @@ -19,6 +21,7 @@ import { import { ChatMessage } from '@/sharedState'; import { getModelName, isSupportedChain } from '@/utils'; import VectorDBManager, { MemoryVector } from '@/vectorDBManager'; +import { ChatGoogleGenerativeAI } from "@langchain/google-genai"; import { BaseChain, ConversationChain, @@ -62,6 +65,8 @@ interface ModelConfig { azureOpenAIApiInstanceName?: string, azureOpenAIApiDeploymentName?: string, azureOpenAIApiVersion?: string, + // Google API key https://api.js.langchain.com/classes/langchain_google_genai.ChatGoogleGenerativeAI.html + apiKey?: string, openAIProxyBaseUrl?: string, localAIModel?: string, } @@ -76,6 +81,7 @@ export interface LangChainParams { azureOpenAIApiDeploymentName: string, azureOpenAIApiVersion: string, azureOpenAIApiEmbeddingDeploymentName: string, + googleApiKey?: string, model: string, modelDisplayName: string, temperature: number, @@ -135,6 +141,7 @@ class AIState { private static chatOpenAI: ChatOpenAI; private static chatAnthropic: ChatAnthropic; private static azureChatOpenAI: ChatOpenAI; + private static chatGoogleGenerativeAI: ChatGoogleGenerativeAI; private static chain: BaseChain; private static retrievalChain: RetrievalQAChain; private static conversationalRetrievalChain: ConversationalRetrievalQAChain; @@ -207,6 +214,7 @@ class AIState { temperature, maxTokens, openAIProxyBaseUrl, + googleApiKey, localAIModel, } = this.langChainParams; @@ -245,6 +253,11 @@ class AIState { azureOpenAIApiVersion: azureOpenAIApiVersion, }; break; + case GOOGLE: + config = { + ...config, + apiKey: googleApiKey, + }; } return config; @@ -288,6 +301,14 @@ class AIState { }; } + for (const modelDisplayNameKey of GOOGLE_MODELS) { + modelMap[modelDisplayNameKey] = { + hasApiKey: Boolean(this.langChainParams.googleApiKey), + AIConstructor: ChatGoogleGenerativeAI, + vendor: GOOGLE, + }; + } + this.modelMap = modelMap; } @@ -396,6 +417,9 @@ class AIState { case AZURE_OPENAI: AIState.azureChatOpenAI = newModelInstance as ChatOpenAI; break; + case GOOGLE: + AIState.chatGoogleGenerativeAI = newModelInstance as ChatGoogleGenerativeAI; + break; } AIState.chatModel = newModelInstance; diff --git a/src/components/ChatComponents/ChatIcons.tsx b/src/components/ChatComponents/ChatIcons.tsx index b7dc928f..e2015c0f 100644 --- a/src/components/ChatComponents/ChatIcons.tsx +++ b/src/components/ChatComponents/ChatIcons.tsx @@ -116,6 +116,7 @@ const ChatIcons: React.FC = ({ + Model Selection diff --git a/src/constants.ts b/src/constants.ts index 7fd74cf5..7f4ea430 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -17,6 +17,7 @@ export enum ChatModels { CLAUDE_INSTANT_1_100K = 'claude-instant-1-100k', AZURE_GPT_35_TURBO = 'gpt-35-turbo', AZURE_GPT_35_TURBO_16K = 'gpt-35-turbo-16k', + GEMINI_PRO = 'gemini-pro', } export enum ChatModelDisplayNames { @@ -33,6 +34,7 @@ export enum ChatModelDisplayNames { AZURE_GPT_35_TURBO_16K = 'AZURE GPT-3.5-16K', AZURE_GPT_4 = 'AZURE GPT-4', AZURE_GPT_4_32K = 'AZURE GPT-4 32K', + GEMINI_PRO = 'GEMINI PRO', LOCAL_AI = 'LocalAI', } @@ -59,6 +61,10 @@ export const CLAUDE_MODELS = new Set([ ChatModelDisplayNames.CLAUDE_INSTANT_1_100K, ]); +export const GOOGLE_MODELS = new Set([ + ChatModelDisplayNames.GEMINI_PRO, +]); + export const DISPLAY_NAME_TO_MODEL: Record = { [ChatModelDisplayNames.GPT_35_TURBO]: ChatModels.GPT_35_TURBO, [ChatModelDisplayNames.GPT_35_TURBO_16K]: ChatModels.GPT_35_TURBO_16K, @@ -73,6 +79,7 @@ export const DISPLAY_NAME_TO_MODEL: Record = { [ChatModelDisplayNames.AZURE_GPT_35_TURBO_16K]: ChatModels.AZURE_GPT_35_TURBO_16K, [ChatModelDisplayNames.AZURE_GPT_4]: ChatModels.GPT_4, [ChatModelDisplayNames.AZURE_GPT_4_32K]: ChatModels.GPT_4_32K, + [ChatModelDisplayNames.GEMINI_PRO]: ChatModels.GEMINI_PRO, }; // Model Providers @@ -81,12 +88,14 @@ export const HUGGINGFACE = 'huggingface'; export const COHEREAI = 'cohereai'; export const AZURE_OPENAI = 'azure_openai'; export const ANTHROPIC = 'anthropic'; +export const GOOGLE = 'google'; export const LOCALAI = 'localai'; export const VENDOR_MODELS: Record> = { [OPENAI]: OPENAI_MODELS, [AZURE_OPENAI]: AZURE_MODELS, [ANTHROPIC]: CLAUDE_MODELS, + [GOOGLE]: GOOGLE_MODELS, }; // Embedding Models @@ -106,6 +115,7 @@ export const DEFAULT_SETTINGS: CopilotSettings = { azureOpenAIApiDeploymentName: '', azureOpenAIApiVersion: '', azureOpenAIApiEmbeddingDeploymentName: '', + googleApiKey: '', defaultModel: ChatModels.GPT_4_TURBO, defaultModelDisplayName: ChatModelDisplayNames.GPT_4_TURBO, temperature: 0.7, diff --git a/src/main.ts b/src/main.ts index 99fa9abc..20d0a5f3 100644 --- a/src/main.ts +++ b/src/main.ts @@ -27,6 +27,7 @@ export interface CopilotSettings { azureOpenAIApiDeploymentName: string; azureOpenAIApiVersion: string; azureOpenAIApiEmbeddingDeploymentName: string; + googleApiKey: string; defaultModel: string; defaultModelDisplayName: string; temperature: number; @@ -482,6 +483,7 @@ export default class CopilotPlugin extends Plugin { azureOpenAIApiDeploymentName, azureOpenAIApiVersion, azureOpenAIApiEmbeddingDeploymentName, + googleApiKey, temperature, maxTokens, contextTurns, @@ -498,6 +500,7 @@ export default class CopilotPlugin extends Plugin { azureOpenAIApiDeploymentName, azureOpenAIApiVersion, azureOpenAIApiEmbeddingDeploymentName, + googleApiKey, localAIModel, model: this.settings.defaultModel, modelDisplayName: this.settings.defaultModelDisplayName, diff --git a/src/settings.ts b/src/settings.ts index 77563d7d..7909d85d 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -85,6 +85,7 @@ export class CopilotSettingTab extends PluginSettingTab { ChatModelDisplayNames.AZURE_GPT_35_TURBO_16K, ChatModelDisplayNames.AZURE_GPT_4, ChatModelDisplayNames.AZURE_GPT_4_32K, + ChatModelDisplayNames.GEMINI_PRO, ChatModelDisplayNames.LOCAL_AI, ]; @@ -205,6 +206,32 @@ export class CopilotSettingTab extends PluginSettingTab { // } // ); + containerEl.createEl('h6', { text: 'Google Gemini API' }); + + new Setting(containerEl) + .setName("Your Google API key") + .setDesc( + createFragment((frag) => { + frag.appendText("If you have Google Cloud, you can get Gemini API key "); + frag.createEl('a', { + text: "here", + href: "https://makersuite.google.com/app/apikey" + }); + }) + ) + .addText((text) => { + text.inputEl.type = "password"; + text.inputEl.style.width = "100%"; + text + .setPlaceholder("Google API key") + .setValue(this.plugin.settings.googleApiKey) + .onChange(async (value) => { + this.plugin.settings.googleApiKey = value; + await this.plugin.saveSettings(); + }) + } + ); + containerEl.createEl('h6', { text: 'Azure OpenAI API' }); new Setting(containerEl) diff --git a/versions.json b/versions.json index 3f45ce69..7ff9953b 100644 --- a/versions.json +++ b/versions.json @@ -27,5 +27,6 @@ "2.4.3": "0.15.0", "2.4.4": "0.15.0", "2.4.5": "0.15.0", - "2.4.6": "0.15.0" + "2.4.6": "0.15.0", + "2.4.7": "0.15.0" } \ No newline at end of file