Skip to content

Commit

Permalink
2.18.4: feat: Ask your vault questions with the command Ava Ask
Browse files Browse the repository at this point in the history
  • Loading branch information
louis030195 committed Feb 24, 2023
1 parent 246b42f commit 8250938
Show file tree
Hide file tree
Showing 8 changed files with 148 additions and 23 deletions.
2 changes: 1 addition & 1 deletion manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "ava",
"name": "🧙 AVA",
"version": "2.18.3",
"version": "2.18.4",
"minAppVersion": "0.12.0",
"description": "AI assistant for Obsidian",
"author": "louis030195",
Expand Down
31 changes: 29 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ava",
"version": "2.18.3",
"version": "2.18.4",
"description": "AI assistant for Obsidian",
"main": "main.js",
"scripts": {
Expand All @@ -18,6 +18,7 @@
"license": "MIT",
"dependencies": {
"@heroicons/react": "^2.0.13",
"embeddings-splitter": "^0.0.5",
"lodash": "^4.17.21",
"posthog-js": "^1.37.0",
"react": "^18.2.0",
Expand Down
20 changes: 16 additions & 4 deletions src/PromptModal.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,25 @@
import { App, Modal, Setting } from 'obsidian';

interface Titles {
heading: string;
subheading: string;
button: string;
}
const defaultTitles: Titles = {
heading: 'Write a paragraph about',
subheading: 'Write a paragraph about',
button: 'Write paragraph',
};
export class PromptModal extends Modal {
text: string;
titles: Titles;

onSubmit: (text: string) => void;

constructor(app: App, onSubmit: (text: string) => void) {
constructor(app: App, onSubmit: (text: string) => void, titles: Titles = defaultTitles) {
super(app);
this.onSubmit = onSubmit;
this.titles = titles;
}

search = (evt: Event) => {
Expand All @@ -19,10 +31,10 @@ export class PromptModal extends Modal {
onOpen() {
const { contentEl } = this;

contentEl.createEl('h1', { text: 'AVA - Paragraph Assist' });
contentEl.createEl('h1', { text: this.titles.heading });
const form = contentEl.createEl('form');
form.onsubmit = this.search;
new Setting(form).setName('Write a paragraph about').addText((text) =>
new Setting(form).setName(this.titles.subheading).addText((text) =>
text.setValue(this.text).onChange((value) => {
this.text = value;
})
Expand All @@ -31,7 +43,7 @@ export class PromptModal extends Modal {
new Setting(form).addButton((btn) => {
btn.buttonEl.type = 'submit';

return btn.setButtonText('Write paragraph').setCta().onClick(this.search);
return btn.setButtonText(this.titles.button).setCta().onClick(this.search);
});
}

Expand Down
67 changes: 59 additions & 8 deletions src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import { RewriteModal } from './RewriteModal';
import { store } from './store';
import { tutorial } from './tutorial';
import { VIEW_TYPE_WRITE, WriteView } from './writeView';
import { generativeSearch } from './prompt';

// e.g. ["Buddhism/Veganism"]
// path: "Buddhism/Veganism/2021-01-01.md" should be ignored
Expand Down Expand Up @@ -125,18 +126,14 @@ export default class AvaPlugin extends Plugin {
* Semantically search your vault
* Example:
```ts
const response = await search({
note: {
notePath: 'path/to/note.md',
noteContent: 'text of the note',
noteTags: ['tag1', 'tag2'],
},
});
const response = await search(
'the note disccusing the white horse of Henry VIII'
);
console.log(response);
```
*/

public search: (request: ISearchRequest) => Promise<ISearchResponse>;
public search: (query: string) => Promise<ISearchResponse>;
public clearIndex: () => Promise<any>;
private eventRefRenamed: EventRef;
private eventRefDeleted: EventRef;
Expand Down Expand Up @@ -862,6 +859,60 @@ export default class AvaPlugin extends Plugin {
// can configure various aspects of the plugin
this.addSettingTab(new AvaSettingTab(this.app, this));
});

this.addCommand({
id: 'ava-generative-search',
name: 'Ask',
editorCallback: (editor: Editor) => {
posthog.capture('use-feature', { feature: 'ask' });
new Notice('🧙 Asking your vault', 2000);
if (!this.settings.token) {
new Notice('🧙 You need to login to use this feature', 2000);
return;
}

const onSubmit = async (text: string) => {
this.statusBarItem.render(<StatusBar status="loading" />);
try {
this.setStreamingSource(
await generativeSearch(
text,
this.settings.token,
this.settings.vaultId,
this.manifest.version,
)
);
this.streamingSource.addEventListener(
'message',
function (e: any) {
const payload = JSON.parse(e.data);
console.log(payload);
const currentLine = editor.getCursor().line;
const lastChar = editor.getLine(currentLine).length;
editor.setCursor({ line: currentLine, ch: lastChar });
editor.replaceRange(
`${payload.choices[0].text}`,
editor.getCursor()
);
}
);
this.streamingSource.addEventListener('error', onSSEError);
this.streamingSource.stream();
this.statusBarItem.render(<StatusBar status="success" />);
} catch (e) {
onGeneralError(e.message);
new Notice(`️⛔️ AVA ${e}`, 4000);
this.statusBarItem.render(<StatusBar status="error" />);
}
};

new PromptModal(this.app, onSubmit, {
heading: 'Ask your vault',
subheading: 'What do you want to know?',
button: 'Ask',
}).open();
},
});
}

// eslint-disable-next-line require-jsdoc
Expand Down
34 changes: 34 additions & 0 deletions src/prompt.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { complete, search } from "./utils";

// TODO: make it work on browser
// import { merge } from 'embeddings-splitter';
const maxLen = 1800; // TODO: probably should be more with string length
// TODO: very experimental
export const createContext = async (question: string, token: string, vaultId: string, version: string) => {
const searchResponse = await search(question, token, vaultId, version);
let curLen = 0;
const returns = [];
for (const similarity of searchResponse["similarities"]) {
const sentence = similarity["data"];
// const nTokens = enc.encode(sentence).length;
const nChars = sentence.length;
// curLen += nTokens + 4;
curLen += nChars;
if (curLen > maxLen) {
break;
}
returns.push(sentence);
}
return returns.join("\n\n###\n\n");
// return output;
// return merge(searchResponse["similarities"].map((similarity) => similarity["data"]));
}

export const generativeSearch = async (question: string, token: string, vaultId: string, version: string) => {
const context = await createContext(question, token, vaultId, version);
const newPrompt = `Answer the question based on the context below, and if the question can't be answered based on the context, say "I don't know"\n\nContext: ${context}\n\n---\n\nQuestion: ${question}\nAnswer:`;
console.log('generativeSearch', newPrompt);
return complete(newPrompt, token, version, {
stream: true,
});
};
11 changes: 5 additions & 6 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { SSE } from 'lib/sse';
import { camelCase, isArray, isObject, transform } from 'lodash';
import { App } from 'obsidian';
import posthog from 'posthog-js';
import { API_HOST, buildHeaders, EMBEDBASE_URL } from './constants';
import AvaPlugin from './main';

Expand Down Expand Up @@ -40,11 +39,12 @@ export interface ISearchResponse {
export const REWRITE_CHAR_LIMIT = 5800;
export const EMBED_CHAR_LIMIT = 25000;
export const search = async (
request: ISearchRequest,
query: string,
token: string,
vaultId: string,
version: string,
): Promise<ISearchResponse> => {
console.log('Search query:', query);
const response = await fetch(`${EMBEDBASE_URL}/v1/${vaultId}/search`, {
method: 'POST',
headers: {
Expand All @@ -53,12 +53,13 @@ export const search = async (
'X-Client-Version': version,
},
body: JSON.stringify({
query: request.query,
query: query,
}),
}).then((res) => res.json());
if (response.message) {
throw new Error(`Failed to search: ${response.message}`);
}
console.log('Search response:', response);
return response;
};

Expand All @@ -70,9 +71,7 @@ export const createSemanticLinks = async (
version: string,
) => {
const response = await search(
{
query: `File:\n${title}\nContent:\n${text}`,
},
`File:\n${title}\nContent:\n${text}`,
token,
vaultId,
version,
Expand Down
3 changes: 2 additions & 1 deletion versions.json
Original file line number Diff line number Diff line change
Expand Up @@ -151,5 +151,6 @@
"2.17.1": "0.12.0",
"2.17.2": "0.12.0",
"2.17.3": "0.12.0",
"2.18.3": "0.12.0"
"2.18.3": "0.12.0",
"2.18.4": "0.12.0"
}

0 comments on commit 8250938

Please sign in to comment.