class chat_history:
def __init__(self, storage_dir="chat_histories"):
self.storage_dir = storage_dir
self.user_histories = {}
os.makedirs(self.storage_dir, exist_ok=True)
def login(self, username):
self.username = username
self.user_histories[username] = self._load_history(username)
def add_message(self, role, content):
if not hasattr(self, "username"):
raise Exception("로그인이 필요합니다.")
self.user_histories[self.username].append({"role": role, "content": content})
def get_history(self):
if not hasattr(self, "username"):
raise Exception("로그인이 필요합니다.")
return self.user_histories[self.username]
def save_history(self):
if not hasattr(self, "username"):
raise Exception("로그인이 필요합니다.")
filename = os.path.join(self.storage_dir, f"{self.username}_history.json")
with open(filename, "w", encoding="utf-8") as file:
json.dump(self.user_histories[self.username], file, ensure_ascii=False, indent=4)
def _load_history(self, username):
filename = os.path.join(self.storage_dir, f"{username}_history.json")
if os.path.exists(filename):
with open(filename, "r", encoding="utf-8") as file:
return json.load(file)
return []
#---------------------------------------------------------------------
def filter_text(text):
text = re.sub(r'\s+', '', text)
text = re.sub(r'[^a-zA-Z가-힣\s]', '', text)
text = text.lower()
return text
query = "사탕 레시피와 칼로리에 대해 설명해주세요." #추후 계속 질문을 받는식으로 변경 가능
#----------------------------------------------------------------------
# webdriver_options = Options()
# webdriver_options.add_argument("--headless")
# driver_service = Service(ChromeDriverManager().install())
# webdriver_chrome = webdriver.Chrome(service=driver_service, options=webdriver_options)
korea_food = 'C:\\Users\\kevinkim\\Desktop\\recipes\\한식.json'
western_food = 'C:\\Users\\kevinkim\\Desktop\\recipes\\양식.json'
japanses_food = 'C:\\Users\\kevinkim\\Desktop\\recipes\\일식.json'
chinses_food = 'C:\\Users\\kevinkim\\Desktop\\recipes\\중식.json'
embeddings = OpenAIEmbeddings()
course = ['한식', '양식', '중식', '일식']
country_food = input('정하세요: ').replace(" ", "_").replace("&", "_")
if country_food not in course:
print('다시 선택해 주세요')
persist_directory=f"chroma_{country_food}"
if os.path.exists(persist_directory):
vector_store = Chroma(
persist_directory=persist_directory,
embedding_function=embeddings,
)
elif country_food == '한식':
with open(korea_food, 'r', encoding='utf-8') as k:
korean_food_list = json.load(k)
documents = [Document(page_content=filter_text(food_list)) for food_list in korean_food_list]
vector_store = Chroma.from_documents(
documents=documents,
embedding=embeddings,
persist_directory=persist_directory
)
vector_store.persist()
elif country_food == '양식':
with open(korea_food, 'r', encoding='utf-8') as k:
western_food_list = json.load(k)
documents = [Document(page_content=filter_text(food_list)) for food_list in western_food_list]
vector_store = Chroma.from_documents(
documents=documents,
embedding=embeddings,
persist_directory=persist_directory
)
vector_store.persist()
elif country_food == '일식':
with open(japanses_food, 'r', encoding='utf-8') as k:
japanses_food_list = json.load(k)
documents = [Document(page_content=filter_text(food_list)) for food_list in japanses_food_list]
vector_store = Chroma.from_documents(
documents=documents,
embedding=embeddings,
persist_directory=persist_directory
)
vector_store.persist()
elif country_food == '중식':
with open(korea_food, 'r', encoding='utf-8') as k:
chinses_food_list = json.load(k)
documents = [Document(page_content=filter_text(food_list)) for food_list in chinses_food_list]
vector_store = Chroma.from_documents(
documents=documents,
embedding=embeddings,
persist_directory=persist_directory
)
vector_store.persist()
callback_manager = CallbackManager([StreamingStdOutCallbackHandler()])
llm = ChatOpenAI(model = 'gpt-4o', temperature = 0, streaming=True, callbacks=[StreamingStdOutCallbackHandler()])
qa_chain = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff",
retriever=vector_store.as_retriever()
)
response = qa_chain.run(query)
print(response, end='', flush=True)
if not response or "죄송" in response:
print('외부에서 레시피를 검색하겠습니다! 조금만 기다려주세요!....')
output = subprocess.check_output(['python', 'search.py'], text=True)
print("레시피:", output.strip()) # search.py에서 출력한 값 사용
chat_history_log = []
while True:
continue_question = input('혹시 질문이나 궁금하신 점 있을까요? ')
client = OpenAI()
completion = client.chat.completions.create(
model = 'gpt-4o-mini',
messages = [
{'role': 'system', 'content': """
You are a master chef and a helpful assistant. You will receive multiple questions based on {response} but don't make any duplicated answers.
1. **Answer the Question**
- Provide a thorough and informative response to each question.
2. **Handle Exit Requests**
- If the user's message indicates a desire to leave or end the chat, respond with only the word "quit". Do not add any additional text or commentary.
example:
question no.1 = '아니야 없어', answer = 'quit'
question no.2 = '필요없을 거 같아, answer = 'quit'
question no.3 = '괜찮아', answer = 'quit'
question no.4 = '고마워', answer = 'quit'
question no.5 = '이제 괜찮아, answer = 'quit'
question no.6 = '없어', answer = 'quit'
3. **Detailed Ingredient Instructions**
- If the user asks how to make specific ***ingredients***, provide a detailed, step-by-step explanation on how to prepare them.
4. **chat history**
- If user is asking a question regarding previous chat, try to find it in {chat_history_log}
**Notes:**
- Replace `{response}` with the relevant context or topic as needed.
- Ensure all responses are clear, concise, and relevant to the user's queries.
- Maintain a professional and friendly tone throughout the conversation.
"""},
{'role' : 'user', 'content': response},
{'role' : 'user', 'content' : continue_question},
] + chat_history_log
)
questions = completion.choices[0].message.content
if questions.lower() == 'quit':
print(questions)
calories = input('칼로리를 확인 후 다음 음식을 추천 받으시겠습니까? y/n')
if calories == 'y':
subprocess.run(['python', 'calorie_helper.py'])
else:
break
break
else:
print(questions)
chat_history_log.append({'role': 'user', 'content': continue_question})
chat_history_log.append({'role': 'assistant', 'content': questions})
전체적으로 수정......
Chat_history는 나중에 DRF하시는 사람이 필요할 때를 대비해서 만든 것
하지만 문제는 바로 레시피가 없을 때를 가정했을 때, 그 값을 따로 저장해서 들고와야 하는데, 그것이 안되는 상황. 내일 아마 계속 해야할 것 같습니다.
특히 바뀐 부분은
callback_manager = CallbackManager([StreamingStdOutCallbackHandler()]) llm = ChatOpenAI(model = 'gpt-4o', temperature = 0, streaming=True, callbacks=[StreamingStdOutCallbackHandler()])
이 부분인데, 특히 callback_manager는 ai의 답변을 streaming 즉 실시간으로 보여주는 기능을 합니다.
하지만 아직까지 파일에 있는데 없다고 뜨는 문제가 발생하고 있습니다. 이 부분을 빨리 해결해야 하는데....
임베딩의 모델 변경, 텍스트 전처리, 여러가지를 넣어봤지만 그대로 나오는 것이 참...