파이썬 업무 자동화#5로컬 LLM(LM Studio)으로 고객 문의 자동 분류·요약하기! (무료 AI)
목차10개 항목

안녕하세요! Mojangcam입니다 😎
지난 파이썬 업무 자동화 #4 - 디스코드 웹훅(Webhook)으로 알림 보내기에서는 파이썬이 디스코드로 먼저 알림을 보내게 만들어봤는데요. 오늘은 드디어 이 시리즈에 AI를 붙여볼 차례예요!
그런데 ChatGPT API는 쓸 때마다 요금이 나가고, 회사 문의 내용을 외부 서버로 보내는 것도 좀 찜찜하죠. 그래서 이번 편은 내 컴퓨터에서 공짜로 도는 로컬 LLM(LM Studio)으로 갑니다! 쌓여 있는 고객 문의를 자동으로 분류하고 요약하는 스크립트를 만들어볼게요. 문의 100건을 하나하나 읽고 "이건 환불 건, 이건 배송 문의..." 하고 나누던 작업이 스크립트 한 번 실행으로 끝나요. 요금 0원, 데이터 유출 걱정 0 💡
🧠 왜 로컬 LLM인가요?
- 무료·무제한: API 토큰 요금이 없어요. 밤새 10만 건을 돌려도 전기세만 나갑니다.
- 프라이버시: 고객 문의·사내 문서가 내 PC 밖으로 안 나가요.
- 호환성: LM Studio 서버는 OpenAI 호환 API라서, openai 파이썬 라이브러리를 그대로 쓰고 주소만 바꾸면 돼요. 나중에 유료 API로 갈아탈 때도 코드 몇 줄만 고치면 됩니다.
단점은 딱 하나, PC 사양을 좀 탄다는 거예요. 요즘 나오는 4B~8B급 경량 모델은 램 16GB 정도면 충분히 돌아갑니다.
📌 준비물
- Python 3.10 이상
- LM Studio (작성 기준 0.3.x — /v1/responses까지 지원하는 0.3.29 이상 권장) — lmstudio.ai에서 무료 다운로드
- openai 2.x (작성 기준 최신 2.53.0) + python-dotenv 1.x
pip install openai python-dotenv- 채팅 모델 1개 — LM Studio 안에서 다운로드해요. 한국어 되는 경량 모델(예: qwen/qwen3-4b 같은 4B~8B급)이면 충분합니다.
💬 참고: openai 라이브러리를 설치하지만 OpenAI에 가입하거나 결제할 필요는 없어요. LM Studio가 같은 규격의 API를 내 컴퓨터에서 열어주기 때문에, 라이브러리는 그냥 "통신 규격"으로만 쓰는 거예요!
📌 1단계 - LM Studio 설치하고 로컬 서버 켜기
- lmstudio.ai에서 설치 → 실행
- 돋보기(Discover) 탭에서 모델 검색 → 다운로드 (예: qwen3-4b)
- Developer 탭 → Start Server 클릭 — 기본 주소는 http://localhost:1234/v1 이에요
- 서버 설정에서 API 토큰을 걸 수 있어요(선택). 걸었다면 그 값을 잠시 복사해두세요.

