diff --git a/app/database/chroma_db.py b/app/database/chroma_db.py index 25ccc5d..ec3be0d 100644 --- a/app/database/chroma_db.py +++ b/app/database/chroma_db.py @@ -46,6 +46,17 @@ async def search_db_query(member_id, query): ) return result +# description: DB에서 검색하는 함수 - chat case 4에 사용 +# 후보들을 선정해서 gpt에게 가장 적합한 스케줄을 선택하라고 할 예정 +async def search_db_query_delete(member_id, query): + member = member_id + result = schedules.query( + query_texts=query, + n_results=10, + where={"member": {"$eq": int(member)}} + ) + return result + # description: DB에 저장하는 함수 # 스프링 백엔드로부터 chroma DB에 저장할 데이터를 받아 DB에 추가한다. async def add_db_data(schedule_data: AddScheduleDTO): diff --git a/app/prompt/openai_prompt.py b/app/prompt/openai_prompt.py index da6e4a2..34d3db7 100644 --- a/app/prompt/openai_prompt.py +++ b/app/prompt/openai_prompt.py @@ -59,11 +59,10 @@ class Template: AI Comments: """ - # case 분류 잘 안됨 - 수정 필요 case_classify_template = """ Task: User Chat Classification You are a case classifier integrated in scheduler application. - Please analyze User Chat according to the following criteria and return the appropriate case number (1, 2, 3). + Please analyze User Chat according to the following criteria and return the appropriate case number (1, 2, 3, 4). {chat_type} - Case 1: \ @@ -72,27 +71,30 @@ class Template: The question involves a request to create a new schedule for the user, including setting up events for specific dates or times. - Case 3: \ The question requires accessing or searching through the user's previous schedule information. This might involve past schedules, preferences, or other relevant details. + - Case 4: \ + The question involves a request to delete an event or events from the user's schedule, necessitating identification and removal of specific entries from the database. After analyzing the content of the question, return the most suitable case number. - YOU MUST ANSWER ONLY WITH NUMBER (1, 2, 3). OTHER WORDS ARE PROHIBITED. IT IS VERY IMPORTANT TO RETURN ONLY THE NUMBERS. NO YAPPING! + YOU MUST ANSWER ONLY WITH NUMBER (1, 2, 3, 4). OTHER WORDS ARE PROHIBITED. IT IS VERY IMPORTANT TO RETURN ONLY THE NUMBERS. NO YAPPING! + Task: Analyze the content of the question and return the most suitable case number. Example 1: User Chat: "What's the weather like tomorrow?" - Task: Analyze the content of the question and return the most suitable case number. Answer: 1 Example 2: User Chat: "I have a meeting with Dr. Lee next Monday at 10 AM." - Task: Analyze the content of the question and return the most suitable case number. Answer: 2 Example 3: User Chat: "Did I have any appointments on the last Friday?" - Task: Analyze the content of the question and return the most suitable case number. Answer: 3 - + Example 4: - Task: Analyze the content of the question and return the most suitable case number. + User Chat: "Please delete my appointment with Dr. Smith next Tuesday." + Answer: 4 + + Example 5: User Chat: {question} Answer: """ @@ -183,4 +185,64 @@ class Template: User input: {question}, RAG Retrieval: {schedule} Response: + """ + + case4_template = """ + {persona} + {chat_type} + The user's input contains information about several events they want to delete in 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 events the user wants to delete into a json format to make a delete api call in a database. Each event should be represented as a separate json object within a list. Each json object will have keys for info, location, person, start_time, end_time, and category. The category should include the name, id, and color. + - 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. + - start_time: If the user's event information includes a specific date and time, save that date and time in ISO 8601 datetime format. Dates should be organized based on the current time. Current time is {current_time}. + - end_time: If the user's event information includes an end time, save that date and time in ISO 8601 datetime format. + - category: Choose the most appropriate category for the event from the following list: {categories}. The category should include the name, id, and color. + You will be given a list of potential candidates from the database for events that the user may want to delete, and you must organize those events that the user has indicated they want to delete into a list. + Separate the outputs for tasks 1 and 2 with a special token . Even if there is only one JSON object, it must be enclosed within a list. + + Example for one-shot learning: + + User input: 개발 공부하기와 한강에서의 놀러가기 이벤트를 삭제해 주세요. + + Schedules: {'ids': [['29', '8', '7', '25', '16']], 'distances': [[0.1681539537965312, 0.17174183647570107, 0.2014914961195574, 0.2014914961195574, 0.21989337760155114]], 'embeddings': None, 'metadatas': [[{'category': '🍀미분류', 'category_id': 29, 'date': 27, 'datetime_end': '2024-05-27T16:00:00Z', 'datetime_start': '2024-05-27T15:00:00Z', 'location': '공대', 'member': 1, 'month': 5, 'person': '', 'year': 2024}, {'category': '공부', 'category_id': 8, 'date': 25, 'datetime_end': '2024-05-25T16:00:00Z', 'datetime_start': '2024-05-25T15:00:00Z', 'location': '카페', 'member': 1, 'month': 5, 'person': '민주, 채원', 'year': 2024}, {'category': '공부', 'category_id': 7, 'date': 10, 'datetime_end': '2024-05-10T00:00:00Z', 'datetime_start': '2024-05-10T00:00:00Z', 'location': '한강', 'member': 1, 'month': 5, 'person': '혜승', 'year': 2024}, {'category': '🍀미분류', 'category_id': 25, 'date': 10, 'datetime_end': '2024-05-10T00:00:00Z', 'datetime_start': '2024-05-10T00:00:00Z', 'location': '한강', 'member': 1, 'month': 5, 'person': '혜승', 'year': 2024}, {'category': '📖 공부', 'category_id': 16, 'date': 15, 'datetime_end': '2024-05-15T16:00:00Z', 'datetime_start': '2024-05-15T15:00:00Z', 'location': '', 'member': 3, 'month': 5, 'person': '', 'year': 2024}]], 'documents': [['개발 공부하기', '열심히 개발하기', '한강 놀러가기', '한강 놀러가기', '리액트 공부하기']], 'uris': None, 'data': None} + + Response to user: + Shall I add your meeting with Dr. Smith at her office on March 3rd from 10am to 11am and your dinner with John at the Italian restaurant on March 4th at 7pm to your schedule? + + [ + {{ + "info": "개발 공부하기", + "location": "공대", + "person": "", + "start_time": "2024-05-27T15:00:00Z", + "end_time": "2024-05-27T16:00:00Z", + "category": {{ + "name": "🍀미분류", + "id": 29, + "color": "" + }} + }}, + {{ + "info": "한강 놀러가기", + "location": "한강", + "person": "혜승", + "start_time": "2024-05-10T00:00:00Z", + "end_time": "2024-05-10T00:00:00Z", + "category": {{ + "name": "🍀미분류", + "id": 25, + "color": "" + }} + }} + ] + + User input: {question} + + Schedules: {schedules} + + Response to user: + """ \ No newline at end of file diff --git a/app/routers/chat.py b/app/routers/chat.py index 72d4c7d..fd39608 100644 --- a/app/routers/chat.py +++ b/app/routers/chat.py @@ -73,6 +73,11 @@ async def get_langchain_case(data: PromptRequest) -> ChatCaseResponse: response = await get_langchain_rag(data, chat_type_prompt) metadata = "null" + elif case == 4: + response_with_metadata = await delete_schedule(data, chat_type_prompt) + response = response_with_metadata.split("")[0] + metadata = response_with_metadata.split("")[1] + else: response = "좀 더 명확한 요구가 필요해요. 다시 한 번 얘기해주실 수 있나요?" case = "Exception" @@ -189,3 +194,33 @@ async def get_langchain_rag(data: PromptRequest, chat_type_prompt): response = chat_model.predict(prompt.format(persona=user_persona_prompt, output_language="Korean", question=question, schedule=schedule, current_time=current_time, chat_type=chat_type_prompt)) print(response) return response + +# case 4 : delete schedule +async def delete_schedule(data: PromptRequest, chat_type_prompt): + print("running case 4: delete schedule") + + config_normal = config['NESS_NORMAL'] + + chat_model = ChatOpenAI(temperature=config_normal['TEMPERATURE'], # 창의성 (0.0 ~ 2.0) + max_tokens=config_normal['MAX_TOKENS'], # 최대 토큰수 + model_name=config_normal['MODEL_NAME'], # 모델명 + openai_api_key=OPENAI_API_KEY # API 키 + ) + member_id = data.member_id + question = data.prompt + persona = data.persona + user_persona_prompt = persona_prompt.Template.from_persona(persona) + + # vectordb.search_db_query를 비동기적으로 호출합니다. + schedule = await vectordb.search_db_query_delete(member_id, question) # vector db에서 검색 + + # description: give NESS's ideal instruction as template + case4_template = openai_prompt.Template.case4_template + + prompt = PromptTemplate.from_template(case4_template) + seoul_timezone = pytz.timezone('Asia/Seoul') + current_time = datetime.now(seoul_timezone) + print(f'current time: {current_time}') + response = chat_model.predict(prompt.format(persona=user_persona_prompt, output_language="Korean", question=question, schedule=schedule, current_time=current_time, chat_type=chat_type_prompt)) + print(response) + return response