--- base_model: Qwen/Qwen3-4B pipeline_tag: text-generation tags: - qwen3 - peft - lora - grpo - retrieval - query-expansion --- # QueStER Qwen3 Keyword Model LoRA adapter for Qwen3-4B that generates keyword-based query expansions for retrieval. ## Paper Accepted to EACL 2026 This model is associated with the paper [QueStER: Query Specification for Generative Keyword-Based Retrieval](https://aclanthology.org/2026.findings-eacl.312/). Training code [github](https://github.com/arthur-75/quester/tree/main) ## Install ```bash pip install -U transformers accelerate torch safetensors ``` ## Load and run ```python import torch from transformers import AutoModelForCausalLM from transformers import AutoTokenizer model_id = "Arthur-75/quester-qwen3-4B" system_prompt = "Generate relevant single-word keywords to improve retrieval performance. Only output unique keywords, separated by commas." tokenizer = AutoTokenizer.from_pretrained(model_id, trust_remote_code=True) model = AutoModelForCausalLM.from_pretrained( model_id, trust_remote_code=True, ) model.eval() def clean_output(text: str) -> str: text = text.strip() if " " in text: text = text.split(" ", 1)[-1].strip() if " " in text: text = text.split(" ", 1)[-1].strip() if text.lower().startswith("keywords:"): text = text[len("keywords:"):].strip() if text.lower().startswith("keyword:"): text = text[len("keyword:"):].strip() if "\nassistant" in text: text = text.split("\nassistant", 1)[-1].strip() if "assistant\n" in text: text = text.split("assistant\n", 1)[-1].strip() return text def generate_keywords(query: str) -> str: messages = [ {"role": "system", "content": system_prompt}, {"role": "user", "content":"[QUERY]: "+ query+" [KEYWORDS]:"}, ] prompt = tokenizer.apply_chat_template( messages, tokenize=False, add_generation_prompt=True, enable_thinking=False, ) inputs = tokenizer(prompt, return_tensors="pt").to(model.device) with torch.inference_mode(): output = model.generate( **inputs, max_new_tokens=64, do_sample=False, ) new_tokens = output[:, inputs["input_ids"].shape[1]:] text = tokenizer.decode(new_tokens[0], skip_special_tokens=True) return clean_output(text) query = "What are the symptoms of vitamin D deficiency?" print(generate_keywords(query)) ``` ## Citation ```bibtex @inproceedings{satouf-etal-2026-quester, title = "{Q}ue{S}t{ER}: Query Specification for Generative Keyword-Based Retrieval", author = "Satouf, Arthur and Zong, Yuxuan and Boubacar, Habiboulaye Amadou and Piantanida, Pablo and Piwowarski, Benjamin", editor = "Demberg, Vera and Inui, Kentaro and Marquez, Llu{\'i}s", booktitle = "Findings of the {A}ssociation for {C}omputational {L}inguistics: {EACL} 2026", month = mar, year = "2026", address = "Rabat, Morocco", publisher = "Association for Computational Linguistics", url = "https://aclanthology.org/2026.findings-eacl.312/", doi = "10.18653/v1/2026.findings-eacl.312", pages = "5957--5968", ISBN = "979-8-89176-386-9", abstract = "Generative retrieval (GR) differs from the traditional index{--}then{--}retrieve pipeline by storing relevance in model parameters and generating retrieval cues directly from the query, but it can be brittle out of domain and expensive to scale. We introduce QueStER (QUEry SpecificaTion for gEnerative Keyword-Based Retrieval), which bridges GR and query reformulation by learning to generate explicit keyword-based search specifications. Given a user query, a lightweight LLM produces a keyword query that is executed by a standard retriever (BM25), combining the generalization benefits of generative query rewriting with the efficiency and scalability of lexical indexing. We train the rewriting policy with reinforcement learning techniques. Across in- and out-of-domain evaluations, QueStER consistently improves over BM25 and is competitive with neural IR baselines, while maintaining strong efficiency." } ```