From 65a6eec509d919f8bbf9e2a474cc94ef4a3518da Mon Sep 17 00:00:00 2001 From: Pabloader Date: Thu, 19 Feb 2026 12:20:37 +0000 Subject: [PATCH] Format templates, add pwa icon --- build/html.ts | 4 +- src/games/ai-story/assets/favicon.ico | Bin 3262 -> 4286 bytes src/games/ai-story/assets/pwa_icon.png | Bin 0 -> 54430 bytes src/games/ai-story/assets/style.css | 1 + .../components/header/connectionEditor.tsx | 16 ++- .../components/header/header.module.css | 6 + .../ai-story/components/header/header.tsx | 13 +- .../ai-story/components/message/message.tsx | 2 +- src/games/ai-story/contexts/llm.tsx | 6 +- src/games/ai-story/contexts/state.tsx | 30 ++-- src/games/ai-story/tools/huggingface.ts | 131 ++++++++++++++++-- src/games/ai-story/tools/messages.ts | 2 +- 12 files changed, 168 insertions(+), 43 deletions(-) create mode 100644 src/games/ai-story/assets/pwa_icon.png diff --git a/build/html.ts b/build/html.ts index fa1c496..c6d917d 100644 --- a/build/html.ts +++ b/build/html.ts @@ -70,7 +70,7 @@ export async function buildHTML(game: string, { production = false, mobile = fal } let manifest = ''; if (production && !local) { - const pwaIcon = `data:;base64,${await b64(pwaIconFile)}`; + const pwaIcon = `data:image/png;base64,${await b64(pwaIconFile)}`; const publishURL = process.env.PUBLISH_URL ? `${process.env.PUBLISH_URL}${game}` : '.'; const manifestJSON = JSON.stringify({ name: title, @@ -87,7 +87,7 @@ export async function buildHTML(game: string, { production = false, mobile = fal type: 'image/png' }] }); - manifest = ``; + manifest = ``; } let script = await scriptFile.text(); const inits = new Set(); diff --git a/src/games/ai-story/assets/favicon.ico b/src/games/ai-story/assets/favicon.ico index 057ea8e950d3a65d5c90ad0f216dc320e3518710..f18ba1e5d035391598aa6e37c20cf436413170b0 100644 GIT binary patch literal 4286 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 literal 3262 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 { .then(template => { if (template) { setModelTemplate(template); - setInstruct(template); } }); } @@ -109,15 +108,18 @@ export const ConnectionEditor = ({ connection, setConnection }: IProps) => { } - {Object.entries(Instruct).map(([label, value]) => ( + {Object.entries(INSTRUCTS).map(([label, value]) => ( ))} - {instruct !== modelTemplate && - - } + {instruct !== modelTemplate + && !Object.values(INSTRUCTS).includes(instruct) + && + + + } {connection.type === 'kobold' && { - const { contextLength, promptTokens, modelName, spentKudos } = useContext(LLMContext); + const { contextLength, promptTokens, modelName, spentKudos, hasToolCalls } = useContext(LLMContext); const { messages, connection, @@ -102,11 +102,11 @@ export const Header = () => {
- {modelName} + {modelName} 📃{promptTokens}/{contextLength} {connection.type === 'horde' ? <> - 💲{spentKudos} - 💰{totalSpentKudos} + 💲{spentKudos} + 💰{totalSpentKudos} : null}
@@ -181,7 +181,10 @@ export const Header = () => {  Enable summarization
-

Instruct template

+

+ Instruct template + {hasToolCalls && (tool calls)} +

diff --git a/src/games/ai-story/components/message/message.tsx b/src/games/ai-story/components/message/message.tsx index 1e4f957..0d5eeb3 100644 --- a/src/games/ai-story/components/message/message.tsx +++ b/src/games/ai-story/components/message/message.tsx @@ -33,7 +33,7 @@ export const Message = ({ message, index, isLastUser, isLastAssistant }: IProps) }, [content]); const handleSaveEdit = useCallback(() => { - editMessage(index, editedMessage.trim(), cost); + editMessage(index, editedMessage.trim(), 0); editSummary(index, '', 0); setEditing(false); }, [editMessage, editSummary, index, editedMessage, cost]); diff --git a/src/games/ai-story/contexts/llm.tsx b/src/games/ai-story/contexts/llm.tsx index 942ef66..fd4b6c1 100644 --- a/src/games/ai-story/contexts/llm.tsx +++ b/src/games/ai-story/contexts/llm.tsx @@ -227,7 +227,6 @@ export const LLMContextProvider = ({ children }: { children?: any }) => { let messageId = messages.length - 1; let text = ''; - let cost = 0; const { prompt, isRegen } = await actions.compilePrompt(messages, { continueLast }); @@ -242,14 +241,13 @@ export const LLMContextProvider = ({ children }: { children?: any }) => { editSummary(messageId, 'Generating...', 0); for await (const chunk of actions.generate(prompt)) { text += chunk.text; - cost += chunk.cost; setPromptTokens(promptTokens + approximateTokens(text)); - editMessage(messageId, text.trim(), cost); + editMessage(messageId, text.trim(), chunk.cost); } generating.setFalse(); text = MessageTools.trimSentence(text); - editMessage(messageId, text, cost); + editMessage(messageId, text, 0); editSummary(messageId, '', 0); MessageTools.playReady(); diff --git a/src/games/ai-story/contexts/state.tsx b/src/games/ai-story/contexts/state.tsx index 0138484..8a402dd 100644 --- a/src/games/ai-story/contexts/state.tsx +++ b/src/games/ai-story/contexts/state.tsx @@ -6,6 +6,7 @@ import { type IConnection } from "../tools/connection"; import { loadObject, saveObject } from "../tools/storage"; import { useInputCallback } from "@common/hooks/useInputCallback"; import { callUpdater, throttle } from "@common/utils"; +import { Huggingface } from "../tools/huggingface"; interface IStory { lore: string; @@ -96,32 +97,39 @@ interface IActions { const SAVE_KEY = 'ai_game_save_state'; export const DEFAULT_STORY = 'default'; -export enum Instruct { - CHATML = `{% for message in messages %}{{'<|im_start|>' + message['role'] + '\\n\\n' + message['content'] + '<|im_end|>' + '\\n'}}{% endfor %}{% if add_generation_prompt %}{{ '<|im_start|>assistant\\n\\n' }}{% endif %}`, +const INSTRUCT_MISTRAL = Huggingface.formatTemplate(`{% if messages[0]['role'] == 'system' %}{% set system_message = messages[0]['content'] %}{% set loop_messages = messages[1:] %}{% else %}{% set loop_messages = messages %}{% endif %}{% for message in loop_messages %}{% if message['role'] == 'user' %}{% if loop.first and system_message is defined %}{{ ' [INST] ' + system_message + '\n\n' + message['content'] + ' [/INST]' }}{% else %}{{ ' [INST] ' + message['content'] + ' [/INST]' }}{% endif %}{% elif message['role'] == 'assistant' %}{{ ' ' + message['content'] + '' }}{% endif %}{% endfor %}`); - LLAMA = `{% for message in messages %}{% set content = '<|start_header_id|>' + message['role'] + '<|end_header_id|>\\n\\n' + message['content'] | trim + '<|eot_id|>' %}{{ content }}{% endfor %}{% if add_generation_prompt %}{{ '<|start_header_id|>assistant<|end_header_id|>\\n\\n' }}{% endif %}`, +const INSTRUCT_CHATML = Huggingface.formatTemplate(`{% for message in messages %}{{ '<|im_start|>' + message['role'] + '\n\n' + message['content'] + '<|im_end|>' + '\n' }}{% endfor %}{% if add_generation_prompt %}{{ '<|im_start|>assistant\n\n' }}{% endif %}`); - MISTRAL = `{%- if messages[0]['role'] == 'system' %}{%- set system_message = messages[0]['content'] %}{%- set loop_messages = messages[1:] %}{%- else %}{%- set loop_messages = messages %}{%- endif %}{%- for message in loop_messages %}{%- if message['role'] == 'user' %}{%- if loop.first and system_message is defined %}{{- ' [INST] ' + system_message + '\\n\\n' + message['content'] + ' [/INST]' }}{%- else %}{{- ' [INST] ' + message['content'] + ' [/INST]' }}{%- endif %}{%- elif message['role'] == 'assistant' %}{{- ' ' + message['content'] + ''}}{%- endif %}{%- endfor %}`, +const INSTRUCT_LLAMA = Huggingface.formatTemplate(`{% for message in messages %}{{ '<|start_header_id|>' + message['role'] + '<|end_header_id|>\n\n' + message['content'] | trim + '<|eot_id|>' }}{% endfor %}{% if add_generation_prompt %}{{ '<|start_header_id|>assistant<|end_header_id|>\n\n' }}{% endif %}`); - METHARME = `{% for message in messages %}{% if message['role'] == 'system' and message['content'] %}{{'<|system|>' + message['content'] }}{% elif message['role'] == 'user' %}{{'<|user|>' + message['content'] }}{% elif message['role'] == 'assistant' %}{{'<|model|>' + message['content'] }}{% endif %}{% endfor %}{% if add_generation_prompt %}{{ '<|model|>' }}{% endif %}`, +const INSTRUCT_ALPACA = Huggingface.formatTemplate(`{% for message in messages %}{% if message['role'] == 'system' and message['content'] %}{{ message['content'] + '\n\n' }}{% elif message['role'] == 'user' %}{{ '### Instruction:\n\n' + message['content'] + '\n\n' }}{% elif message['role'] == 'assistant' %}{{ '### Response:\n\n' + message['content'] + '\n\n' }}{% endif %}{% endfor %}{% if add_generation_prompt %}{{ '### Response:\n\n' }}{% endif %}`); - GEMMA = `{% for message in messages %}{% if (message['role'] == 'assistant') %}{% set role = 'model' %}{% else %}{% set role = message['role'] %}{% endif %}{{ '' + role + '\n' + message['content'] | trim + '\n' }}{% endfor %}{% if add_generation_prompt %}{{'model\n'}}{% endif %}`, +const INSTRUCT_METHARME = Huggingface.formatTemplate(`{% for message in messages %}{% if message['role'] == 'system' and message['content'] %}{{ '<|system|>' + message['content'] }}{% elif message['role'] == 'user' %}{{ '<|user|>' + message['content'] }}{% elif message['role'] == 'assistant' %}{{'<|model|>' + message['content'] }}{% endif %}{% endfor %}{% if add_generation_prompt %}{{ '<|model|>' }}{% endif %}`); - ALPACA = `{% for message in messages %}{% if message['role'] == 'system' and message['content'] %}{{ message['content'] + '\\n\\n'}}{% elif message['role'] == 'user' %}{{'### Instruction:\\n\\n' + message['content'] + '\\n\\n'}}{% elif message['role'] == 'assistant' %}{{'### Response:\\n\\n' + message['content'] + '\\n\\n'}}{% endif %}{% endfor %}{% if add_generation_prompt %}{{ '### Response:\\n\\n' }}{% endif %}`, -}; +const INSTRUCT_GEMMA = Huggingface.formatTemplate(`{% for message in messages %}{% if (message['role'] == 'assistant') %}{% set role = 'model' %}{% else %}{% set role = message['role'] %}{% endif %}{{ '' + role + '\n' + message['content'] | trim + '\n' }}{% endfor %}{% if add_generation_prompt %}{{ 'model\n' }}{% endif %}`); + +export const INSTRUCTS = { + 'Mistral': INSTRUCT_MISTRAL, + 'ChatML': INSTRUCT_CHATML, + 'LLama': INSTRUCT_LLAMA, + 'Alpaca': INSTRUCT_ALPACA, + 'Metharme': INSTRUCT_METHARME, + 'Gemma': INSTRUCT_GEMMA, +} const DEFAULT_CONTEXT: IContext = { currentConnection: 0, availableConnections: [{ type: 'kobold', url: 'http://localhost:5001', - instruct: Instruct.MISTRAL, + instruct: INSTRUCT_MISTRAL, }], input: '', systemPrompt: 'You are a creative writer. Write a story based on the world description below. Story should be adult and mature; and could include swearing, violence and unfairness. Portray characters realistically and stay in the lore.', stories: {}, currentStory: DEFAULT_STORY, - userPrompt: `{% if isStart -%} + userPrompt: Huggingface.formatTemplate(`{% if isStart -%} Write a novel using information above as a reference. {%- else -%} Continue the story forward. @@ -131,7 +139,7 @@ Continue the story forward. This is the description of what should happen next in your answer: {{ prompt | trim }} {% endif %} Remember that this story should be infinite and go forever. -Make sure to follow the world description and rules exactly. Avoid cliffhangers and pauses, be creative.`, +Make sure to follow the world description and rules exactly. Avoid cliffhangers and pauses, be creative.`), summarizePrompt: 'Summarize following text in one paragraph:\n\n{{ message }}\n\nAnswer with shortened text only.', summaryEnabled: true, bannedWords: [], diff --git a/src/games/ai-story/tools/huggingface.ts b/src/games/ai-story/tools/huggingface.ts index 8b0f49f..0b49f0b 100644 --- a/src/games/ai-story/tools/huggingface.ts +++ b/src/games/ai-story/tools/huggingface.ts @@ -110,6 +110,20 @@ export namespace Huggingface { }); if (fileResponse) { const maybeConfig = JSON.parse(await fileResponse.text()); + if (!hasField(maybeConfig, 'chat_template') || !maybeConfig.chat_template) { + console.log(`[huggingface] searching template in '${name}/chat_template.jinja'`); + const templateResponse = await hub.downloadFile({ + repo: name, + path: 'chat_template.jinja', + }).catch(() => null); + + if (templateResponse) { + const template = await templateResponse.text().catch(() => null); + if (template) { + maybeConfig.chat_template = template; + } + } + } if (isTokenizerConfig(maybeConfig)) { tokenizerConfig = maybeConfig; foundName = `${name}/tokenizer_config.json`; @@ -223,6 +237,110 @@ export namespace Huggingface { return text.includes(needle); } + export const minifyTemplate = (input: string, config?: TokenizerConfig) => { + let minified = input; + do { + input = minified; + minified = input.replace(/raise_exception\(('[^')]+'|"[^")]+")\)/g, `''`) + .replace(/(['"])\s*\+\s*bos_token/gi, `$1`) + .replace(/bos_token\s*\+\s*(['"])/gi, `$1`) + .replace(/(['"])\s*\+\s*eos_token/gi, `${config?.eos_token?.replace('$', '$$') ?? ''}$1`) + .replace(/eos_token\s*\+\s*(['"])/gi, `$1${config?.eos_token?.replace('$', '$$') ?? ''}`) + .replace(/\{#-?[^#]+-?#}/gi, '') + .replace(/\s*(\{[{%])-/gi, '$1') + .replace(/-([}%]\})\s*/gi, '$1') + .replace(/\{\{\s*(''|"")\s*\}\}/g, '') + .replace(/\s*\}\}\{\{\s*/, ' + ') + .replace(/\n+['"]/g, (match) => match.replace(/\n/gi, '\\n')) + .replace(/'\s*\+\s*'/g, '') + .replace(/"\s*\+\s*"/g, '') + .replace(/\{%\s*else\s*%\}\{%\s*endif\s*%\}/gi, '{% endif %}') + .replace(/\{%\s*elif[^}]+%\}\{%\s*endif\s*%\}/gi, '{% endif %}') + .replace(/\{%\s*if[^}]+%\}\{%\s*endif\s*%\}/gi, '') + .replaceAll('bos_token', `''`) + .replaceAll('eos_token', `'${config?.eos_token ?? ''}'`); + } while (minified !== input); + + return minified; + } + + export const formatTemplate = (input: string, config?: TokenizerConfig) => { + const minified = minifyTemplate(input, config); + + type ParserState = 'none' | 'open_brace' | 'block' | 'block_end' | 'quote' | 'escaped'; + let state: ParserState = 'none'; + let currentBlock = ''; + let blockStart = ''; + let quoteStart = ''; + let escaped = false; + + const blocks: string[] = []; + + for (const ch of minified) { + currentBlock += ch; + if (state === 'none') { + if (ch === '{') { + state = 'open_brace'; + } + } else if (state === 'open_brace') { + if (ch === '{' || ch === '%') { + blockStart = ch; + state = 'block'; + currentBlock += '-'; + } else { + state = 'none'; + } + } else if (state === 'block') { + if (ch === '"' || ch === "'") { + quoteStart = ch; + state = 'quote'; + } else if (ch === blockStart || blockStart === '{' && ch === '}') { + currentBlock = currentBlock.slice(-1) + '-' + ch; + state = 'block_end'; + } + } else if (state === 'block_end') { + if (ch === '}') { + state = 'none'; + blocks.push(currentBlock); + currentBlock = ''; + } else { + state = 'block'; + } + } else if (state === 'quote') { + if (!escaped && ch === quoteStart) { + state = 'block'; + } else if (!escaped && ch === '\\') { + escaped = true; + } else { + escaped = false; + } + } + } + if (currentBlock) { + blocks.push(currentBlock); + } + let indent = ''; + for (let i = 0; i < blocks.length; i++) { + const line = blocks[i]; + const content = line.slice(3).trim(); + if (content.startsWith('if ') || content.startsWith('for ')) { + blocks[i] = indent + line; + indent += ' '; + } else if (content.startsWith('else ') || content.startsWith('elif ')) { + indent = indent.slice(2); + blocks[i] = indent + line; + indent += ' '; + } else if (content.startsWith("end")) { + indent = indent.slice(2); + blocks[i] = indent + line; + } else { + blocks[i] = indent + line; + } + } + + return blocks.filter(b => b.trim()).join('\n'); + } + export const findModelTemplate = async (modelName: string): Promise => { modelName = normalizeModel(modelName); if (!modelName) return ''; @@ -235,18 +353,7 @@ export namespace Huggingface { const config = await loadHuggingfaceTokenizerConfig(modelName); if (config?.chat_template?.trim()) { - template = config.chat_template.trim() - .replace(/raise_exception\(('[^')]+'|"[^")]+")\)/g, `''`) - .replaceAll('eos_token', `'${config.eos_token ?? ''}'`) - .replaceAll('bos_token', `''`) - .replace(/\{\{ ?(''|"") ?\}\}/g, '') - .replace(/\n'/g, `\\n'`) - .replace(/\n"/g, `\\n"`) - .replace(/'\s*\+\s*'/g, '') - .replace(/"\s*\+\s*"/g, '') - .replace(/\{%\s*else\s*%\}\{%\s*endif\s*%\}/gi, '{% endif %}') - .replace(/\{%\s*elif[^}]+%\}\{%\s*endif\s*%\}/gi, '{% endif %}') - .replace(/\{%\s*if[^}]+%\}\{%\s*endif\s*%\}/gi, ''); + template = formatTemplate(config.chat_template, config); } } diff --git a/src/games/ai-story/tools/messages.ts b/src/games/ai-story/tools/messages.ts index 1e482d2..a54fcff 100644 --- a/src/games/ai-story/tools/messages.ts +++ b/src/games/ai-story/tools/messages.ts @@ -103,7 +103,7 @@ export namespace MessageTools { (m, i) => ({ ...m, swipes: i === index - ? m.swipes.map((s, si) => (si === m.currentSwipe ? { ...s, ...update, cost: s.cost + cost } : s)) + ? m.swipes.map((s, si) => (si === m.currentSwipe ? { ...s, ...update, cost: (s.cost || 0) + cost } : s)) : m.swipes }) )