Views
No views yet
1from vllm import LLM, SamplingParams
2from vllm.lora.request import LoRARequest
3
4# Initialize vLLM Engine with LoRA support
5model_path = "unsloth/meta-llama-3.1-8b-instruct-bnb-4bit"
6lora_path_answ = "sag-uniroma2/llama3.1_adapter_biorag_answer_generation"
7lora_adapter_id = 2
8
9llm = LLM(
10 model=model_path,
11 enable_lora=True,
12 max_loras=2, # Support multiple LoRA adapters
13 max_lora_rank=64,
14 gpu_memory_utilization=0.75,
15 trust_remote_code=True,
16 disable_custom_all_reduce=True,
17 enforce_eager=True
18)
19
20# Setup LoRA request for answer generation
21lora_request_answ = LoRARequest(
22 lora_name=str(lora_adapter_id),
23 lora_int_id=lora_adapter_id,
24 lora_path=lora_path_answ
25)
26
27# Define sampling parameters
28sampling_params = SamplingParams(temperature=0.0, max_tokens=256)
29
30# Define instruction
31instruction = """You are a biomedical expert. Your task is to generate a concise, well-structured summary answering the given question.
32Base your response on the provided PubMed abstracts, focusing on the text marked with [BS] and [ES].
33
34Rules:
35- Use only the information provided with a special focus on the marked information.
36- The summary must be ≤200 words.
37- Do NOT include personal opinions, speculations, or unrelated information.
38- Maintain a neutral and scientific tone."""
39
40def answer_from_snippets(query_text: str, documents: list):
41 """
42 Generates an answer from biomedical documents with context windowing.
43 Processes up to the first 3 documents and surrounds snippets with context.
44
45 Args:
46 query_text: The biomedical question
47 documents: List of documents with extracted snippets [BS] and [ES]
48
49 Returns:
50 Generated answer (≤200 words)
51 """
52 # Take only the first 3 valid documents
53 top_3_docs = documents[:3]
54
55 doc_blocks = []
56
57 for doc in top_3_docs:
58 # Combine title and abstract into full text
59 title = doc["title"][0] if doc.get("title") and doc["title"] else ""
60 abstract = doc["text"][0] if doc.get("text") and doc["text"] else ""
61 full_text = f"{title} {abstract}".strip()
62
63 # Collect all snippets from this document
64 all_snippets = doc.get("snippets_title", []) + doc.get("snippets_abstract", [])
65
66 formatted_snippets = []
67
68 for snippet in all_snippets:
69 # Find snippet position in original text
70 start_idx = full_text.find(snippet)
71
72 if start_idx != -1:
73 end_idx = start_idx + len(snippet)
74
75 # Split surrounding text into words
76 words_before = full_text[:start_idx].split()
77 words_after = full_text[end_idx:].split()
78
79 # Get context: max 20 words before, max 10 words after
80 context_before = " ".join(words_before[-20:]) if words_before else ""
81 context_after = " ".join(words_after[:10]) if words_after else ""
82
83 # Format with context window
84 block = f"... abstract truncated here... {context_before} [BS] {snippet} [ES] {context_after} ... abstract truncated here..."
85 block_clean = " ".join(block.split())
86 formatted_snippets.append(block_clean)
87
88 if formatted_snippets:
89 doc_blocks.append("\n".join(formatted_snippets))
90
91 # Combine all document blocks
92 resources_text = "\n".join(doc_blocks)
93
94 # Build final prompt
95 prompt = f"{instruction}\n\n# Question: {query_text}\n# PubMed resources:\n{resources_text}\n# Answer:"
96
97 # Generate answer using LoRA adapter for answer generation
98 output = llm.generate(
99 [prompt],
100 sampling_params,
101 lora_request=lora_request_answ,
102 use_tqdm=False
103 )
104
105 # Parse generated answer
106 generated_text = output[0].outputs[0].text
107 answer = generated_text.split("<|eot_id|>")[0].strip()
108
109 return answer
110
111# Example usage
112question = "YOUR_BIOMEDICAL_QUESTION_HERE"
113documents = [
114 {
115 "id": "PUBMED_ID_1",
116 "title": ["Article Title"],
117 "text": ["Article abstract..."],
118 "snippets_title": ["relevant snippet from title"],
119 "snippets_abstract": ["relevant snippet from abstract"]
120 },
121 # ... more documents ...
122]
123
124final_answer = answer_from_snippets(question, documents)
125print(f"Generated Answer: {final_answer}")1{
2 "id": "PUBMED_ID",
3 "title": ["Article Title"],
4 "text": ["Article abstract"],
5 "snippets_title": ["snippet from title"],
6 "snippets_abstract": ["snippet from abstract"]
7}1@InProceedings{10.1007/978-3-032-21324-2_31,
2author="Borazio, Federico
3and Labbate, Francesco
4and Croce, Danilo
5and Basili, Roberto",
6editor="Campos, Ricardo
7and Jatowt, Adam
8and Lan, Yanyan
9and Aliannejadi, Mohammad
10and Bauer, Christine
11and MacAvaney, Sean
12and Anand, Avishek
13and Ren, Zhaochun
14and Verberne, Suzan
15and Bai, Nan
16and Mansoury, Masoud",
17title="Integrating AI and IR Paradigms for Sustainable and Trustworthy Accurate Access to Large Scale Biomedical Information",
18booktitle="Advances in Information Retrieval",
19year="2026",
20publisher="Springer Nature Switzerland",
21address="Cham",
22pages="398--412",
23isbn="978-3-032-21324-2"
24}1@inproceedings{unitor,
2 title={{UniTor at BioASQ 2025: Modular Biomedical QA with Synthetic Snippets and Multiple Task Answer Generation}},
3 author={Borazio, Federico and Shcherbakov, Andriy and Croce, Danilo and Basili, Roberto},
4 year=2025,
5 booktitle={CLEF 2025 Working Notes},
6 editor= {Faggioli, Guglielmo and Ferro, Nicola and Rosso, Paolo and Spina, Damiano}
7}