Spaces:
Building
Building
Update chat_handler.py
Browse files- chat_handler.py +113 -10
chat_handler.py
CHANGED
@@ -155,7 +155,7 @@ def _extract_parameters_from_response(raw: str, session: Session, intent_config)
|
|
155 |
|
156 |
# ───────────────────────── API EXECUTION ───────────────────────── #
|
157 |
async def _execute_api_call(session: Session, intent_config) -> str:
|
158 |
-
"""Execute API call and return humanized response"""
|
159 |
try:
|
160 |
session.state = "call_api"
|
161 |
api_name = intent_config.action
|
@@ -164,7 +164,7 @@ async def _execute_api_call(session: Session, intent_config) -> str:
|
|
164 |
if not api_config:
|
165 |
log_info(f"❌ API config not found: {api_name}")
|
166 |
session.reset_flow()
|
167 |
-
return
|
168 |
|
169 |
log_info(f"📡 Calling API: {api_name}")
|
170 |
log_info(f"📦 API variables: {session.variables}")
|
@@ -191,11 +191,11 @@ async def _execute_api_call(session: Session, intent_config) -> str:
|
|
191 |
except requests.exceptions.Timeout:
|
192 |
log_warning(f"⏱️ API timeout: {api_name}")
|
193 |
session.reset_flow()
|
194 |
-
return
|
195 |
except Exception as e:
|
196 |
log_error("❌ API call error", e)
|
197 |
session.reset_flow()
|
198 |
-
return
|
199 |
|
200 |
# ───────────────────────── REQUEST MODELS ───────────────────────── #
|
201 |
class ChatRequest(BaseModel):
|
@@ -282,8 +282,25 @@ async def chat(req: ChatRequest, x_session_id: str = Header(...)):
|
|
282 |
# Get session
|
283 |
session = session_store.get(x_session_id)
|
284 |
if not session:
|
285 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
286 |
|
|
|
|
|
|
|
|
|
|
|
287 |
# Add user message to history
|
288 |
session.add_message("user", req.message)
|
289 |
log_info(f"💬 User [{session.session_id[:8]}...]: {req.message}")
|
@@ -291,13 +308,19 @@ async def chat(req: ChatRequest, x_session_id: str = Header(...)):
|
|
291 |
# Get project and version config
|
292 |
project = next((p for p in cfg.projects if p.name == session.project_name), None)
|
293 |
if not project:
|
294 |
-
raise HTTPException(
|
|
|
|
|
|
|
295 |
|
296 |
version = session.get_version_config()
|
297 |
if not version:
|
298 |
-
raise HTTPException(
|
|
|
|
|
|
|
299 |
|
300 |
-
# Process based on current state
|
301 |
if session.state == "idle":
|
302 |
# Build intent detection prompt
|
303 |
prompt = build_intent_prompt(version, session.chat_history, project.default_locale)
|
@@ -400,15 +423,28 @@ async def chat(req: ChatRequest, x_session_id: str = Header(...)):
|
|
400 |
else:
|
401 |
# Unknown state, reset
|
402 |
session.reset_flow()
|
403 |
-
return {"response": "
|
404 |
|
405 |
except HTTPException:
|
406 |
raise
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
407 |
except Exception as e:
|
408 |
log_error("❌ Chat error", e)
|
409 |
import traceback
|
410 |
traceback.print_exc()
|
411 |
-
|
|
|
|
|
|
|
|
|
|
|
412 |
|
413 |
async def handle_new_message(session: Session, user_input: str) -> str:
|
414 |
"""Handle new message (not parameter followup) - for WebSocket"""
|
@@ -537,5 +573,72 @@ async def handle_parameter_followup(session: Session, user_input: str) -> str:
|
|
537 |
session.reset_flow()
|
538 |
return "Bir hata oluştu. Lütfen tekrar deneyin."
|
539 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
540 |
# Initialize LLM on module load
|
541 |
setup_llm_provider()
|
|
|
155 |
|
156 |
# ───────────────────────── API EXECUTION ───────────────────────── #
|
157 |
async def _execute_api_call(session: Session, intent_config) -> str:
|
158 |
+
"""Execute API call and return humanized response with better error handling"""
|
159 |
try:
|
160 |
session.state = "call_api"
|
161 |
api_name = intent_config.action
|
|
|
164 |
if not api_config:
|
165 |
log_info(f"❌ API config not found: {api_name}")
|
166 |
session.reset_flow()
|
167 |
+
return get_user_friendly_error("api_error", {"api_name": api_name})
|
168 |
|
169 |
log_info(f"📡 Calling API: {api_name}")
|
170 |
log_info(f"📦 API variables: {session.variables}")
|
|
|
191 |
except requests.exceptions.Timeout:
|
192 |
log_warning(f"⏱️ API timeout: {api_name}")
|
193 |
session.reset_flow()
|
194 |
+
return get_user_friendly_error("api_timeout")
|
195 |
except Exception as e:
|
196 |
log_error("❌ API call error", e)
|
197 |
session.reset_flow()
|
198 |
+
return get_user_friendly_error("api_error", {"api_name": api_name})
|
199 |
|
200 |
# ───────────────────────── REQUEST MODELS ───────────────────────── #
|
201 |
class ChatRequest(BaseModel):
|
|
|
282 |
# Get session
|
283 |
session = session_store.get(x_session_id)
|
284 |
if not session:
|
285 |
+
# Better error message
|
286 |
+
raise HTTPException(
|
287 |
+
status_code=404,
|
288 |
+
detail=get_user_friendly_error("session_not_found")
|
289 |
+
)
|
290 |
+
|
291 |
+
# Session expiry check ekle
|
292 |
+
if session.is_expired():
|
293 |
+
session_store.delete_session(x_session_id)
|
294 |
+
raise HTTPException(
|
295 |
+
status_code=401,
|
296 |
+
detail=get_user_friendly_error("session_expired")
|
297 |
+
)
|
298 |
|
299 |
+
# Update last activity
|
300 |
+
session.last_activity = datetime.utcnow().isoformat()
|
301 |
+
session_store.update_session(session)
|
302 |
+
|
303 |
+
# Mevcut kod devam ediyor...
|
304 |
# Add user message to history
|
305 |
session.add_message("user", req.message)
|
306 |
log_info(f"💬 User [{session.session_id[:8]}...]: {req.message}")
|
|
|
308 |
# Get project and version config
|
309 |
project = next((p for p in cfg.projects if p.name == session.project_name), None)
|
310 |
if not project:
|
311 |
+
raise HTTPException(
|
312 |
+
status_code=404,
|
313 |
+
detail=get_user_friendly_error("project_not_found")
|
314 |
+
)
|
315 |
|
316 |
version = session.get_version_config()
|
317 |
if not version:
|
318 |
+
raise HTTPException(
|
319 |
+
status_code=400,
|
320 |
+
detail=get_user_friendly_error("version_not_found")
|
321 |
+
)
|
322 |
|
323 |
+
# Process based on current state - MEVCUT KODU KORUYORUZ
|
324 |
if session.state == "idle":
|
325 |
# Build intent detection prompt
|
326 |
prompt = build_intent_prompt(version, session.chat_history, project.default_locale)
|
|
|
423 |
else:
|
424 |
# Unknown state, reset
|
425 |
session.reset_flow()
|
426 |
+
return {"response": get_user_friendly_error("internal_error"), "state": "error"}
|
427 |
|
428 |
except HTTPException:
|
429 |
raise
|
430 |
+
except requests.exceptions.Timeout:
|
431 |
+
# Better timeout error
|
432 |
+
log_error(f"Timeout in chat for session {x_session_id[:8]}")
|
433 |
+
return {
|
434 |
+
"response": get_user_friendly_error("llm_timeout"),
|
435 |
+
"state": "error",
|
436 |
+
"error": True
|
437 |
+
}
|
438 |
except Exception as e:
|
439 |
log_error("❌ Chat error", e)
|
440 |
import traceback
|
441 |
traceback.print_exc()
|
442 |
+
# Better generic error
|
443 |
+
return {
|
444 |
+
"response": get_user_friendly_error("internal_error"),
|
445 |
+
"state": "error",
|
446 |
+
"error": True
|
447 |
+
}
|
448 |
|
449 |
async def handle_new_message(session: Session, user_input: str) -> str:
|
450 |
"""Handle new message (not parameter followup) - for WebSocket"""
|
|
|
573 |
session.reset_flow()
|
574 |
return "Bir hata oluştu. Lütfen tekrar deneyin."
|
575 |
|
576 |
+
def get_user_friendly_error(error_type: str, context: dict = None) -> str:
|
577 |
+
"""Get user-friendly error messages"""
|
578 |
+
error_messages = {
|
579 |
+
"session_not_found": "Oturumunuz bulunamadı. Lütfen yeni bir konuşma başlatın.",
|
580 |
+
"project_not_found": "Proje konfigürasyonu bulunamadı. Lütfen yönetici ile iletişime geçin.",
|
581 |
+
"version_not_found": "Proje versiyonu bulunamadı. Lütfen geçerli bir versiyon seçin.",
|
582 |
+
"intent_not_found": "Üzgünüm, ne yapmak istediğinizi anlayamadım. Lütfen daha açık bir şekilde belirtir misiniz?",
|
583 |
+
"api_timeout": "İşlem zaman aşımına uğradı. Lütfen tekrar deneyin.",
|
584 |
+
"api_error": "İşlem sırasında bir hata oluştu. Lütfen daha sonra tekrar deneyin.",
|
585 |
+
"parameter_validation": "Girdiğiniz bilgide bir hata var. Lütfen kontrol edip tekrar deneyin.",
|
586 |
+
"llm_error": "Sistem yanıt veremedi. Lütfen biraz sonra tekrar deneyin.",
|
587 |
+
"llm_timeout": "Sistem meşgul. Lütfen birkaç saniye bekleyip tekrar deneyin.",
|
588 |
+
"session_expired": "Oturumunuz zaman aşımına uğradı. Lütfen yeni bir konuşma başlatın.",
|
589 |
+
"rate_limit": "Çok fazla istek gönderdiniz. Lütfen biraz bekleyin.",
|
590 |
+
"internal_error": "Beklenmeyen bir hata oluştu. Lütfen yönetici ile iletişime geçin."
|
591 |
+
}
|
592 |
+
|
593 |
+
message = error_messages.get(error_type, error_messages["internal_error"])
|
594 |
+
|
595 |
+
# Context bilgisi varsa ekle
|
596 |
+
if context:
|
597 |
+
if error_type == "parameter_validation" and "field" in context:
|
598 |
+
message = f"{context['field']} alanı için {message}"
|
599 |
+
elif error_type == "api_error" and "api_name" in context:
|
600 |
+
message = f"{context['api_name']} servisi için {message}"
|
601 |
+
|
602 |
+
return message
|
603 |
+
|
604 |
+
def validate_parameter_with_message(param_config, value, locale="tr") -> tuple[bool, str]:
|
605 |
+
"""Validate parameter and return user-friendly message"""
|
606 |
+
try:
|
607 |
+
# Type validation
|
608 |
+
if param_config.type == "int":
|
609 |
+
try:
|
610 |
+
int(value)
|
611 |
+
except ValueError:
|
612 |
+
return False, f"Lütfen geçerli bir sayı girin."
|
613 |
+
|
614 |
+
elif param_config.type == "float":
|
615 |
+
try:
|
616 |
+
float(value)
|
617 |
+
except ValueError:
|
618 |
+
return False, f"Lütfen geçerli bir ondalık sayı girin."
|
619 |
+
|
620 |
+
elif param_config.type == "date":
|
621 |
+
# Date parsing with locale support
|
622 |
+
from locale_manager import LocaleManager
|
623 |
+
parsed_date = LocaleManager.parse_date_expression(value, locale)
|
624 |
+
if not parsed_date:
|
625 |
+
return False, f"Lütfen geçerli bir tarih girin (örn: yarın, 15 Haziran, 2025-06-15)."
|
626 |
+
|
627 |
+
elif param_config.type == "bool":
|
628 |
+
if value.lower() not in ["evet", "hayır", "yes", "no", "true", "false"]:
|
629 |
+
return False, f"Lütfen 'evet' veya 'hayır' olarak cevaplayın."
|
630 |
+
|
631 |
+
# Regex validation
|
632 |
+
if param_config.validation_regex:
|
633 |
+
import re
|
634 |
+
if not re.match(param_config.validation_regex, value):
|
635 |
+
return False, param_config.invalid_prompt or "Girdiğiniz değer geçerli formatta değil."
|
636 |
+
|
637 |
+
return True, ""
|
638 |
+
|
639 |
+
except Exception as e:
|
640 |
+
log_error(f"Parameter validation error", e)
|
641 |
+
return False, "Değer kontrol edilirken bir hata oluştu."
|
642 |
+
|
643 |
# Initialize LLM on module load
|
644 |
setup_llm_provider()
|