Views
No views yet
Qwen/Qwen3.5-2B using QLoRA (Low-Rank Adaptation) for Aspect-Based Sentiment Analysis (ABSA) on multilingualnd bilingual restaurant reviews.restaurant_general, food_quality, service, ambience, food_style_options, food_prices, restaurant_prices, drinks_quality, drinks_style_options, location, drinks_prices.positive, negative, neutral, conflict.devel.json dataset across the four mandatory stages of the project. The QLoRA fine-tuning stage proved to be the most robust approach to combat dataset imbalance, yielding the highest scores across all macro and micro metrics.| Configuration | Precision (Macro) | F1 (Macro) | F1 (Micro) |
|---|---|---|---|
| Empty baseline | 0.0% | 0.0% | 0.0% |
| Top 3 majority baseline | 60.4% | 55.6% | 56.2% |
| Best Zero-Shot Sweep | 74.6% | 67.9% | 68.3% |
| Best Few-Shot | 79.6% | 73.9% | 73.9% |
| Best Full LoRA Checkpoint | 86.4% | 84.4% | 86.4% |
| Best QLoRA Checkpoint (This Model) | 87.4% | 85.3% | 87.3% |
absa_prompt.json file, separated into system and user roles to maximize Qwen's instruction-following capabilities.absa_prompt.json prompt from this Hugging Face repository at runtime, formats the text, and runs the inference:1from peft import AutoPeftModelForCausalLM
2from transformers import AutoTokenizer
3from huggingface_hub import hf_hub_download
4import json
5import torch
6
7repo_id = "guillemolivart/qwen-2b-absa-qlora"
8
9# 1. Download and load the prompt template from the repository files
10prompt_file_path = hf_hub_download(repo_id=repo_id, filename="absa_prompt.json")
11with open(prompt_file_path, "r", encoding="utf-8") as f:
12 prompt_data = json.load(f)
13
14# 2. Load the model and tokenizer in quantized 4-bit for high efficiency
15model = AutoPeftModelForCausalLM.from_pretrained(
16 repo_id,
17 load_in_4bit=True,
18 device_map="auto"
19)
20tokenizer = AutoTokenizer.from_pretrained(repo_id)
21
22# 3. Define your custom multilingual review
23review_text = "La comida buenísima, especialmente la carne, de precio correcto, pero los camareros tardaron una eternidad en llevarnos la cuenta."
24review_language = "es" # Supports "es" and "en"
25
26# Format the user part of the prompt
27user_content = prompt_data["user"].format(language=review_language, text=review_text)
28
29# Build the ChatML message array using the separated system and user roles
30messages = [
31 {"role": "system", "content": prompt_data["system"]},
32 {"role": "user", "content": user_content}
33]
34
35inputs = tokenizer.apply_chat_template(
36 messages,
37 tokenize=True,
38 add_generation_prompt=True,
39 return_tensors="pt"
40).to("cuda")
41
42outputs = model.generate(
43 inputs,
44 max_new_tokens=256,
45 temperature=0.1,
46 do_sample=False
47)
48
49# 4. Decode response skipping the prompt system structure
50generated_tokens = outputs[0][len(inputs[0]):]
51response = tokenizer.decode(generated_tokens, skip_special_tokens=True)
52
53print(response)
54# Expected Output: {"food_quality": "positive", "food_prices": "neutral", "service": "negative"}