Akoda35 commited on
Commit
707e062
·
verified ·
1 Parent(s): ff5b659

Update theme/app.py

Browse files
Files changed (1) hide show
  1. theme/app.py +65 -64
theme/app.py CHANGED
@@ -1,5 +1,6 @@
1
  import os
2
  import requests
 
3
  from fastapi import FastAPI, Request
4
  from fastapi.responses import JSONResponse, HTMLResponse
5
  from fastapi.templating import Jinja2Templates
@@ -8,13 +9,13 @@ from fastapi.templating import Jinja2Templates
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
  # =========================
19
 
20
  OLLAMA_URL = os.getenv("OLLAMA_URL", "http://localhost:11434")
@@ -26,11 +27,11 @@ MODELS = {
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):
@@ -46,14 +47,10 @@ def call_ollama(prompt: str, model: str):
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
@@ -67,27 +64,30 @@ def call_ollama(prompt: str, model: str):
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
@@ -95,14 +95,14 @@ 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
 
@@ -111,25 +111,19 @@ User:
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):
133
  return call_ollama(prompt, MODELS["fallback"])
134
 
135
 
@@ -137,18 +131,18 @@ def fallback_agent(prompt):
137
  # ROUTER
138
  # =========================
139
 
140
- def route_agent(category: str, prompt: str):
141
 
142
  if category == "code":
143
- return coder_agent(prompt)
144
 
145
  if category == "fashion":
146
- return fashion_agent(prompt)
147
 
148
  if category == "hairstyle":
149
- return hairstyle_agent(prompt)
150
 
151
- return fallback_agent(prompt)
152
 
153
 
154
  # =========================
@@ -157,10 +151,13 @@ def route_agent(category: str, prompt: str):
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
  # =========================
@@ -182,36 +179,40 @@ def health():
182
  @app.post("/api/agent")
183
  async def agent(request: Request):
184
 
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"
 
1
  import os
2
  import requests
3
+ from pathlib import Path
4
  from fastapi import FastAPI, Request
5
  from fastapi.responses import JSONResponse, HTMLResponse
6
  from fastapi.templating import Jinja2Templates
 
9
  # APP INIT
10
  # =========================
11
 
12
+ app = FastAPI(title="PyRunner Agent OS", version="3.2")
13
 
14
+ BASE_DIR = Path(__file__).resolve().parent
15
+ templates = Jinja2Templates(directory=str(BASE_DIR / "templates"))
16
 
17
  # =========================
18
+ # CONFIG
19
  # =========================
20
 
21
  OLLAMA_URL = os.getenv("OLLAMA_URL", "http://localhost:11434")
 
27
  "fallback": os.getenv("OLLAMA_BACKUP_MODEL", "llama3.2:1b")
28
  }
29
 
30
+ TIMEOUT = 90
31
 
32
 
33
  # =========================
34
+ # OLLAMA CORE CALL (SAFE)
35
  # =========================
36
 
37
  def call_ollama(prompt: str, model: str):
 
47
  )
48
 
49
  if r.status_code != 200:
50
+ return {"error": f"Ollama HTTP {r.status_code}", "raw": r.text}
 
 
 
51
 
52
  data = r.json()
53
 
 
54
  return {
55
  "response": data.get("response", "").strip(),
56
  "raw": data
 
64
  # CLEAN OUTPUT PARSER
65
  # =========================
66
 
67
+ def clean_category(text: str) -> str:
68
  if not text:
69
  return "general"
70
 
71
+ text = text.lower().strip()
72
+
73
+ # force valid categories only
74
+ valid = ["code", "vision", "fashion", "hairstyle", "general"]
75
+
76
+ for v in valid:
77
+ if v in text:
78
+ return v
79
+
80
+ return "general"
81
 
82
 
83
  # =========================
84
  # ORCHESTRATOR
85
  # =========================
86
 
87
+ def orchestrator(user_input: str):
 
 
88
 
89
+ prompt = f"""
90
+ Classify into ONE word only:
91
 
92
  code
93
  vision
 
95
  hairstyle
96
  general
97
 
98
+ Input:
99
  {user_input}
100
  """
101
 
102
  res = call_ollama(prompt, MODELS["orchestrator"])
103
 
104
  if "response" in res:
105
+ return clean_category(res["response"])
106
 
107
  return "general"
108
 
 
111
  # AGENTS
112
  # =========================
113
 
114
+ def coder(prompt):
115
  return call_ollama(prompt, MODELS["coder"])
116
 
117
 
118
+ def fashion(prompt):
119
+ return call_ollama(f"Fashion analysis:\n{prompt}", MODELS["fast"])
 
 
 
120
 
121
 
122
+ def hairstyle(prompt):
123
+ return call_ollama(f"Hairstyle analysis:\n{prompt}", MODELS["fast"])
 
 
 
124
 
125
 
126
+ def fallback(prompt):
127
  return call_ollama(prompt, MODELS["fallback"])
128
 
129
 
 
131
  # ROUTER
132
  # =========================
133
 
134
+ def route(category: str, prompt: str):
135
 
136
  if category == "code":
137
+ return coder(prompt)
138
 
139
  if category == "fashion":
140
+ return fashion(prompt)
141
 
142
  if category == "hairstyle":
143
+ return hairstyle(prompt)
144
 
145
+ return fallback(prompt)
146
 
147
 
148
  # =========================
 
151
 
152
  @app.get("/", response_class=HTMLResponse)
153
  async def home(request: Request):
154
+ try:
155
+ return templates.TemplateResponse(
156
+ "index.html",
157
+ {"request": request}
158
+ )
159
+ except Exception as e:
160
+ return HTMLResponse(f"<h1>Template Error</h1><pre>{e}</pre>")
161
 
162
 
163
  # =========================
 
179
  @app.post("/api/agent")
180
  async def agent(request: Request):
181
 
182
+ try:
183
+ body = await request.json()
184
+ prompt = body.get("prompt", "")
185
 
186
+ if not prompt:
187
+ return JSONResponse(
188
+ {"error": "missing prompt"},
189
+ status_code=400
190
+ )
191
 
192
+ category = orchestrator(prompt)
193
+ result = route(category, prompt)
194
 
195
+ if isinstance(result, dict) and "error" in result:
196
+ result = fallback(prompt)
197
 
198
+ return {
199
+ "category": category,
200
+ "result": result.get("response", result)
201
+ }
202
 
203
+ except Exception as e:
204
+ return JSONResponse(
205
+ {"error": str(e)},
206
+ status_code=500
207
+ )
208
 
209
 
210
  # =========================
211
+ # IMAGE PIPELINE (STABLE STUB)
212
  # =========================
213
 
214
  @app.post("/api/image")
215
+ async def image(request: Request):
216
  return {
217
  "status": "queued",
218
  "pipeline": "vision_stub"