Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Llm candidate #149

Merged
merged 11 commits into from
Sep 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions .github/workflows/quality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,15 @@ jobs:
cargo-deny:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install Rust
- uses: actions/checkout@v4
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
profile: minimal
override: true
- name: Run sccache-cache
uses: Xuanwo/sccache-action@c94e27bef21ab3fb4a5152c8a878c53262b4abb0
with:
version: "v0.4.0-pre.6"
uses: mozilla-actions/[email protected]
- name: Get Date
id: get-date
run: |
Expand Down
17 changes: 7 additions & 10 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ name: Linux and macOS
# Template Reference: https://www.infinyon.com/blog/2021/04/github-actions-best-practices/
on:
push:
branches: [ master ]
branches: [ master, llm_candidate ]
pull_request:
branches: [ master ]
branches: [ master, llm_candidate ]

env:
CARGO_TERM_COLOR: always
Expand All @@ -22,17 +22,17 @@ jobs:
os: [ubuntu-latest, macos-13, macos-14]
rust: [stable]
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Run sccache-cache
uses: mozilla-actions/[email protected]
- name: Install Rust ${{ matrix.rust }}
uses: actions-rs/toolchain@v1
with:
toolchain: ${{ matrix.rust }}
profile: minimal
override: true
- name: Run sccache-cache
uses: mozilla-actions/sccache-action@c94e27bef21ab3fb4a5152c8a878c53262b4abb0
with:
version: "v0.4.0-pre.6"
uses: mozilla-actions/[email protected]
- name: Get Date
id: get-date
run: |
Expand Down Expand Up @@ -74,7 +74,6 @@ jobs:
- name: Run sccache stat for check
shell: bash
run: ${SCCACHE_PATH} --show-stats



release:
Expand All @@ -89,9 +88,7 @@ jobs:
profile: minimal
override: true
- name: Run sccache-cache
uses: Xuanwo/sccache-action@c94e27bef21ab3fb4a5152c8a878c53262b4abb0
with:
version: "v0.4.0-pre.6"
uses: mozilla-actions/[email protected]
- name: Get Date
id: get-date
run: |
Expand Down
6 changes: 6 additions & 0 deletions docs/examples.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## LLM

2024 Sept 22

https://github.com/user-attachments/assets/b0a4ca66-0a33-401a-a916-af7a69f2ae7b

## ObsidianMD

