우선 해당 링크 참고 해서 llama.cpp를 빌드합니다.

conda create -n gpt_oss -y python==3.11.3
conda activate gpt_oss
pip install pandas
pip install torch==2.5.1 torchvision torchaudio --index-url=https://download.pytorch.org/whl/cu124
pip install -U "huggingface_hub[cli]"
mkdir model
cd model
huggingface-cli download unsloth/gpt-oss-20b-BF16 --local-dir Q:\gpt_oss_test\model\gpt-oss-20b\bf16
huggingface-cli download unsloth/gpt-oss-20b-BF16 --local-dir Q:\gpt_oss_test\model\gpt-oss-20b\bf16 --resume-download
을 통해 모델을 가져옵니다.
다운 받가다 중간에 파일이 누락되거나 한다면 다음 명령어를 사용하여 누락한 부분을 채웁니다.
huggingface-cli download unsloth/gpt-oss-20b-BF16 --local-dir Q:\gpt_oss_test\model\gpt-oss-20b\bf16(이와 같이 절대경로 사용) --resume-download
기가랜으로 바꾸고 싶다…

cd ../llama.cpp
pip install transformers
pip install mistral-inference
pip install torch==2.5.1 torchvision torchaudio --index-url=https://download.pytorch.org/whl/cu124
pip install xformers==0.0.28.post3 --index-url=https://download.pytorch.org/whl/cu124
python llama.cpp/convert_hf_to_gguf.py --outtype f16 --verbose "Q:\gpt_oss_test\model\gpt-oss-20b\bf16" --outfile gpt-oss-20b-f16.gguf

다음과 같이 *.safetensors 파일들을 *.gguf의 파일 포맷으로 변환해주고 있습니다.


gguf로의 변환이 완료 된 시점에서 양자화를 진행합니다.
cd llama.cpp/build/bin/Release
./llama-quantize "Q:\gpt_oss_test\model\gpt-oss-20b\original\gpt-oss-20b.gguf" gpt-oss-20b-q4_k_m.gguf Q4_K_M
와 같이 모델(*.gguf)경로를 절대경로로 해서 인수로 넣어주면 양자화를 진행합니다.

양자화를 하는 이유는 제 gpu의 vram이 12gb밖에 안되어서 입니다. inference 시에 너무 느립니다.
Ollama로 gpt-oss를 그냥 pull해서 돌리게 되면 기존 vram을 초과하는 건 당연하고 공유 GPU메모리까지 차지하기 때문에 inference가 굉장히 느립니다.
따라서 ollama에서도 LLM 모델은 양자화 후에 사용하는 것도 방법이라며 알려줍니다.
llama.cpp는 연산의 상당부분을 cpu로 돌리는 비중이 높다고 생각하고 있습니다.
따라서 gpu의 메모리가 살짝 부족해도 cpu에서 커버를 칠 수 있는 부분이 존재하는 것 같단 말이죠.

다음과 같이 양자화를 마쳤습니다.

아까 41G에 해당 하던 무시무시한 용량은 다음과 같이 확 줄어들게 됩니다.
.\llama-cli.exe -m gpt-oss-20b-q4_k_m.gguf --prompt "Test" -ngl 28 -c 2048 -n 512
다음과 같은 명령어를 통해 inference를 진행할 수 있습니다.

뭐라뭐라고 말을 청산유수같이 쏟아냅니다.
계속 진행해 볼게요.

vram이 부족하니 ngl을 14로 줄여서 실행해봤습니다.

다행히 fit-in하고 있습니다.
음 cli.exe는 연이어서 대화도 힘들고 귀찮다. 따라서 같이 포함된 llama-simple-chat.exe를 사용하도록 합니다.
.\llama-simple-chat.exe -m gpt-oss-20b-q4_k_m.gguf -c 2048 -ngl 14

한국어로 설명하라니까 영어로 설명해서 “에헤이~~”하는 순간!

역시나 똑똑한 gpt 답게 아주 잘 설명하고 있습니다. ㅋㅋㅋㅋㅋ

