Skip to content

Commit

Permalink
Support parent example message generation and on-demand print.
Browse files Browse the repository at this point in the history
  • Loading branch information
yghokim committed Apr 24, 2024
1 parent 875c4cc commit 2535da4
Show file tree
Hide file tree
Showing 17 changed files with 378 additions and 178 deletions.
21 changes: 21 additions & 0 deletions data/card_translation_dictionary.csv
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
id,category,english,localized,inspected
-lUSHwHPs0,action,Drew,그렸어요,False
qn-eVMVboh,action,Met,만났어요,False
T-w6AqR2WI,action,Wrote,썼어요,False
AtpX8pHl4M,action,after school,학교 끝나고,False
Z7PKuepeFz,action,apologize,사과해요,False
9xqfhNC0iY,action,argue,논해요,False
Expand All @@ -7,11 +10,13 @@ rFP_f6kugO,action,ask,물어봐요,False
S5ybpAoUkJ,action,at lunch,점심 때,False
C981hmNoSM,action,ate,먹었어요,True
PcgcuBvG2g,action,attacked,공격했어요,False
WuY3NIdVc7,action,bored,지루해요,False
J3qH5TLi_n,action,bring,가져가요,True
QYBk1Wh9mw,action,built,지었어요,True
Bir4yNufTz,action,buy,사요,True
9ApkXNWhGk,action,chat,잡담해요,True
Z6-RUtuXwp,action,choose,선택해요,True
Y8B-lSXI_c,action,climb,올라가요,False
r35xvR3VnP,action,climbed,올라갔어요,True
f7x6vYZGZH,action,color,색칠해요,True
eSlLLkKkpf,action,comfort,편안해요,False
Expand All @@ -21,6 +26,7 @@ c9nrRATbZC,action,create,만들어요,True
3xqmUR6WRo,action,created,만들었어요,True
ZM7wuj5mEf,action,cry,울어요,False
n-Tf8mfwDt,action,dance,춤춰요,True
La-iP5y-_Y,action,describe,설명해요,False
O1Z_dMAq4X,action,did,했어요,True
qCj-Koppsp,action,discuss,토의해요,True
DWKV6w20jL,action,dislike,싫어요,True
Expand All @@ -35,6 +41,7 @@ qFMNNFSCX5,action,eat,먹어요,True
H67n9i7nOg,action,eating,먹어요,True
voBXCU3PyM,action,enjoy,즐겨요,True
bFnGzqF9Yj,action,enjoyed,즐겼어요,True
eABl8ClFz9,action,excited,신나요,False
eM3DY40FFi,action,explain,설명해요,True
lnHBypcdND,action,explore,탐험해요,False
a3KelxlGJh,action,feel,느껴요,True
Expand All @@ -48,6 +55,7 @@ dcBKqBvDJT,action,forgive,용서해요,True
FG6t-MIGTa,action,forgot,잊어버렸어요,False
-urVCbaa_L,action,go,가요,True
O6u0XAv7Vm,action,had,했어요,True
5y7kANN0Oi,action,happy,행복해요,False
IIfEakpYmR,action,have,가져요,True
SQOjY1hhrK,action,help,도와줘요,True
LHl8HjriW6,action,helped,도와주었어요,True
Expand Down Expand Up @@ -75,6 +83,7 @@ FKx7TtcCcr,action,listened,들었어요,True
siwWKm9BV8,action,look,보아요,True
QHErJpKn02,action,lost,잃어버렸어요,False
6aCL61BwoT,action,love,사랑해요,True
K6c6-F2e8w,action,made,만들었어요,False
eFapnHTSZ-,action,make,만들어요,True
CehJbDpG_e,action,meet,만나요,True
D5Pq-2-sTX,action,met,만났어요,True
Expand All @@ -100,6 +109,7 @@ RkGMYue-3T,action,sang,노래했어요,True
SvdWDngshX,action,saw,봤어요,True
CmuDetIOQk,action,say,말해요,False
0vELrai42a,action,scare,무서워요,False
WdrrGIWji7,action,scared,무서워요,False
WKb3RbrCmU,action,see,보아요,True
1N_POFEXle,action,share,함께 나누어요,True
AvJsfa28_0,action,share with,공유해요,False
Expand Down Expand Up @@ -132,12 +142,14 @@ ssoybtBkSf,action,tease,놀려요,False
SVk91PDyct,action,tell,이야기해요,True
eQZL7MHvE9,action,threw,던졌어요,True
7iZI-C4C66,action,throw,던져요,True
5M-KuPT-LW,action,tired,피곤해요,False
nLu2kQrCgk,action,try,시도해요,True
hpsevNf_wR,action,understand,이해해요,True
O68F6a00VU,action,upset,화나요,False
gtjJfAAdum,action,use,사용해요,True
3w7mNezvPA,action,visit,방문해요,True
EWpMoIaJI9,action,want,원해요,True
6luWwXtp1D,action,wanted,원했어요,False
AOIFIQ4lZv,action,was boring,지루했어요,False
OECWt0H5PH,action,was fun,즐거웠어요,False
iLeKwAROSy,action,was hard,어려웠어요,False
Expand Down Expand Up @@ -168,6 +180,7 @@ yvtJ2-R-Dd,emotion,concentrated,집중해요,True
XNDF0_wSwd,emotion,content,만족해요,True
mh-UBb8kM7,emotion,curious,궁금해요,True
wrcjq2faU1,emotion,defiant,저항해요,False
A3VbaDJAAi,emotion,delicious,맛있어요,False
91Ex6R4Ws0,emotion,difficult,어려워요,True
A3qnncaY1q,emotion,disappointed,실망했어요,True
shSNzAio8H,emotion,dislike,싫어해요,True
Expand Down Expand Up @@ -218,6 +231,7 @@ E3fWcTGiDH,emotion,sad,슬퍼요,True
VNwYfr00ga,emotion,shy,부끄러워요,True
hDt7NLgf2u,emotion,simple,간단해요,True
86201LBWef,emotion,sorry,미안해요,True
uamsWkkXKf,emotion,stressed,스트레스받아요,False
2X0JOPBeuS,emotion,surprised,놀랐어요,True
kpnbdnPwqE,emotion,tired,피곤해요,True
OCaMDYq79-,emotion,tiring,피곤해요,True
Expand Down Expand Up @@ -246,6 +260,7 @@ tEDMBJYVR8,topic,blocks,블록,True
rwvFdtPeH0,topic,book,책,True
6dkvootrxa,topic,break,휴식,True
SPH_0gDzXd,topic,break time,쉬는 시간,True
LsJBeFwtmA,topic,breaktime,쉬는 시간,False
2DNqirPt0_,topic,car,자동차,False
abPVau7epK,topic,cartoon,만화,True
ucBETq0Hhp,topic,cartoons,만화,True
Expand All @@ -255,6 +270,7 @@ lanXgQ4kc9,topic,classes,수업,True
uK0UmLUNHi,topic,classmate,친구,True
IKFZpU4ECQ,topic,classmates,동급생,True
L5n_Q6xRVF,topic,classroom,교실,True
uG4JKN6TSL,topic,classroom activity,교실 활동,False
63BIuiTJAL,topic,color,색깔,True
ZMzrVSxPQy,topic,colors,색깔,True
ZqQmq0jgXj,topic,conversation,대화,True
Expand All @@ -278,6 +294,7 @@ XYd7spA6_e,topic,food,음식,True
LOPwB6gP7U,topic,football,축구,True
bXfu9JuvvL,topic,friend,친구,True
FzmfcoAijg,topic,friends,친구,True
wYZ3hlqRaH,topic,fun,즐거움,False
kIjPY5r2mK,topic,game,놀이,True
HXUW6Aqul2,topic,games,게임,True
yzbNoUa1xE,topic,gluing,붙이기,True
Expand All @@ -294,7 +311,9 @@ yHMiG8vVr7,topic,lesson,수업,True
KqMbwnuQTE,topic,lessons,수업,True
7HjNTrqSKY,topic,listen,듣기,True
4PgUQB51Ht,topic,lunch,점심,True
_0hjBhSJwK,topic,lunchtime,점심 시간,False
Vw7mR4BXYQ,topic,math,수학,True
-Q6cagIwqO,topic,math class,수학 수업,False
vMmv5GwdN7,topic,meal,식사,True
92wk3FeCUg,topic,mom,엄마,True
0IK-m4gxPa,topic,movie,영화,True
Expand Down Expand Up @@ -345,13 +364,15 @@ ymcbqCiwH-,topic,songs,노래,False
Ddl43DNFUp,topic,sports,스포츠,True
lnpE__vNu7,topic,story,이야기,True
sX6NvIW7H0,topic,study,공부,True
6JyUR7bg_T,topic,studying,공부,False
Oct0H6k8G7,topic,subject,과목,True
rzQIL0Zu5b,topic,subjects,과목,False
3L58S0C71G,topic,swing,그네,True
rjRieEWi9P,topic,talk,이야기,True
53eLBLSTuk,topic,teacher,선생님,True
8T9a-E4F7B,topic,theater,극장,True
fwevuioC5m,topic,tickets,티켓,True
Cvu5PkRqny,topic,time,시간,False
UhU29qrEDh,topic,together,함께,True
05joagL419,topic,toy,장난감,True
pt-tfZEEK4,topic,toys,장난감,True
Expand Down
6 changes: 4 additions & 2 deletions libs/py_core/py_core.iml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$" />
<orderEntry type="jdk" jdkName="Poetry (py_core)" jdkType="Python SDK" />
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.venv" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
36 changes: 29 additions & 7 deletions libs/py_core/py_core/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
from chatlib.utils.validator import make_non_empty_string_validator