[obsidian_example_2023-Feb-05.mp4](
Expand Down
29 changes: 29 additions & 0 deletions docs/release_notes_0.2_2024Sep.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
### 0.2.1

New feature: Note Summarization with Local LLM.

What happens locally, what stays locally.

#### Run server with local LLM
fireSeqSearch facilitates [llamafile](https://github.com/Mozilla-Ocho/llamafile) by [Mozilla](https://github.com/Mozilla-Ocho).

```
mkdir -pv ~/.llamafile && cd ~/.llamafile
wget https://huggingface.co/Mozilla/Mistral-7B-Instruct-v0.2-llamafile/resolve/main/mistral-7b-instruct-v0.2.Q4_0.llamafile?download=true
chmod +x mistral-7b-instruct-v0.2.Q4_0.llamafile
```

After that, compile and run fireSeqSearch with LLM
```
cargo build --features llm
target/debug/fire_seq_search_server --notebook_path ~/logseq
# Obsidian users
target/debug/fire_seq_search_server --notebook_path ~/obsidian --obsidian-md
```

Finally, update the [Firefox Addon](https://addons.mozilla.org/en-US/firefox/addon/fireseqsearch/).

#### Demo Video
https://github.com/user-attachments/assets/b0a4ca66-0a33-401a-a916-af7a69f2ae7b

This demo used [AstroWiki](https://github.com/AYelland/AstroWiki_2.0), which is licensed under MIT license.
185 changes: 135 additions & 50 deletions fireSeqSearch_addon/main.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// MIT License
// Copyright (c) 2021-2023 Zhenbo Li
// Copyright (c) 2021-2024 Zhenbo Li

const fireSeqSearchDomId = "fireSeqSearchDom";

Expand Down Expand Up @@ -128,79 +128,151 @@ function checkUserOptions() {
ShowHighlight: res[2].ShowHighlight,
ShowScore: res[3].ShowScore
}
consoleLogForDebug(options);
return options;
});
}


async function appendResultToSearchResult(fetchResultArray, _container) {
const serverInfo = fetchResultArray[0];
const rawSearchResult = fetchResultArray[1];
const firefoxExtensionUserOption = await checkUserOptions();
function parseRawList(rawSearchResult) {
const hits = [];
for (const rawRecord of rawSearchResult) {
const record = JSON.parse(rawRecord);
hits.push(record);
}
return hits;
}

consoleLogForDebug('Loaded user option: ' + JSON.stringify(firefoxExtensionUserOption));
async function processLlmSummary(serverInfo, parsedSearchResult, fireDom) {

const doneListApi = "http://127.0.0.1:3030/llm_done_list";
let list = await fetch(doneListApi);
list = await list.text();
list = JSON.parse(list);

const findByTitle = function(title) {
const ul = fireDom.querySelector( ".fireSeqSearchHitList" );
if (ul === null) return null;
for (const child of ul.children) {
const liTitle = child.firstChild.text;
if (title === liTitle) {
return child;
}
}
return null;
};
const setLlmResult = function (title, llmSummary) {
const targetRow = findByTitle(title);
if (targetRow === null) {
consoleLogForDebug("Error! Can't find dom for ", title);
return;
}
if (targetRow.querySelector( ".fireSeqSearchLlmSummary" ) != null) {
consoleLogForDebug("Skip. We have the summary for ", title);
return;
}

function createTitleBarDom(count) {
const summary = createElementWithText("span", "");
summary.innerHTML = llmSummary;
summary.classList.add('fireSeqSearchLlmSummary');
targetRow.appendChild(summary);
};
for (const record of parsedSearchResult) {
const title = record.title;
if (!list.includes(title)) {
consoleLogForDebug("Not ready, skip" + title);
continue;
}
// TODO remove hard code port
const llm_api = "http://127.0.0.1:3030/summarize/" + title;
let sum = await fetch(llm_api);
sum = await sum.text();
setLlmResult(title, sum);
}
}


function createFireSeqDom(serverInfo, parsedSearchResult) {
const count = parsedSearchResult.length;
const div = document.createElement("div");
div.setAttribute("id", fireSeqSearchDomId);

const createTitleBarDom = function () {
const titleBar = createElementWithText("div");
titleBar.classList.add('fireSeqSearchTitleBar');
const hitCount = `<span>We found <b>${count.toString()}</b> results in your logseq notebook</span>`;
titleBar.insertAdjacentHTML("afterbegin",hitCount);
const btn = document.createElement("button");

function setSummaryState(cl, state) {
let prop = 'none';
if (state) { prop = ''; }
for (const el of document.querySelectorAll(cl)) {
el.style.display=prop;
}
}
let btn = document.createElement("button");
btn.classList.add("hideSummary");
const text = document.createTextNode("Hide Summary (Tmp)");
let text = document.createTextNode("Hide Summary");
btn.appendChild(text);
btn.onclick = function () {
// alert("Button is clicked");
for (const el of document.querySelectorAll('.fireSeqSearchHitSummary')) {
// el.style.visibility = 'hidden';
el.remove();
}
setSummaryState(".fireSeqSearchHitSummary", false);
setSummaryState(".fireSeqSearchLlmSummary", false);
};
titleBar.appendChild(btn);
return titleBar;
}
function createFireSeqDom() {
const div = document.createElement("div");
div.setAttribute("id", fireSeqSearchDomId);
return div;
}

const dom = createFireSeqDom();
dom.appendChild(createTitleBarDom(rawSearchResult.length));
consoleLogForDebug(dom);

const hitList = document.createElement("ul");
btn = document.createElement("button");
btn.classList.add("showSummary");
text = document.createTextNode("Summary");
btn.appendChild(text);
btn.onclick = function () {
setSummaryState(".fireSeqSearchHitSummary", true);
setSummaryState(".fireSeqSearchLlmSummary", false);
};
titleBar.appendChild(btn);

consoleLogForDebug(rawSearchResult);
for (const rawRecord of rawSearchResult) {
// const e = document.createTextNode(record);
consoleLogForDebug(rawRecord);
const record = JSON.parse(rawRecord);
consoleLogForDebug(typeof record);
btn = document.createElement("button");
btn.classList.add("showLlm");
text = document.createTextNode("LLM");
btn.appendChild(text);
btn.onclick = function () {
setSummaryState(".fireSeqSearchHitSummary", false);
setSummaryState(".fireSeqSearchLlmSummary", true);
processLlmSummary(serverInfo, parsedSearchResult, div);
};
titleBar.appendChild(btn);
return titleBar;
};
const bar = createTitleBarDom();
div.appendChild(bar);
return div;
}

const li = createElementWithText("li", "");
async function appendResultToSearchResult(serverInfo, parsedSearchResult, dom) {
const firefoxExtensionUserOption = await checkUserOptions();
consoleLogForDebug('Loaded user option: ' + JSON.stringify(firefoxExtensionUserOption));

function buildListItems(parsedSearchResult) {
const hitList = document.createElement("ul");
hitList.classList.add('fireSeqSearchHitList');
for (const record of parsedSearchResult) {
const li = createElementWithText("li", "");
li.classList.add('fireSeqSearchHitListItem');
if (firefoxExtensionUserOption.ShowScore) {
const score = createElementWithText("span", String(record.score));
li.appendChild(score);
}
const href = createHrefToLogseq(record, serverInfo);
li.appendChild(href);

if (firefoxExtensionUserOption.ShowScore) {
const score = createElementWithText("span", String(record.score));
li.appendChild(score);
}
const href = createHrefToLogseq(record, serverInfo);
li.appendChild(href);
li.append(' ')
if (firefoxExtensionUserOption.ShowHighlight) {
const summary = createElementWithText("span", "");
summary.innerHTML = record.summary;
summary.classList.add('fireSeqSearchHitSummary');
li.appendChild(summary);
}
// let e = wrapRawRecordIntoElement(record, serverInfo);

// e.style.
hitList.appendChild(li);
// consoleLogForDebug("Added an element to the list");
hitList.appendChild(li);
}
return hitList;
}
const hitList = buildListItems(parsedSearchResult);
dom.appendChild(hitList);

if (firefoxExtensionUserOption.ExperimentalLayout) {
Expand Down Expand Up @@ -228,6 +300,21 @@ async function appendResultToSearchResult(fetchResultArray, _container) {
insertDivToWebpage(dom);
}

async function mainProcess(fetchResultArray) {
consoleLogForDebug("main process");

const serverInfo = fetchResultArray[0];
const rawSearchResult = fetchResultArray[1];
consoleLogForDebug(serverInfo);
const parsedSearchResult = parseRawList(rawSearchResult);

const fireDom = createFireSeqDom(serverInfo, parsedSearchResult);

appendResultToSearchResult(serverInfo, parsedSearchResult, fireDom);

}


function getSearchParameterFromCurrentPage() {
let searchParam = "";

Expand Down Expand Up @@ -259,7 +346,6 @@ function getSearchParameterFromCurrentPage() {
(function() {
const searchParameter = getSearchParameterFromCurrentPage();


addGlobalStyle(fireSeqSearchScriptCSS);

//https://gomakethings.com/waiting-for-multiple-all-api-responses-to-complete-with-the-vanilla-js-promise.all-method/
Expand All @@ -269,8 +355,7 @@ function getSearchParameterFromCurrentPage() {
]).then(function (responses) {
return Promise.all(responses.map(function (response) {return response.json();}));
}).then(function (data) {
consoleLogForDebug(data);
return appendResultToSearchResult(data);
mainProcess(data);
}).then((_e) => {
const highlightedItems = document.querySelectorAll('.fireSeqSearchHighlight');
consoleLogForDebug(highlightedItems);
Expand Down
2 changes: 1 addition & 1 deletion fireSeqSearch_addon/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"manifest_version": 2,
"name": "fireSeqSearch",
"version": "0.1.4",
"version": "0.2.2",

"description": "Everytime you use the search engine, this plugin will search against your personal logseq notes.",

Expand Down
Loading
Loading