---
library_name: transformers
license: mit
datasets:
- yowww1094/tourism-llm-fine-tuning-dataset
language:
- en
base_model:
- Qwen/Qwen2.5-1.5B-Instruct
tags:
- tourism
- travel
- question-answering
- lora
- fine-tuned
- rag
---

# Tourism Assistant — Qwen2.5-1.5B Fine-Tuned

A fine-tuned version of [Qwen/Qwen2.5-1.5B-Instruct](https://huggingface.co/Qwen/Qwen2.5-1.5B-Instruct) trained on a custom tourism Q&A dataset generated through a RAG-grounded pipeline. Built as a personal end-to-end learning project covering data collection, dataset engineering, supervised fine-tuning, and deployment.

> ⚠️ This model is not production-ready. It is a learning project. Outputs can be incorrect, incomplete, or inconsistent — especially on topics not well-represented in the training data. Do not rely on this model for real travel decisions.

---

## Model Details

### Model Description

This model was fine-tuned using FP16 LoRA (Low-Rank Adaptation) on a small custom dataset of ~150–200 tourism-focused question-answer pairs. The training examples were generated through a RAG pipeline: Reddit travel posts were scraped, embedded, and stored in a Qdrant vector store, then a locally-hosted Qwen2.5-7B (via Ollama) was used to generate grounded Q&A pairs from retrieved context chunks. The resulting dataset was formatted in ChatML and used to fine-tune this model.

The goal of fine-tuning was to adjust the model's **behavioral style** — making it more focused, concise, and consistently helpful for travel queries — rather than to inject new factual knowledge. Factual grounding at inference time is handled by a RAG pipeline backed by Qdrant Cloud.

- **Developed by:** Younes
- **Model type:** Causal Language Model — fine-tuned for instruction following
- **Language:** English
- **License:** MIT
- **Base model:** [Qwen/Qwen2.5-1.5B-Instruct](https://huggingface.co/Qwen/Qwen2.5-1.5B-Instruct)
- **Fine-tuning method:** FP16 LoRA (merged into base weights)
- **Training dataset:** [yowww1094/tourism-llm-fine-tuning-dataset](https://huggingface.co/datasets/yowww1094/tourism-llm-fine-tuning-dataset)

### Model Sources

- **Repository:** [Github](https://github.com/yowww1094/llm-tourism-assistant)
- **Demo:** [Demo](https://huggingface.co/spaces/yowww1094/AI-tourism-chatbot)

---

## Uses

### Direct Use

This model can be used as a conversational assistant for general tourism and travel questions — destination information, logistics, visa guidance, packing advice, and similar topics. It works best when paired with a retrieval pipeline that provides relevant context at inference time.

```python
from transformers import AutoModelForCausalLM, AutoTokenizer

model_id = "yowww1094/tourism-assistant-qwen2"
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(model_id, torch_dtype="auto", device_map="auto")

messages = [
    {"role": "system", "content": "You are a helpful tourism assistant."},
    {"role": "user", "content": "What are the must-visit places in Marrakech?"}
]

text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
inputs = tokenizer([text], return_tensors="pt").to(model.device)

outputs = model.generate(**inputs, max_new_tokens=256, temperature=0.7, do_sample=True)
response = tokenizer.decode(outputs[0][len(inputs.input_ids[0]):], skip_special_tokens=True)
print(response)
```

### Downstream Use

This model is designed to be used as the generation component of a RAG pipeline. The recommended usage is:

1. Embed the user query with `all-MiniLM-L6-v2`
2. Retrieve top-k relevant chunks from a Qdrant vector store
3. Inject retrieved context into the prompt before generation
4. Pass the full prompt to this model

Pairing the model with retrieval significantly improves factual accuracy on specific travel queries compared to using the model standalone.

### Out-of-Scope Use

- **Real-time travel information:** The model has no access to live data. Flight prices, visa requirements, and safety conditions change frequently — do not rely on this model for current information.
- **Medical or legal travel advice:** The model is not equipped to give reliable guidance on health requirements, legal restrictions, or emergency situations.
- **Non-English queries:** The model was trained exclusively on English data and is not reliable for other languages.
- **High-stakes decisions:** This is a learning project. Outputs should not be used to make actual travel bookings, visa applications, or safety assessments.

---

## Bias, Risks, and Limitations

**Dataset limitations — primary source of inaccuracy:**
The training dataset contains only ~150–200 examples sourced from Reddit travel communities. This introduces several compounding problems:

- Reddit's user base skews toward English-speaking, Western travellers — advice reflects this demographic and may not generalise to other travel styles or origins
- The dataset covers only a narrow slice of the tourism domain; large topic areas have no representation
- Source Reddit posts were not independently fact-checked; incorrect or outdated community advice may appear in training examples
- Only ~40 examples (~20%) were manually reviewed for quality before training

**Model behaviour limitations:**
- The model hallucinates specific facts (prices, distances, operating hours, visa fees) when retrieved context does not provide explicit grounding
- It does not reliably abstain from answering when it does not know — it tends to produce a confident-sounding response regardless
- Response consistency is variable; the same query may produce meaningfully different answers across runs
- The model may reflect biases present in Reddit data, including opinions presented as facts

### Recommendations

- Always pair this model with a retrieval pipeline for factual queries
- Display a disclaimer to end users that outputs may be inaccurate
- Do not deploy in contexts where incorrect travel information could cause harm
- Treat all specific factual claims (prices, hours, requirements) as unverified until confirmed from an authoritative source

---

## How to Get Started with the Model

### Basic inference (no RAG)

```python
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch

model_id = "yowww1094/tourism-assistant-qwen2"

tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(
    model_id,
    torch_dtype=torch.float16,
    device_map="auto"
)

messages = [
    {"role": "system", "content": "You are a helpful tourism assistant. Answer travel questions clearly and concisely."},
    {"role": "user", "content": "What is the best time of year to visit Morocco?"}
]

text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
inputs = tokenizer([text], return_tensors="pt").to(model.device)

with torch.no_grad():
    outputs = model.generate(
        **inputs,
        max_new_tokens=300,
        temperature=0.7,
        top_p=0.9,
        do_sample=True,
        repetition_penalty=1.1
    )

response = tokenizer.decode(outputs[0][len(inputs.input_ids[0]):], skip_special_tokens=True)
print(response)
```

### Recommended inference (with RAG context)

```python
# retrieved_context = top-k chunks from your Qdrant vector store

system_prompt = "You are a helpful tourism assistant. Use only the provided context to answer. If the context does not contain enough information, say so."

user_prompt = f"""Context:
{retrieved_context}

Question: {user_query}"""

messages = [
    {"role": "system", "content": system_prompt},
    {"role": "user", "content": user_prompt}
]

# then apply chat template and generate as above
```

---

## Training Details

### Training Data

The model was fine-tuned on [yowww1094/tourism-llm-fine-tuning-dataset](https://huggingface.co/datasets/yowww1094/tourism-llm-fine-tuning-dataset), a custom dataset generated through the following pipeline:

1. Reddit travel posts and comments were scraped from subreddits including r/travel, r/Morocco, r/solotravel, and r/backpacking using PRAW
2. Raw text was cleaned (length filter, deduplication, HTML stripping, encoding fix) and chunked
3. Chunks were embedded with `all-MiniLM-L6-v2` and indexed in a Qdrant vector store
4. A locally-hosted Qwen2.5-7B (via Ollama) was prompted to generate grounded question-answer pairs from retrieved context chunks
5. Outputs were post-processed into ChatML format and manually sampled for quality (~40 examples reviewed)

**Dataset size:** ~150–200 question-answer pairs  
**Format:** JSON Lines  
**Split:** 90% train / 10% validation  
**Quality note:** Only ~65% of manually reviewed examples were rated acceptable. No automated quality filter was applied to the full dataset.

### Training Procedure

#### Preprocessing

Each example was formatted using the Qwen2.5-Instruct chat template via `tokenizer.apply_chat_template()`. Sequences were truncated to a maximum length of 512 tokens. No data augmentation was applied.

#### Training Hyperparameters

| Parameter | Value |
|---|---|
| Training regime | FP16 mixed precision |
| LoRA rank (r) | 16 |
| LoRA alpha | 32 |
| LoRA dropout | 0.05 |
| Target modules | q_proj, v_proj |
| Epochs | 3 |
| Batch size | 4 |
| Gradient accumulation steps | 4 (effective batch size: 16) |
| Learning rate | 2e-4 |
| LR scheduler | Cosine annealing |
| Warmup ratio | 0.03 |
| Max sequence length | 512 tokens |
| Optimizer | AdamW (default via transformers) |

#### Hardware and Duration

- **Hardware:** NVIDIA T4 GPU (15 GB VRAM) — Kaggle free tier
- **Training time:** ~45–60 minutes for 3 epochs on ~150 examples
- **Framework:** transformers 4.x + peft + trl (SFTTrainer) + accelerate

---

## Evaluation

### Testing Data

Evaluation was performed on a held-out validation split of ~15–20 examples (10% of the total dataset). Due to the small size of this split, quantitative metrics should be interpreted with significant caution — they are not statistically reliable estimates of generalisation performance.

In addition to automatic metrics, a qualitative evaluation was performed by manually inspecting model outputs on ~20 held-out queries not present in the training data.

### Metrics

| Metric | Value | Notes |
|---|---|---|
| Training loss (epoch 1) | ~1.62 | |
| Training loss (epoch 3) | ~0.85 | Consistent decrease across epochs |
| Validation loss (epoch 1) | ~1.74 | |
| Validation loss (epoch 3) | ~1.29 | Slight divergence from train loss — mild overfitting |
| Validation perplexity | ~2.3 | On 15–20 examples only; not a reliable generalisation estimate |

### Results

**What improved after fine-tuning:**
- Response style and tone became more focused and consistently helpful compared to the base model
- The model more readily uses tourism-relevant vocabulary and response structure
- For in-distribution queries (topics well-represented in the dataset), the combination of fine-tuning + RAG outperforms either mechanism alone

**What did not improve:**
- Factual accuracy on out-of-distribution queries is comparable to the base model — fine-tuning at this scale does not inject meaningful new factual knowledge
- Hallucination rate on specific facts (prices, dates, requirements) is unchanged without retrieval grounding
- The model occasionally produces responses that closely paraphrase training examples, suggesting partial memorisation

#### Summary

Fine-tuning on this small dataset improved behavioral style but not factual coverage. The model is more useful when paired with a retrieval pipeline than when used standalone. A dataset 10–20× larger with verified factual content would be needed to produce a genuinely reliable tourism assistant.

---

## Environmental Impact

Carbon emissions were not formally measured. Estimated figures based on training setup:

- **Hardware type:** NVIDIA T4 GPU (Kaggle free tier)
- **Hours used:** ~1 hour total training time
- **Cloud provider:** Google (Kaggle infrastructure)
- **Compute region:** Unknown
- **Carbon emitted:** Estimated < 0.05 kg CO₂eq (based on [ML Impact Calculator](https://mlco2.github.io/impact#compute))

---

## Technical Specifications

### Model Architecture

- **Architecture:** Qwen2.5 decoder-only transformer (causal LM)
- **Parameters:** 1.5 billion (base model)
- **Context window:** 32,768 tokens (base model capability; fine-tuning used max 512 tokens)
- **Fine-tuning method:** LoRA adapters applied to `q_proj` and `v_proj` attention matrices, then merged into base weights before upload

### Compute Infrastructure

- **Training:** Kaggle free-tier notebook, T4 GPU, 15 GB VRAM
- **Inference:** Hugging Face Inference Endpoints (free tier)
- **Vector store:** Qdrant Cloud (free tier, ~1,200 indexed chunks)
- **Embedding:** `sentence-transformers/all-MiniLM-L6-v2`, CPU inference

### Software

```
transformers>=4.40.0
peft>=0.10.0
trl>=0.8.0
accelerate>=0.28.0
sentence-transformers>=2.6.0
qdrant-client>=1.9.0
torch>=2.1.0
```

---

## Citation

If you reference this project, please cite it as:

```bibtex
@misc{younes2026tourismllm,
  author    = {Younes},
  title     = {End-to-End LLM Pipeline for Tourism Assistant},
  year      = {2026},
  publisher = {Hugging Face},
  url       = {[Model](https://huggingface.co/yowww1094/tourism-llm-fine-tuned-qwen2-1.5b-lora-merged)}
}
```

---

## More Information

Full technical report (covering pipeline design, training decisions, limitations, and results in detail):
[docs/technical_report.pdf](https://github.com/yowww1094/llm-tourism-assistant/blob/master/docs/technical_report.pdf)

GitHub repository with full pipeline code:
[Github](https://github.com/yowww1094/llm-tourism-assistant)

Training dataset:
[yowww1094/tourism-llm-fine-tuning-dataset](https://huggingface.co/datasets/yowww1094/tourism-llm-fine-tuning-dataset)

---

## Model Card Author

Younes AIT SI ABBOU — personal learning project, April 2026