LLM 모델을 기반으로 반도체 검사 명령어를 이해하는 인터페이스 구성하기
최근 대규모 언어 모델(LLM)의 활용 범위가 넓어지면서, 이를 특정 도메인에 특화시켜 적용하는 흐름이 활발해졌다.
이번에는 반도체 검사 시스템을 대상으로, 자연어로 명령을 입력받아 시스템 내부 명령어 형태로 변환하는 인터페이스를 만들어보았다.
모델 여러 모델을 비교하여 보았지만 가장 빠르고 결과가 나쁘지 않았던 Hugging Face에 공개된 LGAI의 EXAONE-3.5-2.4B-Instruct를 사용하였다.
https://huggingface.co/LGAI-EXAONE/EXAONE-3.5-2.4B-Instruct
LGAI-EXAONE/EXAONE-3.5-2.4B-Instruct · Hugging Face
EXAONE-3.5-2.4B-Instruct Introduction We introduce EXAONE 3.5, a collection of instruction-tuned bilingual (English and Korean) generative models ranging from 2.4B to 32B parameters, developed and released by LG AI Research. EXAONE 3.5 language models incl
huggingface.co
이후에는 Flask와 Swagger 연동은 다음 글에서 다룰 예정이며, 이번 글에서는 모델과 추론 처리 로직 중심으로 설명한다.
배경
LLM으로 시스템 인터페이스를 구성하기로 생각한 이유는, 지난번 리뷰한 2022년에 발표된 Google에 로봇 시스템 SayCan 논문 덕분이었다.
[논문 리뷰] Do As I Can, Not As I Say:Grounding Language in Robotic Affordances (saycan)
이 리뷰는 오직 학습과 참고 목적으로 작성되었으며, 해당 논문을 통해 얻은 통찰력과 지식을 공유하고자 하는 의도에서 작성된 것입니다. 본 리뷰를 통해 수익을 창출하는 것이 아니라, 제 학
c0mputermaster.tistory.com
SayCan은 LLM(PaLM)으로부터 명령의 의미를 해석하고, 로봇의 물리적 제약과 상황을 고려해 가능한 행동만을 선택하는 방식으로 계획을 수립한다. 이 시스템은 고수준 명령어를 (1) Task Grounding과 (2) World Grounding을 통해 분해하고 평가함으로써,
실제 환경에서 실행 가능한 행동 시퀀스를 생성할 수 있게 한다.
→ 즉, LLM이 단순히 “무엇을 해야 하는지” 판단하는 데 그치지 않고, 실제 “할 수 있는지”를 함께 고려하는 방식이다.
이번 글에서는 이처럼 LLM과 실제 시스템의 연결을 목표로 하여, 자연어로 명령을 내리면
이를 시스템 내부에서 실행 가능한 함수 호출 형태의 명령어로 변환하는 인터페이스를 구현해보았다.
사용 기술
- PyTorch + HuggingFace Transformers
- 사전 학습된 EXAONE Instruct 모델
- GPU 환경 (BF16 지원)
- 도메인 특화 시스템 프롬프트
프로젝트 구성
간단한 파이썬 프로젝트의 구성은 다음과 같다.
- model_runner.py # 모델 로딩 및 실행 함수
- prompt_only.py # 시스템 프롬프트 정의
prompt_only.py
prompt_only.py에는 모델이 따라야 할 규칙을 시스템 프롬프트 형태로 정의하였다
system_prompt = """
너는 검사 시스템의 대화형 인터페이스야.
사용자가 명령을 내리면 다음과 같은 함수 호출 형태로만 응답해야 해:
open_teaching_window("LGA")
switch_mode("RUN")
설명 없이, 반드시 함수 호출만 줄 바꿈으로 나열해.
"""
이 프롬프트는 모델이 설명 없이 함수 호출만 반환하도록 강제하는 역할을 한다.
model_runner.py
이 파일은 모델을 로딩하고 사용자의 자연어 명령어를 받아 시스템 명령어 형태로 변환하는 핵심 로직을 포함하고 있다.
1. 모델 초기화
model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype=torch.bfloat16,
trust_remote_code=True
).to("cuda")
BF16 타입으로 GPU에 로딩하였고, EXAONE의 2.4B Instruct 버전을 사용하였다.
2. 입력 구성 및 토크나이징
messages = [
{"role": "system", "content": system_prompt},
{"role": "user", "content": prompt}
]
input_ids = tokenizer.apply_chat_template(
messages,
tokenize=True,
add_generation_prompt=True,
return_tensors="pt"
).to("cuda")
Hugging Face에서 제공하는 apply_chat_template()를 활용해 Chat 형식의 입력을 구성하였다.
3. 모델 추론 실행
output = model.generate(
input_ids,
eos_token_id=tokenizer.eos_token_id,
max_new_tokens=100,
do_sample=False
)
4. 후처리 로직 구현
모델 출력은 다음과 같은 형식으로 생성된다.
[|assistant|]switch_mode("RUN")
open_teaching_window("LGA")
이를 후처리하는 함수는 다음과 같이 구현하였다.
def extract_assistant_response(full_text: str) -> str:
match = re.search(r"\[\|assistant\|\](.+)", full_text, re.DOTALL)
if not match:
return full_text.strip()
lines = match.group(1).strip().splitlines()
clean_lines = [line.strip(" `") for line in lines if line.strip()]
return "\n".join(clean_lines)
줄바꿈 기준으로 분리한 뒤, 백틱(`)과 양쪽 공백을 제거하여 순수한 함수 호출 문자열만 남도록 처리하였다.
5. GPU 메모리 확인 및 결과 구성
allocated, reserved = get_gpu_memory()
return {
"output": assistant_only,
"elapsed_time": elapsed_time,
"gpu_memory": {
"allocated_mb": allocated,
"reserved_mb": reserved
}
}
추론 이후 현재 사용 중인 GPU 메모리 정보를 함께 반환하도록 구성하였다.
이는 디버깅이나 추론 부하 측정에 유용하다.
실행 예시
입력:
LGA 검사 시작해줘
출력:
{
"output": "switch_mode(\"RUN\")\n open_teaching_window(\"LGA\")",
"elapsed_time": 1.53,
"gpu_memory": {
"allocated_mb": 487.14,
"reserved_mb": 652.89
}
}
추가
Exaone 2.4B 모델과 7.8 모델을 비교해보았는데 CPU 환경이긴 했으나 테스트 결과 속도차이가 조금 있어 2.4B모델로 구성하였다.
다음 글에서는 이 모델 추론 로직을 Flask 기반의 API 서버로 감싸고,
Swagger UI를 통해 실시간으로 명령어를 입력하고 결과를 확인할 수 있도록 확장해볼 예정이다.
'LLM > Project' 카테고리의 다른 글
[NLP] FastText Python 바인딩 오류 해결하기 (0) | 2025.04.06 |
---|---|
[NLP] FastText로 간단한 텍스트 분류 모델 만들기 (0) | 2025.04.02 |