diff --git a/service/auto.py b/service/auto.py index f0142d9..4889cdb 100644 --- a/service/auto.py +++ b/service/auto.py @@ -62,10 +62,10 @@ def post_summary_update( except json.JSONDecodeError as e: raise ValueError(f"요약 JSON 파싱 실패: {e}") - + summaries = payload["summaries"] new_prefs_list = payload["persona"] - prefs_map = { p["id"]: p.get("preferences", []) for p in new_prefs_list } + prefs_map = {p["id"]: p.get("preferences", []) for p in new_prefs_list} merged_personas = [] for person in parsed_summary.persona: @@ -74,7 +74,7 @@ def post_summary_update( combined = list(dict.fromkeys(person.preferences + new_prefs)) person.preferences = combined merged_personas.append(person.model_dump()) - + body = { "roomId": parsed_summary.roomId, "persona": merged_personas, @@ -91,18 +91,24 @@ def post_summary_update( def summary_prompt(response) -> list[dict]: # open ai에 질의 메시지 + # 1. health_status -> 노인이 건강 상의 이유로 스마트폰 조작 시 어려움을 파악 + # 2. hobbies_and_interests -> 취미, 흥미를 파악 + # 3. relationship_context -> 청년과 어르신신 관계를 파악 + # 4. digital_skill_focus -> 당일 배우거나 다룬 기능이나 앱 요약: ex) “카톡 사진 묶어서 전송”, “네이버 지도 경로 저장” + # 5. learning_challenge -> 여전히 어르신이 어려워하거나 막힌 지점: ex) “카드 등록 실패 오류 940”, “앱 업데이트 용량 부족” + main_prompt_content = f""" ### ROLE 너는 오늘 채팅방의 내용을 매우 심도있게 분석하여 요약하는 것이 역할이다. - 첫 번째 역할은 두 사람이 오늘 나눈 대화 내역(today_messages)을 6개의 주제에 대화 내역에서 추출하여 각각 요약해야한다. + 첫 번째 역할은 두 사람이 오늘 나눈 대화 내역(today_messages)을 5개의 주제에 대화 내역에서 추출하여 각각 요약해야한다. 두 번째 역할은 두 사람이 오늘 나눈 대화 내역와 요약의 hobbies_and_interests 주제에서 각 사용자가 선호하는 것을 1~3가지 정도를 키워드 추출하여 각 사용자의 persona의 이미 있는 내용을 preferences 리스트 맨 뒤에 추가만 해야한다. - 6개의 주제는 다음과 같다. - 1. health_status - 2. hobbies_and_interests - 3. emotional_and_mental_state - 4. relationship_context - 5. social_activitie - 6. intimacy + 5개의 주제는 다음과 같다. + # 1. health_status -> 어르신 건강 상의 이유로 스마트폰 조작 시 어려움을 파악: ex) “눈이 침침”, “스마트폰 터치가 어려움” + # 2. hobbies_and_interests -> 취미, 흥미를 파악: ex) “노래 듣기”, “바둑 게임” + # 3. relationship_context -> 청년과 어르신 관계를 파악: ex) “아직 어색”, “친밀”, + # 4. digital_skill_focus -> 당일 배우거나 다룬 기능이나 앱 요약: ex) “카톡 사진 묶어서 전송”, “네이버 지도 경로 저장” + # 5. learning_challenge -> 여전히 어르신이 어려워하거나 막힌 지점: ex) “카드 등록 실패 오류 940”, “앱 업데이트 용량 부족” + ### 요약 {response.summaries} @@ -115,7 +121,7 @@ def summary_prompt(response) -> list[dict]: ### TASK - 1) 오늘 나눈 대화 내역을 읽고, 6개의 주제에 대한 내용을 추출하여 한 문장으로 요약한다. + 1) 오늘 나눈 대화 내역을 읽고, 5개의 주제에 대한 내용을 추출하여 한 문장으로 요약한다. 2) 만일 일부 주제에 대한 내용을 추출할 내용을 없을 시에는 "주제에 대한 대화 없음"이라고 저장한다. 3) 반드시 기존에 있는 요약 내용에 추가하는 것이다. 대답할 때 오늘 나눈 대화 내역에서 각 주제에 추출한 내용을 이미 있는 내용에 day리스트 맨 뒤에 추가만 할 것. 4) {datetime.now()}가 현재 시각임으로 last_update에 반영할 것. @@ -135,11 +141,11 @@ def summary_prompt(response) -> list[dict]: "persona": [ {{ "id": {response.persona[0].id}, - "preferences": [/* A 어르신 선호 키워드 리스트 */] + "preferences": [/* 청년 선호 키워드 리스트 */] }}, {{ "id": {response.persona[1].id}, - "preferences": [/* B 어르신 선호 키워드 리스트 */] + "preferences": [/* 어르신 선호 키워드 리스트 */] }} ] }} @@ -148,7 +154,7 @@ def summary_prompt(response) -> list[dict]: return [ { "role": "system", - "content": "너는 어르신 채팅방을 세밀하게 분석하여 요약하는 봇이자 사용자의 선호도를 찾아내는 봇이다.", + "content": "너는 청년과 어르신이 있는 채팅방을 세밀하게 분석하여 요약하는 봇이자 두 사용자의 선호도를 찾아내는 봇이다.", }, {"role": "user", "content": main_prompt_content}, ] @@ -159,16 +165,15 @@ def weekly_summary_scheduler() -> None: for room in rooms: room_id = room["_id"] - resp = get_summary(room_id) # Response + resp = get_summary(room_id) summary_obj: AssistantSummary = AssistantSummary.model_validate(resp.json()) topics = [ "health_status", "hobbies_and_interests", - "emotional_and_mental_state", "relationship_context", - "social_activities", - "intimacy", + "digital_skill_focus", + "learning_challenge", ] today = datetime.now() @@ -176,10 +181,10 @@ def weekly_summary_scheduler() -> None: week_end = today.strftime("%m-%d") week_of_month = (today.day - 1) // 7 + 1 week_label = f"{today.month}월 {week_of_month}주차" - # 4) GPT 프롬프트 구성 + prompt = f""" 지난 일주일({week_start} ~ {week_end}) 각 주제별로 day 리스트에 쌓인 항목을 읽고, -각 주제에 대해 한 문장으로 요약해라라 +각 주제에 대해 한 문장으로 요약해라 - 입력 데이터(딕셔너리): {{ """ @@ -241,10 +246,9 @@ def monthly_summary_scheduler() -> None: topics = [ "health_status", "hobbies_and_interests", - "emotional_and_mental_state", "relationship_context", - "social_activities", - "intimacy", + "digital_skill_focus", + "learning_challenge", ] for room in rooms: @@ -293,7 +297,6 @@ def get_reply(messages) -> str: OpenAI.api_key = os.getenv("OPENAI_API_KEY") client = OpenAI(api_key=OpenAI.api_key) - # gpt에 요청 gpt_response = client.chat.completions.create( model="gpt-4o", messages=messages, @@ -311,10 +314,9 @@ def yearly_summary_scheduler() -> None: topics = [ "health_status", "hobbies_and_interests", - "emotional_and_mental_state", "relationship_context", - "social_activities", - "intimacy", + "digital_skill_focus", + "learning_challenge", ] for room in rooms: @@ -350,7 +352,6 @@ def yearly_summary_scheduler() -> None: "summaries": summaries_json, } - # 6) chat 서버에 업데이트 requests.post( f"{settings.CHAT_SERVER_URL}/summary/update", json=body, timeout=5 ).raise_for_status() @@ -363,9 +364,8 @@ def yearly_summary_scheduler() -> None: ( "daily_summary_job", fetch_roomList, - dict(hour=18, minute=45, second=00), + dict(hour=2, minute=00, second=00), ), # 매일 02:00:00 - ( "weekly_summary_job", weekly_summary_scheduler, diff --git a/service/summary.py b/service/summary.py index 86eac50..fb56ea8 100644 --- a/service/summary.py +++ b/service/summary.py @@ -30,11 +30,10 @@ class _SummaryPeriod(BaseModel): class Summaries(BaseModel): health_status: _SummaryPeriod - emotional_and_mental_state: _SummaryPeriod hobbies_and_interests: _SummaryPeriod relationship_context: _SummaryPeriod - social_activities: _SummaryPeriod - intimacy: _SummaryPeriod + digital_skill_focus: _SummaryPeriod + learning_challenge: _SummaryPeriod class Sender(BaseModel): @@ -78,17 +77,23 @@ def user_prompt(response, userId) -> list[dict]: # 현재 대화추천을 요청한 사용자가 누구인지 판단하는 로직 id = userId + prompt_pick = "너는 청년의 입장에서 어르신의 스마트폰 기기 사용법을 알려주기 위해 최선을 다하도록 성심 성의껏 답변을 해야한다." if userId == response.persona[0].id: speaker = response.persona[0].name speaker_speech_style = response.persona[0].speech_style + prompt_pick = "너는 청년의 입장에서 어르신의 스마트폰 기기 사용법을 알려주기 위해 어르신이 무엇을 모르는지 최근 대화 내용을 보고 파악하여 최선을 다하여 성심 성의껏 답변을 해야한다." else: speaker = response.persona[1].name speaker_speech_style = response.persona[1].speech_style + prompt_pick = "너는 어르신의 입장에서 청년에게 스마트폰 기기 사용법을 어떻게 물어보면 쉽게 물어볼지 최근 대화를 보고 파악하여 최선을 다하여 성심 성의껏 생각하고 질문이나 답변을 해야한다." # open ai에 질의 메시지 user_content = f""" ### ROLE 이번 문장은 {speaker}의 말투({speaker_speech_style})로 작성한다. + 특별한 말투가 없다면 존맛말을 사용하여 작성하라. + {prompt_pick} + ### CRITICAL_FLAGS {response.persona[0].name}의 {response.persona[0].critical_flags} @@ -102,21 +107,23 @@ def user_prompt(response, userId) -> list[dict]: ### TASK 1) 상황 파악 → 사고 단계 기록 - 2) {speaker} 입장에서 한 문장 작성 - 3) JSON 만 출력 + 2) 반드시 요약에서 2개의 주제 "digital_skill_focus"와 "learning_challenge"를 먼저 파악하라. + 3) 최근 대화에 가장 많은 비중을 두어 {speaker} 입장에서 마지막 발화에 자연스럽게 이어질 **한 문장**을 작성해야 한다. + 3) 나머지 요약 내용도 최근 대화에 필요한 내용이라면 참고하여 최고의 한 문장으로 작성해라. + 4) 문장을 총 7개 제안 → 셀프체크 후 3개 → 최종 1개 제안 + 5) JSON 만 출력 json {{ "reply": "..." }} """ return [ { "role": "system", - "content": "너는 한국어 어르신 대화 코치이다. 두 어르신의 건강을 고려해 한 문장으로 답한다.", + "content": "너는 청년과 노인이 멘토 멘티가 되어서 채팅방에서 대화를 나누도록 도움을 주는 코치이다. 원활한 소통을 위해 대화를 이어나갈 최고의 한 문장으로 답한다.", }, {"role": "user", "content": user_content}, ] - ### OpenAI 호출 def get_reply(response, userId) -> str: