Spaces:
Running
on
Zero
Running
on
Zero
kwabs22
commited on
Commit
•
a69d738
1
Parent(s):
ae6b3e0
Some changes and flie splitting
Browse files- app.py +0 -0
- file_explorer_and_upload.py +115 -0
- jsconfig_idea_support.py +22 -0
- leveraging_machine_learning.py +338 -0
- my_text_game_engine_attempt.py +285 -0
- relatively_constant_variables.py +355 -2
- state_prompt_fileman_UI_functions.py +324 -0
- timeline_and_UI_generation_functions.py +370 -0
- ui_gr_media_management.py +429 -0
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": "
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
|
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
|