playdata/project

project 3. AI Control System ( AI 관제 시스템 )

soojin1 2024. 10. 14. 22:35

목적

  • 임의의 ML 및 DL 모델에 대한 서비스를 관리 제어 하는 내부 관리 프로그램
  • streamlit 을 통해 관리 화면을 html css js 없이 python 만으로 생성
  • 관리화면은 예측 결과에 대한 검토 및 잘못된 예측에 대한 코맨트, 라벨 기록 가능
  • 그 외 관리 화면에서 위 검토된 코맨트, 라벨을 기반으로 서비스 예측 정확성 통계 도출

사용 기술

  • pyspark
  • streamlit
  • airflow
  • mariadb
  • fastapi ( 모델 서빙 및 모델 질의 API & streamlit 관리 화면 사용 query API )

구조

  • Airflow DAG 2 종 ( 질의처리, 집계 )
  • 모델 처리 결과는 파일 형식(log)으로 저장
  • 파일로 저장된 log 의 집계 및 집계 결과는 DB 에 저장 - pySpark 활용

산출물

  • github team repo
  • pre research ( google doc url ) - 사전조사, huggingface 모델 탐색, 사용법, 선정 이유

평가기준

  • PR 생성 및 코드리뷰 활성화 <- 기능별 PR 생성, 팀원 PR 리뷰 코맨트 활성화 체크
  • 내가 운영하는 프로젝트 - 장애 및 운영에 대한 모든 팀원의 이해 ( 특정 장애가 발생하면, 팀원 누구라도 장애 처리가 가능한 수준 )

DAY 1

우리 팀은 이미지 파일에서 텍스트를 추출하는 "도넛" 모델을 사용하여 영수증 이미지를 처리하기로 했다.

영수증 이미지에서 품목, 가격, 매장 주소 등을 추출하여 다양한 인사이트를 도출해낼 수 있을 것으로 예상했다.

 

이번 프로젝트에서 나는 깃헙 이슈와 PR을 잘 사용해보고싶다.  팀원들끼리도 얘기했는데 이번 프로젝트 평가기준에도 그런 내용이 있기도 하고 나도 이전 프로젝트에서 그렇게까지 잘 활용하지 못했던 것 같아서 글 작성하는 연습 겸 ...@.@

 

나는 이번에도 !! airflow를 담당하게 되었다. 

그 전에 잠깐 DB 역할도 살짝 수행했다. AWS 서버에 도커를 설치하고 계속 사용해왔던 mariadb 도커를 실행시키고 테이블을 생성했다.

 

도커 설치는 아래 블로그 참조했다.

https://velog.io/@osk3856/Docker-Ubuntu-22.04-Docker-Installation

 

[Docker] Ubuntu 22.04 Docker 설치

Ubuntu 22.04 에 Docker 설치하기

velog.io

 

mariadb 도커는 아래와 같이 실행

$ sudo docker run -d \
        --name mariadb \
        -e MARIADB_USER=team1 \
        --env MARIADB_PASSWORD=1234 \
        --env MARIADB_DATABASE=team1 \
        --env MARIADB_ROOT_PASSWORD=my-secret-pw \
        -p 53306:3306 \
        mariadb:latest

 

수업시간에 활요했던 코드에는 --env MARIADB_DATABASE=mnistdb 라고 되어있었고, 도커 실행해서 DB에 접속해보면 mnistdb라는 데이터베이스가 생성되어있었다.

 

지금은 mnist가 아니기 때문에 새로운 데이터베이스를 만들어 사용하고 싶었는데 권한 문제로 새 데이터베이스를 생성하지못했다. 

 

※ 해결법 : 알고보니 --env로 생성할 수 있는 것 이었다..

[설명]

MariaDB 이미지 자체가 초기화 시 설정된 환경 변수를 바탕으로 데이터베이스와 사용자 계정을 생성하도록 되어있다.

MariaDB 공식 Docker 이미지는 다음과 같은 초기화 환경 변수를 지원

  • MARIADB_DATABASE: 지정한 이름의 데이터베이스를 컨테이너 초기화 시 자동으로 생성합니다.
  • MARIADB_USER, MARIADB_PASSWORD: 해당 데이터베이스와 연관된 사용자를 생성하고 권한을 부여합니다.
  • MARIADB_ROOT_PASSWORD: 루트 사용자 비밀번호를 설정합니다.

mariadb 도커 컨테이너에 접속한 후 mariadb -u ~ -p~로 데이터베이스에 접속했다.

