j-js commited on
Commit
05b53ba
·
verified ·
1 Parent(s): 4cfa74b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +142 -74
app.py CHANGED
@@ -1,76 +1,144 @@
1
  from __future__ import annotations
2
 
3
- from dataclasses import dataclass, field
4
- from typing import Any, Dict, List, Optional
5
-
6
- from pydantic import BaseModel
7
-
8
-
9
- class ChatRequest(BaseModel):
10
- message: Optional[str] = None
11
- prompt: Optional[str] = None
12
- query: Optional[str] = None
13
- text: Optional[str] = None
14
- user_message: Optional[str] = None
15
- input: Optional[str] = None
16
- content: Optional[str] = None
17
-
18
- tone: Optional[float] = 0.5
19
- verbosity: Optional[float] = 0.5
20
- transparency: Optional[float] = 0.5
21
-
22
- help_mode: Optional[str] = None
23
- intent: Optional[str] = None
24
- category: Optional[str] = None
25
- chat_history: Optional[List[Dict[str, Any]]] = None
26
- history: Optional[List[Dict[str, Any]]] = None
27
-
28
- question_text: Optional[str] = None
29
- options_text: Optional[List[str]] = None
30
- question_id: Optional[str] = None
31
- session_id: Optional[str] = None
32
- user_id: Optional[str] = None
33
-
34
-
35
- class SessionStartRequest(BaseModel):
36
- session_id: str
37
- user_id: Optional[str] = None
38
- condition: Optional[str] = None
39
- metadata: Optional[Dict[str, Any]] = None
40
-
41
-
42
- class EventLogRequest(BaseModel):
43
- session_id: str
44
- event_type: str
45
- timestamp: Optional[str] = None
46
- payload: Optional[Dict[str, Any]] = None
47
-
48
-
49
- class SessionFinalizeRequest(BaseModel):
50
- session_id: str
51
- summary: Optional[Dict[str, Any]] = None
52
-
53
-
54
- @dataclass
55
- class RetrievedChunk:
56
- text: str
57
- topic: str = "general"
58
- source: str = "local"
59
- score: float = 0.0
60
-
61
-
62
- @dataclass
63
- class SolverResult:
64
- reply: str = ""
65
- domain: str = "fallback"
66
- solved: bool = False
67
- help_mode: str = "answer"
68
- answer_letter: Optional[str] = None
69
- answer_value: Optional[str] = None
70
- topic: Optional[str] = None
71
- used_retrieval: bool = False
72
- used_generator: bool = False
73
- internal_answer: Optional[str] = None
74
- steps: List[str] = field(default_factory=list)
75
- teaching_chunks: List[RetrievedChunk] = field(default_factory=list)
76
- meta: Dict[str, Any] = field(default_factory=dict)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  from __future__ import annotations
2
 
