Added thinking presets

This commit is contained in:
Saifeddine ALOUI 2025-02-03 23:27:19 +01:00
parent 79dd5a1f9b
commit 892466e09f
9 changed files with 372 additions and 129 deletions

3
app.py
View File

@ -345,6 +345,8 @@ if __name__ == "__main__":
add_events as lollms_personality_events_add
from lollms.server.endpoints.lollms_function_calls import router as lollms_function_calls
from lollms.server.endpoints.lollms_thinking import router as lollms_thinking
from endpoints.chat_bar import router as chat_bar_router
from endpoints.lollms_advanced import router as lollms_advanced_router
@ -395,6 +397,7 @@ if __name__ == "__main__":
app.include_router(lollms_whisper)
app.include_router(lollms_function_calls)
app.include_router(lollms_thinking)
app.include_router(lollms_sd_router)
app.include_router(lollms_diffusers_router)

View File

@ -1,5 +1,5 @@
# =================== Lord Of Large Language Multimodal Systems Configuration file ===========================
version: 153
version: 154
# video viewing and news recovering
last_viewed_video: null
@ -338,6 +338,26 @@ negative_boost: null
current_language: english
fun_mode: false
think_first_mode: false
thinking_prompt: "Use a think first process to answer the user:
<thinking>
Ask yourself about the user's request and answer it with logical details.
If the user is requesting general information that does not require internet search and you are confident about it, then prepare to answer directly.
If the user is requesting general information that does require internet search and you have in the context enough information to answer, then use that data to answer.
If the user is requesting general information that does require internet search but you do not have any information, then ask him to activate internet search.
if the user is posing a riddle or asking a math question, make sure you use regourous math hypothisis, testing and analysis.
If the user is requesting to perform a task, then plan it through steps and prepare to answer
If the user is just discussing casually, do not perform the think first process
Make sure you continue thinking until you find a satisfactory answer
Assess any potential errors you may make
</thinking>
After thinking you can answer the user."
function_calls: []
# { name: the function name,
# value: the function name without spaces,
@ -349,5 +369,3 @@ function_calls: []
# webui configurations
show_code_of_conduct: true
activate_audio_infos: true

@ -1 +1 @@
Subproject commit df3b8eb78daf6e03fb879ae78279a46314a1c858
Subproject commit c9f0b552ddab1f5deae8c1e733ab14ff74d5e96f

File diff suppressed because one or more lines are too long

17
web/dist/assets/index-vEmjhqy9.css vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

4
web/dist/index.html vendored
View File

@ -6,8 +6,8 @@
<script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LoLLMS WebUI</title>
<script type="module" crossorigin src="/assets/index-DOAjMF0-.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-xuUsdK2A.css">
<script type="module" crossorigin src="/assets/index-Du9lXL9Z.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-vEmjhqy9.css">
</head>
<body>
<div id="app"></div>

View File

@ -69,14 +69,6 @@
<!-- Main Chat Input and Actions -->
<div class="flex flex-col gap-2">
<div class="flex flex-row gap-2 w-full">
<!-- Left Panel Toggle -->
<button
@click="toggleLeftPanel"
class="p-2 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-lg transition-colors"
:title="$store.state.leftPanelCollapsed ? 'Expand Left Panel' : 'Collapse Left Panel'"
>
<i :data-feather="$store.state.leftPanelCollapsed ? 'chevron-right' : 'chevron-left'" class="w-5 h-5"></i>
</button>
<!-- Input Box with Integrated Send Buttons -->
<div class="relative flex-grow">
@ -119,19 +111,29 @@
</template>
</div>
</div>
<!-- Right Panel Toggle -->
<button
@click="toggleRightPanel"
class="p-2 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-lg transition-colors"
:title="$store.state.rightPanelCollapsed ? 'Expand Right Panel' : 'Collapse Right Panel'"
>
<i :data-feather="$store.state.rightPanelCollapsed ? 'chevron-left' : 'chevron-right'" class="w-5 h-5"></i>
</button>
</div>
<!-- Additional Actions Row -->
<div class="flex items-center justify-between relative">
<!-- Left Panel Toggle -->
<button
@click="toggleLeftPanel"
class="p-2 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-lg transition-colors"
:class="$store.state.leftPanelCollapsed ? '' : 'bg-gray-700'"
:title="$store.state.leftPanelCollapsed ? 'Expand Left Panel' : 'Collapse Left Panel'"
>
<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<!-- Main vertical bar with rounded corners -->
<rect x="3" y="2" width="4" height="20" rx="2" fill="currentColor"/>
<!-- Three horizontal lines with rounded corners -->
<rect x="9" y="6" width="12" height="2" rx="1" fill="currentColor"/>
<rect x="9" y="11" width="12" height="2" rx="1" fill="currentColor"/>
<rect x="9" y="16" width="12" height="2" rx="1" fill="currentColor"/>
</svg>
</button>
<!-- Left Side: Personalities / Commands -->
<div class="flex items-center gap-2">
<PersonalitiesCommands
@ -286,6 +288,25 @@
<i data-feather="cpu" class="w-5 h-5"></i>
</button>
</div>
<!-- Right Panel Toggle -->
<button
@click="toggleRightPanel"
class="p-2 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-lg transition-colors"
:class="$store.state.rightPanelCollapsed ? '' : 'bg-gray-700'"
:title="$store.state.rightPanelCollapsed ? 'Expand Right Panel' : 'Collapse Right Panel'"
>
<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<!-- Main vertical bar with rounded corners (right side) -->
<rect x="17" y="2" width="4" height="20" rx="2" fill="currentColor"/>
<!-- Three horizontal lines with rounded corners -->
<rect x="3" y="6" width="12" height="2" rx="1" fill="currentColor"/>
<rect x="3" y="11" width="12" height="2" rx="1" fill="currentColor"/>
<rect x="3" y="16" width="12" height="2" rx="1" fill="currentColor"/>
</svg>
</button>
</div>
</div>
</div>

