자 이제 그 동안 개선하고 추가 구현한 것을 설명해보겠다.
하루나 이틀치라고 해도 커밋을 꽤나 많이 했다.
근데 재미있었음. 실시간으로 무언가 바뀌는 모습이 보이고 사용자들도 반응이 괜찮았기 떄문.
암튼 바로시작한다.
백앤드 로직의 커밋메세지를 요약하자면 아래와 같다.
- 2024년 12월 6일
- 초기 커밋: "만능그림봇 프로젝트" 코드 업로드.
- 2024년 12월 8일
- CORS 환경 변수화: CORS 관련 설정 및 패키지 추가.
- OpenAI 응답 로그 추가: 사용자 프롬프트 개선 및 응답 기록 기능 추가.
- 디렉토리 자동 생성: 일부 로그 파일 자동 생성과 디렉토리 자동화.
- 번역 및 로직 강화: 번역 기능과 상세 설명 검증 로직 개선.
- 2024년 12월 9일
- 프롬프트 강화: 사용자 입력 처리 로직 개선.
- 프롬프트 변경: 프롬프트 모델과 디테일 위치 변경 작업.
- 추가 설명 전달 기능: detailed_explanation 전달 기능 추가.
로그추가
일단 첫번쨰로 EC2서버에 Guicorn으로 배포했을때 누군가 어떤 API를 쏘는지 확인할 수 가 없어 로그를 추가해줬다.
# 날짜별 로그 파일 설정
log_dir = "logs"
today_date = datetime.now().strftime("%Y-%m-%d") # 오늘 날짜 형식: YYYY-MM-DD
# 로그 디렉토리 생성
if not os.path.exists(log_dir):
os.makedirs(log_dir) # logs 디렉토리 생성
# 로그 파일 경로 설정
log_file = f"{log_dir}/{today_date}.log"
filename=log_file,
level=logging.DEBUG if DEBUG_MODE else logging.INFO,
format="%(asctime)s - %(levelname)s - %(message)s"
logging.info(f"Translated Prompt: {translated_prompt}") # 번역된 프롬프트 저장
logging.info(f"OpenAI Image Response: {response}") # OpenAI 응답 저장
logging.info(f"Generated Image URL: {image_url}") # 이미지 URL만 별도로 저장
logging.error(f"Error: {str(e)}") # 에러 로그 기록
로그는 그냥 단순히 logs디렉토리 안에 날짜별로 로그가 생성되게 하는 단순한 로직을 추가해서 사용자가 어떤 프롬프트를 입력하는지 openai는 어떤응답을 말하는지와 응답값에 대한 이미지의 url 정보가 로그에 찍히게 개선하였다.
프롬프트 강화
{"role": "system", "content": "You are a translator that converts Korean to English."},
{"role": "system", "content": "You are a translator and assistant that translates Korean prompts to English and enhances them with detailed descriptions for image generation."}
또 두번째는 기존 프롬프트를 강화시켜줬는데, 이 부분은 ChatGPT에 내가 어떤 그림을 그려달라고 했을때, chatGPT는 내 단순한 문장에 상세한 디테일을 넣어서 DALL:E2 이미지 모델에 전달하는걸로 보였다.
이 부분에 착안해서 나도 내 프롬프트에서 " 당신은 한국어를 영어로 변환하는 번역가입니다. " 를
" 귀하는 한국어 프롬프트를 영어로 번역하고 이미지 생성에 대한 자세한 설명으로 향상시키는 번역가이자 어시스턴트입니다. " 로 자세한 설명을 추가해달라고 요청을 추가한것이다.
참고로 저렇게 역할(Role) 에 system 을 집어 넣으면 content의 내용대로 모델의 초기 지침을 설정할수있다.
모델의 행동 방식이나 응답 스타일을 설정한다고 보면 된다.
예를 들어 content 안에 너는 5000년 전부터 살아온 전설의 용이고 모르는게 없어. 라고 설정하면 자기가 용으로 컨셉을 잡는다.
이러한 기능으로 뤼튼같은 사이트처럼 나만의 말투를 가진 챗봇을 만들 수 있는것이다.
재미있당.
아무튼 그래서 내 content의 내용을 번역만 하는게 아닌 번역하고 자세한 설명까지 추가해서 이미지 생성해라~ 라고 되는것이다.
하지만 이 부분은 실패가 있었다.
이유가 뭐냐면 원하는 이미지를 잘 생성해주지 않았다.
가령 잘 모르는 한국단어 같은걸 영어로 말해주다 보니 내가 원하는 이미지완 전혀 다른 이미지를 자꾸 생성했다.
모델이 둘 중 하나의 작업(번역 또는 설명 강화)을 덜 정확하게 처리할 가능성이 있는것 같다.
그래서 프로세스를 두개로 나누기 시작했다.
번역/디테일설정 프롬프트 분리
처음에 진행한 사항은 한글단어나 문장을 받으면 그걸 번역하고
번역한 부분에 대한 자세한 설명을 추가하는 방식이였다.
{"role": "system", "content": "You are a translator that converts Korean text to English."},
당신은 한국어 프롬프트를 영어로 번역하는 번역가입니다.
이렇게 한번의 API를 보내고,
{"role": "system", "content": "You are an assistant that enhances English prompts for detailed image generation."},
당신은 자세한 이미지 생성을 위한 영어 프롬프트를 향상시키는 어시스턴트입니다.
(한글프롬프트 입력 -> 한국어를 번역 -> 번역한대상을 자세하게 영어로 설명)
이렇게 나눠 보내니까 이미지의 품질이 조금 좋아지는게 느껴졌다.
하지만 이 로직도 곧 문제가 발생하고 말았다.
한글프롬프트로 입력된 말을 (예:사오정) 이라고 보냈을때 saojeong으로 번역 후 API를 한번 더 보낸다.
근데 응답에 제가 잘 모르는단어예요! 라고 말해버린다.
그럼 이 응답값으로 이미지를 생성하는 대 환장파티가 발생해버린다.
그래서 이부분도 일단 검증로직을 추가했다.
검증로직 추가
[금지된 입력 패턴 추가]
# 금지된 입력 패턴 (무의미한 입력)
invalid_input_patterns = ["^[ㄱ-ㅎㅏ-ㅣ]+$", "^[a-zA-Z]+$", "^[!@#$%^&*()_+=]+$"]
for pattern in invalid_input_patterns:
if re.match(pattern, user_input):
logging.warning("유효하지 않은 입력 패턴")
return jsonify({"error": "앗! 무의미한 입력이에요. 조금 더 구체적으로 입력해 주세요! 🌟"}), 400
[번역 결과 검증]
# 번역 결과 검증
invalid_keywords = [
"I'm sorry","i'm unable to", "could you provide", "does not appear to", "meaning is unclear",
"difficult to understand", "please try again", "may be an error", "may be a typo",
"i do not recognize", "does not make sense", "could not process", "could not determine",
"ambiguous", "not clear", "unsure", "is confusing", "cannot generate",
"unknown context", "lack of clarity", "doesn't seem clear", "hard to understand",
"not valid", "does not make sense", "is not a valid",
"could not understand", "may be a typo", "please provide more context",
"check for errors", "unrecognizable", "does not appear", "meaning is unclear",
"specific term", "unknown term", "does not exist", "is unclear", "is not recognized",
"seems to be invalid", "could you clarify", "please clarify"
]
if any(keyword in translated_prompt.lower() for keyword in invalid_keywords):
logging.warning("유효하지 않은 번역 결과")
return jsonify({"error": "앗! 제가 그 말을 잘 이해하지 못했어요. 다른 멋진 아이디어를 입력해 주세요! 🚀"}), 400
[디테일프롬프트 결과 검증]
invalid_detailed_keywords = [
"I'm sorry","i'm unable to", "could you provide", "does not appear to", "meaning is unclear",
"difficult to understand", "please try again", "may be an error", "may be a typo",
"i do not recognize", "does not make sense", "could not process", "could not determine",
"ambiguous", "not clear", "unsure", "is confusing", "cannot generate",
"unknown context", "lack of clarity", "doesn't seem clear", "hard to understand",
"not valid", "does not make sense", "is not a valid",
"could not understand", "may be a typo", "please provide more context",
"check for errors", "unrecognizable", "does not appear", "meaning is unclear",
"specific term", "unknown term", "does not exist", "is unclear", "is not recognized",
"seems to be invalid", "could you clarify", "please clarify"
]
if any(keyword in detailed_prompt.lower() for keyword in invalid_detailed_keywords):
logging.warning("유효하지 않은 상세 설명 결과")
return jsonify({"error": "음... 제가 잘 모르겠는 내용이에요. 더 구체적으로 알려주세요! 🧐"}), 400
# 상세 설명이 지나치게 짧은 경우 검증
if len(detailed_prompt.split()) < 5:
logging.warning("상세 설명이 너무 짧음")
return jsonify({"error": "앗! 설명이 너무 짧아요. 조금 더 자세히 입력해 주세요! 📜"}), 400
최대한 이상한 말을 테스트 해가며 모른다는 표현이나 알수없다는 표현을 캐치 해 이러한 키워드가 나오면 즉시 멈추고 에러로그를 리턴시키도록 진행했다.
프롬프트 강화2
이 후 조금 생각해보니 내가 필요한 말을 다 시스템에 써 놓으면 이녀석이 제대로 동작하겠구나 싶어서
"content": "You are a translator who converts Korean text into English. You fully understand common Korean and English words and phrases, as well as general knowledge about Korea. If you encounter any extremely uncommon or unclear word or phrase that you genuinely cannot understand, respond only with \"i'm sorry\" and do not produce any further prompt."
당신은 한국어 텍스트를 영어로 변환하는 번역가입니다. 당신은 한국어와 영어의 일반적인 단어와 구문뿐만 아니라 한국에 대한 일반적인 지식도 충분히 이해하고 있습니다. 정말로 이해할 수 없는 매우 드물거나 불분명한 단어나 구문을 발견하면 "미안해요"로만 응답하고 더 이상의 프롬프트를 만들지 마세요
"content": "Your role is to transform a short piece of text into a realistic, straightforward image-generation prompt. You fully understand common English words and phrases. Emphasize clear, visible details and a believable setting rather than overly artistic or abstract elements. If you encounter any extremely uncommon or unclear word or phrase that you genuinely cannot understand, respond only with \"i'm sorry\" and do not produce any further prompt."
"당신의 역할은 짧은 텍스트를 현실적이고 간단한 이미지 생성 프롬프트로 변환하는 것입니다. 일반적인 영어 단어와 구문을 완전히 이해합니다. 지나치게 예술적이거나 추상적인 요소보다는 명확하고 눈에 보이는 세부 사항과 믿을 수 있는 설정을 강조하세요. 정말 이해할 수 없는 매우 드물거나 불분명한 단어나 구문을 발견하면 "죄송합니다"로만 응답하고 더 이상 프롬프트를 만들지 마세요."
주저리 주저리 content를 추가하다보니 엄청 길어졌다.
API 순서 변경
또한 현재의 프로세스 번역->디테일추가에서한국어로 디테일추가->번역 으로 순서까지 변경해줬따.
이유는 아래와 같은데,만약 사오정을 물어보면 사오정에 대해 한글로 잘 말해준다.근데 saojeong을 물어보면 뭔지 모른다는 답변이 오거나 이상한 설명을 추가한다.
그래서 사오정에 대한 디테일한 프롬프트를 한글로 생성한 뒤,그 프롬프트를 번역하게끔 로직의 순서를 바꾼것이다.
예시를 보면 아래와 같다.
(프롬프트의 설명 길이가 너무 길어져서 200자 이내로 말하라고 추 후에 수정하긴 했다.)
이후의 결과는 이렇게 로그로 보여주겠다.
사람들이 아무단어 혹은 문장을 입력하면, 그걸 디테일하게 설명을 추가한 뒤 번역하는 시스템으로 변경하였다.
(참고로 저 URL은 1시간 이내로 openAI에서 알아서 지워버리기 떄문에 지금은 저 URL로 들어가도 이미지를 볼 수없다.)
이 후 조금은 안정적인 AI 이미지생성이 가능해졌고 사용자들의 만족도도 조금 높아졌다.
백엔드 로직은 이 정도로 마무리하겠다.
다음편은 프론트엔드 로직에서 수정된 부분을 설명하겠다.
다음편에 께속~~
'만들고 싶은거 만들기' 카테고리의 다른 글
광고 수익을 창출할 웹사이트 만들어보기 4-4(React서버 프론트엔드 부분 기능 추가구현 및 개선사항) (2) | 2024.12.10 |
---|---|
광고 수익을 창출할 웹사이트 만들어보기 4-2(open AI API,AWS EC2 사용료 예상) (1) | 2024.12.10 |
광고 수익을 창출할 웹사이트 만들어보기 4-1(중간점검) (2) | 2024.12.08 |
광고 수익을 창출할 웹사이트 만들어보기 3-7(Vercel과 EC2 flask서버 통신 + Gunicorn으로 앱 띄워보기) (1) | 2024.12.08 |
광고 수익을 창출할 웹사이트 만들어보기 3-6(EC2 서버에 SSL인증 + 도메인 넣기) (0) | 2024.12.08 |