Downloads · 30 days
19
2% of all-time downloads
diego-florez/Qwen2.5-7B-Comment-Sexuality-Reasoner
Qwen2.5-7B-Comment-Sexuality-Reasoner is a text classification model from diego-florez. Use it when you need a label for a piece of text. The card lists the license as apache-2.0.
A Spanish-language, context-aware reasoning model fine-tuned from Qwen/Qwen2.5-7B-Instruct for analyzing social-media comments in relation to image context, topic, and comment author information.
Downloads · 30 days
19
2% of all-time downloads
All-time downloads
786
Public
Parameters
7.6B
15.2 GB on disk
Likes
0
Public
Click a slice to open those files.
.safetensors15.2 GB · 100%
From the Hugging Face model README
A Spanish-language, context-aware reasoning model fine-tuned from Qwen/Qwen2.5-7B-Instruct for analyzing social-media comments in relation to image context, topic, and comment author information.
The model classifies comments as non-sexualized, sexualized, or neutral, and also returns a short Spanish reasoning and a probability for each of the three classes.
Qwen2.5-7B-Comment-Sexuality-Reasoner is a fine-tuned version of Qwen2.5-7B-Instruct adapted to a specific social-media analysis task in Spanish.
The model receives contextual information associated with an image together with one or more comments and analyzes each comment individually.
The task is context-aware: the model evaluates the meaning and intent of a comment in relation to the provided image context and topic, rather than relying only on individual words.
Qwen/Qwen2.5-7B-InstructThe model is intended for:
The model should be considered a research model, not a production-ready moderation system.
The model expects structured information containing:
image_context: textual description of the associated image.topic: topic associated with the image/content.comment_author: author identifier.author_gender: estimated gender of the comment author, i.e. the commenter (Male, Female or Not identifiable).comments: one or more comments to analyze.Comments are grouped by:
image_id + comment_author
This allows multiple comments from the same author on the same image to be provided together as additional context, while each comment is still classified independently.
non-sexualized: The comment is based on the image context and/or expresses admiration, support, or humor without sexual connotations or hidden intentions.sexualized: The comment expresses desire, objectification, or an explicit or implicit sexual insinuation toward the person, outside the context of the image.neutral: Multiple interpretations are possible and there is insufficient evidence to decide between them, or there is insufficient context.For each input comment, the model returns a JSON object with:
labelreasoning (in Spanish)non_sexualized_probabilitysexualized_probabilityneutral_probabilityThe output is a JSON array with exactly one object per input comment, in the same order as the input. The three probabilities are intended to sum to 1.00, and the label should correspond to the class with the highest probability.
The training data was built for this specific task from Spanish social-media comments, each with an image description, topic, author metadata, label, reasoning and class probabilities.
Qwen2.5-32B-Instruct-AWQ with few-shot examples taken from a human-labeled gold set.| Phase | Source | Comments | non-sexualized | sexualized | neutral |
|---|---|---|---|---|---|
| Phase 1 | LLM-annotated | 8,618 | 81.5% | 14.2% | 4.3% |
| Phase 2 | 344 human-corrected + 1,000 LLM-annotated (stratified) | 1,344 | 76.3% | 12.1% | 11.6% |
The gold set used for evaluation was never used for training.
Training was performed in two phases on top of the same adapter:
| Hyperparameter | Phase 1 | Phase 2 |
|---|---|---|
| Epochs | 3 (best checkpoint at step 600 of 1,029) | 2 (112 steps) |
| Learning rate | 1.5e-4 | 4e-5 |
| Batch size | 24 | 24 |
| Scheduler / warmup | cosine / 0.1 | cosine / 0.1 |
| Max grad norm | 0.5 | 0.5 |
Adapter configuration: DoRA with rsLoRA, r=64, lora_alpha=128, lora_dropout=0.05, applied to q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj and down_proj (162.9M trainable parameters, 2.09% of the model). Base model loaded in 4-bit, max_seq_length=2048, NVIDIA A100 80GB.
The final adapter was merged with the base model and saved in 16-bit format for inference.
The model was evaluated on a held-out, human-annotated gold set of 448 comments (342 non-sexualized, 54 sexualized, 52 neutral).
The main comparison is against Qwen2.5-32B-Instruct-AWQ, the same base model used as annotator, here evaluated under the same conditions as the fine-tuned model: same prompt and no few-shot examples. Both models were run with vLLM on an NVIDIA A100 (Google Colab).
The benchmark is task-specific and should not be interpreted as a general-purpose LLM benchmark.
| Metric | Qwen2.5-32B-Instruct-AWQ | Qwen2.5-7B-Comment-Sexuality-Reasoner |
|---|---|---|
| Accuracy [95% CI] | 42.19% [37.5–47.1] | 70.54% [66.3–74.6] |
| Weighted F1 | 49.24% | 70.53% |
| Macro F1 [95% CI] | 37.93% [33.0–43.0] | 46.98% [41.1–53.1] |
| Inference time (448 comments) | 4m 30s | 35s |
Weighted F1 weights each class by its number of examples and is dominated by non-sexualized (76% of the test set). Macro F1 weights the three classes equally and is more demanding on the minority classes. Confidence intervals are computed by bootstrap (2,000 resamples of the test set).
The difference with the 32B model is statistically significant (McNemar's test, p < 10⁻¹⁷): the fine-tuned model correctly classifies 166 comments that the 32B model gets wrong, while the opposite happens in only 39.
Per class:
| Class | Model | Precision | Recall | F1 |
|---|---|---|---|---|
| non-sexualized | 32B | 0.913 | 0.398 | 0.554 |
| 7B | 0.836 | 0.833 | 0.835 | |
| sexualized | 32B | 0.318 | 0.500 | 0.388 |
| 7B | 0.302 | 0.352 | 0.325 | |
| neutral | 32B | 0.121 | 0.500 | 0.195 |
| 7B | 0.273 | 0.231 | 0.250 |
The 32B model over-predicts neutral (214 predictions for 52 true cases), which explains most of its accuracy gap. The fine-tuned 7B model predicts each class in a proportion close to the real one, but has lower recall than the 32B model on sexualized.
A TF-IDF + logistic regression classifier trained on the same training data and with the same inputs as the language models (comment, topic, author_gender and image_context) reaches 68.5% accuracy [64.1–72.8] and 43.8% macro F1 [38.8–49.3] on the same test set. The fine-tuned model obtains higher point estimates, but the difference is not statistically significant on this test set (McNemar's test, p = 0.36): in classification alone, both reach a similar level. Adding the image description does not improve the TF-IDF model: a bag-of-words model cannot relate the comment to what the image shows.
What the fine-tuned model adds over a classical classifier is a per-comment reasoning that can be audited, class probabilities, and the use of the image context. The baseline also shows that performance is bounded by the quality of the training labels: it reaches 63.4% macro F1 in cross-validation against the annotator's labels, but 43.8% against the human labels.
Brier score per class (lower is better):
| Class | Qwen2.5-32B-Instruct-AWQ | Qwen2.5-7B-Comment-Sexuality-Reasoner |
|---|---|---|
| neutral | 0.1380 | 0.1078 |
| non-sexualized | 0.2605 | 0.2075 |
| sexualized | 0.1385 | 0.1569 |
| Mean | 0.1790 | 0.1574 |
The 7B model is well calibrated for non-sexualized in the high-probability range, but it is overconfident on sexualized: when it assigns ~0.95 to sexualized, only ~28% of those comments are actually sexualized.
| Metric | Qwen2.5-32B-Instruct-AWQ | Qwen2.5-7B-Comment-Sexuality-Reasoner |
|---|---|---|
| Lexical diversity: TTR | 0.859 | 0.822 |
| Lexical diversity: MTLD | 86.75 | 55.73 |
| Cosine similarity to human reasoning, correct predictions | 0.673 | 0.645 |
| Cosine similarity to human reasoning, all predictions | 0.645 | 0.656 |
| Cosine similarity to label definition (mean of 3 classes) | 0.611 | 0.624 |
Cosine similarity was computed with BAAI/bge-m3 embeddings.
Reasoning quality was also evaluated with Mistral-Small-24B-Instruct-2501-AWQ as judge, from a different model family to avoid self-preference bias. For each of the 448 test comments, the judge received the image context, the comment, the human label and reasoning, and the outputs of both models, presented anonymously as model A and model B with a random assignment per comment. For each criterion, it scored both models from 0 to 5 before choosing one.
| Criterion | 32B mean score | 7B mean score | 32B chosen | 7B chosen |
|---|---|---|---|---|
| Best answer | 3.90 | 3.88 | 240 | 208 |
| Most similar to human reasoning | 3.41 | 3.48 | 229 | 219 |
| Richest reasoning | 3.94 | 3.56 | 288 | 160 |
| Self-contradictory (lower is better) | 0.39 | 0.41 | 1 | 3 |
The judge rates both models as equivalent in overall reasoning quality, the fine-tuned model as slightly closer to the human reasoning, and the 32B model as producing richer reasoning. Self-contradictions are rare for both (under 1% of comments). The judge shows some position bias (it picks the second model about 60% of the time on two criteria), so mean scores are more reliable than win counts.
sexualized.image_context and topic. Errors or biases in the image-to-text description can propagate to the final classification.sexualized predictions concentrate on comments by male authors (42 of 44), cases where gender weighs more than the comment content. Accuracy is 57.0% on comments by male authors vs 92.9% on comments by female authors, partly because almost all sexualized and ambiguous comments in the test set are written by men.sexualized: all false sexualized predictions on the test set have a probability of 0.9 or higher.neutral and sexualized have wide confidence intervals (e.g. sexualized F1: 0.22–0.43).pip install transformers==4.45.2 unsloth==2026.8.16 torch==2.4.0 vllm==0.6.3.post1 trl==1.10.0 peft==0.19.1
Inference environment: Python 3.12.13, NVIDIA A100-SXM4-40GB. The model is expected to run on smaller GPUs such as an NVIDIA L4 or T4, although memory requirements and inference speed depend on the configuration and workload.
from vllm import LLM
MODEL_PATH = "diego-florez/Qwen2.5-7B-Comment-Sexuality-Reasoner"
llm = LLM(
model=MODEL_PATH,
dtype="float16",
gpu_memory_utilization=0.90,
max_model_len=6144,
trust_remote_code=True,
)
tokenizer_vllm = llm.get_tokenizer()
Use the full prompt below: it is the same one used during training.
import json
SYSTEM_MESSAGE = (
"Eres un experto razoneando y etiquetando comentarios "
"en redes sociales. "
"Responde SOLO JSON válido en español castellano."
)
TASK_INSTRUCTIONS = """
TASK:
Tu tarea es analizar comentarios relacionando con:
- image_context
- topic
- author_gender
Para cada comentario de la lista devuelve:
- label
- reasoning
- non_sexualized_probability
- sexualized_probability
- neutral_probability
IMPORTANTE:
- Usa SIEMPRE español castellano.
- No uses inglés en el reasoning.
- Usa el contexto completo antes de decidir.
- Si existen varios comentarios del mismo autor para la misma imagen, utilízalos como contexto adicional para interpretar la intención de cada comentario, pero clasifica cada comentario de forma individual.
Requisitos de las probabilidades:
- Las tres deben sumar exactamente 1.00
- El label debe corresponder a la categoría con mayor probabilidad
- Usa toda la escala, no solo valores predeterminados
DEFINICIÓN DE LABELS:
non_sexualized: Comentario basado en el contexto de la imagen y/o que expresa admiración, apoyo o humor, sin connotaciones ni segundas intenciones.
sexualized: Comentario que expresa deseo, objetificación o insinuación explícita o enmascarada hacia la persona, fuera de contexto de la imagen.
neutral: Existen varias interpretaciones posibles y no hay evidencia suficiente para decidir entre ellas o falta contexto suficiente en el comentario.
EVITA SESGOS:
- El author_gender aporta contexto, pero nunca debe ser suficiente por sí solo para decidir la clasificación.
- El topic no implica sexualización. Comparar siempre comentario y contexto.
- Si durante el razonamiento existen varias interpretaciones posibles y no hay evidencia suficiente para favorecer claramente una de ellas, prioriza la categoría neutral.
- Reserva probabilidades superiores a 0.90 para casos con evidencia clara y directa.
- El reasoning debe explicar qué evidencias del comentario y del contexto justifican la clasificación.
- Evalúa la intención del comentario en relación con el contexto de la imagen, no únicamente las palabras utilizadas.
# FORMATO DE SALIDA (ARRAY JSON)
[
{
"label": "sexualized | neutral | non-sexualized",
"reasoning": "explicación en español",
"non_sexualized_probability": 0.XX,
"sexualized_probability": 0.XX,
"neutral_probability": 0.XX
}
]
Cada elemento del array "comments" corresponde a un comentario independiente.
La salida debe ser un único array JSON que contenga exactamente un objeto por cada elemento del array "comments", respetando el mismo orden.
"""
def build_user_message(grouped_row):
comments_list = [{"comment_text": ctext} for ctext in grouped_row["comment_text"]]
input_data = {
"image_context": grouped_row["image_context"],
"topic": grouped_row["topic"],
"comment_author": grouped_row["comment_author"],
"author_gender": grouped_row["author_gender"],
"num_comments": len(comments_list),
"comments": comments_list,
}
return f"""INPUT DATA:
{json.dumps(input_data, ensure_ascii=False, indent=2)}
{TASK_INSTRUCTIONS}"""
def build_full_prompt(grouped_row):
messages = [
{"role": "system", "content": SYSTEM_MESSAGE},
{"role": "user", "content": build_user_message(grouped_row)},
]
return tokenizer_vllm.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True,
)
df is a dataframe with one row per comment and the columns comment_id, comment_text, comment_author, author_gender, image_id, image_context and topic.
grouped = (
df
.groupby(["image_id", "comment_author"])
.agg({
"image_context": "first",
"topic": "first",
"author_gender": "first",
"comment_id": list,
"comment_text": list,
})
.reset_index()
)
from vllm import SamplingParams
prompts = []
sampling_params = []
for _, row in grouped.iterrows():
n = len(row["comment_id"])
prompts.append(build_full_prompt(row))
sampling_params.append(
SamplingParams(
temperature=0.0,
repetition_penalty=1.05,
max_tokens=min(512, n * 384),
)
)
outputs = llm.generate(prompts, sampling_params, use_tqdm=True)
Each JSON object in the response is parsed individually, so a single malformed object does not invalidate the rest of the group. Predictions are aligned with the original comment_id values by position, never by any identifier generated by the model.
import re
import pandas as pd
def parse_objects(text):
parsed = []
for match in re.findall(r"\{[^{}]*\}", text):
try:
parsed.append(json.loads(match))
except json.JSONDecodeError:
parsed.append(None)
return parsed
rows = []
for (_, group), output in zip(grouped.iterrows(), outputs):
objects = parse_objects(output.outputs[0].text)
for i, comment_id in enumerate(group["comment_id"]):
obj = objects[i] if i < len(objects) and objects[i] else {}
rows.append({
"comment_id": comment_id,
"pred_label": obj.get("label", "parse_error"),
"reasoning": obj.get("reasoning"),
"non_sexualized_probability": obj.get("non_sexualized_probability"),
"sexualized_probability": obj.get("sexualized_probability"),
"neutral_probability": obj.get("neutral_probability"),
})
predictions = pd.DataFrame(rows)
Input for one group (image_id + comment_author):
{
"image_context": "Mujer posando en ropa interior",
"topic": "Modeling lingerie",
"comment_author": "@test_user",
"author_gender": "Male",
"num_comments": 2,
"comments": [
{"comment_text": "Qué guapa"},
{"comment_text": "Te amo ❤️"}
]
}
Output format (one object per comment, in the same order):
[
{
"label": "non-sexualized",
"reasoning": "El comentario expresa admiración general.",
"non_sexualized_probability": 0.75,
"sexualized_probability": 0.15,
"neutral_probability": 0.1
},
{
"label": "sexualized",
"reasoning": "Expresa atracción directa hacia la persona.",
"non_sexualized_probability": 0.1,
"sexualized_probability": 0.8,
"neutral_probability": 0.1
}
]
This example illustrates the input and output format used during training; it is not an actual model prediction.
The repository contains the complete merged 16-bit model, its configuration and the tokenizer files. All weight shards listed in the safetensors index are required.
This model is released under the Apache License 2.0, consistent with the licensing of the Qwen2.5-7B-Instruct base model.
Please review the base model's license and terms before using the model in downstream applications.
If you use this model or the associated dataset/pipeline in research, please cite the corresponding project repository once it is published.