Skip to content

Commit

Permalink
Merge pull request #49 from studio-recoding/dev
Browse files Browse the repository at this point in the history
[feat] 데모용 코드 완성
  • Loading branch information
uommou authored Apr 28, 2024
2 parents 91a1abd + 83d82c7 commit ae98855
Show file tree
Hide file tree
Showing 10 changed files with 245 additions and 43 deletions.
46 changes: 42 additions & 4 deletions app/database/chroma_db.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import os
import datetime
from dotenv import load_dotenv
from app.dto.db_dto import AddScheduleDTO, RecommendationMainRequestDTO
from app.dto.db_dto import AddScheduleDTO, RecommendationMainRequestDTO, ReportTagsRequestDTO

load_dotenv()
CHROMA_DB_IP_ADDRESS = os.getenv("CHROMA_DB_IP_ADDRESS")
Expand Down Expand Up @@ -48,28 +48,66 @@ async def search_db_query(query):
# 스프링 백엔드로부터 chroma DB에 저장할 데이터를 받아 DB에 추가한다.
async def add_db_data(schedule_data: AddScheduleDTO):
schedule_date = schedule_data.schedule_datetime_start.split("T")[0]
year = int(schedule_date.split("-")[0])
month = int(schedule_date.split("-")[1])
date = int(schedule_date.split("-")[2])
schedules.add(
documents=[schedule_data.data],
ids=[str(schedule_data.schedule_id)],
metadatas=[{"date": schedule_date, "datetime_start": schedule_data.schedule_datetime_start, "datetime_end": schedule_data.schedule_datetime_end, "member": schedule_data.member_id, "category": schedule_data.category, "location": schedule_data.location, "person": schedule_data.person}]
metadatas=[{"year": year, "month": month, "date": date, "datetime_start": schedule_data.schedule_datetime_start, "datetime_end": schedule_data.schedule_datetime_end, "member": schedule_data.member_id, "category": schedule_data.category, "location": schedule_data.location, "person": schedule_data.person}]
)
return True

# 메인페이지 한 줄 추천 기능에 사용하는 함수
# 유저의 id, 해당 날짜로 필터링
async def db_recommendation_main(user_data: RecommendationMainRequestDTO):
async def db_daily_schedule(user_data: RecommendationMainRequestDTO):
member = user_data.member_id
schedule_datetime_start = user_data.schedule_datetime_start
schedule_datetime_end = user_data.schedule_datetime_end
schedule_date = schedule_datetime_start.split("T")[0]
year = int(schedule_date.split("-")[0])
month = int(schedule_date.split("-")[1])
date = int(schedule_date.split("-")[2])
persona = user_data.user_persona or "hard working"
results = schedules.query(
query_texts=[persona],
n_results=5,
where={"$and":
[
{"member": {"$eq": int(member)}},
{"date": {"$eq": schedule_date}}
{"year": {"$eq": year}},
{"month": {"$eq": month}},
{"date": {"$eq": date}}
]
}
# where_document={"$contains":"search_string"} # optional filter
)
return results['documents']

