ciyidogan commited on
Commit
3f2fcc0
·
verified ·
1 Parent(s): 162db22

Update chat_handler.py

Browse files
Files changed (1) hide show
  1. chat_handler.py +51 -52
chat_handler.py CHANGED
@@ -1,6 +1,6 @@
1
  """
2
- Flare – Chat Handler (small-talk trim + resmî selamlama)
3
- =========================================================
4
  """
5
 
6
  import re, json, uuid, sys, httpx, commentjson
@@ -17,25 +17,31 @@ from prompt_builder import build_intent_prompt, build_parameter_prompt, log
17
  # HELPERS
18
  # ─────────────────────────
19
  def _trim_smalltalk(raw: str) -> str:
20
- """
21
- Kısa selamlaşma çıktısında yalnızca ilk blok (etiketsiz) kısmını döndürür.
22
- """
23
  # intent etiketi öncesini al
24
  pos_intent = raw.find("#DETECTED_INTENT")
25
  if pos_intent != -1:
26
  raw = raw[:pos_intent]
27
 
28
- # arka arkaya 'assistant' blokları varsa ilkini al
29
- pos_asst = raw.lower().find("assistant")
30
- if pos_asst != -1:
31
- raw = raw[:pos_asst]
32
 
 
 
 
 
 
 
 
 
33
  return raw.strip()
34
 
35
 
36
- # ─────────────────────────
37
  # CONFIG LOAD
38
- # ─────────────────────────
39
  def load_config(path: str = "service_config.jsonc") -> dict:
40
  try:
41
  with open(path, encoding="utf-8") as f:
@@ -53,9 +59,9 @@ SPARK_URL = CFG["config"]["spark_endpoint"].rstrip("/") + "/generate"
53
  ALLOWED_INTENTS = {"flight-booking", "flight-info", "booking-cancel"}
54
 
55
 
56
- # ─────────────────────────
57
  # SESSION
58
- # ─────────────────────────
59
  class Session:
60
  def __init__(self, project_name: str):
61
  self.id = str(uuid.uuid4())
@@ -68,9 +74,9 @@ class Session:
68
  SESSIONS: Dict[str, Session] = {}
69
 
70
 
71
- # ─────────────────────────
72
  # SPARK CLIENT
73
- # ─────────────────────────
74
  async def spark_generate(session: Session,
75
  system_prompt: str,
76
  user_input: str) -> str:
