mirror of
https://github.com/khoaliber/khoj.git
synced 2026-03-03 05:29:12 +00:00
Add Offline chat to Obsidian (#359)
* Add support for configuring/using offline chat from within Obsidian * Fix type checking for search type * If Github is not configured, /update call should fail * Fix regenerate tests same as the update ones * Update help text for offline chat in obsidian * Update relevant description for Khoj settings in Obsidian * Simplify configuration logic and use smarter defaults
This commit is contained in:
@@ -38,9 +38,9 @@ export default class Khoj extends Plugin {
|
||||
id: 'chat',
|
||||
name: 'Chat',
|
||||
checkCallback: (checking) => {
|
||||
if (!checking && this.settings.connectedToBackend && !!this.settings.openaiApiKey)
|
||||
if (!checking && this.settings.connectedToBackend && (!!this.settings.openaiApiKey || this.settings.enableOfflineChat))
|
||||
new KhojChatModal(this.app, this.settings).open();
|
||||
return !!this.settings.openaiApiKey;
|
||||
return !!this.settings.openaiApiKey || this.settings.enableOfflineChat;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import { App, Notice, PluginSettingTab, request, Setting } from 'obsidian';
|
||||
import Khoj from 'src/main';
|
||||
|
||||
export interface KhojSetting {
|
||||
enableOfflineChat: boolean;
|
||||
openaiApiKey: string;
|
||||
resultsCount: number;
|
||||
khojUrl: string;
|
||||
@@ -10,6 +11,7 @@ export interface KhojSetting {
|
||||
}
|
||||
|
||||
export const DEFAULT_SETTINGS: KhojSetting = {
|
||||
enableOfflineChat: false,
|
||||
resultsCount: 6,
|
||||
khojUrl: 'http://127.0.0.1:42110',
|
||||
connectedToBackend: false,
|
||||
@@ -35,7 +37,7 @@ export class KhojSettingTab extends PluginSettingTab {
|
||||
// Add khoj settings configurable from the plugin settings tab
|
||||
new Setting(containerEl)
|
||||
.setName('Khoj URL')
|
||||
.setDesc('The URL of the Khoj backend')
|
||||
.setDesc('The URL of the Khoj backend.')
|
||||
.addText(text => text
|
||||
.setValue(`${this.plugin.settings.khojUrl}`)
|
||||
.onChange(async (value) => {
|
||||
@@ -45,16 +47,25 @@ export class KhojSettingTab extends PluginSettingTab {
|
||||
}));
|
||||
new Setting(containerEl)
|
||||
.setName('OpenAI API Key')
|
||||
.setDesc('Your OpenAI API Key for Khoj Chat')
|
||||
.setDesc('Use OpenAI for Khoj Chat with your API key.')
|
||||
.addText(text => text
|
||||
.setValue(`${this.plugin.settings.openaiApiKey}`)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.openaiApiKey = value.trim();
|
||||
await this.plugin.saveSettings();
|
||||
}));
|
||||
new Setting(containerEl)
|
||||
.setName('Enable Offline Chat')
|
||||
.setDesc('Chat privately without an internet connection. Enabling this will use offline chat even if OpenAI is configured.')
|
||||
.addToggle(toggle => toggle
|
||||
.setValue(this.plugin.settings.enableOfflineChat)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.enableOfflineChat = value;
|
||||
await this.plugin.saveSettings();
|
||||
}));
|
||||
new Setting(containerEl)
|
||||
.setName('Results Count')
|
||||
.setDesc('The number of results to show in search and use for chat')
|
||||
.setDesc('The number of results to show in search and use for chat.')
|
||||
.addSlider(slider => slider
|
||||
.setLimits(1, 10, 1)
|
||||
.setValue(this.plugin.settings.resultsCount)
|
||||
@@ -65,7 +76,7 @@ export class KhojSettingTab extends PluginSettingTab {
|
||||
}));
|
||||
new Setting(containerEl)
|
||||
.setName('Auto Configure')
|
||||
.setDesc('Automatically configure the Khoj backend')
|
||||
.setDesc('Automatically configure the Khoj backend.')
|
||||
.addToggle(toggle => toggle
|
||||
.setValue(this.plugin.settings.autoConfigure)
|
||||
.onChange(async (value) => {
|
||||
@@ -75,7 +86,7 @@ export class KhojSettingTab extends PluginSettingTab {
|
||||
let indexVaultSetting = new Setting(containerEl);
|
||||
indexVaultSetting
|
||||
.setName('Index Vault')
|
||||
.setDesc('Manually force Khoj to re-index your Obsidian Vault')
|
||||
.setDesc('Manually force Khoj to re-index your Obsidian Vault.')
|
||||
.addButton(button => button
|
||||
.setButtonText('Update')
|
||||
.setCta()
|
||||
|
||||
@@ -9,6 +9,19 @@ export function getVaultAbsolutePath(vault: Vault): string {
|
||||
return '';
|
||||
}
|
||||
|
||||
type OpenAIType = null | {
|
||||
"chat-model": string;
|
||||
"api-key": string;
|
||||
};
|
||||
|
||||
interface ProcessorData {
|
||||
conversation: {
|
||||
"conversation-logfile": string;
|
||||
openai: OpenAIType;
|
||||
"enable-offline-chat": boolean;
|
||||
};
|
||||
}
|
||||
|
||||
export async function configureKhojBackend(vault: Vault, setting: KhojSetting, notify: boolean = true) {
|
||||
let vaultPath = getVaultAbsolutePath(vault);
|
||||
let mdInVault = `${vaultPath}/**/*.md`;
|
||||
@@ -132,48 +145,36 @@ export async function configureKhojBackend(vault: Vault, setting: KhojSetting, n
|
||||
}
|
||||
}
|
||||
|
||||
// If OpenAI API key not set in Khoj plugin settings
|
||||
if (!setting.openaiApiKey) {
|
||||
// Disable khoj processors, as not required
|
||||
delete data["processor"];
|
||||
let conversationLogFile = data?.["processor"]?.["conversation"]?.["conversation-logfile"] ?? `${khojDefaultChatDirectory}/conversation.json`;
|
||||
|
||||
let processorData: ProcessorData = {
|
||||
"conversation": {
|
||||
"conversation-logfile": conversationLogFile,
|
||||
"openai": null,
|
||||
"enable-offline-chat": setting.enableOfflineChat,
|
||||
}
|
||||
}
|
||||
// Else if khoj backend not configured yet
|
||||
else if (!khoj_already_configured || !data["processor"]) {
|
||||
data["processor"] = {
|
||||
|
||||
// If the Open AI API Key was configured in the plugin settings
|
||||
if (!!setting.openaiApiKey) {
|
||||
|
||||
let openAIChatModel = data?.["processor"]?.["conversation"]?.["openai"]?.["chat-model"] ?? khojDefaultChatModelName;
|
||||
|
||||
processorData = {
|
||||
"conversation": {
|
||||
"conversation-logfile": `${khojDefaultChatDirectory}/conversation.json`,
|
||||
"conversation-logfile": conversationLogFile,
|
||||
"openai": {
|
||||
"chat-model": khojDefaultChatModelName,
|
||||
"chat-model": openAIChatModel,
|
||||
"api-key": setting.openaiApiKey,
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
// Else if khoj config has no conversation processor config
|
||||
else if (!data["processor"]["conversation"] || !data["processor"]["conversation"]["openai"]) {
|
||||
data["processor"] = {
|
||||
"conversation": {
|
||||
"conversation-logfile": `${khojDefaultChatDirectory}/conversation.json`,
|
||||
"openai": {
|
||||
"chat-model": khojDefaultChatModelName,
|
||||
"api-key": setting.openaiApiKey,
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
// Else if khoj is not configured with OpenAI API key from khoj plugin settings
|
||||
else if (data["processor"]["conversation"]["openai"]["api-key"] !== setting.openaiApiKey) {
|
||||
data["processor"] = {
|
||||
"conversation": {
|
||||
"conversation-logfile": data["processor"]["conversation"]["conversation-logfile"],
|
||||
"openai": {
|
||||
"chat-model": data["processor"]["conversation"]["openai"]["chat-model"],
|
||||
"api-key": setting.openaiApiKey,
|
||||
}
|
||||
},
|
||||
"enable-offline-chat": setting.enableOfflineChat,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Set khoj processor config to conversation processor config
|
||||
data["processor"] = processorData;
|
||||
|
||||
// Save updated config and refresh index on khoj backend
|
||||
updateKhojBackend(setting.khojUrl, data);
|
||||
if (!khoj_already_configured)
|
||||
|
||||
Reference in New Issue
Block a user