3
+ import os
4
+ from typing import Any, Dict
5
+
6
+ from fastapi import FastAPI, Request
7
+ from fastapi.middleware.cors import CORSMiddleware
8
+ from fastapi.responses import HTMLResponse, JSONResponse
9
+
10
+ from context_parser import detect_intent, extract_game_context_fields, intent_to_help_mode, split_unity_message
11
+ from conversation_logic import ConversationEngine
12
+ from generator_engine import GeneratorEngine
13
+ from logging_store import LoggingStore
14
+ from models import ChatRequest, EventLogRequest, SessionFinalizeRequest, SessionStartRequest
15
+ from retrieval_engine import RetrievalEngine
16
+ from ui_html import HOME_HTML
17
+ from utils import clamp01, get_user_text
18
+
19
+ retriever = RetrievalEngine()
20
+ generator = GeneratorEngine()
21
+ engine = ConversationEngine(retriever=retriever, generator=generator)
22
+ store = LoggingStore()
23
+
24
+ app = FastAPI(title="Trading Game AI V2", version="2.3.0")
25
+ app.add_middleware(
26
+ CORSMiddleware,
27
+ allow_origins=["*"],
28
+ allow_credentials=True,
29
+ allow_methods=["*"],
30
+ allow_headers=["*"],
31
+ )
32
+
33
+
34
+ @app.get("/health")
35
+ def health() -> Dict[str, Any]:
36
+ return {
37
+ "ok": True,
38
+ "app": "Trading Game AI V2",
39
+ "generator_available": generator.available(),
40
+ }
41
+
42
+
43
+ @app.get("/", response_class=HTMLResponse)
44
+ def home() -> str:
45
+ return HOME_HTML
46
+
47
+
48
+ @app.post("/chat")
49
+ async def chat(request: Request) -> JSONResponse:
50
+ try:
51
+ raw_body: Any = None
52
+ try:
53
+ raw_body = await request.json()
54
+ except Exception:
55
+ try:
56
+ raw_body = (await request.body()).decode("utf-8", errors="ignore")
57
+ except Exception:
58
+ raw_body = None
59
+
60
+ req_data: Dict[str, Any] = raw_body if isinstance(raw_body, dict) else {}
61
+ req = ChatRequest(**req_data) if isinstance(req_data, dict) else ChatRequest()
62
+
63
+ full_text = get_user_text(req, raw_body)
64
+ hidden_context, actual_user_message = split_unity_message(full_text)
65
+ game_fields = extract_game_context_fields(hidden_context)
66
+
67
+ question_text = (getattr(req, "question_text", None) or "").strip() or game_fields["question"]
68
+ options_text = getattr(req, "options_text", None) or game_fields["options"]
69
+ category = (
70
+ req_data.get("category")
71
+ or getattr(req, "category", None)
72
+ or game_fields.get("category")
73
+ )
74
+
75
+ tone = clamp01(req_data.get("tone", getattr(req, "tone", 0.5)), 0.5)
76
+ verbosity = clamp01(req_data.get("verbosity", getattr(req, "verbosity", 0.5)), 0.5)
77
+ transparency = clamp01(req_data.get("transparency", getattr(req, "transparency", 0.5)), 0.5)
78
+
79
+ incoming_help_mode = req_data.get("help_mode", getattr(req, "help_mode", None))
80
+ explicit_intent = req_data.get("intent", getattr(req, "intent", None))
81
+ intent = explicit_intent or detect_intent(actual_user_message or full_text, incoming_help_mode)
82
+ help_mode = intent_to_help_mode(intent)
83
+
84
+ result = engine.generate_response(
85
+ raw_user_text=actual_user_message or full_text,
86
+ tone=tone,
87
+ verbosity=verbosity,
88
+ transparency=transparency,
89
+ intent=intent,
90
+ help_mode=help_mode,
91
+ chat_history=getattr(req, "chat_history", None) or getattr(req, "history", None) or [],
92
+ question_text=question_text,
93
+ options_text=options_text,
94
+ category=category,
95
+ )
96
+
97
+ return JSONResponse(
98
+ {
99
+ "reply": result.reply,
100
+ "meta": {
101
+ "domain": result.domain,
102
+ "solved": result.solved,
103
+ "help_mode": result.help_mode,
104
+ "answer_letter": result.answer_letter,
105
+ "answer_value": result.answer_value,
106
+ "topic": result.topic,
107
+ "used_retrieval": result.used_retrieval,
108
+ "used_generator": result.used_generator,
109
+ },
110
+ }
111
+ )
112
+ except Exception as e:
113
+ return JSONResponse(
114
+ {
115
+ "error": type(e).__name__,
116
+ "detail": str(e),
117
+ },
118
+ status_code=500,
119
+ )
120
+
121
+
122
+ @app.post("/log/session/start")
123
+ def log_session_start(payload: SessionStartRequest) -> Dict[str, Any]:
124
+ return store.start_session(payload.session_id, payload.user_id, payload.condition, payload.metadata)
125
+
126
+
127
+ @app.post("/log/event")
128
+ def log_event(payload: EventLogRequest) -> Dict[str, Any]:
129
+ return store.log_event(payload.session_id, payload.event_type, payload.payload, payload.timestamp)
130
+
131
+
132
+ @app.post("/log/session/finalize")
133
+ def log_session_finalize(payload: SessionFinalizeRequest) -> Dict[str, Any]:
134
+ return store.finalize_session(payload.session_id, payload.summary)
135
+
136
+
137
+ @app.get("/research/sessions")
138
+ def research_sessions() -> Dict[str, Any]:
139
+ return {"sessions": store.list_sessions()}
140
+
141
+
142
+ @app.get("/research/session/{session_id}")
143
+ def research_session(session_id: str) -> Dict[str, Any]:
144
+ return store.get_session(session_id)