from py_core import ModeratorSession
from py_core.system.model import ChildCardRecommendationResult, ParentGuideRecommendationResult, CardInfo, DialogueRole
from py_core.system.model import ChildCardRecommendationResult, ParentGuideRecommendationResult, CardInfo, DialogueRole, \
ParentGuideType, ParentExampleMessage


async def test_session_loop(session: ModeratorSession):
Expand All @@ -15,12 +16,33 @@ async def test_session_loop(session: ModeratorSession):

if current_parent_guide_recommendation_result is not None:
print(current_parent_guide_recommendation_result.model_dump_json(indent=2))
if len(current_parent_guide_recommendation_result.messaging_guides) > 0:
while True:
enter_parent_message = "Enter parent message"
choices = []
choices.extend([f"Show example message for \"{guide.guide_localized}\"" for guide in
current_parent_guide_recommendation_result.messaging_guides])
choices.append(enter_parent_message)
selection = await questionary.select(
message="Choose an option.",
choices=choices,
default="Enter parent message"
).ask_async()

if choices.index(selection) < len(choices) - 1:
guide = current_parent_guide_recommendation_result.messaging_guides[choices.index(selection)]
example_message: ParentExampleMessage = await session.request_parent_example_message(
current_parent_guide_recommendation_result.id, guide_id=guide.id)
questionary.print(f"\"{example_message.message_localized}\" ({example_message.message})", style="bold italic fg:green")
else:
break

