--- library_name: transformers --- # Model Card for Model ID ## Model Details ### Model Description ``` 이 모델은 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.0 ``` ## Uses ```python from transformers import AutoModelForCausalLM, AutoTokenizer base_model = "chyungwon/police-report-analysis-model" tokenizer = AutoTokenizer.from_pretrained(base_model) model = AutoModelForCausalLM.from_pretrained( base_model, torch_dtype=torch.bfloat16, device_map="auto" ) question = """다음 사건 보고서를 통해서 당시 범죄 사건을 재구성해주고, 사건 유형을 분류해줘. [사건 보고서] 2024년 4월 25일, 서울 숭실대입구역 인근에서 이삿짐 화물차가 인도로 돌진해 60대 남성을 부상시킨 사건이 발생하였다. 현장 조사 결과, 화물차 운전자 김민수(35)는 사전에 브레이크 패드를 마모시키고 브레이크액에 물을 섞어 고장을 유발한 것으로 확인되었다. 사고 직후 김은 차 내부에 숨겨진 금고에서 현금 200만 원과 가죽 가방, 스마트폰을 꺼내 상가 안경원 직원에게 전달하고, 은행 계좌로 송금하였다. 경찰은 차량 GPS 기록, 브레이크 패드 마모 상태, CCTV 영상 조작 여부를 조사 중이며, 김은 교통사고처리특례법에 따라 치상 혐의로 입건되었다. 현재 수사는 김의 은행 송금 기록과 금고 내용물 확보를 통해 범죄 동기와 범행 방법을 파악 중이다. 사건은 아직 결말이 내려지지 않았으며, 추가 증거 확보가 필요하다.""" messages = [ {"role": "system", "content": """당신은 범행분석 AI 모델입니다. 질문에 정확하게 답변하세요."""}, {"role": "user", "content": question} ] inputs = tokenizer.apply_chat_template( messages, add_generation_prompt=True, return_tensors="pt", return_dict=True, ).to(model.device) model.eval() outputs = model.generate( **inputs, max_new_tokens=1024 * 2, temperature=0.1, do_sample=True, ) generated = outputs[0][inputs["input_ids"].shape[-1] :] answer = tokenizer.decode(generated, skip_special_tokens=True) print('사건 재구성 : ', answer) 사건 재구성 : 2024년 4월 25일 오후 1시 30분, 서울 숭실대입구역 인근에서 발생한 이삿짐 화물차 사고는 단순한 교통사고가 아니라 정교하게 계획된 절도 사건의 일환이었다. 화물차 운전자인 김민수(35)는 3개월 전부터 지역 상가에서 일하는 60대 남성(피해자)과의 금전적 갈등을 품고 있었다. 김은 피해자가 자신이 운영하던 작은 가게에서 물건을 훔쳐 가는 것을 목격하고, 그 사실을 폭로하면 자신의 사업이 망가질 위험이 있다고 판단했다. 이에 김은 피해자를 제거하고 동시에 가게에서 훔친 물건을 회수하려는 계획을 세웠다. 계획 단계에서 김은 화물차의 브레이크 패드를 미리 마모시키고, 브레이크액에 물을 섞어 브레이크가 갑자기 작동하지 않도록 조작했다. 또한, 차 내부에 숨겨진 작은 금고에 훔친 물건(현금 200만 원, 가죽 가방, 스마트폰)을 보관했다. 사고 발생 시 피해자가 차에 부딪혀 부상을 입으면, 김은 즉시 차를 멈추고 금고를 열어 물건을 꺼내어 상가 안경원 직원에게 전달했다. 이 직원은 김이 사전에 협상한 인물로, 물건을 수거해 김의 은행 계좌로 송금하도록 했다. 실행 단계에서 김은 화물차를 숭실대입구역 인근 인도에 주차한 뒤, 피해자가 차를 지나가던 순간 브레이크를 고의로 작동시키지 않도록 조작했다. 차가 인도를 돌진하면서 피해자는 차체에 부딪혀 다리를 크게 다쳤고, 즉시 병원으로 이송되었다. 김은 사고 직후 차를 멈추고, 피해자가 부상으로 움직일 수 없다는 상황을 이용해 금고를 열어 물건을 꺼냈다. 그는 물건을 상가 안경원 직원에게 전달하고, 직원은 즉시 현금과 물건을 김의 은행 계좌로 송금했다. 은폐 단계에서는 김은 사고 현장을 빠르게 정리하고, 차 내부에 남은 흔적을 최소화했다. 그는 차를 다른 지역으로 이동시켜 CCTV가 감시되지 않는 곳에 주차했다. 또한, 사고 당시 차가 정지한 위치와 피해자의 부상 정도를 이용해 경찰이 사고를 단순한 교통사고로 판단하도록 유도했다. 김은 이후 은행 계좌에서 물건을 현금으로 인출해 현지 편의점에서 현금화하고, 남은 금액은 가짜 신분증으로 만든 가상 계좌에 송금했다. 수사 과정에서 경찰은 CCTV 영상을 분석해 화물차가 인도를 돌진한 순간을 확인했고, 브레이크 패드 마모와 브레이크액에 물이 섞인 흔적을 발견했다. 또한, 김이 사전에 상가 안경원 직원과 연락을 주고받았다는 증거가 확보되었다. 그러나 김은 교통사고처리특례법에 따라 치상 혐의로 입건되었으며, 현재는 구속영장이 신청 중이다. 사건은 아직 수사 단계이며, 김이 실제로 물건을 훔쳤는지, 그리고 피해자와의 갈등이 범행 동기에 얼마나 영향을 미쳤는지에 대한 추가 조사가 필요하다. 사건은 아직 결말이 내려지지 않았으며, 경찰은 김의 은행 계좌와 상가 안경원 직원의 증언을 통해 범행의 전모를 파악하려 하고 있다. 사건 유형 : 절도 ``` ## Training Details ``` 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) ``` #### Preprocessing [optional] ``` 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"""system 당신은 범행분석 AI 모델입니다. 질문에 정확하게 답변하세요. user {title} [사건 보고서] {question}\n\nmodel\n""" prompt_ids = tokenizer(prompt, add_special_tokens=False)["input_ids"] model_part = f"""{answer} {kind}""" 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 Hyperparameters ``` 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" ) ``` #### Speeds, Sizes, Times [optional] ``` [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 ``` ## Model Card Authors [optional] ``` (주)인정보 홈페이지 : http://www.ijbinfo.com 정보통신산업진흥원의 지원을 받아서 진행했습니다. ``` ## Model Card Contact ``` (주)인정보 주소 : 서울시 금천구 가산동 60-5 갑올그레이트밸리A동 805호 연락처 : TEL : 02-3397-7765 FAX : 02-3397-7769 E-mail : sales@injungbo.co.kr 담당자 : 장형원(chyungwon@ijbinfo.com) ```