From 175172a70b29030c6aad1eda4af7eb5c9b14ed7b Mon Sep 17 00:00:00 2001 From: ModelHub XC Date: Thu, 30 Jul 2026 06:55:18 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96=E9=A1=B9=E7=9B=AE?= =?UTF-8?q?=EF=BC=8C=E7=94=B1ModelHub=20XC=E7=A4=BE=E5=8C=BA=E6=8F=90?= =?UTF-8?q?=E4=BE=9B=E6=A8=A1=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Model: PeterPaker123/Qwen2.5-7B-Vietnamese-Medical-NER-GRPO Source: Original Platform --- .gitattributes | 36 +++++++ README.md | 206 +++++++++++++++++++++++++++++++++++++++++ chat_template.jinja | 1 + config.json | 61 ++++++++++++ generation_config.json | 13 +++ model.safetensors | 3 + tokenizer.json | 3 + tokenizer_config.json | 33 +++++++ 8 files changed, 356 insertions(+) create mode 100644 .gitattributes create mode 100644 README.md create mode 100644 chat_template.jinja create mode 100644 config.json create mode 100644 generation_config.json create mode 100644 model.safetensors create mode 100644 tokenizer.json create mode 100644 tokenizer_config.json diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..52373fe --- /dev/null +++ b/.gitattributes @@ -0,0 +1,36 @@ +*.7z filter=lfs diff=lfs merge=lfs -text +*.arrow filter=lfs diff=lfs merge=lfs -text +*.bin filter=lfs diff=lfs merge=lfs -text +*.bz2 filter=lfs diff=lfs merge=lfs -text +*.ckpt filter=lfs diff=lfs merge=lfs -text +*.ftz filter=lfs diff=lfs merge=lfs -text +*.gz filter=lfs diff=lfs merge=lfs -text +*.h5 filter=lfs diff=lfs merge=lfs -text +*.joblib filter=lfs diff=lfs merge=lfs -text +*.lfs.* filter=lfs diff=lfs merge=lfs -text +*.mlmodel filter=lfs diff=lfs merge=lfs -text +*.model filter=lfs diff=lfs merge=lfs -text +*.msgpack filter=lfs diff=lfs merge=lfs -text +*.npy filter=lfs diff=lfs merge=lfs -text +*.npz filter=lfs diff=lfs merge=lfs -text +*.onnx filter=lfs diff=lfs merge=lfs -text +*.ot filter=lfs diff=lfs merge=lfs -text +*.parquet filter=lfs diff=lfs merge=lfs -text +*.pb filter=lfs diff=lfs merge=lfs -text +*.pickle filter=lfs diff=lfs merge=lfs -text +*.pkl filter=lfs diff=lfs merge=lfs -text +*.pt filter=lfs diff=lfs merge=lfs -text +*.pth filter=lfs diff=lfs merge=lfs -text +*.rar filter=lfs diff=lfs merge=lfs -text +*.safetensors filter=lfs diff=lfs merge=lfs -text +saved_model/**/* filter=lfs diff=lfs merge=lfs -text +*.tar.* filter=lfs diff=lfs merge=lfs -text +*.tar filter=lfs diff=lfs merge=lfs -text +*.tflite filter=lfs diff=lfs merge=lfs -text +*.tgz filter=lfs diff=lfs merge=lfs -text +*.wasm filter=lfs diff=lfs merge=lfs -text +*.xz filter=lfs diff=lfs merge=lfs -text +*.zip filter=lfs diff=lfs merge=lfs -text +*.zst filter=lfs diff=lfs merge=lfs -text +*tfevents* filter=lfs diff=lfs merge=lfs -text +tokenizer.json filter=lfs diff=lfs merge=lfs -text diff --git a/README.md b/README.md new file mode 100644 index 0000000..e78ce76 --- /dev/null +++ b/README.md @@ -0,0 +1,206 @@ +--- +library_name: transformers +tags: [ner, medical, vietnamese, qwen, grpo, rlhf, peft, lora, text-extraction] +--- + +# Model Card for Vietnamese Medical NER (Qwen2.5-7B SFT + GRPO) + + +This model is a generative Large Language Model (based on the Qwen/Qwen2.5-7B architecture) strictly fine-tuned for **Vietnamese Medical Named Entity Recognition (NER)**. It accurately extracts Symptoms, Diseases, Medical Procedures, Drugs, etc. from Vietnamese medical texts and outputs them in a highly structured JSON format. + +## Model Details + +### Model Description + + +This model transitions away from traditional token-classification BERT models by utilizing an LLM as an intelligent extraction agent. It reads Vietnamese medical texts (such as clinical notes, user questions, or news) and outputs structured JSON lists. + +The model was trained using an advanced two-stage alignment pipeline: +1. **Stage 1: Supervised Fine-Tuning (SFT)** to teach the model the strict JSON extraction schema and Vietnamese medical terminology. +2. **Stage 2: Group Relative Policy Optimization (GRPO)** using Reinforcement Learning (RL) with LoRA. The model was mathematically penalized via shifted-bound and exponential scaling reward functions for hallucinations and missed entities, forcing it to achieve near-perfect Precision, Recall, and Type Accuracy. + +- **Developed by:** PeterPaker123 +- **Model type:** Causal Language Model (Generative NER) +- **Language(s) (NLP):** Vietnamese (`vi`) +- **License:** Apache 2.0 (Derived from Qwen base models) +- **Finetuned from model:** `Qwen/Qwen2.5-7B-Instruct` + +## Uses + + + +### Direct Use + + +Unlike traditional NER models constrained to a fixed set of predefined classes, this model supports **dynamic, prompt-defined entity extraction**. It acts as an intelligent agent that extracts *any* medical or clinical entity type specified in the system prompt. + +Commonly targeted categories include (but are not limited to): +* **`SYMPTOM_AND_DISEASE`**: Symptoms, signs of illness, diseases, or medical conditions. +* **`MEDICAL_PROCEDURE`**: Medical procedures, surgeries, therapies, or diagnostic methods. +* **`DRUG`**: Names of medicines, drugs, vitamins, or supplements. +* **`BODY_PART / ANATOMY`**: Anatomical locations, organs, or body structures. +* **`DOSAGE & MEASUREMENT`**: Medical quantities, medication dosages, or frequencies. +* **`DEMOGRAPHICS`**: Patient-specific identifiers (e.g., Age, Gender, Occupation). + +**How it works:** You simply define the desired categories and their descriptions in the `system` prompt, and the model will strictly adhere to extracting only those requested types into the required JSON schema. + +### Downstream Use + + +This model can be integrated into downstream healthcare applications such as: +- Medical chatbot prompt enrichment (RAG pipelines). +- Automated summarization of telehealth transcripts. +- Clinical knowledge graph construction. + +### Out-of-Scope Use + + +- **Medical Diagnosis or Triage:** This model is strictly an extraction tool. It does not diagnose, prescribe, or provide medical advice. +- **General Conversation:** The model has been aggressively aligned to output JSON lists. It will perform poorly at standard conversational AI tasks. +- **Other Entity Types:** The model was trained to ignore Demographic data (Names, Ages, Locations, Occupations, Dates). Attempting to extract these will likely yield empty lists. + +## Bias, Risks, and Limitations + + +- **Clinical Disclaimer:** This model is an AI research tool and **must not** be used for automated medical diagnosis, treatment planning, or life-or-death triage without human oversight. +- **Language Limitation:** The model is exclusively trained for the Vietnamese language. +- **Hallucination Residuals:** While GRPO significantly reduces hallucinations, Generative LLMs may occasionally hallucinate or alter the spelling of extracted text. + +### Recommendations + + + +Users (both direct and downstream) should be made aware of the risks, biases and limitations of the model. Extracted entities in a clinical setting must be validated by a human medical professional or a deterministic cross-checking system. + +## How to Get Started with the Model + +Use the code below to get started with the model. + +```python +import json +from transformers import AutoModelForCausalLM, AutoTokenizer + +model_id = "PeterPaker123/Qwen2.5-7B-Vietnamese-Medical-NER-GRPO" + +tokenizer = AutoTokenizer.from_pretrained(model_id) +model = AutoModelForCausalLM.from_pretrained(model_id, device_map="auto", torch_dtype="auto") + +prompt = [ + { + "role": "system", + "content": "You are a medical expert. Your task is to identify and extract medical entities from the given text.\nThe entity types to extract are:\n- SYMPTOM_AND_DISEASE: Symptoms, signs of illness, diseases, or medical conditions.\n- MEDICAL_PROCEDURE: Medical procedures, surgeries, therapies, or diagnostic methods.\n- DRUG: Names of medicines, drugs, vitamins, or supplements.\n\nReturn the result as a JSON list containing dictionaries with \"entity\" and \"type\" keys. If no relevant entities are found, return an empty list []" + }, + { + "role": "user", + "content": "Text: Trẻ sơ sinh 2 tháng tuổi vàng mặt , hay khóc thét có phải bị vàng da nhân não không ?" + } +] + +inputs = tokenizer.apply_chat_template(prompt, return_tensors="pt", add_generation_prompt=True).to(model.device) +outputs = model.generate(inputs, max_new_tokens=256, temperature=0.0) + +response = tokenizer.decode(outputs[0][inputs.shape[-1]:], skip_special_tokens=True) +print(response) +# Expected Output: [{"entity": "vàng mặt", "type": "SYMPTOM_AND_DISEASE"}, {"entity": "khóc thét", "type": "SYMPTOM_AND_DISEASE"}, {"entity": "vàng da nhân não", "type": "SYMPTOM_AND_DISEASE"}] +``` + +## Training Details + +### Training Data + + +This model was trained on a consolidated corpus derived from four premier Vietnamese medical datasets. The original datasets contained diverse entity tags which were mapped down to our three primary clinical targets (`SYMPTOM_AND_DISEASE`, `MEDICAL_PROCEDURE`, `DRUG`). + +| Dataset Name | Domain / Source | Total Samples | Key Original Entities | +|---|---|---|---| +| **VietBioNER** | Tuberculosis (TB) clinical treatment | ~1,700 | Symptom & Disease, Diagnostic Procedure, Location | +| **PhoNER_COVID19** | COVID-19 pandemic surveillance | ~10,000 | Symptom & Disease, Patient ID, Age, Location | +| **ViMQ** | Healthcare dialogue systems | ~10,000 | Symptom, Disease, Drug, Procedure, Body Structure | +| **ViMedNER** | General Medical NER | ~10,000 | Symptom, Disease, Drug, Body Part, Procedure | + +*Data Split:* 75% used for Phase 1 (SFT) and 25% used for Phase 2 (GRPO/RL). + +### Training Procedure + + + +#### Preprocessing [optional] + +- Prompts were formatted into strict ChatML format using text-only templates. +- Target entities outside the three core classes were stripped from the ground truth to force the model to ignore non-medical demographic data. + +#### Training Hyperparameters + +- **Training regime:** `bf16` mixed precision +- **Phase 1 (SFT):** Full parameter fine-tuning, Max Seq Len 4096, Batch Size 2, Gradient Accumulation 8, LR 2e-5, Cosine Scheduler. +- **Phase 2 (GRPO):** LoRA target modules (`q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj, down_proj`), Rank 16, Alpha 32. 4 Generations per prompt, Temperature 0.5. Full AdamW optimizer. + +## Model Examination + + + +## Technical Specifications + +### Model Architecture and Objective + +Qwen2.5-7B Architecture. Causal Language Modeling objective heavily modified via RLHF/GRPO to act as an entity extraction classifier. + +#### Hardware + +NVIDIA RTX PRO 6000 Blackwell + +#### Software + +- `transformers` +- `trl` (SFTTrainer, GRPOTrainer) +- `peft` +- `torch` (with `sdpa` attention) + +## Citation + + + +**BibTeX:** + +```bibtex +@inproceedings{vietbioner, + title = "{A Named Entity Recognition Corpus for Vietnamese Biomedical Texts to Support Tuberculosis Treatment}", + author = "Phan, Uyen and Nguyen, Phuong and Nguyen, Nhung", + booktitle = "Proceedings of the 13th Language Resources and Evaluation Conference", + year = "2022", + publisher = "European Language Resources Association" +} + +@inproceedings{PhoNER_COVID19, + title = {{COVID-19 Named Entity Recognition for Vietnamese}}, + author = {Thinh Hung Truong and Mai Hoang Dao and Dat Quoc Nguyen}, + booktitle = {Proceedings of the 2021 Conference of the North American Chapter of the Association for Computational Linguistics: Human Language Technologies}, + year = {2021} +} + +@article{vimq2023, + title={ViMQ: A Vietnamese Medical Question Dataset for Healthcare Dialogue System Development}, + author={Vu, Hieu M. and Phan, Long and Nguyen, Nhung and others}, + year={2023} +} + +@article{10.4108/eetinis.v11i3.5221, + author={Pham Van Duong and Tien-Dat Trinh and Minh-Tien Nguyen and Huy-The Vu and Minh Chuan Pham and Tran Manh Tuan and Le Hoang Son}, + title={ViMedNER: A Medical Named Entity Recognition Dataset for Vietnamese}, + journal={EAI Endorsed Transactions on Industrial Networks and Intelligent Systems}, + volume={11}, + number={4}, + publisher={EAI}, + year={2024}, + doi={10.4108/eetinis.v11i3.5221} +} +``` + +## Glossary + + + +- **NER:** Named Entity Recognition +- **SFT:** Supervised Fine-Tuning +- **GRPO:** Group Relative Policy Optimization (An RL algorithm optimized for Generative Models) +- **LoRA:** Low-Rank Adaptation \ No newline at end of file diff --git a/chat_template.jinja b/chat_template.jinja new file mode 100644 index 0000000..3299a2e --- /dev/null +++ b/chat_template.jinja @@ -0,0 +1 @@ +{% for message in messages %}{% set role = message['role'] %}{% if role == 'assistant' %}{% set role = 'model' %}{% endif %}{{ '' + role + '\n' + message['content'] + '\n' }}{% endfor %}{% if add_generation_prompt %}{{ 'model\n' }}{% endif %} \ No newline at end of file diff --git a/config.json b/config.json new file mode 100644 index 0000000..722df32 --- /dev/null +++ b/config.json @@ -0,0 +1,61 @@ +{ + "architectures": [ + "Qwen2ForCausalLM" + ], + "attention_dropout": 0.0, + "bos_token_id": null, + "dtype": "bfloat16", + "eos_token_id": 151645, + "hidden_act": "silu", + "hidden_size": 3584, + "initializer_range": 0.02, + "intermediate_size": 18944, + "layer_types": [ + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention" + ], + "max_position_embeddings": 32768, + "max_window_layers": 28, + "model_type": "qwen2", + "num_attention_heads": 28, + "num_hidden_layers": 28, + "num_key_value_heads": 4, + "pad_token_id": 151643, + "rms_norm_eps": 1e-06, + "rope_parameters": { + "rope_theta": 1000000.0, + "rope_type": "default" + }, + "sliding_window": null, + "tie_word_embeddings": false, + "transformers_version": "5.0.0", + "use_cache": false, + "use_sliding_window": false, + "vocab_size": 152064 +} diff --git a/generation_config.json b/generation_config.json new file mode 100644 index 0000000..94fb73e --- /dev/null +++ b/generation_config.json @@ -0,0 +1,13 @@ +{ + "do_sample": true, + "eos_token_id": [ + 151645, + 151643 + ], + "pad_token_id": 151643, + "repetition_penalty": 1.05, + "temperature": 0.7, + "top_k": 20, + "top_p": 0.8, + "transformers_version": "5.0.0" +} diff --git a/model.safetensors b/model.safetensors new file mode 100644 index 0000000..1ab3108 --- /dev/null +++ b/model.safetensors @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3c7c5360f18e1a4ff3e083561b06bfe537bb9e1457740c5240d3c09b1a948eb3 +size 15231272152 diff --git a/tokenizer.json b/tokenizer.json new file mode 100644 index 0000000..5e65314 --- /dev/null +++ b/tokenizer.json @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1a7aabe7a3b44651592a99607bb33066e6965260336be9218cccd53af161491d +size 11422060 diff --git a/tokenizer_config.json b/tokenizer_config.json new file mode 100644 index 0000000..73c422b --- /dev/null +++ b/tokenizer_config.json @@ -0,0 +1,33 @@ +{ + "add_prefix_space": false, + "backend": "tokenizers", + "bos_token": null, + "clean_up_tokenization_spaces": false, + "eos_token": "<|im_end|>", + "errors": "replace", + "extra_special_tokens": [ + "<|im_start|>", + "<|im_end|>", + "<|object_ref_start|>", + "<|object_ref_end|>", + "<|box_start|>", + "<|box_end|>", + "<|quad_start|>", + "<|quad_end|>", + "<|vision_start|>", + "<|vision_end|>", + "<|vision_pad|>", + "<|image_pad|>", + "<|video_pad|>" + ], + "is_local": true, + "max_length": null, + "model_max_length": 131072, + "pad_to_multiple_of": null, + "pad_token": "<|endoftext|>", + "pad_token_type_id": 0, + "padding_side": "right", + "split_special_tokens": false, + "tokenizer_class": "TokenizersBackend", + "unk_token": null +}