Skip to content

Commit

Permalink
Merge pull request #52 from SkywardAI/rag-implement
Browse files Browse the repository at this point in the history
implement RAG features
  • Loading branch information
cbh778899 authored Jul 24, 2024
2 parents 3490a43 + 6242c76 commit 29abf4a
Show file tree
Hide file tree
Showing 18 changed files with 605 additions and 151 deletions.
5 changes: 3 additions & 2 deletions components/chat-page/chatMain.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import getSVG from "../../tools/svgs.js";
import createRAGSelector from "./rag-blocks.js";

let conversation = {pending: false}, model_settings = {},
main_elem, toggle_expand,
main_elem, toggle_expand, open_settings_page,
stream_response=true, download_conversation_icon;

let abort_controller;
Expand Down Expand Up @@ -83,6 +83,7 @@ export default function createChatMain(main, toggleExpand, openModelSetting) {
</div>`)

toggle_expand = toggleExpand;
open_settings_page = openModelSetting;
document.getElementById('submit-chat').onsubmit=submitContent;
main_elem = document.getElementById('conversation-main');
document.getElementById('toggle-sidebar-expand').onclick = toggle_expand;
Expand Down Expand Up @@ -256,7 +257,7 @@ function updateConversation() {
if(!conversation.history) return;
if(!conversation.history.length && main_elem) {
main_elem.innerHTML = "<div class='greeting start-session'>Hi, how can I help you today?</div>"
main_elem.appendChild(createRAGSelector(conversation))
main_elem.appendChild(createRAGSelector(open_settings_page))
return;
}

Expand Down
4 changes: 2 additions & 2 deletions components/chat-page/history.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ function updateHistoryList() {
const tickets_list = document.createElement('div')
tickets_list.className='tickets-list'

history.forEach(({id, name, type, createdAt}) => {
history.forEach(({id, name, session_type, dataset_name, createdAt}) => {
const ticket = document.createElement('div')
ticket.className = 'ticket clickable'
id === last_selected_id && ticket.classList.add('selected')
Expand All @@ -64,7 +64,7 @@ function updateHistoryList() {
<div class='datetime'>${createdAt}</div>`

ticket.onclick = () => {
selectConversation(id, name, type);
selectConversation(id, name, session_type, dataset_name);
}

tickets_list.appendChild(ticket)
Expand Down
2 changes: 1 addition & 1 deletion components/chat-page/model-settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export default function createModelSettings(main) {

for(const key in fields) {
const { title, valueRange } = fields[key];
const [component, setter] = rangeSettingSection(
const [component, {setter}] = rangeSettingSection(
title, valueRange,
() => { setToDefault(key) && loadSettings() },
value=>updateModelSettings(key, value)
Expand Down
67 changes: 52 additions & 15 deletions components/chat-page/normal-setting-section.js
Original file line number Diff line number Diff line change
@@ -1,37 +1,74 @@
/**
* create a normal setting section
* @param { "text" | "select" } type What type this section should contains
* @param { "text" | "select" | "button" } type What type this section should contains
* @param {String} title Name of this secction, apperas on top
* @param {Function} callback Callback function takes one parameter of updated value of this section
* @returns { [HTMLElement, Function] } Returns an array where index 0 is the element of section and index 1 is the setter function
* @returns { [HTMLElement, Function, Function] }
* Returns an array containes necessary fields
* **Index 0**: The HTMLElement
* **Index 1**: The setter function to update value
* **Index 2**: The setter function to update args
*/
export default function normalSettigSection(type, title, callback, ...args) {
export default function normalSettigSection(type, title, callback = null, ...args) {
const section = document.createElement('div');
section.className = 'setting-section'
section.innerHTML = `<div class='title'>${title}</div>`;

let input_like;
if(type === 'text') {
input_like = document.createElement('input');
input_like.type = 'text';
} else if(type === 'select') {

function setArgs(...new_args) {
args = new_args;
loadArgs();
}

function loadArgs() {
if(type === 'select') {
input_like.innerHTML = '';
args[0].forEach(({value, title})=>{
const option = document.createElement('option');
option.value = value;
option.textContent = title || value;
input_like.appendChild(option);
})
} else if(type === 'button') {
input_like.value = args[0];
input_like.onclick = args[1];
input_like.classList.add('clickable')
}
}

if(type === 'select') {
input_like = document.createElement('select');
args[0].forEach(({value, title})=>{
const option = document.createElement('option');
option.textContent = title || value;
input_like.appendChild(option);
})
} else {
input_like = document.createElement('input');
input_like.type = type;
}

function setter(value) {
loadArgs();

function setValue(value) {
input_like.value = value;
}

function toggleDisable(is_disabled) {
switch(type) {
case 'text':
input_like.disable = is_disabled;
break;
case 'button':
input_like.onclick = is_disabled ? null : args[1];
break;
case 'select':
input_like.classList.toggle('disabled', is_disabled);
break;
}
}

input_like.onchange = () => {
callback(input_like.value);
callback && callback(input_like.value);
}

section.appendChild(input_like)

return [section, setter];
return [section, { setValue, setArgs, toggleDisable }];
}
31 changes: 23 additions & 8 deletions components/chat-page/rag-blocks.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,32 @@
import request from "../../tools/request.js";
import showMessage from "../../tools/message.js";
import useUser from "../../global/useUser.js";
import useHistory from "../../global/useHistory.js";
import useConversation from "../../global/useConversation.js";

const rag_modes = [
{ mode: 'on' },
{ mode: 'off' },
{ mode: 'hybrid', disabled: true },
]

let user_id = null;
let user_id = null, conversation = {};
useUser(user=>{
user_id = user.id;
})

async function updateRAG(mode, element, id) {
const { updateHistoryInfo } = useHistory();
const { updateConversationInfo } = useConversation(c=>{
conversation = c;
})

async function updateRAG(mode, element, id, expand_setting) {
if(mode === 'on') {
const { http_error } = await request('chat/session', {
method: 'PATCH',
body: {
sessionUuid: id,
type: 'rag'
session_type: 'rag'
}
})
if(http_error) {
Expand All @@ -28,22 +35,30 @@ async function updateRAG(mode, element, id) {
}
}
showMessage(`This session will start with RAG ${mode}`);
updateHistoryInfo(id, 'session_type', 'chat');
element.classList.add('completed');
await new Promise(s=>setTimeout(s, 1000));
element.insertAdjacentHTML(
"beforebegin",
`<div class='greeting rag-info'>RAG <strong>${mode.toUpperCase()}</strong></div>`
)
element.remove();
if(mode == 'on') {
await new Promise(s=>setTimeout(s, 600));
updateHistoryInfo(id, 'session_type', 'rag');
updateConversationInfo('session_type', 'rag');
showMessage("Please set your dataset for RAG");
expand_setting();
}
}

export default function createRAGSelector(conversation) {
if(conversation.type || user_id === null) {
export default function createRAGSelector(expand_setting) {
if(conversation.session_type || user_id === null) {
const rag_info = document.createElement('div');
rag_info.className = 'greeting rag-info';
rag_info.innerHTML = `RAG <strong>${
conversation.type === 'rag' ? 'ON' :
conversation.type === 'chat' || user_id === null ? 'OFF' : ''
conversation.session_type === 'rag' ? 'ON' :
conversation.session_type === 'chat' || user_id === null ? 'OFF' : ''
}</strong>`
return rag_info;
}
Expand All @@ -58,7 +73,7 @@ export default function createRAGSelector(conversation) {
} else {
option.classList.add('clickable')
option.onclick = () => {
updateRAG(mode, rag_select, conversation.id)
updateRAG(mode, rag_select, conversation.id, expand_setting)
};
}
option.innerHTML = `Start session with RAG <strong>${mode}</strong>`;
Expand Down
24 changes: 21 additions & 3 deletions components/chat-page/range-setting-section.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import getSVG from "../../tools/svgs.js";

export default function rangeSettingSection(title, valueRange, setToDefault, updateSetting) {
export default function rangeSettingSection(title, valueRange, setToDefault, updateSetting, initial_value = null) {

const { max, min, from_range, to_range } = rangeValueConverter(valueRange)

Expand All @@ -16,6 +16,7 @@ export default function rangeSettingSection(title, valueRange, setToDefault, upd

const range = document.createElement('input');
range.type = 'range';
if(valueRange.step) range.step = valueRange.step;
range.max = max;
range.min = min;

Expand All @@ -25,7 +26,6 @@ export default function rangeSettingSection(title, valueRange, setToDefault, upd
const restore_default_btn = document.createElement('div');
restore_default_btn.className = 'restore-default-icon clickable';
restore_default_btn.innerHTML = getSVG('arrow-counterclockwise');
restore_default_btn.onclick = setToDefault;

container.appendChild(range);
container.appendChild(text);
Expand Down Expand Up @@ -60,7 +60,25 @@ export default function rangeSettingSection(title, valueRange, setToDefault, upd
range.value = to_range(value);
}

return [setting_section, setter]
function toggleDisable(is_disabled) {
text.disabled = is_disabled;
range.disabled = is_disabled;
restore_default_btn.classList.toggle('disabled', is_disabled)
if(is_disabled) {
restore_default_btn.onclick = null;
} else {
restore_default_btn.onclick = setToDefault;
}
}
restore_default_btn.onclick = setToDefault;

if(initial_value !== null) setter(initial_value);

if(typeof setToDefault === 'number') {
setToDefault = () => setter(setToDefault);
}

return [setting_section, {setter, toggleDisable}]
}

function rangeValueConverter({ max, min, is_100_times }) {
Expand Down
Loading

0 comments on commit 29abf4a

Please sign in to comment.