Views
No views yet
이 모델은 Google의 강력한 소형 언어 모델인 Gemma-3-1B-it을 기반으로, 한국어 범죄 사건 보고서 분석 태스크에 맞게 미세 조정(Fine-tuning)되었습니다.
# 주요 기능
사건 재구성 (Context Generation): 사건 보고서의 내용과 사실 관계를 분석하여 당시 상황을 논리적으로 재구성합니다.
사건 유형 분류 (Kind Classification): 재구성된 내용을 바탕으로 사건의 종류를 정확히 분류하여 제시합니다.
# 학습 전략
(QLoRA)모델 학습에는 QLoRA (Quantized Low-Rank Adaptation) 기법이 적용되어, 높은 메모리 효율성과 빠른 학습 속도를 달성했습니다.
양자화: 4-bit NF4 양자화 (BitsAndBytes)
PEFT: LoRA 적용 (Rank $r=16$, $\alpha=32$)
최적화: adamw_torch, Learning Rate $2e-4$, Cosine Scheduler
필수 라이브러리 및 버전이 모델의 학습 및 사용을 위해서는 다음 라이브러리 버전이 권장됩니다.
라이브러리 버전
transformers : 4.57.3
accelerate : 1.12.0
bitsandbytes : 0.48.2
peft : 0.15.2
torch : 2.9.01from transformers import AutoModelForCausalLM, AutoTokenizer
2
3
4base_model = "chyungwon/police-report-analysis-model"
5
6tokenizer = AutoTokenizer.from_pretrained(base_model)
7
8model = AutoModelForCausalLM.from_pretrained(
9 base_model,
10 torch_dtype=torch.bfloat16,
11 device_map="auto"
12)
13
14
15question = """다음 사건 보고서를 통해서 당시 범죄 사건을 재구성해주고, 사건 유형을 분류해줘.
16
17[사건 보고서]
182024년 4월 25일, 서울 숭실대입구역 인근에서 이삿짐 화물차가 인도로 돌진해 60대 남성을 부상시킨 사건이 발생하였다.
19현장 조사 결과, 화물차 운전자 김민수(35)는 사전에 브레이크 패드를 마모시키고 브레이크액에 물을 섞어 고장을 유발한 것으로 확인되었다.
20사고 직후 김은 차 내부에 숨겨진 금고에서 현금 200만 원과 가죽 가방, 스마트폰을 꺼내 상가 안경원 직원에게 전달하고, 은행 계좌로 송금하였다.
21경찰은 차량 GPS 기록, 브레이크 패드 마모 상태, CCTV 영상 조작 여부를 조사 중이며, 김은 교통사고처리특례법에 따라 치상 혐의로 입건되었다.
22현재 수사는 김의 은행 송금 기록과 금고 내용물 확보를 통해 범죄 동기와 범행 방법을 파악 중이다.
23사건은 아직 결말이 내려지지 않았으며, 추가 증거 확보가 필요하다."""
24
25
26messages = [
27 {"role": "system", "content": """당신은 범행분석 AI 모델입니다. 질문에 정확하게 답변하세요."""},
28 {"role": "user", "content": question}
29]
30
31inputs = tokenizer.apply_chat_template(
32 messages,
33 add_generation_prompt=True,
34 return_tensors="pt",
35 return_dict=True,
36).to(model.device)
37
38model.eval()
39outputs = model.generate(
40 **inputs,
41 max_new_tokens=1024 * 2,
42 temperature=0.1,
43 do_sample=True,
44)
45
46generated = outputs[0][inputs["input_ids"].shape[-1] :]
47answer = tokenizer.decode(generated, skip_special_tokens=True)
48print('사건 재구성 : ', answer)
49
50
51사건 재구성 : 2024년 4월 25일 오후 1시 30분, 서울 숭실대입구역 인근에서 발생한 이삿짐 화물차 사고는 단순한 교통사고가 아니라 정교하게 계획된 절도 사건의 일환이었다. 화물차 운전자인 김민수(35)는 3개월 전부터 지역 상가에서 일하는 60대 남성(피해자)과의 금전적 갈등을 품고 있었다. 김은 피해자가 자신이 운영하던 작은 가게에서 물건을 훔쳐 가는 것을 목격하고, 그 사실을 폭로하면 자신의 사업이 망가질 위험이 있다고 판단했다. 이에 김은 피해자를 제거하고 동시에 가게에서 훔친 물건을 회수하려는 계획을 세웠다.
52
53계획 단계에서 김은 화물차의 브레이크 패드를 미리 마모시키고, 브레이크액에 물을 섞어 브레이크가 갑자기 작동하지 않도록 조작했다. 또한, 차 내부에 숨겨진 작은 금고에 훔친 물건(현금 200만 원, 가죽 가방, 스마트폰)을 보관했다. 사고 발생 시 피해자가 차에 부딪혀 부상을 입으면, 김은 즉시 차를 멈추고 금고를 열어 물건을 꺼내어 상가 안경원 직원에게 전달했다. 이 직원은 김이 사전에 협상한 인물로, 물건을 수거해 김의 은행 계좌로 송금하도록 했다.
54
55실행 단계에서 김은 화물차를 숭실대입구역 인근 인도에 주차한 뒤, 피해자가 차를 지나가던 순간 브레이크를 고의로 작동시키지 않도록 조작했다. 차가 인도를 돌진하면서 피해자는 차체에 부딪혀 다리를 크게 다쳤고, 즉시 병원으로 이송되었다. 김은 사고 직후 차를 멈추고, 피해자가 부상으로 움직일 수 없다는 상황을 이용해 금고를 열어 물건을 꺼냈다. 그는 물건을 상가 안경원 직원에게 전달하고, 직원은 즉시 현금과 물건을 김의 은행 계좌로 송금했다.
56
57은폐 단계에서는 김은 사고 현장을 빠르게 정리하고, 차 내부에 남은 흔적을 최소화했다. 그는 차를 다른 지역으로 이동시켜 CCTV가 감시되지 않는 곳에 주차했다. 또한, 사고 당시 차가 정지한 위치와 피해자의 부상 정도를 이용해 경찰이 사고를 단순한 교통사고로 판단하도록 유도했다. 김은 이후 은행 계좌에서 물건을 현금으로 인출해 현지 편의점에서 현금화하고, 남은 금액은 가짜 신분증으로 만든 가상 계좌에 송금했다.
58
59수사 과정에서 경찰은 CCTV 영상을 분석해 화물차가 인도를 돌진한 순간을 확인했고, 브레이크 패드 마모와 브레이크액에 물이 섞인 흔적을 발견했다. 또한, 김이 사전에 상가 안경원 직원과 연락을 주고받았다는 증거가 확보되었다. 그러나 김은 교통사고처리특례법에 따라 치상 혐의로 입건되었으며, 현재는 구속영장이 신청 중이다. 사건은 아직 수사 단계이며, 김이 실제로 물건을 훔쳤는지, 그리고 피해자와의 갈등이 범행 동기에 얼마나 영향을 미쳤는지에 대한 추가 조사가 필요하다. 사건은 아직 결말이 내려지지 않았으며, 경찰은 김의 은행 계좌와 상가 안경원 직원의 증언을 통해 범행의 전모를 파악하려 하고 있다.
60사건 유형 : 절도base_model = "./gemma-3-1b-it"
tokenizer = AutoTokenizer.from_pretrained(base_model)
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_compute_dtype=torch.bfloat16,
bnb_4bit_use_double_quant=True,
bnb_4bit_quant_type="nf4"
)
model = AutoModelForCausalLM.from_pretrained(
base_model,
quantization_config=bnb_config,
torch_dtype=torch.bfloat16,
device_map="auto"
)
lora_config = LoraConfig(
r=16,
lora_alpha=32,
target_modules=[
"q_proj", "k_proj", "v_proj", "o_proj",
"gate_proj", "up_proj", "down_proj"
],
lora_dropout=0.05,
bias="none",
task_type=TaskType.CAUSAL_LM,
)
model2 = get_peft_model(model, lora_config)def format_prompt(ex, max_length=1775):
global max_length_cal, row
title = '다음 사건 보고서를 통해서 당시 사건을 재구성해주고, 사건 유형을 분류해줘\n'
question = ex["report"]
answer = ex["context"]
kind = f'\n사건 유형 : {ex["kind"]}'
prompt = f"""<start_of_turn>system
당신은 범행분석 AI 모델입니다.
질문에 정확하게 답변하세요.
<end_of_turn>
<start_of_turn>user
{title}
[사건 보고서]
{question}\n<end_of_turn>\n<start_of_turn>model\n"""
prompt_ids = tokenizer(prompt, add_special_tokens=False)["input_ids"]
model_part = f"""{answer} {kind}<end_of_turn>"""
answer_ids = tokenizer(model_part, add_special_tokens=False)["input_ids"]
input_ids = prompt_ids + answer_ids
labels = [-100] * len(prompt_ids) + answer_ids
attention_mask = [1] * len(input_ids)
pad_len = max_length - len(input_ids)
input_ids += [tokenizer.pad_token_id] * pad_len
attention_mask += [0] * pad_len
labels += [-100] * pad_len
return {
"input_ids": input_ids,
"attention_mask": attention_mask,
"labels": labels,
}training_args = TrainingArguments(
output_dir=model_path,
per_device_train_batch_size=16,
gradient_accumulation_steps=2,
num_train_epochs=4,
learning_rate=2e-4,
bf16=True,
fp16=False,
gradient_checkpointing = False,
logging_steps=5,
eval_steps=300,
save_strategy="steps",
save_steps=300,
save_total_limit=2,
report_to="none",
lr_scheduler_type="cosine",
warmup_ratio=0.05,
optim="adamw_torch"
)[4844/4844 5:28:09, Epoch 4/4]
Step Training Loss
10 2.668900
20 2.386700
30 2.226000
40 2.026500
50 1.896800
60 1.778100
70 1.733700
80 1.678000
90 1.622100
100 1.583400
200 1.399400
300 1.343400
400 1.290700
500 1.286000
600 1.229200
700 1.226100
800 1.216800
900 1.204500
1000 1.158700
1100 1.153700
1200 1.157400
1300 1.106100
1400 1.114300
1500 1.091600
1600 1.087400
1700 1.087200
1800 1.093100
1900 1.082200
2000 1.084200
2100 1.090000
2200 1.084300
2300 1.058100
2400 1.062100
2500 1.021800
2600 1.028800
2700 1.034700
2800 1.040300
2900 1.033000
3000 1.016200
3100 1.015800
3200 0.983400
3300 1.010900
3400 1.015900
3500 1.028600
3600 1.019400
3700 0.971100
3800 0.947100
3900 0.984500
4000 0.965500
4100 0.973800
4200 0.968100
4300 0.969000
4400 0.953500
4500 0.988400
4505 0.942400
4510 0.931300
4515 0.973200
4520 0.989900
4525 0.979900
4530 0.963000
4535 0.981700
4540 0.953700
4545 0.963700
4550 0.961500
4555 0.972000
4560 0.958600
4565 0.970500
4570 0.987800
4575 0.974500
4580 0.968700
4585 0.982000
4590 0.961300
4595 0.968400
4600 0.966000
4700 0.998300
4800 0.966200
4805 0.973900
4810 0.975200
4815 0.974400
4820 0.973400
4825 0.972000
4830 0.960200
4835 0.961700
4840 0.974000
Evaluation Result :
{'eval_loss': 1.062408447265625, 'eval_runtime': 15.7428, 'eval_samples_per_second': 24.9, 'eval_steps_per_second': 3.113, 'epoch': 4.0}
Best checkpoint :
4510 0.931300(주)인정보
홈페이지 : http://www.ijbinfo.com
정보통신산업진흥원의 지원을 받아서 진행했습니다.(주)인정보
주소 : 서울시 금천구 가산동 60-5 갑올그레이트밸리A동 805호
연락처 : TEL : 02-3397-7765 FAX : 02-3397-7769 E-mail : sales@injungbo.co.kr
담당자 : 장형원(chyungwon@ijbinfo.com)