개요
재미 삼아 만든 오늘의 운세.
OpenAI를 활용해서 만들었는데, 생각보다 금액이 많이 나감.
그래서 오픈소스 LLM인 LLaMA를 활용해서 오늘의 운세를 만듦
- OpenAI통해서 오늘 날짜 기준으로 띠별, 별자리별 운세데이터 생성.
- JSON 형식으로 변환.
- DB 저장.
세팅
- 선택 버전 : LLaMA 3 8B (GGUF)
해당 버전을 선택한 이유는, 성능이 안좋은 서버컴으로 돌리기 위해서 8B(파라미터)로 타협을 본 것이고, LLM을 돌릴만한 GPU가 아니어서 CPU만 활용하기 위해 CPU-only 포맷인 GGUF 포맷(양자화 포맷)으로 세팅.
1. window python에서 GGUF 모델을 실행하기 위해 컴파일이 필요하므로, Visual Studio C++ Build Tools가 선행되어야 함.
- Visual C++ 빌드 도구 설치
Microsoft C++ Build Tools 다운로드(https://visualstudio.microsoft.com/ko/visual-cpp-build-tools/)
설치 마법사에서 "C++ build tools" 체크 - 필수 구성 요소
- MSVC v142 이상
- Windows 10 SDK
- CMake (선택 사항)
- 설치 후 PC 재부팅
2. Meta LLaMA 3 8B 모델 다운로드 (GGUF 포맷)
(Meta-Llama-3-8B-Instruct.Q4_K_M.gguf)
https://huggingface.co/QuantFactory/Meta-Llama-3-8B-Instruct-GGUF
코드에서 불러올 수 있게 특정 경로에 세팅
코드 샘플
from llama_cpp import Llama
from datetime import datetime
import json
# 모델 로딩
llm = Llama(
model_path="./models/Meta-Llama-3-8B-Instruct.Q4_K_M.gguf", # 경로 수정 필요
n_ctx=2048,
n_threads=4, # CPU 스레드 수에 맞게 조정
)
# 오늘 날짜
today = datetime.today().strftime("%Y년 %m월 %d일")
# 프롬프트 구성 (역할 + 스타일 + few-shot + 포맷 모두 포함)
prompt = f"""
당신은 10년 경력의 운세 작가이며, 띠별 운세를 매일 작성합니다.
운세는 하루를 시작하는 사람에게 도움이 되도록 감정, 인간관계, 직장, 건강, 금전운 중 2~3가지를 포함해 1~2문단으로 작성합니다.
문체는 부드럽고 따뜻하며, 실용적인 조언도 포함되어야 합니다.
1. 띠별 운세 (12간지):
- 각 띠(쥐, 소, 호랑이, 토끼, 용, 뱀, 말, 양, 원숭이, 닭, 개, 돼지)에 대해
- 해당 띠에 속하는 주요 출생 연도별 운세도 포함시켜 주세요. (예: 쥐띠 - 1948, 1960, 1972, 1984, 1996)
2. 별자리 운세:
- 양자리, 황소자리, 쌍둥이자리, 게자리, 사자자리, 처녀자리, 천칭자리, 전갈자리, 사수자리, 염소자리, 물병자리, 물고기자리
띠별과 별자리 운세를 아래 JSON 형식에 맞춰 출력해주세요.
- 오늘은 {today}입니다.
- "date" 필드에 오늘 날짜({datetime.today().strftime("%Y%m%d")})를 실제로 포함시켜주세요.
- 출력은 모두 한국어로 작성해주세요. 영어 단어를 섞지 말고, 문장도 완전하게 써주세요.
- 각 항목은 가능하면 빠짐없이 1문단 이상 채워주세요.
- JSON 형식은 아래와 같습니다. (예시로 작성된 내용은 무시하세요.)
{{
"date": "YYYYMMDD",
"horoscope": {{
"chinese_zodiac": {{
"rat": {{
"1948" : "",
"1960" : "",
"1972" : "",
"1984" : "",
"1996" : ""
}},
"ox": {{
"1949" : "",
"1961" : "",
"1973" : "",
"1985" : "",
"1997" : ""
}},
"tiger": {{
"1950" : "",
"1962" : "",
"1974" : "",
"1986" : "",
"1998" : ""
}},
"rabbit": {{
"1951" : "",
"1963" : "",
"1975" : "",
"1987" : "",
"1999" : ""
}},
"dragon": {{
"1952" : "",
"1964" : "",
"1976" : "",
"1988" : "",
"2000" : ""
}},
"snake": {{
"1953" : "",
"1965" : "",
"1977" : "",
"1989" : "",
"2001" : ""
}},
"horse": {{
"1954" : "",
"1966" : "",
"1978" : "",
"1990" : "",
"2002" : ""
}},
"sheep": {{
"1955" : "",
"1967" : "",
"1979" : "",
"1991" : "",
"2003" : ""
}},
"monkey": {{
"1956" : "",
"1968" : "",
"1980" : "",
"1992" : "",
"2004" : ""
}},
"rooster": {{
"1957" : "",
"1969" : "",
"1981" : "",
"1993" : "",
"2005" : ""
}},
"dog": {{
"1958" : "",
"1970" : "",
"1982" : "",
"1994" : "",
"2006" : ""
}},
"pig": {{
"1959" : "",
"1971" : "",
"1983" : "",
"1995" : "",
"2007" : ""
}}
}},
"zodiac_sign": {{
"aries": "",
"taurus": "",
"gemini": "",
"cancer": "",
"leo": "",
"virgo": "",
"libra": "",
"scorpio": "",
"sagittarius": "",
"capricorn": "",
"aquarius": "",
"pisces": ""
}}
}}
}}
"""
# 운세 생성
response = llm(
prompt,
max_tokens=4096, # 전체 길이 제한
temperature=0.85, # 창의성 조절
top_p=0.9, # 상위 확률 내에서 샘플링
repeat_penalty=1.15, # 중복 억제
# stop=["\n\n", "\n }", "\n }", "\n}"] # JSON 형식 종료를 위한 중지 토큰
)
# 결과 추출
try:
result = response["choices"][0]["text"]
print(result)
json_start = result.find("{")
result_json = result[json_start:]
parsed = json.loads(result_json)
# print(f"=== 운세 결과 ({today}) ===")
# print(json.dumps(parsed, ensure_ascii=False, indent=2))
except json.JSONDecodeError as e:
print("❌ JSON 파싱 실패!")
print("오류 메시지:", str(e))
print("출력 일부 확인:\n")
print(result_json[:1000])
마무리
느린건 둘째치고,
원하는 결과가 잘 안나온다.
결과가 나오다가 만다.
저사양 LLM으로 원하는 결과를 나오게 할 전략이 필요하다.
'샘플 작업' 카테고리의 다른 글
[python, 샘플] 오늘의 운세 (OpenAI 활용) (0) | 2025.04.06 |
---|---|
[python, 샘플] 오늘의 운세 (신문사 RSS피드 활용) (0) | 2025.04.06 |