심지어 vram을 초과하지 않고 있어서 아주 맘에 듭니다. 이제부터 gpt는 제껍니다.
이제 여기에 RAG를 붙여서 실시간 검색기능을 추가하고, 파인튜닝을 할 방법이 있다면 해서 저만의 gpt로 만들어야 겠죠.
Let’s produce answer.<|end|><|start|>assistant<|channel|>final<|message|>## 1. 정의 개요
**Application Binary Interface (ABI)** – 한 프로그램(혹은 라이브러리)과 다른 프로그램이 **바이너리 수준(즉, 머신 코드)에서 서로 상호작용**할 때 필요한 일련의 규칙을 말합니다.
즉, **컴파일러가 생성한 기계어와 다른 컴파일러가 생성한 기계어가 서로 “이해할 수 있도록” 보장하는 계약**입니다.> **ABI와 API의 차이**
> – **API**(Application Programming Interface)는 소스코드(소스 파일) 수준에서 함수 선언, 파라미터 타입, 리턴값, 예외 처리 등을 정의한 것입니다.
> – **ABI**는 그 API가 실제로 컴파일되어 **바이너리 형태**가 되었을 때 필요한 **레지스터, 스택, 네이밍, 데이터 타입** 등에 관한 세부 규칙을 정의합니다.
> – API가 바뀌면 보통 코드 재작성, 컴파일이 필요하지만, ABI가 바뀌면 **바이너리 호환성**이 깨져서 기존 이진식으로 재컴파일하거나 재배포가 필요합니다.—
## 2. 핵심 구성요소
| 구분 | 내용 | 예시 |
|——|——|——|
| **레지스터 활용** | 함수 인자를 레지스터에 담는지, 스택에 넣는지. | System V AMD64: 첫 6개 인자를 RDI, RSI, RDX, RCX, R8, R9에 담는다. |
| **스택 프레임** | 호출자/호출자 관계에서 스택 프레임(프레임) 크기, 정렬(Alignment) | 16‑바이트 정렬을 요구하는 ABI. |
| **레지스터 보존 규칙** | 호출자/호출자 중 누가 어떤 레지스터를 보존(Caller‑saved / Callee‑saved)해야 하는지. | System V: RDI, RSI, RDX 등은 호출자 보존. |
| **네이밍 / 매니포리** | C++에서 함수 이름을 어떻게 mangling(이름 변환)할 것인가. | Itanium C++ ABI: `?foo@@YAXH@Z`. |
| **타입 크기, 정렬, 패딩** | `struct`의 필드가 실제 메모리에서 어떻게 배치될 것인지. | C++ struct { int a; char b; }의 정렬을 4바이트. |
| **예외 처리** | 예외 발생 시 스택에 예외 객체를 어떻게 저장할 것인지. | Itanium C++ 예외 처리 매커니즘. |
| **함수 프로로그/에필로그** | 함수가 시작/끝에서 스택 포인터, 레지스터를 어떻게 초기화/복구할 것인지. | 32‑비트 x86: `push ebp; mov ebp, esp; sub esp, 16`. |
| **함수 호출 규칙** | 인자 전달 방식, 반환값 전달 방식. | x86‑64: RAX에 반환값. |
| **동적/정적 링크** | `.so/.dll` 로딩 시 심볼 주소 해석 방식. | System V: `dlopen` + `dlsym`. |> **결론**: **ABI는 “컴파일러가 생성한 코드가 서로 다른 컴파일러/플랫폼에서도 동작하도록 보장”하는 바이트 레벨 계약**입니다.
—
## 3. 대표적인 ABI 예시
| 플랫폼 / 아키텍처 | ABI 규칙 예시 |
|——————–|————–|
| **x86 / x86‑64 (System V)** | 인자 6개를 RDI, RSI, RDX, RCX, R8, R9에 저장. 스택 정렬 16바이트. |
| **Windows x86‑64 (Microsoft)** | 첫 4개 인자를 RCX, RDX, R8, R9에 저장. `STI` 레지스터 사용. |
| **ARM (AAPCS)** | 인자 4개를 R0~R3에 저장. 스택 정렬 8바이트. |
| **C++ (Itanium ABI)** | 네이밍 규칙, 예외 처리, 가상 함수 테이블(VDT) 구조 등. |> **예시**: Linux에서 `libc.so`의 `printf`가 x86‑64 System V ABI에 따라 `RDI`에 format string을 담고, `RDX`에 가변수 인자를 전달한다.
—
## 4. 왜 중요한가? (ABI가 깨지면)
1. **동적 링크**
– `.so`·`.dll` 를 로딩할 때 심볼이 정확히 매칭되지 않으면 실행시 오류가 발생합니다.
– ABI가 바뀌면 심볼이 같은 이름이라도 **스택 프레임**이나 **레지스터 보존** 방식이 달라져 호출자/호출자 간 호환이 깨집니다.2. **라이브러리 업데이트**
– glibc, libstdc++ 등 핵심 라이브러리의 ABI를 바꾸면 **모든 이진식 재컴파일**이 필요합니다.
– 이 때문에 운영체제(예: Debian/Ubuntu)에서는 **ABI 안정성**을 명시하고, 업데이트 시 `–with-abi=stable` 옵션을 사용합니다.3. **언어 간 통합**
– C/C++ → Rust, Go, Swift 같은 언어끼리 서로 호출할 때도 **같은 ABI**를 사용해야 합니다.
– Rust는 `extern “C”`로 C ABI를 따르고, Go는 `cgo`를 통해 C ABI를 준수합니다.4. **가상환경/컨테이너**
– Docker, QEMU 등은 **호스트와 게스트** 사이에 ABI 차이를 감지해야 하므로, 동일한 ABI 규칙이 필수적입니다.—
## 5. ABI와 스마트컨트랙트 (블록체인)
블록체인(예: 이더리움)에서도 ABI가 존재합니다.
– **EVM ABI**: 스마트컨트랙트 함수 호출 시 4
와 같이 간지나는 대답을 해줍니다.
그럼 이제 평가의 시간입니다.

