π Rasa Form Validation μ΄μ ν΄κ²°κΈ°
π Rasa Form Validation μ΄μ ν΄κ²°κΈ° μ΄λ² κΈμμλ Rasaλ₯Ό νμ©ν λνν μ±λ΄ κ°λ° μ€ κ²ͺμλ Form Validation μ΄μμ μ΄λ₯Ό μ΄λ»κ² ν΄κ²°νλμ§μ λν΄ μ 리νμ΅λλ€. π― λ¬Έμ μν© Rasaλ₯Ό νμ©ν΄ μ¬ν μΌμ μ μμ§νλ μ±λ΄μ κ°λ°νκ³ μμμ΅λλ€. λν νβ¦
π Rasa Form Validation μ΄μ ν΄κ²°κΈ°
μ΄λ² κΈμμλ Rasaλ₯Ό νμ©ν λνν μ±λ΄ κ°λ° μ€ κ²ͺμλ Form Validation μ΄μμ μ΄λ₯Ό μ΄λ»κ² ν΄κ²°νλμ§μ λν΄ μ 리νμ΅λλ€.
π― λ¬Έμ μν©
Rasaλ₯Ό νμ©ν΄ μ¬ν μΌμ μ μμ§νλ μ±λ΄μ κ°λ°νκ³ μμμ΅λλ€. λν νλ¦μ λ€μκ³Ό κ°μμ΅λλ€:
-
μ¬μ©μκ° "μμΈλ‘ μ¬ν κ°κ³ μΆμ΄" μ λ ₯
-
μ±λ΄μ΄ "λͺ μΌλμ 머무λ₯Ό μμ μ΄μΌ?" μ§λ¬Έ (
utter_ask_days) -
μ¬μ©μκ° "5μΌ"λ‘ μλ΅
λ¬Έμ :
-
μ¬μ©μμ μ§§μ μλ΅(μ: "5μΌ", "3")μ λν΄
daysμ¬λ‘―μ΄ μ μμ μΌλ‘ μ±μμ§μ§ μμμ΅λλ€. -
actions.pyμ μμ±νvalidate_daysν¨μκ° νΈμΆλμ§ μμμ΅λλ€.
π λ¬Έμ λΆμ κ³Όμ
Regex ν¨ν΄ μ κ²:
- κΈ°μ‘΄μ μ κ· ννμμ΄ λ¨μ μ«μ μ λ ₯μ μΈμνμ§ λͺ»νλ λ¬Έμ λ₯Ό νμΈνμ΅λλ€.
NLU λ°μ΄ν° λΆμ‘±:
- μ§§μ μλ΅μ λν νμ΅ λ°μ΄ν°κ° λΆμ‘±νμ¬ μν°ν° μΈμμ μ΄λ €μμ΄ μμμ λ°κ²¬νμ΅λλ€.
Action Server μ€μ μ€λ₯:
- 컀μ€ν
μ‘μ
μ μ€ννκΈ° μν
endpoints.ymlμ€μ μ΄ λλ½λμ΄ μμκ³ , μ΄λ‘ μΈν΄ μ‘μ μλ² νΈμΆμ΄ λμ§ μμμ΅λλ€.
Form Validation λ‘μ§ λΆμ¬:
- νΌ νμ±ν ν μ¬μ©μ μ λ ₯μ λν κ²μ¦ λ‘μ§μ΄ μ μμ μΌλ‘ λμνμ§ μλ κ²μ νμΈνμ΅λλ€.
π οΈ ν΄κ²° κ³Όμ
1λ² λ°©λ²μΌλ‘λ λ¬Έμ κ° ν΄κ²°λμ§ μμμ΅λλ€. 2λ² λ°©λ²μΌλ‘ λ°μ΄ν°λ₯Ό μΆκ°νκ³ μ¬νμ΅μ μ§ννμ λ, μ μμ μΌλ‘ λμνμ΅λλ€.
νμ§λ§ 2λ² λ°©λ²μ λ무 μ½κ³ , λ°μ΄ν°κ° λΆνμνκ² λ°©λν΄μ§λ€κ³ νλ¨νμ΅λλ€.
κ·Έλμ action μλ²κ° νΈμΆλμ§ μλ λ¬Έμ λ₯Ό ν΄κ²°(3λ²)νκ³ 4λ² λ°©λ²μΌλ‘ λ¬Έμ ν΄κ²°μ μ§ννμ΅λλ€.
1οΈβ£ endpoints.yml μ€μ μΆκ°
action_endpoint:
url: "http://localhost:5055/webhook"
-
μ‘μ μλ²κ° μ±λ΄κ³Ό ν΅μ ν μ μλλ‘ μ€μ ν©λλ€.
-
rasa run actionsλͺ λ Ήμ΄λ‘ μ‘μ μλ²λ₯Ό μ€νν©λλ€.
2οΈβ£ actions.py μμ (Validation μ‘μ
μΆκ°)
from typing import Any, Text, Dict
from rasa_sdk import Tracker, FormValidationAction
from rasa_sdk.executor import CollectingDispatcher
import re
class ValidateTravelForm(FormValidationAction):
def name(self) -> Text:
return "validate_travel_form"
async def validate_days(
self,
slot_value: Any,
dispatcher: CollectingDispatcher,
tracker: Tracker,
domain: Dict[Text, Any],
) -> Dict[Text, Any]:
match = re.search(r"\d+", str(slot_value))
if match:
return {"days": match.group(0)}
else:
dispatcher.utter_message(text="μ νν μΌμλ₯Ό μ
λ ₯ν΄ μ£ΌμΈμ. μ: 3μΌ, 5μΌ")
return {"days": None}
-
validate_daysν¨μλ μ¬μ©μ μ λ ₯μμ μ«μλ₯Ό μΆμΆνμ¬daysμ¬λ‘―μ μ μ₯ν©λλ€. -
μλͺ»λ μ λ ₯ μ μ¬μ©μμκ² μ¬μ λ ₯μ μμ²ν©λλ€.
3οΈβ£ domain.yml μ€μ 보μ
forms:
travel_form:
required_slots:
- location
- days
actions:
- validate_travel_form
slots:
days:
type: text
influence_conversation: true
mappings:
- type: from_entity
entity: days
- type: from_text
conditions:
- active_loop: travel_form
requested_slot: days
-
actionsμΉμ μvalidate_travel_formμ λ±λ‘ν©λλ€. -
from_textλ§€νμ μΆκ°νμ¬ μ§§μ μ λ ₯λ μ¬λ‘―μ μ μ₯λ μ μλλ‘ νμ΅λλ€.
4οΈβ£ λͺ¨λΈ μ¬νμ΅ λ° μ€ν
rasa train
rasa run actions
rasa shell
- λͺ¨λΈμ μ¬νμ΅νκ³ μ‘μ μλ²λ₯Ό μ€ννμ¬ λ³κ²½ μ¬νμ λ°μνμ΅λλ€.
β μ΅μ’ κ²°κ³Ό
-
μ¬μ©μμ μ§§μ μλ΅(μ: "5μΌ", "3")μλ
validate_daysν¨μκ° μ μμ μΌλ‘ νΈμΆλμμ΅λλ€. -
μ λ ₯κ°μ΄ μ νν μΆμΆλμ΄
daysμ¬λ‘―μ μ μ₯λμμ΅λλ€.
μμ λν νλ¦:
μ¬μ©μ: μμΈλ‘ μ¬ν κ°κ³ μΆμ΄
λ΄: λͺ μΌλμ 머무λ₯Ό μμ μ΄μΌ?π§
μ¬μ©μ: 5μΌ
λ΄: μ’μμπ μμΈμΌλ‘ 5μΌλμ μ¬νν μΌμ μ κ³νν΄λ³Όκ²μπ
π€ λ°°μ΄ μ
μ‘μ μλ² μ€μ μ μ€μμ±:
endpoints.ymlμ€μ μ΄ λλ½λλ©΄ 컀μ€ν μ‘μ μ΄ μ€νλμ§ μμ΅λλ€.
Validation μ‘μ μ μ νν λ§€ν:
validate_<slot_name>νμμΌλ‘ ν¨μ μ΄λ¦μ μ§μ ν΄μΌ μλ νΈμΆλ©λλ€.
μ μ°ν μ¬λ‘― λ§€ν:
from_entityμfrom_textλ₯Ό ν¨κ» μ¬μ©νλ©΄ λ€μν μ λ ₯ ν¨ν΄μ μ²λ¦¬ν μ μμ΅λλ€.
λλ²κΉ μ ν:
--debugλͺ¨λλ₯Ό νμ©νλ©΄ νΌ νμ±ν λ° μ‘μ νΈμΆ κ³Όμ μ μμΈν νμΈν μ μμ΅λλ€.
π λ§λ¬΄λ¦¬
μ΄λ² κ²½νμ ν΅ν΄ Rasaμ Form Validation λ‘μ§μ κΉμ΄ μ΄ν΄ν μ μμμ΅λλ€. μ±λ΄ κ°λ° μ€ μ μ¬ν μ΄μκ° λ°μνλ€λ©΄ μ΄ κΈμ΄ λμμ΄ λκΈ°λ₯Ό λ°λλλ€. π