# 태그 생성용 스케쥴 반환 - 카테고리에 따라
async def db_monthly_tag_schedule(user_data: ReportTagsRequestDTO):
member = user_data.member_id
schedule_datetime_start = user_data.schedule_datetime_start
schedule_datetime_end = user_data.schedule_datetime_end
schedule_date = schedule_datetime_start.split("T")[0]
year = int(schedule_date.split("-")[0])
month = int(schedule_date.split("-")[1])
date = int(schedule_date.split("-")[2])
persona = user_data.user_persona or "hard working"
results = schedules.query(
query_texts=[persona],
n_results=15,
where={"$and":
[
{"member": {"$eq": int(member)}},
{"year": {"$eq": year}},
{"month": {"$eq": month - 1}}
# {"$or":
# [{"$and":
# [{"month": {"$eq": month-1}}, {"date": {"$gte": 10}}]},
# {"$and":
# [{"month": {"$eq": month}}, {"date": {"$lt": 10}}]}
# ]}
]
}
# where_document={"$contains":"search_string"} # optional filter
Expand Down
14 changes: 13 additions & 1 deletion app/dto/db_dto.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class AddScheduleDTO(BaseModel):
schedule_datetime_end: str
schedule_id: int
member_id: int
category: str
category: int
location: str
person: str

Expand All @@ -17,3 +17,15 @@ class RecommendationMainRequestDTO(BaseModel):
schedule_datetime_start: str
schedule_datetime_end: str

class ReportMemoryEmojiRequestDTO(BaseModel):
member_id: int
user_persona: str
schedule_datetime_start: str
schedule_datetime_end: str

class ReportTagsRequestDTO(BaseModel):
member_id: int
user_persona: str
schedule_datetime_start: str
schedule_datetime_end: str

11 changes: 9 additions & 2 deletions app/dto/openai_dto.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from pydantic import BaseModel

from typing import List

class PromptRequest(BaseModel):
prompt: str
Expand All @@ -9,4 +9,11 @@ class ChatResponse(BaseModel):

class ChatCaseResponse(BaseModel):
ness: str
case: int
case: int

class TagDescription(BaseModel):
tag: str
desc: str

class TagsResponse(BaseModel):
tagList: List[TagDescription]
3 changes: 3 additions & 0 deletions app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@
from app.routers import recommendation
app.include_router(recommendation.router)

from app.routers import report
app.include_router(report.router)

# description: prevent CORS error
origins = [
"*",
Expand Down
13 changes: 9 additions & 4 deletions app/prompt/openai_config.ini
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
[NESS_NORMAL]
TEMPERATURE = 0
TEMPERATURE = 0.5
MAX_TOKENS = 2048
MODEL_NAME = gpt-3.5-turbo-1106
MODEL_NAME = gpt-4

[NESS_CASE]
TEMPERATURE = 0
MAX_TOKENS = 2048
MODEL_NAME = gpt-4

[NESS_RECOMMENDATION]
TEMPERATURE = 0
TEMPERATURE = 1
MAX_TOKENS = 2048
MODEL_NAME = gpt-4

[NESS_TAGS]
TEMPERATURE = 0.5
MAX_TOKENS = 2048
MODEL_NAME = gpt-3.5-turbo-1106
MODEL_NAME = gpt-4
57 changes: 31 additions & 26 deletions app/prompt/openai_prompt.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ class Template:
recommendation_template = """
You are an AI assistant designed to recommend daily activities based on a user's schedule. You will receive a day's worth of the user's schedule information. Your task is to understand that schedule and, based on it, recommend an activity for the user to perform that day. There are a few rules you must follow in your recommendations:
1. YOU MUST USE {output_language} TO RESPOND TO THE USER INPUT.
2. Ensure your recommendation is encouraging, so the user doesn't feel compelled.
2. Ensure your recommendation is encouraging and delicate, so the user doesn't feel compelled.
3. The recommendation must be concise, limited to one sentence without any additional commentary.
4. The recommendation must not exceed 20 characters in the {output_language}.
5. The final punctuation of the recommendation must be exclusively an exclamation point or a question mark.
Example:
User schedule: [Practice guitar, Calculate accuracy, Study backend development, Run AI models in the lab, Study NEST.JS]
AI Recommendation: "Your day is filled with learning and research. how about taking a short walk in between studies?"
AI Recommendation: "공부 사이에 짧게 산책 어때요?"
User schedule: {schedule}
AI Recommendation:
Expand Down Expand Up @@ -48,36 +50,39 @@ class Template:
Answer:
"""
case1_template = """
You are a friendly assistant who helps users manage their schedules. Respond kindly to the user's input. YOU MUST USE {output_language} TO RESPOND TO THE USER INPUT.
User input: {question}
"""
You are a friendly assistant, NESS. NESS helps users manage their schedules. Respond kindly to the user's input. YOU MUST USE {output_language} TO RESPOND TO THE USER INPUT.
User input: {question}
"""
case2_template = """
You are a friendly assistant who helps users manage their schedules. The user's input contains information about a new event they want to add to their schedule. You have two tasks to perform:
You are a friendly assistant who helps users manage their schedules. The user's input contains information about a new event they want to add to their schedule. You have two tasks to perform:
1. Respond kindly to the user's input. YOU MUST USE {output_language} TO RESPOND TO THE USER INPUT.
2. Organize the event the user wants to add into a json format for saving in a database. The returned json will have keys for info, location, person, and date.
- info: Summarizes what the user wants to do. This value must always be present.
- location: If the user's event information includes a place, save that place as the value.
- person: If the user's event mentions a person they want to include, save that person as the value.
- date: If the user's event information includes a specific date and time, save that date and time in datetime format.
Separate the outputs for tasks 1 and 2 with a special token <separate>.
1. Respond kindly to the user's input. YOU MUST USE {output_language} TO RESPOND TO THE USER INPUT.
2. Organize the event the user wants to add into a json format for saving in a database. The returned json will have keys for info, location, person, and date.
- info: Summarizes what the user wants to do. This value must always be present.
- location: If the user's event information includes a place, save that place as the value.
- person: If the user's event mentions a person they want to include, save that person as the value.
- date: If the user's event information includes a specific date and time, save that date and time in datetime format. Dates should be organized based on the current time at the user's location. Current time is {current_time}.
Separate the outputs for tasks 1 and 2 with a special token <separate>.
Example for one-shot learning:
Example for one-shot learning:
User input: "I have a meeting with Dr. Smith at her office on March 3rd at 10am."
User input: "I have a meeting with Dr. Smith at her office on March 3rd at 10am."
Response to user:
"I've added your meeting with Dr. Smith at her office on March 3rd at 10am to your schedule. Is there anything else you'd like to add or modify?"
<separate>
{{
"info": "meeting with Dr. Smith",
"location": "Dr. Smith's office",
"person": "Dr. Smith",
"date": "2023-03-03T10:00:00"
}}
Response to user:
"I've added your meeting with Dr. Smith at her office on March 3rd at 10am to your schedule. Is there anything else you'd like to add or modify?"
<separate>
{{
"info": "meeting with Dr. Smith",
"location": "Dr. Smith's office",
"person": "Dr. Smith",
"date": "2023-03-03T10:00:00"
}}
User input: {question}
Response to user:
"""

User input: {question}
"""
case3_template = """
You are an advanced, friendly assistant dedicated to helping users efficiently manage their schedules and navigate their day-to-day tasks with ease. Your primary role is to interact with users in a supportive and courteous manner, ensuring they feel valued and assisted at every step.
Expand Down
36 changes: 36 additions & 0 deletions app/prompt/report_prompt.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
class Template:
memory_emoji_template = """
You are an AI assistant designed to return an emoji that represents a user's day based on their schedule. You will receive information about the user's daily schedule. Your task is to analyze this schedule and select a single emoji that encapsulates the day's activities. There are a few guidelines you must adhere to in your selection:
YOU MUST RESPOND WITH A SINGLE EMOJI without any additional commentary.
The emoji must reflect the overall theme or mood of the day's activities.
Your recommendation should be intuitive, making it easy for the user to see the connection between the schedule and the chosen emoji.
Example:
User schedule: [Practice guitar, Calculate accuracy, Study backend development, Run AI models in the lab, Study NEST.JS]
AI Recommendation: 🎓
User schedule: [Morning jog, Office work, Lunch with friends, Evening yoga]
AI Recommendation: ☀️
User schedule: {schedule}
AI Recommendation:
"""

report_tags_template = """
You are an AI assistant tasked with analyzing a user's schedule over the span of a month. From this detailed schedule, you will distill three keywords that best encapsulate the user's activities, interests, or achievements throughout the month. Additionally, you will provide a brief explanation for each keyword to illustrate why it was chosen, making the output more informative and engaging. Here are the rules for your analysis:
YOU MUST USE {output_language} TO RESPOND TO THE INPUT.
YOU MUST PROVIDE THREE KEYWORDS in your response, each accompanied by a concise explanation.
The keywords must capture the essence of the user's monthly activities, highlighting aspects that are both rewarding and enjoyable.
Your selections should be creative and personalized, aiming to reflect the user's unique experiences over the month.
Each explanation of the keywords must not exceed 50 characters in the {output_language}.
Example:
User's monthly schedule: [Attended a programming bootcamp, Completed a marathon, Read three novels, Volunteered at the local food bank, Started a blog about sustainability]
AI Recommendation: "공부 매니아: 이번 달엔 공부를 정말 많이 하셨군요!, 환경 지킴이: 지속 가능한 생활에 대한 열정이 느껴져요., 자기 계발 홀릭: 성장을 위해 노력하는 모습이 멋져요."
User's monthly schedule: [Took photography classes, Explored three new hiking trails, Organized a neighborhood clean-up, Experimented with vegan recipes]
AI Recommendation: "모험가: 새로운 활동에 많이 도전하셨네요!, 미식가: 레시피 실험을 했다니 멋져요., 도파민 중독자: 즐거운 일을 많이 만드시네요!"
User's monthly schedule: {schedule}
AI Recommendation:
"""
14 changes: 9 additions & 5 deletions app/routers/chat.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from fastapi import APIRouter, HTTPException, status
from langchain_community.chat_models import ChatOpenAI
from langchain_core.prompts import PromptTemplate
from datetime import datetime

from app.dto.openai_dto import PromptRequest, ChatResponse, ChatCaseResponse
from app.prompt import openai_prompt
Expand All @@ -30,7 +31,7 @@
async def get_langchain_case(data: PromptRequest) -> ChatCaseResponse:
# description: use langchain

config_chat = config['NESS_CHAT']
config_chat = config['NESS_CASE']

chat_model = ChatOpenAI(temperature=config_chat['TEMPERATURE'], # 창의성 (0.0 ~ 2.0)
max_tokens=config_chat['MAX_TOKENS'], # 최대 토큰수
Expand All @@ -57,9 +58,11 @@ async def get_langchain_case(data: PromptRequest) -> ChatCaseResponse:
response = await get_langchain_rag(data)

else:
print("wrong case classification")
# 적절한 HTTP 상태 코드와 함께 오류 메시지를 반환하거나, 다른 처리를 할 수 있습니다.
raise HTTPException(status_code=400, detail="Wrong case classification")
# print("wrong case classification")
# # 적절한 HTTP 상태 코드와 함께 오류 메시지를 반환하거나, 다른 처리를 할 수 있습니다.
# raise HTTPException(status_code=400, detail="Wrong case classification")
response = "좀 더 명확한 요구가 필요해요. 다시 한 번 얘기해주실 수 있나요?"
case = "Exception"

return ChatCaseResponse(ness=response, case=case)

Expand Down Expand Up @@ -104,7 +107,8 @@ async def get_langchain_schedule(data: PromptRequest):
case2_template = openai_prompt.Template.case2_template

prompt = PromptTemplate.from_template(case2_template)
response = chat_model.predict(prompt.format(output_language="Korean", question=question))
current_time = datetime.now()
response = chat_model.predict(prompt.format(output_language="Korean", question=question, current_time=current_time))
print(response)
return response

Expand Down
2 changes: 1 addition & 1 deletion app/routers/recommendation.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ async def get_recommendation(user_data: RecommendationMainRequestDTO) -> ChatRes
)

# vectordb에서 유저의 정보를 가져온다.
schedule = await vectordb.db_recommendation_main(user_data)
schedule = await vectordb.db_daily_schedule(user_data)

print(schedule)

Expand Down
Loading

0 comments on commit ae98855

Please sign in to comment.