📌 2단계 - .env 파일로 토큰·모델명 관리하기
토큰이나 모델명을 코드에 직접 적으면 코드 공유할 때 유출 위험도 있고, 바꿀 때마다 코드를 고쳐야 해서 번거로워요. 그래서 .env 파일에 따로 빼둡니다.
스크립트와 같은 폴더에 .env 파일을 만들고 이렇게 적어주세요.
LM_STUDIO_TOKEN=서버에-설정한-토큰
LMS_CHAT_MODEL=qwen/qwen3-4b그리고 파이썬에서 이렇게 불러옵니다.
from dotenv import load_dotenv
import os
load_dotenv() # 같은 폴더의 .env 파일을 읽어서 환경변수로 등록
token = os.getenv("LM_STUDIO_TOKEN")
model = os.getenv("LMS_CHAT_MODEL")하나씩 뜯어볼게요 💡
- load_dotenv() :
.env파일 내용을 환경변수로 올려주는 함수예요. os.getenv보다 먼저 호출해야 합니다! - os.getenv("이름") : 환경변수 값을 꺼내요. 없으면 에러 대신 None을 돌려줘요.
- LMS_CHAT_MODEL : LM Studio에 뜨는 모델 식별자를 그대로 적으면 돼요. 서버 켠 뒤 모델 목록에서 확인!
💡 팁:
.env는 비밀값 보관함이에요. 깃허브에 올릴 땐 꼭 .gitignore에 추가해서 같이 안 올라가게 하세요. (디스코드 봇 시리즈의 봇 토큰도 앞으로 이 방식으로 관리하면 좋아요!)
📌 3단계 - 첫 호출 해보기
from dotenv import load_dotenv
import os
from openai import OpenAI
load_dotenv()
token = os.getenv("LM_STUDIO_TOKEN")
model = os.getenv("LMS_CHAT_MODEL")
client = OpenAI(
base_url="http://localhost:1234/v1", # LM Studio 로컬 서버 주소
api_key=token,
)
response = client.chat.completions.create(
model=model,
messages=[{"role": "user", "content": "파이썬으로 할 수 있는 업무 자동화 3가지를 한 줄씩 알려줘"}],
)
print(response.choices[0].message.content)하나씩 뜯어볼게요 💡
- base_url : 이게 핵심이에요! OpenAI 서버 대신 내 컴퓨터(localhost:1234)로 요청을 보내게 만드는 한 줄입니다.
- api_key=token : .env에서 불러온 토큰이 들어가요. 서버에 토큰을 안 걸었다면 아무 문자열이나 넣어도 됩니다(비워두면 안 돼요).
- client.chat.completions.create() : OpenAI 호환 표준 호출이에요. LM Studio가 그대로 알아듣습니다.
- response.choices[0].message.content : 답변 텍스트가 들어있는 위치예요.
답변이 출력되면 내 PC에서 AI가 돌아간 겁니다! 🙌
📌 4단계 - 고객 문의 자동 분류·요약 함수 만들기
이제 진짜 업무에 써먹어볼게요. 문의 문장을 주면 카테고리·긴급도·한 줄 요약을 JSON으로 뽑아내는 함수를 만듭니다.
import json
SYSTEM_PROMPT = (
"당신은 고객 문의 분류 담당자입니다. 문의를 읽고 "
"category(배송/환불·교환/상품 문의/불만/기타), "
"urgency(높음/보통/낮음), summary(한 줄 요약) "
"세 개의 키를 가진 JSON만 출력하세요. 코드블록·설명 금지."
)
def classify_inquiry(client, model, text):
response = client.chat.completions.create(
model=model,
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": text},
],
temperature=0,
)
raw = response.choices[0].message.content.strip()
if raw.startswith("```"): # 혹시 코드블록으로 감싸서 오면 벗겨내기
raw = raw.strip("`").removeprefix("json").strip()
return json.loads(raw)하나씩 뜯어볼게요 💡
- system 역할 : 모델에게 주는 역할·규칙 지시문이에요. 로컬 경량 모델은 말을 잘 안 들을 때가 있어서 "JSON만 출력"을 강하게 박아줘야 파이썬에서 바로 파싱할 수 있어요.
- temperature=0 : 창의성을 끄는 옵션이에요. 분류 같은 작업은 매번 같은 형식으로 나와야 하니 0이 좋습니다.
- json.loads() : JSON 문자열을 파이썬 딕셔너리로 변환해요. 이제
result["category"]처럼 값을 꺼내 쓸 수 있죠!
📌 전체 코드 (복붙 OK)
# openai 2.x (작성 기준 2.53.0) / python-dotenv 1.x / LM Studio 0.3.29+ / Python 3.10+
# 실행 전: pip install openai python-dotenv → LM Studio 서버 켜기 → .env 작성
import csv
import json
import os
from dotenv import load_dotenv
from openai import OpenAI
load_dotenv()
token = os.getenv("LM_STUDIO_TOKEN")
model = os.getenv("LMS_CHAT_MODEL")
client = OpenAI(
base_url="http://localhost:1234/v1", # LM Studio 로컬 서버
api_key=token,
)
# 실무에서는 엑셀·메일 등에서 불러오면 돼요 (1편 openpyxl 참고!)
inquiries = [
"주문한 지 일주일이 넘었는데 아직도 배송 준비중이에요. 언제 오나요?",
"사이즈가 안 맞아서 교환하고 싶은데 절차가 어떻게 되나요?",
"상품 상세페이지랑 실제 색상이 너무 달라요. 환불해주세요. 별점 테러하기 전에 빨리요.",
"이 제품 재입고 계획 있나요? 알림 신청은 어디서 하나요?",
"결제가 두 번 된 것 같아요. 카드 명세서에 같은 금액이 두 번 찍혔습니다.",
]
SYSTEM_PROMPT = (
"당신은 고객 문의 분류 담당자입니다. 문의를 읽고 "
"category(배송/환불·교환/상품 문의/불만/기타), "
"urgency(높음/보통/낮음), summary(한 줄 요약) "
"세 개의 키를 가진 JSON만 출력하세요. 코드블록·설명 금지."
)
def classify_inquiry(client, model, text):
"""문의 1건을 분류·요약해 딕셔너리로 반환"""
response = client.chat.completions.create(
model=model,
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": text},
],
temperature=0,
)
raw = response.choices[0].message.content.strip()
if raw.startswith("```"): # 혹시 코드블록으로 감싸서 오면 벗겨내기
raw = raw.strip("`").removeprefix("json").strip()
return json.loads(raw)
results = []
for i, text in enumerate(inquiries, start=1):
item = classify_inquiry(client, model, text)
item["원문"] = text
results.append(item)
print(f"[{i}/{len(inquiries)}] {item['category']} / 긴급도 {item['urgency']} - {item['summary']}")
# CSV로 저장 (엑셀에서 바로 열려요)
with open("문의_분류_결과.csv", "w", newline="", encoding="utf-8-sig") as f:
writer = csv.DictWriter(f, fieldnames=["category", "urgency", "summary", "원문"])
writer.writeheader()
writer.writerows(results)
print("\n완료! 문의_분류_결과.csv 파일을 확인하세요 ✅")💡 encoding="utf-8-sig" 로 저장해야 엑셀에서 한글이 안 깨져요! 진짜 .xlsx로 서식까지 입히고 싶다면 파이썬 업무 자동화 #1 - 엑셀 자동화 입문 (openpyxl)!과 조합하면 됩니다.
📌 실행 결과
[1/5] 배송 / 긴급도 보통 - 주문 후 일주일째 배송 준비중이라 배송 시점 문의
[2/5] 환불·교환 / 긴급도 보통 - 사이즈 불일치로 교환 절차 문의
[3/5] 불만 / 긴급도 높음 - 색상 차이로 환불 요구, 부정 리뷰 예고
[4/5] 상품 문의 / 긴급도 낮음 - 재입고 일정과 알림 신청 방법 문의
[5/5] 환불·교환 / 긴급도 높음 - 중복 결제 의심, 확인·환불 요청(모델과 실행 시점에 따라 표현은 조금씩 달라질 수 있어요!)

