kwabs22 commited on
Commit
a69d738
1 Parent(s): ae6b3e0

Some changes and flie splitting

Browse files
app.py CHANGED
The diff for this file is too large to render. See raw diff
 
file_explorer_and_upload.py ADDED
@@ -0,0 +1,115 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import gradio as gr
3
+ import shutil
4
+ from PIL import Image
5
+ import tempfile
6
+ import json
7
+ import zipfile
8
+
9
+ # Set the directory where files will be saved
10
+ SAVE_DIR = os.path.abspath("saved_media") #make sure its the as media_folder Above
11
+
12
+ # Ensure the save directory exists
13
+ os.makedirs(SAVE_DIR, exist_ok=True)
14
+
15
+ # Define supported file extensions
16
+ SUPPORTED_EXTENSIONS = {
17
+ "image": [".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp"],
18
+ "audio": [".mp3", ".wav", ".ogg"],
19
+ "video": [".mp4", ".avi", ".mov", ".webm"]
20
+ }
21
+
22
+ def save_file(file):
23
+ if file is None:
24
+ return "No file uploaded.", gr.update()
25
+
26
+ try:
27
+ # Get the original filename and extension
28
+ original_filename = os.path.basename(file.name)
29
+ _, extension = os.path.splitext(original_filename)
30
+
31
+ # Check if the file extension is supported
32
+ if not any(extension.lower() in exts for exts in SUPPORTED_EXTENSIONS.values()):
33
+ return f"Unsupported file type: {extension}", gr.update()
34
+
35
+ # Create a unique filename to avoid overwriting
36
+ base_name = os.path.splitext(original_filename)[0]
37
+ counter = 1
38
+ new_filename = f"{base_name}{extension}"
39
+ while os.path.exists(os.path.join(SAVE_DIR, new_filename)):
40
+ new_filename = f"{base_name}_{counter}{extension}"
41
+ counter += 1
42
+
43
+ # Copy the file from the temporary location to our save directory
44
+ dest_path = os.path.join(SAVE_DIR, new_filename)
45
+ shutil.copy2(file.name, dest_path)
46
+
47
+ # Return success message and updated FileExplorer
48
+ return f"File saved as {SAVE_DIR}/{new_filename}", gr.update(value=SAVE_DIR), gr.update(value=None)
49
+ except Exception as e:
50
+ return f"Error saving file: {str(e)}", gr.update(value=SAVE_DIR), gr.update()
51
+
52
+ def view_file(file_path):
53
+ if not file_path:
54
+ return None, None, None, "No file selected."
55
+
56
+ try:
57
+ full_path = os.path.join(SAVE_DIR, file_path)
58
+ _, extension = os.path.splitext(full_path)
59
+ extension = extension.lower()
60
+
61
+ if extension in SUPPORTED_EXTENSIONS["image"]:
62
+ return Image.open(full_path), None, None, None
63
+ elif extension in SUPPORTED_EXTENSIONS["audio"]:
64
+ return None, full_path, None, None
65
+ elif extension in SUPPORTED_EXTENSIONS["video"]:
66
+ return None, None, full_path, None
67
+ else:
68
+ return None, None, None, f"Unsupported file type: {extension}"
69
+ except Exception as e:
70
+ return None, None, None, f"Error viewing file: {str(e)}"
71
+
72
+ def refresh_file_explorer():
73
+ return gr.update()
74
+
75
+ def import_config_with_media(zip_path):
76
+ global SAVE_DIR
77
+ target_folder = SAVE_DIR
78
+ """
79
+ Import the config JSON and media files from a zip file.
80
+ Extract only the media files that don't already exist in the target folder.
81
+
82
+ :param zip_path: Path to the zip file containing the config and media files
83
+ :param target_folder: Path to the folder where media files should be extracted
84
+ :return: Tuple containing the loaded config (as a dictionary) and a list of newly extracted files
85
+ """
86
+ config = None
87
+ extracted_files = []
88
+
89
+ with tempfile.TemporaryDirectory() as temp_dir:
90
+ # Extract all files to a temporary directory
91
+ with zipfile.ZipFile(zip_path, 'r') as zip_ref:
92
+ zip_ref.extractall(temp_dir)
93
+
94
+ # Load the config
95
+ config_path = os.path.join(temp_dir, 'config.json')
96
+ if os.path.exists(config_path):
97
+ with open(config_path, 'r') as f:
98
+ config = json.load(f)
99
+ else:
100
+ raise FileNotFoundError("config.json not found in the zip file")
101
+
102
+ # Create the target folder if it doesn't exist
103
+ os.makedirs(target_folder, exist_ok=True)
104
+
105
+ # Copy media files that don't already exist in the target folder
106
+ for root, _, files in os.walk(temp_dir):
107
+ for file in files:
108
+ if file != 'config.json':
109
+ src_path = os.path.join(root, file)
110
+ dst_path = os.path.join(target_folder, file)
111
+ if not os.path.exists(dst_path):
112
+ shutil.copy2(src_path, dst_path)
113
+ extracted_files.append(file)
114
+
115
+ return config, extracted_files
jsconfig_idea_support.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #importing default_config from relatively_constant_variables (app.py)
2
+
3
+ # Helper functions to dynamically add items
4
+ def add_inventory_item(inventory_items, type, name, description):
5
+ new_item = {"type": type, "name": name, "description": description}
6
+ inventory_items.append(new_item)
7
+ return inventory_items
8
+
9
+ def add_skill(skills_items, branch, name, learned):
10
+ new_skill = {"branch": branch, "name": name, "learned": learned == 'True'}
11
+ skills_items.append(new_skill)
12
+ return skills_items
13
+
14
+ def add_objective(objectives_items, id, name, complete):
15
+ new_objective = {"id": id, "name": name, "complete": complete == 'True'}
16
+ objectives_items.append(new_objective)
17
+ return objectives_items
18
+
19
+ def add_target(targets_items, name, x, y, collisionType, collisiontext):
20
+ new_target = {"name": name, "x": int(x), "y": int(y), "collisionType": collisionType, "collisiontext": collisiontext}
21
+ targets_items.append(new_target)
22
+ return targets_items
leveraging_machine_learning.py ADDED
@@ -0,0 +1,338 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from transformers import AutoModelForCausalLM, AutoTokenizer, TextIteratorStreamer
3
+ import gc
4
+ import sys
5
+ from diffusers import FluxPipeline
6
+ import time
7
+ from sentence_transformers import SentenceTransformer
8
+ import psutil
9
+ import json
10
+ import spaces
11
+ from threading import Thread
12
+ #-----------------
13
+ from relatively_constant_variables import knowledge_base
14
+
15
+ # Initialize the zero tensor on CUDA
16
+ zero = torch.Tensor([0]).cuda()
17
+ print(zero.device) # This will print 'cpu' outside the @spaces.GPU decorated function
18
+
19
+ modelnames = ["stvlynn/Gemma-2-2b-Chinese-it", "nbeerbower/mistral-nemo-wissenschaft-12B", "princeton-nlp/gemma-2-9b-it-SimPO", "cognitivecomputations/dolphin-2.9.3-mistral-7B-32k", "01-ai/Yi-Coder-9B-Chat", "ArliAI/Llama-3.1-8B-ArliAI-RPMax-v1.1", "ArliAI/Phi-3.5-mini-3.8B-ArliAI-RPMax-v1.1",
20
+ "Qwen/Qwen2.5-7B-Instruct", "Qwen/Qwen2-0.5B-Instruct", "Qwen/Qwen2-1.5B-Instruct", "Qwen/Qwen2-7B-Instruct", "Qwen/Qwen1.5-MoE-A2.7B-Chat", "HuggingFaceTB/SmolLM-135M-Instruct", "microsoft/Phi-3-mini-4k-instruct", "Groq/Llama-3-Groq-8B-Tool-Use", "hugging-quants/Meta-Llama-3.1-8B-Instruct-BNB-NF4",
21
+ "SpectraSuite/TriLM_3.9B_Unpacked", "h2oai/h2o-danube3-500m-chat", "OuteAI/Lite-Mistral-150M-v2-Instruct", "Zyphra/Zamba2-1.2B", "anthracite-org/magnum-v2-4b", ]
22
+
23
+ imagemodelnames = ["black-forest-labs/FLUX.1-schnell"]
24
+
25
+ current_model_index = 0
26
+ current_image_model_index = 0
27
+ modelname = modelnames[current_model_index]
28
+ imagemodelname = imagemodelnames[current_image_model_index]
29
+ lastmodelnameinloadfunction = None
30
+ lastimagemodelnameinloadfunction = None
31
+
32
+ # Load the embedding model
33
+ embedding_model = SentenceTransformer('all-MiniLM-L6-v2')
34
+
35
+ # Initialize model and tokenizer as global variables
36
+ model = None
37
+ tokenizer = None
38
+ flux_pipe = None
39
+
40
+ # Dictionary to store loaded models
41
+ loaded_models = {}
42
+
43
+ def get_size_str(bytes):
44
+ for unit in ['B', 'KB', 'MB', 'GB', 'TB']:
45
+ if bytes < 1024:
46
+ return f"{bytes:.2f} {unit}"
47
+ bytes /= 1024
48
+
49
+ def load_model(model_name):
50
+ global model, tokenizer, lastmodelnameinloadfunction, loaded_models
51
+
52
+ print(f"Loading model and tokenizer: {model_name}")
53
+
54
+ # Record initial GPU memory usage
55
+ initial_memory = torch.cuda.memory_allocated()
56
+
57
+ # Clear old model and tokenizer if they exist
58
+ if 'model' in globals() and model is not None:
59
+ model = None
60
+ if 'tokenizer' in globals() and tokenizer is not None:
61
+ tokenizer = None
62
+
63
+ torch.cuda.empty_cache()
64
+ gc.collect()
65
+
66
+ model = AutoModelForCausalLM.from_pretrained(
67
+ model_name,
68
+ torch_dtype="auto",
69
+ device_map="auto"
70
+ )
71
+ tokenizer = AutoTokenizer.from_pretrained(model_name)
72
+ model_size = sum(p.numel() * p.element_size() for p in model.parameters())
73
+ tokenizer_size = sum(sys.getsizeof(v) for v in tokenizer.__dict__.values())
74
+ loaded_models[model_name] = (model, tokenizer)
75
+
76
+ # Calculate memory usage
77
+ final_memory = torch.cuda.memory_allocated()
78
+ memory_used = final_memory - initial_memory
79
+
80
+ loaded_models[model_name] = [str(time.time()), memory_used]
81
+
82
+ lastmodelnameinloadfunction = (model_name, model_size, tokenizer_size)
83
+ print(f"Model and tokenizer {model_name} loaded successfully")
84
+ print(f"Model size: {get_size_str(model_size)}")
85
+ print(f"Tokenizer size: {get_size_str(tokenizer_size)}")
86
+ print(f"GPU memory used: {get_size_str(memory_used)}")
87
+
88
+ return (f"Model and tokenizer {model_name} loaded successfully. "
89
+ f"Model size: {get_size_str(model_size)}, "
90
+ f"Tokenizer size: {get_size_str(tokenizer_size)}, "
91
+ f"GPU memory used: {get_size_str(memory_used)}")
92
+
93
+ def load_image_model(imagemodelname):
94
+ global flux_pipe, lastimagemodelnameinloadfunction, loaded_models
95
+
96
+ print(f"Loading image model: {imagemodelname}")
97
+
98
+ # Record initial GPU memory usage
99
+ initial_memory = torch.cuda.memory_allocated()
100
+
101
+ if 'flux_pipe' in globals() and flux_pipe is not None:
102
+ flux_pipe = None
103
+
104
+ torch.cuda.empty_cache()
105
+ gc.collect()
106
+
107
+ flux_pipe = FluxPipeline.from_pretrained(imagemodelname, torch_dtype=torch.bfloat16)
108
+ flux_pipe.enable_model_cpu_offload()
109
+ model_size = sum(p.numel() * p.element_size() for p in flux_pipe.transformer.parameters())
110
+ #tokenizer_size = 0 # FLUX doesn't use a separate tokenizer
111
+ loaded_models[imagemodelname] = flux_pipe
112
+
113
+ # Calculate memory usage
114
+ final_memory = torch.cuda.memory_allocated()
115
+ memory_used = final_memory - initial_memory
116
+
117
+ loaded_models[imagemodelname] = [str(time.time()), memory_used]
118
+
119
+ lastimagemodelnameinloadfunction = (imagemodelname, model_size) #, tokenizer_size)
120
+ print(f"Model and tokenizer {imagemodelname} loaded successfully")
121
+ print(f"Model size: {get_size_str(model_size)}")
122
+ #print(f"Tokenizer size: {get_size_str(tokenizer_size)}")
123
+ print(f"GPU memory used: {get_size_str(memory_used)}")
124
+
125
+ return (f"Model and tokenizer {imagemodelname} loaded successfully. "
126
+ f"Model size: {get_size_str(model_size)}, "
127
+ #f"Tokenizer size: {get_size_str(tokenizer_size)}, "
128
+ f"GPU memory used: {get_size_str(memory_used)}")
129
+
130
+
131
+ def clear_all_models():
132
+ global model, tokenizer, flux_pipe, loaded_models
133
+ for model_name, model_obj in loaded_models.items():
134
+ if isinstance(model_obj, tuple):
135
+ model_obj[0].to('cpu')
136
+ del model_obj[0]
137
+ del model_obj[1]
138
+ else:
139
+ model_obj.to('cpu')
140
+ del model_obj
141
+ model = None
142
+ tokenizer = None
143
+ flux_pipe = None
144
+ loaded_models.clear()
145
+ torch.cuda.empty_cache()
146
+ gc.collect()
147
+ return "All models cleared from memory."
148
+
149
+ def load_model_list(model_list):
150
+ messages = []
151
+ for model_name in model_list:
152
+ message = load_model(model_name)
153
+ messages.append(message)
154
+ return "\n".join(messages)
155
+
156
+ def loaded_model_list():
157
+ global loaded_models
158
+ return loaded_models
159
+
160
+
161
+ # Initial model load
162
+ load_model(modelname)
163
+ load_image_model(imagemodelname)
164
+
165
+ # Create embeddings for the knowledge base
166
+ knowledge_base_embeddings = embedding_model.encode([doc["content"] for doc in knowledge_base])
167
+
168
+ def retrieve(query, k=2):
169
+ query_embedding = embedding_model.encode([query])
170
+ similarities = torch.nn.functional.cosine_similarity(torch.tensor(query_embedding), torch.tensor(knowledge_base_embeddings))
171
+ top_k_indices = similarities.argsort(descending=True)[:k]
172
+ return [(knowledge_base[i]["content"], knowledge_base[i]["id"]) for i in top_k_indices]
173
+
174
+ def get_ram_usage():
175
+ ram = psutil.virtual_memory()
176
+ return f"RAM Usage: {ram.percent:.2f}%, Available: {ram.available / (1024 ** 3):.2f}GB, Total: {ram.total / (1024 ** 3):.2f}GB"
177
+
178
+ # Global dictionary to store outputs
179
+ output_dict = {}
180
+
181
+ def empty_output_dict():
182
+ global output_dict
183
+ output_dict = {}
184
+ print("Output dictionary has been emptied.")
185
+
186
+ def get_model_details(model):
187
+ return {
188
+ "name": model.config.name_or_path,
189
+ "architecture": model.config.architectures[0] if model.config.architectures else "Unknown",
190
+ "num_parameters": sum(p.numel() for p in model.parameters()),
191
+ }
192
+
193
+ def get_tokenizer_details(tokenizer):
194
+ return {
195
+ "name": tokenizer.__class__.__name__,
196
+ "vocab_size": tokenizer.vocab_size,
197
+ "model_max_length": tokenizer.model_max_length,
198
+ }
199
+
200
+ @spaces.GPU
201
+ def generate_response(prompt, use_rag, stream=False):
202
+ global output_dict, model, tokenizer
203
+
204
+ print(zero.device) # This will print 'cuda:0' inside the @spaces.GPU decorated function
205
+ torch.cuda.empty_cache()
206
+ print(dir(model))
207
+
208
+ if use_rag:
209
+ retrieved_docs = retrieve(prompt)
210
+ context = " ".join([doc for doc, _ in retrieved_docs])
211
+ doc_ids = [doc_id for _, doc_id in retrieved_docs]
212
+ full_prompt = f"Context: {context}\nQuestion: {prompt}\nAnswer:"
213
+ else:
214
+ full_prompt = prompt
215
+ doc_ids = None
216
+ messages = [
217
+ {"role": "system", "content": "You are a helpful assistant."},
218
+ {"role": "user", "content": full_prompt}
219
+ ]
220
+ text = tokenizer.apply_chat_template(
221
+ messages,
222
+ tokenize=False,
223
+ add_generation_prompt=True
224
+ )
225
+ model_inputs = tokenizer([text], return_tensors="pt").to(zero.device)
226
+ start_time = time.time()
227
+ total_tokens = 0
228
+
229
+ print(output_dict)
230
+ output_key = f"output_{len(output_dict) + 1}"
231
+ print(output_key)
232
+ output_dict[output_key] = {
233
+ "input_prompt": prompt,
234
+ "full_prompt": full_prompt,
235
+ "use_rag": use_rag,
236
+ "generated_text": "",
237
+ "tokens_per_second": 0,
238
+ "ram_usage": "",
239
+ "doc_ids": doc_ids if doc_ids else "N/A",
240
+ "model_details": get_model_details(model),
241
+ "tokenizer_details": get_tokenizer_details(tokenizer),
242
+ "timestamp": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(start_time))
243
+ }
244
+ print(output_dict)
245
+
246
+ if stream:
247
+ streamer = TextIteratorStreamer(tokenizer, skip_special_tokens=True)
248
+ generation_kwargs = dict(
249
+ model_inputs,
250
+ streamer=streamer,
251
+ max_new_tokens=512,
252
+ temperature=0.7,
253
+ )
254
+ thread = Thread(target=model.generate, kwargs=generation_kwargs)
255
+ thread.start()
256
+ for new_text in streamer:
257
+ output_dict[output_key]["generated_text"] += new_text
258
+ total_tokens += 1
259
+ current_time = time.time()
260
+ tokens_per_second = total_tokens / (current_time - start_time)
261
+ ram_usage = get_ram_usage()
262
+ output_dict[output_key]["tokens_per_second"] = f"{tokens_per_second:.2f}"
263
+ output_dict[output_key]["ram_usage"] = ram_usage
264
+ yield (output_dict[output_key]["generated_text"],
265
+ output_dict[output_key]["tokens_per_second"],
266
+ output_dict[output_key]["ram_usage"],
267
+ output_dict[output_key]["doc_ids"])
268
+ else:
269
+ generated_ids = model.generate(
270
+ model_inputs.input_ids,
271
+ max_new_tokens=512
272
+ )
273
+ generated_ids = [
274
+ output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)
275
+ ]
276
+ response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]
277
+ total_tokens = len(generated_ids[0])
278
+ end_time = time.time()
279
+ tokens_per_second = total_tokens / (end_time - start_time)
280
+ ram_usage = get_ram_usage()
281
+
282
+ output_dict[output_key]["generated_text"] = response
283
+ output_dict[output_key]["tokens_per_second"] = f"{tokens_per_second:.2f}"
284
+ output_dict[output_key]["ram_usage"] = ram_usage
285
+ print(output_dict)
286
+
287
+ yield (output_dict[output_key]["generated_text"],
288
+ output_dict[output_key]["tokens_per_second"],
289
+ output_dict[output_key]["ram_usage"],
290
+ output_dict[output_key]["doc_ids"])
291
+
292
+ @spaces.GPU
293
+ def generate_image(prompt):
294
+ global output_dict, flux_pipe
295
+
296
+ print(dir(flux_pipe))
297
+
298
+ # Generate image using FLUX
299
+ image = flux_pipe(
300
+ prompt,
301
+ guidance_scale=0.0,
302
+ num_inference_steps=4,
303
+ max_sequence_length=256,
304
+ generator=torch.Generator("cpu").manual_seed(0)
305
+ ).images[0]
306
+ image_path = f"flux_output_{time.time()}.png"
307
+ print(image_path)
308
+ image.save(image_path)
309
+ ram_usage = get_ram_usage()
310
+ return image_path, ram_usage, image_path
311
+
312
+ def get_output_details(output_key):
313
+ if output_key in output_dict:
314
+ return output_dict[output_key]
315
+ else:
316
+ return f"No output found for key: {output_key}"
317
+
318
+ # Update the switch_model function to return the load_model message
319
+ def switch_model(choice):
320
+ global modelname
321
+ modelname = choice
322
+ load_message = load_model(modelname)
323
+ return load_message, f"Current model: {modelname}"
324
+
325
+ # Update the model_change_handler function
326
+ def model_change_handler(choice):
327
+ message, current_model = switch_model(choice)
328
+ return message, current_model, message # Use the same message for both outputs
329
+
330
+ def format_output_dict():
331
+ global output_dict
332
+ formatted_output = ""
333
+ for key, value in output_dict.items():
334
+ formatted_output += f"Key: {key}\n"
335
+ formatted_output += json.dumps(value, indent=2)
336
+ formatted_output += "\n\n"
337
+ print(formatted_output)
338
+ return formatted_output
my_text_game_engine_attempt.py ADDED
@@ -0,0 +1,285 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import json
3
+ import os
4
+ import tempfile
5
+ import shutil
6
+ import zipfile
7
+ from relatively_constant_variables import finished_product_demo, all_states
8
+
9
+ class Player:
10
+ def __init__(self):
11
+ self.inventory = []
12
+ self.money = 20
13
+ self.knowledge = {}
14
+
15
+ def add_item(self, item):
16
+ self.inventory.append(item)
17
+
18
+ def has_item(self, item):
19
+ return item in self.inventory
20
+
21
+ def update_knowledge(self, topic):
22
+ self.knowledge[topic] = True
23
+
24
+ class GameSession:
25
+ def __init__(self, starting_location='village', starting_state='start'):
26
+ self.player = Player()
27
+ self.current_location = starting_location
28
+ self.current_state = starting_state
29
+ self.game_log = []
30
+
31
+ def make_choice(self, choice_index):
32
+ state = all_states[self.current_location][self.current_state]
33
+ if 0 <= choice_index < len(state['choices']):
34
+ choice = state['choices'][choice_index]
35
+ next_state = state['transitions'][choice]
36
+
37
+ self.game_log.append(f"You chose: {choice}")
38
+ self.game_log.append(state['description'])
39
+
40
+ if 'consequences' in state and choice in state['consequences']:
41
+ if state['consequences'][choice]:
42
+ state['consequences'][choice](self.player)
43
+ else:
44
+ # Handle empty consequence, e.g., log a message or provide a default action
45
+ print(f"No consequence for choice: {choice}")
46
+ # You can add any default action here if needed
47
+
48
+ if '_' in next_state:
49
+ self.current_location, self.current_state = next_state.split('_')
50
+ else:
51
+ self.current_state = next_state
52
+
53
+ return self.get_current_state_info()
54
+ else:
55
+ return "Invalid choice. Please try again."
56
+
57
+ def get_current_state_info(self):
58
+ state = all_states[self.current_location][self.current_state]
59
+ choices = [f"{idx + 1}. {choice}" for idx, choice in enumerate(state['choices'])]
60
+ return state['description'], choices, "\n".join(self.game_log)
61
+
62
+ def get_current_state_media(self):
63
+ media = all_states[self.current_location][self.current_state]['media']
64
+ return media
65
+
66
+ def start_game(starting_location='village', starting_state='start', new_states=all_states):
67
+ global all_states
68
+ game_session = GameSession(starting_location, starting_state)
69
+ description, choices, game_log = game_session.get_current_state_info()
70
+ all_states = new_states
71
+ return description, choices, game_log, game_session
72
+
73
+ def make_choice(choice, game_session, with_media=False): #Calls the nested make choice function in the game session class
74
+ if not choice:
75
+ description, choices, game_log = game_session.get_current_state_info()
76
+ return description, choices, "Please select a choice before proceeding.", game_session
77
+
78
+ choice_index = int(choice.split('.')[0]) - 1
79
+ result = game_session.make_choice(choice_index)
80
+
81
+ if with_media:
82
+ media = game_session.get_current_state_media()
83
+ return result[0], gr.update(choices=result[1]), result[2], game_session, media
84
+ else:
85
+ return result[0], gr.update(choices=result[1]), result[2], game_session
86
+
87
+ def validate_transitions(all_states):
88
+ errors = []
89
+ for location, states in all_states.items():
90
+ for state_key, state in states.items():
91
+ for transition_key, transition_state in state['transitions'].items():
92
+ # Check if the transition is to another location
93
+ if transition_state in all_states:
94
+ trans_location, trans_state = transition_state, 'start' # Assuming 'start' state for new locations
95
+ elif '_' in transition_state:
96
+ trans_location, trans_state = transition_state.split('_')
97
+ else:
98
+ trans_location, trans_state = location, transition_state
99
+
100
+ # Validate the transition state
101
+ if trans_location not in all_states or trans_state not in all_states[trans_location]:
102
+ errors.append(f"Invalid transition from {location}.{state_key} to {trans_location}.{trans_state}")
103
+
104
+ return errors
105
+
106
+ path_errors = validate_transitions(all_states)
107
+ if path_errors:
108
+ for error in path_errors:
109
+ print(error)
110
+ else:
111
+ print("All transitions are valid.")
112
+
113
+
114
+ def load_game(custom_config=None, with_media=False):
115
+ global all_states
116
+ if not custom_config:
117
+ return gr.update(value="No custom configuration provided."), None, None, None, None, None, None
118
+
119
+ try:
120
+ new_config = json.loads(custom_config)
121
+ all_states = new_config
122
+
123
+ # Determine the starting location and state
124
+ starting_location = next(iter(all_states.keys()))
125
+ starting_state = next(iter(all_states[starting_location].keys()))
126
+ print(f"Starting location: {starting_location}, Starting state: {starting_state}")
127
+
128
+ game_session = GameSession(starting_location, starting_state)
129
+ description, choices, game_log = game_session.get_current_state_info()
130
+ new_path_errors = validate_transitions(all_states)
131
+
132
+ output_media = []
133
+
134
+ if with_media:
135
+ media_list = all_states[starting_location][starting_state].get('media', [])
136
+ print(f"Media list: {media_list}")
137
+
138
+ if media_list:
139
+ for media_path in media_list:
140
+ #media_component = create_media_component(media_path)
141
+ output_media.append(media_path)
142
+ print(f"Created {len(output_media)} media components")
143
+
144
+ success_message = f"Custom configuration loaded successfully!\n{new_path_errors}"
145
+ return (
146
+ gr.update(value=success_message),
147
+ game_log,
148
+ description,
149
+ gr.update(choices=choices),
150
+ gr.update(value=custom_config),
151
+ game_session,
152
+ output_media if with_media else None
153
+ )
154
+
155
+ except json.JSONDecodeError as e:
156
+ error_message = format_json_error(custom_config, e)
157
+ return gr.update(value=error_message), None, None, None, gr.update(value=custom_config), None, None
158
+
159
+ except Exception as e:
160
+ error_message = f"Error loading custom configuration: {str(e)}"
161
+ return gr.update(value=error_message), None, None, None, gr.update(value=custom_config), None, None
162
+
163
+ def load_game_edit_version(custom_config=None, with_media=False, custom_starting_location=None, custom_starting_state=None):
164
+ global all_states
165
+ if not custom_config:
166
+ return gr.update(value="No custom configuration provided."), None, None, None, None, None, None
167
+
168
+ try:
169
+ new_config = json.loads(custom_config)
170
+ all_states = new_config
171
+
172
+ # Determine the starting location and state
173
+ if custom_starting_location and custom_starting_state:
174
+ if custom_starting_location not in all_states or custom_starting_state not in all_states[custom_starting_location]:
175
+ raise ValueError(f"Invalid custom starting point: {custom_starting_location}, {custom_starting_state}")
176
+ starting_location = custom_starting_location
177
+ starting_state = custom_starting_state
178
+ else:
179
+ starting_location = next(iter(all_states.keys()))
180
+ starting_state = next(iter(all_states[starting_location].keys()))
181
+
182
+ print(f"Starting location: {starting_location}, Starting state: {starting_state}")
183
+
184
+ game_session = GameSession(starting_location, starting_state)
185
+ description, choices, game_log = game_session.get_current_state_info()
186
+ new_path_errors = validate_transitions(all_states)
187
+
188
+ output_media = []
189
+
190
+ if with_media:
191
+ media_list = all_states[starting_location][starting_state].get('media', [])
192
+ print(f"Media list: {media_list}")
193
+
194
+ if media_list:
195
+ for media_path in media_list:
196
+ output_media.append(media_path)
197
+ print(f"Created {len(output_media)} media components")
198
+
199
+ success_message = f"Custom configuration loaded successfully!\n{new_path_errors}"
200
+ return (
201
+ gr.update(value=success_message),
202
+ game_log,
203
+ description,
204
+ gr.update(choices=choices),
205
+ gr.update(value=custom_config),
206
+ game_session,
207
+ output_media if with_media else None
208
+ )
209
+
210
+ except json.JSONDecodeError as e:
211
+ error_message = format_json_error(custom_config, e)
212
+ return gr.update(value=error_message), None, None, None, gr.update(value=custom_config), None, None
213
+
214
+ except Exception as e:
215
+ error_message = f"Error loading custom configuration: {str(e)}"
216
+ return gr.update(value=error_message), None, None, None, gr.update(value=custom_config), None, None
217
+
218
+ media_folder = os.path.abspath("saved_media") #make sure same as SAVE_DIR below
219
+
220
+ def export_config_with_media(config_json):
221
+ global media_folder
222
+ """
223
+ Export the config JSON and zip it along with any files referenced in the media fields.
224
+
225
+ :param config_json: JSON string containing the config
226
+ :param media_folder: Path to the folder containing media files
227
+ :return: Path to the created zip file
228
+ """
229
+ # Parse the JSON
230
+ config = json.loads(config_json)
231
+
232
+ # Create a temporary directory to store files for zipping
233
+ with tempfile.TemporaryDirectory() as temp_dir:
234
+ # Save the config JSON to the temp directory
235
+ config_path = os.path.join(temp_dir, 'config.json')
236
+ with open(config_path, 'w') as f:
237
+ json.dump(config, f, indent=2)
238
+
239
+ # Collect all media files
240
+ media_files = set()
241
+ for location in config.values():
242
+ if isinstance(location, dict):
243
+ for sublocation in location.values():
244
+ if isinstance(sublocation, dict) and 'media' in sublocation:
245
+ media_files.update(sublocation['media'])
246
+
247
+ # Copy media files to the temp directory
248
+ for media_file in media_files:
249
+ src_path = os.path.join(media_folder, media_file)
250
+ if os.path.exists(src_path):
251
+ dst_path = os.path.join(temp_dir, media_file)
252
+ shutil.copy2(src_path, dst_path)
253
+ else:
254
+ print(f"Warning: Media file not found: {media_file}")
255
+
256
+ # Create a zip file
257
+ zip_path = os.path.join(os.path.dirname(media_folder), 'config_with_media.zip')
258
+ with zipfile.ZipFile(zip_path, 'w') as zipf:
259
+ for root, _, files in os.walk(temp_dir):
260
+ for file in files:
261
+ file_path = os.path.join(root, file)
262
+ arcname = os.path.relpath(file_path, temp_dir)
263
+ zipf.write(file_path, arcname)
264
+
265
+ return zip_path
266
+
267
+ def format_json_error(config, error):
268
+ lineno, colno = error.lineno, error.colno
269
+ lines = config.split('\n')
270
+ error_line = lines[lineno - 1] if lineno <= len(lines) else ""
271
+ pointer = ' ' * (colno - 1) + '^'
272
+
273
+ return f"""Invalid JSON format in custom configuration:
274
+ Error at line {lineno}, column {colno}:
275
+ {error_line}
276
+ {pointer}
277
+ Error details: {str(error)}"""
278
+
279
+ def display_website(link):
280
+ html = f"<iframe src='{link}' width='100%' height='1000px'></iframe>"
281
+ gr.Info("If 404 then the space/page has probably been disabled - normally due to a better alternative")
282
+ return html
283
+
284
+ initgameinfo = start_game()
285
+ fpeinitgameinfo = start_game(new_states=finished_product_demo)
relatively_constant_variables.py CHANGED
@@ -206,7 +206,14 @@ knowledge_base = [
206
  {"id": "doc2", "content": "Python is a popular programming language."},
207
  {"id": "doc3", "content": "Machine learning is a subset of artificial intelligence."},
208
  {"id": "doc4", "content": "The Earth orbits around the Sun."},
209
- {"id": "doc5", "content": "orbits is the name of a korean fangroup"},
 
 
 
 
 
 
 
210
  ]
