From 63a2ebe21fee9d705bed8696dbf34f27d1c3dad0 Mon Sep 17 00:00:00 2001 From: Lee-EunSeok Date: Thu, 12 Jun 2025 22:04:49 +0900 Subject: [PATCH] return --- service/auto.py | 99 +++++++++++++++------------------------------- service/summary.py | 17 +++----- 2 files changed, 37 insertions(+), 79 deletions(-) diff --git a/service/auto.py b/service/auto.py index 4889cdb..111ce4b 100644 --- a/service/auto.py +++ b/service/auto.py @@ -63,52 +63,33 @@ 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} - - merged_personas = [] - for person in parsed_summary.persona: - pid = person.id - new_prefs = prefs_map.get(pid, []) - 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, - "summaries": summaries, + "persona": [persona.model_dump() for persona in parsed_summary.persona], + "summaries": payload, } url = f"{settings.CHAT_SERVER_URL}/summary/update" resp = requests.post(url, json=body, timeout=5) resp.raise_for_status() - print(f"[{room_id}] 요약 업데이트 성공") + print(f"[{room_id}] 요약 업데이트 성공", [{resp}], resp.status_code) 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)을 5개의 주제에 대화 내역에서 추출하여 각각 요약해야한다. - 두 번째 역할은 두 사람이 오늘 나눈 대화 내역와 요약의 hobbies_and_interests 주제에서 각 사용자가 선호하는 것을 1~3가지 정도를 키워드 추출하여 각 사용자의 persona의 이미 있는 내용을 preferences 리스트 맨 뒤에 추가만 해야한다. - 5개의 주제는 다음과 같다. - # 1. health_status -> 어르신 건강 상의 이유로 스마트폰 조작 시 어려움을 파악: ex) “눈이 침침”, “스마트폰 터치가 어려움” - # 2. hobbies_and_interests -> 취미, 흥미를 파악: ex) “노래 듣기”, “바둑 게임” - # 3. relationship_context -> 청년과 어르신 관계를 파악: ex) “아직 어색”, “친밀”, - # 4. digital_skill_focus -> 당일 배우거나 다룬 기능이나 앱 요약: ex) “카톡 사진 묶어서 전송”, “네이버 지도 경로 저장” - # 5. learning_challenge -> 여전히 어르신이 어려워하거나 막힌 지점: ex) “카드 등록 실패 오류 940”, “앱 업데이트 용량 부족” - + 두 사람이 오늘 나눈 대화 내역(today_messages)을 6개의 주제에 대화 내역에서 추출하여 각각 요약해야한다. + 6개의 주제는 다음과 같다. + 1. health_status + 2. hobbies_and_interests + 3. emotional_and_mental_state + 4. relationship_context + 5. social_activitie + 6. intimacy ### 요약 {response.summaries} @@ -116,47 +97,24 @@ def summary_prompt(response) -> list[dict]: ### 오늘 나눈 대화 내역 {response.today_messages} - ### 선호도 - {response.persona} - ### TASK - 1) 오늘 나눈 대화 내역을 읽고, 5개의 주제에 대한 내용을 추출하여 한 문장으로 요약한다. + 1) 오늘 나눈 대화 내역을 읽고, 6개의 주제에 대한 내용을 추출하여 한 문장으로 요약한다. 2) 만일 일부 주제에 대한 내용을 추출할 내용을 없을 시에는 "주제에 대한 대화 없음"이라고 저장한다. 3) 반드시 기존에 있는 요약 내용에 추가하는 것이다. 대답할 때 오늘 나눈 대화 내역에서 각 주제에 추출한 내용을 이미 있는 내용에 day리스트 맨 뒤에 추가만 할 것. 4) {datetime.now()}가 현재 시각임으로 last_update에 반영할 것. 5) 금기) 반드시 요약 JSON 구조를 지키며 수정하지 말아라. 6) 금기) 반드시 기존의 요약에 day 리스트 맨 뒤에 요약 내용을 추가할 것. 6-1) 예시) 추가할 때의 형태는 ★{datetime.today().strftime("%m-%d")}: "요약 내용" 형태로 추가할 것. - 7) 오늘 나눈 대화 내역와 요약의 hobbies_and_interests 주제에서 각 사용자가 선호하는 것을 1~3가지 정도를 추출하여 각 사용자의 persona의 이미 있는 내용을 preferences 리스트 맨 뒤에 추가만 할 것. - 7-1) 단 선호도를 판단할 만한 키워드를 추출할 것이 없다면, 아무것도 추가하지 않는다. 중복되는 내용이 이미 preferences에 있다면 추가하지 않는다. - - - ### OUTPUT FORMAT - 반드시 다음 JSON만 반환하세요: - {{ - "summaries": {{ # 기존 summaries 전체 - … - }}, - "persona": [ - {{ - "id": {response.persona[0].id}, - "preferences": [/* 청년 선호 키워드 리스트 */] - }}, - {{ - "id": {response.persona[1].id}, - "preferences": [/* 어르신 선호 키워드 리스트 */] - }} - ] - }} """ - print(main_prompt_content) + return [ { "role": "system", - "content": "너는 청년과 어르신이 있는 채팅방을 세밀하게 분석하여 요약하는 봇이자 두 사용자의 선호도를 찾아내는 봇이다.", + "content": "너는 한국어 어르신 대화 코치이다. 두 어르신의 건강을 고려해 한 문장으로 답한다.", }, {"role": "user", "content": main_prompt_content}, + # {"role": "user", "content": few_shot_example}, ] @@ -165,15 +123,16 @@ def weekly_summary_scheduler() -> None: for room in rooms: room_id = room["_id"] - resp = get_summary(room_id) + resp = get_summary(room_id) # Response summary_obj: AssistantSummary = AssistantSummary.model_validate(resp.json()) topics = [ "health_status", "hobbies_and_interests", + "emotional_and_mental_state", "relationship_context", - "digital_skill_focus", - "learning_challenge", + "social_activities", + "intimacy", ] today = datetime.now() @@ -181,10 +140,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 리스트에 쌓인 항목을 읽고, -각 주제에 대해 한 문장으로 요약해라 +각 주제에 대해 한 문장으로 요약해라라 - 입력 데이터(딕셔너리): {{ """ @@ -246,9 +205,10 @@ def monthly_summary_scheduler() -> None: topics = [ "health_status", "hobbies_and_interests", + "emotional_and_mental_state", "relationship_context", - "digital_skill_focus", - "learning_challenge", + "social_activities", + "intimacy", ] for room in rooms: @@ -297,6 +257,7 @@ 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, @@ -314,9 +275,10 @@ def yearly_summary_scheduler() -> None: topics = [ "health_status", "hobbies_and_interests", + "emotional_and_mental_state", "relationship_context", - "digital_skill_focus", - "learning_challenge", + "social_activities", + "intimacy", ] for room in rooms: @@ -352,6 +314,7 @@ 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() @@ -364,7 +327,7 @@ def yearly_summary_scheduler() -> None: ( "daily_summary_job", fetch_roomList, - dict(hour=2, minute=00, second=00), + dict(hour=2, minute=0, second=0), ), # 매일 02:00:00 ( "weekly_summary_job", @@ -392,4 +355,4 @@ def yearly_summary_scheduler() -> None: replace_existing=True, ) -scheduler.start() +scheduler.start() \ No newline at end of file diff --git a/service/summary.py b/service/summary.py index fb56ea8..dba97b9 100644 --- a/service/summary.py +++ b/service/summary.py @@ -16,7 +16,7 @@ class Persona(BaseModel): name: str relationship: str | None = "" speech_style: str | None = "" - preferences: List[str] + preferences: str | None = "" critical_flags: List[str] @@ -30,10 +30,11 @@ class _SummaryPeriod(BaseModel): class Summaries(BaseModel): health_status: _SummaryPeriod + emotional_and_mental_state: _SummaryPeriod hobbies_and_interests: _SummaryPeriod relationship_context: _SummaryPeriod - digital_skill_focus: _SummaryPeriod - learning_challenge: _SummaryPeriod + social_activities: _SummaryPeriod + intimacy: _SummaryPeriod class Sender(BaseModel): @@ -77,23 +78,17 @@ 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} @@ -107,7 +102,7 @@ def user_prompt(response, userId) -> list[dict]: ### TASK 1) 상황 파악 → 사고 단계 기록 - 2) 반드시 요약에서 2개의 주제 "digital_skill_focus"와 "learning_challenge"를 먼저 파악하라. + 2) 반드시 요약에서 2개의 주제 "hobbies_and_interests"와 "relationship_context"를 먼저 파악하라. 3) 최근 대화에 가장 많은 비중을 두어 {speaker} 입장에서 마지막 발화에 자연스럽게 이어질 **한 문장**을 작성해야 한다. 3) 나머지 요약 내용도 최근 대화에 필요한 내용이라면 참고하여 최고의 한 문장으로 작성해라. 4) 문장을 총 7개 제안 → 셀프체크 후 3개 → 최종 1개 제안 @@ -118,7 +113,7 @@ def user_prompt(response, userId) -> list[dict]: return [ { "role": "system", - "content": "너는 청년과 노인이 멘토 멘티가 되어서 채팅방에서 대화를 나누도록 도움을 주는 코치이다. 원활한 소통을 위해 대화를 이어나갈 최고의 한 문장으로 답한다.", + "content": "너는 한국어 어르신 대화 코치이다. 두 어르신의 건강을 고려해 한 문장으로 답한다.", }, {"role": "user", "content": user_content}, ]