AutoPercenty/ai/gemini.py

243 lines
16 KiB
Python

import requests
import google.generativeai as genai
import logging
import markdown
# 로거 인스턴스 가져오기
logger = logging.getLogger('default_logger')
class ImageDescriptionGenerator:
def __init__(self, api_key):
"""API 키를 사용하여 객체를 초기화합니다."""
self.api_key = api_key
genai.configure(api_key=self.api_key)
self.model = genai.GenerativeModel('gemini-pro-vision')
def download_image(self, image_url):
"""이미지 URL에서 이미지를 다운로드하고 바이트 데이터를 반환합니다."""
response = requests.get(image_url)
response.raise_for_status() # 에러가 발생했을 경우 예외를 발생시킵니다.
return response.content
def fill_naver_products(self, product_info, required_length=5):
nv_products = product_info.naver_products
default_product = {"productTitle": "상품 정보 없음", "price": "가격 정보 없음"}
while len(nv_products) < required_length:
nv_products.append(default_product)
logger.debug(f"{len(nv_products)}번째 상품정보가 없어 기본정보로 채웁니다.")
def fill_product_info_lists(self, product_info, required_length=5):
# naver_products 리스트 채우기
nv_products = product_info.naver_products
default_product = {"productTitle": "상품 정보 없음", "price": "가격 정보 없음"}
while len(nv_products) < required_length:
nv_products.append(default_product)
logger.debug(f"{len(nv_products)}번째 상품정보가 없어 기본정보로 채웁니다.")
# trans_option_1_names 리스트 채우기
while len(product_info.trans_option_1_names) < required_length:
product_info.trans_option_1_names.append("옵션 정보 없음")
logger.debug(f"{len(product_info.trans_option_1_names)}번째 trans_option_1_names 정보가 없어 기본정보로 채웁니다.")
# trans_option_2_names 리스트 채우기
if hasattr(product_info, 'trans_option_2_names'):
while len(product_info.trans_option_2_names) < required_length:
product_info.trans_option_2_names.append("옵션 정보 없음")
logger.debug(f"{len(product_info.trans_option_2_names)}번째 trans_option_2_names 정보가 없어 기본정보로 채웁니다.")
def generate_description(self, product_info, top_k=3):
"""이미지 URL을 받아 해당 이미지에 대한 설명을 생성하고 반환합니다."""
# 'gemini-pro-vision' 모델을 사용하여 이미지 설명 생성
# prompt = f"이미지의 상품명은 {title} 1. 이 상품이 무엇인지, 어떤 용도로 사용하는지 설명해줘 2. 이 상품의 배송비 산정을 위해 대략적인 무게를 kg으로 단답형으로 추정해줘. 3. 이 이미지의 상품을 한국의 온라인 쇼핑몰에서 팔기위한 홍보문구를 상품이미지에 맞게 3줄 ~ 4줄 정도 만들어줘. 4.대답하는 방식은 [상품의 홍보문구] 여러줄, [상품의 용도] 자세히, [상품의 무게] 형식과 순서로 해줘."
# prompt = f"주어진 이미지의 상품명은 {product_info.keyword_title} 1. 이 상품이 무엇인지, 어떤 용도로 사용하는지 설명해줘 2. 이 상품의 배송비 산정을 위해 대략적인 무게를 kg으로 단답형으로 추정해줘. 3. 이 이미지의 상품을 한국의 온라인 쇼핑몰에서 팔기위한 홍보문구를 상품이미지에 맞게 3줄 ~ 4줄 정도 만들어줘."
# self.fill_naver_products(product_info)
self.fill_product_info_lists(product_info)
prompt = f'''
나는 타오바오에서 상품을 가져와서 한국의 온라인 쇼핑몰에서 구매대행업을 하는 사업가야.
너는 온라인 쇼핑몰 상세페이지 제작 전문가야. 니가 만든 상품페이지는 모두를 감동시키고, 구매로 이어지는 마법같은 능력이 있어.
이제 주어진 이미지와 내가 원하는 상세페이지에 대한 정보를 줄께.
하나씩 차근차근 진행해보자.
각 질문에 대한 답변을 기존의 html에 추가할수 있는 형태로 (HTML 태그로 이루어진) 만들어줘. HTML편집기에 바로 추가하여 사용할 수 있게 말이야. 문단기호, 구분기호등으로 분리해서 답변해줘.
[정보]
A. 해당상품의 타오바오 상품명은 '{product_info.tao_title}'
B. 해당상품의 키워드는 '{product_info.keyword_title}'
C. 해당상품을 나타나는 상품의 옵션이름은 '{product_info.trans_option_1_names}'
D. 해당상품의 특징이라 할 수 옵션의 공통적인 키워드는 '{product_info.trans_option_1_name_common_parts}'
E. 해당상품과 비슷한 상품을 파는 경쟁사의 제품정보는 아래와 같아.
E-1. 상품명1 : {product_info.naver_products[0]["productTitle"]}
상품가격1 : {product_info.naver_products[0]["price"]}
E-2. 상품명2 : {product_info.naver_products[1]["productTitle"]}
상품가격2 : {product_info.naver_products[1]["price"]}
E-3. 상품명3 : {product_info.naver_products[2]["productTitle"]}
상품가격3 : {product_info.naver_products[2]["price"]}
E-4. 상품명4 : {product_info.naver_products[3]["productTitle"]}
상품가격4 : {product_info.naver_products[3]["price"]}
E-5. 상품명5 : {product_info.naver_products[4]["productTitle"]}
상품가격5 : {product_info.naver_products[4]["price"]}
[상품명]
위의 모든 정보를 바탕으로 상품을 잘 설명한 상품명을 만들어줘 1개 만들어줘.
- 상품명 제작 권장 사항 1: 키워드, 용도, 재질, 용량, 형식, 모양,특징등의 단어를 콤마를 제외하고 띄어쓰기로 나열해(용량과 스펙등은 뒤쪽으로 배치).
- 상품명 제작 권장 사항 2: 타오바오 상품명과 옵션이름들에서 상품의 특징을 가져와서 상품명에 사용해야해.
- 상품명 제작 권장 사항 3 : 경쟁사의 상품명들을 띄어쓰기를 중심으로 단어를 분리하고, 중복된 단어를 모두 제거한 후 나머지 단어들 중 4개를 가져와서 내 상품명 제작에 사용해줘.
- 반드시 준시해야 할 상품명 제한 사항 : 형용사 사용 금지, 중복단어 절대 사용 금지, 쉼표나 별표를 포함한 모든 특수문자 금지.
- 상품명 형식 : 한글의 글자수로 35자 이상 되어야 해.
이 답변은 html 형식으로, 폰트형식은 css로 설정해줘. '폰트크기 24, 폰트 스타일 굵게'로 해줘
[상품의 용도]
이 상품이 무엇인지, 어떤 용도로 사용하는지 자세하게 설명해줘.
이 답변은 html 형식으로, 폰트형식은 css로 설정해줘. 제목을 '폰트크기 20, 폰트 스타일 굵게', 내용은 '폰트크기 16, 들여쓰기'로해줘
[상품의 무게]
이 상품의 배송비 산정을 위해 무게를 kg으로 알려줘.
이 답변은 html 형식으로, 폰트형식은 css로 설정해줘. 제목을 '폰트크기 20, 폰트 스타일 굵게', 내용은 '폰트크기 16, 들여쓰기'로해줘
[상품의 강점과 특징]
이 상품의 강점, 특징과 함께 왜 이상품을 사야하는지, 다른제품들과의 차별점은 무엇인지, 기존제품의 어떠한 단점을 개선했는지를 중심으로 홍보문구를 상품이미지에 맞게 자세하고 친절하게 만들어줘."
이 답변은 html 형식으로, 폰트형식은 css로 설정해줘. 제목을 '폰트크기 20, 폰트 스타일 굵게', 내용은 '폰트크기 16, 들여쓰기'로해줘
[사용상 주의점]
이 상품의 사용상 주의점을 자세히 알려줘
이 답변은 html 형식으로, 폰트형식은 css로 설정해줘. 제목을 '폰트크기 20, 폰트 스타일 굵게', 내용은 '폰트크기 16, 들여쓰기'로해줘
[상품의 추가 정보]
이 상품의 도움이 될만한 또 다른 추가정보를 자세하게 알려줘
이 답변은 html 형식으로, 폰트형식은 css로 설정해줘. 제목을 '폰트크기 20, 폰트 스타일 굵게', 내용은 '폰트크기 16, 들여쓰기'로해줘
'''
front_prompt = f'''
나는 타오바오에서 상품을 가져와서 한국의 온라인 쇼핑몰에서 구매대행업을 하는 사업가야.
너는 온라인 쇼핑몰 상세페이지 제작 전문가야. 니가 만든 상품페이지는 모두를 감동시키고, 구매로 이어지는 마법같은 능력이 있어.
이제 주어진 이미지와 내가 원하는 상세페이지에 대한 정보를 줄께.
하나씩 차근차근 진행해보자.
내가 원하는 답변 형식은 바로 상품페이지에 쓸수 있는 형식이야. 해당 부분을 구분하고, 부연설명은 빼줘.
[정보]
A. 해당상품의 타오바오 상품명은 '{product_info.tao_title}'
B. 해당상품의 키워드는 '{product_info.keyword_title}'
C. 해당상품을 나타나는 상품의 옵션이름은 '{product_info.trans_option_1_names}'
D. 해당상품의 특징이라 할 수 옵션의 공통적인 키워드는 '{product_info.trans_option_1_name_common_parts}'
E. 해당상품과 비슷한 상품을 파는 경쟁사의 제품정보는 아래와 같아.
E-1. 상품명1 : {product_info.naver_products[0]["productTitle"]}
상품가격1 : {product_info.naver_products[0]["price"]}
E-2. 상품명2 : {product_info.naver_products[1]["productTitle"]}
상품가격2 : {product_info.naver_products[1]["price"]}
E-3. 상품명3 : {product_info.naver_products[2]["productTitle"]}
상품가격3 : {product_info.naver_products[2]["price"]}
E-4. 상품명4 : {product_info.naver_products[3]["productTitle"]}
상품가격4 : {product_info.naver_products[3]["price"]}
E-5. 상품명5 : {product_info.naver_products[4]["productTitle"]}
상품가격5 : {product_info.naver_products[4]["price"]}
'''
purpose_prompt = f'''
[질문]
1. 이 상품이 무엇인지, 어떤 용도로 사용하는지 자세하게 설명해줘.
'''
weight_prompt = f'''
[질문]
2. 이 상품의 배송비 산정을 위해 무게를 kg으로 알려줘.
'''
character_prompt = f'''
[질문]
3. 이 상품의 강점, 특징과 함께 왜 이상품을 사야하는지, 다른제품들과의 차별점은 무엇인지, 기존제품의 어떠한 단점을 개선했는지를 중심으로 홍보문구를 상품이미지에 맞게 자세하고 친절하게 만들어줘."
'''
warning_prompt = f'''
[질문]
4. 이 상품의 사용상 주의점을 자세히 알려줘
'''
addtional_prompt = f'''
[질문]
5. 이 상품의 도움이 될만한 또 다른 추가정보를 자세하게 알려줘
'''
title_prompt = f'''
[질문]
6. 위의 모든 정보를 바탕으로 상품을 잘 설명한 상품명을 만들어줘 1개 만들어줘.
6-1. 상품명 제작 권장 사항 1: 키워드, 용도, 재질, 용량, 형식, 모양,특징등의 단어를 콤마를 제외하고 띄어쓰기로 나열해(용량과 스펙등은 뒤쪽으로 배치).
6-2. 상품명 제작 권장 사항 2: 타오바오 상품명과 옵션이름들에서 상품의 특징을 가져와서 상품명에 사용해야해.
6-3. 상품명 제작 권장 사항 3 : 경쟁사의 상품명들을 띄어쓰기를 중심으로 단어를 분리하고, 중복된 단어를 모두 제거한 후 나머지 단어들 중 4개를 가져와서 내 상품명 제작에 사용해줘.
6-4. 반드시 준시해야 할 상품명 제한 사항 : 형용사 사용 금지, 중복단어 절대 사용 금지, 쉼표나 별표를 포함한 모든 특수문자 금지.
6-5. 상품명 형식 : 한글의 글자수로 35자 이상 되어야 해.
'''
# 원하는 답변형태
# 아래와 같은 형식으로 답변해주면 좋겠어.
# [홍보문구에 해당하는 내용]
# 홍보문구
# xxxxx
# [무게에 해당하는 내용]
# 무게
# xx Kg
# [용도에 해당하는 내용]
# 용도
# xxxx
# [상품명에 해당하는 내용]
# 상품명
# XXX YYY
try:
logger.debug(f"전달된 prompt \n {prompt}")
image_data = self.download_image(product_info.main_image_url)
response = self.model.generate_content([prompt, {"mime_type": "image/jpeg", "data": image_data}])
# 후보 결과 확인 및 처리
if response.candidates and len(response.candidates) > 0:
logger.debug(f"response.text : {response.text}")
# response_html = markdown.markdown(response.text)
# logger.debug(f"response_html : {response_html}")
return response.text
else:
# 후보 결과가 없거나 유효하지 않을 경우 기본 응답 반환
return '''
### 상품의 용도\n\n
- 에러 발생: 유효한 상품 설명을 제공할 수 없습니다.\n\n
### 상품의 홍보문구\n\n
- 에러 발생: 유효한 홍보문구를 제공할 수 없습니다.\n\n
### 상품의 무게\n\n
- 에러 발생: 유효한 상품 무게를 제공할 수 없습니다.
'''
except ValueError as e:
logger.debug(f"오류 발생: {e}", exc_info=True)
return "오류 발생: 유효한 응답을 생성할 수 없습니다."
except Exception as e:
logger.debug(f"예상치 못한 오류 발생: {e}", exc_info=True)
return "예상치 못한 오류 발생: 처리할 수 없습니다."
def generate_option_description(self, product_info, top_k=3):
product_info.option_datas
prompt = f'''
나는 타오바오에서 상품을 가져와서 한국의 온라인 쇼핑몰에서 구매대행업을 하는 사업가야.
너는 온라인 쇼핑몰 상세페이지 제작 전문가야. 니가 만든 상품페이지는 모두를 감동시키고, 구매로 이어지는 마법같은 능력이 있어.
여기 중국어로 된 상품의 옵션들이 있어.
다음 옵션 목록에서 각 옵션의 고유한 특징만 추출하여 한국어로 번역하고, 최대 45바이트를 넘지 않도록 간결하게 작성해주세요. 특수 문자는 제외하고 허용되는 특수 문자(!$~()._-=+/)만 포함해주세요.
하나씩 차근차근 진행해보자.
[정보]
중국어 옵션 목록은 다음과 같아. '{product_info.option_datas}'
[출력형식]
product_info.option_datas['name']
[
{"options1": "특징1"},
{"options2": "특징2"},
...
]
options_info[f'option_type_{idx}'] = {
'name': option_type_name,
'items_count': option_items_count,
'items': option_items_info
}
'''