211
 
212
  #-------------------------#-------------------------#-------------------------#-------------------------
@@ -1581,6 +1588,240 @@ ExampleGameConfigs = {
1581
  }
1582
  },
1583
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1584
  }
1585
 
1586
  #-------------------------#-------------------------#-------------------------#-------------------------
@@ -2237,7 +2478,7 @@ Interconnectedness: The graph visually demonstrates how each location, narrative
2237
 
2238
  )
2239
 
2240
- WFStage2prompt = """Please use the below config as a template to covert the story to config format (dont use the template values like masterlocation1):
2241
 
2242
  {
2243
  "masterlocation1": {
@@ -2254,6 +2495,30 @@ WFStage2prompt = """Please use the below config as a template to covert the sto
2254
  "developernotes": []
2255
  },
2256
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2257
  """
2258
 
2259
 
@@ -2430,6 +2695,94 @@ TimeRelatedMermaidStoryAttempttoRefinefromtoJSON = (
2430
 
2431
  #-------------------------#-------------------------#-------------------------#-------------------------
2432
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2433
 
2434
  #-------------------------#-------------------------#-------------------------#-------------------------
2435
 
 
206
  {"id": "doc2", "content": "Python is a popular programming language."},
207
  {"id": "doc3", "content": "Machine learning is a subset of artificial intelligence."},
208
  {"id": "doc4", "content": "The Earth orbits around the Sun."},
209
+ {"id": "doc5", "content": "Orbits is the name of a korean fangroup"},
210
+ {"id": "doc6", "content": "The capital of France is Paris. It's known for the Eiffel Tower."},
211
+ {"id": "doc7", "content": "The capital of Italy is Rome. It's famous for the Colosseum."},
212
+ {"id": "doc8", "content": "Python is a popular programming language, known for its simplicity."},
213
+ {"id": "doc9", "content": "Java is a widely-used programming language, valued for its portability."},
214
+ {"id": "doc10", "content": "Deep learning is a part of machine learning based on artificial neural networks."},
215
+ {"id": "doc11", "content": "Law is a Tekken character"},
216
+ {"id": "doc12", "content": "The law is very complicated"},
217
  ]
218
 
219
  #-------------------------#-------------------------#-------------------------#-------------------------
 
1588
  }
1589
  },
1590
 
1591
+ "Eventplanningstortytest": {
1592
+ "tavern": {
1593
+ "start": {
1594
+ "description": "The air crackles with anticipation as you step into the bustling event planning expo. Caterers offer tantalizing samples, florists boast breathtaking arrangements, and a charismatic DJ promises an unforgettable party atmosphere.",
1595
+ "choices": ["approach the DJ", "sample the catering", "admire the floral displays"],
1596
+ "transitions": {
1597
+ "approach the DJ": "tavern_rumor",
1598
+ "sample the catering": "tavern_grog",
1599
+ "admire the floral displays": "tavern_start"
1600
+ },
1601
+ "consequences": {},
1602
+ "media": []
1603
+ },
1604
+ "rumor": {
1605
+ "description": "The DJ, a master of hype, spins tales of legendary events he's orchestrated. He mentions a client, a mysterious socialite, planning an extravagant masked ball with a budget that could make your career.",
1606
+ "choices": ["express your interest", "dismiss him as a showman"],
1607
+ "transitions": {
1608
+ "express your interest": "tavern_map",
1609
+ "dismiss him as a showman": "tavern_start"
1610
+ },
1611
+ "consequences": {},
1612
+ "media": []
1613
+ },
1614
+ "grog": {
1615
+ "description": "You savor the exquisite flavors of miniature gourmet dishes. The caterer, a true artist, describes their vision for a multi-sensory dining experience.",
1616
+ "choices": ["inquire about their rates", "network with other attendees"],
1617
+ "transitions": {
1618
+ "inquire about their rates": "tavern_grog",
1619
+ "network with other attendees": "tavern_start"
1620
+ },
1621
+ "media": []
1622
+ },
1623
+ "map": {
1624
+ "description": "The DJ, sensing your ambition, offers a tantalizing clue: the socialite is looking for a fresh perspective. He suggests you submit a proposal, highlighting your unique vision.",
1625
+ "choices": ["propose a themed experience", "focus on logistics and budget"],
1626
+ "transitions": {
1627
+ "propose a themed experience": "docks_prepare",
1628
+ "focus on logistics and budget": "tavern_haggle"
1629
+ },
1630
+ "consequences": {},
1631
+ "media": []
1632
+ },
1633
+ "haggle": {
1634
+ "description": "The DJ warns you that the socialite is notoriously demanding. \"She expects perfection,\" he cautions.",
1635
+ "choices": ["assure him you deliver excellence", "reconsider your options"],
1636
+ "transitions": {
1637
+ "assure him you deliver excellence": "docks_prepare",
1638
+ "reconsider your options": "tavern_start"
1639
+ },
1640
+ "consequences": {},
1641
+ "media": []
1642
+ },
1643
+ "fight": {
1644
+ "description": "You overhear another event planner bragging about securing the masked ball contract. Jealousy burns, and you're tempted to challenge their claim.",
1645
+ "choices": ["confront the planner", "stay focused on your goals"],
1646
+ "transitions": {
1647
+ "confront the planner": "tavern_victory",
1648
+ "stay focused on your goals": "tavern_defeat"
1649
+ },
1650
+ "consequences": {},
1651
+ "media": []
1652
+ },
1653
+ "victory": {
1654
+ "description": "You confront the planner, exposing their lies. The truth prevails, and word of your integrity reaches the socialite.",
1655
+ "choices": ["prepare your proposal"],
1656
+ "transitions": {
1657
+ "prepare your proposal": "docks_prepare"
1658
+ },
1659
+ "consequences": {},
1660
+ "media": []
1661
+ },
1662
+ "defeat": {
1663
+ "description": "You decide not to stoop to their level. Trusting your instincts, you continue networking and refining your pitch.",
1664
+ "choices": ["continue networking"],
1665
+ "transitions": {
1666
+ "continue networking": "tavern_start"
1667
+ },
1668
+ "consequences": {},
1669
+ "media": []
1670
+ }
1671
+ },
1672
+ "docks": {
1673
+ "prepare": {
1674
+ "description": "Armed with a killer concept, you retreat to your studio to craft the perfect proposal. It's time to gather your team: the best florists, caterers, entertainers...",
1675
+ "choices": ["contact your florist", "secure a caterer"],
1676
+ "transitions": {
1677
+ "contact your florist": "docks_ship",
1678
+ "secure a caterer": "docks_crew"
1679
+ },
1680
+ "media": []
1681
+ },
1682
+ "ship": {
1683
+ "description": "Your trusted florist presents a stunning array of options, from elegant orchids to whimsical fairy lights. You envision transforming the venue into a magical landscape.",
1684
+ "choices": ["finalize the floral arrangements", "explore additional decor"],
1685
+ "transitions": {
1686
+ "finalize the floral arrangements": "docks_captain",
1687
+ "explore additional decor": "docks_prepare"
1688
+ },
1689
+ "media": []
1690
+ },
1691
+ "crew": {
1692
+ "description": "You browse through portfolios of caterers, each offering a unique culinary experience. The decision is crucial: the food must be as unforgettable as the event itself.",
1693
+ "choices": ["choose a gourmet caterer", "opt for a themed buffet"],
1694
+ "transitions": {
1695
+ "choose a gourmet caterer": "docks_captain",
1696
+ "opt for a themed buffet": "docks_captain"
1697
+ },
1698
+ "consequences": {},
1699
+ "media": []
1700
+ },
1701
+ "captain": {
1702
+ "description": "With each element falling into place, your vision for the masked ball comes alive. The proposal is complete - a masterpiece of creativity and meticulous planning.",
1703
+ "choices": ["submit your proposal"],
1704
+ "transitions": {
1705
+ "submit your proposal": "openSea_start"
1706
+ },
1707
+ "media": []
1708
+ }
1709
+ },
1710
+ "openSea": {
1711
+ "start": {
1712
+ "description": "Days turn into nights as you await a response. The uncertainty is agonizing, your hopes rising and falling with every ring of the phone.",
1713
+ "choices": ["check your emails obsessively", "distract yourself with another project"],
1714
+ "transitions": {
1715
+ "check your emails obsessively": "openSea_storm",
1716
+ "distract yourself with another project": "openSea_mutiny"
1717
+ },
1718
+ "media": []
1719
+ },
1720
+ "storm": {
1721
+ "description": "A wave of despair crashes over you as you receive a generic rejection email. Your carefully crafted proposal, your dreams... dashed.",
1722
+ "choices": ["analyze the email for feedback", "move on to the next opportunity"],
1723
+ "transitions": {
1724
+ "analyze the email for feedback": "openSea_ghostShip",
1725
+ "move on to the next opportunity": "openSea_start"
1726
+ },
1727
+ "media": []
1728
+ },
1729
+ "mutiny": {
1730
+ "description": "Your phone vibrates - an unknown number. Your heart races as you answer. It's the socialite's assistant, and they're impressed.",
1731
+ "choices": ["accept their invitation to meet", "negotiate your terms"],
1732
+ "transitions": {
1733
+ "accept their invitation to meet": "openSea_ghostShip",
1734
+ "negotiate your terms": "openSea_start"
1735
+ },
1736
+ "consequences": {},
1737
+ "media": []
1738
+ },
1739
+ "ghostShip": {
1740
+ "description": "You meet the socialite - an enigmatic figure radiating elegance and power. They're intrigued by your vision, your passion.",
1741
+ "choices": ["present your ideas in detail", "listen to their expectations"],
1742
+ "transitions": {
1743
+ "present your ideas in detail": "ghostShip_deck",
1744
+ "listen to their expectations": "openSea_start"
1745
+ },
1746
+ "media": []
1747
+ }
1748
+ },
1749
+ "ghostShip": {
1750
+ "deck": {
1751
+ "description": "The socialite listens intently as you unveil your plans, their eyes sparkling with approval. They love your innovative concepts, your attention to detail.",
1752
+ "choices": ["discuss the budget and timeline", "negotiate your fee"],
1753
+ "transitions": {
1754
+ "discuss the budget and timeline": "ghostShip_brig",
1755
+ "negotiate your fee": "ghostShip_quarters"
1756
+ },
1757
+ "media": []
1758
+ },
1759
+ "brig": {
1760
+ "description": "Negotiations are swift and decisive. The socialite appreciates your professionalism and agrees to your terms. The masked ball is yours to create!",
1761
+ "choices": ["celebrate your success", "start planning immediately"],
1762
+ "transitions": {
1763
+ "celebrate your success": "ghostShip_clue",
1764
+ "start planning immediately": "ghostShip_treasure"
1765
+ },
1766
+ "media": []
1767
+ },
1768
+ "quarters": {
1769
+ "description": "You secure a contract that exceeds your wildest dreams. The masked ball, a testament to your talent and dedication, will be your masterpiece.",
1770
+ "choices": ["assemble your dream team", "order the first batch of champagne"],
1771
+ "transitions": {
1772
+ "assemble your dream team": "ghostShip_clue",
1773
+ "order the first batch of champagne": "ghostShip_treasure"
1774
+ },
1775
+ "media": []
1776
+ },
1777
+ "clue": {
1778
+ "description": "Excitement courses through you as you share the good news with your team. The best in the business, they're ready to help you execute this extraordinary event.",
1779
+ "choices": ["begin the preparations"],
1780
+ "transitions": {
1781
+ "begin the preparations": "ghostShip_treasure"
1782
+ },
1783
+ "media": []
1784
+ },
1785
+ "treasure": {
1786
+ "description": "Weeks of tireless work culminate in the grand opening of the masked ball. It's a triumph - a symphony of elegance, enchantment, and pure joy.",
1787
+ "choices": ["bask in the glory of your success", "network with potential clients"],
1788
+ "transitions": {
1789
+ "bask in the glory of your success": "ghostShip_victory",
1790
+ "network with potential clients": "openSea_return"
1791
+ },
1792
+ "consequences": {},
1793
+ "media": []
1794
+ },
1795
+ "victory": {
1796
+ "description": "The masked ball becomes legendary, exceeding all expectations. Your name is on everyone's lips, synonymous with unforgettable events.",
1797
+ "choices": ["claim your place as an event icon"],
1798
+ "transitions": {
1799
+ "claim your place as an event icon": "openSea_return"
1800
+ },
1801
+ "consequences": {},
1802
+ "media": []
1803
+ }
1804
+ },
1805
+ "openSea_return": {
1806
+ "return": {
1807
+ "description": "Your star continues to rise as you orchestrate one successful event after another. Your creativity knows no bounds, your reputation solidified.",
1808
+ "choices": ["embrace your destiny as an event maestro"],
1809
+ "transitions": {
1810
+ "embrace your destiny as an event maestro": "end_end"
1811
+ },
1812
+ "media": []
1813
+ }
1814
+ },
1815
+ "end": {
1816
+ "end": {
1817
+ "description": "From humble beginnings at an industry expo, you've become an icon, transforming dreams into dazzling reality. The world is your canvas, and every event is a masterpiece.",
1818
+ "choices": [],
1819
+ "transitions": {},
1820
+ "media": []
1821
+ }
1822
+ }
1823
+ },
1824
+
1825
  }
1826
 
1827
  #-------------------------#-------------------------#-------------------------#-------------------------
 
2478
 
2479
  )
2480
 
2481
+ WFStage2prompt = """Please use the below config as a template to convert the story to config format (dont use the template values like masterlocation1):
2482
 
