j-js commited on
Commit
82d72b0
·
verified ·
1 Parent(s): 717ffb8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +17 -67
app.py CHANGED
@@ -16,15 +16,16 @@ from conversation_logic import ConversationEngine
16
  from generator_engine import GeneratorEngine
17
  from logging_store import LoggingStore
18
  from models import ChatRequest, EventLogRequest, SessionFinalizeRequest, SessionStartRequest
 
19
  from retrieval_engine import RetrievalEngine
20
  from ui_html import HOME_HTML
21
  from utils import clamp01, get_user_text
22
- from question_support_loader import question_support_bank
23
 
24
  retriever = RetrievalEngine()
25
  generator = GeneratorEngine()
26
  engine = ConversationEngine(retriever=retriever, generator=generator)
27
  store = LoggingStore()
 
28
 
29
  app = FastAPI(title="GameAI")
30
  app.add_middleware(
@@ -33,11 +34,9 @@ app.add_middleware(
33
  allow_credentials=True,
34
  allow_methods=["*"],
35
  allow_headers=["*"],
36
- question_support_bank.load()
37
  )
38
- print(question_support_bank.get("TEST_PERCENT_001"))
39
  # Lightweight in-memory chat session state cache.
40
- # This lets repeated /chat requests work as long as the caller reuses session_id.
41
  CHAT_SESSION_STATE: Dict[str, Dict[str, Any]] = {}
42
 
43
 
@@ -45,10 +44,6 @@ def _as_dict(value: Any) -> Dict[str, Any]:
45
  return value if isinstance(value, dict) else {}
46
 
47
 
48
- def _as_list(value: Any) -> List[Any]:
49
- return value if isinstance(value, list) else []
50
-
51
-
52
  def _extract_session_id(req_data: Dict[str, Any], req: ChatRequest) -> Optional[str]:
53
  candidates = [
54
  req_data.get("session_id"),
@@ -69,11 +64,9 @@ def _extract_chat_history(req_data: Dict[str, Any], req: ChatRequest) -> List[Di
69
  getattr(req, "chat_history", None),
70
  getattr(req, "history", None),
71
  ]
72
-
73
  for candidate in candidates:
74
  if isinstance(candidate, list):
75
  return [item for item in candidate if isinstance(item, dict)]
76
-
77
  return []
78
 
79
 
@@ -81,17 +74,14 @@ def _recover_session_state_from_history(chat_history: List[Dict[str, Any]]) -> D
81
  for item in reversed(chat_history):
82
  if not isinstance(item, dict):
83
  continue
84
-
85
  direct_state = item.get("session_state")
86
  if isinstance(direct_state, dict) and direct_state:
87
  return dict(direct_state)
88
-
89
  meta = item.get("meta")
90
  if isinstance(meta, dict):
91
  meta_state = meta.get("session_state")
92
  if isinstance(meta_state, dict) and meta_state:
93
  return dict(meta_state)
94
-
95
  return {}
96
 
97
 
@@ -109,9 +99,6 @@ def _merge_session_state(
109
  parsed_built_on_previous_turn: bool,
110
  ) -> Dict[str, Any]:
111
  state: Dict[str, Any] = {}
112
-
113
- # Start with cache, then history recovery, then explicit incoming state.
114
- # Explicit client-provided state wins.
115
  if cached_state:
116
  state.update(cached_state)
117
  if history_state:
@@ -119,31 +106,22 @@ def _merge_session_state(
119
  if incoming_state:
120
  state.update(incoming_state)
121
 
122
- # Apply parsed Unity hidden context only when present.
123
  if parsed_question_text:
124
  state["question_text"] = parsed_question_text
125
-
126
  if parsed_hint_stage:
127
  state["hint_stage"] = parsed_hint_stage
128
-
129
  if parsed_user_last_input_type:
130
  state["user_last_input_type"] = parsed_user_last_input_type
131
-
132
  if parsed_built_on_previous_turn:
133
  state["built_on_previous_turn"] = parsed_built_on_previous_turn
134
-
135
  if parsed_help_mode:
136
  state["help_mode"] = parsed_help_mode
137
-
138
  if parsed_intent:
139
  state["intent"] = parsed_intent
140
-
141
  if parsed_topic:
142
  state["topic"] = parsed_topic
143
-
144
  if parsed_category:
145
  state["category"] = parsed_category
146
-
147
  return state
148
 
149
 
@@ -153,6 +131,7 @@ def health() -> Dict[str, Any]:
153
  "ok": True,
154
  "app": "GameAI",
155
  "generator_available": generator.available(),
 
156
  }
157
 
158
 
@@ -164,9 +143,8 @@ def home() -> str:
164
  @app.post("/chat")
165
  async def chat(request: Request) -> JSONResponse:
166
  try:
167
- raw_body: Any = None
168
  try:
169
- raw_body = await request.json()
170
  except Exception:
171
  try:
172
  raw_body = (await request.body()).decode("utf-8", errors="ignore")
@@ -191,7 +169,6 @@ async def chat(request: Request) -> JSONResponse:
191
  parsed_built_on_previous_turn = bool(parsed.get("built_on_previous_turn", False))
192
 
193
  game_fields = extract_game_context_fields(hidden_context)
194
-
195
  chat_history = _extract_chat_history(req_data, req)
196
  incoming_session_state = _as_dict(req_data.get("session_state", getattr(req, "session_state", None)))
197
  history_session_state = _recover_session_state_from_history(chat_history)
@@ -216,11 +193,11 @@ async def chat(request: Request) -> JSONResponse:
216
  question_text = (
217
  (getattr(req, "question_text", None) or "").strip()
218
  or parsed_question_text
219
- or game_fields["question"]
220
  or str(session_state.get("question_text", "") or "").strip()
221
  )
222
-
223
- options_text = getattr(req, "options_text", None) or game_fields["options"]
224
 
225
  category = (
226
  req_data.get("category")
@@ -234,28 +211,12 @@ async def chat(request: Request) -> JSONResponse:
234
  verbosity = clamp01(req_data.get("verbosity", getattr(req, "verbosity", 0.5)), 0.5)
235
  transparency = clamp01(req_data.get("transparency", getattr(req, "transparency", 0.5)), 0.5)
236
 
237
- incoming_help_mode = (
238
- req_data.get("help_mode")
239
- or getattr(req, "help_mode", None)
240
- or parsed_help_mode
241
- or None
242
- )
243
-
244
- explicit_intent = (
245
- req_data.get("intent")
246
- or getattr(req, "intent", None)
247
- or parsed_intent
248
- or None
249
- )
250
-
251
- resolved_user_text = (
252
- req_data.get("raw_user_text")
253
- or actual_user_message
254
- or full_text
255
- or ""
256
- )
257
  resolved_user_text = str(resolved_user_text).strip()
258
-
259
  intent = explicit_intent or detect_intent(resolved_user_text, incoming_help_mode)
260
  help_mode = incoming_help_mode or intent_to_help_mode(intent)
261
 
@@ -269,6 +230,7 @@ async def chat(request: Request) -> JSONResponse:
269
  chat_history=chat_history,
270
  question_text=question_text,
271
  options_text=options_text,
 
272
  session_state=session_state,
273
  category=category,
274
  )
@@ -283,7 +245,6 @@ async def chat(request: Request) -> JSONResponse:
283
  "used_retrieval": result.used_retrieval,
284
  "used_generator": result.used_generator,
285
  }
286
-
287
  if isinstance(result.meta, dict):
288
  meta.update(result.meta)
289
 
@@ -291,20 +252,9 @@ async def chat(request: Request) -> JSONResponse:
291
  if session_id and returned_session_state:
292
  CHAT_SESSION_STATE[session_id] = dict(returned_session_state)
293
 
294
- return JSONResponse(
295
- {
296
- "reply": result.reply,
297
- "meta": meta,
298
- }
299
- )
300
  except Exception as e:
301
- return JSONResponse(
302
- {
303
- "error": type(e).__name__,
304
- "detail": str(e),
305
- },
306
- status_code=500,
307
- )
308
 
309
 
310
  @app.post("/log/session/start")
@@ -329,4 +279,4 @@ def research_sessions() -> Dict[str, Any]:
329
 
330
  @app.get("/research/session/{session_id}")
331
  def research_session(session_id: str) -> Dict[str, Any]:
332
- return store.get_session(session_id)
 
16
  from generator_engine import GeneratorEngine
17
  from logging_store import LoggingStore
18
  from models import ChatRequest, EventLogRequest, SessionFinalizeRequest, SessionStartRequest
19
+ from question_support_loader import question_support_bank
20
  from retrieval_engine import RetrievalEngine
21
  from ui_html import HOME_HTML
22
  from utils import clamp01, get_user_text
 
23
 
24
  retriever = RetrievalEngine()
25
  generator = GeneratorEngine()
26
  engine = ConversationEngine(retriever=retriever, generator=generator)
27
  store = LoggingStore()
28
+ question_support_bank.load()
29
 
30
  app = FastAPI(title="GameAI")
31
  app.add_middleware(
 
34
  allow_credentials=True,
35
  allow_methods=["*"],
36
  allow_headers=["*"],
 
37
  )
38
+
39
  # Lightweight in-memory chat session state cache.
 
40
  CHAT_SESSION_STATE: Dict[str, Dict[str, Any]] = {}
41
 
42
 
 
44
  return value if isinstance(value, dict) else {}
45
 
46
 
 
 
 
 
47
  def _extract_session_id(req_data: Dict[str, Any], req: ChatRequest) -> Optional[str]:
48
  candidates = [
49
  req_data.get("session_id"),
 
64
  getattr(req, "chat_history", None),
65
  getattr(req, "history", None),
66
  ]
 
67
  for candidate in candidates:
68
  if isinstance(candidate, list):
69
  return [item for item in candidate if isinstance(item, dict)]
 
70
  return []
71
 
72
 
 
74
  for item in reversed(chat_history):
75
  if not isinstance(item, dict):
76
  continue
 
77
  direct_state = item.get("session_state")
78
  if isinstance(direct_state, dict) and direct_state:
79
  return dict(direct_state)
 
80
  meta = item.get("meta")
81
  if isinstance(meta, dict):
82
  meta_state = meta.get("session_state")
83
  if isinstance(meta_state, dict) and meta_state:
84
  return dict(meta_state)
 
85
  return {}
86
 
87
 
 
99
  parsed_built_on_previous_turn: bool,
100
  ) -> Dict[str, Any]:
101
  state: Dict[str, Any] = {}
 
 
 
102
  if cached_state:
103
  state.update(cached_state)
104
  if history_state:
 
106
  if incoming_state:
107
  state.update(incoming_state)
108
 
 
109
  if parsed_question_text:
110
  state["question_text"] = parsed_question_text
 
111
  if parsed_hint_stage:
112
  state["hint_stage"] = parsed_hint_stage
 
113
  if parsed_user_last_input_type:
114
  state["user_last_input_type"] = parsed_user_last_input_type
 
115
  if parsed_built_on_previous_turn:
116
  state["built_on_previous_turn"] = parsed_built_on_previous_turn
 
117
  if parsed_help_mode:
118
  state["help_mode"] = parsed_help_mode
 
119
  if parsed_intent:
120
  state["intent"] = parsed_intent
 
121
  if parsed_topic:
122
  state["topic"] = parsed_topic
 
123
  if parsed_category:
124
  state["category"] = parsed_category
 
125
  return state
126
 
127
 
 
131
  "ok": True,
132
  "app": "GameAI",
133
  "generator_available": generator.available(),
134
+ "question_support_loaded": True,
135
  }
136
 
137
 
 
143
  @app.post("/chat")
144
  async def chat(request: Request) -> JSONResponse:
145
  try:
 
