Spaces:
Sleeping
Sleeping
| import requests | |
| import json | |
| from config import Config | |
| def create_plan(goal: str): | |
| """ | |
| Robust AI planner: | |
| - safe LLM call | |
| - strict JSON parsing | |
| - fallback protection | |
| """ | |
| prompt = f""" | |
| You are a planning agent. | |
| Break the goal into executable steps. | |
| GOAL: | |
| {goal} | |
| RULES: | |
| - Output ONLY valid JSON | |
| - NO explanation | |
| - NO markdown | |
| - NO extra text | |
| - steps must be simple actionable instructions | |
| FORMAT: | |
| {{ | |
| "steps": [ | |
| "step 1", | |
| "step 2", | |
| "step 3" | |
| ] | |
| }} | |
| """ | |
| try: | |
| # ========================= | |
| # CALL LLM | |
| # ========================= | |
| res = requests.post( | |
| Config.LLM_API_URL, | |
| headers={ | |
| "Authorization": f"Bearer {Config.LLM_API_KEY}", | |
| "Content-Type": "application/json" | |
| }, | |
| json={ | |
| "model": Config.MODEL, | |
| "messages": [ | |
| {"role": "user", "content": prompt} | |
| ], | |
| "temperature": 0.2 | |
| }, | |
| timeout=30 | |
| ) | |
| # ========================= | |
| # HTTP CHECK | |
| # ========================= | |
| if res.status_code != 200: | |
| return {"steps": [goal]} | |
| # ========================= | |
| # JSON PARSE SAFE | |
| # ========================= | |
| try: | |
| data = res.json() | |
| except Exception: | |
| return {"steps": [goal]} | |
| if not isinstance(data, dict): | |
| return {"steps": [goal]} | |
| # ========================= | |
| # EXTRACT CONTENT | |
| # ========================= | |
| choices = data.get("choices") | |
| if not choices or not isinstance(choices, list): | |
| return {"steps": [goal]} | |
| message = choices[0].get("message", {}) | |
| content = message.get("content", "") | |
| if not content: | |
| return {"steps": [goal]} | |
| # ========================= | |
| # PARSE PLAN JSON | |
| # ========================= | |
| try: | |
| parsed = json.loads(content) | |
| if ( | |
| isinstance(parsed, dict) | |
| and "steps" in parsed | |
| and isinstance(parsed["steps"], list) | |
| and len(parsed["steps"]) > 0 | |
| ): | |
| return parsed | |
| except Exception: | |
| pass | |
| # ========================= | |
| # FALLBACK (SAFE) | |
| # ========================= | |
| return {"steps": [goal]} | |
| except Exception: | |
| # HARD FAIL SAFE | |
| return {"steps": [goal]} |