긴급도 "높음"만 골라 지난 편에서 만든 디스코드 웹훅으로 쏘면? 급한 문의가 들어오는 즉시 디스코드 알림을 받는 자동 CS 모니터링이 완성됩니다 💡 이런 식으로 시리즈에서 배운 걸 레고처럼 조립하는 게 업무 자동화의 재미예요!
📌 자주 나는 에러
- APIConnectionError: Connection refused — 원인: LM Studio 서버가 꺼져 있음. 해결: Developer 탭에서 Start Server를 눌렀는지, 주소가
http://localhost:1234/v1인지 확인하세요. - NotFoundError: model not found — 원인:
LMS_CHAT_MODEL에 적은 이름과 LM Studio의 모델 식별자가 다름. 해결: 서버 켠 뒤 모델 목록에 뜨는 식별자를 그대로 복사해서 .env에 붙여넣으세요. 모델이 로드돼 있는지도 확인! - api_key가 None이라는 에러 / 토큰이 안 읽힘 — 원인:
.env파일 위치·이름 문제이거나load_dotenv()를os.getenv()보다 늦게 호출함. 해결:.env가 스크립트와 같은 폴더에 있는지, 파일명이.env.txt가 아닌지 확인하고, load_dotenv()를 맨 위에서 호출하세요. - json.decoder.JSONDecodeError — 원인: 경량 모델이 JSON 외에 설명이나 생각 과정(
<think>태그)을 덧붙임. 해결: 시스템 프롬프트에 "JSON만 출력" 명시 + 전체 코드처럼 코드블록 제거 처리를 넣고, 추론(reasoning) 모델이라면 LM Studio에서 추론 출력을 끄거나 일반 모델로 바꿔보세요.
📌 마무리
오늘은 LM Studio 로컬 LLM으로 고객 문의를 자동 분류·요약해봤어요. 핵심은 세 가지! base_url 한 줄로 OpenAI 호환 API를 내 PC로 돌리기, .env + python-dotenv로 토큰·모델명 관리하기, 그리고 "JSON만 출력" 프롬프트로 결과를 데이터처럼 다루기입니다. 이 패턴만 익히면 리뷰 분석, 메일 요약, 번역 배치 등 어디든 요금 걱정 없이 응용할 수 있어요.
다음 편에서는 이렇게 만든 자동화 스크립트를 매일 정해진 시간에 알아서 실행되게 만드는 예약 실행 자동화(datetime·schedule)를 다룰 예정이에요. 기대해주세요 🙌
📚 파이썬 업무 자동화 시리즈
- #1 - 엑셀 자동화 입문 (openpyxl)!
- #2 - 웹 크롤링 입문 (requests + BeautifulSoup)!
- #3 - 파일 정리 자동화 (이름 일괄 변경)!
- #4 - 디스코드 웹훅(Webhook)으로 알림 보내기!
- #5 - 로컬 LLM(LM Studio)으로 고객 문의 자동 분류·요약하기! ← 지금 이 글!
- #6 - 예약 실행 자동화 (datetime·schedule) — 예정
연재 · 14편 중 5번째
파이썬 업무 자동화
- #1엑셀 자동화 입문 (openpyxl)!
- #2웹 크롤링 입문 (requests + BeautifulSoup)!
- #3파일 정리 자동화 (이름 일괄 변경)!
- #4디스코드 웹훅(Webhook)으로 알림 보내기 (requests)!
- #5로컬 LLM(LM Studio)으로 고객 문의 자동 분류·요약하기! (무료 AI)지금 읽는 글
- #6예약 실행 자동화! 매일 정해진 시간에 스크립트 돌리기 (schedule·APScheduler)
- #7동적 페이지·로그인 자동화! requests로 안 되는 사이트 긁기 (Selenium)
- #8PDF 자동 처리! 여러 파일 병합·분할부터 비밀번호까지 (pypdf) 📄
- #9마우스·키보드 GUI 자동화! 클릭·타이핑을 파이썬이 대신하게 하기 (PyAutoGUI)
- #10워드(Word) 문서 자동 생성! 엑셀 명단으로 계약서·안내문 100장 뽑기 (python-docx) 📄
- #11개인화 대량 메일 자동 발송! 명단별 첨부파일·발송 로그·재시도까지 (smtplib 실전편) 📬
- #12구글 시트 연동하기! 팀원과 같이 보는 자동 시트 (gspread) 📗
- #13파이썬 자동화 로그·재시도·디스코드 실패 알림 만들기 - 조용히 멈추는 스크립트 잡기
- #14파워포인트(PowerPoint) 보고서 자동 생성! 엑셀 숫자만 바꾸면 발표자료 완성 (python-pptx) 📊
