Instructions to use iPwnds/finanalyst-qwen1.5b-final with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use iPwnds/finanalyst-qwen1.5b-final with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="iPwnds/finanalyst-qwen1.5b-final") messages = [ {"role": "user", "content": "Who are you?"}, ] pipe(messages)# Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("iPwnds/finanalyst-qwen1.5b-final", device_map="auto") - PEFT
How to use iPwnds/finanalyst-qwen1.5b-final with PEFT:
Task type is invalid.
- Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use iPwnds/finanalyst-qwen1.5b-final with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "iPwnds/finanalyst-qwen1.5b-final" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "iPwnds/finanalyst-qwen1.5b-final", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/iPwnds/finanalyst-qwen1.5b-final
- SGLang
How to use iPwnds/finanalyst-qwen1.5b-final 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 "iPwnds/finanalyst-qwen1.5b-final" \ --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": "iPwnds/finanalyst-qwen1.5b-final", "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 "iPwnds/finanalyst-qwen1.5b-final" \ --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": "iPwnds/finanalyst-qwen1.5b-final", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Docker Model Runner
How to use iPwnds/finanalyst-qwen1.5b-final with Docker Model Runner:
docker model run hf.co/iPwnds/finanalyst-qwen1.5b-final
finanalyst-qwen1.5b-final
A financial analyst LLM fine-tuned from Qwen2.5-3B-Instruct using QLoRA + ORPO (Odds Ratio Preference Optimisation) — a single-pass alignment method that combines supervised fine-tuning with preference learning, requiring no separate reward model or reference model. This is the second-generation, upgraded successor to iPwnds/finanalyst-qwen1.5b: a larger base model, a wider LoRA adapter, and a preference-aligned training objective instead of plain SFT.
It runs fully locally — no API keys required. On Apple Silicon it uses MPS acceleration; on a machine with a CUDA GPU it uses that automatically; otherwise it falls back to CPU.
Model Details
Model Description
finanalyst-qwen1.5b-final is a parameter-efficient fine-tune of Qwen/Qwen2.5-3B-Instruct trained to behave like a senior sell-side analyst. The base model is loaded in 4-bit NF4 quantisation while LoRA adapter matrices are injected into all four attention projection layers (q_proj, k_proj, v_proj, o_proj) — double the rank and twice the target modules of v1. Only 0.4756% of the total parameters (14.75M out of 3.10B) were updated during training.
Rather than plain supervised fine-tuning, this model was trained with ORPO (Hong et al., 2024): each step runs two forward passes — one over a "chosen" (high-quality analyst) response, one over a "rejected" (generic, unfine-tuned base-model) response for the same prompt — and combines a standard SFT cross-entropy loss with an odds-ratio preference term that pushes the model to prefer the chosen style over the rejected one. No separate reference model or reward model is required.
Because the installed trl release (1.9.2) neither ships a standalone ORPOTrainer (removed after trl 1.0) nor exposes loss_type="orpo" on DPOTrainer, ORPO was implemented directly on top of transformers.Trainer for this run — a from-scratch, dependency-free reimplementation of the algorithm described in the paper.
The model is the generative core of the FinSight Bloomberg Terminal CLI — a Bloomberg-style terminal that uses this model for all text generation (stock deep-dives, market overviews, watchlist digests, and natural-language Q&A).
- Developed by: Florian Braun (@iPwnds)
- Model type: Causal language model — instruction-tuned with QLoRA, aligned with ORPO
- Language: English
- License: Apache 2.0
- Fine-tuned from:
Qwen/Qwen2.5-3B-Instruct
Model Sources
- Repository: github.com/iPwnds/bloomberg-terminal
- Training notebook:
notebooks/FinAnalyst_Generative_Full.ipynb - Previous version:
iPwnds/finanalyst-qwen1.5b(v1 — Qwen2.5-1.5B, SFT only) - Companion sentiment model:
iPwnds/finsentiment-distilbert-final
Uses
Direct Use
The model is designed to generate analyst-style financial commentary given a structured prompt containing live market data (price, fundamentals, news sentiment). It handles three task types out of the box:
- Stock analysis — given price history, fundamentals, and sentiment, writes a deep-dive covering valuation, momentum, catalysts, and risks.
- Market overview — given index performance, sector rotation, and top movers, writes a macro narrative.
- Analyst Q&A — answers free-form financial questions in plain English, referencing provided data where available.
Downstream Use
The model plugs directly into the FinSight CLI via analysis/llm.py, which loads it with AutoPeftModelForCausalLM and merges the adapter at load time (merge_and_unload()), then exposes ask_llm() / ask_llm_stream() helper functions used throughout the application.
It can also be used as a drop-in instruction-following LLM for any financial NLP pipeline that needs analyst-style prose generation, or as a base for further preference-alignment experiments given its ORPO training lineage.
Out-of-Scope Use
- Real-time trading decisions — the model does not have access to live data and does not produce structured buy/sell signals. Any output should be treated as educational commentary, not financial advice.
- Precise numerical forecasting — price targets or earnings estimates produced by the model are illustrative, not quantitative predictions.
- Non-English text — training data was English-only.
- Domains outside finance — the fine-tuning data is domain-specific; performance on general instruction-following tasks may be degraded compared to the base model.
Bias, Risks, and Limitations
- The ORPO preference pairs were built from only 100 of the 156 available instruction examples (90 train / 10 test after the split), which limits diversity in what "rejected" style the model learned to avoid.
- The "rejected" responses were generated by the same base model being fine-tuned (self-play), rather than an independent weaker model — this narrows the preference signal to stylistic/structural differences rather than factual correctness.
- Training data was generated from a single point-in-time snapshot of live market data. The model may reproduce market conditions or narratives from that period.
- The base model,
Qwen2.5-3B-Instruct, may carry biases inherited from its pre-training corpus. - At 3B parameters the model is larger and more capable than v1, but responses may still occasionally hallucinate specific figures (e.g. exact P/E ratios or earnings dates) if not grounded by a data-rich prompt.
Recommendations
Always supply the model with current, factual market data in the prompt (price, fundamentals, news). Do not rely on the model's parametric knowledge for specific numerical claims. All output should be reviewed by a qualified professional before informing any financial decision.
How to Get Started with the Model
from peft import AutoPeftModelForCausalLM
from transformers import AutoTokenizer, pipeline
import torch
MODEL = "iPwnds/finanalyst-qwen1.5b-final"
# Detect device
if torch.backends.mps.is_available():
device_map, dtype = {"": "mps"}, torch.float16
elif torch.cuda.is_available():
device_map, dtype = "auto", torch.float16
else:
device_map, dtype = {"": "cpu"}, torch.float32
# Load base model + LoRA adapter, then merge for faster inference
model = AutoPeftModelForCausalLM.from_pretrained(
MODEL,
torch_dtype=dtype,
device_map=device_map,
).merge_and_unload()
tokenizer = AutoTokenizer.from_pretrained(MODEL)
pipe = pipeline("text-generation", model=model, tokenizer=tokenizer)
messages = [
{"role": "system", "content": "You are a senior equity analyst. Be concise and data-driven."},
{"role": "user", "content": "Is NVDA overbought at current levels given its AI growth story?"},
]
result = pipe(messages, max_new_tokens=512, temperature=0.3, do_sample=True)
print(result[0]["generated_text"][-1]["content"])
The model uses the ChatML chat template (<|im_start|> / <|im_end|>) inherited from Qwen2.5-3B-Instruct. Always pass messages as a list of role/content dicts rather than raw strings.
Training Details
Training Data
Base instruction data was generated programmatically by scripts/generate_training_data.py, which fetches live fundamentals, price history, and news via yfinance, constructs structured analyst prompts, and calls an LLM to generate reference responses. The dataset contains 156 instruction examples:
| Task type | Count | Unique tickers |
|---|---|---|
stock_analysis |
51 | 51 |
ask (free-form Q&A) |
104 | 52 |
market_overview |
1 | 1 |
For ORPO, preference pairs were built from the first 100 examples:
chosen— the original high-quality reference response from the instruction dataset.rejected— a response to the same prompt generated by the unfine-tunedQwen2.5-3B-Instructbase model (temperature 0.8, top-p 0.9, max 256 new tokens).
Mean chosen length: 334 words. Mean rejected length: 113 words — the base model's zero-shot responses are noticeably shorter and less structured than the curated analyst outputs, which is the contrast ORPO optimises against.
The 90/10 train/test split (seed=42) gives 90 training pairs and 10 evaluation pairs.
Training Procedure
Fine-tuning was performed in Google Colab on a T4 GPU (15 GB VRAM) using a custom ORPOTrainer subclassing transformers.Trainer (see Model Description above for why trl's trainer wasn't used).
Preprocessing
Prompt and response are tokenised separately so the prompt/response boundary is exact, then concatenated: [prompt_ids] + [response_ids] + [eos], truncated/padded to a fixed length. Labels are set to -100 over the prompt span so only the response contributes to the loss.
Sequences were truncated/padded to a maximum of 1024 tokens.
Training Hyperparameters
| Hyperparameter | Value |
|---|---|
| Base model | Qwen/Qwen2.5-3B-Instruct |
| Quantisation | 4-bit NF4 + double quantisation |
| Compute dtype | float16 |
LoRA rank (r) |
32 |
| LoRA alpha | 64 |
| LoRA target modules | q_proj, k_proj, v_proj, o_proj |
| LoRA dropout | 0.05 |
| Trainable parameters | 14,745,600 / 3,100,684,288 (0.4756%) |
| ORPO beta | 0.1 |
| Epochs | 3 |
| Per-device batch size | 1 |
| Gradient accumulation steps | 8 (effective batch size: 8) |
| Learning rate | 8e-6 |
| Max sequence length | 1024 tokens |
| Mixed precision | None (fp16=False, bf16=False) |
| Gradient checkpointing | Enabled |
| Optimizer | AdamW (default) |
Note on evaluation: the base
Trainer.prediction_steplooks for a top-level"labels"key to decide whether to route through a customcompute_loss; since the ORPO collator instead emitschosen_labels/rejected_labels,prediction_stepwas overridden to always call the custom ORPO loss during evaluation.
Speeds, Sizes, Times
| Training time | ~15–20 minutes (T4 GPU, Google Colab) |
| Total steps | 36 (3 epochs × 12 steps) |
| Adapter size (pushed to Hub) | 59.0 MB |
| Base model size (downloaded at inference) | ~6 GB |
Evaluation
Testing Data
A 10% held-out split (10 preference pairs, seed=42) from the same generated ORPO dataset.
Metrics
Evaluation loss — the combined ORPO objective (SFT cross-entropy + β × odds-ratio loss, β=0.1) computed on held-out chosen/rejected pairs.
Results
| Metric | Value |
|---|---|
| Final ORPO eval loss | 1.0125 |
| v1 SFT eval loss (for reference) | 1.4721 |
These two numbers are not directly comparable — v1's 1.4721 is a pure SFT cross-entropy loss, while 1.0125 is the combined ORPO objective (SFT + odds-ratio term). Both are reported for context, not as an apples-to-apples benchmark.
Summary
The model learns the instruction-following format and analyst prose style, and the ORPO odds-ratio term separates chosen from rejected response likelihoods as intended. As with v1, the primary limitation is dataset size — 90 training pairs is small for preference optimisation, and broader coverage of tickers, task types, and market conditions (plus preference pairs sourced from a genuinely weaker/different model rather than self-play) would likely improve robustness.
Environmental Impact
Training was performed on a Google Colab T4 GPU for approximately 15–20 minutes. Estimated carbon emissions are negligible at this scale.
- Hardware type: NVIDIA T4 (Google Colab)
- Hours used: ~0.3 hours
- Cloud provider: Google (Colab)
- Compute region: US (Colab default)
- Carbon emitted: < 5 g COâ‚‚eq (estimated)
Technical Specifications
Model Architecture and Objective
- Base architecture: Qwen2.5-3B-Instruct (decoder-only transformer, 3.10B parameters)
- Fine-tuning method: QLoRA — 4-bit NF4 weight quantisation via
bitsandbytes, with low-rank adapter matrices (LoRA) injected intoq_proj,k_proj,v_proj, ando_projof each attention block - Alignment method: ORPO (Odds Ratio Preference Optimisation, Hong et al. 2024) — monolithic single-pass SFT + preference alignment, no reference model
- Objective: Next-token cross-entropy on chosen responses, combined with an odds-ratio term maximising the log-odds margin between chosen and rejected responses
- Chat format: ChatML (
<|im_start|>/<|im_end|>)
Compute Infrastructure
Hardware
- Google Colab T4 GPU (15 GB VRAM) for training
- Apple Silicon (MPS), CUDA GPU, or CPU for inference
Software
| Package | Role |
|---|---|
transformers |
Model loading, tokenisation, pipeline, base Trainer (custom ORPO loss built on top) |
peft |
LoRA adapter injection and AutoPeftModelForCausalLM |
bitsandbytes ≥ 0.46.1 |
4-bit NF4 quantisation |
accelerate |
Device placement and distributed training |
datasets |
Preference-pair dataset formatting and train/test split |
Model Card Authors
Florian Braun (@iPwnds)