mirror of
https://github.com/vegu-ai/talemate.git
synced 2025-12-28 16:06:38 +01:00
Prep 0.19.0 (#67)
* linting * improve prompt devtools: test changes, show more information * some more polish for the new promp devtools * up default conversation gen length to 128 * openai client tweaks, talemate sets max_tokens on gpt-3.5 generations * support new openai embeddings (and default to text-embedding-3-small) * ux polish for character sheet and character state ux * actor instructions * experiment using # for context / instructions * fix bug where regenerating history would mess up time stamps * remove trailing ] * prevent client ctx from being unset * fix issue where sometimes you'd need to delete a client twice for it to disappear * upgrade dependencies * set 0.19.0 * fix performance degradation caused by circular loading animation * remove coqui studio support * fix issue when switching from unsaved creative mode to loading a scene * third party client / agent support * edit dialogue examples through character / actor editor * remove "edit dialogue" action from editor - replaced by character actor instructions * different icon for delete * prompt adjustment for acting instructions * adhoc context generation for character attributes and details * add adhoc generation for character description * contextual generation tweaks * contextual generation for dialogue examples fix some formatting issues * contextual generation for world entries * prepopulate initial recen scenarios with demo scenes add experimental holodeck scenario * scene info scene experimental * assortment of fixes for holodeck improvements * more holodeck fixes * refactor holodeck instructions * rename holodeck to simulation suite * better scene status messages * add new gpt-3.5-turbo model, better json response coercion for older models * allow exclusion of characters when persisting based on world state * better error handling of world state response * better error handling of world state response * more simulation suite fixes * progress color * world state character name mapping support * if neither quote nor asterisk is in message default to quotes * fix rerun of new paraphrase op * sim suite ping that ensure's characters are not aware of sim * fixes for better character name assessment simulation suite can now give the player character a proper name * fix bug with new status notifications * sim suite adjustments and fixes and tuning * sim suite tweaks * impl scene restore from file * prompting tweaks for reinforcement messages and acting instructions * more tweaks * dialogue prompt tweaks for rerun + rewrite * fix bug with character entry / exit with narration * linting * simsuite screenshots * screenshots
This commit is contained in:
4
talemate_frontend/package-lock.json
generated
4
talemate_frontend/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "talemate_frontend",
|
||||
"version": "0.1.0",
|
||||
"version": "0.19.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "talemate_frontend",
|
||||
"version": "0.1.0",
|
||||
"version": "0.19.0",
|
||||
"dependencies": {
|
||||
"@mdi/font": "7.4.47",
|
||||
"core-js": "^3.8.3",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "talemate_frontend",
|
||||
"version": "0.1.0",
|
||||
"version": "0.19.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
<v-list v-for="(agent, index) in state.agents" :key="index">
|
||||
<v-list-item @click="editAgent(index)">
|
||||
<v-list-item-title>
|
||||
<v-progress-circular v-if="agent.status === 'busy'" indeterminate color="primary"
|
||||
<v-progress-circular v-if="agent.status === 'busy'" indeterminate="disable-shrink" color="primary"
|
||||
size="14"></v-progress-circular>
|
||||
<v-icon v-else-if="agent.status === 'uninitialized'" color="orange" size="14">mdi-checkbox-blank-circle</v-icon>
|
||||
<v-icon v-else-if="agent.status === 'disabled'" color="grey-darken-2" size="14">mdi-checkbox-blank-circle</v-icon>
|
||||
<v-icon v-else-if="agent.status === 'error'" color="red" size="14">mdi-checkbox-blank-circle</v-icon>
|
||||
<v-icon v-else-if="agent.status === 'error'" color="red-darken-1" size="14">mdi-checkbox-blank-circle</v-icon>
|
||||
<v-icon v-else color="green" size="14">mdi-checkbox-blank-circle</v-icon>
|
||||
|
||||
<span class="ml-1" v-if="agent.label"> {{ agent.label }}</span>
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
|
||||
<v-divider v-if="index !== 0" class="mb-3"></v-divider>
|
||||
<v-list-item-title>
|
||||
<v-progress-circular v-if="client.status === 'busy'" indeterminate color="primary"
|
||||
<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" 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 }}
|
||||
@@ -84,6 +84,7 @@ export default {
|
||||
return {
|
||||
saveDelayTimeout: null,
|
||||
clientStatusCheck: null,
|
||||
clientDeleted: false,
|
||||
state: {
|
||||
clients: [],
|
||||
dialog: false,
|
||||
@@ -191,6 +192,7 @@ export default {
|
||||
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) {
|
||||
@@ -212,6 +214,15 @@ export default {
|
||||
|
||||
// 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);
|
||||
|
||||
|
||||
@@ -199,7 +199,7 @@
|
||||
<v-col cols="12">
|
||||
<v-list density="compact">
|
||||
<v-list-item v-for="(value, index) in app_config.creator.content_context" :key="index">
|
||||
<v-list-item-title><v-icon color="red" class="mr-2" @click="contentContextRemove(index)">mdi-delete</v-icon>{{ value }}</v-list-item-title>
|
||||
<v-list-item-title><v-icon color="red-darken-1" class="mr-2" @click="contentContextRemove(index)">mdi-close-box-outline</v-icon>{{ value }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
<v-divider></v-divider>
|
||||
@@ -226,7 +226,7 @@
|
||||
<span class="headline">Configuration</span>
|
||||
</v-card-title>
|
||||
<v-card-text>
|
||||
<v-progress-circular indeterminate color="primary" size="20"></v-progress-circular>
|
||||
<v-progress-circular indeterminate="disable-shrink" color="primary" size="20"></v-progress-circular>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-progress-circular class="ml-1 mr-3" size="24" v-if="generating" indeterminate color="primary"></v-progress-circular>
|
||||
<v-progress-circular class="ml-1 mr-3" size="24" v-if="generating" indeterminate="disable-shrink" color="primary"></v-progress-circular>
|
||||
<v-btn color="primary" @click="submitStep(2)" :disabled="generating" prepend-icon="mdi-memory">Generate</v-btn>
|
||||
<v-btn color="primary" @click="resetStep(2)" :disabled="generating" prepend-icon="mdi-restart">Reset</v-btn>
|
||||
</v-card-actions>
|
||||
@@ -88,7 +88,7 @@
|
||||
<v-textarea rows="10" auto-grow v-model="description"></v-textarea>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-progress-circular class="ml-1 mr-3" size="24" v-if="generating" indeterminate
|
||||
<v-progress-circular class="ml-1 mr-3" size="24" v-if="generating" indeterminate="disable-shrink"
|
||||
color="primary"></v-progress-circular>
|
||||
<v-btn color="primary" @click="submitStep(3)" :disabled="generating" prepend-icon="mdi-memory">Generate</v-btn>
|
||||
</v-card-actions>
|
||||
@@ -105,7 +105,7 @@
|
||||
<v-list>
|
||||
<v-list-item v-for="(question, index) in detail_questions" :key="index">
|
||||
<div>
|
||||
<v-icon color="red" @click="detail_questions.splice(index, 1)">mdi-delete</v-icon>
|
||||
<v-icon color="red-darken-1" @click="detail_questions.splice(index, 1)">mdi-close-box-outline</v-icon>
|
||||
{{ question }}
|
||||
</div>
|
||||
</v-list-item>
|
||||
@@ -121,7 +121,7 @@
|
||||
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-progress-circular class="ml-1 mr-3" size="24" v-if="generating" indeterminate
|
||||
<v-progress-circular class="ml-1 mr-3" size="24" v-if="generating" indeterminate="disable-shrink"
|
||||
color="primary"></v-progress-circular>
|
||||
<v-btn color="primary" @click="submitStep(4)" :disabled="generating" prepend-icon="mdi-memory">Generate</v-btn>
|
||||
</v-card-actions>
|
||||
@@ -136,7 +136,7 @@
|
||||
<v-list>
|
||||
<v-list-item v-for="(example, index) in dialogue_examples" :key="index">
|
||||
<div>
|
||||
<v-icon color="red" @click="dialogue_examples.splice(index, 1)">mdi-delete</v-icon>
|
||||
<v-icon color="red-darken-1" @click="dialogue_examples.splice(index, 1)">mdi-close-box-outline</v-icon>
|
||||
{{ example }}
|
||||
</div>
|
||||
</v-list-item>
|
||||
@@ -144,7 +144,7 @@
|
||||
</v-list>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-progress-circular class="ml-1 mr-3" size="24" v-if="generating" indeterminate color="primary"></v-progress-circular>
|
||||
<v-progress-circular class="ml-1 mr-3" size="24" v-if="generating" indeterminate="disable-shrink" color="primary"></v-progress-circular>
|
||||
<v-btn color="primary" @click="submitStep(5)" :disabled="generating" prepend-icon="mdi-memory">Generate</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
@@ -158,7 +158,7 @@
|
||||
</v-alert>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-progress-circular class="ml-1 mr-3" size="24" v-if="generating" indeterminate color="primary"></v-progress-circular>
|
||||
<v-progress-circular class="ml-1 mr-3" size="24" v-if="generating" indeterminate="disable-shrink" color="primary"></v-progress-circular>
|
||||
<v-btn color="primary" @click="submitStep(6)" :disabled="generating">Add to world</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
@@ -169,7 +169,7 @@
|
||||
</v-window>
|
||||
</v-dialog>
|
||||
|
||||
<v-snackbar v-model="notification" color="red" :timeout="3000">
|
||||
<v-snackbar v-model="notification" color="red-darken-1" :timeout="3000">
|
||||
{{ notification_text }}
|
||||
</v-snackbar>
|
||||
</template>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn color="secondary" text @click="dialog = false" :disabled="importing">Close</v-btn>
|
||||
<v-btn color="primary" text @click="importCharacter" :disabled="importing || !selectedCharacter">Import</v-btn>
|
||||
<v-progress-circular v-if="importing" indeterminate color="primary" size="20"></v-progress-circular>
|
||||
<v-progress-circular v-if="importing" indeterminate="disable-shrink" color="primary" size="20"></v-progress-circular>
|
||||
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<v-card>
|
||||
<v-tabs v-model="tab">
|
||||
<v-tab value="overview">Overview</v-tab>
|
||||
<v-tab value="details">Details</v-tab>
|
||||
<v-tab value="details">Attributes</v-tab>
|
||||
</v-tabs>
|
||||
<v-window v-model="tab">
|
||||
<v-window-item value="overview">
|
||||
@@ -27,16 +27,14 @@
|
||||
</div>
|
||||
</v-col>
|
||||
<v-col cols="8">
|
||||
<v-row>
|
||||
<v-col cols="12">
|
||||
<span class="text-h5">{{ name }}</span>
|
||||
</v-col>
|
||||
<v-col cols="12">
|
||||
<p>
|
||||
<v-card color="grey-darken-3">
|
||||
<v-card-title>{{ name }}</v-card-title>
|
||||
<v-card-text>
|
||||
<p class="pre-wrap">
|
||||
{{ description }}
|
||||
</p>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card-text>
|
||||
@@ -168,5 +166,11 @@ export default {
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
<style scoped>
|
||||
|
||||
.pre-wrap {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
</style>
|
||||
```
|
||||
156
talemate_frontend/src/components/ContextualGenerate.vue
Normal file
156
talemate_frontend/src/components/ContextualGenerate.vue
Normal file
@@ -0,0 +1,156 @@
|
||||
<template>
|
||||
<v-dialog v-model="dialog" max-width="750" :persistent="busy">
|
||||
<v-card>
|
||||
<v-card-title>
|
||||
Generate Context
|
||||
<span v-if="busy">
|
||||
<v-progress-circular class="ml-1 mr-3" size="14" indeterminate="disable-shrink" color="primary">
|
||||
</v-progress-circular>
|
||||
<span class="text-caption text-primary">Generating...</span>
|
||||
</span>
|
||||
</v-card-title>
|
||||
<v-card-text>
|
||||
|
||||
<v-alert density="compact" v-if="character" icon="mdi-account" variant="text" color="grey">
|
||||
{{ character }}
|
||||
</v-alert>
|
||||
|
||||
<v-alert density="compact" icon="mdi-text-box" variant="text" color="grey">
|
||||
{{ context }}
|
||||
</v-alert>
|
||||
|
||||
<v-alert dense icon="mdi-pencil" variant="text" color="grey" v-if="original && withOriginal">
|
||||
<div class="original-overflow">
|
||||
<span class="text-grey-lighten-2">[Rewriting]</span> {{ original }}
|
||||
|
||||
</div>
|
||||
</v-alert>
|
||||
|
||||
<v-textarea class="mt-1" v-model="instructions" rows="2" label="Instructions"
|
||||
hint="Additional instructions for the AI on how to generate the requested content" v-if="withInstructions" :disabled="busy"></v-textarea>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn v-if="withInstructions" color="primary" variant="text" prepend-icon="mdi-auto-fix" @click="generate" :disabled="busy">Generate</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
|
||||
<v-sheet class="text-right">
|
||||
<v-spacer></v-spacer>
|
||||
<v-tooltip class="pre-wrap" :text="tooltipText" >
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-btn v-bind="props" color="primary" @click.stop="open" variant="text" size="x-small" prepend-icon="mdi-auto-fix">Generate</v-btn>
|
||||
</template>
|
||||
</v-tooltip>
|
||||
</v-sheet>
|
||||
</template>
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: 'ContextualGenerate',
|
||||
props: {
|
||||
context: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
original: {
|
||||
type: String,
|
||||
required: false
|
||||
},
|
||||
character: {
|
||||
type: String,
|
||||
required: false
|
||||
},
|
||||
length: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: 255
|
||||
},
|
||||
rewriteEnabled: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dialog: false,
|
||||
instructions: "",
|
||||
withInstructions: false,
|
||||
withOriginal: false,
|
||||
busy: false,
|
||||
}
|
||||
},
|
||||
emits: ["generate"],
|
||||
inject: ["getWebsocket", "registerMessageHandler"],
|
||||
computed: {
|
||||
tooltipText() {
|
||||
if(this.rewriteEnabled)
|
||||
return "Generate "+this.context+"\n[+ctrl to provide instructions]\n[+alt to rewrite existing content]";
|
||||
else
|
||||
return "Generate "+this.context+"\n[+ctrl to provide instructions]";
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
|
||||
open(event) {
|
||||
this.dialog = true;
|
||||
this.busy = false;
|
||||
|
||||
// if ctrl key is pressed, open with instructions
|
||||
this.withInstructions = event.ctrlKey;
|
||||
|
||||
// if alt key is pressed, open with original
|
||||
this.withOriginal = event.altKey && this.rewriteEnabled;
|
||||
|
||||
if (!this.withInstructions) {
|
||||
|
||||
this.generate();
|
||||
}
|
||||
},
|
||||
|
||||
generate() {
|
||||
this.busy = true;
|
||||
this.getWebsocket().send(JSON.stringify({
|
||||
type: "assistant",
|
||||
action: "contextual_generate",
|
||||
context: this.context,
|
||||
character: this.character,
|
||||
length: this.length,
|
||||
instructions: this.withInstructions ? this.instructions : "",
|
||||
original: this.withOriginal ? this.original : null,
|
||||
}));
|
||||
},
|
||||
|
||||
handleMessage(message) {
|
||||
if (message.type === "assistant" && message.action === "contextual_generate_done") {
|
||||
|
||||
// slot will be some input element with a v-model attribute
|
||||
// update the slot with the generated text
|
||||
|
||||
this.dialog = false;
|
||||
console.log("GENERATED", message)
|
||||
this.$emit("generate", message.data.generated_content);
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
created() {
|
||||
this.registerMessageHandler(this.handleMessage);
|
||||
// hook click event on child v-textarea
|
||||
},
|
||||
}
|
||||
|
||||
</script>
|
||||
<style scoped>
|
||||
.pre-wrap {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.original-overflow {
|
||||
max-height: 200px;
|
||||
overflow: auto;
|
||||
}
|
||||
</style>
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
<v-tooltip text="Permanently Delete">
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-btn size="x-small" class="mr-1" v-bind="props" variant="tonal" density="comfortable" rounded="sm" color="red" icon="mdi-account-cancel" @click.stop="removeCharacterFromScene(character.name)"></v-btn>
|
||||
<v-btn size="x-small" class="mr-1" v-bind="props" variant="tonal" density="comfortable" rounded="sm" color="red-darken-1" icon="mdi-account-cancel" @click.stop="removeCharacterFromScene(character.name)"></v-btn>
|
||||
|
||||
</template>
|
||||
</v-tooltip>
|
||||
@@ -53,7 +53,7 @@
|
||||
|
||||
<v-tooltip text="Permanently Delete">
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-btn size="x-small" class="mr-1" v-bind="props" variant="tonal" density="comfortable" rounded="sm" color="red" icon="mdi-account-cancel" @click.stop="removeCharacterFromScene(character_name)"></v-btn>
|
||||
<v-btn size="x-small" class="mr-1" v-bind="props" variant="tonal" density="comfortable" rounded="sm" color="red-darken-1" icon="mdi-account-cancel" @click.stop="removeCharacterFromScene(character_name)"></v-btn>
|
||||
|
||||
</template>
|
||||
</v-tooltip>
|
||||
|
||||
@@ -13,16 +13,20 @@
|
||||
|
||||
<v-row>
|
||||
<v-col cols="2" class="text-info">#{{ prompt.num }}</v-col>
|
||||
<v-col cols="10" class="text-right">{{ prompt.kind }}</v-col>
|
||||
<v-col cols="10" class="text-right">
|
||||
|
||||
<v-chip size="x-small" class="mr-1" color="primary" variant="text" label>{{ prompt.prompt_tokens }}<v-icon size="14"
|
||||
class="ml-1">mdi-arrow-down-bold</v-icon></v-chip>
|
||||
<v-chip size="x-small" class="mr-1" color="secondary" variant="text" label>{{ prompt.response_tokens }}<v-icon size="14"
|
||||
class="ml-1">mdi-arrow-up-bold</v-icon></v-chip>
|
||||
<v-chip size="x-small" variant="text" label color="grey-darken-1">{{ prompt.time }}s<v-icon size="14" class="ml-1">mdi-clock</v-icon></v-chip>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
</v-list-item-title>
|
||||
<v-list-item-subtitle>
|
||||
<v-chip size="x-small" class="mr-1" color="primary">{{ prompt.prompt_tokens }}<v-icon size="14"
|
||||
class="ml-1">mdi-arrow-down-bold</v-icon></v-chip>
|
||||
<v-chip size="x-small" class="mr-1" color="secondary">{{ prompt.response_tokens }}<v-icon size="14"
|
||||
class="ml-1">mdi-arrow-up-bold</v-icon></v-chip>
|
||||
<v-chip size="x-small">{{ prompt.time }}s<v-icon size="14" class="ml-1">mdi-clock</v-icon></v-chip>
|
||||
<v-list-item-subtitle class="text-caption">
|
||||
<v-chip size="x-small" color="grey-lightne-1" variant="text">{{ prompt.agent_name }}</v-chip>
|
||||
<v-chip size="x-small" color="grey" variant="text">{{ prompt.agent_action }}</v-chip>
|
||||
</v-list-item-subtitle>
|
||||
<v-divider class="mt-1"></v-divider>
|
||||
</v-list-item>
|
||||
@@ -66,14 +70,35 @@ export default {
|
||||
|
||||
if(data.type === "prompt_sent") {
|
||||
// add to prompts array, and truncate if necessary (max 50)
|
||||
|
||||
// get active agent (last in agent_stack if agent_stack is not empty)
|
||||
let agent = null;
|
||||
let agentName = null;
|
||||
let agentAction = null;
|
||||
|
||||
if(data.data.agent_stack.length > 0) {
|
||||
agent = data.data.agent_stack[data.data.agent_stack.length - 1];
|
||||
// split by . to get agent name and action
|
||||
let agentParts = agent.split('.');
|
||||
agentName = agentParts[0];
|
||||
agentAction = agentParts[1];
|
||||
}
|
||||
|
||||
this.prompts.unshift({
|
||||
prompt: data.data.prompt,
|
||||
response: data.data.response,
|
||||
kind: data.data.kind,
|
||||
response_tokens: data.data.response_tokens,
|
||||
prompt_tokens: data.data.prompt_tokens,
|
||||
agent_stack: data.data.agent_stack,
|
||||
agent: agent,
|
||||
agent_name: agentName,
|
||||
agent_action: agentAction,
|
||||
client_name: data.data.client_name,
|
||||
client_type: data.data.client_type,
|
||||
time: parseInt(data.data.time),
|
||||
num: this.total++,
|
||||
generation_parameters: data.data.generation_parameters,
|
||||
})
|
||||
|
||||
while(this.prompts.length > this.max_prompts) {
|
||||
@@ -83,7 +108,7 @@ export default {
|
||||
},
|
||||
|
||||
openPromptView(prompt) {
|
||||
this.$refs.promptView.open(prompt);
|
||||
this.$refs.promptView.open(prompt, this.prompts);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -1,28 +1,75 @@
|
||||
<template>
|
||||
<v-dialog v-model="dialog" max-width="90%">
|
||||
<v-dialog v-model="dialog" max-width="1400px">
|
||||
|
||||
<v-card>
|
||||
<v-card-title>
|
||||
#{{ prompt.num }} - {{ prompt.kind }}
|
||||
#{{ prompt.num }}
|
||||
<v-chip color="grey-lightne-1" variant="text">{{ prompt.agent_name }}</v-chip>
|
||||
<v-chip color="grey" variant="text">{{ prompt.agent_action }}</v-chip>
|
||||
<v-divider vertical></v-divider>
|
||||
<v-chip color="grey" variant="text">{{ prompt.kind }}</v-chip>
|
||||
<v-chip size="small" color="primary" variant="text" label>{{ prompt.prompt_tokens }}<v-icon size="14"
|
||||
class="ml-1">mdi-arrow-down-bold</v-icon></v-chip>
|
||||
<v-chip size="small" color="secondary" variant="text" label>{{ prompt.response_tokens }}<v-icon size="14"
|
||||
class="ml-1">mdi-arrow-up-bold</v-icon></v-chip>
|
||||
<v-chip size="small" variant="text" label color="grey-darken-1">{{ prompt.time }}s<v-icon size="14" class="ml-1">mdi-clock</v-icon></v-chip>
|
||||
<v-chip color="grey" variant="text" prepend-icon="mdi-network-outline">{{ prompt.client_name }}</v-chip>
|
||||
<v-chip color="primary" @click.stop="toggleDetails" variant="text" prepend-icon="mdi-list-box">{{ toggleDetailsLabel() }} ({{ prompt.agent_stack.length }})</v-chip>
|
||||
</v-card-title>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="6">
|
||||
<v-card flat>
|
||||
<v-card-title>Prompt</v-card-title>
|
||||
<v-card-text style="max-height:600px; overflow-y:scroll;">
|
||||
<div class="prompt-view">{{ prompt.prompt }}</div>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
<v-col cols="6">
|
||||
<v-card flat>
|
||||
<v-card-title>Response</v-card-title>
|
||||
<v-card-text style="max-height:600px; overflow-y:scroll;">
|
||||
<div class="prompt-view">{{ prompt.response }}</div>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-card-text>
|
||||
<v-row>
|
||||
<v-col :cols="details ? 2 : 0" v-if="details">
|
||||
<v-list density="compact">
|
||||
<v-list-subheader><v-icon>mdi-transit-connection-variant</v-icon> Agent Stack</v-list-subheader>
|
||||
<v-list-item v-for="(agent, index) in prompt.agent_stack" :key="index">
|
||||
<v-list-item-subtitle class="text-grey-lighten-3">{{ agentParts(agent).name }}</v-list-item-subtitle>
|
||||
<v-list-item-subtitle class="text-grey-lighten-1 text-caption">{{ agentParts(agent).action }}</v-list-item-subtitle>
|
||||
</v-list-item>
|
||||
<v-list-subheader>
|
||||
<v-icon>mdi-details</v-icon>Parameters
|
||||
</v-list-subheader>
|
||||
<v-list-item v-for="(value, name) in filteredParameters" :key="name">
|
||||
<v-list-item-subtitle color="grey-lighten-1">{{ name }}</v-list-item-subtitle>
|
||||
<p class="text-caption text-grey">
|
||||
{{ value }}
|
||||
</p>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-col>
|
||||
<v-col :cols="details ? 5 : 6">
|
||||
<v-card flat>
|
||||
<v-card-title>Prompt</v-card-title>
|
||||
<v-card-text>
|
||||
<!--
|
||||
<div class="prompt-view">{{ prompt.prompt }}</div>
|
||||
-->
|
||||
<v-textarea :disabled="busy" density="compact" v-model="prompt.prompt" rows="10" auto-grow max-rows="22"></v-textarea>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
<v-col :cols="details ? 5 : 6">
|
||||
<v-card elevation="10" color="grey-darken-3">
|
||||
<v-card-title>Response
|
||||
<v-progress-circular class="ml-1 mr-3" size="20" v-if="busy" indeterminate="disable-shrink"
|
||||
color="primary"></v-progress-circular>
|
||||
</v-card-title>
|
||||
<v-card-text style="max-height:600px; overflow-y:auto;" :class="busy ? 'text-grey' : 'text-white'">
|
||||
<div class="prompt-view">{{ prompt.response }}</div>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-btn :disabled="busy || !hasPreviousPrompt()" color="primary" @click.stop="loadPreviousPrompt" prepend-icon="mdi-page-previous-outline">Previous Prompt</v-btn>
|
||||
<v-spacer></v-spacer>
|
||||
<v-tooltip text="Regenerate the response, taking your changes into account. This will not push the response to the scene, but is only used for testing how changes to the prompt would affect the generation." max-width="400px">
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-btn :disabled="busy" color="orange" @click.stop="testChanges" v-bind="props" prepend-icon="mdi-atom-variant">Test Changes</v-btn>
|
||||
</template>
|
||||
</v-tooltip>
|
||||
<v-btn :disabled="busy || !hasNextPrompt()" color="primary" @click.stop="loadNextPrompt" prepend-icon="mdi-page-next-outline">Next Prompt</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</template>
|
||||
@@ -34,17 +81,110 @@ export default {
|
||||
return {
|
||||
prompt: null,
|
||||
dialog: false,
|
||||
details: false,
|
||||
busy: false,
|
||||
index: null,
|
||||
prompts: [],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
filteredParameters() {
|
||||
// generation_parameters
|
||||
// remove `prompt`
|
||||
|
||||
let filtered = {};
|
||||
|
||||
for(let key in this.prompt.generation_parameters) {
|
||||
if(key != 'prompt' && key != 'stream' && key != 'max_new_tokens') {
|
||||
filtered[key] = this.prompt.generation_parameters[key];
|
||||
}
|
||||
}
|
||||
|
||||
return filtered;
|
||||
},
|
||||
},
|
||||
inject: [
|
||||
"getWebsocket",
|
||||
'registerMessageHandler',
|
||||
],
|
||||
methods: {
|
||||
open(prompt) {
|
||||
|
||||
toggleDetailsLabel() {
|
||||
return this.details ? 'Hide Details' : 'Show Details';
|
||||
},
|
||||
|
||||
toggleDetails() {
|
||||
this.details = !this.details;
|
||||
},
|
||||
|
||||
agentParts (agent) {
|
||||
let parts = agent.split('.');
|
||||
return {
|
||||
name: parts[0],
|
||||
action: parts[1],
|
||||
}
|
||||
},
|
||||
|
||||
testChanges(){
|
||||
this.busy = true;
|
||||
this.getWebsocket().send(JSON.stringify({
|
||||
type: "devtools",
|
||||
action: "test_prompt",
|
||||
prompt: this.prompt.prompt,
|
||||
generation_parameters: this.prompt.generation_parameters,
|
||||
kind: this.prompt.kind,
|
||||
client_name: this.prompt.client_name,
|
||||
}));
|
||||
},
|
||||
|
||||
hasPreviousPrompt() {
|
||||
return this.index < this.prompts.length - 1;
|
||||
},
|
||||
|
||||
hasNextPrompt() {
|
||||
return this.index > 0;
|
||||
},
|
||||
|
||||
loadPreviousPrompt() {
|
||||
if(this.index < this.prompts.length - 1) {
|
||||
this.index++;
|
||||
this.prompt = this.prompts[this.index];
|
||||
}
|
||||
},
|
||||
|
||||
loadNextPrompt() {
|
||||
if(this.index > 0) {
|
||||
this.index--;
|
||||
this.prompt = this.prompts[this.index];
|
||||
}
|
||||
},
|
||||
|
||||
open(prompt, prompts) {
|
||||
this.prompt = prompt;
|
||||
this.prompts = prompts;
|
||||
|
||||
this.index = this.prompts.indexOf(prompt);
|
||||
|
||||
this.dialog = true;
|
||||
this.busy = false;
|
||||
},
|
||||
close() {
|
||||
this.dialog = false;
|
||||
}
|
||||
}
|
||||
},
|
||||
handleMessage(data) {
|
||||
if(data.type !== "devtools") {
|
||||
return;
|
||||
}
|
||||
|
||||
if(data.action === "test_prompt_response" ) {
|
||||
this.prompt.response = data.data.response;
|
||||
this.busy = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.registerMessageHandler(this.handleMessage);
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -55,4 +195,11 @@ export default {
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.generation-parameters {
|
||||
font-family: monospace;
|
||||
font-size: 12px;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
</style>
|
||||
@@ -25,7 +25,7 @@
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn color="primary" v-if="!saving" text @click="cancel" prepend-icon="mdi-cancel">Cancel</v-btn>
|
||||
<v-progress-circular v-else indeterminate color="primary" size="20"></v-progress-circular>
|
||||
<v-progress-circular v-else indeterminate="disable-shrink" color="primary" size="20"></v-progress-circular>
|
||||
<v-btn color="primary" text :disabled="saving" @click="saveDefaultCharacter" prepend-icon="mdi-check-circle-outline">Continue</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
<template>
|
||||
<v-card flat variant="text" v-if="hasRecentScenes()">
|
||||
<v-card-title>
|
||||
Recent Saves
|
||||
Quick load
|
||||
</v-card-title>
|
||||
<v-card-subtitle>
|
||||
Continue your story
|
||||
</v-card-subtitle>
|
||||
<!--
|
||||
horizontal scroll from config.recent_scenes.scenes
|
||||
if sceneLoadingAvailable, clicking the scene should load it
|
||||
@@ -167,6 +164,7 @@ export default {
|
||||
.tile {
|
||||
flex: 0 0 275px;
|
||||
margin: 10px;
|
||||
max-width: 275px;
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<v-list-subheader v-if="appConfig !== null" @click="toggle()" class="text-uppercase"><v-icon>mdi-script-text-outline</v-icon> Load
|
||||
<v-progress-circular v-if="loading" indeterminate color="primary" size="20"></v-progress-circular>
|
||||
<v-progress-circular v-if="loading" indeterminate="disable-shrink" color="primary" size="20"></v-progress-circular>
|
||||
<v-icon v-if="expanded" icon="mdi-chevron-down"></v-icon>
|
||||
<v-icon v-else icon="mdi-chevron-up"></v-icon>
|
||||
</v-list-subheader>
|
||||
<v-list-subheader class="text-uppercase" v-else>
|
||||
<v-progress-circular indeterminate color="primary" size="20"></v-progress-circular> Waiting for config...
|
||||
<v-progress-circular indeterminate="disable-shrink" color="primary" size="20"></v-progress-circular> Waiting for config...
|
||||
</v-list-subheader>
|
||||
<div v-if="!loading && isConnected() && expanded && !configurationRequired() && appConfig !== null">
|
||||
<v-list-item>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-progress-circular class="ml-1 mr-3" size="24" v-if="generating" indeterminate color="primary"></v-progress-circular>
|
||||
<v-progress-circular class="ml-1 mr-3" size="24" v-if="generating" indeterminate="disable-shrink" color="primary"></v-progress-circular>
|
||||
<v-btn color="primary" @click="submit('generate')" :disabled="generating" prepend-icon="mdi-memory">Generate</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
|
||||
@@ -27,9 +27,14 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<v-alert v-else-if="message.type === 'system'" variant="tonal" closable :type="message.status || 'info'" class="system-message mb-3"
|
||||
<v-alert v-else-if="message.type === 'system'" variant="text" closable :type="message.status || 'info'" class="system-message mb-3 text-caption"
|
||||
:text="message.text">
|
||||
</v-alert>
|
||||
<div v-else-if="message.type === 'status'" :class="`message ${message.type}`">
|
||||
<div class="narrator-message">
|
||||
<StatusMessage :text="message.text" :status="message.status" />
|
||||
</div>
|
||||
</div>
|
||||
<div v-else-if="message.type === 'narrator'" :class="`message ${message.type}`">
|
||||
<div class="narrator-message" :id="`message-${message.id}`">
|
||||
<NarratorMessage :text="message.text" :message_id="message.id" />
|
||||
@@ -45,6 +50,7 @@
|
||||
<TimePassageMessage :text="message.text" :message_id="message.id" :ts="message.ts" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else :class="`message ${message.type}`">
|
||||
{{ message.text }}
|
||||
</div>
|
||||
@@ -57,6 +63,7 @@ import CharacterMessage from './CharacterMessage.vue';
|
||||
import NarratorMessage from './NarratorMessage.vue';
|
||||
import DirectorMessage from './DirectorMessage.vue';
|
||||
import TimePassageMessage from './TimePassageMessage.vue';
|
||||
import StatusMessage from './StatusMessage.vue';
|
||||
|
||||
export default {
|
||||
name: 'SceneMessages',
|
||||
@@ -65,6 +72,7 @@ export default {
|
||||
NarratorMessage,
|
||||
DirectorMessage,
|
||||
TimePassageMessage,
|
||||
StatusMessage,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -182,6 +190,31 @@ export default {
|
||||
this.messages.push({ id: data.id, type: data.type, character: character.trim(), text: text.trim(), color: data.color }); // Add color property to the message
|
||||
} else if (data.type != 'request_input' && data.type != 'client_status' && data.type != 'agent_status' && data.type != 'status') {
|
||||
this.messages.push({ id: data.id, type: data.type, text: data.message, color: data.color, character: data.character, status:data.status, ts:data.ts }); // Add color property to the message
|
||||
} else if (data.type === 'status' && data.data && data.data.as_scene_message === true) {
|
||||
|
||||
// status message can only exist once, remove the most recent one (if within the last 100 messages)
|
||||
// by walking the array backwards then removing the first one found
|
||||
// then add the new status message
|
||||
let max = 100;
|
||||
let iter = 0;
|
||||
for (i = this.messages.length - 1; i >= 0; i--) {
|
||||
if (this.messages[i].type == 'status') {
|
||||
this.messages.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
iter++;
|
||||
if(iter > max) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.messages.push({
|
||||
id: data.id,
|
||||
type: data.type,
|
||||
text: data.message,
|
||||
status: data.status,
|
||||
ts: data.ts
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,25 @@
|
||||
</template>
|
||||
</v-tooltip>
|
||||
</v-chip>
|
||||
|
||||
<v-tooltip v-if="sceneHelp" :text="sceneHelp" class="pre-wrap">
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-chip size="x-small" v-bind="props" color="primary" variant="text" class="ma-1">
|
||||
<v-icon class="mr-1">mdi-help-circle-outline</v-icon>
|
||||
{{ sceneName }} instructions
|
||||
</v-chip>
|
||||
</template>
|
||||
</v-tooltip>
|
||||
|
||||
<v-tooltip v-if="sceneExperimental" text="This scenario is classified as experimental, likely requiring usage of a strong LLM to produce a decent experience." class="pre-wrap">
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-chip size="x-small" v-bind="props" variant="text" color="warning" class="ma-1">
|
||||
<v-icon class="mr-1">mdi-flask</v-icon>
|
||||
Experimental
|
||||
</v-chip>
|
||||
</template>
|
||||
</v-tooltip>
|
||||
|
||||
</v-sheet>
|
||||
|
||||
<!-- Hotbuttons Section -->
|
||||
@@ -26,7 +45,7 @@
|
||||
|
||||
<v-card class="hotbuttons-section-1">
|
||||
<v-card-actions>
|
||||
<v-progress-circular class="ml-1 mr-3" size="24" v-if="!isWaitingForInput()" indeterminate
|
||||
<v-progress-circular class="ml-1 mr-3" size="24" v-if="!isWaitingForInput()" indeterminate="disable-shrink"
|
||||
color="primary"></v-progress-circular>
|
||||
<v-icon class="ml-1 mr-3" v-else-if="isWaitingForInput()">mdi-keyboard</v-icon>
|
||||
<v-icon class="ml-1 mr-3" v-else>mdi-circle-outline</v-icon>
|
||||
@@ -82,7 +101,7 @@
|
||||
|
||||
<v-menu>
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-btn class="hotkey mx-3" v-bind="props" :disabled="isInputDisabled()" color="primary" icon>
|
||||
<v-btn class="hotkey mx-3" v-bind="props" :disabled="isInputDisabled() || npc_characters.length === 0" color="primary" icon>
|
||||
<v-icon>mdi-account-voice</v-icon>
|
||||
</v-btn>
|
||||
</template>
|
||||
@@ -157,7 +176,7 @@
|
||||
|
||||
<!-- world tools -->
|
||||
|
||||
<v-menu max-width="500px">
|
||||
<v-menu max-width="500px" v-if="isEnvironment('scene')">
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-btn class="hotkey mx-3" v-bind="props" :disabled="isInputDisabled()" color="primary" icon>
|
||||
<v-icon>mdi-earth</v-icon>
|
||||
@@ -348,6 +367,9 @@ export default {
|
||||
commandName: null,
|
||||
autoSave: true,
|
||||
autoProgress: true,
|
||||
sceneName: "Scene",
|
||||
sceneHelp: "",
|
||||
sceneExperimental: false,
|
||||
canAutoSave: false,
|
||||
npc_characters: [],
|
||||
|
||||
@@ -634,6 +656,9 @@ export default {
|
||||
this.canAutoSave = data.data.can_auto_save;
|
||||
this.autoSave = data.data.auto_save;
|
||||
this.autoProgress = data.data.auto_progress;
|
||||
this.sceneHelp = data.data.help;
|
||||
this.sceneExperimental = data.data.experimental;
|
||||
this.sceneName = data.name;
|
||||
console.log({autoSave: this.autoSave, autoProgress: this.autoProgress});
|
||||
|
||||
// collect npc characters
|
||||
|
||||
61
talemate_frontend/src/components/StatusMessage.vue
Normal file
61
talemate_frontend/src/components/StatusMessage.vue
Normal file
@@ -0,0 +1,61 @@
|
||||
<template>
|
||||
<v-alert
|
||||
variant="text"
|
||||
:color="notificationColor()"
|
||||
class="text-center text-caption">
|
||||
{{ text }}
|
||||
<p v-if="status == 'busy'">
|
||||
<v-progress-linear color="primary" height="2" indeterminate></v-progress-linear>
|
||||
</p>
|
||||
</v-alert>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'StatusMessage',
|
||||
data() {
|
||||
return {
|
||||
}
|
||||
},
|
||||
props: {
|
||||
text: String,
|
||||
status: String,
|
||||
},
|
||||
inject: ['getWebsocket', 'registerMessageHandler', 'setWaitingForInput'],
|
||||
methods: {
|
||||
notificationIcon: function() {
|
||||
switch(this.status) {
|
||||
case 'success':
|
||||
return 'mdi-check-circle';
|
||||
case 'error':
|
||||
return 'mdi-alert-circle';
|
||||
case 'warning':
|
||||
return 'mdi-alert-circle';
|
||||
case 'info':
|
||||
return 'mdi-information';
|
||||
default:
|
||||
return 'mdi-information';
|
||||
}
|
||||
},
|
||||
|
||||
notificationColor: function() {
|
||||
switch(this.status) {
|
||||
case 'success':
|
||||
return 'success';
|
||||
case 'error':
|
||||
return 'error';
|
||||
case 'warning':
|
||||
return 'warning';
|
||||
case 'info':
|
||||
return 'info';
|
||||
default:
|
||||
return 'grey-darken-1';
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
created() {
|
||||
},
|
||||
}
|
||||
|
||||
</script>
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<v-snackbar v-model="statusMessage" location="top" :color="notificationColor()" close-on-content-click :timeout="notificationTimeout()" elevation="5">
|
||||
<v-progress-circular v-if="statusMessageType === 'busy'" indeterminate color="primary" size="20"></v-progress-circular>
|
||||
<v-progress-circular v-if="statusMessageType === 'busy'" indeterminate="disable-shrink" color="primary" size="20"></v-progress-circular>
|
||||
<v-icon v-else>{{ notificationIcon() }}</v-icon>
|
||||
<span class="ml-2">{{ statusMessageText }}</span>
|
||||
|
||||
@@ -62,6 +62,10 @@ export default {
|
||||
|
||||
handleMessage(data) {
|
||||
if(data.type === 'status') {
|
||||
|
||||
if(data.data && data.data.as_scene_message)
|
||||
return;
|
||||
|
||||
if(data.status === 'idle' && this.statusMessageType === 'busy') {
|
||||
this.statusMessage = false;
|
||||
this.statusMessageText = '';
|
||||
|
||||
@@ -59,11 +59,11 @@
|
||||
<!-- system bar -->
|
||||
<v-system-bar>
|
||||
<v-icon icon="mdi-network-outline"></v-icon>
|
||||
<v-progress-circular v-if="activeAgentName() !== null" indeterminate color="primary" size="11"
|
||||
<v-progress-circular v-if="activeAgentName() !== null" indeterminate="disable-shrink" color="primary" size="11"
|
||||
class="mr-1 ml-1"></v-progress-circular>
|
||||
<span class="mr-1">{{ activeAgentName() }}</span>
|
||||
<v-icon icon="mdi-transit-connection-variant"></v-icon>
|
||||
<v-progress-circular v-if="activeClientName() !== null" indeterminate color="primary" size="11"
|
||||
<v-progress-circular v-if="activeClientName() !== null" indeterminate="disable-shrink" color="primary" size="11"
|
||||
class="mr-1 ml-1"></v-progress-circular>
|
||||
<span class="mr-1">{{ activeClientName() }}</span>
|
||||
<v-divider vertical></v-divider>
|
||||
@@ -107,7 +107,7 @@
|
||||
<v-app-bar-nav-icon @click="toggleNavigation('debug')"><v-icon>mdi-bug</v-icon></v-app-bar-nav-icon>
|
||||
<v-app-bar-nav-icon @click="openAppConfig()"><v-icon>mdi-cog</v-icon></v-app-bar-nav-icon>
|
||||
<v-app-bar-nav-icon @click="toggleNavigation('settings')" v-if="configurationRequired()"
|
||||
color="red"><v-icon>mdi-application-cog</v-icon></v-app-bar-nav-icon>
|
||||
color="red-darken-1"><v-icon>mdi-application-cog</v-icon></v-app-bar-nav-icon>
|
||||
<v-app-bar-nav-icon @click="toggleNavigation('settings')"
|
||||
v-else><v-icon>mdi-application-cog</v-icon></v-app-bar-nav-icon>
|
||||
|
||||
@@ -156,7 +156,7 @@
|
||||
</v-main>
|
||||
|
||||
<AppConfig ref="appConfig" />
|
||||
<v-snackbar v-model="errorNotification" color="red" :timeout="3000">
|
||||
<v-snackbar v-model="errorNotification" color="red-darken-1" :timeout="3000">
|
||||
{{ errorMessage }}
|
||||
</v-snackbar>
|
||||
<StatusNotification />
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<v-list-subheader class="text-uppercase">
|
||||
<v-icon class="mr-1">mdi-earth</v-icon>World
|
||||
<v-progress-circular class="ml-1 mr-3" size="14" v-if="requesting" indeterminate color="primary"></v-progress-circular>
|
||||
<v-progress-circular class="ml-1 mr-3" size="14" v-if="requesting" indeterminate="disable-shrink" color="primary"></v-progress-circular>
|
||||
<v-tooltip v-else text="Update Worldstate">
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-btn :disabled="isInputDisabled()" size="x-small" icon="mdi-refresh" class="mr-1" v-bind="props" variant="tonal" density="comfortable" rounded="sm" @click.stop="refresh()"></v-btn>
|
||||
@@ -18,6 +18,12 @@
|
||||
|
||||
<v-sheet ref="worldStateContainer">
|
||||
|
||||
<!-- empty (no characters or objects) -->
|
||||
|
||||
<v-card elevation="7" v-if="Object.keys(characters).length === 0 && Object.keys(items).length === 0" class="text-center text-caption mx-3" density="compact" variant="tonal" color="grey">
|
||||
World state has not been updated yet.
|
||||
</v-card>
|
||||
|
||||
<div ref="charactersContainer">
|
||||
|
||||
<!-- CHARACTERS -->
|
||||
@@ -43,14 +49,13 @@
|
||||
<!-- ACTIONS: LOOK AT, CHARACTER SHEET, PERSIST -->
|
||||
|
||||
<div class="text-center mt-1">
|
||||
<v-tooltip text="Look at">
|
||||
<v-tooltip :text="'Look at '+name">
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-btn size="x-small" class="mr-1" v-bind="props" variant="tonal" density="comfortable" rounded="sm" @click.stop="lookAtCharacter(name)" icon="mdi-eye"></v-btn>
|
||||
|
||||
</template>
|
||||
</v-tooltip>
|
||||
|
||||
<v-tooltip v-if="characterSheet().characterExists(name)" text="Character details">
|
||||
<v-tooltip v-if="characterSheet().characterExists(name)" text="Character sheet">
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-btn size="x-small" class="mr-1" v-bind="props" variant="tonal" density="comfortable" rounded="sm" @click.stop="openCharacterSheet(name)" icon="mdi-account-details"></v-btn>
|
||||
|
||||
@@ -62,6 +67,12 @@
|
||||
|
||||
</template>
|
||||
</v-tooltip>
|
||||
<v-tooltip v-if="characterSheet().characterExists(name)" text="Manage character">
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-btn size="x-small" class="mr-1" v-bind="props" variant="tonal" density="comfortable" rounded="sm" @click.stop="openWorldStateManager('characters', name, 'description')" icon="mdi-book-open-page-variant"></v-btn>
|
||||
|
||||
</template>
|
||||
</v-tooltip>
|
||||
</div>
|
||||
<v-divider class="mt-1"></v-divider>
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,133 @@
|
||||
|
||||
<template>
|
||||
<v-row>
|
||||
<v-col cols="3">
|
||||
<v-tabs density="compact" color="indigo-lighten-3" direction="vertical" v-model="tab">
|
||||
<v-tab value="instructions" class="text-caption">
|
||||
Dialogue Instructions
|
||||
</v-tab>
|
||||
<v-tab value="examples" class="text-caption">
|
||||
Dialogue Examples
|
||||
</v-tab>
|
||||
</v-tabs>
|
||||
</v-col>
|
||||
<v-col cols="9">
|
||||
|
||||
<div v-if="tab == 'instructions'">
|
||||
<v-textarea
|
||||
placeholder="speak less formally, use more contractions, and be more casual."
|
||||
v-model="dialogueInstructions" label="Acting Instructions"
|
||||
:color="dialogueInstructionsDirty ? 'primary' : null"
|
||||
@update:model-value="queueUpdateCharacterActor"
|
||||
rows="3"
|
||||
auto-grow></v-textarea>
|
||||
<v-alert icon="mdi-bullhorn" density="compact" variant="text" color="grey">
|
||||
<p>
|
||||
Any instructions you enter here will be inserted into the context right before
|
||||
<span class="text-primary">{{ character.name }}</span> speaks the next line. It can have a strong effect on the style
|
||||
of the dialogue. Use this when a character has trouble sticking to their
|
||||
personality / type of speech. Try to keep it short and write them as if giving
|
||||
instructions to an actor.
|
||||
</p>
|
||||
<v-divider class="mt-2 mb-2"></v-divider>
|
||||
<p>
|
||||
<v-icon size="small" color="orange" class="mr-1">mdi-flask</v-icon><span class="text-orange">Experimental feature</span> - whether or not this improves or degrades generations strongly depends on LLM used. Giving too long instructions here may degrade the quality of the dialogue, especially in the beginning of the scene.
|
||||
</p>
|
||||
</v-alert>
|
||||
</div>
|
||||
|
||||
<div v-else-if="tab == 'examples'">
|
||||
<ContextualGenerate
|
||||
:context="'character dialogue:'"
|
||||
:character="character.name"
|
||||
:rewrite-enabled="false"
|
||||
@generate="content => { dialogueExamples.push(content); queueUpdateCharacterActor(); }"
|
||||
/>
|
||||
<v-text-field v-model="dialogueExample" label="Add Dialogue Example" @keyup.enter="dialogueExamples.push(dialogueExample); dialogueExample = ''; queueUpdateCharacterActor();" dense></v-text-field>
|
||||
<v-list density="compact" nav>
|
||||
<v-list-item v-for="(example, index) in dialogueExamplesWithNameStripped" :key="index">
|
||||
<template v-slot:prepend>
|
||||
<v-btn color="red-darken-2" rounded="sm" size="x-small" icon variant="text" @click="dialogueExamples.splice(index, 1); queueUpdateCharacterActor()">
|
||||
<v-icon>mdi-close-box-outline</v-icon>
|
||||
</v-btn>
|
||||
</template>
|
||||
<div class="text-caption text-grey">
|
||||
{{ example }}
|
||||
</div>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</div>
|
||||
|
||||
</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import ContextualGenerate from './ContextualGenerate.vue';
|
||||
|
||||
export default {
|
||||
name: 'WorldStateManagerCharacterActor',
|
||||
components: {
|
||||
ContextualGenerate,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
tab: "instructions",
|
||||
dialogueExamples: [],
|
||||
dialogueExample: "",
|
||||
dialogueInstructions: null,
|
||||
dialogueInstructionsDirty: false,
|
||||
updateCharacterActorTimeout: null,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
dialogueExamplesWithNameStripped() {
|
||||
return this.dialogueExamples.map((example) => {
|
||||
return example.replace(this.character.name + ': ', '');
|
||||
});
|
||||
}
|
||||
},
|
||||
props: {
|
||||
character: Object,
|
||||
},
|
||||
inject: ['getWebsocket', 'registerMessageHandler'],
|
||||
methods: {
|
||||
|
||||
queueUpdateCharacterActor() {
|
||||
this.dialogueInstructionsDirty = true;
|
||||
if (this.updateCharacterActorTimeout) {
|
||||
clearTimeout(this.updateCharacterActorTimeout);
|
||||
}
|
||||
this.updateCharacterActorTimeout = setTimeout(this.updateCharacterActor, 500);
|
||||
},
|
||||
|
||||
updateCharacterActor() {
|
||||
this.getWebsocket().send(JSON.stringify({
|
||||
type: "world_state_manager",
|
||||
action: "update_character_actor",
|
||||
name: this.character.name,
|
||||
dialogue_instructions: this.dialogueInstructions,
|
||||
dialogue_examples: this.dialogueExamples,
|
||||
}));
|
||||
},
|
||||
|
||||
handleMessage(data) {
|
||||
if(data.type === 'world_state_manager') {
|
||||
if(data.action === 'character_actor_updated') {
|
||||
this.dialogueInstructionsDirty = false;
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.registerMessageHandler(this.handleMessage);
|
||||
},
|
||||
mounted() {
|
||||
console.log("MOUNTED", this.character)
|
||||
this.dialogueInstructions = this.character.actor.dialogue_instructions;
|
||||
this.dialogueExamples = this.character.actor.dialogue_examples;
|
||||
},
|
||||
}
|
||||
|
||||
</script>
|
||||
@@ -136,12 +136,12 @@
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<div v-if="templateDeleteConfirm===false">
|
||||
<v-btn rounded="sm" prepend-icon="mdi-delete" color="error" variant="text" @click.stop="templateDeleteConfirm=true" >
|
||||
<v-btn rounded="sm" prepend-icon="mdi-close-box-outline" color="error" variant="text" @click.stop="templateDeleteConfirm=true" >
|
||||
Remove template
|
||||
</v-btn>
|
||||
</div>
|
||||
<div v-else>
|
||||
<v-btn rounded="sm" prepend-icon="mdi-delete" @click.stop="removeTemplate" color="error" variant="text">
|
||||
<v-btn rounded="sm" prepend-icon="mdi-close-box-outline" @click.stop="removeTemplate" color="error" variant="text">
|
||||
Confirm removal
|
||||
</v-btn>
|
||||
<v-btn class="ml-1" rounded="sm" prepend-icon="mdi-cancel" @click.stop="templateDeleteConfirm=false" color="info" variant="text">
|
||||
|
||||
@@ -64,6 +64,11 @@
|
||||
<v-card-text>
|
||||
<v-row>
|
||||
<v-col cols="12">
|
||||
<ContextualGenerate
|
||||
:context="'world context:'+entry.id"
|
||||
:original="entry.text"
|
||||
@generate="content => { entry.text=content; queueSaveEntry(); }"
|
||||
/>
|
||||
<v-textarea
|
||||
v-model="entry.text"
|
||||
label="World information"
|
||||
@@ -87,12 +92,12 @@
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<span v-if="deleteConfirm===false">
|
||||
<v-btn rounded="sm" prepend-icon="mdi-delete" color="error" variant="text" @click.stop="deleteConfirm=true" >
|
||||
<v-btn rounded="sm" prepend-icon="mdi-close-box-outline" color="error" variant="text" @click.stop="deleteConfirm=true" >
|
||||
Remove entry
|
||||
</v-btn>
|
||||
</span>
|
||||
<span v-else>
|
||||
<v-btn rounded="sm" prepend-icon="mdi-delete" @click.stop="removeEntry" color="error" variant="text">
|
||||
<v-btn rounded="sm" prepend-icon="mdi-close-box-outline" @click.stop="removeEntry" color="error" variant="text">
|
||||
Confirm removal
|
||||
</v-btn>
|
||||
<v-btn class="ml-1" rounded="sm" prepend-icon="mdi-cancel" @click.stop="deleteConfirm=false" color="info" variant="text">
|
||||
@@ -203,12 +208,12 @@
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<span v-if="deleteConfirm===false">
|
||||
<v-btn rounded="sm" prepend-icon="mdi-delete" color="error" variant="text" @click.stop="deleteConfirm=true" >
|
||||
<v-btn rounded="sm" prepend-icon="mdi-close-box-outline" color="error" variant="text" @click.stop="deleteConfirm=true" >
|
||||
Remove state
|
||||
</v-btn>
|
||||
</span>
|
||||
<span v-else>
|
||||
<v-btn rounded="sm" prepend-icon="mdi-delete" @click.stop="removeState" color="error" variant="text">
|
||||
<v-btn rounded="sm" prepend-icon="mdi-close-box-outline" @click.stop="removeState" color="error" variant="text">
|
||||
Confirm removal
|
||||
</v-btn>
|
||||
<v-btn class="ml-1" rounded="sm" prepend-icon="mdi-cancel" @click.stop="deleteConfirm=false" color="info" variant="text">
|
||||
@@ -245,8 +250,14 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import ContextualGenerate from './ContextualGenerate.vue';
|
||||
|
||||
export default {
|
||||
name: 'WorldStateManagerWorld',
|
||||
components: {
|
||||
ContextualGenerate,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
entries: {},
|
||||
|
||||
Reference in New Issue
Block a user