상세 컨텐츠

본문 제목

Sluv의 AI 도입기

AI

by 준빅 2024. 1. 8. 16:05

본문

AI는 많은 기능들을 자동화할 수 있다는 장점이 있습니다.

Sluv도 관리 및 편의성 개선을 위해 필요한 작업을 자동화하기 위해 2가지의 AI를 도입하게 되었습니다.

도입 이유

1. 커뮤니티 서비스의 관리 특성

Sluv은 연예인 손민수템의 정보를 공유하는 커뮤니티 서비스입니다.

커뮤니티 서비스를 운영하며 중요한 부분은 부적절한 내용을 관리하는 것입니다.

 

그중에서 우리는 부적절한 댓글에 주목하였습니다.

클린봇의 도입

네이버 웹툰의 클린봇

기존의 댓글 관리 구조는 다음과 같았습니다.

1. 사용자가 부적절한 댓글을 신고한다.
2. 신고된 댓글을 관리자 페이지에서 관리자가 확인 후 제한한다.
3. 작성자에게 패널티를 부여한다.
4. 1달 사이에 작성자의 총 패널티가 3이상 이라면 작성자의 이용을 정지한다.

 

해당 구조는 이용자가 신고를 하지 않으면 관리자의 눈에 누락되는 댓글이 발생할 수 있다는 점과, 관리자가 신고된 댓글을 일일히 확인하여야 한다는 점이 단점으로 다가왔습니다.

 

때문에 댓글 검열을 자동화한다면, 관리자의 눈에 누락되는 댓글을 줄일 수 있고, 관리자가 확인해야 할 댓글의 수가 줄어들 것이라고 판단하여 클린봇을 도입하게 되었습니다.

 

Kobert 사용

클린봇 모델은 Kobert을 활용하여 제작하였습니다.

Kobert는 Transformer 모델 중 하나인 Bert를 한글로 학습시킨 모델입니다.

 

여기서 Bert는 다양한 Task를 수행할 수 있는 언어모델로, 그 중 Text 분류에 특화되어 있습니다. Bert 모델 위에 하나의 간단한 layer를 쌓은 후, 사용자가 필요로 하는 class 개수 맞춰 출력하게 바꿔 준다면, Text에 대한 분류를 수행할 수 있습니다.

 

 

 

학습 데이터 라벨링

학습 데이터 라벨링

해당 서비스에서는 악성 댓글을 판별하기 위한 모델이기에 약 7만 개의 댓글 데이터Huggingface에서 가져와 긍정(0), 부정(1), 악성댓글(2)로 분류하도록 Kobert 모델 위에 layer를 한층 더 쌓았습니다.

(라벨링 해준 Hamsss.. 고마워요!!)

 

모델 서버와 메인 서버 연동

/*
	AiModelService.java
*/

@Async(value = "asyncThreadPoolExecutor")
public void censorComment(Comment comment) {
    boolean isMalicious = aiModelRepository.isMaliciousComment(comment.getContent());

    if (isMalicious) {
        comment.changeStatus(CommentStatus.BLOCKED);
        commentRepository.save(comment);
    }
}
/*
	AiModelRepository.java
*/

public boolean isMaliciousComment(String comment) {
    try {
        boolean isMalicious = false;
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<CommentCleanBotReqDto> request = new HttpEntity<>(CommentCleanBotReqDto.of(comment), headers);

        // RestTemplate
        log.info("Request: POST {}", URL);
        log.info("Comment {}", comment);
        RestTemplate rt = new RestTemplate();
        ResponseEntity<Integer> response = rt.exchange(
                URL + "/check-malicious-comment",
                HttpMethod.POST,
                request,
                Integer.class
        );

        if (response.getBody() == 2) {
            isMalicious = true;
        }

        return isMalicious;
    } catch (Exception e) {
        throw new MaliciousCommentException();
    }
}

 

AiModleService와 AiModleRepository를 만들어 Repository에서 FastAPI로 구현된 AI 모델 서버와 통신하였습니다.

 

/**
	CommentService.java
*/

@Transactional
public void postComment(User user, Long questionId, CommentPostReqDto dto) {
    log.info("댓글 등록 - 사용자 : {}, 질문 게시글 : {}, 댓글 내용 {}", user.getId(), questionId, dto.getContent());
    Question question = questionRepository.findById(questionId).orElseThrow(QuestionNotFoundException::new);

    Comment comment = commentRepository.save(
            Comment.toEntity(user, question, dto.getContent())
    );

    saveCommentImgAndItem(dto, comment);
    aiModelService.censorComment(comment);

}

 

AiModleService의 기능을 댓글 등록, 수정 시마다 비동기로 처리하여 댓글을 검열하였습니다.

 

 

결과

 

이렇게 AI로 부적절한 댓글을 제한할 수 있게 되었습니다.

 

 

2. 아이템 검색 필터링

지그재그, 무신사, 에이블리 필터링 옵션

연예인 손민수템의 정보를 공유하고, 공유된 정보를 검색할 수 있는 것이 Sluv의 주 기능입니다.

