Spaces:
Building
Building
Update chat_handler.py
Browse files- chat_handler.py +36 -28
chat_handler.py
CHANGED
@@ -1,14 +1,15 @@
|
|
1 |
"""
|
2 |
-
Flare – Chat Handler (
|
3 |
-
|
4 |
-
|
|
|
5 |
"""
|
6 |
|
7 |
import re, json, uuid, httpx, commentjson
|
8 |
from datetime import datetime
|
9 |
from typing import Dict, List, Optional
|
10 |
|
11 |
-
from fastapi import APIRouter, HTTPException
|
12 |
from pydantic import BaseModel
|
13 |
|
14 |
from prompt_builder import build_intent_prompt, build_parameter_prompt, log
|
@@ -46,7 +47,7 @@ async def spark_generate(prompt: str) -> str:
|
|
46 |
# ----------------------------------------------------------------------------
|
47 |
# FASTAPI ROUTER
|
48 |
# ----------------------------------------------------------------------------
|
49 |
-
router = APIRouter()
|
50 |
|
51 |
@router.get("/")
|
52 |
def health():
|
@@ -55,9 +56,12 @@ def health():
|
|
55 |
# Schemas
|
56 |
class StartSessionRequest(BaseModel):
|
57 |
project_name: str
|
58 |
-
|
59 |
-
|
60 |
user_input: str
|
|
|
|
|
|
|
61 |
class ChatResponse(BaseModel):
|
62 |
session_id: str
|
63 |
answer: str
|
@@ -72,20 +76,25 @@ async def start_session(req: StartSessionRequest):
|
|
72 |
return ChatResponse(session_id=s.id, answer="Nasıl yardımcı olabilirim?")
|
73 |
|
74 |
@router.post("/chat", response_model=ChatResponse)
|
75 |
-
async def chat(
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
|
|
|
|
|
|
|
|
|
|
80 |
s.history.append({"role": "user", "content": user_msg})
|
81 |
|
82 |
-
#
|
83 |
if s.awaiting:
|
84 |
answer = await _followup(s, user_msg)
|
85 |
s.history.append({"role": "assistant", "content": answer})
|
86 |
return ChatResponse(session_id=s.id, answer=answer)
|
87 |
|
88 |
-
#
|
89 |
gen_prompt = s.project["versions"][0]["general_prompt"]
|
90 |
intent_prompt = build_intent_prompt(gen_prompt, s.history, user_msg)
|
91 |
intent_out = await spark_generate(intent_prompt)
|
@@ -106,21 +115,21 @@ async def chat(req: ChatRequest):
|
|
106 |
return ChatResponse(session_id=s.id, answer=answer)
|
107 |
|
108 |
# ----------------------------------------------------------------------------
|
109 |
-
# Helper funcs
|
110 |
# ----------------------------------------------------------------------------
|
111 |
def _find_intent(project, name_):
|
112 |
return next((i for i in project["versions"][0]["intents"] if i["name"] == name_), None)
|
113 |
|
114 |
-
def _missing(
|
115 |
-
return [p["name"] for p in intent_cfg["parameters"] if p["variable_name"] not in
|
116 |
|
117 |
async def _handle_intent(s, intent_cfg, user_msg):
|
118 |
missing = _missing(s, intent_cfg)
|
119 |
if missing:
|
120 |
p_prompt = build_parameter_prompt(intent_cfg, missing, user_msg, s.history)
|
121 |
-
|
122 |
-
if
|
123 |
-
if bad := _process_params(s, intent_cfg,
|
124 |
return bad
|
125 |
missing = _missing(s, intent_cfg)
|
126 |
if missing:
|
@@ -134,10 +143,10 @@ async def _followup(s, user_msg):
|
|
134 |
intent_cfg = s.awaiting["intent"]
|
135 |
missing = s.awaiting["missing"]
|
136 |
p_prompt = build_parameter_prompt(intent_cfg, missing, user_msg, s.history)
|
137 |
-
|
138 |
-
if not
|
139 |
return "Üzgünüm, anlayamadım."
|
140 |
-
if bad := _process_params(s, intent_cfg,
|
141 |
return bad
|
142 |
missing = _missing(s, intent_cfg)
|
143 |
if missing:
|
@@ -147,11 +156,11 @@ async def _followup(s, user_msg):
|
|
147 |
s.awaiting = None
|
148 |
return await _call_api(s, intent_cfg)
|
149 |
|
150 |
-
def _process_params(s, intent_cfg,
|
151 |
try:
|
152 |
-
data = json.loads(
|
153 |
except json.JSONDecodeError:
|
154 |
-
return "
|
155 |
for pair in data.get("extracted", []):
|
156 |
p_cfg = next(p for p in intent_cfg["parameters"] if p["name"] == pair["name"])
|
157 |
if not _valid(p_cfg, pair["value"]):
|
@@ -165,9 +174,8 @@ def _valid(p_cfg, val):
|
|
165 |
|
166 |
async def _call_api(s, intent_cfg):
|
167 |
api = APIS[intent_cfg["action"]]
|
168 |
-
token
|
169 |
headers = {k: v.replace("{{token}}", token) for k, v in api["headers"].items()}
|
170 |
-
|
171 |
body = json.loads(json.dumps(api["body_template"]))
|
172 |
for k, v in body.items():
|
173 |
if isinstance(v, str) and v.startswith("{{") and v.endswith("}}"):
|
|
|
1 |
"""
|
2 |
+
Flare – Chat Handler (header edition)
|
3 |
+
====================================
|
4 |
+
/start_session -> JSON body döner
|
5 |
+
/chat -> X-Session-ID header + {"user_input": "..."}
|
6 |
"""
|
7 |
|
8 |
import re, json, uuid, httpx, commentjson
|
9 |
from datetime import datetime
|
10 |
from typing import Dict, List, Optional
|
11 |
|
12 |
+
from fastapi import APIRouter, HTTPException, Header, Request
|
13 |
from pydantic import BaseModel
|
14 |
|
15 |
from prompt_builder import build_intent_prompt, build_parameter_prompt, log
|
|
|
47 |
# ----------------------------------------------------------------------------
|
48 |
# FASTAPI ROUTER
|
49 |
# ----------------------------------------------------------------------------
|
50 |
+
router = APIRouter()
|
51 |
|
52 |
@router.get("/")
|
53 |
def health():
|
|
|
56 |
# Schemas
|
57 |
class StartSessionRequest(BaseModel):
|
58 |
project_name: str
|
59 |
+
|
60 |
+
class ChatBody(BaseModel):
|
61 |
user_input: str
|
62 |
+
# session_id optional for legacy
|
63 |
+
session_id: Optional[str] = None
|
64 |
+
|
65 |
class ChatResponse(BaseModel):
|
66 |
session_id: str
|
67 |
answer: str
|
|
|
76 |
return ChatResponse(session_id=s.id, answer="Nasıl yardımcı olabilirim?")
|
77 |
|
78 |
@router.post("/chat", response_model=ChatResponse)
|
79 |
+
async def chat(body: ChatBody,
|
80 |
+
request: Request,
|
81 |
+
x_session_id: Optional[str] = Header(None)):
|
82 |
+
# 1) Session ID alma: header > body
|
83 |
+
sid = x_session_id or body.session_id
|
84 |
+
if not sid or sid not in SESSIONS:
|
85 |
+
raise HTTPException(404, "Invalid or missing session")
|
86 |
+
|
87 |
+
s = SESSIONS[sid]
|
88 |
+
user_msg = body.user_input.strip()
|
89 |
s.history.append({"role": "user", "content": user_msg})
|
90 |
|
91 |
+
# ---------------- follow-up modunda mı?
|
92 |
if s.awaiting:
|
93 |
answer = await _followup(s, user_msg)
|
94 |
s.history.append({"role": "assistant", "content": answer})
|
95 |
return ChatResponse(session_id=s.id, answer=answer)
|
96 |
|
97 |
+
# ---------------- intent detect
|
98 |
gen_prompt = s.project["versions"][0]["general_prompt"]
|
99 |
intent_prompt = build_intent_prompt(gen_prompt, s.history, user_msg)
|
100 |
intent_out = await spark_generate(intent_prompt)
|
|
|
115 |
return ChatResponse(session_id=s.id, answer=answer)
|
116 |
|
117 |
# ----------------------------------------------------------------------------
|
118 |
+
# Helper funcs (aynı)
|
119 |
# ----------------------------------------------------------------------------
|
120 |
def _find_intent(project, name_):
|
121 |
return next((i for i in project["versions"][0]["intents"] if i["name"] == name_), None)
|
122 |
|
123 |
+
def _missing(s, intent_cfg):
|
124 |
+
return [p["name"] for p in intent_cfg["parameters"] if p["variable_name"] not in s.variables]
|
125 |
|
126 |
async def _handle_intent(s, intent_cfg, user_msg):
|
127 |
missing = _missing(s, intent_cfg)
|
128 |
if missing:
|
129 |
p_prompt = build_parameter_prompt(intent_cfg, missing, user_msg, s.history)
|
130 |
+
out = await spark_generate(p_prompt)
|
131 |
+
if out.startswith("#PARAMETERS:"):
|
132 |
+
if bad := _process_params(s, intent_cfg, out):
|
133 |
return bad
|
134 |
missing = _missing(s, intent_cfg)
|
135 |
if missing:
|
|
|
143 |
intent_cfg = s.awaiting["intent"]
|
144 |
missing = s.awaiting["missing"]
|
145 |
p_prompt = build_parameter_prompt(intent_cfg, missing, user_msg, s.history)
|
146 |
+
out = await spark_generate(p_prompt)
|
147 |
+
if not out.startswith("#PARAMETERS:"):
|
148 |
return "Üzgünüm, anlayamadım."
|
149 |
+
if bad := _process_params(s, intent_cfg, out):
|
150 |
return bad
|
151 |
missing = _missing(s, intent_cfg)
|
152 |
if missing:
|
|
|
156 |
s.awaiting = None
|
157 |
return await _call_api(s, intent_cfg)
|
158 |
|
159 |
+
def _process_params(s, intent_cfg, out):
|
160 |
try:
|
161 |
+
data = json.loads(out[len("#PARAMETERS:"):])
|
162 |
except json.JSONDecodeError:
|
163 |
+
return "Parametreleri çözemedim."
|
164 |
for pair in data.get("extracted", []):
|
165 |
p_cfg = next(p for p in intent_cfg["parameters"] if p["name"] == pair["name"])
|
166 |
if not _valid(p_cfg, pair["value"]):
|
|
|
174 |
|
175 |
async def _call_api(s, intent_cfg):
|
176 |
api = APIS[intent_cfg["action"]]
|
177 |
+
token = "testtoken"
|
178 |
headers = {k: v.replace("{{token}}", token) for k, v in api["headers"].items()}
|
|
|
179 |
body = json.loads(json.dumps(api["body_template"]))
|
180 |
for k, v in body.items():
|
181 |
if isinstance(v, str) and v.startswith("{{") and v.endswith("}}"):
|