2483
  {
2484
  "masterlocation1": {
 
2495
  "developernotes": []
2496
  },
2497
 
2498
+ eg. {"tavern": {"start": {"description": "You wake up in a dimly lit tavern, the smell of ale and salt heavy in the air. A grizzled sailor at the bar boasts about a hidden island overflowing with \"more gold than ye can dream of!\" ", "choices": ["approach sailor", "ignore sailor", "order grog"], "transitions": {"approach sailor": "tavern_rumor", "ignore sailor": "tavern_start", "order grog": "tavern_grog"}, "consequences": {}, "media": []}, "rumor": {"description": "The sailor, three sheets to the wind, spins a tale of treacherous waters, ancient curses, and a map hidden on a ghost ship. He claims to know the way.", "choices": ["offer to buy him another drink", "dismiss him as a drunkard"], "transitions": {"offer to buy him another drink": "tavern_map", "dismiss him as a drunkard": "tavern_start"}, "consequences": {}, "media": []}, "grog": {"description": "The tavern keeper slides you a tankard of potent grog. It burns pleasantly as it goes down, and you feel your senses dull.", "choices": ["order another", "eavesdrop on nearby pirates"], "transitions": {"order another": "tavern_grog", "eavesdrop on nearby pirates": "tavern_start"}, "media": []}, "map": {"description": "With a wink and a hiccup, the sailor produces a crumpled piece of parchment. It's stained with salt and what looks suspiciously like blood, but the markings... they resemble a map! ", "choices": ["propose a partnership", "try to buy the map", "steal the map"], "transitions": {"propose a partnership": "docks_prepare", "try to buy the map": "tavern_haggle", "steal the map": "tavern_fight"}, "consequences": {}, "media": []}, "haggle": {"description": "The sailor eyes you shrewdly. \"This here map's worth a king's ransom,\" he slurs.", "choices": ["offer a pouch of gold", "walk away"], "transitions": {"offer a pouch of gold": "docks_prepare", "walk away": "tavern_start"}, "consequences": {}, "media": []}, "fight": {"description": "You lunge for the map, but the sailor's quicker than he looks! A brawl erupts, tables are overturned, and mugs fly through the air.", "choices": ["fight dirty", "try to reason with him"], "transitions": {"fight dirty": "tavern_victory", "try to reason with him": "tavern_defeat"}, "consequences": {}, "media": []}, "victory": {"description": "With a final blow, you knock the sailor unconscious. You grab the map and make a hasty exit.", "choices": ["head to the docks"], "transitions": {"head to the docks": "docks_prepare"}, "consequences": {}, "media": []}, "defeat": {"description": "The sailor and a couple of his cronies land some solid punches. You're tossed out of the tavern, bruised and map-less.", "choices": ["nurse your wounds"], "transitions": {"nurse your wounds": "tavern_start"}, "consequences": {}, "media": []}}, "docks": {"prepare": {"description": "The salty air of the docks fills your lungs. You can practically taste the adventure on the horizon. But first, you need a ship and a crew...", "choices": ["find a ship", "assemble a crew"], "transitions": {"find a ship": "docks_ship", "assemble a crew": "docks_crew"}, "media": []}, "ship": {"description": "You spot a sturdy-looking galleon with a \"For Sale\" sign hanging precariously from its mast.", "choices": ["inspect the ship", "look for another vessel"], "transitions": {"inspect the ship": "docks_captain", "look for another vessel": "docks_prepare"}, "media": []}, "crew": {"description": "The docks are teeming with salty dogs of all shapes and sizes.", "choices": ["recruit seasoned sailors", "round up some desperate souls"], "transitions": {"recruit seasoned sailors": "docks_captain", "round up some desperate souls": "docks_captain"}, "consequences": {}, "media": []}, "captain": {"description": "With a ship and a crew (of varying competence), you're ready to set sail! ", "choices": ["set sail for the open sea!"], "transitions": {"set sail for the open sea!": "openSea_start"}, "media": []}}, "openSea": {"start": {"description": "The open sea stretches before you, vast and unforgiving. The wind whips at your sails as you set course for the uncharted waters where the treasure awaits.", "choices": ["consult the map", "enjoy the voyage"], "transitions": {"consult the map": "openSea_storm", "enjoy the voyage": "openSea_mutiny"}, "media": []}, "storm": {"description": "A storm gathers on the horizon, dark clouds swirling ominously. Waves crash against the hull, threatening to swallow you whole.", "choices": ["weather the storm", "change course"], "transitions": {"weather the storm": "openSea_ghostShip", "change course": "openSea_start"}, "media": []}, "mutiny": {"description": "Your crew, a motley bunch at best, begin to grumble. They're growing impatient and greedy, their eyes glinting with mutiny.", "choices": ["quell the mutiny", "reason with them"], "transitions": {"quell the mutiny": "openSea_ghostShip", "reason with them": "openSea_start"}, "consequences": {}, "media": []}, "ghostShip": {"description": "Through the mist and fog, a ghostly silhouette emerges. A ship, its sails in tatters, manned by skeletal figures. This... is the ghost ship.", "choices": ["board the ghost ship", "flee"], "transitions": {"board the ghost ship": "ghostShip_deck", "flee": "openSea_start"}, "media": []}}, "ghostShip": {"deck": {"description": "You step aboard the ghost ship, the air heavy with the stench of decay. Eerie silence hangs over the vessel.", "choices": ["explore the ship", "search for the captain's quarters"], "transitions": {"explore the ship": "ghostShip_brig", "search for the captain's quarters": "ghostShip_quarters"}, "media": []}, "brig": {"description": "You stumble upon the ship's brig, its cells still occupied by skeletal remains shackled to the walls.", "choices": ["examine the skeletons", "leave the brig"], "transitions": {"examine the skeletons": "ghostShip_clue", "leave the brig": "ghostShip_deck"}, "media": []}, "quarters": {"description": "The captain's quarters are in disarray, as if a struggle took place. A tattered journal lies open on the floor.", "choices": ["read the journal", "search for the map"], "transitions": {"read the journal": "ghostShip_clue", "search for the map": "ghostShip_treasure"}, "media": []}, "clue": {"description": "You piece together clues from the journal and the skeletons. The ghost ship's captain hid the real treasure map to protect it from mutineers.", "choices": ["continue searching"], "transitions": {"continue searching": "ghostShip_treasure"}, "media": []}, "treasure": {"description": "After careful searching, you find a hidden compartment behind a portrait. Inside, a gleaming treasure chest awaits!", "choices": ["open the chest", "take the chest and flee"], "transitions": {"open the chest": "ghostShip_victory", "take the chest and flee": "openSea_return"}, "consequences": {}, "media": []}, "victory": {"description": "The treasure chest overflows with gold, jewels, and artifacts beyond your wildest dreams! You've found the legendary pirate treasure!", "choices": ["claim your prize and set sail"], "transitions": {"claim your prize and set sail": "openSea_return"}, "consequences": {}, "media": []}}, "openSea_return": {"return": {"description": "With the treasure safely stowed on your own ship, you set sail for home, leaving the ghost ship to its eternal slumber.", "choices": ["sail into the sunset"], "transitions": {"sail into the sunset": "end_end"}, "media": []}}, "end": {"end": {"description": "The sun dips below the horizon, painting the sky in hues of gold and crimson. You've cheated death, outsmarted ghosts, and claimed a fortune in pirate treasure. Your legend will be sung in taverns for centuries to come.", "choices": [], "transitions": {}, "media": []}}}
2499
+
2500
+ The user will provide a theme
2501
+ """
2502
+
2503
+ WFStage2prompt2 = """Please use the below config as a template to convert the story to config format (dont use the template values like masterlocation1):
2504
+
2505
+ {
2506
+ "masterlocation1": {
2507
+ "location1": {
2508
+ "description": "UI - Experience Bar",
2509
+ "events": [],
2510
+ "choices": [
2511
+ "continue"
2512
+ ],
2513
+ "transitions": {
2514
+ "continue": "masterlocation1_location2"
2515
+ },
2516
+ "media": [],
2517
+ "developernotes": []
2518
+ },
2519
+
2520
+ There should be 3 master and 10 total sublocations.
2521
+ The theme is provided by the user
2522
  """
2523
 
2524
 
 
2695
 
2696
  #-------------------------#-------------------------#-------------------------#-------------------------
2697
 
2698
+ finished_product_demo = {
2699
+ 'village': {
2700
+ 'start': {
2701
+ "description": "You wake up in a small village. You hear a rumor about a lost treasure.",
2702
+ "choices": ['explore village', 'gather supplies', 'rest'],
2703
+ "transitions": {'explore village': 'village_rumor', 'gather supplies': 'village_supplies', 'rest': 'village_start'},
2704
+ "consequences": {
2705
+ 'gather supplies': lambda player: player.add_item('basic supplies')
2706
+ },
2707
+ "media": ["testmedia/fpe_small_village.webp", "testmedia/fpe_rumor_about_a_lost_treasure.webp", "testmedia/fpe_gathering_supplies_in_a_village.webp"]
2708
+ },
2709
+ 'rumor': {
2710
+ "description": "You hear more details about the treasure hidden in the ancient ruins nearby.",
2711
+ "choices": ['decide to go', 'ignore'],
2712
+ "transitions": {'decide to go': 'village_supplies', 'ignore': 'village_start'},
2713
+ "consequences": {
2714
+ 'decide to go': lambda player: player.update_knowledge('treasure location')
2715
+ },
2716
+ "media": ["testmedia/fpe_rumor_about_a_lost_treasure.webp"]
2717
+ },
2718
+ 'supplies': {
2719
+ "description": "You gather supplies for your journey.",
2720
+ "choices": ['head to forest', 'stay in village'],
2721
+ "transitions": {'head to forest': 'forest_forest', 'stay in village': 'village_start'},
2722
+ "media": ["testmedia/fpe_person_looking_away_Listening_I_cant_hear_you_pose.webp", "testmedia/fpr_person_looking_away_Listening_hand_over_ear.webp", "testmedia/fpe_You_gather_supplies_for_your_journey.webp", "testmedia/fpe_head_to_forest.webp"]
2723
+ },
2724
+ },
2725
+ 'forest': {
2726
+ 'forest': {
2727
+ "description": "You enter the dense forest, heading towards the ruins.",
2728
+ "choices": ['travel further', 'return to village'],
2729
+ "transitions": {'travel further': 'ruins_ruins', 'return to village': 'village_start'},
2730
+ "media": ["testmedia/fpe_village_start_collage.png", ]
2731
+ },
2732
+ },
2733
+ 'ruins': {
2734
+ 'ruins': {
2735
+ "description": "You reach the ancient ruins. The entrance is dark and eerie.",
2736
+ "choices": ['enter ruins', 'return to forest'],
2737
+ "transitions": {'enter ruins': 'ruins_explore', 'return to forest': 'forest_forest'},
2738
+ "media": []
2739
+ },
2740
+ 'explore': {
2741
+ "description": "You explore the ruins, encountering traps and puzzles.",
2742
+ "choices": ['solve puzzle', 'avoid traps'],
2743
+ "transitions": {'solve puzzle': 'ruins_hiddenPassage', 'avoid traps': 'ruins_ruins'},
2744
+ "media": []
2745
+ },
2746
+ 'hiddenPassage': {
2747
+ "description": "You solve a challenging puzzle and unlock a hidden passage.",
2748
+ "choices": ['enter passage', 'go back'],
2749
+ "transitions": {'enter passage': 'ruins_treasureRoom', 'go back': 'ruins_explore'},
2750
+ "media": []
2751
+ },
2752
+ 'treasureRoom': {
2753
+ "description": "You enter the treasure room and find the treasure chest.",
2754
+ "choices": ['take treasure', 'leave'],
2755
+ "transitions": {'take treasure': 'ruins_celebrate', 'leave': 'ruins_ruins'},
2756
+ "consequences": {
2757
+ 'take treasure': lambda player: player.add_item('treasure')
2758
+ },
2759
+ "media": []
2760
+ },
2761
+ 'celebrate': {
2762
+ "description": "You celebrate your discovery and decide to bring the treasure back to the village.",
2763
+ "choices": ['return to village'],
2764
+ "transitions": {'return to village': 'village_return'},
2765
+ "media": []
2766
+ },
2767
+ },
2768
+ 'village_return': {
2769
+ 'village_return': {
2770
+ "description": "You return to the village with the treasure and share it with the villagers.",
2771
+ "choices": ['end adventure'],
2772
+ "transitions": {'end adventure': 'end_end'},
2773
+ "media": []
2774
+ },
2775
+ },
2776
+ 'end': {
2777
+ 'end': {
2778
+ "description": "Your adventure ends here. The villagers are grateful and everyone's lives improve.",
2779
+ "choices": [],
2780
+ "transitions": {},
2781
+ "media": []
2782
+ },
2783
+ }
2784
+ }
2785
+
2786
 
2787
  #-------------------------#-------------------------#-------------------------#-------------------------
2788
 
state_prompt_fileman_UI_functions.py ADDED
@@ -0,0 +1,324 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from datetime import datetime
2
+ import json
3
+ import os
4
+ import gradio as gr
5
+ from gradio_client import Client
6
+ import shutil
7
+ import time
8
+ import random
9
+ import zipfile
10
+ import base64
11
+
12
+ # Global variables
13
+ SPFManstate = {
14
+ "last_file": 0,
15
+ "output_dir": "output",
16
+ "errors": [],
17
+ "skipped_items": [],
18
+ "is_paid_api": False,
19
+ "cost_per_item": 0.1, # Default cost per item for paid API
20
+ "timestamp": datetime.now().strftime("%Y%m%d_%H%M%S"),
21
+ "api_provider": "default", # Default API provider
22
+ "retry_delay": 300, # 5 minutes delay for retry
23
+ "max_retries": 3 # Maximum number of retries
24
+ }
25
+ SPFManprompt_list = []
26
+
27
+ #SPFMan - State, Prompt and file manager
28
+
29
+ def SPFManload_state(config_file=None):
30
+ global SPFManstate, SPFManprompt_list
31
+ try:
32
+ if config_file:
33
+ with open(config_file, "r", encoding="utf-8", errors="replace") as f:
34
+ loaded_data = json.load(f)
35
+ SPFManstate.update(loaded_data.get("state", {}))
36
+ SPFManprompt_list = loaded_data.get("prompt_list", [])
37
+ elif os.path.exists("state.json"):
38
+ with open("state.json", "r", encoding="utf-8", errors="replace") as f:
39
+ loaded_data = json.load(f)
40
+ SPFManstate.update(loaded_data.get("state", {}))
41
+ SPFManprompt_list = loaded_data.get("prompt_list", [])
42
+ except json.JSONDecodeError as e:
43
+ print(f"Error decoding JSON: {e}")
44
+ except Exception as e:
45
+ print(f"Unexpected error: {e}")
46
+
47
+ def SPFMansave_state():
48
+ SPFManstate["timestamp"] = datetime.now().strftime("%Y%m%d_%H%M%S")
49
+ data_to_save = {
50
+ "state": SPFManstate,
51
+ "prompt_list": SPFManprompt_list
52
+ }
53
+ with open(f"state_{SPFManstate['timestamp']}.json", "w") as f:
54
+ json.dump(data_to_save, f)
55
+
56
+ # Delete old state files
57
+ for file in os.listdir():
58
+ if file.startswith("state_") and file.endswith(".json") and file != f"state_{SPFManstate['timestamp']}.json":
59
+ os.remove(file)
60
+
61
+ def SPFManensure_output_directory():
62
+ os.makedirs(SPFManstate['output_dir'], exist_ok=True)
63
+
64
+ def SPFMangenerate_image(prompt, retries=0):
65
+ SPFManensure_output_directory()
66
+ try:
67
+ client = Client("black-forest-labs/FLUX.1-dev")
68
+ result = client.predict(
69
+ prompt=prompt,
70
+ seed=0,
71
+ randomize_seed=True,
72
+ width=1024,
73
+ height=1024,
74
+ guidance_scale=3.5,
75
+ num_inference_steps=28,
76
+ api_name="/infer"
77
+ )
78
+ image_path = result[0]
79
+ filename = f"{SPFManstate['output_dir']}/{prompt[:50].replace(' ', '_')}_image_{SPFManstate['timestamp']}.webp"
80
+ shutil.move(image_path, filename)
81
+ return f"Image saved as {filename}"
82
+ except Exception as e:
83
+ error_msg = f"Error generating image: {str(e)}"
84
+ if "exceeded your GPU quota" in str(e) and retries < SPFManstate['max_retries']:
85
+ time.sleep(SPFManstate['retry_delay'])
86
+ return SPFMangenerate_image(prompt, retries + 1)
87
+ SPFManstate["errors"].append(error_msg)
88
+ return error_msg
89
+
90
+ def SPFMangenerate_audio(prompt, retries=0):
91
+ SPFManensure_output_directory()
92
+ try:
93
+ client = Client("artificialguybr/Stable-Audio-Open-Zero")
94
+ result = client.predict(
95
+ prompt=prompt,
96
+ seconds_total=30,
97
+ steps=100,
98
+ cfg_scale=7,
99
+ api_name="/predict"
100
+ )
101
+
102
+ if isinstance(result, str) and os.path.exists(result):
103
+ filename = f"{SPFManstate['output_dir']}/{prompt[:50].replace(' ', '_')}_audio_{SPFManstate['timestamp']}.wav"
104
+ shutil.move(result, filename)
105
+ else:
106
+ audio_data = base64.b64decode(result)
107
+ filename = f"{SPFManstate['output_dir']}/{prompt[:50].replace(' ', '_')}_audio_{SPFManstate['timestamp']}.wav"
108
+ with open(filename, "wb") as audio_file:
109
+ audio_file.write(audio_data)
110
+
111
+ return f"Audio saved as {filename}"
112
+ except Exception as e:
113
+ error_msg = f"Error generating audio: {str(e)}"
114
+ if "exceeded your GPU quota" in str(e) and retries < SPFManstate['max_retries']:
115
+ time.sleep(SPFManstate['retry_delay'])
116
+ return SPFMangenerate_audio(prompt, retries + 1)
117
+ SPFManstate["errors"].append(error_msg)
118
+ return error_msg
119
+
120
+ def SPFManprocess_prompts(prompt_list):
121
+ router = {
122
+ 'image': SPFMangenerate_image,
123
+ 'audio': SPFMangenerate_audio,
124
+ }
125
+ results = []
126
+ for prompt_type, prompt in prompt_list:
127
+ if prompt_type in router:
128
+ result = router[prompt_type](prompt)
129
+ results.append(result)
130
+ if "Error" in result:
131
+ break # Stop processing if there's an error
132
+ else:
133
+ error_msg = f"Unknown prompt type: {prompt_type}"
134
+ SPFManstate["errors"].append(error_msg)
135
+ results.append(error_msg)
136
+ break # Stop processing if there's an error
137
+ return results
138
+
139
+ def SPFMancreate_files_with_generation(resume=True):
140
+ global SPFManstate, SPFManprompt_list
141
+ results = []
142
+
143
+ if resume and SPFManstate["last_file"] < len(SPFManprompt_list):
144
+ start = SPFManstate["last_file"]
145
+ results.append(f"Resuming from item {start + 1}")
146
+ else:
147
+ start = 0
148
+
149
+ end = len(SPFManprompt_list)
150
+
151
+ for i in range(start, end):
152
+ if i in SPFManstate["skipped_items"]:
153
+ results.append(f"Skipped item {i + 1}")
154
+ continue
155
+
156
+ prompt_type, prompt = SPFManprompt_list[i]
157
+
158
+ try:
159
+ if SPFManstate["is_paid_api"]:
160
+ generation_results = SPFManprocess_prompts([(prompt_type, prompt)])
161
+ results.extend(generation_results)
162
+ else:
163
+ results.append(f"Processing: {prompt_type} - {prompt}")
164
+ generation_results = SPFManprocess_prompts([(prompt_type, prompt)])
165
+ results.extend(generation_results)
166
+
167
+ if any("Error" in result for result in generation_results):
168
+ break # Stop processing if there's an error
169
+
170
+ SPFManstate["last_file"] = i + 1
171
+ except Exception as e:
172
+ error_msg = f"Error processing item {i + 1}: {str(e)}"
173
+ SPFManstate["errors"].append(error_msg)
174
+ results.append(error_msg)
175
+ break # Stop processing if there's an error
176
+
177
+ SPFMansave_state()
178
+ yield "\n".join(results)
179
+
180
+ if not SPFManstate["is_paid_api"]:
181
+ break # Stop after processing one item for non-paid API
182
+
183
+ def SPFManadd_prompt(prompt_type, prompt):
184
+ global SPFManprompt_list
185
+ SPFManprompt_list.append((prompt_type, prompt))
186
+ SPFMansave_state()
187
+ return f"Added {prompt_type}: {prompt}", gr.update(value=len(SPFManprompt_list))
188
+
189
+ def SPFManclear_prompts():
190
+ global SPFManprompt_list
191
+ SPFManprompt_list = []
192
+ SPFMansave_state()
193
+ return "Prompt list cleared", gr.update(value=0)
194
+
195
+ def SPFManview_all_prompts():
196
+ return "\n".join([f"{i+1}. {t}: {p}" for i, (t, p) in enumerate(SPFManprompt_list)])
197
+
198
+ def SPFManzip_files():
199
+ SPFManensure_output_directory()
200
+ zip_filename = f"output_{SPFManstate['timestamp']}.zip"
201
+ with zipfile.ZipFile(zip_filename, 'w') as zipf:
202
+ for root, _, files in os.walk(SPFManstate['output_dir']):
203
+ for file in files:
204
+ zipf.write(os.path.join(root, file))
205
+ zipf.write(f"state_{SPFManstate['timestamp']}.json")
206
+
207
+ # Add prompt list to zip
208
+ prompt_list_filename = f"prompt_list_{SPFManstate['timestamp']}.txt"
209
+ with open(prompt_list_filename, 'w') as f:
210
+ for t, p in SPFManprompt_list:
211
+ f.write(f"{t}: {p}\n")
212
+ zipf.write(prompt_list_filename)
213
+ os.remove(prompt_list_filename) # Remove the temporary file
214
+
215
+ return f"Files zipped as {zip_filename}"
216
+
217
+ def SPFMantoggle_paid_api(value):
218
+ SPFManstate["is_paid_api"] = value
219
+ SPFMansave_state()
220
+ return f"Paid API: {'Enabled' if value else 'Disabled'}"
221
+
222
+ def SPFManestimate_cost():
223
+ return f"Estimated cost: ${len(SPFManprompt_list) * SPFManstate['cost_per_item']:.2f}"
224
+
225
+ def SPFManauto_generate_prompt(prompt_type):
226
+ subjects = ["cat", "dog", "tree", "mountain", "ocean", "city", "person", "flower", "car", "building"]
227
+ styles = ["realistic", "cartoon", "abstract", "vintage", "futuristic", "minimalist", "surreal", "impressionist"]
228
+ actions = ["running", "sleeping", "flying", "dancing", "singing", "jumping", "sitting", "laughing"]
229
+
230
+ if prompt_type == "image":
231
+ return f"A {random.choice(styles)} {random.choice(subjects)} {random.choice(actions)}"
232
+ elif prompt_type == "audio":
233
+ return f"Sound of a {random.choice(subjects)} {random.choice(actions)}"
234
+
235
+ def SPFManview_config():
236
+ config = {
237
+ "state": SPFManstate,
238
+ "prompt_list_length": len(SPFManprompt_list)
239
+ }
240
+ return json.dumps(config, indent=2)
241
+
242
+ def SPFManskip_item():
243
+ if SPFManstate["last_file"] < len(SPFManprompt_list):
244
+ SPFManstate["skipped_items"].append(SPFManstate["last_file"])
245
+ SPFManstate["last_file"] += 1
246
+ SPFMansave_state()
247
+ return f"Skipped item {SPFManstate['last_file']}"
248
+ return "No more items to skip"
249
+
250
+ def SPFManupdate_api_details(provider, cost):
251
+ SPFManstate["api_provider"] = provider
252
+ SPFManstate["cost_per_item"] = float(cost)
253
+ SPFMansave_state()
254
+ return f"API details updated: Provider - {provider}, Cost per item - ${cost}"
255
+
256
+ def SPFManload_config_file(file):
257
+ global SPFManstate, SPFManprompt_list
258
+ try:
259
+ # Clear existing state and prompt list
260
+ SPFManstate = {
261
+ "last_file": 0,
262
+ "output_dir": "output",
263
+ "errors": [],
264
+ "skipped_items": [],
265
+ "is_paid_api": False,
266
+ "cost_per_item": 0.1,
267
+ "timestamp": datetime.now().strftime("%Y%m%d_%H%M%S"),
268
+ "api_provider": "default",
269
+ "retry_delay": 300,
270
+ "max_retries": 3
271
+ }
272
+ SPFManprompt_list = []
273
+
274
+ # Check if the file is a ZIP archive
275
+ if file.name.endswith('.zip'):
276
+ # Extract the ZIP file
277
+ extracted_folder_path = 'extracted_files'
278
+ os.makedirs(extracted_folder_path, exist_ok=True)
279
+ with zipfile.ZipFile(file.name, 'r') as zip_ref:
280
+ zip_ref.extractall(extracted_folder_path)
281
+
282
+ # Find and load the state JSON file
283
+ json_files = [f for f in os.listdir(extracted_folder_path) if f.startswith('state_') and f.endswith('.json')]
284
+ if json_files:
285
+ json_file_path = os.path.join(extracted_folder_path, json_files[0])
286
+ with open(json_file_path, 'r') as json_file:
287
+ loaded_data = json.load(json_file)
288
+ SPFManstate.update(loaded_data.get("state", {}))
289
+ SPFManprompt_list = loaded_data.get("prompt_list", [])
290
+
291
+ # Find and load the prompt list text file
292
+ txt_files = [f for f in os.listdir(extracted_folder_path) if f.startswith('prompt_list_') and f.endswith('.txt')]
293
+ if txt_files:
294
+ txt_file_path = os.path.join(extracted_folder_path, txt_files[0])
295
+ with open(txt_file_path, 'r') as txt_file:
296
+ for line in txt_file:
297
+ prompt_type, prompt = line.strip().split(': ', 1)
298
+ SPFManprompt_list.append((prompt_type, prompt))
299
+
300
+ # Clean up extracted files
301
+ shutil.rmtree(extracted_folder_path)
302
+
303
+ else:
304
+ # Load new configuration from a single file
305
+ SPFManload_state(file.name)
306
+
307
+ SPFMansave_state() # Save the loaded state
308
+ return f"Configuration loaded from {file.name}", gr.update(value=len(SPFManprompt_list))
309
+ except Exception as e:
310
+ return f"Error loading configuration: {str(e)}", gr.update(value=len(SPFManprompt_list))
311
+
312
+ # Handle JSON input and loading
313
+ def SPFManload_json_configuration(json_text):
314
+ global SPFManstate, SPFManprompt_list
315
+ try:
316
+ loaded_data = json.loads(json_text)
317
+ SPFManstate = loaded_data.get("state", SPFManstate)
318
+ SPFManprompt_list = loaded_data.get("prompt_list", SPFManprompt_list)
319
+ SPFMansave_state()
320
+ return "Configuration loaded from JSON input", gr.update(value=len(SPFManprompt_list))
321
+ except json.JSONDecodeError as e:
322
+ return f"Error parsing JSON: {str(e)}", gr.update(value=len(SPFManprompt_list))
323
+ except Exception as e:
324
+ return f"Unexpected error: {str(e)}", gr.update(value=len(SPFManprompt_list))
timeline_and_UI_generation_functions.py ADDED
@@ -0,0 +1,370 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import random
2
+ from relatively_constant_variables import player_engagement_items, story_events, all_idea_lists, existing_game_inspirations, multiplayer_features, list_names
3
+ import json
4
+ import gradio as gr
5
+ import re
6
+ import os
7
+
8
+
9
+ def pick_random_items(items, n):
10
+ return random.sample(items, n)
11
+
12
+ def generate_timeline(events, label):
13
+ timeline = []
14
+ for event in events:
15
+ timeline.append((random.randint(1, 100), label, event))
16
+ return timeline
17
+
18
+ def create_story(timeline):
19
+ story = []
20
+ for entry in timeline:
21
+ if entry[1] == "Story":
22
+ story.append(f"The hero {entry[2].replace('engageBattle', 'engaged in a fierce battle').replace('solveRiddle', 'solved a complex riddle').replace('exploreLocation', 'explored a mysterious location')}.")
23
+ else:
24
+ story.append(f"The player interacted with {entry[2]}.")
25
+ return " ".join(story)
26
+
27
+ def generate_story_and_timeline(no_story_timeline_points=10, no_ui_timeline_points=10, num_lists=1, items_per_list=1, include_existing_games=False, include_multiplayer=False): # , no_media_timeline_points=5, include_media=True):
28
+ # Pick 10 random UI items
29
+ random_ui_items = pick_random_items(player_engagement_items, no_ui_timeline_points)
30
+ random_story_items = pick_random_items(story_events, no_story_timeline_points)
31
+
32
+ # Generate UI and story timelines
33
+ ui_timeline = generate_timeline(random_ui_items, "UI")
34
+ story_timeline = generate_timeline(random_story_items, "Story")
35
+
36
+ # Initialize merged timeline with UI and story timelines
37
+ merged_timeline = ui_timeline + story_timeline
38
+ #no_media_merged_timeline = ui_timeline + story_timeline
39
+ #print(merged_timeline)
40
+ #print(no_media_merged_timeline)
41
+
42
+ # Include media-related items if specified
43
+ # if include_media:
44
+ # media_files = generate_media_file_list(no_media_timeline_points)
45
+ # #rendered_media = render_media_with_dropdowns(media_files)
46
+ # media_timeline = generate_timeline(media_files, "Media")
47
+ # merged_timeline += media_timeline
48
+
49
+ # print(merged_timeline)
50
+
51
+ # Sort the merged timeline based on the random numbers
52
+ merged_timeline.sort(key=lambda x: x[0])
53
+ # no_media_merged_timeline.sort(key=lambda x: x[0])
54
+
55
+ # Create the story
56
+ story = create_story(merged_timeline)
57
+
58
+ # Format the timeline for display
59
+ formatted_timeline = "\n".join([f"{entry[0]}: {entry[1]} - {entry[2]}" for entry in merged_timeline])
60
+ # no_media_formatted_timeline = "\n".join([f"{entry[0]}: {entry[1]} - {entry[2]}" for entry in no_media_merged_timeline])
61
+
62
+ # game_structure_with_media = generate_game_structures(formatted_timeline) #, game_structure_without_media = generate_game_structures(formatted_timeline, no_media_formatted_timeline)
63
+ game_structure_with_media = convert_timeline_to_game_structure(formatted_timeline)
64
+
65
+ print("simulplay debug - good to here 4")
66
+
67
+ suggestions, selected_list_names = timeline_get_random_suggestions(num_lists, items_per_list, include_existing_games, include_multiplayer)
68
+
69
+ print("simulplay debug - good to here 4")
70
+
71
+ return formatted_timeline, story, json.dumps(game_structure_with_media, indent=2), suggestions, selected_list_names #no_media_formatted_timeline, json.dumps(game_structure_without_media, indent=2) #, game_structure_with_media
72
+
73
+ media_file_types = ["image", "video", "audio"]
74
+
75
+ def generate_media_file_list(n):
76
+ return [random.choice(media_file_types) for _ in range(n)]
77
+
78
+
79
+ def show_elements(text):
80
+ # Parse the input text
81
+ pattern = r'(\d+): (UI|Story|Media) - (.+)'
82
+ blocks = re.findall(pattern, text)
83
+
84
+ # Sort blocks by their timestamp
85
+ blocks.sort(key=lambda x: int(x[0]))
86
+
87
+ outputs = []
88
+
89
+ for timestamp, block_type, content in blocks:
90
+ if block_type == 'UI':
91
+ # Create HTML for UI elements
92
+ ui_html = f'<div class="ui-element">{content}</div>'
93
+ outputs.append(gr.HTML(ui_html))
94
+ elif block_type == 'Story':
95
+ # Display story elements as Markdown
96
+ outputs.append(gr.Markdown(f"**{content}**"))
97
+ elif block_type == 'Media':
98
+ if content.lower() == 'audio':
99
+ # Placeholder for audio element
100
+ outputs.append(gr.Audio(label=f"Audio at {timestamp} in the order"))
101
+ elif content.lower() == 'video':
102
+ # Placeholder for video element
103
+ outputs.append(gr.Video(label=f"Video at {timestamp} in the order"))
104
+ elif content.lower() == 'image':
105
+ # Placeholder for image element
106
+ outputs.append(gr.Image(label=f"Image at {timestamp} in the order"))
107
+
108
+ return outputs
109
+
110
+ def show_elements_json_input(json_input):
111
+ data = json.loads(json_input)
112
+ masterlocation1 = data['masterlocation1']
113
+
114
+ outputs = []
115
+
116
+ for location, details in masterlocation1.items():
117
+ if location == 'end':
118
+ continue
119
+
120
+ with gr.Accordion(f"Location: {location} - Previous description {details['description']}", open=False):
121
+ description = gr.Textbox(label="Description", value=details['description'], interactive=True)
122
+ outputs.append(description)
123
+
124
+ events = gr.Textbox(label="Events", value=json.dumps(details['events']), interactive=True)
125
+ outputs.append(events)
126
+
127
+ choices = gr.Textbox(label="Choices", value=json.dumps(details['choices']), interactive=True)
128
+ outputs.append(choices)
129
+
130
+ transitions = gr.Textbox(label="Transitions", value=json.dumps(details['transitions']), interactive=True)
131
+ outputs.append(transitions)
132
+
133
+ # New media field
134
+ media = gr.Textbox(label="Media", value=json.dumps(details['media']), interactive=True)
135
+ outputs.append(media)
136
+
137
+ # New developernotes field
138
+ developernotes = gr.Textbox(label="developernotes", value=json.dumps(details['developernotes']), interactive=True)
139
+ outputs.append(developernotes)
140
+
141
+ #adding/removing a field means incrementing/decreasing the i+n to match the fields
142
+ num_current_unique_fields = 6
143
+
144
+ def update_json(*current_values):
145
+ updated_data = {"masterlocation1": {}}
146
+ locations = [loc for loc in masterlocation1.keys() if loc != 'end']
147
+ for i, location in enumerate(locations):
148
+ updated_data["masterlocation1"][location] = {
149
+ "description": current_values[i*num_current_unique_fields],
150
+ "events": json.loads(current_values[i*num_current_unique_fields + 1]),
151
+ "choices": json.loads(current_values[i*num_current_unique_fields + 2]),
152
+ "transitions": json.loads(current_values[i*num_current_unique_fields + 3]),
153
+ "media": json.loads(current_values[i*num_current_unique_fields + 4]), # New media field
154
+ "developernotes": json.loads(current_values[i*num_current_unique_fields + 5])
155
+ }
156
+ updated_data["masterlocation1"]["end"] = masterlocation1["end"]
157
+ return json.dumps(updated_data, indent=2) #json.dumps(updated_data, default=lambda o: o.__dict__, indent=2)
158
+
159
+ update_button = gr.Button("Update JSON - Still need to copy to correct textbox to load")
160
+ json_output = gr.Textbox(label="Updated JSON - Still need to copy to correct textbox to load", lines=10)
161
+ #json_output = gr.Code(label="Updated JSON", lines=10) #Locks whole UI so use textbox
162
+
163
+ update_button.click(update_json, inputs=outputs, outputs=json_output)
164
+
165
+ return outputs + [update_button, json_output] #, json_output_code]
166
+
167
+ def show_elements_json_input_play_and_edit_version(json_input):
168
+ data = json.loads(json_input)
169
+ outputs = []
170
+
171
+ for location_name, location_data in data.items():
172
+ if location_name == "end":
173
+ continue
174
+
175
+ for sub_location, details in location_data.items():
176
+ with gr.Accordion(f"Location: {location_name} - {sub_location}", open=False):
177
+ description = gr.Textbox(label="Description", value=details.get('description', ''), interactive=True)
178
+ outputs.append(description)
179
+
180
+ choices = gr.Textbox(label="Choices", value=json.dumps(details.get('choices', [])), interactive=True)
181
+ outputs.append(choices)
182
+
183
+ transitions = gr.Textbox(label="Transitions", value=json.dumps(details.get('transitions', {})), interactive=True)
184
+ outputs.append(transitions)
185
+
186
+ consequences = gr.Textbox(label="Consequences", value=json.dumps(details.get('consequences', {})), interactive=True)
187
+ outputs.append(consequences)
188
+
189
+ media = gr.Textbox(label="Media", value=json.dumps(details.get('media', [])), interactive=True)
190
+ outputs.append(media)
191
+
192
+ # Add developernotes field if it exists in the config
193
+ if 'developernotes' in details:
194
+ developernotes = gr.Textbox(label="Developer Notes", value=details.get('developernotes', ''), interactive=True)
195
+ outputs.append(developernotes)
196
+
197
+ # Determine the number of fields dynamically
198
+ num_current_unique_fields = 5 if 'developernotes' not in next(iter(next(iter(data.values())).values())) else 6
199
+
200
+ def update_json(*current_values):
201
+ updated_data = {}
202
+ location_names = list(data.keys())
203
+ location_names.remove("end") if "end" in location_names else None
204
+
205
+ value_index = 0
206
+ for location_name in location_names:
207
+ updated_data[location_name] = {}
208
+ sub_locations = list(data[location_name].keys())
209
+
210
+ for sub_location in sub_locations:
211
+ updated_data[location_name][sub_location] = {
212
+ "description": current_values[value_index],
213
+ "choices": json.loads(current_values[value_index + 1]),
214
+ "transitions": json.loads(current_values[value_index + 2]),
215
+ "consequences": json.loads(current_values[value_index + 3]),
216
+ "media": json.loads(current_values[value_index + 4])
217
+ }
218
+ if num_current_unique_fields == 6:
219
+ updated_data[location_name][sub_location]["developernotes"] = current_values[value_index + 5]
220
+ value_index += num_current_unique_fields
221
+
222
+ if "end" in data:
223
+ updated_data["end"] = data["end"]
224
+
225
+ return json.dumps(updated_data, indent=2)
226
+
227
+ update_button = gr.Button("Update JSON")
228
+ json_output = gr.Textbox(label="Updated JSON", lines=10)
229
+
230
+ update_button.click(update_json, inputs=outputs, outputs=json_output)
231
+
232
+ return outputs + [update_button, json_output]
233
+
234
+ def create_media_component(file_path):
235
+ print(file_path)
236
+ _, extension = os.path.splitext(file_path)
237
+ extension = extension.lower()[1:] # Remove the dot and convert to lowercase
238
+
239
+ if extension in ['jpg', 'jpeg', 'png', 'gif', 'webp']:
240
+ return gr.Image(value=file_path, label="Image Input")
241
+ elif extension in ['mp4', 'avi', 'mov']:
242
+ return gr.Video(value=file_path, label="Video Input")
243
+ elif extension in ['mp3', 'wav', 'ogg']:
244
+ return gr.Audio(value=file_path, label="Audio Input")
245
+ else:
246
+ return gr.Textbox(value=file_path, label=f"File: {os.path.basename(file_path)}")
247
+
248
+ def convert_timeline_to_game_structure(timeline):
249
+ lines = timeline.split('\n')
250
+ game_structure = {}
251
+ current_location = 0
252
+ sub_location = 0
253
+
254
+ for i, line in enumerate(lines):
255
+ if line.strip() == "":
256
+ continue
257
+
258
+ if line[0].isdigit(): # New location starts
259
+ current_location += 1
260
+ sub_location = 0
261
+ location_key = f"location{current_location}"
262
+ game_structure[location_key] = {
263
+ "description": "",
264
+ "events": [],
265
+ "choices": ["continue"],
266
+ "transitions": {},
267
+ "media": [],
268
+ "developernotes": []
269
+ }
270
+ else: # Continue with sub-locations or media entries
271
+ sub_location += 1
272
+ location_key = f"location{current_location}_{sub_location}"
273
+
274
+ # Extract the event description
275
+ parts = line.split(': ', 1)
276
+ if len(parts) == 2:
277
+ prefix, rest = parts
278
+ event_parts = rest.split(' - ', 1)
279
+ if len(event_parts) == 2:
280
+ event_type, event_description = event_parts
281
+ else:
282
+ event_type, event_description = "Unknown", rest
283
+ else:
284
+ event_type, event_description = "Unknown", line
285
+
286
+ description = rest.strip() if event_type in ["Media", "UI"] else f"{event_type}: {event_description}"
287
+
288
+ if sub_location == 0:
289
+ game_structure[f"location{current_location}"]["description"] = description
290
+ else:
291
+ game_structure[f"location{current_location}"]["events"].append({
292
+ "description": description,
293
+ "type": event_type
294
+ })
295
+
296
+ # Set the transition to the next location or to the end
297
+ if i < len(lines) - 1:
298
+ next_line = lines[i + 1].strip()
299
+ if next_line and next_line[0].isdigit(): # New location starts
300
+ game_structure[f"location{current_location}"]["transitions"]["continue"] = f"masterlocation1_location{current_location + 1}"
301
+ else:
302
+ #game_structure[f"location{current_location}"]["transitions"]["continue"] = f"location_{current_location}_{sub_location + 1}"
303
+ game_structure[f"location{current_location}"]["transitions"]["continue"] = "end"
304
+ else:
305
+ game_structure[f"location{current_location}"]["transitions"]["continue"] = "end"
306
+
307
+ # Add an end location
308
+ game_structure["end"] = {
309
+ "description": "The adventure ends here.",
310
+ # "choices": [],
311
+ # "transitions": {}
312
+ "choices": ["restart"],
313
+ "transitions": {"restart": "location1"} # Assuming location_1 is the start
314
+
315
+ }
316
+
317
+ # Wrap the game structure in master_location1
318
+ wrapped_structure = {"masterlocation1": game_structure}
319
+
320
+ return wrapped_structure
321
+
322
+ # def generate_game_structures(timeline_with_media): #, timeline_without_media):
323
+
324
+ # game_structure_with_media = convert_timeline_to_game_structure(timeline_with_media)
325
+ # #game_structure_without_media = convert_timeline_to_game_structure(timeline_without_media)
326
+
327
+ # return game_structure_with_media #, game_structure_without_media
328
+
329
+
330
+ # def timeline_get_random_suggestions(num_lists, items_per_list):
331
+ # """
332
+ # Generate random suggestions from a specified number of lists.
333
+
334
+ # :param num_lists: Number of lists to consider
335
+ # :param items_per_list: Number of items to select from each list
336
+ # :return: A list of randomly selected suggestions
337
+ # """
338
+ # selected_lists = random.sample(all_idea_lists, min(num_lists, len(all_idea_lists)))
339
+ # suggestions = []
340
+
341
+ # for lst in selected_lists:
342
+ # suggestions.extend(random.sample(lst, min(items_per_list, len(lst))))
343
+
344
+ # return suggestions
345
+
346
+ def timeline_get_random_suggestions(num_lists, items_per_list, include_existing_games, include_multiplayer):
347
+ """
348
+ Generate random suggestions from a specified number of lists.
349
+
350
+ :param num_lists: Number of lists to consider
351
+ :param items_per_list: Number of items to select from each list
352
+ :param include_existing_games: Whether to include existing game inspiration lists
353
+ :param include_multiplayer: Whether to include multiplayer features list
354
+ :return: A tuple containing the list of randomly selected suggestions and the names of selected lists
355
+ """
356
+ available_lists = all_idea_lists.copy()
357
+ if not include_existing_games:
358
+ available_lists = [lst for lst in available_lists if lst not in existing_game_inspirations]
359
+ if not include_multiplayer:
360
+ available_lists = [lst for lst in available_lists if lst != multiplayer_features]
361
+
362
+ selected_lists = random.sample(available_lists, min(num_lists, len(available_lists)))
363
+ suggestions = []
364
+ selected_list_names = []
365
+
366
+ for lst in selected_lists:
367
+ suggestions.extend(random.sample(lst, min(items_per_list, len(lst))))
368
+ selected_list_names.append(list_names[all_idea_lists.index(lst)])
369
+
370
+ return suggestions, selected_list_names
ui_gr_media_management.py ADDED
@@ -0,0 +1,429 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from file_explorer_and_upload import *
3
+ from state_prompt_fileman_UI_functions import *
4
+ from my_text_game_engine_attempt import display_website
5
+
6
+ def TestGradioClientQwen270b(text):
7
+ # client = Client("Qwen/Qwen2-72B-Instruct")
8
+ # result = client.predict(
9
+ # query=text, #"Hello!!",
10
+ # history=[],
11
+ # system="You are a helpful assistant.",
12
+ # api_name="/model_chat"
13
+ # )
14
+
15
+ client = Client("huggingface-projects/gemma-2-9b-it")
16
+ result = client.predict(
17
+ message=text, #"Hello!!",
18
+ max_new_tokens=1024,
19
+ temperature=0.6,
20
+ top_p=0.9,
21
+ top_k=50,
22
+ repetition_penalty=1.2,
23
+ api_name="/chat"
24
+ )
25
+ #print(result)
26
+
27
+ #print(result[1][0]) #All messages in the conversation
28
+ #print(result[2]) # System prompt
29
+ return result #result[1][0][1] # If supporting conversations this needs to return the last message instead
30
+
31
+ def SPFManJLget_config_part(config_json, location, part):
32
+ if not config_json:
33
+ return {"error": "No configuration provided."}
34
+
35
+ try:
36
+ config = json.loads(config_json)
37
+ location_config = config.get(location, {})
38
+ return location_config.get(part, {"error": f"Part '{part}' not found in '{location}' configuration."})
39
+ except json.JSONDecodeError:
40
+ return {"error": "Invalid JSON format."}
41
+
42
+ def SPFManJLupdate_location_choices(config_json):
43
+ if not config_json:
44
+ return gr.update(choices=[], value=""), gr.update(choices=[], value="")
45
+
46
+ try:
47
+ config = json.loads(config_json)
48
+ locations = list(config.keys())
49
+ return (gr.update(choices=locations, value=locations[0] if locations else ""),
50
+ gr.update(choices=[], value=""))
51
+ except json.JSONDecodeError:
52
+ return gr.update(choices=[], value=""), gr.update(choices=[], value="")
53
+
54
+ def SPFManJLupdate_part_choices(config_json, location):
55
+ if not config_json or not location:
56
+ return gr.update(choices=[], value="")
57
+
58
+ try:
59
+ config = json.loads(config_json)
60
+ location_config = config.get(location, {})
61
+ parts = list(location_config.keys())
62
+ return gr.update(choices=parts, value=parts[0] if parts else "")
63
+ except json.JSONDecodeError:
64
+ return gr.update(choices=[], value="")
65
+
66
+ def SPFManJLPromptSuggestionGradClient(config, additionalnotes):
67
+ prompt = f"Here is a config for a game and our job is to poulate the media field to fit the context: \n{config} \nadditional information from the user: \n{additionalnotes}"
68
+ FinalOutput = TestGradioClientQwen270b(text=prompt)
69
+
70
+ return FinalOutput
71
+
72
+ SPFManload_state()
73
+
74
+
75
+ def ui_gr_media_management_acc():
76
+ with gr.Accordion("Incomplete Media Management Assist - click to open", open=False) as filemanager:
77
+ gr.HTML("Make Files and Text ideas for the field and paste <br>When Space is restarted it will clear - zip export and import will be added later")
78
+ #with gr.Tab("Media Management Assistance"): #, open=False):
79
+ with gr.Accordion("Some Idea / Inspiration Sources / Demos", open=False):
80
+ with gr.Row():
81
+ gr.HTML("Licenses for the spaces still to be evaluated - June 2024 <br> Users to follow with cool spaces - <br>https://huggingface.co/osanseviero - https://huggingface.co/spaces/osanseviero/TheMLGame <br>https://huggingface.co/jbilcke-hf <br>https://huggingface.co/dylanebert <br>https://huggingface.co/fffiloni <br>https://huggingface.co/artificialguybr <br>https://huggingface.co/radames <br>https://huggingface.co/multimodalart, ")
82
+ gr.HTML("Some Youtube Channels to keep up with updates <br><br>https://www.youtube.com/@lev-selector <br>https://www.youtube.com/@fahdmirza/videos")
83
+ gr.HTML("Social media that shows possiblities <br><br>https://www.reddit.com/r/aivideo/ https://www.reddit.com/r/StableDiffusion/ https://www.reddit.com/r/midjourney/ https://x.com/blizaine https://www.reddit.com/r/singularity/comments/1ead7vp/not_sure_if_this_is_the_right_place_to_post_but_i/ https://www.reddit.com/r/singularity/comments/1ebpra6/the_big_reveal_book_trailer_made_with_runway_gen3/ https://www.reddit.com/r/LocalLLaMA/comments/1e3aboz/folks_with_one_24gb_gpu_you_can_use_an_llm_sdxl/ <br>https://www.reddit.com/r/singularity/comments/1f81ira/utilizing_ai_in_solo_game_development_my/ <br>https://www.reddit.com/r/singularity/comments/1fhe402/another_runawaymls_vid_to_vid_testing_for_first/ <br>https://www.reddit.com/r/singularity/comments/1fh08nz/runawaymls_new_videotovideo_feature_is_crazy/ <br> https://www.reddit.com/r/singularity/comments/1fe4rkv/6_chinese_ai_video_generator_comparisons_hailuo/")
84
+ with gr.Accordion("Upload Files for config", open=False):
85
+ gr.Markdown("# Media Saver and Explorer (refresh file list to be resolved - for now upload all files and reload the space - they persist as long as the space creator doesnt reset/update the space - will add manual clear options later)")
86
+ with gr.Tab("Upload Files"):
87
+ file_input = gr.File(label="Choose File to Upload")
88
+ save_output = gr.Textbox(label="Upload Status")
89
+
90
+ with gr.Tab("File Explorer"):
91
+
92
+ file_explorer = gr.FileExplorer(
93
+ root_dir=SAVE_DIR,
94
+ glob="*.*",
95
+ file_count="single",
96
+ height=300,
97
+ label="Select a file to view"
98
+ )
99
+ with gr.Row():
100
+ refresh_button = gr.Button("Refresh", scale=1)
101
+ view_button = gr.Button("View File")
102
+ image_output = gr.Image(label="Image Output", type="pil")
103
+ audio_output = gr.Audio(label="Audio Output")
104
+ video_output = gr.Video(label="Video Output")
105
+ error_output = gr.Textbox(label="Error")
106
+
107
+ file_input.upload(
108
+ save_file,
109
+ inputs=file_input,
110
+ outputs=[save_output, file_explorer, file_input]
111
+ )
112
+
113
+ view_button.click(
114
+ view_file,
115
+ inputs=file_explorer,
116
+ outputs=[image_output, audio_output, video_output, error_output]
117
+ )
118
+
119
+ refresh_button.click(
120
+ refresh_file_explorer,
121
+ outputs=file_explorer
122
+ )
123
+
124
+ with gr.Tab("Batch add files to config"):
125
+ gr.HTML("Placeholder for Config parser to allow dropdowns for the media parts of the config inserted to make assigning media quick")
126
+ gr.HTML("Placeholder for Config parser to allow for current zerospace creation and placement into the config (LLM can give list of media but still have to figure out workflow from there)")
127
+ gr.Interface(import_config_with_media, inputs=["file"], outputs=["code", "text"], description="Uploads the files needed for your config and present config for loading somewhere else")
128
+
129
+ gr.HTML("Placeholder for clearing uploaded assets (public space and temporary persistence = sharing and space problems)")
130
+
131
+ with gr.Tab("Using Embedded HF spaces / Premade files in external sources"):
132
+ gr.HTML("Generate the files and then sort and manage them in their appropriate field in the config")
133
+ gr.HTML("Currently - need to create then save to pc then reupload to use here in test tab")
134
+ gr.HTML("Whole game engine in a space? - https://huggingface.co/spaces/thomwolf/test_godot_editor <br><br> https://huggingface.co/godot-demo https://huggingface.co/spaces/thomwolf/test_godot")
135
+
136
+ with gr.Accordion("Media Suggestions based on config"):
137
+ #gr.Interface( , description="Load a config and get some prompt ideas")
138
+ gr.HTML("Either duplicate the interface on the api side or move it out so that both sides can use it")
139
+
140
+ with gr.Tab("Text-based"):
141
+ gr.HTML("Some Benchmark Leaderboards - https://huggingface.co/spaces/allenai/ZebraLogic | https://huggingface.co/spaces/allenai/WildBench https://scale.com/leaderboard https://livebench.ai")
142
+ with gr.Accordion("LLM HF Spaces/Sites (Click Here to Open) - Ask for a story and suggestions based on the autoconfig", open=False):
143
+ with gr.Row():
144
+ linktochat = gr.Dropdown(choices=[ "--Long Output--", "https://thudm-longwriter.hf.space",
145
+ "--Function Calling--", "https://groq-demo-groq-tool-use.hf.space",
146
+ "--Multiple Models--", "https://huggingface.co/spaces/nvidia/minitron", "https://lmsys-gpt-4o-mini-battles.hf.space", "https://labs.perplexity.ai/", "https://chat.lmsys.org", "https://sdk.vercel.ai/docs", "https://cyzgab-catch-me-if-you-can.hf.space",
147
+ "--11B and above--", "https://llamameta-llama3-1-405b.static.hf.space", "https://qwen-qwen-max-0428.hf.space", "https://cohereforai-c4ai-command-r-plus.hf.space", "https://qwen-qwen1-5-110b-chat-demo.hf.space",
148
+ "--70B and above--", "https://cognitivecomputations-chat.hf.space", "https://snowflake-snowflake-arctic-st-demo.hf.space", "https://databricks-dbrx-instruct.hf.space", "https://qwen-qwen1-5-72b-chat.hf.space",
149
+ "--20B and above--", "https://grin-moe-demo-grin-moe.hf.space", "https://gokaygokay-gemma-2-llamacpp.hf.space", "https://01-ai-yi-34b-chat.hf.space", "https://cohereforai-c4ai-command-r-v01.hf.space", "https://ehristoforu-mixtral-46-7b-chat.hf.space", "https://mosaicml-mpt-30b-chat.hf.space",
150
+ "--7B and above--", "https://vilarin-mistral-nemo.hf.space", "https://arcee-ai-arcee-scribe.hf.space", "https://vilarin-llama-3-1-8b-instruct.hf.space", "https://ysharma-chat-with-meta-llama3-8b.hf.space", "https://qwen-qwen1-5-moe-a2-7b-chat-demo.hf.space", "https://deepseek-ai-deepseek-coder-7b-instruct.hf.space", "https://osanseviero-mistral-super-fast.hf.space", "https://artificialguybr-qwen-14b-chat-demo.hf.space", "https://huggingface-projects-llama-2-7b-chat.hf.space",
151
+ "--1B and above--", "https://huggingface.co/spaces/eswardivi/Phi-3-mini-128k-instruct", "https://eswardivi-phi-3-mini-4k-instruct.hf.space", "https://stabilityai-stablelm-2-1-6b-zephyr.hf.space",
152
+ "--under 1B--",
153
+ "--unorganised--", "https://ysharma-zephyr-playground.hf.space", "https://huggingfaceh4-zephyr-chat.hf.space", "https://ysharma-explore-llamav2-with-tgi.hf.space", "https://huggingfaceh4-falcon-chat.hf.space", "https://uwnlp-guanaco-playground-tgi.hf.space", "https://stabilityai-stablelm-tuned-alpha-chat.hf.space", "https://mosaicml-mpt-7b-storywriter.hf.space", "https://huggingfaceh4-starchat-playground.hf.space", "https://bigcode-bigcode-playground.hf.space", "https://mosaicml-mpt-7b-chat.hf.space", "https://huggingchat-chat-ui.hf.space", "https://togethercomputer-openchatkit.hf.space"], label="Choose/Cancel type any .hf.space link here (can also type a link)'", allow_custom_value=True)
154
+ chatspacebtn = gr.Button("Use the chosen URL to load interface with a chat model. For sdk.vercel click the chat button on the top left. For lymsys / chat arena copy the link and use a new tab")
155
+ chatspace = gr.HTML("Chat Space Chosen will load here")
156
+ chatspacebtn.click(display_website, inputs=linktochat, outputs=chatspace)
157
+
158
+ with gr.Tab("Media Understanding"):
159
+ gr.HTML("NPC Response Engines? Camera, Shopkeeper, Companion, Enemies, etc.")
160
+ with gr.Accordion("Media understanding model Spaces/Sites (Click Here to Open)", open=False):
161
+ with gr.Row():
162
+ linktomediaunderstandingspace = gr.Dropdown(choices=[ "--Weak Audio Understanding = Audio to text, Weak Video Understanding = Video to Image to Image Understanding", "https://skalskip-florence-2-video.hf.space", "https://kingnish-opengpt-4o.hf.space",
163
+ "--Audio Understanding--", "https://jan-hq-llama3-1-s-v0-2.hf.space",
164
+ "--Video Understanding--", "https://ivgsz-flash-vstream-demo.hf.space",
165
+ "--Image Understanding--", "https://gokaygokay-flux-prompt-generator.hf.space", "https://gokaygokay-florence-2.hf.space", "https://vilarin-vl-chatbox.hf.space", "https://qnguyen3-nanollava.hf.space", "https://skalskip-better-florence-2.hf.space", "https://merve-llava-interleave.hf.space",
166
+ "--Img-to-img Understanding--", "https://merve-draw-to-search-art.hf.space",
167
+ "--Image Understanding without conversation--", "https://epfl-vilab-4m.hf.space", "https://epfl-vilab-multimae.hf.space", "https://gokaygokay-sd3-long-captioner.hf.space" ],
168
+ label="Choose/Cancel type any .hf.space link here (can also type a link)'", allow_custom_value=True)
169
+ mediaunderstandingspacebtn = gr.Button("Use the chosen URL to load interface with a media understanding space")
170
+ mediaunderstandingspace = gr.HTML("Mdeia Understanding Space Chosen will load here")
171
+ mediaunderstandingspacebtn.click(display_website, inputs=linktomediaunderstandingspace, outputs=mediaunderstandingspace)
172
+ gr.HTML("Image Caption = https://huggingface.co/spaces/microsoft/Promptist (Prompt Lengthen) ")
173
+
174
+
175
+ with gr.Tab("Images"):
176
+ with gr.Accordion("Image Gen or Animation HF Spaces/Sites (Click Here to Open) - Have to download and upload at the the top", open=False):
177
+ # with gr.Tabs("General"):
178
+ with gr.Row():
179
+ linktoimagegen = gr.Dropdown(choices=["--Text-Interleaved--", "https://ethanchern-anole.hf.space",
180
+ "--Hidden Image--", "https://ap123-illusiondiffusion.hf.space",
181
+ "--Panorama--", "https://gokaygokay-360panoimage.hf.space",
182
+ "--General--", "https://pixart-alpha-pixart-sigma.hf.space", "https://stabilityai-stable-diffusion-3-medium.hf.space", "https://prodia-sdxl-stable-diffusion-xl.hf.space", "https://prodia-fast-stable-diffusion.hf.space", "https://bytedance-hyper-sdxl-1step-t2i.hf.space", "https://multimodalart-cosxl.hf.space", "https://cagliostrolab-animagine-xl-3-1.hf.space", "https://stabilityai-stable-diffusion.hf.space",
183
+ "--Speed--", "https://radames-real-time-text-to-image-sdxl-lightning.hf.space", "https://ap123-sdxl-lightning.hf.space",
184
+ "--LORA Support--", "https://multimodalart-flux-lora-the-explorer.hf.space", "https://artificialguybr-artificialguybr-demo-lora.hf.space", "https://artificialguybr-studio-ghibli-lora-sdxl.hf.space", "https://artificialguybr-pixel-art-generator.hf.space", "https://fffiloni-sdxl-control-loras.hf.space", "https://ehristoforu-dalle-3-xl-lora-v2.hf.space",
185
+ "--Image to Image--", "https://gokaygokay-kolorsplusplus.hf.space", "https://lllyasviel-ic-light.hf.space", "https://gparmar-img2img-turbo-sketch.hf.space",
186
+ "--Upscaler--", "https://gokaygokay-tile-upscaler.hf.space",
187
+ "--Control of Pose--", "https://instantx-instantid.hf.space", "https://modelscope-transferanything.hf.space", "https://okaris-omni-zero.hf.space"
188
+ "--Control of Shapes--", "https://linoyts-scribble-sdxl-flash.hf.space",
189
+ "--Control of Text--", "",
190
+ "--Clothing Try on demos--", "https://kwai-kolors-kolors-virtual-try-on.hf.space",
191
+ "--Foreign Language Input--", "https://gokaygokay-kolors.hf.space"], label="Choose/Cancel type any .hf.space link here (can also type a link)'", allow_custom_value=True)
192
+ imagegenspacebtn = gr.Button("Use the chosen URL to load interface with a image generation model")
193
+
194
+ imagegenspace = gr.HTML("Image Space Chosen will load here")
195
+ imagegenspacebtn.click(display_website, inputs=linktoimagegen, outputs=imagegenspace)
196
+
197
+ linkstobecollectednoembed = "https://artgan-diffusion-api.hf.space", "https://multimodalart-stable-cascade.hf.space", "https://google-sdxl.hf.space", "https://visionmaze-magic-me.hf.space", "https://segmind-segmind-stable-diffusion.hf.space", "https://simianluo-latent-consistency-model.hf.space",
198
+ gr.HTML("Concept Art, UI elements, Static/3D Characters, Environments and Objects")
199
+ gr.HTML("Images Generation General (3rd Party) = https://www.craiyon.com/")
200
+ gr.HTML("Images Generation Posters with text - https://huggingface.co/spaces/GlyphByT5/Glyph-SDXL-v2")
201
+ gr.HTML("SVG Generation = Coding models / SOTA LLM ")
202
+ gr.HTML("Images Generation - Upscaling - https://huggingface.co/spaces/gokaygokay/Tile-Upscaler")
203
+ gr.HTML("Vision Models for descriptions <br> https://huggingface.co/spaces/gokaygokay/Florence-2 <br>https://huggingface.co/spaces/vilarin/VL-Chatbox - glm 4v 9b <br>")
204
+ gr.HTML("Upscalers (save data transfer costs? highly detailed characters?) - https://huggingface.co/spaces/gokaygokay/AuraSR")
205
+ gr.HTML("Placeholder for huggingface spaces that can assist ")
206
+ gr.HTML("Placeholder for models small enough to run on cpu here in this space that can assist")
207
+
208
+ with gr.Tab("Video"):
209
+ with gr.Accordion("Video Spaces/Sites (Click Here to Open)", open=False):
210
+ with gr.Row():
211
+ linktovideogenspace = gr.Dropdown(choices=["--Texttovid--", "https://kingnish-instant-video.hf.space",
212
+ "--General--", "https://zheyangqin-vader.hf.space", "https://kadirnar-open-sora.hf.space",
213
+ "--Talking Portrait--", "https://fffiloni-tts-hallo-talking-portrait.hf.space",
214
+ "--Gif / ImgtoImg based video--", "https://wangfuyun-animatelcm-svd.hf.space", "https://bytedance-animatediff-lightning.hf.space", "https://wangfuyun-animatelcm.hf.space", "https://guoyww-animatediff.hf.space",],
215
+ label="Choose/Cancel type any .hf.space link here (can also type a link)'", allow_custom_value=True)
216
+ videogenspacebtn = gr.Button("Use the chosen URL to load interface with video generation")
217
+ videogenspace = gr.HTML("Video Space Chosen will load here")
218
+ videogenspacebtn.click(display_website, inputs=linktovideogenspace, outputs=videogenspace)
219
+
220
+ gr.HTML("Cutscenes, Tutorials, Trailers")
221
+ gr.HTML("Portrait Video eg. Solo Taking NPC - https://huggingface.co/spaces/fffiloni/tts-hallo-talking-portrait (Image + Audio and combination) https://huggingface.co/spaces/KwaiVGI/LivePortrait (Non verbal communication eg. in a library, when running from a pursuer)")
222
+ gr.HTML("Placeholder for huggingface spaces that can assist - https://huggingface.co/spaces/KingNish/Instant-Video, https://huggingface.co/spaces/multimodalart/stable-video-diffusion, https://huggingface.co/spaces/multimodalart/stable-video-diffusion")
223
+ gr.HTML("Placeholder for models small enough to run on cpu here in this space that can assist")
224
+ gr.HTML("3rd Party / Closed Source - https://runwayml.com/ <br>")
225
+ with gr.Tab("Animations (for lower resource use)"):
226
+ gr.HTML("Characters, Environments, Objects")
227
+ gr.HTML("Placeholder for huggingface spaces that can assist - image as 3d object in video https://huggingface.co/spaces/ashawkey/LGM")
228
+ gr.HTML("Placeholder for models small enough to run on cpu here in this space that can assist")
229
+
230
+ with gr.Tab("Audio"):
231
+ with gr.Accordion("Audio Spaces/Sites (Click Here to Open)", open=False):
232
+ with gr.Row():
233
+ linktoaudiogenspace = gr.Dropdown(choices=["General", "https://artificialguybr-stable-audio-open-zero.hf.space", "",
234
+ "--Talking Portrait--","https://fffiloni-tts-hallo-talking-portrait.hf.space"],
235
+ label="Choose/Cancel type any .hf.space link here (can also type a link)'", allow_custom_value=True)
236
+ audiogenspacebtn = gr.Button("Use the chosen URL to load interface with audio generation")
237
+ audiogenspace = gr.HTML("Audio Space Chosen will load here")
238
+ audiogenspacebtn.click(display_website, inputs=linktoaudiogenspace, outputs=audiogenspace)
239
+ gr.HTML("Music - Background, Interactive, Cutscene, Menu <br>Sound Effects - Environment, character, action (environmental triggered by user eg. gun), UI <br>Speech - Dialouge, narration, voiceover <br>The new render function means the Config can be made and iframe/api functions can be ordered as neccessary based on the part of the config that needs it to streamline workflows based on current state of config ")
240
+ gr.HTML("Placeholder for huggingface spaces that can assist")
241
+ gr.HTML("Audio Sound Effects - https://huggingface.co/spaces/artificialguybr/Stable-Audio-Open-Zero")
242
+ gr.HTML("Voices - Voice clone eg. actors part of your project - https://huggingface.co/spaces/tonyassi/voice-clone")
243
+ gr.HTML("Placeholder for models small enough to run on cpu here in this space that can assist")
244
+ gr.HTML("3rd Party / Closed Source - https://suno.com/ <br>https://www.udio.com/")
245
+
246
+ with gr.Tab("3D"):
247
+ with gr.Accordion("3D Model Spaces/Sites (Click Here to Open)", open=False):
248
+ with gr.Row():
249
+ linktoThreedModel = gr.Dropdown(choices=["--Image prompt--", "https://vast-ai-charactergen.hf.space"
250
+ "--Video prompt--", "https://facebook-vggsfm.hf.space",
251
+ "--Text prompt--", "https://wuvin-unique3d.hf.space", "https://stabilityai-triposr.hf.space", "https://hysts-shap-e.hf.space", "https://tencentarc-instantmesh.hf.space", "https://ashawkey-lgm.hf.space", "https://dylanebert-lgm-mini.hf.space", "https://dylanebert-splat-to-mesh.hf.space", "https://dylanebert-multi-view-diffusion.hf.space"], label="Choose/Cancel type any .hf.space link here (can also type a link)'", allow_custom_value=True)
252
+ ThreedModelspacebtn = gr.Button("Use the chosen URL to load interface with a 3D model")
253
+ ThreedModelspace = gr.HTML("3D Space Chosen will load here")
254
+ ThreedModelspacebtn.click(display_website, inputs=linktoThreedModel, outputs=ThreedModelspace)
255
+ gr.HTML("Characters, Environments, Objects")
256
+ gr.HTML("Placeholder for huggingface spaces that can assist - https://huggingface.co/spaces/dylanebert/3d-arena")
257
+ gr.HTML("Closed Source - https://www.meshy.ai/")
258
+
259
+ with gr.Tab("Fonts"):
260
+ gr.HTML("Style of whole game, or locations, or characters")
261
+ gr.HTML("Placeholder for huggingface spaces that can assist - there was a space that could make letter into pictures based on the prompt but I cant find it now")
262
+ gr.HTML("Placeholder for models small enough to run on cpu here in this space that can assist")
263
+
264
+ with gr.Tab("Shaders and related"):
265
+ with gr.Accordion("'Special Effects' Spaces/Sites (Click Here to Open)", open=False):
266
+ with gr.Row():
267
+ linktospecialeffectsgenspace = gr.Dropdown(choices=["--Distorted Image--", "https://epfl-vilab-4m.hf.space", "https://epfl-vilab-multimae.hf.space"],
268
+ label="Choose/Cancel type any .hf.space link here (can also type a link)'", allow_custom_value=True)
269
+ specialeffectsgenspacebtn = gr.Button("Use the chosen URL to load interface with special effects generation")
270
+ specialeffectsgenspace = gr.HTML("Special Effects Space Chosen will load here")
271
+ specialeffectsgenspacebtn.click(display_website, inputs=linktospecialeffectsgenspace, outputs=specialeffectsgenspace)
272
+ gr.HTML("Any output that is not understood by the common person can be used as special effects eg. depth map filters on images etc.")
273
+ gr.HTML("Post-processing Effects, material effects, Particle systems, visual feedback")
274
+ gr.HTML("Visual Effects - eg. explosion can turn all items white for a moment, losing conciousness blurs whole screen")
275
+ gr.HTML("Placeholder for models small enough to run on cpu here in this space that can assist")
276
+
277
+ with gr.Tab("NPCS"):
278
+ gr.HTML("For ideas on NPCS check: https://lifearchitect.ai/leta/, ")
279
+ with gr.Tab("Save files"):
280
+ gr.HTML("For Dynamic events overnight or when player is not active what can LLMS edit? <br><br>eg. Waiting for a letter from a random npc can be decided by the llm <br>eg. Improved Stats on certain days (eg. bitrthday) <br>Privacy <br>User Directed DLC eg. Rockstar Editor with local llm guide")
281
+ gr.HTML("Some ideas - In game websites eg. GTA esp stock markets, news; ")
282
+ gr.HTML("Placeholder for huggingface spaces that can assist - https://huggingface.co/nvidia/Nemotron-4-340B-Instruct (Purpose is supposed to be synthetic data generation), https://huggingface.co/spaces/gokaygokay/Gemma-2-llamacpp ")
283
+ gr.HTML("Placeholder for models small enough to run on cpu here in this space that can assist (9b and under) <br>initial floor for testing can be https://huggingface.co/spaces/Qwen/Qwen2-0.5B-Instruct, https://huggingface.co/spaces/Qwen/Qwen2-1.5b-instruct-demo, https://huggingface.co/spaces/stabilityai/stablelm-2-1_6b-zephyr, https://huggingface.co/spaces/IndexTeam/Index-1.9B, https://huggingface.co/microsoft/Phi-3-mini-4k-instruct")
284
+ with gr.Tab("Diagrams"):
285
+ gr.HTML("Claude 3.5 sonnet is very good with mermaid graphs - can used for maps, situational explanations")
286
+ with gr.Tab("Maths"):
287
+ gr.HTML("https://huggingface.co/spaces/AI-MO/math-olympiad-solver")
288
+
289
+ with gr.Tab("Using gradio client / External Source as API provider"):
290
+ gr.HTML("State file managed and one item at time creation using gradio client")
291
+ with gr.Tab("Bulk Generate Assets"):
292
+ with gr.Tab("Load Configuration"):
293
+ with gr.Row():
294
+ SPFManconfig_file = gr.File(label="Load Configuration File")
295
+ SPFManload_config_button = gr.Button("Load Configuration")
296
+ SPFManload_result = gr.Textbox(label="Load Result")
297
+
298
+ with gr.Tab("Manage Prompts"):
299
+ with gr.Accordion("Load the current game state that you want to add media to", open=False):
300
+ gr.Markdown("# Load and View Game Configuration")
301
+
302
+ with gr.Accordion("Click to hide config for space"):
303
+ SPFManJLconfig_input = gr.Textbox(label="Enter Game Configuration JSON", placeholder="Paste JSON config here", lines=4)
304
+ SPFManJLlocation_choice = gr.Dropdown(choices=[], label="Choose location")
305
+ SPFManJLpart_choice = gr.Dropdown(choices=[], label="Choose part")
306
+ SPFManJLconfig_view = gr.JSON(label="Configuration Details")
307
+
308
+ SPFManJLconfig_input.change(fn=SPFManJLupdate_location_choices, inputs=SPFManJLconfig_input, outputs=[SPFManJLlocation_choice, SPFManJLpart_choice])
309
+ SPFManJLlocation_choice.change(fn=SPFManJLupdate_part_choices, inputs=[SPFManJLconfig_input, SPFManJLlocation_choice], outputs=SPFManJLpart_choice)
310
+
311
+ def SPFManJLupdate_config_view(config_json, location, part):
312
+ return SPFManJLget_config_part(config_json, location, part)
313
+
314
+ SPFManJLpart_choice.change(fn=SPFManJLupdate_config_view, inputs=[SPFManJLconfig_input, SPFManJLlocation_choice, SPFManJLpart_choice], outputs=SPFManJLconfig_view)
315
+
316
+ gr.Interface(SPFManJLPromptSuggestionGradClient, inputs=[SPFManJLconfig_view, "text"], outputs=["text"], description="Ask a random LLM for suggestions eg. bring life to the game by focusing more on the description")
317
+
318
+ with gr.Row():
319
+ SPFManprompt_type = gr.Dropdown(["image", "audio"], label="Prompt Type")
320
+ SPFManprompt = gr.Textbox(label="Prompt")
321
+ with gr.Row():
322
+ SPFManadd_button = gr.Button("Add Prompt")
323
+ SPFManclear_button = gr.Button("Clear Prompts")
324
+ SPFManauto_generate_button = gr.Button("Auto-Generate Prompt")
325
+ with gr.Row():
326
+ SPFManprompt_output = gr.Textbox(label="Added Prompts")
327
+ SPFManprompt_count = gr.Number(value=0, label="Number of Prompts")
328
+ SPFManview_prompts_button = gr.Button("View All Prompts")
329
+ SPFManall_prompts_output = gr.Textbox(label="All Prompts", lines=10)
330
+ #SPFManconfig_view = gr.Textbox(label="Current Configuration", lines=10)
331
+
332
+ # New JSON input for loading configurations
333
+ #SPFManjson_input = gr.Textbox(label="JSON Configuration", lines=10)
334
+ #SPFManload_json_button = gr.Button("Load JSON Configuration")
335
+
336
+ # Link the button to the function
337
+ #SPFManload_json_button.click(SPFManload_json_configuration, inputs=[SPFManjson_input], outputs=[load_result, prompt_count])
338
+
339
+ with gr.Tab("API Settings"):
340
+ with gr.Row():
341
+ SPFManapi_provider = gr.Textbox(label="API Provider", value=lambda: SPFManstate["api_provider"])
342
+ SPFMancost_per_item = gr.Number(label="Cost per Item", value=lambda: SPFManstate["cost_per_item"])
343
+ SPFManupdate_api_button = gr.Button("Update API Details")
344
+ SPFManapi_update_result = gr.Textbox(label="API Update Result")
345
+
346
+ with gr.Tab("Generate Files and Media"):
347
+ with gr.Row():
348
+ SPFManoutput_dir = gr.Textbox(label="Output Directory", value=lambda: SPFManstate["output_dir"])
349
+ SPFManresume = gr.Checkbox(label="Resume from last run", value=True)
350
+ with gr.Row():
351
+ SPFManpaid_api_checkbox = gr.Checkbox(label="Use Paid API", value=lambda: SPFManstate["is_paid_api"])
352
+ SPFMancost_estimate = gr.Textbox(label="Estimated Cost")
353
+ SPFMangenerate_button = gr.Button("Generate Files and Media")
354
+ SPFManskip_button = gr.Button("Skip Current Item")
355
+ SPFManresults = gr.Textbox(label="Results", lines=10)
356
+ SPFManerror_output = gr.Textbox(label="Errors", lines=5)
357
+ SPFManzip_button = gr.Button("Zip Output Files")
358
+ SPFManzip_result = gr.Textbox(label="Zip Result")
359
+
360
+ SPFManload_config_button.click(SPFManload_config_file, inputs=[SPFManconfig_file], outputs=[SPFManload_result, SPFManprompt_count])
361
+ SPFManadd_button.click(SPFManadd_prompt, inputs=[SPFManprompt_type, SPFManprompt], outputs=[SPFManprompt_output, SPFManprompt_count])
362
+ SPFManclear_button.click(SPFManclear_prompts, outputs=[SPFManprompt_output, SPFManprompt_count])
363
+ SPFManview_prompts_button.click(SPFManview_all_prompts, outputs=SPFManall_prompts_output)
364
+ SPFManauto_generate_button.click(SPFManauto_generate_prompt, inputs=[SPFManprompt_type], outputs=[SPFManprompt])
365
+ SPFManupdate_api_button.click(SPFManupdate_api_details, inputs=[SPFManapi_provider, SPFMancost_per_item], outputs=[SPFManapi_update_result])
366
+ SPFManpaid_api_checkbox.change(SPFMantoggle_paid_api, inputs=[SPFManpaid_api_checkbox], outputs=[SPFMancost_estimate])
367
+ SPFMangenerate_button.click(SPFMancreate_files_with_generation, inputs=[SPFManresume], outputs=SPFManresults)
368
+ SPFManskip_button.click(SPFManskip_item, outputs=SPFManresults)
369
+ SPFManzip_button.click(SPFManzip_files, outputs=SPFManzip_result)
370
+ gr.Textbox(label="Configuration", value=SPFManview_config, every=1)
371
+
372
+ with gr.Tab("Replicate - API Definitions crucial models"):
373
+ gr.HTML("Many custom models set-up and the ability to set up the neccesary ones using cog <br> https://replicate.com/collections/text-to-image | https://replicate.com/collections/text-to-video | https://replicate.com/collections/audio-generation https://replicate.com/collections/text-to-speech | https://replicate.com/collections/3d-models ")
374
+ gr.Code("""Install Replicate’s Python client library
375
+ pip install replicate
376
+
377
+ Copy
378
+ Set the REPLICATE_API_TOKEN environment variable
379
+ export REPLICATE_API_TOKEN=<paste-your-token-here>
380
+
381
+ Visibility
382
+
383
+ Copy
384
+ Find your API token in your account settings.
385
+
386
+ Import the client
387
+ import replicate
388
+
389
+ Copy
390
+ Run meta/musicgen using Replicate’s API. Check out the model's schema for an overview of inputs and outputs.
391
+
392
+ output = replicate.run(
393
+ "meta/musicgen:671ac645ce5e552cc63a54a2bbff63fcf798043055d2dac5fc9e36a837eedcfb",
394
+ input={
395
+ "top_k": 250,
396
+ "top_p": 0,
397
+ "prompt": "Edo25 major g melodies that sound triumphant and cinematic. Leading up to a crescendo that resolves in a 9th harmonic",
398
+ "duration": 8,
399
+ "temperature": 1,
400
+ "continuation": False,
401
+ "model_version": "stereo-large",
402
+ "output_format": "mp3",
403
+ "continuation_start": 0,
404
+ "multi_band_diffusion": False,
405
+ "normalization_strategy": "peak",
406
+ "classifier_free_guidance": 3
407
+ }
408
+ )
409
+ print(output)""", language="python")
410
+
411
+ with gr.Tab("Cloud Computing"):
412
+ gr.HTML("Storage, AI api access, VMs, ")
413
+
414
+
415
+ with gr.Tab("Using 3rd Party Interface - free/paid"):
416
+ gr.HTML("General - https://artificialanalysis.ai/models/llama-3-1-instruct-405b/providers")
417
+ gr.HTML("Image - https://playground.com/login | https://www.midjourney.com/showcase")
418
+ gr.HTML("Audio - https://www.udio.com/home https://www.udio.com/pricing | https://suno.com/ ")
419
+ gr.HTML("Video - https://lumalabs.ai/dream-machine https://lumalabs.ai/dream-machine/pricing (free 30 gens a month) | https://klingai.com/ - https://www.reddit.com/r/singularity/comments/1fk4tgp/kling_ai_showcasing_the_use_of_the_motion_brush/ | https://www.hedra.com/")
420
+ gr.HTML("3D - https://www.csm.ai/ | https://www.tripo3d.ai/ | https://zoo.dev/text-to-cad")
421
+ gr.HTML("Multiple - https://fal.ai/pricing | ")
422
+
423
+ with gr.Tab("Examples of Generated Media on Reddit"):
424
+ gr.HTML("https://www.reddit.com/r/singularity/comments/1fknejj/facecamai_lets_anyone_convert_a_single_image_into/ <br>https://www.reddit.com/r/singularity/comments/1fjylow/tripo_v20_is_out_now_you_can_create_stunning_3d/")
425
+
426
+ with gr.Tab("Licensing"):
427
+ gr.HTML("Need to find the press release to see license eg. https://blackforestlabs.ai/announcing-black-forest-labs/")
428
+
429
+ return filemanager