flare / chat_handler.py
ciyidogan's picture
Update chat_handler.py
f24aded verified
raw
history blame
5.73 kB
"""
Flare – Chat Handler (state-machine + header session)
"""
from __future__ import annotations
import json, re
from typing import Dict, List
from fastapi import APIRouter, HTTPException, Request
from pydantic import BaseModel
from config_provider import ConfigProvider, VersionConfig, IntentConfig, ParameterConfig
from prompt_builder import (
build_detection_prompt, build_param_extract_prompt,
build_missing_param_prompt, build_api_humanize_prompt)
from validation_engine import validate
from api_executor import call_api
from session import session_store, Session
from utils import log
cfg=ConfigProvider.get()
router=APIRouter()
_cancel_words=re.compile(r"\b(vazgeç|iptal|boşver|cancel)\b",re.I)
# -------- helper ----------
def detect_intent(version: VersionConfig, text: str) -> IntentConfig | None:
for it in version.intents:
prompt=build_detection_prompt(version.general_prompt,it)
if it.name.lower() in text.lower(): # placeholder: ask_llm(prompt,text,"classification")
return it
return None
# --------- endpoints -------
class SessionStartRequest(BaseModel):
project_name:str
class SessionStartResponse(BaseModel):
session_id:str
@router.post("/start_session",response_model=SessionStartResponse)
def start_session(body:SessionStartRequest):
s=session_store.create_session(body.project_name)
return SessionStartResponse(session_id=s.session_id)
class ChatRequest(BaseModel):
user_input:str
class ChatResponse(BaseModel):
reply:str
session:Dict
@router.post("/chat",response_model=ChatResponse)
def chat(req:Request, body:ChatRequest):
sid=req.headers.get("X-Session-ID")
if not sid: raise HTTPException(400,"X-Session-ID header missing")
s=session_store.get_session(sid)
if not s: raise HTTPException(404,"Session not found")
version=_get_live_version(s.project_name)
user_text=body.user_input
s.add_turn("user",user_text)
# quick cancel
if _cancel_words.search(user_text):
s.reset_flow()
reply="Elbette, başka bir konuda nasıl yardımcı olabilirim?"
s.add_turn("assistant",reply)
return ChatResponse(reply=reply,session=s.__dict__)
# ---- idle state: intent arar
if s.state=="idle":
intent=detect_intent(version,user_text)
if not intent:
reply="(LLM-sohbet cevabı)" # burada ask_llm kullanılacak
s.add_turn("assistant",reply)
return ChatResponse(reply=reply,session=s.__dict__)
s.last_intent=intent.name
s.state="await_param"
s.awaiting_parameters=[p.name for p in intent.parameters]
s.variables={} # yeni intentte öncekileri sıfırla
# ---- await_param state
if s.state=="await_param":
intent=next(i for i in version.intents if i.name==s.last_intent)
# intent değişti mi?
new_int=detect_intent(version,user_text)
if new_int and new_int.name!=intent.name:
log("🔄 new intent overrides current flow")
s.reset_flow()
s.last_intent=new_int.name
s.state="await_param" if new_int.parameters else "call_api"
s.awaiting_parameters=[p.name for p in new_int.parameters]
intent=new_int
# param extraction
for p in intent.parameters:
if p.name in s.variables: continue
if p.name in user_text.lower(): # basit demo extraction
val=user_text
if not validate(val,p):
reply=p.invalid_prompt or f"{p.caption or p.name} değerini doğrulayamadım."
s.add_turn("assistant",reply)
return ChatResponse(reply=reply,session=s.__dict__)
s.variables[p.name]=val
s.awaiting_parameters.remove(p.name)
if s.awaiting_parameters:
s.missing_ask_count+=1
if s.missing_ask_count>=2:
s.reset_flow()
reply="Başka bir konuda yardımcı olabilir miyim?"
s.add_turn("assistant",reply)
return ChatResponse(reply=reply,session=s.__dict__)
ask=build_missing_param_prompt(s.awaiting_parameters)
s.add_turn("assistant",ask)
return ChatResponse(reply=ask,session=s.__dict__)
s.state="call_api"
# ---- call_api state
if s.state=="call_api":
intent=next(i for i in version.intents if i.name==s.last_intent)
api=cfg.get_api(intent.action)
if not api: raise HTTPException(500,"API not found")
try:
resp=call_api(api,s.variables)
except Exception as e:
log(f"❌ API error {e}")
s.reset_flow()
reply=intent.fallback_error_prompt or "Hata oluştu."
s.add_turn("assistant",reply)
return ChatResponse(reply=reply,session=s.__dict__)
s.api_raw=resp.json() # debug
s.state="humanize"
# ---- humanize
if s.state=="humanize":
intent=next(i for i in version.intents if i.name==s.last_intent)
api=cfg.get_api(intent.action)
human_prompt=build_api_humanize_prompt(
version.general_prompt,
api.response_prompt or "",
json.dumps(s.api_raw,ensure_ascii=False,indent=2)
)
reply="(LLM-humanize)" # burada ask_llm kullanılacak
s.add_turn("assistant",reply)
s.reset_flow()
return ChatResponse(reply=reply,session=s.__dict__)
def _get_live_version(project_name:str)->VersionConfig:
proj=next(p for p in cfg.projects if p.name==project_name and p.enabled)
return max((v for v in proj.versions if v.published),key=lambda x:x.id)