판단 모델 'Laya'를 사용해 학생 질문을 대학 담당 부서로 연결하기
요약
본 기사는 판단 모델(Decision Model) 'Laya'를 활용하여 학생의 질문을 대학의 적절한 담당 부서로 자동 분류하는 시스템 구축 과정을 소개합니다. Laya는 상황, 질문, 선택지를 입력받아 후보별 확률과 최적의 선택 결과를 반환하며, 이를 통해 자연어 질의응답 기반의 문의 창구 안내 시스템을 구현할 수 있습니다.
핵심 포인트
- Laya 모델은 주어진 상황/질문으로부터 가장 적합한 선택지(부서)를 판단합니다.
- 다국어 지원이 가능한 Laya-multilingual 모델을 사용하여 일본어 질문 처리에 활용했습니다.
- 단순 키워드 매칭 대신, 문맥적 어려움을 파악하여 부서를 안내하는 것이 핵심입니다.
학생의 질문을 대학 담당 부서에 연결하기
"수강 등록 사이트에 로그인할 수 없습니다. 비밀번호를 잊었습니다."
이러한 질문을 대학의 어느 부서에 문의해야 할까요?
'수강 등록(履修登録)'이라는 단어만 보면 교무과가 떠오르지만, 문제가 된 것은 비밀번호입니다.
반면, '수강 등록 사이트에는 접속할 수 있지만, 필수 과목을 선택할 수 없습니다'라는 질문이라면, 수강 등록 담당 부서로 안내하고 싶어집니다.
질문에 포함된 단어뿐만 아니라, 무엇에 어려움을 겪고 있는지를 읽어서 분류해야 합니다.
Jeff의 기사에서는 문장으로부터 조명 조작을 선택하게 했고, Clef의 기사에서는 이미지에 고양이가 있는지 판단하게 했습니다.
이번에는 Laya라는 판단 모델(Decision Model)을 사용하여 일본어 질문으로부터 대학 문의 창구를 선택하는 프로그램을 만들어 보았습니다.
Google Colab의 T4 GPU에서 실행한 결과, 준비된 9건의 질문 중 8건은 참조처와 일치했습니다.
다만, 담당 업무를 안내할 때 오류가 발생한 사례도 있었습니다.
나아가 장학금 담당 부서를 변경하는 비교 테스트도 진행하고 있습니다.
본 기사에서는 가상의 대학 창구 안내, 실행한 코드, 저장된 결과를 소개합니다.
Laya는 선택 결과를 반환하는 판단 모델
문의를 분류할 때 프로그램이 필요한 것은 '교무과', '정보 시스템과'와 같은 부서 이름입니다.
Laya에는 상황(situation), 질문(question), 그리고 선택지(choice)가 주어집니다.
모델은 선택지를 평가하여 후보별 확률과 선택 결과를 반환합니다.
이러한 용도의 모델을 여기서는 판단 모델 (Decision Model) 이라고 부릅니다.
이번에 사용할 것은 Convai Innovations에서 공개하는 convaiinnovations/laya-multilingual입니다.
공식 자료에 따르면, mmBERT-base를 기반으로 한 약 3.22억 개의 파라미터를 가진 다국어 모델이며, 문장이나 JSON을 입력할 수 있습니다.
일본어 문의를 처리하기 위해 영어용 모델이 아닌 다국어 버전을 선택했습니다.
Laya를 알게 된 계기가 된 receptron/laya는 Node.js나 TypeScript에서 ONNX Runtime으로 Laya를 구동하는 패키지입니다.
이번 Colab에서는 모델 개발사에서 사용하는 Python 패키지를 사용합니다.
같은 Laya를 다루지만, 본 기사에서 사용할 실행 방법은 Python입니다.
Laya에는 선택식인 choice, 단계 평가의 score, 참/거짓을 묻는 noul이 있습니다.
이번에는 choice만 사용합니다.
설명문을 생성하여 거기서 부서 이름을 추출하는 처리는 필요 없고, 반환된 키를 그대로 Python에서 다룰 수 있습니다.
다만, 부서 이름이 올바른 형식으로 반환되는 것과 적절한 부서를 선택하는 것은 별개의 문제입니다.
가상의 대학 창구 안내 준비하기
실제 대학에서는 학무와 교무의 담당 범위도, 부서 이름도 다릅니다.
이번에는 가상의 '아오조라 대학교(青空大学)'를 설정했습니다.
아래 내용은 실험을 위한 담당 분배이며, 실존하는 대학 안내가 아닙니다.
| 부서 | 이 대학에서의 담당 |
|---|---|
| 교무과 | 수강 등록, 수업, 시험, 학점 인정. 인턴십의 학점 인정도 포함 |
| ... | |
| 모델에는 학생의 질문뿐만 아니라 이 창구 안내도 함께 전달합니다. |
일반적인 부서명 지식에서 추론하게 하는 것보다, 이 대학에서 정한 담당에 따르기를 원하기 때문입니다.
'종합 안내(総合案内)'도 하나의 선택지로 준비했습니다.
모든 질문을 전문 부서로 억지로 분류하는 구성은 아닙니다.
다만, 종합 안내를 적절할 때 선택할 수 있는지 여부도 이번에 확인할 대상입니다.
실행한 환경
첨부된 실행 완료 노트북에는 다음 조건이 기록되어 있습니다.
| 항목 | 이번의 설정 또는 출력 |
|---|---|
| 실행 환경 | Google Colab |
| ... | 추론 시 max_len |
| 2048 | |
추론 시 head_max_len | |
| 512 | |
| 추가 학습 | 없음 |
| 외부의 추론 API | 사용하지 않음 |
이 환경에서 모델 로드와 추론이 완료되었습니다.
Python과 PyTorch 버전도 마지막 저장 셀에서 JSON으로 출력하는 구성입니다.
위 표에서는 노트북 표시로 확인된 정보와 코드상의 지정을 나누어 보여주었습니다.
모델을 Colab 내부로 불러오기 때문에 API 키는 필요하지 않습니다.
모델 가중치는 Apache 2.0 라이선스로 공개되어 있습니다.
Colab GPU에는 이용 제한이 있어, 같은 GPU가 언제든 사용 가능하다는 보장은 없습니다.
Colab 공식 FAQ
Colab에서 모델 불러오기
Colab의 '런타임 유형 변경'에서 T4 GPU를 선택하고, 아래 내용을 순서대로 실행합니다.
추가적인 이미지나 데이터 파일은 필요하지 않습니다.
1. 라이브러리 설치하기
import os
os.environ["USE_TF"] = "0" # 이 교재에서는 TensorFlow를 사용하지 않습니다.
%pip install -q "laya==0.4.0" "transformers==5.19.0"
USE_TF=0
은 이 교재에서 사용하지 않는 TensorFlow의 로드를 피하기 위한 설정입니다.
Laya와 Transformers의 버전을 고정했습니다.
다른 교재에서 라이브러리를 변경한 런타임을 재사용하는 것보다, 새로운 런타임에서 시도하는 것이 조건을 맞추기 쉽습니다.
2. 다국어 모델 불러오기
import json
import platform
import importlib.metadata
...
GPU를 사용할 수 없는 경우, CPU로 전환되도록 했습니다.
이번 로그에는 다음 표시가 남아 있습니다.
실행 위치: Tesla T4
Laya: 0.4.0
모델 준비 완료.
REVISION
은 모델 배포 파일을 고정하기 위한 지정입니다.
모델 업데이트에 따라 결과가 달라지는 경우에도, 사용한 버전을 확인할 수 있습니다.
안내 창구를 Python 딕셔너리로 만들기
앞서의 담당 업무를 그대로 딕셔너리로 만듭니다.
왼쪽이 부서명, 오른쪽이 담당 업무입니다.
OFFICES = {
"교무과": "수강 신청, 수업, 시험, 학점 인정. 인턴십의 학점 인정도 담당합니다.",
"학무과": "장학금, 학생 생활, 동아리, 과외 활동.",
...
문의처를 선택하는 조건은 이 딕셔너리에 작성된 것입니다.
예를 들어, 인턴십의 학점 인정은 교무과, 지원 서류 첨삭은 커리어 지원과로 명시했습니다.
이렇게 이름이 비슷한 용건이라도 담당 부서가 나뉘는 예를 넣으면, 단순히 '인턴십'이라는 단어에 반응하는 것인지, 용건에 따라 선택하고 있는 것인지를 관찰할 수 있습니다.
질문으로부터 담당 부서를 선택하는 함수 작성하기
문의처를 선택하는 함수의 전체 내용입니다.
모델에 대한 입력을 만들고, 결과를 표시하며, 나중에 저장하기 위해 기록합니다.
records = []
def choose_office(student_question, offices=None, guide_name="일반 안내", expected=None):
if offices is None:
...
핵심이 되는 것은 agent.predict()의 호출입니다.
인수를 나누어 보면 다음 대응 관계가 됩니다.
| 입력 | 내용 |
|---|---|
state | 대학명, 안내 창구, 학생의 질문 |
instructions | 안내에 따라 부서를 하나 선택하라는 지시 |
criteria | 선택 가능한 부서명과 담당 업무 |
이번에는 안내를 state와 criteria 양쪽에 넣었습니다.
상황으로 대학의 규칙을 전달하고, 선택지에도 담당 업무를 덧붙이는 구성입니다.
이 중복이 최적인지는 이번에 비교하지 않았습니다.
max_len과 head_max_len은 입력 토큰 수의 상한과 관련된 설정입니다.
일본어 담당 업무가 포함되어 있어, 이번 호출에서는 2048과 512를 지정했습니다.
모델이 입력 잘림을 보고했다면 주의를 표시합니다.
Laya의 입력 예산 및 이용 방법은 공식 Python 구현에서 설명하고 있습니다.
표시되는 '담당 업무'는 선택된 부서의 안내문을 딕셔너리에서 가져온 것입니다.
모델이 판단 이유를 설명한 문장이 아닙니다.
또한, expected는 확인용 참조처이며, 모델 입력에는 포함하지 않았습니다.
자신의 질문을 하나 넣어보기
처음에는 수강 신청 사이트의 비밀번호를 잊어버린 경우입니다.
student_question = "수강 신청 사이트에 로그인할 수 없습니다. 비밀번호를 잊었습니다." #@param {type:"string"}
result = choose_office(student_question)
display(pd.DataFrame(
...
결과는 다음과 같았습니다.
部署별 출력값도 확인할 수 있습니다.
| 부서 | 모델의 출력 확률 |
|---|---|
| 정보시스템과 | 71.43% |
| ... | |
| 이번 안내에서는, 로그인할 수 없는 문제는 정보시스템과의 담당입니다. |
이 입력에서는, 그 참조처를 선택할 수 있습니다.
여기서 표시하는 것은 probabilities의 값입니다.
Laya가 반환하는 다른 항목인 confidence와 혼동하지 않도록 했습니다.
또한, 이 출력값을 상담이 올바르게 분류되었다는 확률로 무조건 신뢰할 수도 없습니다.
9건의 질문을 모아서 테스트하기
다음으로는, 비슷한 단어를 포함하는 질문과 담당 부서가 명확하지 않은 질문을 모아서 테스트하겠습니다.
TEST_CASES = [
("수강신청 사이트에 로그인할 수 없습니다. 비밀번호를 잊었습니다.", "정보시스템과"),
("수강신청 사이트에는 들어갈 수 있지만, 필수 과목을 선택할 수 없습니다.", "교무과"),
...
T4 GPU에서의 결과는 다음과 같습니다.
표의 확률은, 선택된 부서에 대응하는 probabilities 값입니다.
| 질문 | 참조처 | 선택 결과 | 선택된 후보의 확률 | 일치 |
|---|---|---|---|
| 수강신청 사이트에 로그인할 수 없습니다. 비밀번호를 잊었습니다. | 정보시스템과 | 정보시스템과 | 71.4% | ○ |
| ... |
9건 중 8건이 참조처와 일치했습니다.
이는 교재로 준비한 소수 사례에서의 결과입니다.
실제 대학에 도착하는 문의를 모은 평가가 아니므로, "대학의 문의를 약 89%의 정확도로 분류할 수 있다"고 말할 수는 없습니다.
같은 '수강신청 사이트'라도 문의처가 나뉘었습니다
비밀번호를 잊었다는 질문에서는 정보시스템과, 필수 과목을 선택할 수 없다는 질문에서는 교무과가 되었습니다.
이 두 건에서는, 같은 사이트에 대한 상담이라도 용건에 따른 담당 부서를 선택할 수 있었습니다.
지원 서류 상담은 종합안내로 갔습니다
한편, 인턴십 지원 서류를 봐달라는 질문에서는, 종합안내가 선택되었습니다.
안내에는 커리어지원과가 지원 서류의 첨삭을 담당한다고 쓰여 있습니다.
이번에는 명시된 담당 업무에 맞는 창구를 선택할 수 없었습니다.
그때, 선택된 종합안내의 출력값은 **96.2%**였습니다.
모델이 망설이는 듯한 낮은 값에서의 실패는 아닙니다.
왜 종합안내로 강하게 치우쳤는지에 대해서는, 이 결과만으로는 알 수 없습니다.
참조처와 일치해도, 확률이 높다고 할 수는 없다
반대로, 인턴십의 학점 인정은 교무과를 선택할 수 있지만, 그 후보 값은 28.8%입니다.
동아리 상담도, 학무과를 선택한 값은 36.7%였습니다.

파란색은 참조처와의 일치, 빨간색은 불일치를 나타냅니다. 막대의 길이는 정답률이 아니라, 선택된 후보의 모델 출력입니다.
낮은 값이라면 사람에게 확인하는 처리는 작성할 수 있습니다.
하지만, 이번 지원 서류의 오판정은 96.2%이므로, 낮은 확률의 결과를 보류만 해서는 제거할 수 없습니다.
공식 모델 카드도, 다국어 버전의 확률에 과신하는 경향이 있음을 설명하고 있습니다.
다국어 버전의 제약
장학금 담당 부서를 변경한다
실제 창구 안내에서는, 조직 개편으로 인해 담당이 바뀔 수 있습니다.
그래서, 같은 질문에 대해, 안내만 변경하는 비교를 시도했습니다.
변경 전에는 학무과가 장학금을 담당합니다.
변경 후에는 '장학금지원실'을 신설하고, 학무과의 설명에도 "장학금은 담당하지 않는다"라고 씁니다.
NEW_OFFICES = dict(OFFICES)
NEW_OFFICES["학무과"] = "학생 생활, 동아리, 과외 활동. 장학금은 담당하지 않는다。"
NEW_OFFICES["장학금지원실"] = "장학금의 신청, 지속 신청, 장학금에 관한 상담。"
...
기대하는 변화는 "학무과 → 장학금지원실"입니다.
실제 출력은 다음과 같았습니다.
【변경 전】
문의처: 학무과
선택된 후보의 확률: 47.7%
...
변경 후에는, 원래의 학무과는 다른 부서를 선택했지만, 신설된 장학금지원실은 아니었습니다.
이 비교에서는, 입력한 담당 변경에 올바르게 따르지 못했습니다.
여기서는 추가 학습을 하지 않았습니다.
변경된 것은, 매번 모델에게 전달하는 창구 안내와 선택지입니다.
또한, 부서를 신설했기 때문에 선택지 수도 5개에서 6개로 늘어났습니다.
담당 업무의 변경과 선택지 추가를 동시에 진행하고 있기 때문에, 어느 쪽이 실패에 영향을 미쳤는지는 이번 한 번으로는 분리할 수 없습니다.
이번 처리는 RAG나 Fine-tuning인가
이번 프로그램은 짧은 창구 안내문 전체를 질문과 함께 매번 전달합니다.
안내문을 검색하는 처리 과정도 없고, 모델의 가중치(weight)도 업데이트하지 않았습니다.
따라서 이번에는 RAG도 Fine-tuning도 진행하지 않았습니다.
부서나 규정이 늘어난 경우에는, 질문과 관련된 안내문을 검색한 후 모델에 전달하는 구성으로 만들 수 있습니다.
이것이 RAG로 나아갈 방향입니다.
다만, 이번에는 관련 담당 업무를 이미 입력했음에도 오판이 있었습니다.
검색을 추가하는 것만으로 해결될 것이라고 기대하기는 이르며, 필요한 안내문을 가져올 수 있었는지와, 가져온 안내문으로부터 올바르게 선택할 수 있었는지를 나누어 확인할 필요가 있습니다.
과거 문의 내용과 담당 부서가 모이면, 대학 고유의 사례로 추가 학습(additional learning)하는 방법도 생각할 수 있습니다.
Laya 공식 리포지토리에는 추가 학습 자료가 있지만, 이 일본어 대학 창구 과제에서 효과가 있을지는 아직 시험해 보지 않았습니다.
공식 리포지토리의 Fine-Tuning 설명
결과와 조건을 저장하기
마지막으로, 결과를 CSV와 JSON에 저장합니다.
나중에 담당 업무나 질문문을 변경했을 경우에도, 어떤 안내문에서 어떤 결과가 나왔는지 확인할 수 있도록 합니다.
import zipfile
environment = {
"recorded_at_utc": datetime.now(timezone.utc).isoformat(),
...
CSV는 질문별 결과를 표로 읽기 위해 사용됩니다.
JSON에는 창구 안내문, 모델의 전체 출력, 실행 환경이 들어갑니다.
같은 셀을 재실행하면 기록이 추가되기 때문에, 기사(article) 개수를 셀 때는 어떤 실행을 집계했는지도 확인합니다.
이번 '9건 중 8건'은 일괄 실행한 예제 9건만의 결과입니다.
첫 번째 단독 사례나, 담당 변경 전후의 비교는 그 9건에 가산되지 않았습니다.
참고 자료
Discussion

AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기