Akoda35 commited on
Commit
b5d7148
·
verified ·
1 Parent(s): 18f90f1

Update theme/app.py

Browse files
Files changed (1) hide show
  1. theme/app.py +76 -50
theme/app.py CHANGED
@@ -8,12 +8,11 @@ from fastapi.templating import Jinja2Templates
8
  # APP INIT
9
  # =========================
10
 
11
- app = FastAPI(title="PyRunner Agent OS", version="3.0")
12
 
13
  BASE_DIR = os.path.dirname(os.path.abspath(__file__))
14
  templates = Jinja2Templates(directory=os.path.join(BASE_DIR, "templates"))
15
 
16
-
17
  # =========================
18
  # ENV
19
  # =========================
@@ -27,12 +26,14 @@ MODELS = {
27
  "fallback": os.getenv("OLLAMA_BACKUP_MODEL", "llama3.2:1b")
28
  }
29
 
 
 
30
 
31
  # =========================
32
- # OLLAMA CORE CALL
33
  # =========================
34
 
35
- def call_ollama(prompt, model):
36
  try:
37
  r = requests.post(
38
  f"{OLLAMA_URL}/api/generate",
@@ -41,71 +42,91 @@ def call_ollama(prompt, model):
41
  "prompt": prompt,
42
  "stream": False
43
  },
44
- timeout=60
45
  )
46
- return r.json()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  except Exception as e:
48
  return {"error": str(e)}
49
 
50
 
51
  # =========================
52
- # AGENT DEFINITIONS
53
  # =========================
54
 
55
- def orchestrator_agent(user_input: str):
56
- """
57
- Classifies task type
58
- """
59
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
  prompt = f"""
61
- You are an orchestrator AI.
62
 
63
- Classify this request into one category ONLY:
64
 
65
- - code
66
- - vision
67
- - fashion
68
- - hairstyle
69
- - general
70
 
71
- User request:
72
  {user_input}
73
-
74
- Return ONLY the category name.
75
  """
76
 
77
  res = call_ollama(prompt, MODELS["orchestrator"])
78
 
79
  if "response" in res:
80
- return res["response"].strip().lower()
81
 
82
  return "general"
83
 
84
 
 
 
 
 
85
  def coder_agent(prompt):
86
  return call_ollama(prompt, MODELS["coder"])
87
 
88
 
89
  def fashion_agent(prompt):
90
- system_prompt = f"""
91
- You are a fashion expert AI.
92
- Analyze outfit, styling, colors, trends.
93
-
94
- User:
95
- {prompt}
96
- """
97
- return call_ollama(system_prompt, MODELS["fast"])
98
 
99
 
100
  def hairstyle_agent(prompt):
101
- system_prompt = f"""
102
- You are a barber & hairstyle expert.
103
- Describe hairstyle changes, fades, textures, transformations.
104
-
105
- User:
106
- {prompt}
107
- """
108
- return call_ollama(system_prompt, MODELS["fast"])
109
 
110
 
111
  def fallback_agent(prompt):
@@ -136,7 +157,10 @@ def route_agent(category: str, prompt: str):
136
 
137
  @app.get("/", response_class=HTMLResponse)
138
  async def home(request: Request):
139
- return templates.TemplateResponse("index.html", {"request": request})
 
 
 
140
 
141
 
142
  # =========================
@@ -147,7 +171,7 @@ async def home(request: Request):
147
  def health():
148
  return {
149
  "status": "ok",
150
- "agents": list(MODELS.keys())
151
  }
152
 
153
 
@@ -161,32 +185,34 @@ async def agent(request: Request):
161
  body = await request.json()
162
  user_input = body.get("prompt", "")
163
 
164
- # 1. Decide agent
 
 
 
 
 
165
  category = orchestrator_agent(user_input)
166
 
167
- # 2. Route to agent
168
  result = route_agent(category, user_input)
169
 
170
- # 3. Fallback safety
171
- if "error" in result:
172
  result = fallback_agent(user_input)
173
 
174
  return JSONResponse({
175
  "category": category,
176
- "result": result
177
  })
178
 
179
 
180
  # =========================
181
- # IMAGE PIPELINE HOOK (future)
182
  # =========================
183
 
184
  @app.post("/api/image")
185
  async def image_pipeline(request: Request):
186
- body = await request.json()
187
-
188
  return {
189
  "status": "queued",
190
- "pipeline": "vision_stub",
191
- "note": "Attach diffusion model later"
192
  }
 
8
  # APP INIT
