Add adjustable context size, custom chatbot name, and cat icon for AI chat
Settings > AI tab now includes context size slider (2048–131072) with VRAM estimate and a chatbot name field. ChatService reads both dynamically instead of hardcoding num_ctx=16384 and "Purrse AI". Chat panel FAB and empty state use mdi-cat icon to match the rest of the app. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -8,14 +8,14 @@
|
||||
elevation="8"
|
||||
@click="togglePanel"
|
||||
>
|
||||
<v-icon>{{ panelOpen ? 'mdi-close' : 'mdi-robot-outline' }}</v-icon>
|
||||
<v-icon>{{ panelOpen ? 'mdi-close' : 'mdi-cat' }}</v-icon>
|
||||
</v-btn>
|
||||
|
||||
<!-- Chat Panel -->
|
||||
<v-card v-show="panelOpen" class="chat-panel" elevation="12" rounded="lg">
|
||||
<!-- Header -->
|
||||
<v-toolbar density="compact" color="primary" class="flex-grow-0">
|
||||
<v-toolbar-title class="text-body-1 font-weight-medium">Purrse AI</v-toolbar-title>
|
||||
<v-toolbar-title class="text-body-1 font-weight-medium">{{ chatBotName }}</v-toolbar-title>
|
||||
<template v-slot:append>
|
||||
<v-menu>
|
||||
<template v-slot:activator="{ props }">
|
||||
@@ -56,7 +56,7 @@
|
||||
<div ref="messagesContainer" class="chat-messages">
|
||||
<!-- Empty state -->
|
||||
<div v-if="messages.length === 0 && !loading" class="d-flex flex-column align-center justify-center" style="height: 100%;">
|
||||
<v-icon size="48" color="primary" class="mb-3">mdi-robot-outline</v-icon>
|
||||
<v-icon size="48" color="primary" class="mb-3">mdi-cat</v-icon>
|
||||
<p class="text-body-2 text-medium-emphasis mb-4">Ask me about your finances</p>
|
||||
<div class="d-flex flex-wrap justify-center ga-2 px-4">
|
||||
<v-chip
|
||||
@@ -140,6 +140,7 @@
|
||||
import { ref, nextTick, onMounted, watch } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { chatApi } from '@/services/chat'
|
||||
import { aiCategorizationApi } from '@/services/aiCategorization'
|
||||
import { usePageContext } from '@/composables/usePageContext'
|
||||
import ChatToolResult from '@/views/chat/ChatToolResult.vue'
|
||||
import type { ChatConversation, ChatMessage } from '@/types'
|
||||
@@ -155,6 +156,7 @@ const inputMessage = ref('')
|
||||
const loading = ref(false)
|
||||
const messagesContainer = ref<HTMLElement | null>(null)
|
||||
const conversationsLoaded = ref(false)
|
||||
const chatBotName = ref('Purrse AI')
|
||||
|
||||
let _idCounter = 0
|
||||
function tempId(): string {
|
||||
@@ -214,6 +216,18 @@ function togglePanel() {
|
||||
panelOpen.value = !panelOpen.value
|
||||
if (panelOpen.value && !conversationsLoaded.value) {
|
||||
loadConversations()
|
||||
loadChatBotName()
|
||||
}
|
||||
}
|
||||
|
||||
async function loadChatBotName() {
|
||||
try {
|
||||
const { data } = await aiCategorizationApi.getSettings()
|
||||
if (data.chatBotName) {
|
||||
chatBotName.value = data.chatBotName
|
||||
}
|
||||
} catch {
|
||||
// Default name is fine
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -521,6 +521,8 @@ export interface AiCategorizationSettings {
|
||||
updatePayeeDefaults: boolean
|
||||
systemPrompt: string | null
|
||||
userPromptTemplate: string | null
|
||||
chatContextSize: number
|
||||
chatBotName: string | null
|
||||
}
|
||||
|
||||
export interface OllamaConnectionTestResult {
|
||||
|
||||
@@ -762,6 +762,37 @@
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
|
||||
<v-card class="mt-4">
|
||||
<v-card-title>AI Chat Settings</v-card-title>
|
||||
<v-card-text>
|
||||
<div class="text-body-2 mb-1">Context Size: {{ aiSettings.chatContextSize.toLocaleString() }} tokens</div>
|
||||
<v-slider
|
||||
v-model="aiSettings.chatContextSize"
|
||||
:min="2048"
|
||||
:max="131072"
|
||||
:step="2048"
|
||||
thumb-label
|
||||
color="primary"
|
||||
hide-details
|
||||
class="mb-1"
|
||||
/>
|
||||
<div class="text-caption text-medium-emphasis mb-4">
|
||||
Estimated VRAM: ~{{ Math.round((aiSettings.chatContextSize / 1024) * 75) }} MB — Increase if the AI loses context in long chats. Decrease if Ollama runs out of memory.
|
||||
</div>
|
||||
|
||||
<v-text-field
|
||||
v-model="aiSettings.chatBotName"
|
||||
label="Chatbot Name"
|
||||
variant="outlined"
|
||||
density="compact"
|
||||
placeholder="Purrse AI"
|
||||
hint="Custom name shown in the chat panel header and used by the AI"
|
||||
persistent-hint
|
||||
clearable
|
||||
/>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
|
||||
<v-snackbar v-model="showAiSuccess" :timeout="4000" color="success">
|
||||
AI categorization settings saved
|
||||
</v-snackbar>
|
||||
@@ -1305,7 +1336,9 @@ const aiSettings = reactive<AiCategorizationSettings>({
|
||||
timeoutSeconds: 30,
|
||||
updatePayeeDefaults: true,
|
||||
systemPrompt: null,
|
||||
userPromptTemplate: null
|
||||
userPromptTemplate: null,
|
||||
chatContextSize: 16384,
|
||||
chatBotName: null
|
||||
})
|
||||
const aiSaving = ref(false)
|
||||
const aiTesting = ref(false)
|
||||
|
||||
Reference in New Issue
Block a user