Spaces:
Paused
Paused
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()
|