Spaces:
Building
Building
Update chat_handler.py
Browse files- chat_handler.py +142 -23
chat_handler.py
CHANGED
@@ -11,7 +11,7 @@ from fastapi import APIRouter, HTTPException, Header
|
|
11 |
from pydantic import BaseModel
|
12 |
import requests
|
13 |
|
14 |
-
from prompt_builder import build_intent_prompt, build_parameter_prompt
|
15 |
from utils import log
|
16 |
from api_executor import call_api as execute_api
|
17 |
from validation_engine import validate
|
@@ -292,7 +292,7 @@ async def _handle_new_message(session: Session, user_input: str, version) -> str
|
|
292 |
return await _extract_parameters(session, intent_config, user_input)
|
293 |
|
294 |
async def _handle_parameter_followup(session: Session, user_input: str, version) -> str:
|
295 |
-
"""Handle parameter collection followup"""
|
296 |
if not session.last_intent:
|
297 |
log("⚠️ No last intent in session")
|
298 |
session.reset_flow()
|
@@ -315,24 +315,46 @@ async def _handle_parameter_followup(session: Session, user_input: str, version)
|
|
315 |
# Try parsing with or without #PARAMETERS: prefix
|
316 |
success = _process_parameters(session, intent_config, raw)
|
317 |
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
323 |
if session.missing_ask_count >= 3:
|
324 |
session.reset_flow()
|
325 |
return "Üzgünüm, istediğiniz bilgileri anlayamadım. Başka bir konuda yardımcı olabilir miyim?"
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
|
|
|
|
|
|
|
|
|
|
336 |
|
337 |
# All parameters collected, call API
|
338 |
log("✅ All parameters collected, calling API")
|
@@ -341,7 +363,12 @@ async def _handle_parameter_followup(session: Session, user_input: str, version)
|
|
341 |
|
342 |
# ───────────────────────── PARAMETER HANDLING ───────────────────────── #
|
343 |
async def _extract_parameters(session: Session, intent_config, user_input: str) -> str:
|
344 |
-
"""Extract parameters from user input"""
|
|
|
|
|
|
|
|
|
|
|
345 |
missing = _get_missing_parameters(session, intent_config)
|
346 |
log(f"🔍 Missing parameters: {missing}")
|
347 |
|
@@ -364,18 +391,110 @@ async def _extract_parameters(session: Session, intent_config, user_input: str)
|
|
364 |
log("⚠️ Failed to extract parameters from response")
|
365 |
|
366 |
if missing:
|
367 |
-
# Still missing parameters
|
368 |
session.state = "await_param"
|
369 |
-
session.awaiting_parameters = missing
|
370 |
session.missing_ask_count = 0
|
371 |
-
|
372 |
-
|
373 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
374 |
|
375 |
# All parameters collected
|
376 |
log("✅ All parameters collected after extraction")
|
377 |
return await _execute_api_call(session, intent_config)
|
378 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
379 |
def _get_missing_parameters(session: Session, intent_config) -> List[str]:
|
380 |
"""Get list of missing required parameters"""
|
381 |
missing = [
|
|
|
11 |
from pydantic import BaseModel
|
12 |
import requests
|
13 |
|
14 |
+
from prompt_builder import build_intent_prompt, build_parameter_prompt, build_smart_parameter_question_prompt, extract_params_from_question
|
15 |
from utils import log
|
16 |
from api_executor import call_api as execute_api
|
17 |
from validation_engine import validate
|
|
|
292 |
return await _extract_parameters(session, intent_config, user_input)
|
293 |
|
294 |
async def _handle_parameter_followup(session: Session, user_input: str, version) -> str:
|
295 |
+
"""Handle parameter collection followup with smart question generation"""
|
296 |
if not session.last_intent:
|
297 |
log("⚠️ No last intent in session")
|
298 |
session.reset_flow()
|
|
|
315 |
# Try parsing with or without #PARAMETERS: prefix
|
316 |
success = _process_parameters(session, intent_config, raw)
|
317 |
|
318 |
+
# Hangi parametreler hala eksik?
|
319 |
+
still_missing = _get_missing_parameters(session, intent_config)
|
320 |
+
|
321 |
+
# Sorulan ama cevaplanmayan parametreleri belirle
|
322 |
+
asked_but_not_answered = []
|
323 |
+
for param in session.awaiting_parameters:
|
324 |
+
if param in still_missing:
|
325 |
+
asked_but_not_answered.append(param)
|
326 |
+
|
327 |
+
# Cevaplanmayanları session'a kaydet
|
328 |
+
if asked_but_not_answered:
|
329 |
+
session.mark_parameters_unanswered(asked_but_not_answered)
|
330 |
+
log(f"❓ Parameters not answered: {asked_but_not_answered}")
|
331 |
+
|
332 |
+
# Cevaplananları işaretle
|
333 |
+
for param in session.awaiting_parameters:
|
334 |
+
if param not in still_missing:
|
335 |
+
session.mark_parameter_answered(param)
|
336 |
+
log(f"✅ Parameter answered: {param}")
|
337 |
+
|
338 |
+
if still_missing:
|
339 |
+
# Maksimum deneme kontrolü
|
340 |
if session.missing_ask_count >= 3:
|
341 |
session.reset_flow()
|
342 |
return "Üzgünüm, istediğiniz bilgileri anlayamadım. Başka bir konuda yardımcı olabilir miyim?"
|
343 |
+
|
344 |
+
session.missing_ask_count += 1
|
345 |
+
|
346 |
+
# Akıllı soru üret
|
347 |
+
question = await _generate_smart_parameter_question(
|
348 |
+
session, intent_config, still_missing, version
|
349 |
+
)
|
350 |
+
|
351 |
+
# Sorulan parametreleri tahmin et ve kaydet
|
352 |
+
params_in_question = extract_params_from_question(question, still_missing, intent_config)
|
353 |
+
session.record_parameter_question(params_in_question)
|
354 |
+
session.awaiting_parameters = params_in_question
|
355 |
+
|
356 |
+
log(f"🤖 Smart question generated for params: {params_in_question}")
|
357 |
+
return question
|
358 |
|
359 |
# All parameters collected, call API
|
360 |
log("✅ All parameters collected, calling API")
|
|
|
363 |
|
364 |
# ───────────────────────── PARAMETER HANDLING ───────────────────────── #
|
365 |
async def _extract_parameters(session: Session, intent_config, user_input: str) -> str:
|
366 |
+
"""Extract parameters from user input with smart question generation"""
|
367 |
+
|
368 |
+
# Yeni intent için parametre takibini sıfırla
|
369 |
+
if session.parameter_ask_rounds == 0:
|
370 |
+
session.reset_parameter_tracking()
|
371 |
+
|
372 |
missing = _get_missing_parameters(session, intent_config)
|
373 |
log(f"🔍 Missing parameters: {missing}")
|
374 |
|
|
|
391 |
log("⚠️ Failed to extract parameters from response")
|
392 |
|
393 |
if missing:
|
394 |
+
# Still missing parameters - generate smart question
|
395 |
session.state = "await_param"
|
|
|
396 |
session.missing_ask_count = 0
|
397 |
+
|
398 |
+
# Akıllı soru üret
|
399 |
+
question = await _generate_smart_parameter_question(
|
400 |
+
session, intent_config, missing, version
|
401 |
+
)
|
402 |
+
|
403 |
+
# Sorulan parametreleri tahmin et ve kaydet
|
404 |
+
params_in_question = extract_params_from_question(question, missing, intent_config)
|
405 |
+
session.record_parameter_question(params_in_question)
|
406 |
+
session.awaiting_parameters = params_in_question
|
407 |
+
|
408 |
+
log(f"🤖 Smart question generated for initial params: {params_in_question}")
|
409 |
+
return question
|
410 |
|
411 |
# All parameters collected
|
412 |
log("✅ All parameters collected after extraction")
|
413 |
return await _execute_api_call(session, intent_config)
|
414 |
|
415 |
+
async def _generate_smart_parameter_question(
|
416 |
+
session: Session,
|
417 |
+
intent_config,
|
418 |
+
missing_params: List[str],
|
419 |
+
version
|
420 |
+
) -> str:
|
421 |
+
"""LLM kullanarak doğal parametre sorusu üret"""
|
422 |
+
|
423 |
+
# Config'i al
|
424 |
+
collection_config = cfg.global_config.parameter_collection_config
|
425 |
+
|
426 |
+
# Öncelik sıralaması: önce cevaplanmayanlar
|
427 |
+
prioritized_params = []
|
428 |
+
|
429 |
+
# 1. Daha önce sorulup cevaplanmayanlar
|
430 |
+
for param in session.unanswered_parameters:
|
431 |
+
if param in missing_params:
|
432 |
+
prioritized_params.append(param)
|
433 |
+
log(f"🔝 Priority param (unanswered): {param}")
|
434 |
+
|
435 |
+
# 2. Hiç sorulmamışlar
|
436 |
+
for param in missing_params:
|
437 |
+
if param not in prioritized_params:
|
438 |
+
prioritized_params.append(param)
|
439 |
+
log(f"➕ Additional param (not asked): {param}")
|
440 |
+
|
441 |
+
# Maksimum parametre sayısını belirle
|
442 |
+
max_params = min(
|
443 |
+
len(prioritized_params),
|
444 |
+
collection_config.max_params_per_question
|
445 |
+
)
|
446 |
+
params_to_ask = prioritized_params[:max_params]
|
447 |
+
|
448 |
+
log(f"📋 Params to ask in this round: {params_to_ask}")
|
449 |
+
|
450 |
+
# Proje dilini belirle
|
451 |
+
project_language = "Turkish" # Default
|
452 |
+
if hasattr(version, 'project') and hasattr(version.project, 'default_language'):
|
453 |
+
lang_map = {
|
454 |
+
"tr": "Turkish", "en": "English", "de": "German",
|
455 |
+
"fr": "French", "es": "Spanish"
|
456 |
+
}
|
457 |
+
project_language = lang_map.get(version.project.default_language, "Turkish")
|
458 |
+
|
459 |
+
# Prompt oluştur
|
460 |
+
prompt = build_smart_parameter_question_prompt(
|
461 |
+
collection_config,
|
462 |
+
intent_config,
|
463 |
+
params_to_ask, # Sadece bu turda sorulacak parametreler
|
464 |
+
session,
|
465 |
+
project_language
|
466 |
+
)
|
467 |
+
|
468 |
+
# LLM'den soru üret
|
469 |
+
response = await spark_generate(session, prompt, "")
|
470 |
+
|
471 |
+
# Güvenlik: Eğer LLM boş veya hatalı response verirse fallback
|
472 |
+
if not response or len(response.strip()) < 10:
|
473 |
+
log("⚠️ Empty or invalid response from LLM, using fallback")
|
474 |
+
# En yüksek öncelikli parametre için fallback soru
|
475 |
+
param = params_to_ask[0]
|
476 |
+
param_config = next(p for p in intent_config.parameters if p.name == param)
|
477 |
+
|
478 |
+
# Parametrenin kaç kez sorulduğuna göre farklı fallback
|
479 |
+
ask_count = session.get_parameter_ask_count(param)
|
480 |
+
if ask_count == 0:
|
481 |
+
return f"{param_config.caption} bilgisini alabilir miyim?"
|
482 |
+
elif ask_count == 1:
|
483 |
+
return f"Lütfen {param_config.caption.lower()} bilgisini paylaşır mısınız?"
|
484 |
+
else:
|
485 |
+
return f"Devam edebilmem için {param_config.caption.lower()} bilgisine ihtiyacım var."
|
486 |
+
|
487 |
+
# Response'u temizle
|
488 |
+
clean_response = response.strip()
|
489 |
+
|
490 |
+
# Eğer response yanlışlıkla başka şeyler içeriyorsa temizle
|
491 |
+
if "#" in clean_response or "assistant:" in clean_response.lower():
|
492 |
+
# İlk satırı al
|
493 |
+
clean_response = clean_response.split('\n')[0].strip()
|
494 |
+
|
495 |
+
log(f"💬 Generated smart question: {clean_response[:100]}...")
|
496 |
+
return clean_response
|
497 |
+
|
498 |
def _get_missing_parameters(session: Session, intent_config) -> List[str]:
|
499 |
"""Get list of missing required parameters"""
|
500 |
missing = [
|