Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 94 additions & 0 deletions api/simulation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
from fastapi import APIRouter, Query
from pydantic import BaseModel
from typing import List
from service.simulation import create_simulation_mode_room, get_simulation_response

router = APIRouter(tags=["Simulation Mode"])


class BasicInfo(BaseModel):
name: str
gender: str
age_group: str
hometown: str
current_residence: str
religion: str


class RelationshipValues(BaseModel):
marriage_intent: str
companion_type: str
dating_style: str
family_acceptance: str
past_experience: str


class PersonalityTraits(BaseModel):
keyword: str
conversation_style: str
personality_type: str


class HobbiesActivities(BaseModel):
indoor_hobby: str
outdoor_hobby: str
cultural_activity: str


class Lifestyle(BaseModel):
wake_up_time: str
eating_habit: str
outing_frequency: str
daily_rhythm: str


class HealthIndependence(BaseModel):
health_status: str
independent_living: str
transportation: str


class TechLiteracy(BaseModel):
smartphone_usage: str
preferred_contact_method: str


# 전체 페르소나
class SimulationPersonaDTO(BaseModel):
basic_info: BasicInfo
relationship_values: RelationshipValues
personality_traits: PersonalityTraits
hobbies_activities: HobbiesActivities
lifestyle: Lifestyle
health_independence: HealthIndependence
tech_literacy: TechLiteracy


class SimulationRoomRequest(BaseModel):
user_id: int
user_name: str
user_gender: str = "사용자 성별: 남성 or 여성"


class SimulationMessageRequest(BaseModel):
message_list: List[str]
simulation_persona: SimulationPersonaDTO
room_id: str


@router.post("/simulation/room")
async def create_simulation_room(payload: SimulationRoomRequest):

room_id = create_simulation_mode_room(
payload.user_id, payload.user_name, payload.user_gender
)

return {"room_id": room_id}


@router.post("/simulation/message")
async def get_simulation_message(payload: SimulationMessageRequest):

return get_simulation_response(
payload.message_list, payload.simulation_persona, payload.room_id
)
3 changes: 2 additions & 1 deletion main.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from fastapi import FastAPI
from api import health, icebreaking, summary, embedding
from api import health, icebreaking, simulation, summary, embedding
from service import auto

app = FastAPI(root_path="/ai")
Expand All @@ -8,3 +8,4 @@
app.include_router(icebreaking.router)
app.include_router(summary.router)
app.include_router(embedding.router)
app.include_router(simulation.router)
143 changes: 143 additions & 0 deletions service/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,146 @@
ICEBREAKER_MESSAGE_LIST_MAX_CNT = 9 # end state 결정 요소

END_TEXT = "서로 충분한 정서적 교류를 마쳤습니다. 저는 이만 나가보겠습니다."