9
  # =========================
10
 
11
+ app = FastAPI(title="PyRunner Agent OS", version="3.1")
12
 
13
  BASE_DIR = os.path.dirname(os.path.abspath(__file__))
14
  templates = Jinja2Templates(directory=os.path.join(BASE_DIR, "templates"))
15
 
 
16
  # =========================
17
  # ENV
18
  # =========================
 
26
  "fallback": os.getenv("OLLAMA_BACKUP_MODEL", "llama3.2:1b")
27
  }
28
 
29
+ TIMEOUT = (5, 120) # connect, read
30
+
31
 
32
  # =========================
33
+ # SAFE OLLAMA CALL
34
  # =========================
35
 
36
+ def call_ollama(prompt: str, model: str):
37
  try:
38
  r = requests.post(
39
  f"{OLLAMA_URL}/api/generate",
 
42
  "prompt": prompt,
43
  "stream": False
44
  },
45
+ timeout=TIMEOUT
46
  )
47
+
48
+ if r.status_code != 200:
49
+ return {
50
+ "error": f"Ollama error {r.status_code}",
51
+ "raw": r.text
52
+ }
53
+
54
+ data = r.json()
55
+
56
+ # normalize output
57
+ return {
58
+ "response": data.get("response", "").strip(),
59
+ "raw": data
60
+ }
61
+
62
  except Exception as e:
63
  return {"error": str(e)}
64
 
65
 
66
  # =========================
67
+ # CLEAN OUTPUT PARSER
68
  # =========================
69
 
70
+ def clean_text(text: str) -> str:
71
+ if not text:
72
+ return "general"
 
73
 
74
+ return (
75
+ text.lower()
76
+ .replace("\n", "")
77
+ .replace(".", "")
78
+ .strip()
79
+ )
80
+
81
+
82
+ # =========================
83
+ # ORCHESTRATOR
84
+ # =========================
85
+
86
+ def orchestrator_agent(user_input: str):
87
  prompt = f"""
88
+ You are an AI classifier.
89
 
90
+ Return ONLY ONE word:
91
 
92
+ code
93
+ vision
94
+ fashion
95
+ hairstyle
96
+ general
97
 
98
+ User:
99
  {user_input}
 
 
100
  """
101
 
102
  res = call_ollama(prompt, MODELS["orchestrator"])
103
 
104
  if "response" in res:
105
+ return clean_text(res["response"])
106
 
107
  return "general"
108
 
109
 
110
+ # =========================
111
+ # AGENTS
112
+ # =========================
113
+
114
  def coder_agent(prompt):
115
  return call_ollama(prompt, MODELS["coder"])
116
 
117
 
118
  def fashion_agent(prompt):
119
+ return call_ollama(
120
+ f"Fashion analysis:\n{prompt}",
121
+ MODELS["fast"]
122
+ )
 
 
 
 
123
 
124
 
125
  def hairstyle_agent(prompt):
126
+ return call_ollama(
127
+ f"Hairstyle analysis:\n{prompt}",
128
+ MODELS["fast"]
129
+ )
 
 
 
 
130
 
131
 
132
  def fallback_agent(prompt):
 
157
 
158
  @app.get("/", response_class=HTMLResponse)
159
  async def home(request: Request):
160
+ return templates.TemplateResponse(
161
+ "index.html",
162
+ {"request": request}
163
+ )
164
 
165
 
166
  # =========================
 
171
  def health():
172
  return {
173
  "status": "ok",
174
+ "models": MODELS
175
  }
176
 
177
 
 
185
  body = await request.json()
186
  user_input = body.get("prompt", "")
187
 
188
+ if not user_input:
189
+ return JSONResponse({
190
+ "error": "No prompt provided"
191
+ }, status_code=400)
192
+
193
+ # 1. classify
194
  category = orchestrator_agent(user_input)
195
 
196
+ # 2. route
197
  result = route_agent(category, user_input)
198
 
199
+ # 3. fallback safety
200
+ if isinstance(result, dict) and "error" in result:
201
  result = fallback_agent(user_input)
202
 
203
  return JSONResponse({
204
  "category": category,
205
+ "result": result.get("response", result)
206
  })
207
 
208
 
209
  # =========================
210
+ # IMAGE PIPELINE HOOK
211
  # =========================
212
 
213
  @app.post("/api/image")
214
  async def image_pipeline(request: Request):
 
 
215
  return {
216
  "status": "queued",
217
+ "pipeline": "vision_stub"
 
218
  }