ballagb19's picture
Upload captcha_solver/engines/qwen_engine.py with huggingface_hub
9299116 verified
Raw
History Blame Contribute Delete
2.34 kB
"""Qwen2.5 small text LLM engine for math / reasoning / OCR cleanup."""
from __future__ import annotations
import os
from typing import Optional
from captcha_solver.engines.base import BaseEngine
from captcha_solver.config import get_settings
class QwenEngine(BaseEngine):
name = "qwen"
def __init__(self) -> None:
super().__init__()
self._model = None
self._tokenizer = None
def _do_load(self) -> None:
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
s = get_settings()
os.environ.setdefault("HF_HOME", str(s.cache_dir / "hf"))
dtype = {"float32": torch.float32, "float16": torch.float16, "bfloat16": torch.bfloat16}[
s.qwen_torch_dtype
]
self._tokenizer = AutoTokenizer.from_pretrained(s.qwen_model)
self._model = AutoModelForCausalLM.from_pretrained(
s.qwen_model,
torch_dtype=dtype,
low_cpu_mem_usage=True,
).to(s.qwen_device).eval()
def _do_unload(self) -> None:
self._model = None
self._tokenizer = None
def generate(
self,
prompt: str,
system: Optional[str] = None,
max_new_tokens: int = 64,
temperature: float = 0.0,
) -> str:
"""Generate a short response. Best for math, OCR cleanup, simple reasoning."""
if not self._loaded:
self.load()
import torch
assert self._model is not None and self._tokenizer is not None
messages = []
if system:
messages.append({"role": "system", "content": system})
messages.append({"role": "user", "content": prompt})
text = self._tokenizer.apply_chat_template(
messages, tokenize=False, add_generation_prompt=True
)
inputs = self._tokenizer(text, return_tensors="pt").to(self._model.device)
with torch.no_grad():
gen = self._model.generate(
**inputs,
max_new_tokens=max_new_tokens,
do_sample=temperature > 0,
temperature=temperature or 1.0,
pad_token_id=self._tokenizer.eos_token_id,
)
out = gen[0][inputs["input_ids"].shape[1]:]
return self._tokenizer.decode(out, skip_special_tokens=True).strip()