mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
Working state stat UI
This commit is contained in:
@@ -2566,6 +2566,9 @@
|
||||
<input type="file" id="avatar_upload_file" accept="image/*" name="avatar">
|
||||
<input type="hidden" id="avatar_upload_overwrite" name="overwrite_name" value="">
|
||||
</form>
|
||||
<button class="menu_button user_stats_button" title="Click for stats!" style="position: absolute; right: 0; bottom: 0;">
|
||||
<i class="fa-solid fa-circle-info"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -2604,7 +2607,6 @@
|
||||
<div id="rm_button_selected_ch">
|
||||
<h2></h2>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<!-- end group peeking cope structure-->
|
||||
|
@@ -1,4 +1,5 @@
|
||||
import { humanizedDateTime, favsToHotswap, getMessageTimeStamp, dragElement, isMobile, AA_CountCharTime } from "./scripts/RossAscends-mods.js";
|
||||
import { humanizedDateTime, humanizeGenTime, favsToHotswap, getMessageTimeStamp, dragElement, isMobile, AA_CountCharTime } from "./scripts/RossAscends-mods.js";
|
||||
import { userStatsHandler, characterStatsHandler } from './scripts/stats.js';
|
||||
import { encode } from "../scripts/gpt-2-3-tokenizer/mod.js";
|
||||
import { GPT3BrowserTokenizer } from "../scripts/gpt-3-tokenizer/gpt3-tokenizer.js";
|
||||
import {
|
||||
@@ -955,7 +956,7 @@ async function getCharacters() {
|
||||
|
||||
|
||||
updateCharacterCount('#rm_print_characters_block > div');
|
||||
await AA_CountCharTime(this_chid);
|
||||
//await AA_CountCharTime(this_chid);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4895,7 +4896,6 @@ async function getSettings(type) {
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
getStats();
|
||||
if (data.result != "file not find" && data.settings) {
|
||||
settings = JSON.parse(data.settings);
|
||||
if (settings.username !== undefined) {
|
||||
@@ -5122,25 +5122,6 @@ async function saveSettings(type) {
|
||||
}
|
||||
|
||||
|
||||
async function getStats() {
|
||||
const response = await fetch("/getstats", {
|
||||
method: "POST",
|
||||
headers: getRequestHeaders(),
|
||||
body: JSON.stringify({}),
|
||||
cache: "no-cache",
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
toastr.error('Stats could not be loaded. Try reloading the page.');
|
||||
throw new Error('Error getting stats');
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
charStats = data;
|
||||
console.log(charStats);
|
||||
|
||||
}
|
||||
|
||||
|
||||
function setCharacterBlockHeight() {
|
||||
const $children = $("#rm_print_characters_block").children();
|
||||
@@ -8581,6 +8562,10 @@ $(document).ready(function () {
|
||||
restoreCaretPosition($(this).get(0), caretPosition);
|
||||
});
|
||||
|
||||
$(".user_stats_button").on('click', function () {
|
||||
userStatsHandler(charStats);
|
||||
});
|
||||
|
||||
$('#external_import_button').on('click', async () => {
|
||||
const html = `<h3>Enter the URL of the content to import</h3>
|
||||
Supported sources:<br>
|
||||
@@ -8719,4 +8704,4 @@ $(document).ready(function () {
|
||||
$("#charListGridToggle").on('click', async () => {
|
||||
doCharListDisplaySwitch();
|
||||
});
|
||||
})
|
||||
});
|
@@ -16,6 +16,10 @@ import {
|
||||
charStats,
|
||||
} from "../script.js";
|
||||
|
||||
import {
|
||||
characterStatsHandler,
|
||||
} from "./stats.js";
|
||||
|
||||
|
||||
import {
|
||||
power_user,
|
||||
@@ -72,7 +76,7 @@ const observer = new MutationObserver(function (mutations) {
|
||||
RA_checkOnlineStatus();
|
||||
} else if (mutation.target.parentNode === SelectedCharacterTab) {
|
||||
setTimeout(RA_CountCharTokens, 200);
|
||||
setTimeout(AA_CountCharTime, 200);
|
||||
//setTimeout(AA_CountCharTime, 200);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -108,10 +112,10 @@ function waitForElement(querySelector, timeout) {
|
||||
|
||||
|
||||
//humanize character generation time
|
||||
export function humanizeGenTime(character) {
|
||||
let stat = charStats[character.avatar]
|
||||
export function humanizeGenTime(total_gen_time) {
|
||||
|
||||
//convert time_spent to humanized format of "_ Hours, _ Minutes, _ Seconds" from milliseconds
|
||||
let time_spent = stat.total_gen_time
|
||||
let time_spent = total_gen_time || 0;
|
||||
time_spent = Math.floor(time_spent / 1000);
|
||||
let seconds = time_spent % 60;
|
||||
time_spent = Math.floor(time_spent / 60);
|
||||
@@ -327,7 +331,10 @@ export function RA_CountCharTokens() {
|
||||
// if neither, probably safety char or some error in loading
|
||||
} else { console.debug("RA_TC -- no valid char found, closing."); }
|
||||
}
|
||||
$("#result_info").html(`<small>${count_tokens} Tokens (${perm_tokens} Permanent)</small>`);
|
||||
//label rm_stats_button with a tooltip indicating stats
|
||||
$("#result_info").html(`<small>${count_tokens} Tokens (${perm_tokens} Permanent)</small>
|
||||
|
||||
<i title='Click for stats!' class="fa-solid fa-circle-info rm_stats_button"></i>`);
|
||||
// display the counted tokens
|
||||
const tokenLimit = Math.max(((main_api !== 'openai' ? max_context : oai_settings.openai_max_context) / 2), 1024);
|
||||
if (count_tokens < tokenLimit && perm_tokens < tokenLimit) {
|
||||
@@ -339,10 +346,16 @@ export function RA_CountCharTokens() {
|
||||
<small class="flex-container flexnowrap flexNoGap">
|
||||
<div class="neutral_warning">${count_tokens}</div> Tokens (<div class="neutral_warning">${perm_tokens}</div><div> Permanent)</div>
|
||||
</small>
|
||||
<i title='Click for stats!' class="fa-solid fa-circle-info rm_stats_button"></i>
|
||||
</div>
|
||||
<div id="chartokenwarning" class="menu_button margin0 whitespacenowrap"><a href="https://docs.sillytavern.app/usage/core-concepts/characterdesign/#character-tokens" target="_blank">About Token 'Limits'</a></div>
|
||||
</div>`);
|
||||
|
||||
|
||||
} //warn if either are over 1024
|
||||
$(".rm_stats_button").on('click', function () {
|
||||
characterStatsHandler(charStats, characters, this_chid);
|
||||
});
|
||||
}
|
||||
//Auto Load Last Charcter -- (fires when active_character is defined and auto_load_chat is true)
|
||||
async function RA_autoloadchat() {
|
||||
|
@@ -1223,7 +1223,7 @@ function openCharacterDefinition(characterSelect) {
|
||||
select_selected_character(chid);
|
||||
// Gentle nudge to recalculate tokens
|
||||
RA_CountCharTokens();
|
||||
AA_CountCharTime(chid);
|
||||
//AA_CountCharTime(chid);
|
||||
// Do a little tomfoolery to spoof the tag selector
|
||||
applyTagsOnCharacterSelect.call(characterSelect);
|
||||
}
|
||||
|
98
public/scripts/stats.js
Normal file
98
public/scripts/stats.js
Normal file
@@ -0,0 +1,98 @@
|
||||
// statsHelper.js
|
||||
import { getRequestHeaders, callPopup, token } from '../script.js';
|
||||
import { humanizeGenTime } from './RossAscends-mods.js';
|
||||
|
||||
|
||||
|
||||
// Function for creating stat block HTML
|
||||
function createStatBlock(statName, statValue) {
|
||||
return `<div class="rm_stat_block">
|
||||
<div class="rm_stat_name">${statName}:</div>
|
||||
<div class="rm_stat_value">${statValue}</div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
function calculateTotal(stat) {
|
||||
return isNaN(stat) ? 0 : stat;
|
||||
}
|
||||
|
||||
function calculateTotalStats(charStats) {
|
||||
let totalStats = {
|
||||
total_gen_time: 0,
|
||||
user_msg_count: 0,
|
||||
non_user_msg_count: 0,
|
||||
user_word_count: 0,
|
||||
non_user_word_count: 0,
|
||||
total_swipe_count: 0
|
||||
};
|
||||
|
||||
for (let stats of Object.values(charStats)) {
|
||||
totalStats.total_gen_time += calculateTotal(stats.total_gen_time);
|
||||
totalStats.user_msg_count += calculateTotal(stats.user_msg_count);
|
||||
totalStats.non_user_msg_count += calculateTotal(stats.non_user_msg_count);
|
||||
totalStats.user_word_count += calculateTotal(stats.user_word_count);
|
||||
totalStats.non_user_word_count += calculateTotal(stats.non_user_word_count);
|
||||
totalStats.total_swipe_count += calculateTotal(stats.total_swipe_count);
|
||||
}
|
||||
|
||||
return totalStats;
|
||||
}
|
||||
|
||||
function createHtml(statsType, stats) {
|
||||
// Get time string
|
||||
let timeStirng = humanizeGenTime(stats.total_gen_time);
|
||||
|
||||
// Create popup HTML with stats
|
||||
let html = `<h3>${statsType} Stats</h3>`;
|
||||
html += createStatBlock('Chat Time', timeStirng);
|
||||
html += createStatBlock('Total User Messages', stats.user_msg_count);
|
||||
html += createStatBlock('Total Character Messages', stats.non_user_msg_count);
|
||||
html += createStatBlock('Total User Words', stats.user_word_count);
|
||||
html += createStatBlock('Total Character Words', stats.non_user_word_count);
|
||||
html += createStatBlock('Swipes', stats.total_swipe_count);
|
||||
|
||||
callPopup(html, 'text');
|
||||
}
|
||||
|
||||
async function userStatsHandler(charStats) {
|
||||
// Get stats from server
|
||||
let stats = await getStats(charStats);
|
||||
|
||||
// Calculate total stats
|
||||
let totalStats = calculateTotalStats(stats);
|
||||
console.log(totalStats);
|
||||
|
||||
// Create HTML with stats
|
||||
createHtml('User', totalStats);
|
||||
}
|
||||
|
||||
async function characterStatsHandler(charStats, characters, this_chid) {
|
||||
// Get stats from server
|
||||
let stats = await getStats(charStats);
|
||||
|
||||
// Get character stats
|
||||
let myStats = stats[characters[this_chid].avatar];
|
||||
|
||||
// Create HTML with stats
|
||||
createHtml('Character', myStats);
|
||||
}
|
||||
|
||||
async function getStats(charStats) {
|
||||
const response = await fetch("/getstats", {
|
||||
method: "POST",
|
||||
headers: getRequestHeaders(),
|
||||
body: JSON.stringify({}),
|
||||
cache: "no-cache",
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
toastr.error('Stats could not be loaded. Try reloading the page.');
|
||||
throw new Error('Error getting stats');
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
return data;
|
||||
|
||||
}
|
||||
|
||||
export { userStatsHandler, characterStatsHandler, getStats };
|
@@ -1877,6 +1877,11 @@ grammarly-extension {
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
.rm_stat_block {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.large_dialogue_popup {
|
||||
height: 90vh !important;
|
||||
height: 90svh !important;
|
||||
|
@@ -132,7 +132,6 @@ function countWordsInString(str) {
|
||||
* @return {object} An object containing the calculated statistics.
|
||||
*/
|
||||
const calculateStats = (chatsPath, item, index) => {
|
||||
console.log('Calculating stats for', item);
|
||||
const char_dir = path.join(chatsPath, item.replace('.png', ''));
|
||||
let chat_size = 0;
|
||||
let date_last_chat = 0;
|
||||
@@ -152,7 +151,6 @@ const calculateStats = (chatsPath, item, index) => {
|
||||
const chats = fs.readdirSync(char_dir);
|
||||
if (Array.isArray(chats) && chats.length) {
|
||||
for (const chat of chats) {
|
||||
console.log(uniqueGenStartTimes);
|
||||
const result = calculateTotalGenTimeAndWordCount(char_dir, chat, uniqueGenStartTimes);
|
||||
stats.total_gen_time += result.totalGenTime || 0;
|
||||
stats.user_word_count += result.userWordCount || 0;
|
||||
@@ -164,7 +162,6 @@ const calculateStats = (chatsPath, item, index) => {
|
||||
const chatStat = fs.statSync(path.join(char_dir, chat));
|
||||
stats.chat_size += chatStat.size;
|
||||
stats.date_last_chat = Math.max(stats.date_last_chat, chatStat.mtimeMs);
|
||||
console.log(stats);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user