평가는 현재 최상위권 성능을 자랑하는 grok4쨩에게 부탁해볼게요
gpt-oss의 응답을 제3자로서 분석해 보았습니다. 평가 기준으로는 정확성(내용의 사실성), 상세함(설명 깊이와 포괄성), 완전성(응답의 마무리 여부), 구조화(읽기 편의성), 한국어 사용 적합성(요청 준수), 그리고 전반적인 품질(유용성 및 잠재적 개선점)을 중심으로 판단했습니다. 이는 웹 검색 결과(예: Wikipedia, Stack Overflow)와 비교하며 검증했습니다.
1. 정확성 (Accuracy)
- 강점: 응답의 대부분 내용이 정확합니다. ABI의 정의(“바이너리 수준에서 프로그램 모듈 간 인터페이스 규칙”)가 표준 설명과 일치하며, API와의 차이(소스 코드 vs 바이너리 수준)를 명확히 구분했습니다. 핵심 구성 요소(레지스터 활용, 스택 프레임, 이름 맹글링, 타입 크기 등)도 프로그래밍 ABI의 표준 요소를 잘 반영했습니다. 예시로 System V AMD64의 레지스터(RDI, RSI 등)와 Itanium C++ ABI의 이름 맹글링 예시가 사실에 부합합니다. 중요성 부분(바이너리 호환성, 라이브러리 업데이트 문제, 언어 간 통합)도 실무적 관점에서 올바릅니다.
- 약점: 블록체인 ABI(EVM ABI) 부분은 프로그래밍 일반 ABI와는 별개의 개념으로, 사용자가 “프로그래밍의 개념”이라고 지정했으므로 약간 벗어납니다. 하지만 유사 용어로 유용할 수 있음. EVM ABI는 스마트 컨트랙트 함수 호출(예: 4바이트 셀렉터, 파라미터 패킹)에서 사용되지만, 응답이 끊겨 정확히 설명되지 않았습니다. 전체적으로 사소한 오류 없음.
- 점수: 9/10 (높은 정확성, 하지만 맥락 약간 확대).
2. 상세함 (Detail Level)
- 강점: 요청대로 “최대한 상세히” 설명했습니다. 섹션별로 정의, 구성 요소(테이블 형식), 예시(플랫폼별 ABI), 중요성(동적 링크, 라이브러리 업데이트 등)을 포괄적으로 다루었습니다. 예를 들어, 레지스터 보존 규칙(Caller-saved vs Callee-saved), 함수 프로로그/에필로그, ABI 안정성 같은 고급 주제를 포함해 깊이가 있습니다. 블록체인 ABI 추가는 보너스지만, 일반 프로그래밍 ABI(예: x86-64, ARM)에 초점을 맞춘 점이 좋습니다.
- 약점: 일부 예시(예: Windows x86-64의 RCX, RDX 등)가 간략하며, 더 구체적인 코드 스니펫이나 ABI 버전 관리(예: glibc ABI 변화 사례)를 추가할 수 있었습니다. 하지만 요청 수준으로는 충분.
- 점수: 9/10 (상세하고 포괄적).
3. 완전성 (Completeness)
- 강점: 응답이 논리적으로 시작(정의)부터 끝(블록체인 ABI)까지 흐름이 있지만…
- 약점: 응답이 중간에 끊겼습니다. “스마트컨트랙트 함수 호출 시 4″로 끝나 불완전합니다. EVM ABI의 핵심(함수 셀렉터, 파라미터 인코딩, 리턴값 디코딩 등)이 설명되지 않아 마무리가 아쉽습니다. 만약 완전했다면 더 좋았을 텐데, 이는 gpt-oss의 생성 제한 때문으로 보임.
- 점수: 7/10 (주요 부분은 완성, 하지만 끝맺음 미흡).
4. 구조화 (Structure)
- 강점: 섹션(1. 정의 개요, 2. 핵심 구성요소 등), 테이블(구성 요소, 예시), 불릿 리스트(왜 중요한가?)로 잘 구성되어 읽기 쉽습니다. 마크다운 사용으로 시각적으로 매력적.
- 약점: 없음. 구조가 응답의 강점입니다.
- 점수: 10/10 (우수한 조직화).
5. 한국어 사용 적합성 (Korean Language Suitability)
- 강점: 요청(“please response in korean”)대로 전부 한국어로 작성. 용어 번역(예: “네이밍 / 매니포리” → name mangling)이 자연스럽고, 기술 용어를 적절히 혼용.
- 약점: 없음.
- 점수: 10/10 (완벽 준수).
6. 전반적인 품질 및 개선점 (Overall Quality and Suggestions)
- 전반 평가: 높은 품질의 응답으로, 초보자부터 중급자까지 유용합니다. 정확하고 상세하며, 구조가 좋아 이해하기 쉽습니다. 하지만 불완전한 끝맺음으로 인해 완벽하지 않습니다. 양자화된 gpt-oss 모델의 성능으로 보아, 대형 모델(20B)치고 잘 생성했으나, 토큰 제한이나 양자화 손실로 끊김 발생 가능.
- 점수: 9/10 (우수, 하지만 완전성 개선 필요).
- 개선 제안:
- 응답을 완성하기 위해 EVM ABI 부분을 보완(예: “4바이트 함수 셀렉터, 파라미터 솔리디티 ABI 인코딩 방식” 추가).
- 더 많은 실생활 사례(예: ABI 깨짐으로 인한 소프트웨어 버그) 추가.
- 만약 양자화로 인한 품질 저하가 의심되면, 더 높은 비트 양자화(Q5_K_M) 시도 추천.
이 평가는 객관적이며, 필요 시 추가 도구(예: 더 구체적 웹 검색)로 검증 가능합니다. 추가 질문 있으신가요?
평가가 되게 후하네요 ㄷㄷ
제가 보기에는 용어가 틀린게 있는데
“매니포리” 이부분이 문제인데 말이죠

그럼 그렇죠 ㅋㅋㅋ 확실히 양자화를 해서 약간의 성능적 손실은 감내해야 하는 군요. 이 부분은 RAG로 개선될지 궁금합니다.
이상 gpt-oss를 llama-cpp에서 돌리기 끝입니다.