반응형
일전의 포스트에서 말했듯이 두 가지 문제가 있었다.
- Selenium을 사용하기에 한 가지의 보조기능을 위해 너무 많은 클라우드 컴퓨팅 리소스가 Chrome Driver에서 사용된다.
- 실제로 이미지 평가가 정확성을 떠나 작동하지 않는 경우가 있다.
먼저 Youtube Data API를 활용하여 첫 번째 문제의 경우 확실히 해결을 했다. 그리고 두 번째 문제의 경우 Youtube Data API에서 Thumdnail과 동시에 조회해 올 수 있는 title과 description을 활용하여 text_evaluation을 추가하기로 했다. 그래서 아래와 같은 로직으로 FastAPI로 전환을 마무리했다.
- Youtube Data API로 최근에 업로드한 영상 4개 조회
- 해당 영상들읠 Title, Description 그리고 Thumbnail을 전처리 진행
- 먼저 Image에 대한 평가를 진행
- 평가에서 불합격의 경우 바로 결과 반환 하지만 합격 혹은 평가 불가의 경우 재평가 진행
그래서 해당 로직의 FastAPI의 service.py는 아래와 같이 구현하였다.
def profile_evaluation(request: ProfileEvaluationRequestDto):
# Getting Youtube Data API Object
youtube_data_api = youtube_data_api_request(api_key=YOUTUBE_API_KEY)
# Getting Channel Info
channel_response = youtube_channel_request(
youtube_data_api=youtube_data_api,
channel_id=request.channel_id)
# Getting Playlist
playlist_response = playlist__request(
youtube_data_api=youtube_data_api,
youtube_channel=channel_response)
# Parsing response aka preprocessing
videos_text_info, thumbnail_urls = response_preprocessing(
playlist_response=playlist_response)
evaluation_prompt = EvaluationPrompt
# Image Evaluation
# Image request & preprocessing
image_response = image_request(thumbnail_urls)
combined_image = image_preprocessing(image_response)
image_evaluation_prompt = evaluation_prompt.image_evaluation_prompt.value
try:
image_evaluation_result = image_evaluation(combined_image, image_evaluation_prompt)
if (not image_evaluation_result['appropriate'] and len(image_evaluation_result['reason']) != 0):
return ProfileEvaluationResponseDto(
evaluation_status=False,
reason=image_evaluation_result['reason']
)
except Exception as e:
print(e)
# Text Evaluation
text_evaluation_prompt = evaluation_prompt.text_evaluation_prompt.value
text_evaluation_result = text_evaluation(
description=videos_text_info, prompt=text_evaluation_prompt)
return ProfileEvaluationResponseDto(
evaluation_status=text_evaluation_result['appropriate'],
reason=text_evaluation_result['reason']
)
추가적으로 구현한 요청함수와 전처리 함수는 아래와 같다.
요청함수 모음: request_methods.py
def youtube_data_api_request(api_key):
youtube_data_api = googleapiclient.discovery.build(
'youtube', 'v3', developerKey=api_key)
return youtube_data_api
def youtube_channel_request(youtube_data_api, channel_id):
channel_response = youtube_data_api.channels().list(
part='contentDetails',
id=channel_id
).execute()
return channel_response
def playlist_request(youtube_data_api, youtube_channel):
uploads_playlist_id = youtube_channel["items"][0]["contentDetails"]["relatedPlaylists"]["uploads"]
playlist_response = youtube_data_api.playlistItems().list(
part='snippet',
playlistId=uploads_playlist_id,
maxResults=4,
pageToken=None
).execute()
return playlist_response
def image_request(image_urls):
image_responses = []
for i in range(len(image_urls)):
image_responses.append(requests.get(image_urls[i]))
return image_responses
전처리 함수 모음: preprocessing_methods.py
def response_preprocessing(playlist_response):
text_info = []
thumbnail_urls = []
for item in playlist_response["items"]:
snippet = item["snippet"]
# title
video_title = snippet["title"]
# description
video_desc = snippet['description']
# thumbnails - urls
video_thumbnail_url = snippet['thumbnails']['standard']['url']
text_info.append({
"title": video_title,
"description": video_desc,
})
thumbnail_urls.append(video_thumbnail_url)
return text_info, thumbnail_urls
def image_preprocessing(image_response):
img_in_bytes = []
for i in range(len(image_response)):
img_in_bytes.append(Image.open(BytesIO(image_response[i].content)))
img_width = img_in_bytes[0].size[0]
img_height = img_in_bytes[0].size[1]
combined_width = img_width*2
combined_height = img_height*2
combined_image = Image.new('RGB', (combined_width, combined_height))
combined_image.paste(img_in_bytes[0], (0, 0))
combined_image.paste(img_in_bytes[1], (img_width, 0))
combined_image.paste(img_in_bytes[2], (0, img_height))
combined_image.paste(img_in_bytes[3], (img_width, img_height))
buffer = BytesIO()
combined_image.save(buffer, format="JPEG")
buffer.seek(0)
combined_base64 = base64.b64encode(buffer.read()).decode('utf-8')
return combined_base64
이렇게 하여 초기 프로필 평가로직의 두 문제를 해결하는 변경된 로직 구현을 마무리했다.
다음으로는 콘티생성과 최적화 및 비동기 적용 포스트로 돌아오겠다.
아래의 링크에서 전체 코드를 확인할 수 있다.
GitHub - jwywoo/Project-Joing-Service-MVP-Dev
Contribute to jwywoo/Project-Joing-Service-MVP-Dev development by creating an account on GitHub.
github.com
반응형
'AI > Projects' 카테고리의 다른 글
Project Joing: 콘티 생성기 - Intro (1) | 2024.11.18 |
---|---|
Project Joing: 데이터 수집 - Proposal (1) | 2024.11.17 |
Project Joing: Profile Evaluation 로직변경 - Youtube Data API (3) | 2024.11.15 |
Project Joing: 데이터 수집 - RecSystem (4) | 2024.11.12 |
Project Joing: 데이터 수집 - Intro (3) | 2024.11.11 |