team1 데이터베이스가 생성되어있는 것을 확인할 수 있고 해당 데이터베이스에 테이블을 CREATE 를 사용하여 생성해주었다.

테스트 데이터인 Laptop 데이터를 INSERT VALUES ~ INTO ~ 구문을 사용하여 임시 생성해두었다.

$ sudo docker exec -it mariadb bash
root@56513afb256c:/# mariadb -u team1 -p1234
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 3
Server version: 11.5.2-MariaDB-ubu2404 mariadb.org binary distribution

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| team1              |
+--------------------+
2 rows in set (0.001 sec)

MariaDB [(none)]> use team1;
Database changed

MariaDB [team1]> show tables;
Empty set (0.001 sec)

MariaDB [team1]> CREATE TABLE receipt (
    ->     num INT AUTO_INCREMENT PRIMARY KEY COMMENT '자동 증가 숫자',
    ->     date DATE NOT NULL COMMENT '날짜',
    ->     name VARCHAR(255) NOT NULL COMMENT '품명',
    ->     amount DECIMAL(10, 2) NOT NULL COMMENT '금액',
    ->     payment VARCHAR(50) NOT NULL COMMENT '결제수단',
    ->     address VARCHAR(100) COMMENT '주소'
    -> );
Query OK, 0 rows affected (0.013 sec)

MariaDB [team1]> show tables;
+-----------------+
| Tables_in_team1 |
+-----------------+
| receipt         |
+-----------------+
1 row in set (0.001 sec)


MariaDB [team1]> select * from receipt;
+-----+------------+--------+------------+--------------+---------------------+
| num | date       | name   | amount     | payment      | address
  |
+-----+------------+--------+------------+--------------+---------------------+
|   1 | 2024-10-01 | Laptop | 1500000.00 | 신용카드     | 서울시 서초구       |
+-----+------------+--------+------------+--------------+---------------------+
1 row in set (0.001 sec)

 

여기까지의 과정을 Issue에 저장해둠.

https://github.com/DE32-3nd-team1/DE32-3nd-team1/issues/4

 

DB TABLE 생성 · Issue #4 · DE32-3nd-team1/DE32-3nd-team1

AWS 서버 접속 $ ssh -i samdulko.pem ubuntu@52.78.215.75 docker run $ sudo docker run -d \ --name mariadb \ -e MARIADB_USER=team1 \ --env MARIADB_PASSWORD=1234 \ --env MARIADB_DATABASE=team1 \ --env MAR...

github.com

 


airflow는 아직 선행 기능들이 구현되지 않았기 때문에 큰 틀만 만들어두었다.

그리고 프로젝트 첫 쨋날 목표는 에어플로우 기능 자체를 도커 이미지로 빌드하는 것 이다.

방법을 찾아보았는데, AIFFLOW는 일반적으로 웹서버, 데이터베이스, 스케줄러 등 여러 컴포넌트를 동시에 운영해야 하므로, Docker Compose를 사용하는 것이 적합하다고 해서, 컴포즈를 사용하여 이미지 빌드를 시도했다.

 

따라서 프로젝트 첫쨋 날 오후에는 yml파일을 작성했었다.

내용 이해는 완벽하게 하지는 못했지만 yml파일에 여러 이미지를 선언해서 $docker compose build ~  같은 명령어로 수행했는데 원하는대로 작동하지 않았다. yml 파일도 100% 이해하지 못하고 작성해서 오류 해결을 하지 못한채 집에 갔다..

 

그러고나서 주말에 관련 정보를 좀 찾아봤다.

https://velog.io/@moon_happy/%EB%8F%84%EC%BB%A4%EC%97%90%EC%84%9C-Airflow-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0#-%EB%8F%84%EC%BB%A4%ED%8C%8C%EC%9D%BC-%EB%A7%8C%EB%93%A4%EA%B8%B0

 

도커에서 Airflow 시작하기

처음 로컬 컴퓨터에서 Airflow를 할때 환경의 일관성 부족이라던지, 로컬환경과의 충돌등의 문제로 도커에서 하게된다면 이러한 문제들을 해결할수 있지 않을까 라는 생각을 했습니다.

velog.io

이 블로그를 참고했다.

결론 먼저 얘기하자면 docker compose를 사용하지 않고 docker run 옵션으로 여러 컴포넌트를 동시에 수행하는 방법도 있었다.

먼저 Dockerfile 작성

$ cat Dockerfile

