Views
No views yet
unsloth/Phi-3.5-mini-instruct (an optimized 4-bit version of microsoft/Phi-3-mini-4k-instruct). It has been fine-tuned using Low-Rank Adaptation (LoRA) specifically for the task of generating multiple-choice questions (MCQs) in JSON format based on provided context text. The fine-tuning was performed using the script provided in the context.microsoft/Phi-3-mini-4k-instruct is licensed under the MIT License. The fine-tuned adapters are subject to the base model's license and potentially the license of the training data (asanchez75/medical_textbooks_mcq). Unsloth code is typically Apache 2.0. Please check the specific licenses for compliance.unsloth/Phi-3.5-mini-instruct (4-bit quantized version).unsloth/Phi-3.5-mini-instruct model (in 4-bit) and then applying the saved LoRA adapters using the PEFT library.asanchez75/medical_textbooks_mcq training dataset, which is derived from medical literature."path/to/your/saved/adapters/" with the actual path where you saved the adapter files (adapter_model.safetensors, adapter_config.json, etc.) and the tokenizer (tokenizer.json, etc.).1import torch
2from transformers import AutoTokenizer
3from unsloth import FastLanguageModel
4from peft import PeftModel
5import json # For parsing output
6
7# --- Configuration ---
8base_model_name = "unsloth/Phi-3.5-mini-instruct"
9adapter_path = "path/to/your/saved/adapters/" # <--- CHANGE THIS
10max_seq_length = 4096
11
12# --- 1. Load Base Model and Tokenizer (4-bit) ---
13print("Loading base model and tokenizer...")
14model, tokenizer = FastLanguageModel.from_pretrained(
15 model_name = base_model_name,
16 max_seq_length = max_seq_length,
17 dtype = None,
18 load_in_4bit = True, # Load base in 4-bit
19 device_map = "auto",
20)
21print("Base model loaded in 4-bit.")
22
23# Set padding token if necessary
24if tokenizer.pad_token is None:
25 if tokenizer.pad_token_id is None:
26 tokenizer.pad_token = tokenizer.eos_token
27 else:
28 tokenizer.pad_token = tokenizer.convert_ids_to_tokens(tokenizer.pad_token_id)
29tokenizer.padding_side = 'right'
30print(f"Tokenizer pad token: {tokenizer.pad_token}, ID: {tokenizer.pad_token_id}")
31
32# --- 2. Load LoRA Adapters ---
33print(f"Loading LoRA adapters from {adapter_path}...")
34# Load adapters onto the base model
35model = PeftModel.from_pretrained(model, adapter_path)
36print("LoRA adapters loaded.")
37
38# --- 3. Prepare for Inference ---
39print("Preparing combined model for inference...")
40FastLanguageModel.for_inference(model)
41print("Model ready for inference.")
42
43# --- 4. Prepare Inference Prompt ---
44test_context = "Human beings are fallible and it is in their nature to make mistakes. An error of omission occurs when a necessary action has not been taken." # Example context
45inference_prompt = f"<|user|>\nContext:\n{test_context}\n\nGenerate ONE valid multiple-choice question based strictly on the context above. Output ONLY the valid JSON object representing the question.\nMCQ JSON:<|end|>\n<|assistant|>\n"
46
47inputs = tokenizer(inference_prompt, return_tensors="pt", truncation=True, max_length=max_seq_length).to("cuda")
48
49# --- 5. Generate Output ---
50print("Generating MCQ JSON...")
51with torch.no_grad():
52 outputs = model.generate(
53 input_ids = inputs["input_ids"],
54 max_new_tokens=512, # Max length for the generated JSON
55 temperature=0.1, # Low temperature for more deterministic output
56 top_p=0.9,
57 do_sample=True,
58 pad_token_id=tokenizer.pad_token_id if tokenizer.pad_token_id is not None else tokenizer.eos_token_id
59 )
60
61# Decode the generated part
62output_ids = outputs[0][inputs["input_ids"].shape[1]:]
63generated_json_part = tokenizer.decode(output_ids, skip_special_tokens=True).strip()
64
65print("\n--- Generated Output ---")
66print(generated_json_part)
67
68# --- 6. (Optional) Validate JSON ---
69try:
70 # Clean up potential markdown fences
71 if generated_json_part.startswith("```json"):
72 generated_json_part = generated_json_part[len("```json"):].strip()
73 if generated_json_part.endswith("```"):
74 generated_json_part = generated_json_part[:-len("```")].strip()
75
76 parsed_json = json.loads(generated_json_part)
77 print("\nGenerated JSON Parsed Successfully:")
78 print(json.dumps(parsed_json, indent=2))
79except json.JSONDecodeError as e:
80 print(f"\nGenerated output IS NOT valid JSON. Error: {e}")
811{
2 "question": "What is the maximum duration of a temporary ban from practising as a disciplinary sanction in the medical profession?",
3 "option_a": "1 year",
4 "option_b": "2 years",
5 "option_c": "3 years",
6 "option_d": "5 years",
7 "correct_option": "C",
8 "explanation": "The correct answer is C, which states that the maximum duration of a temporary ban from practising as a disciplinary sanction in the medical profession is 3 years. This information is explicitly stated in the text, which mentions that a temporary ban from practising may be imposed for a maximum of three years. The other options are incorrect because they either underestimate or overestimate the maximum duration of the ban."
9}