parent_message = await questionary.text("<Parent>: ",
default="오늘 학교에서 뭐 했니?" if current_parent_guide_recommendation_result is None and current_card_recommendation_result is None else "",
validate=make_non_empty_string_validator(
"A message should not be empty."), qmark="*").ask_async()
current_card_recommendation_result = await session.submit_parent_message(parent_message, current_parent_guide_recommendation_result)
current_card_recommendation_result = await session.submit_parent_message(parent_message,
current_parent_guide_recommendation_result)
current_interim_cards.clear()
continue

Expand All @@ -34,11 +56,11 @@ async def test_session_loop(session: ModeratorSession):
if submittable:
choices += ["[Submit]"]

selection = await questionary.select(**{
'choices': choices,
'default': '[Refresh cards]',
'message': f'Choose a word card. {"" if current_interim_cards is None or len(current_interim_cards) == 0 else ("Current selection: " + ", ".join([card.simple_str() for card in current_interim_cards]))}...'
}).ask_async()
selection = await questionary.select(
choices=choices,
default='[Refresh cards]',
message=f'Choose a word card. {"" if current_interim_cards is None or len(current_interim_cards) == 0 else ("Current selection: " + ", ".join([card.simple_str() for card in current_interim_cards]))}...'
).ask_async()

if choices.index(selection) == 0:
# refresh
Expand Down
78 changes: 78 additions & 0 deletions libs/py_core/py_core/system/guide_categories.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
from enum import StrEnum
from functools import cache
from typing import Optional

from pydantic import BaseModel


class CategoryWithDescription(BaseModel):
label: str
description: str
min_turns: Optional[int] = None # Min number of messages in dialogue to activate this category

class DialogueInspectionCategory(StrEnum):
Blame = "blame"
Correction = "correction"
Complex = "complex"
Deviation = "deviation"

def __init__(self, value):
self.description: str = {
"blame": "When the parent criticizes or negatively evaluates the child's responds, like reprimanding or scolding",
"correction": "When the parent is compulsively correcting the child's response or pointing out that the child is wrong",
"complex": "When a parent's dialogue contains more than one goal or intent",
"deviation": "When both parent and child stray from the main topic of the conversation"
}[value]

min_turns_table = {
"deviation": 5
}

