import os, json, tempfile, pathlib, zipfile, io, spaces, time spaces.GPU(lambda: None)() import gradio as gr from huggingface_hub import InferenceClient MODEL = os.environ.get("SKILLS_MODEL", "meta-llama/Llama-3.1-8B-Instruct") TOKEN = os.environ.get("OPENAI_API_KEY", "") SYS = ( "You are SkillBot, helping users create Codex skills. Follow this process:\n" "1. Understand: Ask what the skill does, get 2-3 concrete scenarios\n" "2. Name: Suggest a hyphen-case name and confirm\n" "3. Generate: When ready, output ONLY a JSON object on one line with these fields:\n" ' {"skill_name":"...","display_name":"...","description":"...","short_description":"...","default_prompt":"...","skill_body":"markdown body"}\n' "Rules: Ask 1-2 questions at a time. For skill_body write real markdown with Overview, Quick Start, Workflow. Speak Chinese if user speaks Chinese." ) def chat(message, history): msgs = [{"role": "system", "content": SYS}] for m in (history or []): if isinstance(m, dict): msgs.append(m) elif isinstance(m, (list, tuple)): msgs.append({"role": "user", "content": m[0]}) if m[1]: msgs.append({"role": "assistant", "content": m[1]}) msgs.append({"role": "user", "content": message}) client = InferenceClient(model=MODEL, token=TOKEN) resp = client.chat_completion(messages=msgs, max_tokens=2048, temperature=0.7) reply = resp.choices[0].message.content # Check if model output contains skill JSON skill_data = None import re for match in re.finditer(r"\{", reply): start = match.start() depth, end = 0, len(reply) for i in range(start, len(reply)): if reply[i] == "{": depth += 1 elif reply[i] == "}": depth -= 1 if depth == 0: end = i + 1; break candidate = reply[start:end] try: data = json.loads(candidate) if "skill_name" in data and "skill_body" in data: skill_data = data reply = reply[:start].strip() + "\n\nSkill generated! Click download below." break except: pass # Save skill if generated zip_path = None if skill_data: sd = skill_data # Build skill files in temp dir tmp = tempfile.mkdtemp() skill_dir = pathlib.Path(tmp) / sd["skill_name"] skill_dir.mkdir() agents = skill_dir / "agents"; agents.mkdir() md = f'---\nname: {sd["skill_name"]}\ndescription: "{sd.get("description","")}"\n---\n{sd["skill_body"]}' (skill_dir / "SKILL.md").write_text(md, encoding="utf-8") yaml = f'display_name: "{sd.get("display_name",sd["skill_name"])}"\nshort_description: "{sd.get("short_description","")}"\ndefault_prompt: "{sd.get("default_prompt","")}"' (agents / "openai.yaml").write_text(yaml, encoding="utf-8") # Create zip buf = io.BytesIO() with zipfile.ZipFile(buf, "w") as zf: zf.writestr(f'{sd["skill_name"]}/SKILL.md', md) zf.writestr(f'{sd["skill_name"]}/agents/openai.yaml', yaml) zip_path = f"/tmp/{sd['skill_name']}.zip" with open(zip_path, "wb") as f: f.write(buf.getvalue()) history.append({"role": "user", "content": message}) history.append({"role": "assistant", "content": reply}) if zip_path: return history, gr.File(value=zip_path, visible=True) return history, gr.File(visible=False) with gr.Blocks(title="SkillBot", theme=gr.themes.Soft()) as demo: gr.Markdown("# SkillBot - Create a Codex Skill by Chatting") chatbot = gr.Chatbot(label="Conversation", height=400) msg = gr.Textbox(placeholder="Describe what skill you want to create...", label="Message") with gr.Row(): send = gr.Button("Send", variant="primary") clear_btn = gr.Button("New Skill") file_out = gr.File(label="Download Skill", visible=False) send.click(chat, [msg, chatbot], [chatbot, file_out]).then(lambda: "", None, [msg]) msg.submit(chat, [msg, chatbot], [chatbot, file_out]).then(lambda: "", None, [msg]) clear_btn.click(lambda: ([], gr.File(visible=False)), None, [chatbot, file_out]) demo.launch(server_name="0.0.0.0", server_port=int(os.environ.get("PORT", 7860))) # v1785312598.4308667