Text Generation
Transformers
Safetensors
English
qwen2
qwen2.5
qwen
code-generation
python
python-code-generation
dpo
direct-preference-optimization
preference-learning
lora
parameter-efficient-fine-tuning
conversational
text-generation-inference
Instructions to use ranjanrajib/DPO-trained-Qwen2.5-Python-Coder-7B with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use ranjanrajib/DPO-trained-Qwen2.5-Python-Coder-7B with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="ranjanrajib/DPO-trained-Qwen2.5-Python-Coder-7B") messages = [ {"role": "user", "content": "Who are you?"}, ] pipe(messages)# pip install -U transformers accelerate # Load model directly from transformers import AutoTokenizer, AutoModelForCausalLM tokenizer = AutoTokenizer.from_pretrained("ranjanrajib/DPO-trained-Qwen2.5-Python-Coder-7B") model = AutoModelForCausalLM.from_pretrained("ranjanrajib/DPO-trained-Qwen2.5-Python-Coder-7B", device_map="auto") messages = [ {"role": "user", "content": "Who are you?"}, ] inputs = tokenizer.apply_chat_template( messages, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt", ).to(model.device) outputs = model.generate(**inputs, max_new_tokens=256) print(tokenizer.decode(outputs[0][inputs["input_ids"].shape[-1]:])) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use ranjanrajib/DPO-trained-Qwen2.5-Python-Coder-7B with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "ranjanrajib/DPO-trained-Qwen2.5-Python-Coder-7B" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "ranjanrajib/DPO-trained-Qwen2.5-Python-Coder-7B", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/ranjanrajib/DPO-trained-Qwen2.5-Python-Coder-7B
- SGLang
How to use ranjanrajib/DPO-trained-Qwen2.5-Python-Coder-7B with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "ranjanrajib/DPO-trained-Qwen2.5-Python-Coder-7B" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "ranjanrajib/DPO-trained-Qwen2.5-Python-Coder-7B", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "ranjanrajib/DPO-trained-Qwen2.5-Python-Coder-7B" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "ranjanrajib/DPO-trained-Qwen2.5-Python-Coder-7B", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Docker Model Runner
How to use ranjanrajib/DPO-trained-Qwen2.5-Python-Coder-7B with Docker Model Runner:
docker model run hf.co/ranjanrajib/DPO-trained-Qwen2.5-Python-Coder-7B
Update README.md
Browse files
README.md
CHANGED
|
@@ -23,773 +23,49 @@ tags:
|
|
| 23 |
- parameter-efficient-fine-tuning
|
| 24 |
---
|
| 25 |
|
| 26 |
-
|
| 27 |
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
\- en
|
| 31 |
-
|
| 32 |
-
license: apache-2.0
|
| 33 |
-
|
| 34 |
-
library_name: transformers
|
| 35 |
-
|
| 36 |
-
pipeline_tag: text-generation
|
| 37 |
-
|
| 38 |
-
base_model:
|
| 39 |
-
|
| 40 |
-
\- Qwen/Qwen2.5-Coder-7B-Instruct
|
| 41 |
-
|
| 42 |
-
datasets:
|
| 43 |
-
|
| 44 |
-
\- bigcode/bigcodebench
|
| 45 |
-
|
| 46 |
-
\- Muennighoff/mbpp
|
| 47 |
-
|
| 48 |
-
\- openai/openai_humaneval
|
| 49 |
-
|
| 50 |
-
tags:
|
| 51 |
-
|
| 52 |
-
\- qwen2.5
|
| 53 |
-
|
| 54 |
-
\- qwen
|
| 55 |
-
|
| 56 |
-
\- code-generation
|
| 57 |
-
|
| 58 |
-
\- python
|
| 59 |
|
| 60 |
-
|
| 61 |
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
\- direct-preference-optimization
|
| 65 |
-
|
| 66 |
-
\- preference-learning
|
| 67 |
-
|
| 68 |
-
\- lora
|
| 69 |
-
|
| 70 |
-
\- parameter-efficient-fine-tuning
|
| 71 |
-
|
| 72 |
-
\---
|
| 73 |
-
# Qwen2.5-Coder-7B-Instruct — DPO Fine-Tuned for Python## Model at a Glance
|
| 74 |
-
This model is a ****Python-focused, DPO fine-tuned version of Qwen2.5-Coder-7B-Instruct****, designed to improve the model's ability to generate ****functionally correct Python code****.
|
| 75 |
-
|
| 76 |
-
The model was trained using ****Direct Preference Optimization (DPO)**** with automatically constructed preference pairs. Candidate Python solutions were generated for programming problems and evaluated by executing them against unit tests. Solutions that passed the required tests were used as preferred examples, while solutions that failed tests were used as rejected examples.
|
| 77 |
|
| 78 |
The resulting model was evaluated against the original Qwen2.5-Coder-7B-Instruct model on held-out programming problems.
|
|
|
|
| 79 |
### What changed?
|
| 80 |
The base model:
|
| 81 |
-
|
| 82 |
-
****Qwen2.5-Coder-7B-Instruct****
|
| 83 |
|
| 84 |
was fine-tuned using:
|
| 85 |
-
|
| 86 |
-
****DPO + LoRA + execution-based preference data****
|
| 87 |
|
| 88 |
The resulting model demonstrates improved coding performance on the evaluated held-out benchmark:
|
| 89 |
|
| 90 |
| Metric | Qwen2.5-Coder-7B-Instruct | DPO Model | Improvement |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 91 |
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
| Pass@1 | 41.87% | ****45.22%**** | ****+3.35 pp**** |
|
| 95 |
-
|
| 96 |
-
| Pass@5 | 48.87% | ****51.10%**** | ****+2.23 pp**** |
|
| 97 |
-
|
| 98 |
-
| Pass@10 | 50.99% | ****53.16%**** | ****+2.17 pp**** |
|
| 99 |
-
|
| 100 |
-
| Tests passed per answer | 66.20% | ****69.41%**** | ****+3.21 pp**** |
|
| 101 |
-
|
| 102 |
-
The primary result is the improvement in ****Pass@1****, meaning that a single generated solution was more likely to produce a correct solution on the evaluated programming problems.
|
| 103 |
-
|
| 104 |
-
The model also showed improved Pass@5, Pass@10, and partial test coverage.
|
| 105 |
|
| 106 |
---
|
| 107 |
|
| 108 |
-
**
|
| 109 |
|
| 110 |
-
|
| 111 |
-
## Downloading and using### The merged model (what most people want)
|
| 112 |
-
\`\`\`python
|
| 113 |
|
|
|
|
| 114 |
from transformers import AutoModelForCausalLM, AutoTokenizer
|
| 115 |
|
| 116 |
model = AutoModelForCausalLM.from_pretrained(
|
| 117 |
-
|
| 118 |
-
|
| 119 |
-
|
| 120 |
tok = AutoTokenizer.from_pretrained("ranjanrajib/DPO-trained-Qwen2.5-Coder-7B")
|
| 121 |
|
| 122 |
msgs = [{"role": "user", "content": "Write a Python function that merges overlapping intervals."}]
|
| 123 |
-
|
| 124 |
text = tok.apply_chat_template(msgs, tokenize=False, add_generation_prompt=True)
|
| 125 |
-
|
| 126 |
out = model.generate(**tok(text, return_tensors="pt").to(model.device), max_new_tokens=512)
|
| 127 |
-
|
| 128 |
-
print(tok.decode(out[0], skip_special_tokens=True))
|
| 129 |
-
|
| 130 |
-
\`\`\`
|
| 131 |
-
|
| 132 |
-
Or fetch the files without loading them (~14 GB, four shards):
|
| 133 |
-
|
| 134 |
-
\`\`\`bash
|
| 135 |
-
|
| 136 |
-
hf download ranjanrajib/DPO-trained-Qwen2.5-Coder-7B --exclude "adapter/*" --local-dir ./d4
|
| 137 |
-
|
| 138 |
-
\`\`\`
|
| 139 |
-
### The LoRA adapter only (308 MB)
|
| 140 |
-
The adapter lives in \`adapter/\`. Applying it to the base model gives the same result as the
|
| 141 |
-
|
| 142 |
-
merged weights, at a fraction of the download.
|
| 143 |
-
|
| 144 |
-
\`\`\`bash
|
| 145 |
-
|
| 146 |
-
hf download ranjanrajib/DPO-trained-Qwen2.5-Coder-7B --include "adapter/*" --local-dir ./d4-lora
|
| 147 |
-
|
| 148 |
-
\`\`\`
|
| 149 |
-
|
| 150 |
-
\`\`\`python
|
| 151 |
-
|
| 152 |
-
import torch
|
| 153 |
-
|
| 154 |
-
from peft import PeftModel
|
| 155 |
-
|
| 156 |
-
from transformers import AutoModelForCausalLM
|
| 157 |
-
|
| 158 |
-
BASE = "Qwen/Qwen2.5-Coder-7B-Instruct"
|
| 159 |
-
|
| 160 |
-
REVISION = "c03e6d358207e414f1eca0bb1891e29f1db0e242" # the snapshot this was trained against
|
| 161 |
-
|
| 162 |
-
base = AutoModelForCausalLM.from_pretrained(
|
| 163 |
-
|
| 164 |
-
BASE, revision=REVISION, dtype=torch.bfloat16, device_map="auto")
|
| 165 |
-
|
| 166 |
-
model = PeftModel.from_pretrained(
|
| 167 |
-
|
| 168 |
-
base, "ranjanrajib/DPO-trained-Qwen2.5-Coder-7B", subfolder="adapter")
|
| 169 |
-
|
| 170 |
-
\`\`\`
|
| 171 |
-
|
| 172 |
-
---
|
| 173 |
-
|
| 174 |
-
**# ## VRAM Requirements
|
| 175 |
-
|
| 176 |
-
The base model and the merged trained model use the same VRAM. The merge changes weight values, not tensor shapes: both models have the same 7.6B parameters and architecture, so the model weights occupy the same amount of bf16 memory.
|
| 177 |
-
|
| 178 |
-
| Component | bf16 VRAM |
|
| 179 |
-
| --- | ---: |
|
| 180 |
-
| Weights (base or merged D4) | 14.19 GiB |
|
| 181 |
-
| KV cache, per token | 56 KiB |
|
| 182 |
-
| Activations / workspace | ~0.5–1 GiB |
|
| 183 |
-
| **Practical single-stream total** | **~15–16 GiB** |
|
| 184 |
-
|
| 185 |
-
---
|
| 186 |
-
|
| 187 |
-
Why Use This Model?**
|
| 188 |
-
|
| 189 |
-
If your primary use case is ****Python code generation****, this model is intended to be a stronger alternative to the original Qwen2.5-Coder-7B-Instruct model based on the evaluation performed in this project.
|
| 190 |
-
|
| 191 |
-
It is particularly relevant for users who want to:
|
| 192 |
-
|
| 193 |
-
* generate Python functions and implementations
|
| 194 |
-
|
| 195 |
-
* solve programming problems
|
| 196 |
-
|
| 197 |
-
* generate code that needs to satisfy functional requirements
|
| 198 |
-
|
| 199 |
-
* improve first-attempt coding correctness
|
| 200 |
-
|
| 201 |
-
* experiment with DPO-trained code-generation models
|
| 202 |
-
|
| 203 |
-
* study execution-based preference optimization
|
| 204 |
-
|
| 205 |
-
* build research or evaluation pipelines for Python code generation
|
| 206 |
-
|
| 207 |
-
The main motivation for the fine-tuning was not simply to make the model generate more code.
|
| 208 |
-
|
| 209 |
-
It was to encourage the model toward ****solutions that work****.
|
| 210 |
-
|
| 211 |
-
The preference data therefore used actual program execution and unit-test results rather than subjective judgments about whether generated code **looked** correct.
|
| 212 |
-
|
| 213 |
-
---
|
| 214 |
-
# How Is It Different From Qwen2.5-Coder-7B-Instruct?
|
| 215 |
-
The underlying model architecture and capabilities come from ****Qwen2.5-Coder-7B-Instruct****.
|
| 216 |
-
|
| 217 |
-
This model adds a preference-optimization stage on top of that model.
|
| 218 |
-
|
| 219 |
-
Conceptually:
|
| 220 |
-
|
| 221 |
-
\`\`\`text
|
| 222 |
-
|
| 223 |
-
Qwen2.5-Coder-7B-Instruct
|
| 224 |
-
|
| 225 |
-
│
|
| 226 |
-
|
| 227 |
-
▼
|
| 228 |
-
|
| 229 |
-
Generate multiple Python
|
| 230 |
-
|
| 231 |
-
candidate solutions
|
| 232 |
-
|
| 233 |
-
│
|
| 234 |
-
|
| 235 |
-
▼
|
| 236 |
-
|
| 237 |
-
Execute candidates
|
| 238 |
-
|
| 239 |
-
against tests
|
| 240 |
-
|
| 241 |
-
│
|
| 242 |
-
|
| 243 |
-
┌─────┴─────┐
|
| 244 |
-
|
| 245 |
-
▼ ▼
|
| 246 |
-
|
| 247 |
-
Pass Fail
|
| 248 |
-
|
| 249 |
-
│ │
|
| 250 |
-
|
| 251 |
-
▼ ▼
|
| 252 |
-
|
| 253 |
-
Chosen Rejected
|
| 254 |
-
|
| 255 |
-
│ │
|
| 256 |
-
|
| 257 |
-
└─────┬─────┘
|
| 258 |
-
|
| 259 |
-
▼
|
| 260 |
-
|
| 261 |
-
DPO
|
| 262 |
-
|
| 263 |
-
│
|
| 264 |
-
|
| 265 |
-
▼
|
| 266 |
-
|
| 267 |
-
LoRA Adapter
|
| 268 |
-
|
| 269 |
-
│
|
| 270 |
-
|
| 271 |
-
▼
|
| 272 |
-
|
| 273 |
-
Python-focused model
|
| 274 |
-
|
| 275 |
-
\`\`\`
|
| 276 |
-
|
| 277 |
-
The goal is to shift the model toward coding behaviors associated with solutions that successfully execute against the available tests.
|
| 278 |
-
### Important distinction
|
| 279 |
-
This is ****not a new foundation model****.
|
| 280 |
-
|
| 281 |
-
It is a parameter-efficient fine-tuned adapter for Qwen2.5-Coder-7B-Instruct.
|
| 282 |
-
|
| 283 |
-
The base model remains unchanged.
|
| 284 |
-
|
| 285 |
-
---
|
| 286 |
-
# What Kind of Model Is This?### Primary task
|
| 287 |
-
****Python code generation****
|
| 288 |
-
### Model family
|
| 289 |
-
Qwen2.5-Coder
|
| 290 |
-
### Base model
|
| 291 |
-
\`Qwen/Qwen2.5-Coder-7B-Instruct\`
|
| 292 |
-
### Fine-tuning
|
| 293 |
-
Direct Preference Optimization (DPO)
|
| 294 |
-
### Parameter-efficient method
|
| 295 |
-
LoRA
|
| 296 |
-
### Precision
|
| 297 |
-
bfloat16
|
| 298 |
-
### Quantization
|
| 299 |
-
None
|
| 300 |
-
### Model size
|
| 301 |
-
7.7B-parameter base model
|
| 302 |
-
### Adapter
|
| 303 |
-
Approximately 80.7M trainable parameters
|
| 304 |
-
|
| 305 |
-
---
|
| 306 |
-
# Performance
|
| 307 |
-
The model was evaluated against the original Qwen2.5-Coder-7B-Instruct using a controlled benchmark consisting of 508 held-out BigCodeBench programming problems.
|
| 308 |
-
|
| 309 |
-
The same prompts, generation settings, random seeds, number of samples, and grading procedure were used for both models.
|
| 310 |
-
## Pass@k
|
| 311 |
-
| Metric | Base Model | DPO Model |
|
| 312 |
-
|
| 313 |
-
| ------- | ---------: | ---------: |
|
| 314 |
-
|
| 315 |
-
| Pass@1 | 41.87% | ****45.22%**** |
|
| 316 |
-
|
| 317 |
-
| Pass@5 | 48.87% | ****51.10%**** |
|
| 318 |
-
|
| 319 |
-
| Pass@10 | 50.99% | ****53.16%**** |
|
| 320 |
-
|
| 321 |
-
The improvement in Pass@1 is approximately ****3.35 percentage points****.
|
| 322 |
-
## Partial Correctness
|
| 323 |
-
The average proportion of tests passed by each generated answer increased from:
|
| 324 |
-
|
| 325 |
-
****66.20% → 69.41%****
|
| 326 |
-
|
| 327 |
-
This is a secondary metric intended to provide additional information about functional correctness beyond binary problem-level pass/fail.
|
| 328 |
-
|
| 329 |
-
---
|
| 330 |
-
# Paired Problem-Level Analysis
|
| 331 |
-
The evaluation used the same 508 problems for both models, allowing direct comparison of model behavior on individual problems.
|
| 332 |
-
|
| 333 |
-
For the first generated answer:
|
| 334 |
-
|
| 335 |
-
| Base → DPO | Problems |
|
| 336 |
-
|
| 337 |
-
| --------------------- | -------: |
|
| 338 |
-
|
| 339 |
-
| Correct → Correct | 186 |
|
| 340 |
-
|
| 341 |
-
| Correct → Incorrect | 17 |
|
| 342 |
-
|
| 343 |
-
| Incorrect → Correct | 41 |
|
| 344 |
-
|
| 345 |
-
| Incorrect → Incorrect | 264 |
|
| 346 |
-
|
| 347 |
-
The DPO model converted 41 problems from incorrect to correct while 17 previously correct problems became incorrect.
|
| 348 |
-
|
| 349 |
-
This provides additional evidence that the aggregate improvement is associated with meaningful changes in problem-level behavior rather than simply differences in the evaluated problem sets.
|
| 350 |
-
|
| 351 |
-
---
|
| 352 |
-
# Who Should Use This Model?
|
| 353 |
-
This model is most appropriate for:
|
| 354 |
-
### Python Developers
|
| 355 |
-
Developers interested in experimenting with a locally hosted code-generation model that has been specifically fine-tuned toward execution-validated solutions.
|
| 356 |
-
### AI/ML Researchers
|
| 357 |
-
Researchers studying:
|
| 358 |
-
|
| 359 |
-
* DPO
|
| 360 |
-
|
| 361 |
-
* preference learning
|
| 362 |
-
|
| 363 |
-
* LLM alignment
|
| 364 |
-
|
| 365 |
-
* code-generation models
|
| 366 |
-
|
| 367 |
-
* automated preference construction
|
| 368 |
-
|
| 369 |
-
* execution-based evaluation
|
| 370 |
-
|
| 371 |
-
* parameter-efficient fine-tuning
|
| 372 |
-
### LLM Evaluation Researchers
|
| 373 |
-
The model can also be useful as an experimental model for comparing:
|
| 374 |
-
|
| 375 |
-
* base versus preference-tuned models
|
| 376 |
-
|
| 377 |
-
* coding correctness
|
| 378 |
-
|
| 379 |
-
* Pass@k
|
| 380 |
-
|
| 381 |
-
* partial test coverage
|
| 382 |
-
|
| 383 |
-
* preference-learning behavior
|
| 384 |
-
|
| 385 |
-
---
|
| 386 |
-
# When Should You Prefer the Original Qwen Model?
|
| 387 |
-
This model should not automatically be considered better for every possible task.
|
| 388 |
-
|
| 389 |
-
The experiment specifically focused on ****Python code generation****.
|
| 390 |
-
|
| 391 |
-
If your application requires broad general-purpose instruction following, other programming languages, or capabilities that were not evaluated here, you should benchmark both models for your specific workload.
|
| 392 |
-
|
| 393 |
-
The reported improvement should therefore be interpreted as:
|
| 394 |
-
|
| 395 |
-
\> ****Improved performance on the evaluated Python coding benchmark, not a guarantee of improvement across every coding or general-purpose task.****
|
| 396 |
-
|
| 397 |
-
---
|
| 398 |
-
|
| 399 |
-
The base model and the trained model use the same VRAM.
|
| 400 |
-
|
| 401 |
-
The merge changed weight values, not shapes — same 7.6B parameters, same
|
| 402 |
-
|
| 403 |
-
architecture — so they are byte-for-byte the same size.
|
| 404 |
-
|
| 405 |
-
┌───────────────────────────────┬────────────┐
|
| 406 |
-
|
| 407 |
-
│ │ bf16 VRAM │
|
| 408 |
-
|
| 409 |
-
├───────────────────────────────┼────────────┤
|
| 410 |
-
|
| 411 |
-
│ Weights (base or merged D4) │ 14.19 GiB │
|
| 412 |
-
|
| 413 |
-
├───────────────────────────────┼────────────┤
|
| 414 |
-
|
| 415 |
-
│ KV cache, per token │ 56 KiB │
|
| 416 |
-
|
| 417 |
-
├───────────────────────────────┼────────────┤
|
| 418 |
-
|
| 419 |
-
│ Activations / workspace │ ~0.5–1 GiB │
|
| 420 |
-
|
| 421 |
-
├───────────────────────────────┼────────────┤
|
| 422 |
-
|
| 423 |
-
│ Practical single-stream total │ ~15–16 GiB │
|
| 424 |
-
|
| 425 |
-
└───────────────────────────────┴────────────┘
|
| 426 |
-
|
| 427 |
-
---
|
| 428 |
-
# Model Architecture and Training
|
| 429 |
-
The model starts from:
|
| 430 |
-
|
| 431 |
-
\`Qwen/Qwen2.5-Coder-7B-Instruct\`
|
| 432 |
-
|
| 433 |
-
The base model contains approximately 7.7 billion parameters.
|
| 434 |
-
|
| 435 |
-
Rather than updating all parameters, the experiment uses ****LoRA-based parameter-efficient fine-tuning****.
|
| 436 |
-
|
| 437 |
-
The resulting adapter contains approximately 80.7 million trainable parameters.
|
| 438 |
-
|
| 439 |
-
The adapter is approximately 308 MB.
|
| 440 |
-
|
| 441 |
-
---
|
| 442 |
-
# DPO Training## Why DPO?
|
| 443 |
-
Direct Preference Optimization provides a method for optimizing a language model directly from preference pairs without requiring a separate reward-model training stage.
|
| 444 |
-
|
| 445 |
-
For this experiment, a preference pair has the form:
|
| 446 |
-
|
| 447 |
-
\`\`\`text
|
| 448 |
-
|
| 449 |
-
Problem
|
| 450 |
-
|
| 451 |
-
│
|
| 452 |
-
|
| 453 |
-
├── Candidate A → passes tests → chosen
|
| 454 |
-
|
| 455 |
-
│
|
| 456 |
-
|
| 457 |
-
└── Candidate B → fails tests → rejected
|
| 458 |
-
|
| 459 |
-
\`\`\`
|
| 460 |
-
|
| 461 |
-
DPO then learns to increase the relative likelihood of the chosen response compared with the rejected response.
|
| 462 |
-
|
| 463 |
-
---
|
| 464 |
-
# Preference Data Construction
|
| 465 |
-
The preference dataset was generated specifically for this experiment.
|
| 466 |
-
|
| 467 |
-
It was constructed from programming problems drawn from:
|
| 468 |
-
|
| 469 |
-
* BigCodeBench
|
| 470 |
-
|
| 471 |
-
* MBPP
|
| 472 |
-
|
| 473 |
-
* HumanEval
|
| 474 |
-
|
| 475 |
-
* handwritten programming problems
|
| 476 |
-
### Training Data
|
| 477 |
-
| Dataset | License |
|
| 478 |
-
|
| 479 |
-
| ------------ | ---------- |
|
| 480 |
-
|
| 481 |
-
| BigCodeBench | Apache 2.0 |
|
| 482 |
-
|
| 483 |
-
| MBPP | CC BY 4.0 |
|
| 484 |
-
|
| 485 |
-
| HumanEval | MIT |
|
| 486 |
-
|
| 487 |
-
Candidate solutions were generated automatically.
|
| 488 |
-
|
| 489 |
-
Five generation strategies were used:
|
| 490 |
-
|
| 491 |
-
* normal
|
| 492 |
-
|
| 493 |
-
* straightforward
|
| 494 |
-
|
| 495 |
-
* edge-case-focused
|
| 496 |
-
|
| 497 |
-
* alternative
|
| 498 |
-
|
| 499 |
-
* optimized
|
| 500 |
-
|
| 501 |
-
Multiple candidates were generated for each problem.
|
| 502 |
-
|
| 503 |
-
Every candidate was then executed in a Docker sandbox against the associated unit tests.
|
| 504 |
-
|
| 505 |
-
The resulting execution outcome was used to construct chosen/rejected preference pairs.
|
| 506 |
-
|
| 507 |
-
---
|
| 508 |
-
# Preference Dataset
|
| 509 |
-
After filtering and deduplication:
|
| 510 |
-
|
| 511 |
-
* 1,326 preference pairs
|
| 512 |
-
|
| 513 |
-
* 221 programming problems
|
| 514 |
-
|
| 515 |
-
* 933 training pairs
|
| 516 |
-
|
| 517 |
-
* 114 validation pairs
|
| 518 |
-
|
| 519 |
-
The dataset was split by ****problem****, rather than by individual preference pair.
|
| 520 |
-
|
| 521 |
-
This prevents different candidate solutions from the same underlying programming problem from being distributed across training and validation.
|
| 522 |
-
|
| 523 |
-
No human preference labels were used.
|
| 524 |
-
|
| 525 |
-
No external LLM was used as a preference judge.
|
| 526 |
-
|
| 527 |
-
The preference signal was generated from objective unit-test execution.
|
| 528 |
-
|
| 529 |
-
---
|
| 530 |
-
# DPO Configuration
|
| 531 |
-
The primary DPO configuration was:
|
| 532 |
-
|
| 533 |
-
| Parameter | Value |
|
| 534 |
-
| --- | --- |
|
| 535 |
-
| Rank | 32 |
|
| 536 |
-
| Alpha | 64 |
|
| 537 |
-
| Dropout | 0.05 |
|
| 538 |
-
| Target modules | Attention and MLP projections |
|
| 539 |
-
| Epochs | 2 |
|
| 540 |
-
| Maximum sequence length | 1,024 |
|
| 541 |
-
| Batch size | 4 |
|
| 542 |
-
| Gradient accumulation | 4 |
|
| 543 |
-
| Effective batch size | 16 |
|
| 544 |
-
| Optimizer | AdamW |
|
| 545 |
-
| Gradient clipping | 1.0 |
|
| 546 |
-
| Gradient checkpointing | Enabled |
|
| 547 |
-
## LoRA Configuration
|
| 548 |
-
| Parameter | Value |
|
| 549 |
-
| --- | --- |
|
| 550 |
-
| Rank | 32 |
|
| 551 |
-
| Alpha | 64 |
|
| 552 |
-
| Dropout | 0.05 |
|
| 553 |
-
| Target modules | Attention and MLP projections |
|
| 554 |
-
|
| 555 |
-
---
|
| 556 |
-
# Training Hardware
|
| 557 |
-
DPO training was performed on:
|
| 558 |
-
|
| 559 |
-
****NVIDIA RTX A6000 — 48 GB VRAM****
|
| 560 |
-
|
| 561 |
-
Training environment:
|
| 562 |
-
|
| 563 |
-
* CUDA 12.8
|
| 564 |
-
|
| 565 |
-
* PyTorch 2.11
|
| 566 |
-
|
| 567 |
-
* bfloat16
|
| 568 |
-
|
| 569 |
-
* gradient checkpointing
|
| 570 |
-
|
| 571 |
-
Peak GPU memory consumption was approximately 33.4 GiB.
|
| 572 |
-
|
| 573 |
-
---
|
| 574 |
-
# Evaluation Methodology
|
| 575 |
-
The primary evaluation benchmark consisted of:
|
| 576 |
-
|
| 577 |
-
****508 BigCodeBench programming problems****
|
| 578 |
-
|
| 579 |
-
The evaluation problems were reserved separately from the preference-training pool.
|
| 580 |
-
|
| 581 |
-
The same generation and grading procedure was applied to both models.
|
| 582 |
-
### Generation
|
| 583 |
-
* 10 answers per problem
|
| 584 |
-
|
| 585 |
-
* temperature: 0.2
|
| 586 |
-
|
| 587 |
-
* top-p: 0.95
|
| 588 |
-
|
| 589 |
-
* maximum new tokens: 512
|
| 590 |
-
|
| 591 |
-
* repetition penalty: 1.0
|
| 592 |
-
|
| 593 |
-
* sampling enabled
|
| 594 |
-
|
| 595 |
-
* identical random seeds for base and DPO models
|
| 596 |
-
### Pass@k
|
| 597 |
-
Pass@k was calculated using the standard unbiased estimator based on the number of correct samples among the generated candidates.
|
| 598 |
-
|
| 599 |
-
---
|
| 600 |
-
# Preference-Learning Diagnostics
|
| 601 |
-
The DPO training objective produced a strong preference signal on the training examples.
|
| 602 |
-
|
| 603 |
-
However, the validation results were substantially weaker.
|
| 604 |
-
|
| 605 |
-
| Metric | Training | Validation |
|
| 606 |
-
|
| 607 |
-
| ------------------- | -------: | --------------------: |
|
| 608 |
-
|
| 609 |
-
| Preference accuracy | ~84.4% | ~45.8% |
|
| 610 |
-
|
| 611 |
-
| Reward margin | Positive | Approximately neutral |
|
| 612 |
-
|
| 613 |
-
This indicates that the explicit preference signal learned during training did not generalize strongly to the validation preference examples.
|
| 614 |
-
|
| 615 |
-
At the same time, downstream coding performance improved on the held-out benchmark.
|
| 616 |
-
|
| 617 |
-
This is an important observation from the experiment.
|
| 618 |
-
|
| 619 |
-
---
|
| 620 |
-
# What Does This Mean?
|
| 621 |
-
The results should not be interpreted as proof that the model learned a broadly generalized notion of code quality.
|
| 622 |
-
|
| 623 |
-
Instead, they suggest that ****optimizing an automatically constructed preference objective can improve downstream coding performance even when explicit preference metrics show weak validation generalization.****
|
| 624 |
-
|
| 625 |
-
Several explanations are possible, including:
|
| 626 |
-
|
| 627 |
-
* differences between training and validation preference distributions
|
| 628 |
-
|
| 629 |
-
* imperfect test-derived preference labels
|
| 630 |
-
|
| 631 |
-
* overfitting to characteristics of the training preference pairs
|
| 632 |
-
|
| 633 |
-
* changes in generation behavior that are not fully captured by preference accuracy
|
| 634 |
-
|
| 635 |
-
These are hypotheses for further investigation rather than established conclusions.
|
| 636 |
-
|
| 637 |
-
---
|
| 638 |
-
# Important Limitations## No Human Preference Evaluation
|
| 639 |
-
No human preference study was performed.
|
| 640 |
-
|
| 641 |
-
The preference signal was derived from automated unit-test execution.
|
| 642 |
-
|
| 643 |
-
Therefore, this model should not be described as being aligned to human preferences based on this experiment.
|
| 644 |
-
## Unit Tests Are Imperfect
|
| 645 |
-
Passing the available tests does not guarantee that a solution is universally correct.
|
| 646 |
-
|
| 647 |
-
A test suite may fail to cover some edge cases or undesirable implementation behavior.
|
| 648 |
-
## Benchmark Source Overlap
|
| 649 |
-
The evaluation problems were held out at the problem level.
|
| 650 |
-
|
| 651 |
-
However, the preference-training data includes other BigCodeBench problems.
|
| 652 |
-
|
| 653 |
-
Therefore, the evaluation is ****problem-held-out****, but not completely source-family-disjoint.
|
| 654 |
-
## Python Focus
|
| 655 |
-
The primary objective and evaluation were focused on Python programming.
|
| 656 |
-
|
| 657 |
-
Performance should not be assumed to generalize to other programming languages without additional evaluation.
|
| 658 |
-
## Experimental Model
|
| 659 |
-
This is an experimental research model.
|
| 660 |
-
|
| 661 |
-
Users should evaluate it against their own workloads before using it in production.
|
| 662 |
-
|
| 663 |
-
---
|
| 664 |
-
# Reproducibility
|
| 665 |
-
The experiment documents:
|
| 666 |
-
|
| 667 |
-
* base model
|
| 668 |
-
|
| 669 |
-
* preference-data construction
|
| 670 |
-
|
| 671 |
-
* data sources
|
| 672 |
-
|
| 673 |
-
* dataset split methodology
|
| 674 |
-
|
| 675 |
-
* DPO configuration
|
| 676 |
-
|
| 677 |
-
* LoRA configuration
|
| 678 |
-
|
| 679 |
-
* training hardware
|
| 680 |
-
|
| 681 |
-
* generation configuration
|
| 682 |
-
|
| 683 |
-
* evaluation methodology
|
| 684 |
-
|
| 685 |
-
* random seed strategy
|
| 686 |
-
|
| 687 |
-
* benchmark methodology
|
| 688 |
-
|
| 689 |
-
* limitations
|
| 690 |
-
|
| 691 |
-
The objective is to make the experiment sufficiently transparent for others to reproduce, extend, or critique.
|
| 692 |
-
|
| 693 |
-
---
|
| 694 |
-
# Independent Research Project
|
| 695 |
-
This model was developed as an ****independent, out-of-office AI/ML research project****.
|
| 696 |
-
|
| 697 |
-
The project was conceived, designed, implemented, trained, evaluated, analyzed, and released independently.
|
| 698 |
-
|
| 699 |
-
The work covers the complete experimental lifecycle:
|
| 700 |
-
|
| 701 |
-
\`\`\`text
|
| 702 |
-
|
| 703 |
-
Research Question
|
| 704 |
-
|
| 705 |
-
↓
|
| 706 |
-
|
| 707 |
-
Experimental Design
|
| 708 |
-
|
| 709 |
-
↓
|
| 710 |
-
|
| 711 |
-
Preference Data Generation
|
| 712 |
-
|
| 713 |
-
↓
|
| 714 |
-
|
| 715 |
-
Automated Evaluation
|
| 716 |
-
|
| 717 |
-
↓
|
| 718 |
-
|
| 719 |
-
DPO + LoRA Training
|
| 720 |
-
|
| 721 |
-
↓
|
| 722 |
-
|
| 723 |
-
Controlled Benchmarking
|
| 724 |
-
|
| 725 |
-
↓
|
| 726 |
-
|
| 727 |
-
Statistical / Paired Analysis
|
| 728 |
-
|
| 729 |
-
↓
|
| 730 |
-
|
| 731 |
-
Model Release
|
| 732 |
-
|
| 733 |
-
\`\`\`
|
| 734 |
-
|
| 735 |
-
---
|
| 736 |
-
# Model Release
|
| 737 |
-
The trained LoRA adapter and technical documentation are available here:
|
| 738 |
-
|
| 739 |
-
****Hugging Face:****
|
| 740 |
-
|
| 741 |
-
https://huggingface.co/ranjanrajib/DPO-trained-Qwen2.5-Coder-7B
|
| 742 |
-
|
| 743 |
-
The repository contains the model adapter and documentation required to understand the training methodology, evaluation, results, intended use, and limitations.
|
| 744 |
-
|
| 745 |
-
---
|
| 746 |
-
# Licensing and Attribution
|
| 747 |
-
The model is derived from:
|
| 748 |
-
|
| 749 |
-
\`Qwen/Qwen2.5-Coder-7B-Instruct\`
|
| 750 |
-
|
| 751 |
-
Users should review and comply with the licensing and usage terms of the base model.
|
| 752 |
-
|
| 753 |
-
The preference-generation pipeline used programming problems from BigCodeBench, MBPP, HumanEval, and additional handwritten problems.
|
| 754 |
-
|
| 755 |
-
The respective dataset licenses and attribution requirements should be observed when using or redistributing material derived from those datasets.
|
| 756 |
-
|
| 757 |
-
---
|
| 758 |
-
# Citation
|
| 759 |
-
If you use this model or the experimental methodology in your work, please cite the original Qwen2.5-Coder model and the relevant datasets used in the experiment.
|
| 760 |
-
|
| 761 |
-
---
|
| 762 |
-
# Summary
|
| 763 |
-
****What is this?****
|
| 764 |
-
|
| 765 |
-
A Python-focused DPO fine-tuned version of Qwen2.5-Coder-7B-Instruct.
|
| 766 |
-
|
| 767 |
-
****What is different?****
|
| 768 |
-
|
| 769 |
-
The model was trained using LoRA-based Direct Preference Optimization with automatically constructed preferences derived from unit-test execution.
|
| 770 |
-
|
| 771 |
-
****Does it improve coding performance?****
|
| 772 |
-
|
| 773 |
-
On the evaluated held-out benchmark, yes. Pass@1 improved from ****41.87% to 45.22%****, with improvements also observed in Pass@5, Pass@10, and partial test coverage.
|
| 774 |
-
|
| 775 |
-
****Is it human-aligned?****
|
| 776 |
-
|
| 777 |
-
No human preference evaluation was performed. The preference signal was generated automatically from unit-test outcomes.
|
| 778 |
-
|
| 779 |
-
****Who should use it?****
|
| 780 |
-
|
| 781 |
-
Users primarily interested in Python code generation, coding experiments, DPO research, preference learning, and execution-based LLM evaluation.
|
| 782 |
-
|
| 783 |
-
****What is being released?****
|
| 784 |
-
|
| 785 |
-
A LoRA adapter that can be loaded on top of \`Qwen/Qwen2.5-Coder-7B-Instruct\`.
|
| 786 |
-
|
| 787 |
-
****Why is the experiment interesting?****
|
| 788 |
-
|
| 789 |
-
The model improved downstream coding performance even though explicit preference metrics showed weak validation generalization, highlighting the distinction between optimizing a preference objective and improving downstream model capability.
|
| 790 |
-
## Licence and attribution
|
| 791 |
-
Apache-2.0, inherited from \`Qwen/Qwen2.5-Coder-7B-Instruct\`. This is a modified derivative of that
|
| 792 |
-
|
| 793 |
-
model; the original is by the Qwen team at Alibaba Cloud. The preference data was generated from the
|
| 794 |
-
|
| 795 |
-
base model's own outputs on BigCodeBench problems.
|
|
|
|
| 23 |
- parameter-efficient-fine-tuning
|
| 24 |
---
|
| 25 |
|
| 26 |
+
# Qwen2.5-Coder-7B-Instruct — DPO Fine-Tuned for Python
|
| 27 |
|
| 28 |
+
## Model at a Glance
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 29 |
|
| 30 |
+
This model is a **Python-focused, DPO fine-tuned version of Qwen2.5-Coder-7B-Instruct**, designed to improve the model's ability to generate **functionally correct Python code**.
|
| 31 |
|
| 32 |
+
The model was trained using **Direct Preference Optimization (DPO)** with automatically constructed preference pairs. Candidate Python solutions were generated for programming problems and evaluated by executing them against unit tests. Solutions that passed the required tests were used as preferred examples, while solutions that failed tests were used as rejected examples.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
|
| 34 |
The resulting model was evaluated against the original Qwen2.5-Coder-7B-Instruct model on held-out programming problems.
|
| 35 |
+
|
| 36 |
### What changed?
|
| 37 |
The base model:
|
| 38 |
+
**`Qwen/Qwen2.5-Coder-7B-Instruct`**
|
|
|
|
| 39 |
|
| 40 |
was fine-tuned using:
|
| 41 |
+
**DPO + LoRA + execution-based preference data**
|
|
|
|
| 42 |
|
| 43 |
The resulting model demonstrates improved coding performance on the evaluated held-out benchmark:
|
| 44 |
|
| 45 |
| Metric | Qwen2.5-Coder-7B-Instruct | DPO Model | Improvement |
|
| 46 |
+
| :--- | :---: | :---: | :---: |
|
| 47 |
+
| Pass@1 | 41.87% | **45.22%** | **+3.35 pp** |
|
| 48 |
+
| Pass@5 | 48.87% | **51.10%** | **+2.23 pp** |
|
| 49 |
+
| Pass@10 | 50.99% | **53.16%** | **+2.17 pp** |
|
| 50 |
+
| Tests passed per answer | 66.20% | **69.41%** | **+3.21 pp** |
|
| 51 |
|
| 52 |
+
The primary result is the improvement in **Pass@1**, meaning that a single generated solution was more likely to produce a correct solution on the evaluated programming problems. The model also showed improved Pass@5, Pass@10, and partial test coverage.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 53 |
|
| 54 |
---
|
| 55 |
|
| 56 |
+
**Base model:** `Qwen/Qwen2.5-Coder-7B-Instruct` at snapshot `c03e6d358207e414f1eca0bb1891e29f1db0e242`. The merge was performed against exactly these weights.
|
| 57 |
|
| 58 |
+
## Downloading and Using The merged model
|
|
|
|
|
|
|
| 59 |
|
| 60 |
+
```python
|
| 61 |
from transformers import AutoModelForCausalLM, AutoTokenizer
|
| 62 |
|
| 63 |
model = AutoModelForCausalLM.from_pretrained(
|
| 64 |
+
"ranjanrajib/DPO-trained-Qwen2.5-Coder-7B", dtype="bfloat16", device_map="auto"
|
| 65 |
+
)
|
|
|
|
| 66 |
tok = AutoTokenizer.from_pretrained("ranjanrajib/DPO-trained-Qwen2.5-Coder-7B")
|
| 67 |
|
| 68 |
msgs = [{"role": "user", "content": "Write a Python function that merges overlapping intervals."}]
|
|
|
|
| 69 |
text = tok.apply_chat_template(msgs, tokenize=False, add_generation_prompt=True)
|
|
|
|
| 70 |
out = model.generate(**tok(text, return_tensors="pt").to(model.device), max_new_tokens=512)
|
| 71 |
+
print(tok.decode(out[0], skip_special_tokens=True))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|