commit 8d678750b349b2857c55f98176be7dd19fcfccc0 Author: ModelHub XC Date: Fri Sep 11 06:39:14 2026 +0800 初始化项目,由ModelHub XC社区提供模型 Model: Rumiii/LlamaTron-RS1-MedThinker Source: Original Platform diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..ee2f058 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,38 @@ +*.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 +LlamaTron-RS1-MedThinker-Q4_K_M.gguf filter=lfs diff=lfs merge=lfs -text +medthinker-f16.gguf filter=lfs diff=lfs merge=lfs -text diff --git a/README.md b/README.md new file mode 100644 index 0000000..82591c2 --- /dev/null +++ b/README.md @@ -0,0 +1,248 @@ +--- +library_name: transformers +license: llama3.2 +datasets: +- OpenMed/Medical-Reasoning-SFT-Trinity-Mini +language: +- en +base_model: +- meta-llama/Llama-3.2-1B-Instruct +tags: +- transformers +- medical +- reasoning +- chain-of-thought +- clinical +- healthcare +- llama +- lora +- unsloth +- fine-tuned +--- + + +![Screenshot 2026-09-06 at 5.51.36 PM](https://cdn-uploads.huggingface.co/production/uploads/66e00ba55e4fd4bfead4a97c/q_eFcRr5SWrbv7SDSnEf6.png) + + +[![Base Model](https://img.shields.io/badge/Base-Llama%203.2%201B%20Instruct-00cfff?style=for-the-badge&logo=meta&logoColor=white)](https://huggingface.co/meta-llama/Llama-3.2-1B-Instruct) +[![Dataset](https://img.shields.io/badge/Dataset-810K%20Samples-38d996?style=for-the-badge&logo=databricks&logoColor=black)](https://huggingface.co/datasets/OpenMed/Medical-Reasoning-SFT-Trinity-Mini) +[![Method](https://img.shields.io/badge/Method-LoRA%20SFT-ffffff?style=for-the-badge)](https://github.com/unslothai/unsloth) +[![Hardware](https://img.shields.io/badge/Hardware-RTX%20A6000-ffcc00?style=for-the-badge&logo=nvidia&logoColor=black)](https://www.nvidia.com) + +--- + + + +
+ +## What is LlamaTron RS1 MedThinker? + +Most medical language models are trained to retrieve answers. LlamaTron RS1 MedThinker was trained to **reason** through them. + +Built on Meta's Llama 3.2 1B Instruct and fine-tuned on 810,374 medical chain-of-thought samples, MedThinker doesn't just return a diagnosis — it works through the differential, explains the pathophysiology behind its conclusion, gives dose-specific treatment steps, and tells you exactly when to escalate care. + +The reasoning pattern mirrors that of a junior physician presenting a case: structured, explainable, and clinically grounded. + +
+ +## Demo + +**Model Output — Step-by-Step Clinical Reasoning** + +![LlamaTron RS1 MedThinker Output](https://cdn-uploads.huggingface.co/production/uploads/66e00ba55e4fd4bfead4a97c/izPsyNhqNZ_C5mZ7B4HNw.png) + +
+ +## Output Format + +Every response follows a strict four-part clinical structure: + +``` +DIAGNOSIS Primary diagnosis with key differentials +REASONING Clinical logic, pathophysiology, and decision trail +IMMEDIATE TREATMENT Prioritised, dose-specific intervention steps +RED FLAGS Escalation criteria and emergency triggers +``` + +**Example — Input:** + +``` +3yo boy, barking cough, stridor, worse at night. Diagnosis and treatment? +``` + +**Example — Output:** + +``` +DIAGNOSIS: Viral croup (laryngotracheobronchitis). +Differentials: epiglottitis, foreign body aspiration, bacterial tracheitis. + +REASONING: The classic triad of barking cough, inspiratory stridor, and nocturnal +worsening in a toddler is pathognomonic for croup. Caused by parainfluenza virus +producing subglottic edema. Nighttime worsening occurs due to supine positioning +increasing mucosal congestion. Age 6 months to 3 years is the peak incidence window. +Epiglottitis is deprioritised given the absence of drooling, tripod posturing, +or toxic appearance. + +IMMEDIATE TREATMENT: +- Dexamethasone 0.6mg/kg PO/IM single dose (reduces subglottic edema within 2-6h) +- Nebulised epinephrine 5ml of 1:1000 if moderate-severe stridor present at rest +- Humidified cool air — supportive, reduces mucosal congestion +- Keep child calm — agitation significantly worsens stridor +- Oxygen via mask if SpO2 drops below 92% + +RED FLAGS: Call emergency services immediately if stridor is present at rest and +not improving, child is drooling or cannot swallow, cyanosis appears, or the child +becomes exhausted. These indicate impending airway obstruction requiring intubation. +``` + +
+ +## Training Details + +| Parameter | Value | +|---|---| +| Base Model | meta-llama/Llama-3.2-1B-Instruct | +| Fine-Tune Method | LoRA SFT via Unsloth | +| LoRA Rank | 32 | +| LoRA Alpha | 64 | +| Target Modules | q, k, v, o, gate, up, down projections | +| Sequence Length | 2048 | +| Batch Size | 16 per device | +| Gradient Accumulation | 2 steps — effective batch size 32 | +| Learning Rate | 2e-4 | +| Optimizer | AdamW 8-bit | +| Precision | BF16 | +| Packing | Enabled | +| Hardware | NVIDIA RTX A6000 48GB | +| Framework | Unsloth + TRL | + +
+ +## Dataset + +Trained on [OpenMed/Medical-Reasoning-SFT-Trinity-Mini](https://huggingface.co/datasets/OpenMed/Medical-Reasoning-SFT-Trinity-Mini), generated using `arcee-ai/Trinity-Mini`. + +| Metric | Value | +|---|---| +| Total Samples | 810,374 | +| Total Tokens | 1.52 Billion | +| Reasoning Tokens | 977 Million | +| Content Tokens | 542 Million | +| Language | English | + +Each sample contains two components: the **content** (the answer) and the **reasoning_content** (the chain-of-thought trace that produced it). Training on both means the model internalised not just medical knowledge, but the structured thinking process behind clinical decision-making. + +Dataset credit: Maziyar P. + +
+ +## Quickstart + +### Installation + +```bash +pip install torch transformers accelerate +``` + +### Inference + +```python +import torch +from transformers import AutoTokenizer, LlamaForCausalLM + +MODEL_PATH = "Rumiii/LlamaTron-RS1-MedThinker" + +tokenizer = AutoTokenizer.from_pretrained(MODEL_PATH) +model = LlamaForCausalLM.from_pretrained( + MODEL_PATH, + torch_dtype=torch.bfloat16, + device_map="auto", +) +model.eval() + +FEW_SHOT = """CASE: 2yo girl, high fever, tugging right ear, irritable, not sleeping. + +DIAGNOSIS: Acute otitis media (AOM). Differentials: otitis externa, teething. + +REASONING: Unilateral ear tugging with fever and irritability in a toddler is the +classic AOM presentation. Peak incidence at 6mo-2yr due to horizontal Eustachian +tube anatomy impairing drainage. + +IMMEDIATE TREATMENT: +- Amoxicillin 90mg/kg/day divided BID x 10 days +- Ibuprofen/paracetamol for pain and fever +- Re-evaluate in 48-72h if no improvement + +RED FLAGS: Refer immediately if mastoid swelling, facial palsy, or no improvement +after 72h of antibiotics.""" + +def ask(question: str) -> str: + prompt = ( + f"<|begin_of_text|>" + f"<|start_header_id|>system<|end_header_id|>\n" + f"You are LlamaTron RS1 MedThinker, a clinical medical assistant. " + f"Always use the structured format shown.<|eot_id|>" + f"<|start_header_id|>user<|end_header_id|>\n" + f"Answer this case using structured format:\n\n{FEW_SHOT}<|eot_id|>" + f"<|start_header_id|>assistant<|end_header_id|>\n{FEW_SHOT}<|eot_id|>" + f"<|start_header_id|>user<|end_header_id|>\nCASE: {question}<|eot_id|>" + f"<|start_header_id|>assistant<|end_header_id|>\n" + ) + inputs = tokenizer(prompt, return_tensors="pt").to(model.device) + input_len = inputs["input_ids"].shape[1] + with torch.no_grad(): + out = model.generate( + **inputs, + max_new_tokens=400, + temperature=0.35, + top_p=0.85, + do_sample=True, + repetition_penalty=1.2, + pad_token_id=tokenizer.eos_token_id, + ) + raw = tokenizer.decode(out[0][input_len:], skip_special_tokens=False) + for stop in ["<|eot_id|>", "<|end_of_text|>", "<|start_header_id|>"]: + if stop in raw: + raw = raw[:raw.index(stop)] + return raw.strip() + +# Run +print(ask("68yo woman, chest pain radiating to left arm, diaphoresis, nausea. BP 90/60, HR 110.")) +``` + +
+ +## Important Notes on Inference + +This model benefits significantly from **few-shot prompting**. Because the fine-tuning dataset emphasised reasoning content over instruction-following format, providing a single worked example in the prompt before your real question enforces the structured output reliably. The quickstart code above includes this pattern — do not remove the `FEW_SHOT` block. + +Recommended inference parameters: + +| Parameter | Value | Reason | +|---|---|---| +| temperature | 0.35 | Confident without hallucinating | +| top_p | 0.85 | Cuts low-probability tokens | +| repetition_penalty | 1.2 | Prevents reasoning loops | +| max_new_tokens | 400-512 | Sufficient for full structured response | + +
+ +## Disclaimer + +LlamaTron RS1 MedThinker is intended strictly for **research and educational purposes**. It is not a substitute for professional medical advice, clinical diagnosis, or treatment decisions. All outputs must be reviewed by a qualified medical professional before any clinical application. The authors accept no liability for decisions made on the basis of this model's outputs. + +
+ +## Citation + +```bibtex +@model{llamatron_rs1_medthinker_2026, + title = {LlamaTron RS1 MedThinker}, + author = {Rumiii}, + year = {2026}, + base_model = {meta-llama/Llama-3.2-1B-Instruct}, + dataset = {OpenMed/Medical-Reasoning-SFT-Trinity-Mini}, + method = {LoRA SFT via Unsloth}, + url = {https://huggingface.co/Rumiii/LlamaTron-RS1-MedThinker} +} +``` \ No newline at end of file diff --git a/chat_template.jinja b/chat_template.jinja new file mode 100644 index 0000000..1bad6a0 --- /dev/null +++ b/chat_template.jinja @@ -0,0 +1,93 @@ +{{- bos_token }} +{%- if custom_tools is defined %} + {%- set tools = custom_tools %} +{%- endif %} +{%- if not tools_in_user_message is defined %} + {%- set tools_in_user_message = true %} +{%- endif %} +{%- if not date_string is defined %} + {%- if strftime_now is defined %} + {%- set date_string = strftime_now("%d %b %Y") %} + {%- else %} + {%- set date_string = "26 Jul 2024" %} + {%- endif %} +{%- endif %} +{%- if not tools is defined %} + {%- set tools = none %} +{%- endif %} + +{#- This block extracts the system message, so we can slot it into the right place. #} +{%- if messages[0]['role'] == 'system' %} + {%- set system_message = messages[0]['content']|trim %} + {%- set messages = messages[1:] %} +{%- else %} + {%- set system_message = "" %} +{%- endif %} + +{#- System message #} +{{- "<|start_header_id|>system<|end_header_id|>\n\n" }} +{%- if tools is not none %} + {{- "Environment: ipython\n" }} +{%- endif %} +{{- "Cutting Knowledge Date: December 2023\n" }} +{{- "Today Date: " + date_string + "\n\n" }} +{%- if tools is not none and not tools_in_user_message %} + {{- "You have access to the following functions. To call a function, please respond with JSON for a function call." }} + {{- 'Respond in the format {"name": function name, "parameters": dictionary of argument name and its value}.' }} + {{- "Do not use variables.\n\n" }} + {%- for t in tools %} + {{- t | tojson(indent=4) }} + {{- "\n\n" }} + {%- endfor %} +{%- endif %} +{{- system_message }} +{{- "<|eot_id|>" }} + +{#- Custom tools are passed in a user message with some extra guidance #} +{%- if tools_in_user_message and not tools is none %} + {#- Extract the first user message so we can plug it in here #} + {%- if messages | length != 0 %} + {%- set first_user_message = messages[0]['content']|trim %} + {%- set messages = messages[1:] %} + {%- else %} + {{- raise_exception("Cannot put tools in the first user message when there's no first user message!") }} +{%- endif %} + {{- '<|start_header_id|>user<|end_header_id|>\n\n' -}} + {{- "Given the following functions, please respond with a JSON for a function call " }} + {{- "with its proper arguments that best answers the given prompt.\n\n" }} + {{- 'Respond in the format {"name": function name, "parameters": dictionary of argument name and its value}.' }} + {{- "Do not use variables.\n\n" }} + {%- for t in tools %} + {{- t | tojson(indent=4) }} + {{- "\n\n" }} + {%- endfor %} + {{- first_user_message + "<|eot_id|>"}} +{%- endif %} + +{%- for message in messages %} + {%- if not (message.role == 'ipython' or message.role == 'tool' or 'tool_calls' in message) %} + {{- '<|start_header_id|>' + message['role'] + '<|end_header_id|>\n\n'+ message['content'] | trim + '<|eot_id|>' }} + {%- elif 'tool_calls' in message %} + {%- if not message.tool_calls|length == 1 %} + {{- raise_exception("This model only supports single tool-calls at once!") }} + {%- endif %} + {%- set tool_call = message.tool_calls[0].function %} + {{- '<|start_header_id|>assistant<|end_header_id|>\n\n' -}} + {{- '{"name": "' + tool_call.name + '", ' }} + {{- '"parameters": ' }} + {{- tool_call.arguments | tojson }} + {{- "}" }} + {{- "<|eot_id|>" }} + {%- elif message.role == "tool" or message.role == "ipython" %} + {{- "<|start_header_id|>ipython<|end_header_id|>\n\n" }} + {%- if message.content is mapping or message.content is iterable %} + {{- message.content | tojson }} + {%- else %} + {{- message.content }} + {%- endif %} + {{- "<|eot_id|>" }} + {%- endif %} +{%- endfor %} +{%- if add_generation_prompt %} + {{- '<|start_header_id|>assistant<|end_header_id|>\n\n' }} +{%- endif %} diff --git a/config.json b/config.json new file mode 100644 index 0000000..9f4fa6c --- /dev/null +++ b/config.json @@ -0,0 +1,37 @@ +{ + "architectures": [ + "LlamaForCausalLM" + ], + "attention_bias": false, + "attention_dropout": 0.0, + "bos_token_id": 128000, + "torch_dtype": "bfloat16", + "eos_token_id": 128009, + "head_dim": 64, + "hidden_act": "silu", + "hidden_size": 2048, + "initializer_range": 0.02, + "intermediate_size": 8192, + "max_position_embeddings": 131072, + "mlp_bias": false, + "model_type": "llama", + "num_attention_heads": 32, + "num_hidden_layers": 16, + "num_key_value_heads": 8, + "pad_token_id": 128004, + "pretraining_tp": 1, + "rms_norm_eps": 1e-05, + "rope_parameters": { + "factor": 32.0, + "high_freq_factor": 4.0, + "low_freq_factor": 1.0, + "original_max_position_embeddings": 8192, + "rope_theta": 500000.0, + "rope_type": "llama3" + }, + "tie_word_embeddings": true, + "unsloth_fixed": true, + "unsloth_version": "2026.3.11", + "use_cache": false, + "vocab_size": 128256 +} \ No newline at end of file diff --git a/model.safetensors b/model.safetensors new file mode 100644 index 0000000..97a252b --- /dev/null +++ b/model.safetensors @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4bca3b1c5836b1844858ceb121a93bd814632d1b6ccb541a49682f0dffde1fe3 +size 2471645608 diff --git a/tokenizer.json b/tokenizer.json new file mode 100644 index 0000000..1c1d8d5 --- /dev/null +++ b/tokenizer.json @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6b9e4e7fb171f92fd137b777cc2714bf87d11576700a1dcd7a399e7bbe39537b +size 17209920 diff --git a/tokenizer_config.json b/tokenizer_config.json new file mode 100644 index 0000000..232eff2 --- /dev/null +++ b/tokenizer_config.json @@ -0,0 +1,19 @@ +{ + "backend": "tokenizers", + "bos_token": "<|begin_of_text|>", + "clean_up_tokenization_spaces": true, + "eos_token": "<|eot_id|>", + "from_slow": true, + "is_local": false, + "legacy": false, + "model_input_names": [ + "input_ids", + "attention_mask" + ], + "model_max_length": 131072, + "pad_token": "<|finetune_right_pad_id|>", + "padding_side": "left", + "tokenizer_class": "TokenizersBackend", + "unk_token": null, + "chat_template": "{{- bos_token }}\n{%- if custom_tools is defined %}\n {%- set tools = custom_tools %}\n{%- endif %}\n{%- if not tools_in_user_message is defined %}\n {%- set tools_in_user_message = true %}\n{%- endif %}\n{%- if not date_string is defined %}\n {%- if strftime_now is defined %}\n {%- set date_string = strftime_now(\"%d %b %Y\") %}\n {%- else %}\n {%- set date_string = \"26 Jul 2024\" %}\n {%- endif %}\n{%- endif %}\n{%- if not tools is defined %}\n {%- set tools = none %}\n{%- endif %}\n\n{#- This block extracts the system message, so we can slot it into the right place. #}\n{%- if messages[0]['role'] == 'system' %}\n {%- set system_message = messages[0]['content']|trim %}\n {%- set messages = messages[1:] %}\n{%- else %}\n {%- set system_message = \"\" %}\n{%- endif %}\n\n{#- System message #}\n{{- \"<|start_header_id|>system<|end_header_id|>\\n\\n\" }}\n{%- if tools is not none %}\n {{- \"Environment: ipython\\n\" }}\n{%- endif %}\n{{- \"Cutting Knowledge Date: December 2023\\n\" }}\n{{- \"Today Date: \" + date_string + \"\\n\\n\" }}\n{%- if tools is not none and not tools_in_user_message %}\n {{- \"You have access to the following functions. To call a function, please respond with JSON for a function call.\" }}\n {{- 'Respond in the format {\"name\": function name, \"parameters\": dictionary of argument name and its value}.' }}\n {{- \"Do not use variables.\\n\\n\" }}\n {%- for t in tools %}\n {{- t | tojson(indent=4) }}\n {{- \"\\n\\n\" }}\n {%- endfor %}\n{%- endif %}\n{{- system_message }}\n{{- \"<|eot_id|>\" }}\n\n{#- Custom tools are passed in a user message with some extra guidance #}\n{%- if tools_in_user_message and not tools is none %}\n {#- Extract the first user message so we can plug it in here #}\n {%- if messages | length != 0 %}\n {%- set first_user_message = messages[0]['content']|trim %}\n {%- set messages = messages[1:] %}\n {%- else %}\n {{- raise_exception(\"Cannot put tools in the first user message when there's no first user message!\") }}\n{%- endif %}\n {{- '<|start_header_id|>user<|end_header_id|>\\n\\n' -}}\n {{- \"Given the following functions, please respond with a JSON for a function call \" }}\n {{- \"with its proper arguments that best answers the given prompt.\\n\\n\" }}\n {{- 'Respond in the format {\"name\": function name, \"parameters\": dictionary of argument name and its value}.' }}\n {{- \"Do not use variables.\\n\\n\" }}\n {%- for t in tools %}\n {{- t | tojson(indent=4) }}\n {{- \"\\n\\n\" }}\n {%- endfor %}\n {{- first_user_message + \"<|eot_id|>\"}}\n{%- endif %}\n\n{%- for message in messages %}\n {%- if not (message.role == 'ipython' or message.role == 'tool' or 'tool_calls' in message) %}\n {{- '<|start_header_id|>' + message['role'] + '<|end_header_id|>\\n\\n'+ message['content'] | trim + '<|eot_id|>' }}\n {%- elif 'tool_calls' in message %}\n {%- if not message.tool_calls|length == 1 %}\n {{- raise_exception(\"This model only supports single tool-calls at once!\") }}\n {%- endif %}\n {%- set tool_call = message.tool_calls[0].function %}\n {{- '<|start_header_id|>assistant<|end_header_id|>\\n\\n' -}}\n {{- '{\"name\": \"' + tool_call.name + '\", ' }}\n {{- '\"parameters\": ' }}\n {{- tool_call.arguments | tojson }}\n {{- \"}\" }}\n {{- \"<|eot_id|>\" }}\n {%- elif message.role == \"tool\" or message.role == \"ipython\" %}\n {{- \"<|start_header_id|>ipython<|end_header_id|>\\n\\n\" }}\n {%- if message.content is mapping or message.content is iterable %}\n {{- message.content | tojson }}\n {%- else %}\n {{- message.content }}\n {%- endif %}\n {{- \"<|eot_id|>\" }}\n {%- endif %}\n{%- endfor %}\n{%- if add_generation_prompt %}\n {{- '<|start_header_id|>assistant<|end_header_id|>\\n\\n' }}\n{%- endif %}\n" +} \ No newline at end of file