146
  try:
147
+ raw_body: Any = await request.json()
148
  except Exception:
149
  try:
150
  raw_body = (await request.body()).decode("utf-8", errors="ignore")
 
169
  parsed_built_on_previous_turn = bool(parsed.get("built_on_previous_turn", False))
170
 
171
  game_fields = extract_game_context_fields(hidden_context)
 
172
  chat_history = _extract_chat_history(req_data, req)
173
  incoming_session_state = _as_dict(req_data.get("session_state", getattr(req, "session_state", None)))
174
  history_session_state = _recover_session_state_from_history(chat_history)
 
193
  question_text = (
194
  (getattr(req, "question_text", None) or "").strip()
195
  or parsed_question_text
196
+ or game_fields.get("question", "")
197
  or str(session_state.get("question_text", "") or "").strip()
198
  )
199
+ options_text = getattr(req, "options_text", None) or game_fields.get("options", [])
200
+ question_id = req_data.get("question_id") or getattr(req, "question_id", None) or session_state.get("question_id")
201
 
202
  category = (
203
  req_data.get("category")
 
211
  verbosity = clamp01(req_data.get("verbosity", getattr(req, "verbosity", 0.5)), 0.5)
212
  transparency = clamp01(req_data.get("transparency", getattr(req, "transparency", 0.5)), 0.5)
213
 
214
+ incoming_help_mode = req_data.get("help_mode") or getattr(req, "help_mode", None) or parsed_help_mode or None
215
+ explicit_intent = req_data.get("intent") or getattr(req, "intent", None) or parsed_intent or None
216
+
217
+ resolved_user_text = req_data.get("raw_user_text") or actual_user_message or full_text or ""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
218
  resolved_user_text = str(resolved_user_text).strip()
219
+
220
  intent = explicit_intent or detect_intent(resolved_user_text, incoming_help_mode)
221
  help_mode = incoming_help_mode or intent_to_help_mode(intent)
222
 
 
230
  chat_history=chat_history,
231
  question_text=question_text,
232
  options_text=options_text,
233
+ question_id=question_id,
234
  session_state=session_state,
235
  category=category,
236
  )
 
245
  "used_retrieval": result.used_retrieval,
246
  "used_generator": result.used_generator,
247
  }
 
248
  if isinstance(result.meta, dict):
249
  meta.update(result.meta)
250
 
 
252
  if session_id and returned_session_state:
253
  CHAT_SESSION_STATE[session_id] = dict(returned_session_state)
254
 
255
+ return JSONResponse({"reply": result.reply, "meta": meta})
 
 
 
 
 
256
  except Exception as e:
257
+ return JSONResponse({"error": type(e).__name__, "detail": str(e)}, status_code=500)
 
 
 
 
 
 
258
 
259
 
260
  @app.post("/log/session/start")
 
279
 
280
  @app.get("/research/session/{session_id}")
281
  def research_session(session_id: str) -> Dict[str, Any]:
282
+ return store.get_session(session_id)