@@ -85,14 +91,13 @@ async def spark_generate(session: Session,
85
  r.raise_for_status()
86
  d = r.json()
87
  raw = (d.get("assistant") or d.get("model_answer") or d.get("text", ""))
88
- log(f"🪄 Spark raw: {raw!r}") # ham içerik
89
  return raw.strip()
90
- return (d.get("assistant") or d.get("model_answer") or d.get("text", "")).strip()
91
 
92
 
93
- # ─────────────────────────
94
  # FASTAPI ROUTER
95
- # ─────────────────────────
96
  router = APIRouter()
97
 
98
  @router.get("/")
@@ -108,16 +113,17 @@ class ChatResponse(BaseModel):
108
  answer: str
109
 
110
 
111
- # ─────────────────────────
112
  # ENDPOINTS
113
- # ─────────────────────────
114
  @router.post("/start_session", response_model=ChatResponse)
115
  async def start_session(req: StartSessionRequest):
116
  if req.project_name not in PROJECTS:
117
  raise HTTPException(404, "Unknown project")
118
  s = Session(req.project_name)
119
  SESSIONS[s.id] = s
120
- return ChatResponse(session_id=s.id, answer="Hoş geldiniz! Size nasıl yardımcı olabilirim?")
 
121
 
122
  @router.post("/chat", response_model=ChatResponse)
123
  async def chat(body: ChatBody, x_session_id: str = Header(...)):
@@ -137,42 +143,35 @@ async def chat(body: ChatBody, x_session_id: str = Header(...)):
137
  # intent detect
138
  gen_prompt = s.project["versions"][0]["general_prompt"]
139
  intents_cfg = s.project["versions"][0]["intents"]
140
- intent_raw = await spark_generate(
141
  s,
142
  build_intent_prompt(gen_prompt, s.history, user_msg, intents_cfg),
143
  user_msg
144
  )
145
 
146
- # intent_raw geldi ─
147
  if intent_raw.strip() == "":
148
- fallback = "Üzgünüm, şu anda isteğinizi işlemekte zorlanıyorum. Lütfen mesajınızı tekrar edebilir misiniz?"
149
  s.history.append({"role": "assistant", "content": fallback})
150
  return ChatResponse(session_id=s.id, answer=fallback)
151
 
152
- # small-talk yolu
153
  if not intent_raw.startswith("#DETECTED_INTENT:"):
154
  clean = _trim_smalltalk(intent_raw)
155
- # Selamlama resmî değilse düzelt
156
- if "Hoşgeldin" in clean or "Hoş geldin" in clean:
157
- clean = clean.replace("Hoşgeldin", "Hoş geldiniz").replace("Hoş geldin", "Hoş geldiniz")
158
  s.history.append({"role": "assistant", "content": clean})
159
  return ChatResponse(session_id=s.id, answer=clean)
160
 
161
- intent_name = intent_raw.split(":", 1)[1].strip()
 
 
 
162
 
163
  # kısa mesaj guard
164
- if len(user_msg.split()) < 3:
165
- clean = _trim_smalltalk(intent_raw)
166
  s.history.append({"role": "assistant", "content": clean})
167
  return ChatResponse(session_id=s.id, answer=clean)
168
 
169
- # allowed-set
170
- if intent_name not in ALLOWED_INTENTS:
171
- clean = _trim_smalltalk(intent_raw)
172
- s.history.append({"role": "assistant", "content": clean})
173
- return ChatResponse(session_id=s.id, answer=clean)
174
-
175
- # intent handling ...
176
  intent_cfg = _find_intent(s.project, intent_name)
177
  if not intent_cfg:
178
  err = "Üzgünüm, anlayamadım."
@@ -183,9 +182,10 @@ async def chat(body: ChatBody, x_session_id: str = Header(...)):
183
  s.history.append({"role": "assistant", "content": answer})
184
  return ChatResponse(session_id=s.id, answer=answer)
185
 
186
- # --------------------------------------------------------------------------- #
187
- # HELPER FUNCS (değişmeyen kısımlar)
188
- # --------------------------------------------------------------------------- #
 
189
  def _find_intent(project, name_):
190
  return next((i for i in project["versions"][0]["intents"] if i["name"] == name_), None)
191
 
@@ -210,15 +210,16 @@ async def _handle_intent(s, intent_cfg, user_msg):
210
 
211
  async def _followup(s, user_msg):
212
  intent_cfg = s.awaiting["intent"]
213
- missing = s.awaiting["missing"]
214
- p_prompt = build_parameter_prompt(intent_cfg, missing, user_msg, s.history)
215
- p_raw = await spark_generate(s, p_prompt, user_msg)
216
  if not p_raw.startswith("#PARAMETERS:") or _process_params(s, intent_cfg, p_raw):
217
  return "Üzgünüm, anlayamadım."
218
  missing = _missing(s, intent_cfg)
219
  if missing:
220
  s.awaiting["missing"] = missing
221
- cap = next(p for p in intent_cfg["parameters"] if p["name"] == missing[0])["caption"]
 
222
  return f"{cap} nedir?"
223
  s.awaiting = None
224
  return await _call_api(s, intent_cfg)
@@ -254,11 +255,9 @@ async def _call_api(s, intent_cfg):
254
  api_json = r.json()
255
  except Exception:
256
  return intent_cfg["fallback_error_prompt"]
257
- summary_prompt = api["response_prompt"].replace("{{api_response}}", json.dumps(api_json, ensure_ascii=False))
258
-
259
- summary = await spark_generate(s, summary_prompt, "")
260
  if summary.strip() == "":
261
- # yedek plan
262
- summary = f"İşlem sonuç verisi: {json.dumps(api_json, ensure_ascii=False)}"
263
-
264
  return summary
 
1
  """
2
+ Flare – Chat Handler (regex-intent, small-talk trim, boş-yanıt fallback)
3
+ ========================================================================
4
  """
5
 
6
  import re, json, uuid, sys, httpx, commentjson
 
17
  # HELPERS
18
  # ─────────────────────────
19
  def _trim_smalltalk(raw: str) -> str:
20
+ """Keep only the very first greeting sentence; cut everything else."""
 
 
21
  # intent etiketi öncesini al
22
  pos_intent = raw.find("#DETECTED_INTENT")
23
  if pos_intent != -1:
24
  raw = raw[:pos_intent]
25
 
26
+ # model kendi prompt'umuzu eklediyse kes
27
+ pos_sys = raw.find("⚠️")
28
+ if pos_sys != -1:
29
+ raw = raw[:pos_sys]
30
 
31
+ # ilk 'assistant' bloğundan sonrası at
32
+ for marker in ["assistant\n\n", "assistant\n", "assistant"]:
33
+ idx = raw.lower().find(marker)
34
+ if 0 <= idx <= 2:
35
+ raw = raw[idx + len(marker):]
36
+
37
+ # resmî selam: Hoş geldiniz
38
+ raw = re.sub(r"Hoş[\s-]?geldin(iz)?", "Hoş geldiniz", raw, flags=re.IGNORECASE)
39
  return raw.strip()
40
 
41
 
42
+ # ---------------------------------------------------------------------- #
43
  # CONFIG LOAD
44
+ # ---------------------------------------------------------------------- #
45
  def load_config(path: str = "service_config.jsonc") -> dict:
46
  try:
47
  with open(path, encoding="utf-8") as f:
 
59
  ALLOWED_INTENTS = {"flight-booking", "flight-info", "booking-cancel"}
60
 
61
 
62
+ # ---------------------------------------------------------------------- #
63
  # SESSION
64
+ # ---------------------------------------------------------------------- #
65
  class Session:
66
  def __init__(self, project_name: str):
67
  self.id = str(uuid.uuid4())
 
74
  SESSIONS: Dict[str, Session] = {}
75
 
76
 
77
+ # ---------------------------------------------------------------------- #
78
  # SPARK CLIENT
79
+ # ---------------------------------------------------------------------- #
80
  async def spark_generate(session: Session,
81
  system_prompt: str,
82
  user_input: str) -> str:
 
91
  r.raise_for_status()
92
  d = r.json()
93
  raw = (d.get("assistant") or d.get("model_answer") or d.get("text", ""))
94
+ log(f"🪄 Spark raw: {raw!r}")
95
  return raw.strip()
 
96
 
97
 
98
+ # ---------------------------------------------------------------------- #
99
  # FASTAPI ROUTER
100
+ # ---------------------------------------------------------------------- #
101
  router = APIRouter()
102
 
103
  @router.get("/")
 
113
  answer: str
114
 
115
 
116
+ # ---------------------------------------------------------------------- #
117
  # ENDPOINTS
118
+ # ---------------------------------------------------------------------- #
119
  @router.post("/start_session", response_model=ChatResponse)
120
  async def start_session(req: StartSessionRequest):
121
  if req.project_name not in PROJECTS:
122
  raise HTTPException(404, "Unknown project")
123
  s = Session(req.project_name)
124
  SESSIONS[s.id] = s
125
+ return ChatResponse(session_id=s.id,
126
+ answer="Hoş geldiniz! Size nasıl yardımcı olabilirim?")
127
 
128
  @router.post("/chat", response_model=ChatResponse)
129
  async def chat(body: ChatBody, x_session_id: str = Header(...)):
 
143
  # intent detect
144
  gen_prompt = s.project["versions"][0]["general_prompt"]
145
  intents_cfg = s.project["versions"][0]["intents"]
146
+ intent_raw = await spark_generate(
147
  s,
148
  build_intent_prompt(gen_prompt, s.history, user_msg, intents_cfg),
149
  user_msg
150
  )
151
 
152
+ # boş çıktıyı yakala
153
  if intent_raw.strip() == "":
154
+ fallback = "Üzgünüm, mesajınızı anlayamadım. Lütfen tekrar dener misiniz?"
155
  s.history.append({"role": "assistant", "content": fallback})
156
  return ChatResponse(session_id=s.id, answer=fallback)
157
 
158
+ # küçük selamlaşma yolu
159
  if not intent_raw.startswith("#DETECTED_INTENT:"):
160
  clean = _trim_smalltalk(intent_raw)
 
 
 
161
  s.history.append({"role": "assistant", "content": clean})
162
  return ChatResponse(session_id=s.id, answer=clean)
163
 
164
+ # regex ile intent + extras ayır
165
+ m = re.search(r"#DETECTED_INTENT:\s*([A-Za-z0-9_-]+)", intent_raw)
166
+ intent_name = m.group(1) if m else ""
167
+ extras = intent_raw[m.end():].strip() if m else ""
168
 
169
  # kısa mesaj guard
170
+ if len(user_msg.split()) < 3 or intent_name not in ALLOWED_INTENTS:
171
+ clean = _trim_smalltalk(extras or intent_raw)
172
  s.history.append({"role": "assistant", "content": clean})
173
  return ChatResponse(session_id=s.id, answer=clean)
174
 
 
 
 
 
 
 
 
175
  intent_cfg = _find_intent(s.project, intent_name)
176
  if not intent_cfg:
177
  err = "Üzgünüm, anlayamadım."
 
182
  s.history.append({"role": "assistant", "content": answer})
183
  return ChatResponse(session_id=s.id, answer=answer)
184
 
185
+
186
+ # ---------------------------------------------------------------------- #
187
+ # HELPER FUNCS (değişmedi)
188
+ # ---------------------------------------------------------------------- #
189
  def _find_intent(project, name_):
190
  return next((i for i in project["versions"][0]["intents"] if i["name"] == name_), None)
191
 
 
210
 
211
  async def _followup(s, user_msg):
212
  intent_cfg = s.awaiting["intent"]
213
+ missing = s.awaiting["missing"]
214
+ p_prompt = build_parameter_prompt(intent_cfg, missing, user_msg, s.history)
215
+ p_raw = await spark_generate(s, p_prompt, user_msg)
216
  if not p_raw.startswith("#PARAMETERS:") or _process_params(s, intent_cfg, p_raw):
217
  return "Üzgünüm, anlayamadım."
218
  missing = _missing(s, intent_cfg)
219
  if missing:
220
  s.awaiting["missing"] = missing
221
+ cap = next(p for p in intent_cfg["parameters"]
222
+ if p["name"] == missing[0])["caption"]
223
  return f"{cap} nedir?"
224
  s.awaiting = None
225
  return await _call_api(s, intent_cfg)
 
255
  api_json = r.json()
256
  except Exception:
257
  return intent_cfg["fallback_error_prompt"]
258
+
259
+ sum_prompt = api["response_prompt"].replace("{{api_response}}", json.dumps(api_json, ensure_ascii=False))
260
+ summary = await spark_generate(s, sum_prompt, "")
261
  if summary.strip() == "":
262
+ summary = f"İşlem sonucu: {json.dumps(api_json, ensure_ascii=False)}"
 
 
263
  return summary