때문에 타 쇼핑몰의 검색 필터는 어떤식으로 구성되어 있는지 살펴보았습니다.

그 결과 대부분의 쇼핑몰 검색 필터에는 색상을 기준으로 필터링이 가능하다는 것을 발견하였습니다.

 

 

AI를 적용한 이유는?

아이템 색상 추출 AI를 도입하겠다고 했을 때 가장 많이 들었던 이야기는

사용자가 정보 공유 게시글을 등록할 때 적으면 되는 거 아니야?

 

맞는 말입니다. 하지만 해당 기술 AI를 도입하려 자동화한 이유가 2가지나 존재합니다!

 

1. 아이템의 색은 검색에만 사용된다.

컬러는 보통 상품명에 포함됩니다. 때문에 색을 한 번 더 선택하는 건 정보 공유자가 중복된 일을 하게 됩니다.

또한 제품명에서 색을 추출하게 된다면, 브랜드마다 기준이 모호합니다예를 들어 어디선 화이트 색이지만 어디서 아이보리색이 될 수 있습니다.

 

때문에 공유자에게 색에 대한 책임이 가면 안된다고 판단했습니다.

 

2. 아이템 등록 시 이미 많은 정보를 입력해야 한다.

 

아이템 정보 공유 창

색보다 입력해야 할 중요 정보들이 이미 다수 존재합니다.

때문에 색까지 입력을 요구한다면 공유자의 사용성이 떨어진다는 문제가 발생합니다.

 

YOLOv8

이미지에서 아이템의 색상을 추출해 주는 모델은 YOLOv8을 활용하여 제작하였습니다.

 

 옷 색깔 탐지를 위해 먼저 사진에서 옷을 탐지해야 한다는 생각에 옷 탐지를 위한 모델을 개발하게 되었습니다.
사진에서 옷을 탐지하기 위해서, 이미지 객체 탐지에 특화된 모델인 Yolo(You only Look Once를 사용했으며, 그 중 가장 최신 모델인 v8을 사용하게 되었습니다. Yolo 같은 경우에도 이미지에서 객체를 탐지함과 동시에 해당 객체에 대한 분류가 빠른 속도로 가능하기 때문에, 다양한 이미지 탐지 task에서 사용되고 있습니다. 특히 yolov8 같은 경우에는 yolo 버전 중에서 가장 성능이 월등하기 때문에 해당 서비스에서 활용되었습니다.

학습방법

 이미지 학습을 위해 학습 데이터는 DeepFashion2 라는 데이터 세트를 사용했습니다. 해당 데이터 세트는 매우 양질의 데이터로, 객체 탐지 뿐만 아니라, 객체 분할(Segmentation), 분류(classification)도 할 수 있게끔 라벨링 되어 있습니다. 이 중에서 옷 탐지를 위해 객체 탐지를 위한 bounding box 좌표와 해당 옷이 어떤 옷에 해당하는지 정보만을 남겨뒀습니다. 데이터의 개수는 약 10만개로 진행했습니다.

 

 

모델 서버와 메인 서버 연동

/*
	AiModelService.java
*/

@Async(value = "asyncThreadPoolExecutor")
public void getItemColor(Item item) {
    ItemImg mainImg = itemImgRepository.findMainImg(item.getId());

    String color = aiModelRepository.getItemColor(mainImg.getItemImgUrl());

    item.changeColor(color.replace("\"", ""));
    itemRepository.save(item);
}
/*
	AiModelRepository.java
*/

public String getItemColor(String imgUrl) {
	try{
        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Type", "application/json");

        HttpEntity<ItemColorCheckReqDto> request = new HttpEntity<>(ItemColorCheckReqDto.of(imgUrl), headers);

        // RestTemplate
        log.info("Request: POST {}", URL);
        RestTemplate rt = new RestTemplate();
        ResponseEntity<String> response = rt.exchange(
                URL + "/check-item-color",
                HttpMethod.POST,
                request,
                String.class
        );

        return response.getBody();
    } catch (Exception e) {
            throw new ItemColorExtractionException();
    }
}

 

클린봇과 같은 방식으로 AiModleService와 AiModleRepository를 만들어 Repository에서 FastAPI로 구현된 AI 모델 서버와 통신하였습니다.

/*
	ItemService.java
*/

public ItemPostResDto postItem(User user, ItemPostReqDto reqDto) {

	/*아이템 등록 로직*/

    aiModelService.getItemColor(newItem);
    
    return ItemPostResDto.of(newItem.getId());
}

 

AiModleService의 기능을 아이템 등록, 수정 시마다 비동기로 처리하여 댓글을 검열하였습니다.

 

결과

 

이렇게 AI로 아이템 이미지에서 색을 추출하여 검색 필터에 이용할 수 있게 되었습니다.

 

 

 

Docker + FastAPI를 사용한 AI 모델 서버 배포 과정이 궁금하다면 이곳을 참고해주세요

AI 모델은 한국항공대학교 인공지능랩실의 함승현 학생이 제작해주셨습니다.

댓글 영역