View File

@ -750,6 +750,103 @@
</div>
</div>
</Card>
<Card title="Thinking Methods" :is_subcard="true" class="pb-2 m-2">
<div class="grid gap-6 bg-white dark:bg-gray-800 p-6 rounded-lg shadow-md">
<!-- Thinking Prompt with Preset Button -->
<div class="space-y-2 flex flex-col">
<div class="flex justify-between items-center">
<label class="text-sm font-semibold text-gray-700 dark:text-gray-300">
Thinking Prompt
</label>
<div class="space-x-2">
<button
@click="showThinkingPresets = true"
class="px-3 py-1 text-sm bg-blue-500 text-white rounded-md hover:bg-blue-600 transition-colors"
>
Select Thinking Preset
</button>
<button
@click="showAddThinkingPreset = true"
class="px-3 py-1 text-sm bg-green-500 text-white rounded-md hover:bg-green-600 transition-colors"
>
Add New Preset
</button>
</div>
</div>
<textarea
@change="settingsChanged=true"
v-model="configFile.thinking_prompt"
class="p-4 bg-gray-100 dark:bg-gray-900 rounded-md text-sm min-h-[150px]"
placeholder="Enter thinking prompt or select a preset..."
></textarea>
</div>
<!-- Select Thinking Preset Modal -->
<Modal v-if="showThinkingPresets" @close="showThinkingPresets = false">
<div class="p-4">
<h3 class="text-lg font-semibold mb-4">Select Thinking Preset</h3>
<div class="space-y-2">
<div v-for="preset in thinkingPresets"
:key="preset.name"
class="border rounded-md p-4 hover:bg-gray-50 dark:hover:bg-gray-700 cursor-pointer"
@click="selectPreset(preset)"
>
<div class="font-medium">{{ preset.name }}</div>
<div class="text-sm text-gray-600 dark:text-gray-400">{{ preset.description }}</div>
<div class="text-xs text-gray-500 mt-1">Author: {{ preset.author }}</div>
</div>
</div>
</div>
</Modal>
<!-- Add New Thinking Preset Modal -->
<Modal v-if="showAddThinkingPreset" @close="showAddThinkingPreset = false">
<div class="p-4">
<h3 class="text-lg font-semibold mb-4">Add New Thinking Preset</h3>
<form @submit.prevent="saveNewPreset" class="space-y-4">
<div>
<label class="block text-sm font-medium mb-1">Name</label>
<input v-model="newPreset.name" class="w-full rounded-md border p-2" required>
</div>
<div>
<label class="block text-sm font-medium mb-1">Description</label>
<input v-model="newPreset.description" class="w-full rounded-md border p-2" required>
</div>
<div>
<label class="block text-sm font-medium mb-1">Author</label>
<input v-model="newPreset.author" class="w-full rounded-md border p-2" required>
</div>
<div>
<label class="block text-sm font-medium mb-1">Thinking Prompt</label>
<textarea
v-model="newPreset.prompt"
class="w-full rounded-md border p-2 min-h-[150px]"
required
></textarea>
</div>
<div class="flex justify-end space-x-2">
<button
type="button"
@click="showAddPreset = false"
class="px-4 py-2 text-sm text-gray-600 border rounded-md"
>
Cancel
</button>
<button
type="submit"
class="px-4 py-2 text-sm bg-blue-500 text-white rounded-md"
>
Save Preset
</button>
</div>
</form>
</div>
</Modal>
</div>
</Card>
<Card title="User" :is_subcard="true" class="pb-2 m-2">
<div class="grid gap-6 bg-gray-50 dark:bg-gray-700 p-6 rounded-lg shadow-md">
@ -4645,6 +4742,17 @@ export default {
'accept': 'application/json',
'Content-Type': 'application/json'
},
showThinkingPresets: false,
showAddThinkingPreset: false,
thinkingPresets: [],
newPreset: {
name: '',
description: '',
author: '',
prompt: ''
},
selectedMethodDescription: '',
selectedMethodAuthor: '',
isChecking: false,
serverStatuses: [], // Object to store status for each server
expandedStatusIndex: null, // Track which status panel is expanded
@ -4811,7 +4919,35 @@ export default {
this.$store.state.toast.showToast('Could not connect to LightRAG server', 4, false);
}
},
async loadthinkingPresets() {
try {
console.log("loadthinkingPresets")
const response = await axios.post('/get_thinking_methods', {
client_id: this.$store.state.client_id
});
console.log("loadthinkingPresets --- ")
console.log(response)
if (response.data.status === 'success') {
this.thinkingPresets = response.data.thinking_methods;
// Load local presets and merge
this.loadLocalPresets();
// Set initial selection if available
if (this.allThinkingPresets.length > 0) {
this.updateSelectedMethodInfo(this.configFile.selected_thinking_method || this.allThinkingPresets[0].name);
}
}
} catch (error) {
console.error('Error loading thinking methods:', error);
this.$toast.error('Failed to load thinking methods');
// Still load local presets even if backend fails
this.loadLocalPresets();
}
},
handlethinkingPresetselection() {
this.updateSelectedMethodInfo(this.configFile.selected_thinking_method);
this.settingsChanged = true;
},
// Optional: Method to check all servers at once
async checkAllServers() {
for (let i = 0; i < this.configFile.datalakes.length; i++) {
@ -7159,11 +7295,74 @@ export default {
},
searchModel_func() {
this.filterModels()
},
loadLocalPresets() {
const savedPresets = localStorage.getItem('localThinkingPresets');
if (savedPresets) {
this.localThinkingPresets = JSON.parse(savedPresets);
}
},
saveLocalPresets() {
localStorage.setItem('localThinkingPresets', JSON.stringify(this.localThinkingPresets));
},
selectPreset(preset) {
this.configFile.thinking_prompt = preset.prompt;
this.configFile.selected_thinking_method = preset.name;
this.showThinkingPresets = false;
this.settingsChanged = true;
this.updateSelectedMethodInfo(preset.name);
},
saveNewPreset() {
// Ensure prompt has thinking tags
let promptToSave = this.newPreset.prompt;
if (!promptToSave.includes('<thinking>')) {
promptToSave = `<thinking>\n${promptToSave}\n</thinking>`;
}
const newPreset = {
name: this.newPreset.name,
description: this.newPreset.description,
author: this.newPreset.author,
prompt: promptToSave,
isLocal: true // Flag to identify user-created presets
};
// Check for name conflicts
const existingPreset = this.allThinkingPresets.find(p => p.name === newPreset.name);
if (existingPreset) {
this.$toast.error('A preset with this name already exists');
return;
}
this.localThinkingPresets.push(newPreset);
this.saveLocalPresets();
// Reset form
this.newPreset = {
name: '',
description: '',
author: '',
prompt: ''
};
this.showAddThinkingPreset = false;
this.$toast.success('New thinking preset added successfully');
},
updateSelectedMethodInfo(methodName) {
const method = this.allThinkingPresets.find(m => m.name === methodName);
if (method) {
this.configFile.selected_thinking_method = method.name;
this.configFile.thinking_prompt = method.prompt;
}
}
},
async mounted() {
this.loadthinkingPresets();
console.log("Getting voices")
this.getVoices();
console.log("Constructing")