AI 부트캠프/챕터3(11.08~12.04)

TIL 49

musukie 2024. 11. 26. 15:44

챗봇과의 대화 내용을 txt 파일로 저장하고, 그 txt 파일을 다음 대화에 불러올 수 있게 해야 한다.

1. 폴더 생성 및 파일 경로 설정

import os
from datetime import datetime

# 폴더 이름
folder_name = "previous_conversation"

# 폴더가 없으면 생성
if not os.path.exists(folder_name):
    os.makedirs(folder_name)

# 파일 이름에 타임스탬프 추가
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")  # "20241126_153045" 형식
file_name = f"conversation_log_{timestamp}.txt"
file_path = os.path.join(folder_name, file_name)

 

파일을 저장할 폴더를 지정하고, 폴더가 없으면 자동으로 생성하려면 os 모듈의 os.makedirs()를 사용할 수 있다. 폴더 경로를 설정해야 한다. folder_name = "previous_conversation"와 같이 폴더 이름 지정하고, file_path = os.path.join(folder_name, file_name)로 폴더와 파일 이름을 결합해 경로를 설정했다. 그리고 os.makedirs(folder_name)를 사용해 폴더를 생성했다. 또, if not os.path.exists(folder_name) 조건문으로 폴더가 없는 경우에만 생성하도록 설정했다. 모든 파일 작업(읽기 및 쓰기)에 file_path를 사용하도록 파일 경로를 적용했다.

 

이를 통해 매번 대화가 끝날 때 conversation.txt에 새로운 대화 내용(퀴즈, 사용자 답변, 피드백)을 추가로 저장한다. 따라서 파일에는 처음부터 모든 대화 기록이 누적된다. 프로그램 실행 시 conversation_log.txt 파일의 내용을 전부 읽어 previous_conversation에 저장한다. 이후 새로운 대화를 시작할 때 이 내용을 포함하여 맥락을 유지한다.

 

대화를 종료하고 새로운 대화를 시작할 때마다 새로운 파일을 생성하기 위해서 타임스탬프를 사용했다. 파일 이름에 타임스탬프(시간 정보)를 추가하여 대화가 종료될 때마다 고유한 이름의 파일이 생성되게 했다. 파일 이름에 타임스탬프를 포함하면 동일한 이름이 반복되지 않으므로, 새로운 대화가 시작될 때마다 고유한 파일이 생성되게 된다.

 

2. 이전 대화 불러오기

if os.path.exists(file_path):
    with open(file_path, "r", encoding="utf-8") as f:
        previous_conversation = f.read()  # 파일에서 이전 대화 읽어오기
else:
    previous_conversation = ""  # 파일이 없으면 빈 문자열로 시작

 

os.path.exists()로 파일이 존재하는지 확인한다.

 

파일이 존재하면 open(file_path, "r", encoding="utf-8")로 파일을 읽기 모드로 열어서 이전 대화 내용을 가져온다. f.read로 파일의 모든 내용을 문자열로 읽어온다. 이 문자열을 previous_conversation 변수에 저장하여 이후 피드백 생성 시 활용할 수 있다.

 

파일이 없으면 previous_conversation을 빈 문자열로 초기화하여 문제 없이 대화를 진행하게 했다.

 

 

 

 

3. 대화 내용 저장

with open(file_path, "a", encoding="utf-8") as f:  # 기존 대화에 추가로 저장
    f.write(f"Quiz: {quiz}\n")
    f.write(f"User Answer: {user_answer}\n")
    f.write(f"Feedback: {feedback}\n")
    f.write("-" * 50 + "\n")

대화를 저장하려면 open() 함수로 파일을 열고 대화 내용을 추가로 작성해야 한다. with 구문을 사용해 구현할 수 있다.

 

open(file_path, "a", encoding="utf-8")를 사용해 파일을 '추가모드("a")'로 열어서 파일에 대화 내용을 추가로 저장한다. 이를 통해 기존 파일 내용을 유지하면서 새로운 내용을 추가할 수 있다.

 

 

퀴즈(quiz), 사용자 답변(user_answer), AI 피드백(feedback)을 파일에 저장하고, 구분선("-" * 50)을 추가해 저장된 대화 내용이 읽기 쉽도록 구성했다.


트러블슈팅

문제 1

feedback_prompt에 불러온 txt 파일을 적용하는 과정에서 오류가 발생했다. 

   

오류

KeyError: 'Input to ChatPromptTemplate is missing variables {"\'refusal\'", "\'input_tokens\'", "\'token_usage\'"}.  Expected: ["\'input_tokens\'", "\'refusal\'", "\'token_usage\'"] Received: [\'quiz\', \'answer\']\nNote: if you intended {\'refusal\'} to be part of the string and not a variable, please escape it with double curly braces like: \'{{\'refusal\'}}\'.\nFor troubleshooting, visit: https://python.langchain.com/docs/troubleshooting/errors/INVALID_PROMPT_INPUT 

   

ChatPromptTemplate이 기대하는 입력 변수와 실제로 제공된 입력 간의 불일치때문에 발생한 오류라고 한다. 그래서 input_data에 필요한 변수들을 넣어주고, 피드백 체인을 호출할 때 input_data를 넣어주었다.

# 필요한 변수를 기본값으로 추가
    input_data = {
        "quiz": quiz,
        "answer": user_answer,
        "previous_conversation": previous_conversation,
        "refusal": "",  # 기본값 설정
    }

    # 피드백 체인 호출
    feedback_chain = feedback_prompt | llm
    feedback = feedback_chain.invoke(input_data)

오류 코드에서는 'input_tokens', 'token_usage', 'refusal'가 필요하다고 나와있었다. 'input_tokens'와 'token_usage'는 추가하지 않아도 코드가 잘 실행돼서 따로 추가하지 않았다. 그러나 'refusal'를 추가하지 않으면 계속 KeyError가 발생해서 refusal="None" 변수를 추가했다.

문제 2

변수를 추가한 후에도 TypeError, ValueError가 발생했다. 최종적으로 feedback_prompt를 수정하고, invoke 호출 방식을 변경하고, input_data를 수정했다. 

# 3. 사용자 답변에 대한 피드백 생성
    feedback_prompt = ChatPromptTemplate.from_messages([
        ("system", f"""
    AI 강사로서 다음 퀴즈의 정답 여부를 확인하고 피드백을 제공하세요.
    퀴즈: {{quiz}}
    답변: {{answer}}
    대화 기록: {{previous_conversation}}
    거절 사유: {{refusal}}
    """)
    ])

    # 피드백 생성 - 키워드 인수로 전달
    feedback_data = feedback_prompt.format(
        quiz=quiz,
        answer=user_answer,
        previous_conversation=previous_conversation,
        refusal="None"
    )

    # 피드백 체인 호출
    feedback = llm.invoke(feedback_data)   # LLM을 직접 호출하여 피드백 생성

 

 

 

 

 

 

'AI 부트캠프 > 챕터3(11.08~12.04)' 카테고리의 다른 글

TIL 51  (0) 2024.11.28
TIL 50  (1) 2024.11.27
TIL 48  (0) 2024.11.25
TIL 47  (0) 2024.11.23
WIL 7  (0) 2024.11.22