평소와 같이 Github를 확인하던 중, Trending Repository에서 Dify를 찾게 되었다. 설명을 보니 오픈소스 LLM 앱 개발 플랫폼이라고 적혀 있었다. 설명만 보고는 LLM 자체를 만드는 플랫폼인줄 알았지만, 내용을 보니 LLM을 활용해서 앱을 만들 수 있도록 도와주는 플랫폼이였다.
이 소개영상을 확인한 이후에 현혹되어서 레포지토리에 별을 날리고는 설치를 진행했다.
git clone https://github.com/langgenius/dify.git
cd dify/docker
cp .env.example .env
docker compose up -d # 작동하지 않는다면 docker-compose up -d 로 사용!
설치가 완료되고 나니 80번 포트로 자동으로 웹 서버가 열렸다. 계정을 만들고 난 후 처음 본 화면에는 다양한 예시 앱들이 있었다.
이 중 몇가지를 받아 내부 구조를 보니 사용법이 쉽게 이해되었다. 코드로 RAG LLM 앱을 만들어 본 적은 없지만, 노드끼리 연결하여 앱을 구성하는 과정이 정말 잘 만들어졌다는 것이 체감되었다.
사용해보기
본격적인 사용에 앞서, LLM모델과 임베딩 모델이 하나씩 필요했다. OpenAI나 Gemini등 대기업의 API를 사용해도 괜찮지만, Ollama 를 이용해 직접 llm을 서빙하기로 했다. 한국어로 서비스를 제공해야 했기 때문에 KoLLM Leaderboard 에서 한국어 성능이 괜찮은 것 중 8b 이하의 크기 모델로 골랐다. 그렇게 openbuddy-llama3-8b 모델을 선택하였다. 이 모델은 Ollama에도 올라가 있었기 때문에 별도의 변환 과정 없이 즉시 사용할 수 있었다. 3.1-8b 도 있었지만 아직 사용해 보진 않았다.
그렇게, LLM모델은 해결하였지만 임베딩 모델이 문제였다. Ollama에서도 텍스트 임베딩 모델을 구동할 수 있지만, LLM과 같이 구동하기에는 VRAM이 너무 작았다. 그렇다고 작은 임베딩 모델을 사용하니 한국어를 제대로 못 알아먹는듯 했다.
마침 안 쓰는 미니PC를 활용하고자, 데비안을 설치하고 open-text-embeddings를 사용해 openAI 호환 임베딩 서버를 열었다. 여기에서도 모델은 한국어 임베딩 성능이 좋고 크기가 작은 intfloat/multilingual-e5-large 모델을 선택하였다. Dify를 구동하는 컴퓨터와는 망이 분리되어 있어, Wireguard를 통해 연결해주었다.
Wireguard 타임아웃 이슈
Wireguard를 연결하고 5분 정도는 괜찮은데, 그 이후부터 timeout 오류가 나는 문제가 발생했다.
// /etc/wireguard/wg0.conf
PersistentKeepalive = 30
다음과 같이 30초마다 패킷을 보내게 처리하니 해결되었다.
다음과 같이 LLM모델과 임베딩 모델을 연결시켜 주었다. 재랭크 모델과 STT모델, TTS모델은 나중에 필요하면 하는걸로.(ARS만드는거 아니면 필요없을것 같다)
진짜 사용해보기
처음 앱을 만들 때에는 다음과 같이 앱의 카테고리를 고르게 된다. 챗봇 중에서도 기본 모드와 Chatflow 모드가 있는데, Chatflow 모드가 아까 본 것처럼 노드들을 사용해 챗봇을 구성하게 된다.
Chatflow 모드로 들어오게 되면 다음과 같은 블록들을 조합해서 애플리케이션을 만들게 된다. 추가적으로 서드파티 블록도 사용할 수 있다. (아직 DuckDuckGo 밖에 못 써봤다.) Dify는 주로 RAG 시스템과 LLM을 함께 사용하려고 만들어진 것 같다. RAG란, 쉽게 말해 LLM에게 검색 엔진을 붙여 주는 것인데, 주로 회사 내부 문서 자료 등을 자료로 집어넣고, 자료를 활용해서 응답을 받을 수 있도록 하는 뭐,, 그런거다. 회사에서도 채팅 상담용으로 꽤나 관심을 보인다고 한다.
다시 본론으로 돌아와서, 기본 블록 중 지식 검색 블록을 사용해야 하는데, 검색을 하려면 지식부터 만들어야 합니다.
상단 지식 탭에서 새 지식을 생성합니다. 파일을 넣을 수도 있고, Notion 페이지를 동기화시키거나 웹 크롤링을 할 수도 있습니다.
저는 다음과 같이 학교에 관한 공개된 문서들을 여러개 넣었으며, 임베딩 모델은 위에서 설정한 대로, intfloat/multilingual-e5-large 모델을 그대로 사용했습니다.
처음에는 이렇게, 단순히 사용자 쿼리를 가지고 검색을 시도했는데, 사용자의 쿼리가 복잡해지고 문장 형태가 될 수록 임베딩 모델이 알맞는 자료를 못 찾는 일이 발생했습니다.
그래서 다음과 같이, 매개변수 추출기라는 것을 사용하여 LLM으로 검색어를 추출하고, Javascript코드를 넣어 검색어를 정제시킨 후 검색어가 있는 경우에만 검색을 진행하도록 했습니다.(검색어 없이 검색하면 오류나더라고요)
그렇게 완성했나 싶었지만, 이제는 검색이 제대로 안 되는 문제가 있었습니다. 분명 2024 방과후 운영계획 문서를 넣었지만 전혀 사용하지 않을 것을 볼 수 있습니다.
자료의 청크 크기를 늘려서 키워드를 많이 모아두고 어떻게든 검색결과에 걸리게 만들고, 문서 메타데이터 써주는 것이 도움이 되었지만, 그래도 여러 청크에 걸쳐서 자료가 흩뿌려져 있는 경우, 그런 자료들을 종합해서 정리해내지는 못했습니다. 일부 청크만 들고와서 일부의 자료만 정리해 보여주는 경우, 또는 일부 청크조차 키워드로 찾지 못하는 경우가 있었습니다.
문서 이름은 방과후 계획이지만, 문서 내용에는 방과후 관련 내용만 있고, ‘방과후’라는 키워드가 존재하지 않아서 청크 검색이 안되는 그런 상황도 있었습니다.
이러한 문제를 해결하기 위해 임베딩 모델도 바꿔보고, 임베딩과 키워드 간 가중치도 바꿔봤는데요, 확실히 해결되지 않아서, 나중에 Elastic Search 와 같은 외부 검색 엔진이나 검색용 AI를 따로 만들어 API요청을 보내는 방식으로 개선해야 할 것 같았습니다.
총평
간단히 사용해 보았지만, LLM을 사용한 앱을 코드 한줄 안 짜고서도 구축할 수 있는것은 대단한 장점인것 같습니다. 다만, 상용 제품을 만들기 위해서는 외부 api사용이나 코딩이 불가피해 보입니다. 앞으로 더욱 발전한다면 LLM에 대해서 약간의 공부만 한다면 누구나 LLM을 활용한 앱을 만들 수 있을 것 같다는 생각을 했습니다.
나중에 할 일
- Qwen2.5 모델 사용해보기
- Contextual Retrieval 공부하기
- 재랭크 모델 사용해보기
- 동시 접속자 5명까지 늘리기
답글 남기기