FROM apache/airflow:2.6.1
USER root
RUN apt-get update \
  && apt-get install -y --no-install-recommends \
     	vim \
  && apt-get autoremove -yqq --purge \
  && apt-get clean \
  && rm -rf /var/lib/apt/lists/*
USER "${AIRFLOW_UID:-50000}:0"

 

 

  • apache Airflow 2.6.1 이미지를 기반으로 사용한다.
  • 사용 권한을 루트로 바꾸어 vim 패키지 설치 : 최적의 상태(옵션 패키지 제외 필수 패키지만 설치, 패키지 캐시 정리 등)로 설치
  • 다시 Airflow 사용자로 되돌리기 (보안 등 이유)

[도커 이미지 빌드]

$ docker build -t airflow:0.1.0 .

 

[도커 컨테이너 실행]

docker run -d -p 8307:8080 
-v ~/code/docker_airflow/airflow/dags/:/opt/airflow/dags/ 
--entrypoint=/bin/bash 
--name airflow_docker airflow:0.1.0 
-c '(airflow db init && airflow users create --username admin --password admin --firstname Anonymous --lastname Admin --role Admin --email test@test.com); airflow webserver & airflow scheduler'

 

  • --entrypoint=/bin/bash

컨테이너가 시작될 때 기본적으로 실행할 명령어를 /bin/bash로 변경한다.

 

  • -c 옵션

bash를 통해 실행하는 옵션이다.

- airflow db init : Airflow 데이터베이스를 초기화

 

- airflow users create --username admin --password admin --firstname Anonymous --lastname Admin --role Admin --email test@test.com 

 : Admin 사용자 계정을 생성

 

- airflow webserver & airflow scheduler: 웹서버 & 스케줄러 실행

 

[에어플로우 웹서버 접속]

-p 옵션에서 8307로 지정했기 때문에 localhost:8307에 접속하고

-c 옵션에서 설정한대로 ID: admin PW: admin으로 로그인한다.

-v 옵션에서 연결한 저장소대로 dag 파일은 ~/code/docker_airflow/airflow/dags/ 에 생성하면 /opt/airflow/dags/ 저장소와 연동되어 웹서버에서 dag 를 확인할 수 있다.

* 도넛 모델의 성능이 너무너무 별로여서 도현님이 업그레이드 중 이다.. 나중에 어케 했는지 물어봐야지


DAY 2

오늘의 문제1

requirement랑 pip install <github>가 이해가 안됐다.

그래서 도커파일을 챗지피티에게 물어보며 작성해봐도 계속해서 오류가 났다.

 

내가 이해한 걸 기록해보자면

1. requirement.txt

# Dockerfile
COPY requirements.txt /requirements.txt
RUN pip install --no-cache-dir -r /requirements.txt

# requeirment.txt
donut-python
Pillow
torch

 

requirements.txt 는 pdm init 할 때 자동생성 될 수도 있고 그냥 만들어도 된다.

txt파일에 있는 패키지들을 설치하는 명령이 RUN pip ~ 부분이다.

설치될 패키지를 명시하는? 그런 것..

 

 

2. git hub

# Docerfile
RUN pip install --no-cache-dir --upgrade git+<github 주소>

# toml
dependencies = [
donut-python
Pillow
torch
]

 

pdm add <패키지명>을 통해 패키지를 설치하면 toml 파일의 dependencies에 저장된다.

이 디렉토리와 연결된 깃헙 주소를 지정하면서 그 레포를 설치하니까 의존성에 의해서 설치되는..?

말이 복잡한데 암튼 !

 

나는 이걸 이해못해서 하루종일 헤매다가  첫 번째 방식으로 선택해서 구현했다.

 

그리고  pip install 사용 시 에어플로우를 도커에 설치하느라 바꿨던 루트 사용자에서 airflow 사용자로 변경도 해주어야 한다.

 

오늘의 문제2

도넛 모델 적용 코드 패키지로 활용하기

사실 위에서 얘기했던 requirements도 도넛 모델 때문에 필요한 패키지들이다.

이렇게 생긴 구성에서 from model import <함수명> 해서 불러와서 amount.py(dag 파일)에서 사용하고 싶었다.

근데 계속 실패했다.

이건 pip install 깃헙 방법을 사용했고, __init__ 위치도 바꾸어서 해주었는데 임포트가 실행되지 않았다.

아직 이유 모름.................

 

해결한 방법은 그냥 amount.py에 함수를 작성했다.

 

테스트 데이터로 실행시켰을 때 모델 예측 결과가 나오는 것을 확인하고 마무리했다.

DAY3-4

마지막 날은 실제 프론트엔드에서 이미지 파일을 업로드하면 이미지 파일 경로를 받아와서 모델을 적용시키고 결과를 테이블에 업데이트가 목표였는데 완성하지 못해서 연휴를 사용해 시간을 좀 더 투자했다...........

 

 

가장 큰 문제점은 서버 용량이나 cpu 문제였다.

만약에 3개 이상의 이미지가 쌓여서 이 이미지들을 처리하려고 하니까 서버가 계속 멈췄다.

그래서 이미지 하나씩만 처리하도록 했다.

 

원래 처리하고 싶었던 방식은 다음과 같다.

1. create_mariadb_connection : mariadb와 연결

2. fetch_data : model table 특정 데이터 리턴

3. donut : 2 단계에서 리턴된 데이터를 모델에 적용시키고 예측 결과 리턴

4. to.goods : 3 리턴 값을 goods 테이블에 추가

 

2단계를 조금 더 자세히 보자면.

이런 모델 테이블이 있을 때 predict_bool(모델 사용 여부 :1(처리완료) , 0(미완료) ) 이 0인 행들을 리턴하고자 했다.

위의 사진에서는 id가 32,33,34인 행을 리턴하는 것 이다.

 

3단계에서는 반복문을 사용해서 3개의 이미지 파일을 순차적으로 처리하고 결과를 리턴하고자 했다. 근데 모델 적용 단계에서 서버가 계속 다운되었다. 그래서 강사님께 서버 재실행을 부탁드려야하나..했는데 새벽이라 그럴 수 없어서 일단 그냥 뒀는데 시간이 지나니까 정상 작동 되었다. 완전 다운되는건 아니고 실행되는 중에는 너~~무 느려져서 그런건가? 암튼...... 

내가 선택한 방법은 "LIMIT 1"을 통해 한 개의 행만 리턴해서 사용하는 것 이다. 이 방식의 단점을 조금이라도 보완하기 위해 원래 계획했던 에어플로우 실행주기보다 훨씬 줄여서 1분 단위로 실행되도록 설정했다.

 

그리고, 또 구현하고 싶었던것은 에어플로우 태스크 실행 4단계에서 DB연결(1단계)가 중복되는 작업이라고 생각해서 BranchOP를 사용하여 연결되어있으면 연결 작업을 생략하고, 연결이 되어있지 않으면 수행하는 작업을 해보고싶었다. 근데 알고보니 "dag run" 또는 "dag exec" 끼리는 독립적이어서 수행 할 때마다 DB 연결을 해줘야한다고 했다. 좀 복잡했는데 럭키비키..🍀

 

이렇게 내가 맡은 에어플로우 부분을 마무리했다.

 


느낀점

우선 좋았던 점 몇가지가 있다.

1. 프로젝트 초반, 설계를 굉장히 오래했다. 이렇게 시간을 많이 투자해도 되나..? 싶을 정도로 오래했는데 그러다 보니 더 체계적으로 요구사항이 정리되는 느낌이었다. 나중에는 더 큰 규모의 프로젝트를 수행하게 될 텐데 이런식으로 회의를 진행해서 틀을 잡아가면 되지 않을까 싶다.

 

2.기능 구현이 엄청 순조롭게 진행되지는 않았는데, 큼직한 부분 하나씩 성공할 때마다 팀원들이 "굿" , "👍👍" 등등... 리액션을 해줬는데(말로 해줬다 ㅎㅎ) 이거 뭔가 기분좋았다. 그래서 이슈에 반응을 잘 달아주라는 건가..@!!!

 

3. 지금까지의 모든 프로젝트에서 에어플로우를 맡았다. 점점 익숙해지는 거 같기도 하다.

 

아쉬웠던 점

1. 기능 구현을 못했던 모든 부분 !!!

2. 프로젝트 데드라인을 못지켰다. 연휴 없었으면 발표도 못할 뻔 했다.

3. 여전히 내가 맡은 부분 빼고는 하나도 관여하지 못했다. 

4. 발표 너무 어렵고 연습한대로 말이 안나온다.

 

배운점

1. 나는 xcom을 사용해서 에어플로우 task간 데이터를 주고받았다. 강사님이 log 남겨서 수행해라는 것 이해를 못했는데 알고보니 xcom은 디버깅이 어려워서 현업에서도 많이 사용하지 않는다고 한다. 카프카의 악몽이 떠올랐다 ~~ . xcom이라는 기능을 알게된 것도 좋았고 어떤 단점이 있는지 알게 된 것도 좋았다.

2. 에어플로우 괜히 도커로 실행했다 싶었지만 도커 이제 진짜 이해 완료다 👍