mirror of
https://github.com/vegu-ai/talemate.git
synced 2025-09-04 11:29:10 +00:00
* flip title and name in recent scenes * fix issue where a message could not be regenerated after applying continuity error fixes * prompt tweaks * allow json parameters for commands * autocomplete improvements * dialogue cleanup fixes * fix issue with narrate after dialogue and llama3 (and other models that don't have a line break after the user prompt in their prompt template. * expose ability to auto generate dialogue instructions to wsm character ux * use b64_json response type * move tag checks up so they match first * fix typo * prompt tweak * api key support * prompt tweaks * editable parameters in prompt debugger / tester * allow reseting of prompt params * codemirror for prompt editor * prompt tweaks * more prompt debug tool tweaks * some extra control for `context_history` * new analytical preset (testing) * add `join` and `llm_can_be_coerced` to jinja env * support factual list summaries * prompt tweaks to continuity check and fix * new summarization method `facts` exposed to ux * clamp mistral ai temperature according to their new requirements * prompt tweaks * better parsing of fixed dialogue response * prompt tweaks * fix intermittent empty meta issue * history regen status progression and small ux tweaks * summary entries should always be condensed * google gemini support * relock to install google-cloud-aiplatform for vertex ai inference * fix instruction link * better error handling of google safety validation and allow disabling of safety validation * docs * clarify credentials path requirements * tweak error line identification * handle quota limit error * autocomplete ux wired to assistant plugin instead of command * autocomplete narrative editing and fixes to autocomplete during dialog edit * main input autocomplete tweaks * allow new lines in main input * 0.25.0 and relock * fix issue with autocomplete elsewhere locking out main input * better way to determine remote service * prompt tweak * fix rubberbanding issue when editing character attributes * add open mistral 8x22 * fix continuity error check summary inclusion of target entry * docs * default context length to 8192 * linting
275 lines
No EOL
9.4 KiB
Vue
275 lines
No EOL
9.4 KiB
Vue
<template>
|
|
<div v-if="isConnected()">
|
|
<v-list v-for="(client, index) in state.clients" :key="index">
|
|
<v-list-item>
|
|
|
|
<v-divider v-if="index !== 0" class="mb-3"></v-divider>
|
|
<v-list-item-title>
|
|
<v-progress-circular v-if="client.status === 'busy'" indeterminate="disable-shrink" color="primary"
|
|
size="14"></v-progress-circular>
|
|
|
|
<v-icon v-else-if="client.status == 'warning'" color="orange" size="14">mdi-checkbox-blank-circle</v-icon>
|
|
<v-icon v-else-if="client.status == 'error'" color="red-darken-1" size="14">mdi-checkbox-blank-circle</v-icon>
|
|
<v-icon v-else-if="client.status == 'disabled'" color="grey-darken-2" size="14">mdi-checkbox-blank-circle</v-icon>
|
|
<v-icon v-else color="green" size="14">mdi-checkbox-blank-circle</v-icon>
|
|
{{ client.name }}
|
|
</v-list-item-title>
|
|
<v-list-item-subtitle class="text-caption" v-if="client.data.error_action != null">
|
|
<v-btn class="mt-1 mb-1" variant="tonal" :prepend-icon="client.data.error_action.icon" size="x-small" color="warning" @click.stop="callErrorAction(client, client.data.error_action)">
|
|
{{ client.data.error_action.title }}
|
|
</v-btn>
|
|
</v-list-item-subtitle>
|
|
<v-list-item-subtitle class="text-caption">
|
|
{{ client.model_name }}
|
|
</v-list-item-subtitle>
|
|
<v-list-item-subtitle class="text-caption">
|
|
{{ client.type }}
|
|
<v-chip label size="x-small" variant="outlined" class="ml-1">ctx {{ client.max_token_length }}</v-chip>
|
|
</v-list-item-subtitle>
|
|
<div density="compact">
|
|
<v-slider
|
|
hide-details
|
|
v-model="client.max_token_length"
|
|
:min="1024"
|
|
:max="128000"
|
|
:step="1024"
|
|
@update:modelValue="saveClientDelayed(client)"
|
|
@click.stop
|
|
density="compact"
|
|
></v-slider>
|
|
</div>
|
|
<v-list-item-subtitle class="text-center">
|
|
|
|
<v-tooltip text="No LLM prompt template for this model. Using default. Templates can be added in ./templates/llm-prompt" v-if="client.status === 'idle' && client.data && !client.data.has_prompt_template && client.data.meta.requires_prompt_template" max-width="200">
|
|
<template v-slot:activator="{ props }">
|
|
<v-icon x-size="14" class="mr-1" v-bind="props" color="orange">mdi-alert</v-icon>
|
|
</template>
|
|
</v-tooltip>
|
|
|
|
<v-tooltip :text="'Coercion active: ' + client.double_coercion" v-if="client.double_coercion" max-width="200">
|
|
<template v-slot:activator="{ props }">
|
|
<v-icon x-size="14" class="mr-1" v-bind="props" color="primary">mdi-account-lock-open</v-icon>
|
|
</template>
|
|
</v-tooltip>
|
|
|
|
<v-tooltip text="Edit client">
|
|
<template v-slot:activator="{ props }">
|
|
<v-btn size="x-small" class="mr-1" v-bind="props" variant="tonal" density="comfortable" rounded="sm" @click.stop="editClient(index)" icon="mdi-cogs"></v-btn>
|
|
|
|
</template>
|
|
</v-tooltip>
|
|
<v-tooltip text="Assign to all agents">
|
|
<template v-slot:activator="{ props }">
|
|
<v-btn size="x-small" class="mr-1" v-bind="props" variant="tonal" density="comfortable" rounded="sm" @click.stop="assignClientToAllAgents(index)" icon="mdi-transit-connection-variant"></v-btn>
|
|
</template>
|
|
</v-tooltip>
|
|
|
|
<v-tooltip text="Delete client">
|
|
<template v-slot:activator="{ props }">
|
|
<v-btn size="x-small" class="mr-1" v-bind="props" variant="tonal" density="comfortable" rounded="sm" @click.stop="deleteClient(index)" icon="mdi-close-thick"></v-btn>
|
|
</template>
|
|
</v-tooltip>
|
|
|
|
</v-list-item-subtitle>
|
|
</v-list-item>
|
|
</v-list>
|
|
<ClientModal :dialog="state.dialog" :formTitle="state.formTitle" @save="saveClient" @error="propagateError" @update:dialog="updateDialog"></ClientModal>
|
|
<v-alert type="warning" variant="tonal" v-if="state.clients.length === 0">You have no LLM clients configured. Add one.</v-alert>
|
|
<v-btn @click="openModal" elevation="0" prepend-icon="mdi-plus-box">Add client</v-btn>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import ClientModal from './ClientModal.vue';
|
|
|
|
export default {
|
|
components: {
|
|
ClientModal,
|
|
},
|
|
data() {
|
|
return {
|
|
saveDelayTimeout: null,
|
|
clientStatusCheck: null,
|
|
clientDeleted: false,
|
|
state: {
|
|
clients: [],
|
|
dialog: false,
|
|
currentClient: {
|
|
name: '',
|
|
type: '',
|
|
api_url: '',
|
|
model_name: '',
|
|
max_token_length: 8192,
|
|
double_coercion: null,
|
|
data: {
|
|
has_prompt_template: false,
|
|
}
|
|
}, // Add a new field to store the model name
|
|
formTitle: ''
|
|
}
|
|
}
|
|
},
|
|
inject: [
|
|
'getWebsocket',
|
|
'registerMessageHandler',
|
|
'isConnected',
|
|
'getAgents',
|
|
],
|
|
provide() {
|
|
return {
|
|
state: this.state
|
|
};
|
|
},
|
|
emits: [
|
|
'clients-updated',
|
|
'client-assigned',
|
|
'open-app-config',
|
|
],
|
|
methods: {
|
|
|
|
callErrorAction(client, action) {
|
|
if(action.action_name === 'openAppConfig') {
|
|
this.$emit('open-app-config', ...action.arguments);
|
|
}
|
|
},
|
|
|
|
configurationRequired() {
|
|
if(this.state.clients.length === 0) {
|
|
return true;
|
|
}
|
|
|
|
// cycle through clients and check if any are status 'error' or 'warning'
|
|
for (let i = 0; i < this.state.clients.length; i++) {
|
|
if (this.state.clients[i].status === 'error' || this.state.clients[i].status === 'warning') {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
},
|
|
getActive() {
|
|
return this.state.clients.find(a => a.status === 'busy');
|
|
},
|
|
openModal() {
|
|
this.state.currentClient = {
|
|
name: 'TextGenWebUI',
|
|
type: 'textgenwebui',
|
|
api_url: 'http://localhost:5000',
|
|
model_name: '',
|
|
max_token_length: 8192,
|
|
data: {
|
|
has_prompt_template: false,
|
|
}
|
|
};
|
|
this.state.formTitle = 'Add Client';
|
|
this.state.dialog = true;
|
|
},
|
|
propagateError(error) {
|
|
this.$emit('error', error);
|
|
},
|
|
|
|
saveClientDelayed(client) {
|
|
client.dirty = true;
|
|
if (this.saveDelayTimeout) {
|
|
clearTimeout(this.saveDelayTimeout);
|
|
}
|
|
this.saveDelayTimeout = setTimeout(() => {
|
|
this.saveClient(client);
|
|
client.dirty = false;
|
|
}, 500);
|
|
},
|
|
|
|
saveClient(client) {
|
|
const index = this.state.clients.findIndex(c => c.name === client.name);
|
|
if (index === -1) {
|
|
this.state.clients.push(client);
|
|
} else {
|
|
this.state.clients[index] = client;
|
|
}
|
|
console.log("Saving client", client)
|
|
this.state.dialog = false; // Close the dialog after saving the client
|
|
this.$emit('clients-updated', this.state.clients);
|
|
},
|
|
editClient(index) {
|
|
this.state.currentClient = { ...this.state.clients[index] };
|
|
this.state.formTitle = 'Edit AI Client';
|
|
this.state.dialog = true;
|
|
},
|
|
deleteClient(index) {
|
|
if (window.confirm('Are you sure you want to delete this client?')) {
|
|
this.state.clients.splice(index, 1);
|
|
this.$emit('clients-updated', this.state.clients);
|
|
this.clientDeleted = true;
|
|
}
|
|
},
|
|
assignClientToAllAgents(index) {
|
|
let agents = this.getAgents();
|
|
let client = this.state.clients[index];
|
|
|
|
this.saveClient(client);
|
|
|
|
for (let i = 0; i < agents.length; i++) {
|
|
agents[i].client = client.name;
|
|
console.log("Assigning client", client.name, "to agent", agents[i].name);
|
|
}
|
|
this.$emit('client-assigned', agents);
|
|
},
|
|
updateDialog(newVal) {
|
|
this.state.dialog = newVal;
|
|
},
|
|
handleMessage(data) {
|
|
|
|
// Handle client_status message type
|
|
if (data.type === 'client_status') {
|
|
|
|
if(this.clientDeleted) {
|
|
|
|
// If we have just deleted a client, we need to wait for the next client_status message
|
|
|
|
this.clientDeleted = false;
|
|
return;
|
|
}
|
|
|
|
// Find the client with the given name
|
|
const client = this.state.clients.find(client => client.name === data.name);
|
|
|
|
if (client && !client.dirty) {
|
|
// Update the model name of the client
|
|
client.model_name = data.model_name;
|
|
client.model = client.model_name;
|
|
client.type = data.message;
|
|
client.status = data.status;
|
|
client.max_token_length = data.max_token_length;
|
|
client.api_url = data.api_url;
|
|
client.api_key = data.api_key;
|
|
client.double_coercion = data.data.double_coercion;
|
|
client.data = data.data;
|
|
} else if(!client) {
|
|
console.log("Adding new client", data);
|
|
|
|
this.state.clients.push({
|
|
name: data.name,
|
|
model_name: data.model_name,
|
|
model: data.model_name,
|
|
type: data.message,
|
|
status: data.status,
|
|
max_token_length: data.max_token_length,
|
|
api_url: data.api_url,
|
|
api_key: data.api_key,
|
|
double_coercion: data.data.double_coercion,
|
|
data: data.data,
|
|
});
|
|
// sort the clients by name
|
|
this.state.clients.sort((a, b) => (a.name > b.name) ? 1 : -1);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
}
|
|
},
|
|
created() {
|
|
this.registerMessageHandler(this.handleMessage);
|
|
},
|
|
}
|
|
</script> |