XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet
公开
关注 0 Fork 0 Star 1
返回提交历史

XFEstudio/gpt4free

Add count word and tokens in gui

0ade2098
Heiner Lohaus <hlohaus@users.noreply.github.com>
提交于

代码差异

3 个文件 +89 -23
Modified g4f/gui/client/css/style.css +23 -3
@@ -129,7 +129,7 @@ body {
129 129 flex-direction: column;
130 130 overflow: auto;
131 131 overflow-wrap: break-word;
132 padding-bottom: 50px;
132 padding-bottom: 20px;
133 133 }
134 134
135 135 .conversation .user-input {
@@ -291,7 +291,7 @@ body {
291 291 .message .content {
292 292 display: flex;
293 293 flex-direction: column;
294 gap: 18px;
294 gap: 10px;
295 295 }
296 296
297 297 .message .content,
@@ -343,6 +343,26 @@ body {
343 343 display: block;
344 344 }
345 345
346 .message .content .provider a,
347 .message .content .provider {
348 font-size: 12px;
349 text-decoration: none;
350 }
351
352 .message .content .provider a {
353 font-weight: bold;
354 }
355
356 .message .content .count {
357 font-size: 12px;
358 }
359
360 .count_total {
361 font-size: 12px;
362 padding-left: 100px;
363 padding-top: 10px;
364 }
365
346 366 .new_convo {
347 367 padding: 8px 12px;
348 368 display: flex;
@@ -367,7 +387,7 @@ body {
367 387
368 388 .stop_generating, .regenerate {
369 389 position: absolute;
370 bottom: 158px;
390 bottom: 122px;
371 391 left: 50%;
372 392 transform: translateX(-50%);
373 393 z-index: 1000000;
Modified g4f/gui/client/html/index.html +10 -3
@@ -29,10 +29,17 @@
29 29 }
30 30 };
31 31 </script>
32 <script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
32 <script id="MathJax-script" src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js" async></script>
33 <script type="module" src="https://cdn.jsdelivr.net/npm/mistral-tokenizer-js" async>
34 import mistralTokenizer from 'mistral-tokenizer-js'
35 </script>
36 <script type="module" src="https://belladoreai.github.io/llama-tokenizer-js/llama-tokenizer.js" async>
37 import llamaTokenizer from 'llama-tokenizer-js'
38 </script>
39 <script src="https://unpkg.com/gpt-tokenizer/dist/cl100k_base.js" async></script>
33 40 <script>
34 const user_image = `<img src="/assets/img/user.png" alt="your avatar">`;
35 const gpt_image = `<img src="/assets/img/gpt.png" alt="your avatar">`;
41 const user_image = '<img src="/assets/img/user.png" alt="your avatar">';
42 const gpt_image = '<img src="/assets/img/gpt.png" alt="your avatar">';
36 43 </script>
37 44 <style>
38 45 .hljs {
Modified g4f/gui/client/js/chat.v1.js +56 -17
@@ -120,16 +120,8 @@ const remove_cancel_button = async () => {
120 120 }, 300);
121 121 };
122 122
123 const ask_gpt = async () => {
124 regenerate.classList.add(`regenerate-hidden`);
125 messages = await get_messages(window.conversation_id);
126
127 // Remove history, if it is selected
128 if (document.getElementById('history')?.checked) {
129 messages = [messages[messages.length-1]]
130 }
131
132 new_messages = [];
123 const filter_messages = (messages) => {
124 let new_messages = [];
133 125 for (i in messages) {
134 126 new_message = messages[i];
135 127 // Remove generated images from history
@@ -143,6 +135,19 @@ const ask_gpt = async () => {
143 135 new_messages.push(new_message)
144 136 }
145 137 }
138 return new_messages;
139 }
140
141 const ask_gpt = async () => {
142 regenerate.classList.add(`regenerate-hidden`);
143 messages = await get_messages(window.conversation_id);
144 total_messages = messages.length;
145
146 // Remove history, if it is selected
147 if (document.getElementById('history')?.checked) {
148 messages = [messages[messages.length-1]];
149 }
150 messages = filter_messages(messages);
146 151
147 152 window.scrollTo(0, 0);
148 153 window.controller = new AbortController();
@@ -159,8 +164,11 @@ const ask_gpt = async () => {
159 164 await new Promise((r) => setTimeout(r, 500));
160 165 window.scrollTo(0, 0);
161 166
167 el = message_box.querySelector('.count_total');
168 el ? el.parentElement.removeChild(el) : null;
169
162 170 message_box.innerHTML += `
163 <div class="message" data-index="${new_messages.length}">
171 <div class="message" data-index="${total_messages}">
164 172 <div class="assistant">
165 173 ${gpt_image}
166 174 <i class="fa-solid fa-xmark"></i>
@@ -186,7 +194,7 @@ const ask_gpt = async () => {
186 194 web_search: document.getElementById(`switch`).checked,
187 195 provider: provider.options[provider.selectedIndex].value,
188 196 patch_provider: document.getElementById('patch').checked,
189 messages: new_messages
197 messages: messages
190 198 });
191 199 const headers = {
192 200 accept: 'text/event-stream'
@@ -240,7 +248,7 @@ const ask_gpt = async () => {
240 248 } else {
241 249 html = markdown_render(text);
242 250 let lastElement, lastIndex = null;
243 for (element of ['</p>', '</code></pre>', '</li>\n</ol>']) {
251 for (element of ['</p>', '</code></pre>', '</li>\n</ol>', '</li>\n</ul>']) {
244 252 const index = html.lastIndexOf(element)
245 253 if (index > lastIndex) {
246 254 lastElement = element;
@@ -278,8 +286,9 @@ const ask_gpt = async () => {
278 286 let cursorDiv = document.getElementById(`cursor`);
279 287 if (cursorDiv) cursorDiv.parentNode.removeChild(cursorDiv);
280 288 if (text) {
281 add_message(window.conversation_id, "assistant", text, provider);
289 await add_message(window.conversation_id, "assistant", text, provider);
282 290 }
291 await load_conversation(window.conversation_id);
283 292 message_box.scrollTop = message_box.scrollHeight;
284 293 await remove_cancel_button();
285 294 await register_remove_message();
@@ -372,10 +381,16 @@ const load_conversation = async (conversation_id) => {
372 381 let elements = "";
373 382 for (i in messages) {
374 383 let item = messages[i];
375 let provider = item.provider ? `
384 let next_i = parseInt(i) + 1;
385 let next_provider = item.provider ? item.provider : (messages.length > next_i ? messages[next_i].provider : null);
386 let tokens_count = next_provider?.model ? count_tokens(next_provider.model, item.content) : "";
387 let append_count = tokens_count ? `, ${tokens_count} tokens` : "";
388 let words_count = `(${count_words(item.content)} words${append_count})`
389 let provider_link = item?.provider?.name ? `<a href="${item?.provider?.url}" target="_blank">${item.provider.name}</a>` : "";
390 let provider = provider_link ? `
376 391 <div class="provider">
377 <a href="${item.provider.url}" target="_blank">${item.provider.name}</a>
378 ${item.provider.model ? ' with ' + item.provider.model : ''}
392 ${provider_link}
393 ${item.provider.model ? ' with ' + item.provider.model : ''}
379 394 </div>
380 395 ` : "";
381 396 elements += `
@@ -391,10 +406,17 @@ const load_conversation = async (conversation_id) => {
391 406 <div class="content">
392 407 ${provider}
393 408 <div class="content_inner">${markdown_render(item.content)}</div>
409 <div class="count">${words_count}</div>
394 410 </div>
395 411 </div>
396 412 `;
397 413 }
414
415 let count_total = GPTTokenizer_cl100k_base?.encodeChat(filter_messages(messages), "gpt-3.5-turbo").length
416 if (count_total > 0) {
417 elements += `<div class="count_total">(${count_total} tokens used)</div>`;
418 }
419
398 420 message_box.innerHTML = elements;
399 421
400 422 await register_remove_message();
@@ -407,6 +429,23 @@ const load_conversation = async (conversation_id) => {
407 429 }, 500);
408 430 };
409 431
432 function count_words(text) {
433 var matches = text.match(/[\w\d\’\'-]+/gi);
434 return matches ? matches.length : 0;
435 }
436
437 function count_tokens(model, text) {
438 if (model.startsWith("gpt-3") || model.startsWith("gpt-4")) {
439 return GPTTokenizer_cl100k_base?.encode(text).length
440 }
441 if (model.startsWith("llama2") || model.startsWith("codellama")) {
442 return llamaTokenizer?.encode(text).length
443 }
444 if (model.startsWith("mistral") || model.startsWith("mixtral")) {
445 return mistralTokenizer?.encode(text).length
446 }
447 }
448
410 449 const get_conversation = async (conversation_id) => {
411 450 let conversation = await JSON.parse(
412 451 localStorage.getItem(`conversation:${conversation_id}`)