Views
No views yet
1from peft import PeftModel
2from transformers import AutoModelForCausalLM, AutoTokenizer
3import torch
4
5BASE = "Qwen/Qwen2.5-7B-Instruct"
6ADAPTER = "BABAKAFSHINPOUR/earnings-call-guidance-lora"
7
8tokenizer = AutoTokenizer.from_pretrained(BASE)
9base = AutoModelForCausalLM.from_pretrained(BASE, torch_dtype=torch.float16, device_map="auto")
10model = PeftModel.from_pretrained(base, ADAPTER).eval()
11
12system = "You extract forward-looking financial guidance from earnings call transcripts. ..." # see repo
13user = "[Satya Nadella — CEO]\n..." # CEO + CFO prepared remarks
14
15prompt = tokenizer.apply_chat_template(
16 [{"role": "system", "content": system},
17 {"role": "user", "content": user}],
18 tokenize=False, add_generation_prompt=True,
19)
20inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
21out = model.generate(**inputs, max_new_tokens=4096, do_sample=False,
22 eos_token_id=tokenizer.convert_tokens_to_ids("<|im_end|>"))
23print(tokenizer.decode(out[0][inputs["input_ids"].shape[1]:], skip_special_tokens=True))src/build_training_jsonl.py in the linked repo.1{"guidance": [
2 {
3 "metric": "revenue",
4 "metric_detail": null,
5 "period": "Q4-2026",
6 "direction": "raised",
7 "new_low": 4200, "new_high": 4300, "new_point": null,
8 "old_low": null, "old_high": null, "old_point": null,
9 "unit": "usd_millions",
10 "currency": "USD",
11 "vs_consensus": "not_stated",
12 "confidence_language": "we now expect",
13 "source_span": "...",
14 "speaker": "cfo"
15 }
16]}metric ∈ {revenue, eps_gaap, eps_adjusted, operating_income, operating_margin,
gross_margin, fcf, capex, segment_revenue, other}.
unit ∈ {usd_millions, usd_billions, usd, percent, count, other}.
period normalized as Q1-2026, FY2026, H1-2026, CY2026, or long_term.a2-highgpu-1g), using Unsloth + 🤗
transformers.| Base model | unsloth/Qwen2.5-7B-Instruct-bnb-4bit (4-bit NF4) |
| LoRA rank / alpha | 32 / 64 |
| LoRA dropout | 0.0 |
| Target modules | q_proj, k_proj, v_proj, o_proj |
| Trainable params | ~0.4% of base |
| Sequence length | 16,384 (covers the densest transcripts) |
| Optimizer | adamw_8bit |
| LR / schedule | 2e-4, cosine, 10% warmup |
| Weight decay | 0.01 |
| Epochs | 5 |
| Effective batch size | 4 (per-device 1 × grad accum 4) |
| Precision | bf16 (fallback fp16) |
| Prompt masking | system+user masked to -100 via DataCollatorForSeq2Seq |
train.py: the default
DataCollatorForLanguageModeling silently overwrites pre-set labels with
input_ids.clone(), which defeats prompt masking entirely. This run uses
DataCollatorForSeq2Seq so the masked labels are preserved.eval_predictions.jsonl in the linked repo for raw outputs; the headline
checks are JSON validity and record count vs. truth.1@misc{afshinpour2026earnings,
2 title = {Earnings call guidance extraction via QLoRA on Qwen 2.5 7B},
3 author = {Afshin-Pour, Babak},
4 year = {2026},
5 howpublished = {\url{https://huggingface.co/BABAKAFSHINPOUR/earnings-call-guidance-lora}},
6}