Martico2432's picture
Create app.py
e25dead verified
Raw
History Blame Contribute Delete
9.02 kB
import os
import gradio as gr
from game_config import CLOUD_TICK_SECONDS, HF_MAX_NEW_TOKENS, HF_MODEL_ID
from huggingface_hub import InferenceClient
from state import (
buy_upgrade,
chat_temperature,
cloud_tick,
new_game,
status_lines,
toggle_cloud,
train_model,
unlock_cloud,
upgrade_status,
)
CSS = """
<style>
@import url('https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;700&display=swap');
body, .gradio-container {
background-color: #0a0f0d !important;
font-family: 'Fira Code', monospace !important;
color: #33ff33 !important;
}
#terminal-card {
background-color: #0d1410 !important;
border: 2px solid #22aa22 !important;
box-shadow: 0 0 20px rgba(51, 255, 51, 0.15);
border-radius: 4px;
padding: 15px;
}
.gr-button, button {
background: #142218 !important;
color: #33ff33 !important;
border: 1px solid #33ff33 !important;
font-family: 'Fira Code', monospace !important;
border-radius: 2px !important;
cursor: pointer;
transition: all 0.2s ease;
}
.gr-button:hover, button:hover {
background: #33ff33 !important;
color: #0a0f0d !important;
box-shadow: 0 0 10px #33ff33;
}
.gr-text-input, textarea, input[type="text"] {
background-color: #050806 !important;
border: 1px solid #22aa22 !important;
color: #33ff33 !important;
font-family: 'Fira Code', monospace !important;
border-radius: 2px !important;
}
.gr-text-input:focus, textarea:focus, input[type="text"]:focus {
border-color: #33ff33 !important;
outline: none !important;
}
#console-log-area {
max-height: 350px;
overflow-y: auto;
}
footer { display: none !important; }
</style>
"""
def get_huggingface_response(prompt: str, temperature: float, token: str) -> str:
"""
Queries Hugging Face using the player's active OAuth token.
Uses chat_completion to satisfy the conversational task requirement.
"""
try:
# Securely explicitly initializes InferenceClient with the player's token
client = InferenceClient(model=HF_MODEL_ID, token=token)
messages = [{"role": "user", "content": prompt}]
response = client.chat_completion(
messages=messages,
max_tokens=HF_MAX_NEW_TOKENS,
temperature=max(0.01, temperature),
)
return response.choices[0].message.content
except Exception as e:
return f"[FATAL_ERR] Model Inference Failed: {str(e)}"
def render_ui_panes(state: dict) -> tuple[str, str, str]:
stats = f"=== SYSTEM STATUS ===\n{status_lines(state)}\n====================="
upg_info = upgrade_status(state)
upg_lines = ["=== HARDWARE & ARCHITECTURE MARKETPLACE ==="]
for key, info in upg_info.items():
cost_str = f"${info['next_cost']:.0f}" if not info["maxed"] else "MAXED"
upg_lines.append(
f"{info['icon']} {info['label']} [{info['current_name']}]\n"
f" Tier: {info['current_tier']}/{info['max_tier']} | Cost: {cost_str}\n"
f" Desc: {info['description']}"
)
upg_lines.append("==========================================")
log_text = "\n".join(state.get("log", ["[SYS] Cluster Initialized."]))
return stats, "\n\n".join(upg_lines), log_text
# --- Interface Core Action Mappers ---
def handle_init():
state = new_game()
stats, upgs, logs = render_ui_panes(state)
return state, stats, upgs, logs, gr.update(choices=list(state["upgrades"].keys()))
def handle_train(state: dict):
new_state, _ = train_model(state)
stats, upgs, logs = render_ui_panes(new_state)
return new_state, stats, upgs, logs
def handle_upgrade(state: dict, upgrade_key: str):
if not upgrade_key:
return state, gr.update(), gr.update(), gr.update()
new_state, _ = buy_upgrade(state, upgrade_key)
stats, upgs, logs = render_ui_panes(new_state)
return new_state, stats, upgs, logs
def handle_cloud_unlock(state: dict):
new_state, _ = unlock_cloud(state)
stats, upgs, logs = render_ui_panes(new_state)
return new_state, stats, upgs, logs
def handle_cloud_toggle(state: dict):
new_state, _ = toggle_cloud(state)
stats, upgs, logs = render_ui_panes(new_state)
return new_state, stats, upgs, logs
def handle_tick(state: dict):
if not state.get("cloud_active", False):
return state, gr.update(), gr.update(), gr.update()
new_state, revenue = cloud_tick(state)
stats, upgs, logs = render_ui_panes(new_state)
return new_state, stats, upgs, logs
def handle_chat(
state: dict,
history: list,
message: str,
profile: gr.OAuthProfile | None,
oauth_token: gr.OAuthToken | None,
):
if not message.strip():
return history, ""
if history is None:
history = []
# Block inference if the user isn't authenticated through the UI
if oauth_token is None:
history.append(
[
message,
"[SYS_ERR] Access Denied. Please authorize using the 'Sign in with Hugging Face' button.",
]
)
return history, ""
temp = chat_temperature(state)
if temp > 1.4:
prompt = f"Produce dynamic fragmented word-salad, glitch texts, and chaotic tokens based loosely on: {message}"
else:
prompt = message
# Execute request using their injected token
response = get_huggingface_response(prompt, temp, oauth_token.token)
# Reverted to standard tuple arrays to fix TypeError in Chatbot init
history.append([message, response])
return history, ""
# --- Layout Assembly ---
with gr.Blocks(title="AI Training Simulator v2.026") as demo:
gr.HTML(CSS)
game_state = gr.State()
tick_trigger = gr.Button("tick_trigger", visible=False, elem_id="tick_trigger")
gr.Markdown("# 📟 THOUSAND TOKEN WOOD // STARTUP TERMINAL")
with gr.Column(elem_id="terminal-card"):
with gr.Row():
with gr.Column(scale=1):
status_pane = gr.Code(
label="System Mon", language="markdown", interactive=False
)
train_btn = gr.Button("⚡ RUN TRAINING PASS", variant="primary")
with gr.Row():
unlock_cloud_btn = gr.Button("🔓 UNLOCK CLOUD")
toggle_cloud_btn = gr.Button("⏯️ TOGGLE CLOUD")
with gr.Column(scale=1):
market_pane = gr.Code(
label="Stack Upgrade Hub", language="markdown", interactive=False
)
upgrade_dropdown = gr.Dropdown(
label="Select Component to Upgrade", choices=[]
)
buy_btn = gr.Button("💳 PURCHASE UPGRADE")
gr.Markdown("### 📜 Console System Output Logs")
log_pane = gr.Textbox(
label="", interactive=False, lines=8, elem_id="console-log-area"
)
gr.Markdown("### 💬 Live Model Inference Playground")
# Injected Native Hugging Face Auth Components
with gr.Row():
gr.LoginButton()
chatbot = gr.Chatbot(label="Model Output Channel")
with gr.Row():
chat_input = gr.Textbox(
placeholder="Query model parameter space...", scale=4, show_label=False
)
send_btn = gr.Button("📡 INFERENCE", scale=1)
# --- Wire UI action flows ---
demo.load(
handle_init,
outputs=[game_state, status_pane, market_pane, log_pane, upgrade_dropdown],
)
demo.load(
None,
js=f"""
function() {{
setInterval(() => {{
let btn = document.querySelector('#tick_trigger');
if (btn) btn.click();
}}, {CLOUD_TICK_SECONDS * 1000});
}}
""",
)
train_btn.click(
handle_train,
inputs=[game_state],
outputs=[game_state, status_pane, market_pane, log_pane],
)
buy_btn.click(
handle_upgrade,
inputs=[game_state, upgrade_dropdown],
outputs=[game_state, status_pane, market_pane, log_pane],
)
unlock_cloud_btn.click(
handle_cloud_unlock,
inputs=[game_state],
outputs=[game_state, status_pane, market_pane, log_pane],
)
toggle_cloud_btn.click(
handle_cloud_toggle,
inputs=[game_state],
outputs=[game_state, status_pane, market_pane, log_pane],
)
tick_trigger.click(
handle_tick,
inputs=[game_state],
outputs=[game_state, status_pane, market_pane, log_pane],
)
# Gradio handles mapping profile/oauth_token automatically, so we don't put them in the inputs array
send_btn.click(
handle_chat,
inputs=[game_state, chatbot, chat_input],
outputs=[chatbot, chat_input],
)
chat_input.submit(
handle_chat,
inputs=[game_state, chatbot, chat_input],
outputs=[chatbot, chat_input],
)
if __name__ == "__main__":
demo.launch()