이번 글은 AgentShield를 진행하면서 헷갈렸던 Ollama 모델 구조와 Judge/Guard 판정 구조를 정리한 개인 기록입니다.
이번 단계에서 핵심은 판정 모델이 하나가 아니라 여러 레이어로 나뉘어 있다는 점입니다. 또한 .env에 있는 Ollama 모델 변수들이 모두 같은 의미가 아니라, testbed 챗봇용 모델, Red Agent용 모델, Guard용 모델, 파인튜닝 결과물용 모델처럼 역할별로 분리되어 있다는 점을 정리합니다.
1. Judge와 Guard의 차이
AgentShield에서 판정은 하나의 모델이 전부 처리하는 구조가 아닙니다.
현재 구조는 여러 단계의 판정 레이어로 나뉘어 있습니다.
공격 → 타겟 응답
│
Layer 1: 규칙 기반 Judge
│
Layer 2: Guard Judge
│
Layer 3: LLM Judge
처음에는 Judge와 Guard가 비슷한 역할처럼 보였지만, 실제로는 목적과 실행 조건이 다릅니다.
2. Layer 1은 규칙 기반 Judge
Layer 1은 judge.py에서 동작하는 규칙 기반 Judge입니다.
이 단계는 LLM 없이 동작합니다. 정규식 패턴, keyword, 응답 구조 분석 등을 통해 타겟 응답이 취약한지 빠르게 판단합니다.
장점은 빠르고 결정적이라는 점입니다. 같은 입력에 대해 비교적 동일한 결과를 기대할 수 있고, LLM 호출 비용도 없습니다.
하지만 한계도 있습니다. 응답이 애매하거나, 공격 성공처럼 보이지만 실제로는 거부 응답인 경우, 또는 표현이 우회적으로 나온 경우에는 규칙만으로 안정적으로 판단하기 어렵습니다.
그래서 다음 단계로 Guard Judge가 들어갑니다.
3. Layer 2는 Guard Judge
Layer 2는 guard_judge.py에서 동작하는 Guard Judge입니다.
여기서 사용하는 모델은 .env의 OLLAMA_GUARD_MODEL입니다.
현재 값은 다음과 같습니다.
OLLAMA_GUARD_MODEL=qwen3.5:4b
즉, Guard는 qwen3.5:4b 같은 경량 LLM을 사용해서 Layer 1이 애매하다고 본 케이스를 다시 확인하는 역할입니다.
Guard의 목적은 “이 응답이 진짜 취약한 응답인가?”를 한 번 더 확인하는 것입니다.
정리하면 다음과 같습니다.
GUARD_MODEL = Layer 2
사용 모델 = qwen3.5:4b
역할 = 경량 LLM 기반 재판정
실행 위치 = 규칙 기반 Judge 이후
여기서 중요한 점은 Guard가 최종 정밀 판정 모델이 아니라는 점입니다. Guard는 가볍고 빠른 필터에 가깝습니다.
4. Layer 3은 LLM Judge
Layer 3은 더 큰 모델을 사용하는 정밀 판정 단계입니다.
여기서 사용하는 모델은 .env의 OLLAMA_JUDGE_MODEL입니다.
현재 구조에서는 다음 값으로 정리되어 있습니다.
OLLAMA_JUDGE_MODEL=agent-judge
이 모델은 --llm-judge 옵션을 켤 때만 실행되는 정밀 판정 모델입니다.
즉, 항상 실행되는 Guard와 다르게 LLM Judge는 옵션 기반입니다. 확신도가 낮거나 중요한 케이스에 대해 더 정밀하게 판단할 때 사용하는 구조입니다.
현재는 이 Layer 3 역할을 완전히 자동화하기보다는 수동 검수로 보완하고 있습니다.
5. Judge와 Guard 차이를 정리하면
Judge와 Guard를 가장 단순하게 구분하면 다음과 같습니다.
규칙 기반 Judge = 빠른 1차 판정
Guard Judge = 경량 LLM 기반 재확인
LLM Judge = 옵션 기반 정밀 판정
OLLAMA_GUARD_MODEL은 항상 실행되는 경량 판정 모델입니다.
OLLAMA_JUDGE_MODEL은 --llm-judge 옵션을 켰을 때 사용하는 정밀 판정 모델입니다.
따라서 qwen3.5:4b는 Guard 모델이고, agent-judge는 LLM Judge 모델입니다.
6. OLLAMA_MODEL과 OLLAMA_BASE_TARGET_MODEL
다음으로 헷갈렸던 부분은 OLLAMA_MODEL과 OLLAMA_BASE_TARGET_MODEL입니다.
둘 다 실제값은 gemma4:e2b일 수 있습니다.
하지만 쓰이는 위치가 다릅니다.
OLLAMA_MODEL=gemma4:e2b
OLLAMA_BASE_TARGET_MODEL=gemma4:e2b
OLLAMA_MODEL은 testbed 챗봇이 응답을 생성할 때 사용하는 기본 모델입니다.
반면 OLLAMA_BASE_TARGET_MODEL은 run_pipeline.py에서 --target-url 없이 로컬 Ollama에 직접 공격할 때 사용하는 타겟 모델입니다.
즉, 모델 파일은 같아도 호출 경로가 다릅니다.
7. testbed 챗봇 경유와 로컬 Ollama 직접 공격의 차이
testbed 챗봇을 경유할 때는 다음 URL을 사용합니다.
http://localhost:8010/chat
이 경우 타겟 응답은 testbed 챗봇이 생성합니다. 따라서 testbed 쪽 설정인 OLLAMA_MODEL이 사용됩니다.
반대로 --target-url 없이 CLI 파이프라인이 직접 Ollama에 붙는 경우에는 OLLAMA_BASE_TARGET_MODEL이 사용됩니다.
정리하면 다음과 같습니다.
| 변수 | 실제값 | 쓰이는 곳 |
|---|---|---|
OLLAMA_MODEL |
gemma4:e2b |
testbed 챗봇이 응답 생성할 때 |
OLLAMA_BASE_TARGET_MODEL |
gemma4:e2b |
run_pipeline.py에서 --target-url 없이 로컬 Ollama 직접 공격할 때 |
그래서 --target-url http://localhost:8010/chat을 사용하면 OLLAMA_BASE_TARGET_MODEL은 무시됩니다.
8. Ollama 모델 변수 전체 구조
현재 .env의 Ollama 모델 구조는 역할별로 나뉘어 있습니다.
OLLAMA_MODEL=gemma4:e2b
OLLAMA_RED_MODEL=gemma4-ara-abliterated
OLLAMA_JUDGE_MODEL=agent-judge
OLLAMA_GUARD_MODEL=qwen3.5:4b
OLLAMA_BLUE_MODEL=agent-blue
OLLAMA_BASE_TARGET_MODEL=gemma4:e2b
OLLAMA_RED_TARGET_MODEL=agentshield-red
OLLAMA_JUDGE_TARGET_MODEL=agentshield-judge
OLLAMA_BLUE_TARGET_MODEL=agentshield-blue
위쪽은 현재 실행에 직접 쓰이는 역할별 모델입니다.
아래쪽의 *_TARGET_MODEL은 파인튜닝된 결과물을 Ollama에 등록한 뒤 사용할 모델 이름입니다.
여기서 agentshield-* 이름은 실제 Hugging Face 모델명이 아니라, Ollama Modelfile로 등록할 로컬 모델 이름입니다.
9. 각 모델 역할 정리
OLLAMA_MODEL은 기본 베이스 모델입니다. testbed 챗봇이 응답을 생성할 때 쓰이고, 일부 폴백 상황에서도 사용됩니다.
OLLAMA_RED_MODEL은 Red Agent가 공격 프롬프트를 생성할 때 사용하는 모델입니다. 현재는 gemma4-ara-abliterated를 사용합니다.
OLLAMA_JUDGE_MODEL은 LLM Judge용 모델입니다. --llm-judge 옵션을 켰을 때 정밀 판정에 사용됩니다.
OLLAMA_GUARD_MODEL은 Guard Judge용 경량 모델입니다. 현재 값은 qwen3.5:4b이며, Layer 2에서 사용됩니다.
OLLAMA_BLUE_MODEL은 Blue Agent가 방어 응답이나 방어 코드를 생성할 때 사용하는 모델입니다.
OLLAMA_BASE_TARGET_MODEL은 로컬 Ollama 직접 공격 시 타겟 모델입니다.
OLLAMA_RED_TARGET_MODEL, OLLAMA_JUDGE_TARGET_MODEL, OLLAMA_BLUE_TARGET_MODEL은 파인튜닝 결과물을 Ollama에 등록한 뒤 사용할 모델 이름입니다.
10. 파인튜닝 결과물은 Ollama Modelfile로 등록해야 합니다
agentshield-red, agentshield-judge, agentshield-blue는 그냥 자동으로 생기는 이름이 아닙니다.
학습이 끝난 뒤 LoRA adapter를 기반으로 Ollama Modelfile을 만들고, ollama create로 등록해야 실제로 사용할 수 있습니다.
예상되는 등록 흐름은 다음과 같습니다.
ollama create agentshield-red -f adapters/lora-red/Modelfile
ollama create agentshield-judge -f adapters/lora-judge/Modelfile
ollama create agentshield-blue -f adapters/lora-blue/Modelfile
이 과정을 거쳐야 .env에서 다음 값을 실제로 사용할 수 있습니다.
OLLAMA_RED_TARGET_MODEL=agentshield-red
OLLAMA_JUDGE_TARGET_MODEL=agentshield-judge
OLLAMA_BLUE_TARGET_MODEL=agentshield-blue
현재는 agentshield-* 모델이 Ollama에 실제로 등록되어 있지 않기 때문에, llm_client.py가 OLLAMA_MODEL, 즉 gemma4:e2b로 폴백해서 동작 중입니다.
11. 파인튜닝 데이터 준비 흐름
파인튜닝은 먼저 PostgreSQL에 쌓인 실행 결과를 정제된 JSONL로 내보내는 것부터 시작합니다.
python -m backend.data_cleaning.export_cleaned
이 단계는 PostgreSQL에 저장된 raw 결과 중 사람이 검수한 cleaned 데이터를 학습 가능한 형태로 빼내는 과정입니다.
그 다음 prepare_data를 실행해서 DPO 또는 SFT 포맷으로 변환합니다.
python -m backend.finetuning.prepare_data
이 단계에서 Red, Judge, Blue 역할별 학습 데이터가 만들어집니다.
단, Blue는 방어 패턴이 충분히 쌓인 뒤에 의미가 있습니다. 현재는 Red와 Judge 쪽을 먼저 안정화하는 것이 맞습니다.
12. QLoRA 학습 흐름
학습은 backend/finetuning/train_lora.py에서 역할별로 실행합니다.
python backend/finetuning/train_lora.py --role red
python backend/finetuning/train_lora.py --role judge
python backend/finetuning/train_lora.py --role blue
학습 결과는 역할별 adapter 디렉터리에 저장됩니다.
adapters/lora-red/
adapters/lora-judge/
adapters/lora-blue/
여기서 중요한 것은 학습 base model과 실제 런타임 base model이 맞아야 한다는 점입니다.
Red Agent의 런타임 모델이 gemma4-ara-abliterated라면, Red LoRA 학습도 같은 계열의 base model을 기준으로 해야 합니다.
그렇지 않으면 adapter가 실제 실행 모델과 맞지 않아 결과 품질이 흔들릴 수 있습니다.
13. 현재 상태에서 헷갈리면 안 되는 점
현재 agentshield-* 모델 이름은 .env에 들어가 있어도 실제 Ollama에 등록되어 있지 않으면 사용할 수 없습니다.
등록되지 않은 경우에는 llm_client.py가 기본 모델로 폴백합니다.
따라서 다음 두 가지를 구분해야 합니다.
.env에 모델 이름이 적혀 있음
Ollama에 실제 모델이 등록되어 있음
둘은 같은 의미가 아닙니다.
.env는 어떤 이름을 사용할지 지정하는 설정이고, Ollama 등록은 실제 실행 가능한 모델을 만드는 과정입니다.
14. 이번 정리에서 확실히 잡은 기준
이번에 정리하면서 가장 중요한 기준은 모델 이름보다 역할을 먼저 봐야 한다는 점입니다.
gemma4:e2b라는 이름이 여러 곳에 보이더라도 testbed 챗봇용인지, 로컬 직접 공격용인지에 따라 의미가 달라집니다.
qwen3.5:4b는 Judge 전체가 아니라 Guard Judge입니다.
agent-judge는 --llm-judge 옵션을 켰을 때 사용하는 정밀 판정 모델입니다.
agentshield-red, agentshield-judge, agentshield-blue는 파인튜닝 후 Ollama Modelfile로 등록해야 사용할 수 있는 결과물 이름입니다.
지금 상태에서는 Red/Judge/Blue 파인튜닝 결과물이 실제 등록되어 있지 않기 때문에, 폴백 동작까지 같이 확인해야 합니다.
정리하면 현재 구조는 다음 흐름으로 이해하는 것이 맞습니다.
규칙 기반 Judge
→ Guard Judge(qwen3.5:4b)
→ 필요 시 LLM Judge(agent-judge)
→ 사람이 최종 검수
→ cleaned data 생성
→ LoRA 학습
→ Ollama 모델 등록
→ .env TARGET 모델 교체
이 흐름을 기준으로 보면, AgentShield의 모델 설정은 단순히 모델명을 나열한 것이 아니라 공격 생성, 타겟 응답, 판정, 방어, 파인튜닝 결과물까지 역할별로 분리한 구조입니다.
