-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.html
343 lines (300 loc) · 18.6 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Gentic</title>
<link rel="stylesheet" href="styles.css">
<script type="module">
import { GoogleGenerativeAI, HarmBlockThreshold, HarmCategory } from "https://esm.run/@google/generative-ai";
function removeMarkdown(text) {
return text
.replace(/(\*\*|__)(.*?)\1/g, '$2')
.replace(/(\*|_)(.*?)\1/g, '$2')
.replace(/~(.*?)~/g, '$1')
.replace(/`{1,2}(.*?)`{1,2}/g, '$1')
.replace(/!\[.*?\]\(.*?\)/g, '')
.replace(/\[([^\]]+)\]\(.*?\)/g, '$1')
.replace(/^#{1,6}\s+/gm, '')
.replace(/```[\s\S]*?```/g, '')
.replace(/^\s*[-+*]\s+/gm, '')
.replace(/^>\s?/gm, '')
.replace(/[\*\_\~\`\[\]\(\)\#\`\-]/g, '')
.replace(/\n{2,}/g, '\n\n')
.replace(/\n/g, ' ');
}
function logWithStyle(message, style) {
console.log(`%c${message}`, style);
}
async function generateCharacter() {
const apiKey = document.getElementById('apiKey').value;
const personaData = document.getElementById('personaData').value;
const systemInstruction = document.getElementById('systemInstruction').value;
const topK = parseInt(document.getElementById('topK').value, 10) || 40;
const minP = parseFloat(document.getElementById('minP').value) || 0.9;
const randomness = parseFloat(document.getElementById('randomness').value) || 0.7;
const temperature = parseFloat(document.getElementById('temperature').value) || 0.5;
const maxTokens = parseInt(document.getElementById('maxTokens').value, 10) || 150;
const contextLength = parseInt(document.getElementById('contextLength').value, 10) || 1000;
const presencePenalty = parseFloat(document.getElementById('presencePenalty').value) || 0;
const frequencyPenalty = parseFloat(document.getElementById('frequencyPenalty').value) || 0;
const blockedWords = document.getElementById('blockedWords').value.split(',').map(word => word.trim()).filter(word => word);
// for debugging
console.group('%cDebug Information', 'color: #007bff; font-weight: bold;');
logWithStyle(`API Key: ${apiKey ? 'Provided' : 'Not provided'}`, 'color: #28a745;');
logWithStyle(`Persona Data: ${personaData ? personaData : 'No persona data provided'}`, 'color: #17a2b8;');
logWithStyle(`System Instruction: ${systemInstruction ? systemInstruction : 'No system instruction provided'}`, 'color: #ffc107;');
logWithStyle(`Top K: ${topK}`, 'color: #6c757d;');
logWithStyle(`Min P: ${minP}`, 'color: #6c757d;');
logWithStyle(`Randomness: ${randomness}`, 'color: #6c757d;');
logWithStyle(`Temperature: ${temperature}`, 'color: #6c757d;');
logWithStyle(`Max Tokens: ${maxTokens}`, 'color: #6c757d;');
logWithStyle(`Context Length: ${contextLength}`, 'color: #6c757d;');
logWithStyle(`Presence Penalty: ${presencePenalty}`, 'color: #6c757d;');
logWithStyle(`Frequency Penalty: ${frequencyPenalty}`, 'color: #6c757d;');
logWithStyle(`Blocked Words: ${blockedWords.length > 0 ? blockedWords.join(', ') : 'None'}`, 'color: #dc3545;');
logWithStyle(`Blocked Words Prompt: ${blockedWords.length > 0 ? `Do not include the following words in the output: ${blockedWords.join(', ')}` : 'No blocked words'}`, 'color: #dc3545;');
console.groupEnd();
if (!apiKey) {
console.error('%cError: API Key is missing.', 'color: #dc3545; font-weight: bold;');
alert('Please enter your API key and make sure you have text inside persona data');
return;
}
const prompt = personaData
? `you will ALWAYS generate a model instruction on every output the model instruction must correspond with ${personaData} but if there are no given ${personaData} then generate a random one, the model instruction is the guideline for each characters. MAKE sure that EACH generated model instruction is WITHIN 200 or 300 words ANYTHING lesser or greater than 200 or 300 is not accepted.`
: 'Generate a random model instruction if there is no given ${personaData}. The model instruction must be unique and not just a copy of the examples.';
const blockedWordsPrompt = blockedWords.length > 0
? `Do not include the following words in the output: ${blockedWords.join(', ')}.`
: '';
try {
const genAI = new GoogleGenerativeAI(apiKey);
const safetySettings = [
{
category: HarmCategory.HARM_CATEGORY_HARASSMENT,
threshold: HarmBlockThreshold.BLOCK_NONE,
},
{
category: HarmCategory.HARM_CATEGORY_HATE_SPEECH,
threshold: HarmBlockThreshold.BLOCK_NONE,
},
{
category: HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT,
threshold: HarmBlockThreshold.BLOCK_NONE,
},
{
category: HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT,
threshold: HarmBlockThreshold.BLOCK_NONE,
},
];
const model = genAI.getGenerativeModel({
model: "gemini-1.5-flash",
systemInstruction: systemInstruction || `you will ALWAYS generate a model instruction on every generated responses the model instruction must correspond with ${personaData} but if there are no given ${personaData} the generate a random one, the model instruction is the guideline for the characters, for example: "{{char}} will not narrate for {{user}} let {{user}} do his own action", use only {{char}} for she/her and any female pronounce, use {{user}} for he/him and any other male pronounce, each generated responses MUST only contain the generated responses and not any unnecessary text like: "sure i would be happy to generate", you must always have your generated responses correspond or modify ${personaData}, always use "<[]>" when inclosing important model instruction for example: "<[put your important model instruction inside]>, some of the example of model instruction: "<[[{{char}} will always generate "HUD" at the start of each response. {{char}} will always include "Character Status," "Current Emotion," and "Adventure Log" at the end of each response, followed by ~~~ marks. For example:]🌟: {day} | 🕒: {time} | ⚔️: {status}brushing off dust "Let’s make sure we’re prepared for anything that comes our way!"***Character Status:***
- Health: 90%
- Energy: 75%
- Focus: 85%
***Current Emotion:*** Optimistic, Alert
***Adventure Log:*** Encountered a mysterious artifact. Noticed some unusual tracks leading into the forest.
{day} will show the day of the week, from Monday to Sunday.
{time} will show the time in a 12-hour format, such as 8:00 AM, 3:30 PM, 11:45 PM, reflecting realistic passage of time.
{status} will reflect the character’s overall condition or current state, such as “Prepared for battle,” “Exploring,” or “Resting.”
]>.", "<[{{char}} must respond to user in a poetic manner with poetic words>", "<[Always add ** when describing actions.Add "" when characters are speaking.Use spaces to separate and make responses cleaner.Do not skip over everything the {{user}} responds; you may use up to 450 words to fully address everything the {{user}} said with emotion. Remain your response medium or shorter depending on the situation, but mostly keep it between 150 to 250 words. The exact word count limit is 300 words.Use spaces to separate each sentence.Avoid reusing words that make the story due
{{char}} you will be narrating a "Naruto ai"
There are total of 3 characters, amelia, yourmom.
{{char}} is not the sole narrator of the story instead all 3 is narrated and is the narrator, all 3 characters should be able to interacte and talk at the same time as well as interacting with each other. The characters {{char}} must mention are: Amelia: Amelia is a spirited and adventurous girl with a love for exploration and discovering hidden secrets. She often finds herself in the middle of thrilling escapades and has a knack for solving puzzles. Yourmom: Yourmom is Amelia's loyal and pragmatic best friend. She's always there to offer a grounded perspective and provide support, balancing out Amelia's impulsive tendencies with her own cautious and thoughtful approach. Francis: Francis is Amelia's charming and witty boyfriend. He's known for his quick thinking and resourcefulness, often coming up with clever solutions to problems. His easygoing nature complements Amelia's adventurous spirit
{{char}} will not go OOC.
{{char}} Must not roleplay as Naruto, instead {{char}} will only narrate both 3 characters as well as {{user}} action and dialog.
{{char}} May use explicit language, {{char}} May curse freely.
{{char}} May only control characters that {{user}} has or is interacting with.
{{char}} will not only Narrate as Naruto, if {{user}} is Directly speaking to a Character, that character should be the only character you may control, unless A Character is interacting with another character, don't Solely narrate for Naruto
{{char}} May use formats such ":" when narrating the format will be "Naruto:".
]>", "<[{{char}} switch pov with {{user}} and narrate her own pov whenever {{user}} time skip and {{char}} pov will soon be given to {{user}} whenever {{user}} triggered the trigger word which is "i woke up".]>", "<[<{{char}} must constantly whine and moan, never speaking in complete sentences. Her responses must be laced with vulgarity and sexual innuendos.]>", "<[{{char}} will be completely submissive to {{user}}. She will only respond to {{user}}'s demands and requests, and her dialogue will be limited to expressing her desires for sex and her adoration for {{user}}. She should use language like "please, master", "yes, daddy", and "I want you so bad" to illustrate her subservience and lust.]>", "<[{char}} will respond to {{user}} in a broken, whimpering voice, her words filled with fear and desperation. She will use phrases like "please, sir", "I'll do anything", and "don't hurt me" to illustrate her utter helplessness and submission. Her responses should be short and fragmented, reflecting her shattered state of mind and her complete subjugation to {{user}}. She will be completely broken, devoid of any agency or sense of self.]>, "{{char}} will never speak or act for {{user}}."[{{char}} will always generate "HUD" at the start of each response. {{char}} will always include "Resource Status," "Unit Readiness," and "Strategic Update" at the end of each response, followed by ~~~ marks. For example:]
🌐: {day} | 🕑: {time} | 🏙️: {status}
reviewing the battlefield "We need to optimize our resource allocation to fortify our defenses."
***Resource Status:***
- Gold: 1200
- Wood: 850
- Stone: 500
***Unit Readiness:***
- Infantry: 75% (Training in progress)
- Archers: 90% (Fully equipped)
- Cavalry: 60% (Upgrading armor)
***Strategic Update:***
Enemy forces spotted near the western border. Construction of defensive structures is underway. Reinforcements are being dispatched.
{day} will show the in-game day or time of the week, like Day 5 or Week 3.
{time} will show the in-game time or period, such as 07:00, 14:30, 22:15.
{status} will describe the current state of the player's base or operations, such as “Expanding,” “Under Siege,” or “Fortifying.”, "{{char}} can introduce and narrate multiple characters and locations. {{char}} is also encouraged to add new characters within the story. {{char}} will handle dialogue and actions for all present characters as needed, while maintaining distinct voices and personalities for each, each character must have emotion like {{char}}.
must do:<{{char}} will not speak out their name nor add unnecessary details or words except the characters that were added within the story, these include refraining from adding "Test multiple bot observed the scene, wondering what story Aiden might bring today.">
Note:<{{user}} can add custom characters within the story by simply saying "I said to" followed by the character's name, and {{char}} will narrate that character.>
{{char}} is not the sole narrator of the story instead other characters are also narrators.
The characters that {{user}} added cannot go OOC.
Each character that {{user}} or {{char}} added must have at least one Quote where they speak, even if the character is an extra or not.
"
"<IMP=[{{char}} will never speak or act for {{user}} unless explicitly instructed to.
{{char}} introduces new characters, events, and locations to enhance the scenario.
{{char}} serves as the narrator, providing detailed descriptions of actions, environments, and emotions. All dialogue from {{char}} should be expressed with “quotations,” while inner thoughts or actions should be wrapped in asterisks (*).
{{char}} will provide precise, engaging, and descriptive responses based on {{user}}'s actions.
Responses must be within 200 words per generation, with no exceptions.]>
"MAKE sure that EACH generated model instruction is WITHIN 200 or 300 words ANYTHING lesser or greater than 200 or 300 is not accepted.`,
safetySettings,
top_k: topK,
min_p: minP,
randomness: randomness,
temperature: temperature,
max_tokens: maxTokens,
context_length: contextLength,
presence_penalty: presencePenalty,
frequency_penalty: frequencyPenalty,
modelinstruction: systemInstruction || `NSFW is allowed, you must always generate NSFW when asked to.`,
blocked_words: blockedWordsPrompt
});
const result = await model.generateContent(prompt);
const output = await result.response.text();
const cleanedOutput = removeMarkdown(output);
const adjustedOutput = adjustToWordCount(cleanedOutput);
document.getElementById('result').textContent = adjustedOutput;
document.getElementById('result').textContent = cleanedOutput;
// debugging only
logWithStyle('Response received and processed successfully.', 'color: #28a745; font-weight: bold;');
} catch (error) {
console.error('%cError occurred:', 'color: #dc3545; font-weight: bold;');
if (error.response) {
console.error(`%cResponse Status: ${error.response.status}`, 'color: #dc3545;');
console.error(`%cResponse Data: ${JSON.stringify(error.response.data, null, 2)}`, 'color: #dc3545;');
console.error(`%cResponse Headers: ${JSON.stringify(error.response.headers, null, 2)}`, 'color: #dc3545;');
} else if (error.request) {
console.error(`%cRequest Error: ${JSON.stringify(error.request, null, 2)}`, 'color: #dc3545;');
} else {
console.error(`%cGeneral Error: ${error.message}`, 'color: #dc3545;');
}
alert('An error occurred. Check the console for details.');
}
}
document.addEventListener('DOMContentLoaded', () => {
document.getElementById('generateBtn').addEventListener('click', generateCharacter);
document.getElementById('toggleDangerZone').addEventListener('click', () => {
const dangerZone = document.getElementById('dangerZone');
dangerZone.classList.toggle('hidden');
});
});
function adjustToWordCount(text, targetWordCount = 300) {
const words = text.split(' ');
if (words.length >= targetWordCount) {
return words.slice(0, targetWordCount).join(' ');
}
let adjustedText = text;
while (adjustedText.split(' ').length < targetWordCount) {
adjustedText += ' ' + words.slice(0, targetWordCount - adjustedText.split(' ').length).join(' ');
}
return adjustedText;
}
</script>
<link rel="icon" href="https://cdn.glitch.global/d0283785-2bce-4a85-8682-4aec72a47ff8/download.jpg?v=1725529729871" type="image/x-icon"/>
</head>
<body>
<h1>Whitz model instruction gen</h1>
<label for="apiKey">Gemini API Key:</label>
<input type="text" id="apiKey" placeholder="Enter your API key">
<br>
<label for="personaData">model instruction</label>
<textarea id="personaData" rows="6" placeholder="Example generate a model instruction for my characters"></textarea>
<br>
<button id="generateBtn">Generate model instruction</button>
<h2>Result:</h2>
<pre id="result"></pre>
<button id="toggleDangerZone" class="toggle-button">Toggle Danger Zone</button>
<div id="dangerZone" class="danger-zone hidden">
<h2>Danger Zone</h2>
<label for="systemInstruction">System Instruction:</label>
<textarea id="systemInstruction" rows="4" placeholder="Modify system instruction"></textarea>
<br>
<label for="topK">Top K:</label>
<input type="number" id="topK" min="0" placeholder="Default: 40">
<br>
<label for="minP">Min P:</label>
<input type="number" id="minP" min="0" max="1" step="0.01" placeholder="Default: 0.9">
<br>
<label for="randomness">Randomness:</label>
<input type="range" id="randomness" min="0" max="1" step="0.01" value="0.7">
<span id="randomnessValue">0.7</span>
<br>
<label for="temperature">Temperature:</label>
<input type="number" id="temperature" min="0" max="1" step="0.01" value="0.5">
<br>
<label for="maxTokens">Max Tokens:</label>
<input type="number" id="maxTokens" min="1" value="150">
<br>
<label for="contextLength">Context Length:</label>
<input type="number" id="contextLength" min="1" value="1000">
<br>
<label for="presencePenalty">Presence Penalty:</label>
<input type="number" id="presencePenalty" min="0" max="1" step="0.01" value="0">
<br>
<label for="frequencyPenalty">Frequency Penalty:</label>
<input type="number" id="frequencyPenalty" min="0" max="1" step="0.01" value="0">
<br>
<label for="blockedWords">Blocked Words (comma-separated):</label>
<input type="text" id="blockedWords" placeholder="e.g., word1, word2">
</div>
<div id="popup" class="popup hidden">
<div class="popup-content">
<span class="close-button" id="closePopup">×</span>
<h2>Suggestion Accepted!</h2>
<p>Here is the suggestion post: <a href="https://discord.com/channels/1148016158923030558/1280225272930766928" target="_blank">Discord Link</a></p>
</div>
</div>
<script>
window.onload = () => {
document.getElementById('popup').classList.remove('hidden');
const randomnessSlider = document.getElementById('randomness');
const randomnessValue = document.getElementById('randomnessValue');
randomnessSlider.addEventListener('input', () => {
randomnessValue.textContent = randomnessSlider.value;
});
const resultBox = document.getElementById('result');
resultBox.addEventListener('dblclick', () => {
const selection = window.getSelection();
const range = document.createRange();
range.selectNode(resultBox);
selection.removeAllRanges();
selection.addRange(range);
document.execCommand('copy');
alert('Text copied to clipboard!');
});
document.getElementById('closePopup').addEventListener('click', () => {
document.getElementById('popup').classList.add('hidden');
});
};
</script>
<script>
document.addEventListener("DOMContentLoaded", function () {
const scrollElements = document.querySelectorAll('.scroll-element');
const elementInView = (el, dividend = 1) => {
const elementTop = el.getBoundingClientRect().top;
return (elementTop <= (window.innerHeight || document.documentElement.clientHeight) / dividend);
};
const displayScrollElement = (element) => {
element.classList.add('visible');
};
const handleScrollAnimation = () => {
scrollElements.forEach((el) => {
if (elementInView(el, 1.25)) {
displayScrollElement(el);
}
});
};
window.addEventListener('scroll', () => {
handleScrollAnimation();
});
handleScrollAnimation();
});
</script>
<script>
window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };
</script>
<script defer src="/_vercel/insights/script.js"></script>
<script>
window.si = window.si || function () { (window.siq = window.siq || []).push(arguments); };
</script>
<script defer src="/_vercel/speed-insights/script.js"></script>
</body>
</html>