SIMULATION_PERSONA_CATEGORIES = {
"basic_info": {
"gender": ["남성", "여성"],
"age_group": [
"40대 초반",
"40대 후반",
"50대 초반",
"50대 후반",
"60대 초반",
"60대 후반",
"70대 초반",
"70대 후반",
],
"hometown": [
"서울",
"경기",
"강원도",
"충청남도",
"충청북도",
"전라남도",
"전라북도",
"경상남도",
"경상북도",
"제주도",
],
"current_residence": ["아파트", "주택", "요양시설", "가족과 함께", "혼자 거주"],
"religion": ["무교", "기독교", "불교", "천주교", "기타"],
},
"relationship_values": {
"marriage_intent": [
"결혼까지 생각 있음",
"좋은 사람 있으면 생각 있음",
"가벼운 만남 원함",
"친구부터 천천히",
],
"companion_type": [
"같이 취미 즐길 사람",
"마음 나눌 친구",
"가치관 맞는 배우자감",
"대화 잘 통하는 사람",
],
"dating_style": [
"자주 연락하는 편",
"서로 여유를 존중",
"감정 표현 많은 편",
"천천히 가까워짐",
],
"family_acceptance": [
"상대 자녀/가족도 이해 가능",
"부담스럽지 않으면 좋음",
"자녀 간섭 없길 바람",
],
"past_experience": ["해당 없음", "이혼 경험 있음", "사별 경험 있음"],
},
"personality_traits": {
"keyword": [
"다정함",
"유쾌함",
"조용함",
"듬직함",
"배려심 많음",
"말솜씨 좋음",
"진중함",
"낙천적임",
],
"conversation_style": [
"경청 위주",
"재밌는 이야기 좋아함",
"정보 나누기 좋아함",
"가볍게 수다",
],
"personality_type": [
"낯가림 있음",
"개방적인 편",
"신중하게 접근",
"먼저 다가가는 편",
],
},
"hobbies_activities": {
"indoor_hobby": [
"책 읽기",
"TV 시청",
"요리",
"글쓰기",
"수공예",
"음악 감상",
],
"outdoor_hobby": [
"산책",
"등산",
"시장/카페 나들이",
"여행",
"사진 찍기",
"운동",
],
"cultural_activity": [
"영화 감상",
"전시회/공연",
"복지관 프로그램",
"종교 모임",
"자원봉사",
],
},
"lifestyle": {
"wake_up_time": ["새벽형", "아침형", "늦은 아침형"],
"eating_habit": [
"혼자 식사",
"식사 같이 하고 싶음",
"건강식 선호",
"소식하는 편",
],
"outing_frequency": ["매일 외출", "주 2~3회", "주말 중심", "거의 외출 안 함"],
"daily_rhythm": ["규칙적", "유동적", "낮잠 자주", "활동적"],
},
"health_independence": {
"health_status": [
"활동에 지장 없음",
"가벼운 통증/관리 중",
"도움이 조금 필요",
"의료기기 사용 중",
],
"independent_living": [
"혼자 완전 자립",
"가끔 가족 도움",
"누군가 곁에 있으면 좋겠음",
],
"transportation": ["운전 가능", "대중교통 이용", "이동 도움 필요"],
},
"tech_literacy": {
"smartphone_usage": [
"익숙함",
"카톡/영상통화 정도 가능",
"자녀 도움 받음",
"혼자 사용 어려움",
],
"preferred_contact_method": ["카카오톡", "전화 통화", "영상통화", "문자"],
},
}

LAST_NAMES = ["김", "이", "박", "최", "정", "강", "조", "윤"]
MALE_FIRST_NAMES = ["영수", "철수", "동현", "재훈", "성민", "기석", "상우", "준호"]
FEMALE_FIRST_NAMES = ["미영", "지연", "선희", "민정", "은지", "지혜", "수진", "유정"]
19 changes: 12 additions & 7 deletions service/icebreaking.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@ class IceBreakingState(str, Enum):
END = "end"


client = OpenAI(api_key=settings.OPENAI_API_KEY)


def is_end_state(icebreaker_message_list_cnt, state):
return (
icebreaker_message_list_cnt == ICEBREAKER_MESSAGE_LIST_MAX_CNT
Expand All @@ -36,6 +33,7 @@ def get_icebreaking_response(step, message_list, room_id, icebreaker_message_lis
if is_end_state(len(icebreaker_message_list), state):
state = IceBreakingState.END
text = END_TEXT
save_icebreaking_text(room_id, step, text)
return {"state": state, "text": text}

# Ice Breaker가 전송할 메세지 본문
Expand All @@ -52,7 +50,6 @@ def get_icebreaking_text(step, message_list, room_id):

user_prompt = get_icebreaking_text_user_prompt(message_list)
response = get_gpt_api_response(user_prompt)
print(response)

try:
parsed = json.loads(response)
Expand All @@ -61,17 +58,23 @@ def get_icebreaking_text(step, message_list, room_id):
print("GPT 응답 파싱 실패:", e)
text = "error"

url = f"{settings.USER_SERVER_URL}/message/iceBreakingTopic"
save_icebreaking_text(room_id, step, text)

return text


def save_icebreaking_text(room_id, step, text):
url = f"{settings.CHAT_SERVER_URL}/message/iceBreakingTopic"
try:
payload = {
"roomId": room_id,
"stepNum": step + 1,
"content": text,
}
requests.post(url, json=payload)
response = requests.post(url, json=payload)
print("RESPONSE:", response.status_code, response.text)
except Exception as e:
print("메시지 저장 실패:", e)
return text


def get_icebreaking_state(message_list, icebreaker_message_list):
Expand All @@ -93,6 +96,8 @@ def get_icebreaking_state(message_list, icebreaker_message_list):


def get_gpt_api_response(user_prompt):
client = OpenAI(api_key=settings.OPENAI_API_KEY)

response = client.chat.completions.create(
model=GPT_MODEL,
messages=[
Expand Down
Loading