初始化项目,由ModelHub XC社区提供模型
Model: jalpan04/qwen-researcher Source: Original Platform
This commit is contained in:
37
.gitattributes
vendored
Normal file
37
.gitattributes
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
*.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
|
||||
qwen-resercher.gguf filter=lfs diff=lfs merge=lfs -text
|
||||
qwen-researcher-f16.gguf filter=lfs diff=lfs merge=lfs -text
|
||||
10
Modelfile
Normal file
10
Modelfile
Normal file
@@ -0,0 +1,10 @@
|
||||
FROM ./qwen-resercher.gguf
|
||||
PARAMETER stop "<|im_start|>"
|
||||
PARAMETER stop "<|im_end|>"
|
||||
TEMPLATE """<|im_start|>system
|
||||
{{ .System }}<|im_end|>
|
||||
<|im_start|>user
|
||||
{{ .Prompt }}<|im_end|>
|
||||
<|im_start|>assistant
|
||||
"""
|
||||
SYSTEM """You are an expert Computer Science Research Assistant. You provide detailed, academic-style answers based on your specialized training on arXiv papers."""
|
||||
86
README.md
Normal file
86
README.md
Normal file
@@ -0,0 +1,86 @@
|
||||
---
|
||||
license: apache-2.0
|
||||
base_model: Qwen/Qwen2.5-0.5B-Instruct
|
||||
tags:
|
||||
- qwen
|
||||
- qwen2
|
||||
- gguf
|
||||
- f16
|
||||
- computer-science
|
||||
- research
|
||||
- instruction-tuning
|
||||
model_creator: jalpan04
|
||||
model_name: Qwen Research Assistant
|
||||
pipeline_tag: text-generation
|
||||
quantized_by: f16
|
||||
---
|
||||
|
||||
# Qwen Researcher (0.5B - GGUF)
|
||||
|
||||
A specialized version of **Qwen2.5-0.5B-Instruct** fine-tuned for Computer Science research assistance. This model has been instruction-tuned on a curated subset of 2,000 arXiv Computer Science papers to provide academic summaries and technical insights.
|
||||
|
||||
## Model Details
|
||||
|
||||
- **Developed by:** Jalpan04
|
||||
- **Model type:** Causal Language Model
|
||||
- **Language(s):** English
|
||||
- **License:** Apache-2.0
|
||||
- **Fine-tuned from model:** [Qwen/Qwen2.5-0.5B-Instruct](https://huggingface.co/Qwen/Qwen2.5-0.5B-Instruct)
|
||||
- **Training Method:** QLoRA (Rank 16, Alpha 32)
|
||||
- **Dataset:** arXiv Computer Science Metadata (Instruction-formatted)
|
||||
|
||||
## Usage
|
||||
|
||||
### Local Deployment (Ollama)
|
||||
|
||||
1. Create a `Modelfile`:
|
||||
```dockerfile
|
||||
FROM ./qwen-resercher.gguf
|
||||
TEMPLATE """{{ if .System }}<|im_start|>system
|
||||
{{ .System }}<|im_end|>
|
||||
{{ end }}{{ if .User }}<|im_start|>user
|
||||
{{ .User }}<|im_end|>
|
||||
{{ end }}<|im_start|>assistant
|
||||
{{ .Output }}<|im_end|>"""
|
||||
PARAMETER stop "<|im_start|>"
|
||||
PARAMETER stop "<|im_end|>"
|
||||
SYSTEM "You are a professional computer science researcher. Provide academic, detailed information based on research abstracts."
|
||||
```
|
||||
|
||||
2. Run in terminal:
|
||||
```bash
|
||||
ollama create qwen-researcher -f Modelfile
|
||||
ollama run qwen-researcher
|
||||
```
|
||||
|
||||
### Python (llama-cpp-python)
|
||||
|
||||
```python
|
||||
from llama_cpp import Llama
|
||||
|
||||
llm = Llama.from_pretrained(
|
||||
repo_id="jalpan04/qwen-researcher",
|
||||
filename="qwen-resercher.gguf",
|
||||
)
|
||||
|
||||
response = llm.create_chat_completion(
|
||||
messages = [
|
||||
{"role": "system", "content": "You are a CS researcher."},
|
||||
{"role": "user", "content": "Summarize the latest trends in Neural Program Synthesis."}
|
||||
]
|
||||
)
|
||||
print(response["choices"][0]["message"]["content"])
|
||||
```
|
||||
|
||||
## Training Procedure
|
||||
|
||||
The model was trained on an **NVIDIA RTX 4060 (8GB)** using the following setup:
|
||||
- **Optimization:** 4-bit NormalFloat (nf4) quantization.
|
||||
- **Precision:** BFloat16 for stability on 40-series hardware.
|
||||
- **Learning Rate:** 2e-4.
|
||||
- **Batch Size:** 1 with Gradient Accumulation (16 steps).
|
||||
- **Sequence Length:** 1024 tokens.
|
||||
|
||||
## Limitations
|
||||
|
||||
As a 0.5B parameter model, this is highly efficient but may exhibit hallucinations compared to larger models (7B+). It is best used for summarization and quick technical lookups rather than complex logical reasoning.
|
||||
46
merge_model.py
Normal file
46
merge_model.py
Normal file
@@ -0,0 +1,46 @@
|
||||
import torch
|
||||
from peft import PeftModel
|
||||
from transformers import AutoModelForCausalLM, AutoTokenizer
|
||||
import os
|
||||
|
||||
def merge_and_save():
|
||||
"""
|
||||
Script to merge trained LoRA adapters back into the base Qwen model.
|
||||
This creates a standalone model folder that can be converted to GGUF format.
|
||||
"""
|
||||
|
||||
base_model_id = "Qwen/Qwen2.5-0.5B-Instruct"
|
||||
adapter_path = "./qwen-resercher"
|
||||
output_path = "./qwen-resercher-final"
|
||||
|
||||
print(f"Loading base model: {base_model_id}")
|
||||
tokenizer = AutoTokenizer.from_pretrained(base_model_id)
|
||||
|
||||
# Load base model in FP16 for merging precision
|
||||
# device_map="auto" is used to handle large models, though 0.5B fits easily in VRAM.
|
||||
model = AutoModelForCausalLM.from_pretrained(
|
||||
base_model_id,
|
||||
torch_dtype=torch.float16,
|
||||
device_map="auto",
|
||||
)
|
||||
|
||||
# 1. Load the trained adapter onto the base model
|
||||
print(f"Loading adapter from: {adapter_path}")
|
||||
model = PeftModel.from_pretrained(model, adapter_path)
|
||||
|
||||
# 2. Merge the weights
|
||||
# merge_and_unload() combines the LoRA matrices with the original weights.
|
||||
# This results in a standard Transformer model (no adapters needed).
|
||||
print("Merging weights... this creates the final unified model.")
|
||||
model = model.merge_and_unload()
|
||||
|
||||
# 3. Save the final model and tokenizer
|
||||
# This folder will be the source for the 'convert_hf_to_gguf.py' script.
|
||||
print(f"Saving unified model to: {output_path}")
|
||||
model.save_pretrained(output_path)
|
||||
tokenizer.save_pretrained(output_path)
|
||||
|
||||
print("Merge complete.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
merge_and_save()
|
||||
72
prepare_data.py
Normal file
72
prepare_data.py
Normal file
@@ -0,0 +1,72 @@
|
||||
import json
|
||||
import random
|
||||
import os
|
||||
|
||||
def prepare_data():
|
||||
"""
|
||||
Data preparation script to convert raw arXiv metadata into ChatML format.
|
||||
Handles memory efficiency by streaming the source file line-by-line.
|
||||
"""
|
||||
|
||||
input_file = "arxiv-metadata-oai-snapshot.json"
|
||||
output_file = "arxiv_cs_2000.jsonl"
|
||||
|
||||
# Check if input exists
|
||||
if not os.path.exists(input_file):
|
||||
print(f"Source file {input_file} not found. Please ensure it is in the directory.")
|
||||
return
|
||||
|
||||
cs_papers = []
|
||||
print("Scanning arXiv dataset for Computer Science papers...")
|
||||
|
||||
# We use a streaming approach (open/read) to avoid loading the whole JSON into memory.
|
||||
with open(input_file, 'r', encoding='utf-8') as f:
|
||||
for line in f:
|
||||
try:
|
||||
paper = json.loads(line)
|
||||
# Filter for papers containing 'cs.' in categories
|
||||
if 'cs.' in paper.get('categories', ''):
|
||||
cs_papers.append({
|
||||
'title': paper.get('title', 'No Title'),
|
||||
'abstract': paper.get('abstract', 'No Abstract').replace('\n', ' ').strip()
|
||||
})
|
||||
except json.JSONDecodeError:
|
||||
continue
|
||||
|
||||
# Select a diverse sample of 2,000 papers for instruction tuning
|
||||
if len(cs_papers) > 2000:
|
||||
print(f"Found {len(cs_papers)} CS papers. Sampling 2,000...")
|
||||
selected_papers = random.sample(cs_papers, 2000)
|
||||
else:
|
||||
print(f"Found {len(cs_papers)} CS papers. Using all available data.")
|
||||
selected_papers = cs_papers
|
||||
|
||||
# Convert to ChatML/Instruction format for Qwen
|
||||
# Each entry consists of a system prompt, a user question, and the assistant response.
|
||||
print(f"Writing formatted data to {output_file}...")
|
||||
with open(output_file, 'w', encoding='utf-8') as f:
|
||||
for paper in selected_papers:
|
||||
# Construct the conversation
|
||||
messages = [
|
||||
{
|
||||
"role": "system",
|
||||
"content": "You are a professional computer science researcher. Provide academic, detailed information based on research abstracts."
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": f"Summarize the research and key contributions of the paper titled: {paper['title']}"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": paper['abstract']
|
||||
}
|
||||
]
|
||||
|
||||
# Write as a JSONL line
|
||||
json_line = json.dumps({"messages": messages})
|
||||
f.write(json_line + '\n')
|
||||
|
||||
print("Data preparation complete.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
prepare_data()
|
||||
3
qwen-researcher-f16.gguf
Normal file
3
qwen-researcher-f16.gguf
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:7757a1d695617c35f1b81e8fc4183a3088a6eb3b5360fcb04eb7c695b86cd5a1
|
||||
size 994156320
|
||||
7
requirements.txt
Normal file
7
requirements.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
torch
|
||||
transformers
|
||||
datasets
|
||||
peft
|
||||
trl
|
||||
bitsandbytes
|
||||
accelerate
|
||||
111
train.py
Normal file
111
train.py
Normal file
@@ -0,0 +1,111 @@
|
||||
import torch
|
||||
import os
|
||||
from datasets import load_dataset
|
||||
from transformers import (
|
||||
AutoModelForCausalLM,
|
||||
AutoTokenizer,
|
||||
BitsAndBytesConfig,
|
||||
TrainingArguments
|
||||
)
|
||||
from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training
|
||||
from trl import SFTTrainer, SFTConfig
|
||||
|
||||
def train():
|
||||
"""
|
||||
Main training function to fine-tune Qwen2.5-0.5B using QLoRA.
|
||||
Includes debug prints for step-by-step monitoring on Windows.
|
||||
"""
|
||||
print(">>> DEBUG: Entering train() function...")
|
||||
|
||||
# Clear CUDA memory before starting to prevent fragmentation
|
||||
if torch.cuda.is_available():
|
||||
print(">>> DEBUG: Clearing CUDA cache...")
|
||||
torch.cuda.empty_cache()
|
||||
|
||||
model_id = "Qwen/Qwen2.5-0.5B-Instruct"
|
||||
data_file = "arxiv_cs_2000.jsonl"
|
||||
output_dir = "./qwen-resercher-checkpoints"
|
||||
|
||||
# 1. Load Tokenizer
|
||||
print(f">>> DEBUG: Loading tokenizer for {model_id}...")
|
||||
tokenizer = AutoTokenizer.from_pretrained(model_id)
|
||||
tokenizer.pad_token = tokenizer.eos_token
|
||||
tokenizer.padding_side = "right"
|
||||
|
||||
# 2. BitsAndBytes Configuration (QLoRA)
|
||||
print(">>> DEBUG: Configuring BitsAndBytes for 4-bit quantization...")
|
||||
bnb_config = BitsAndBytesConfig(
|
||||
load_in_4bit=True,
|
||||
bnb_4bit_use_double_quant=True,
|
||||
bnb_4bit_quant_type="nf4",
|
||||
bnb_4bit_compute_dtype=torch.bfloat16
|
||||
)
|
||||
|
||||
# 3. Load Base Model
|
||||
print(f">>> DEBUG: Loading base model from {model_id}...")
|
||||
model = AutoModelForCausalLM.from_pretrained(
|
||||
model_id,
|
||||
quantization_config=bnb_config,
|
||||
device_map="auto",
|
||||
trust_remote_code=True
|
||||
)
|
||||
|
||||
print(">>> DEBUG: Preparing model for kbit training...")
|
||||
model = prepare_model_for_kbit_training(model)
|
||||
|
||||
# 4. LoRA Configuration
|
||||
print(">>> DEBUG: Setting up LoRA configuration (Rank=16)...")
|
||||
peft_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="CAUSAL_LM"
|
||||
)
|
||||
|
||||
# 5. Load Dataset
|
||||
print(f">>> DEBUG: Loading dataset from {data_file}...")
|
||||
dataset = load_dataset("json", data_files=data_file, split="train")
|
||||
|
||||
# 6. Training Arguments
|
||||
print(">>> DEBUG: Defining training arguments...")
|
||||
training_args = SFTConfig(
|
||||
output_dir=output_dir,
|
||||
per_device_train_batch_size=1,
|
||||
gradient_accumulation_steps=16,
|
||||
learning_rate=2e-4,
|
||||
logging_steps=10,
|
||||
max_steps=200,
|
||||
save_steps=100,
|
||||
optim="paged_adamw_8bit",
|
||||
bf16=True,
|
||||
fp16=False,
|
||||
dataset_text_field="text",
|
||||
max_length=1024,
|
||||
gradient_checkpointing=True,
|
||||
packing=False
|
||||
)
|
||||
|
||||
# 7. Initialize Trainer
|
||||
print(">>> DEBUG: Initializing SFTTrainer...")
|
||||
trainer = SFTTrainer(
|
||||
model=model,
|
||||
train_dataset=dataset,
|
||||
peft_config=peft_config,
|
||||
args=training_args,
|
||||
processing_class=tokenizer,
|
||||
)
|
||||
|
||||
# 8. Start Training
|
||||
print(">>> DEBUG: Starting training loop...")
|
||||
trainer.train()
|
||||
|
||||
# 9. Save the Adapter
|
||||
print(">>> DEBUG: Saving the fine-tuned adapter to ./qwen-resercher...")
|
||||
trainer.model.save_pretrained("qwen-resercher")
|
||||
tokenizer.save_pretrained("qwen-resercher")
|
||||
print(">>> DEBUG: Training complete.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
train()
|
||||
Reference in New Issue
Block a user