self.inspection_min_turns: int | None = min_turns_table[value] if value in min_turns_table else None

@classmethod
@cache
def values_with_desc(cls) -> list[CategoryWithDescription]:
return list(map(lambda c: CategoryWithDescription(label=c.value, description=c.description, min_turns=c.inspection_min_turns), cls))


class ParentGuideCategory(StrEnum):
Intention="intention"
Specification="specification"
Choice="choice"
Clues="clues"
Coping="coping"
Stimulate="stimulate"
Share="share"
Empathize="empathize"
Encourage="encourage"
Emotion="emotion"
Extend="extend"
Terminate="terminate"

def __init__(self, value):
self.description={
"intention": "Check the intention behind the child’s response and ask back",
"specification": "Ask about \"what\" to specify the event",
"choice": "Provide choices for children to select their answers",
"clues": "Give clues that can be answered based on previously known information",
"coping": "Suggest coping strategies for specific situations to the child",
"stimulate": "Present information that contradicts what is known to stimulate the child's interest",
"share": "Share the parent's emotions and thoughts in simple language",
"empathize": "Empathize with the child's feelings",
"encourage": "Encourage the child's actions or emotions",
"emotion": "Asking about the child's feelings and emotions",
"extend": "Inducing an expansion or change of the conversation topic",
"terminate": "Inquiring about the desire to end the conversation"
}[value]

min_turns_table = {
"terminate": 5
}

self.active_min_turns: int | None = min_turns_table[value] if value in min_turns_table else None

@classmethod
@cache
def values_with_desc(cls) -> list[CategoryWithDescription]:
return list(map(lambda c: CategoryWithDescription(label=c.value, description=c.description, min_turns=c.active_min_turns), cls))
37 changes: 30 additions & 7 deletions libs/py_core/py_core/system/model.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
from enum import StrEnum
from functools import cached_property
from typing import TypeAlias, Optional

from chatlib.utils.time import get_timestamp
from nanoid import generate
from pydantic import BaseModel, ConfigDict, TypeAdapter, Field

from py_core.system.guide_categories import ParentGuideCategory


def id_generator() -> str:
return generate(size=20)
Expand All @@ -29,7 +32,7 @@ class CardCategory(StrEnum):


class CardInfo(CardIdentity):
model_config = ConfigDict(frozen=True)
model_config = ConfigDict(frozen=True, use_enum_values=True)

text: str = Field()
localized: str
Expand Down Expand Up @@ -58,29 +61,49 @@ class ParentGuideType(StrEnum):


class ParentGuideElement(BaseModel):
model_config = ConfigDict(frozen=True)
model_config = ConfigDict(frozen=True, use_enum_values=True)

category: str | None
id: str = Field(default_factory=lambda: generate(size=5))

category: ParentGuideCategory | None
guide: str
guide_localized: Optional[str] =None
guide_localized: Optional[str] = None
type: ParentGuideType = ParentGuideType.Messaging

def with_guide_localized(self, localized: str) -> 'ParentGuideElement':
return self.model_copy(update=dict(guide_localized=localized))

@classmethod
def messaging_guide(cls, category: str, guide: str) -> 'ParentGuideElement':
def messaging_guide(cls, category: ParentGuideCategory, guide: str) -> 'ParentGuideElement':
return ParentGuideElement(category=category, guide=guide, type=ParentGuideType.Messaging)

@classmethod
def feedback(cls, category: str | None, guide: str) -> 'ParentGuideElement':
def feedback(cls, category: ParentGuideCategory | None, guide: str) -> 'ParentGuideElement':
return ParentGuideElement(category=category, guide=guide, type=ParentGuideType.Feedback)


class ParentGuideRecommendationResult(ModelWithIdAndTimestamp):
model_config = ConfigDict(frozen=True)

recommendations: list[ParentGuideElement]
guides: list[ParentGuideElement]

@cached_property
def messaging_guides(self) -> list[ParentGuideElement]:
return [guide for guide in self.guides if guide.type == ParentGuideType.Messaging]

@cached_property
def feedback_guides(self) -> list[ParentGuideElement]:
return [guide for guide in self.guides if guide.type == ParentGuideType.Feedback]


class ParentExampleMessage(ModelWithIdAndTimestamp):
model_config = ConfigDict(frozen=True)

recommendation_id: str | None = None
guide_id: str | None = None

message: str
message_localized: str | None = None


class DialogueRole(StrEnum):
Expand Down
Loading

0 comments on commit 2535da4

Please sign in to comment.