Human Value Detection – Gemma 2 9B (QLoRA Adapters)
This repository provides QLoRA / LoRA adapters for Gemma 2 9B Instruct, trained for sentence-level human value detection as described in:
Human Values in a Single Sentence: Moral Presence, Hierarchies, and Transformer Ensembles on the Schwartz Continuum
Víctor Yeste, Paolo Rosso (2026), arXiv:2601.14172
Do Schwartz Higher-Order Values Help Sentence-Level Human Value Detection? When Hard Gating Hurts
Víctor Yeste, Paolo Rosso (2026), arXiv:2602.00913
Important: this repo contains adapters only (adapter_model.safetensors + PEFT config).
You must load them on top of the base model: google/gemma-2-9b-it.
What the model does
This model is an LLM-based multi-label value detector over the refined Schwartz values (typically 19; some experiments in the code may use subsets).
- Input: a single sentence (news / political text, in English)
- Output: a JSON object mapping each value name to 0/1
- Labels: we collapse “attained” and “constrained” into a single binary label per value (value is expressed vs. not expressed)
The adapters were trained using QLoRA (4-bit quantization + LoRA fine-tuning), keeping the memory footprint compatible with a single consumer GPU.
Intended use
- Research on human value detection, moral language, and Schwartz values in text.
- Baseline / comparison point for:
- Instruction-tuned LLMs for moral/value-aware text analysis
- Multi-label prediction under class imbalance
- LLM prompting vs. fine-tuning for value detection
Not trained or audited for safety-critical or high-stakes decision-making.
Labels
The target labels follow the refined Schwartz value continuum (19-way setup used in the paper):
Self-direction: thoughtSelf-direction: actionStimulationHedonismAchievementPower: dominancePower: resourcesFaceSecurity: personalSecurity: societalTraditionConformity: rulesConformity: interpersonalHumilityBenevolence: caringBenevolence: dependabilityUniversalism: concernUniversalism: natureUniversalism: tolerance
Note: Some training runs may focus on a subset of values (e.g., specific higher-order groups).
The recommended interface is to keep the value list in the prompt consistent with the run you want to reproduce.
How to use
1. Load adapters (PEFT) and run inference
import json
import torch
from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig
from peft import PeftModel
adapter_id = "VictorYeste/human-value-detection-gemma2-9b-qlora"
base_id = "google/gemma-2-9b-it"
bnb_cfg = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.float16,
bnb_4bit_use_double_quant=False,
)
tokenizer = AutoTokenizer.from_pretrained(base_id, token=HF_TOKEN)
if tokenizer.pad_token_id is None:
tokenizer.pad_token = tokenizer.eos_token
base = AutoModelForCausalLM.from_pretrained(
base_id,
device_map="auto",
quantization_config=bnb_cfg,
torch_dtype=torch.float16,
token=HF_TOKEN,
)
model = PeftModel.from_pretrained(base, adapter_id)
model.eval()
VALUE_DEFINITIONS = {
"Self-direction: thought": "Freedom to cultivate one’s own ideas and abilities",
"Self-direction: action": "Freedom to determine one’s own actions",
"Stimulation": "Excitement, novelty, and change",
"Hedonism": "Pleasure and sensuous gratification",
"Achievement": "Success according to social standards",
"Power: dominance": "Power through exercising control over people",
"Power: resources": "Power through control of material and social resources",
"Face": "Maintaining one’s public image and avoiding humiliation",
"Security: personal": "Safety in one’s immediate environment",
"Security: societal": "Safety and stability in the wider society",
"Tradition": "Maintaining and preserving cultural, family, or religious traditions",
"Conformity: rules": "Compliance with rules, laws, and formal obligations",
"Conformity: interpersonal": "Avoidance of upsetting or harming other people",
"Humility": "Recognising one’s insignificance in the larger scheme of things",
"Benevolence: caring": "Devotion to the welfare of in-group members",
"Benevolence: dependability": "Being a reliable and trustworthy member of the in-group",
"Universalism: concern": "Commitment to equality, justice, and protection for all people",
"Universalism: nature": "Preservation of the natural environment",
"Universalism: tolerance": "Acceptance and understanding of those who are different from oneself",
}
DEFS_BLOCK = "\n".join(f"- **{k}**: {v}" for k, v in VALUE_DEFINITIONS.items())
SYS = (
"You are a moral-psychology assistant. Using the 'refined basic values' taxonomy "
"(Schwartz 1992; Schwartz et al. 2012), answer the user’s labeling requests exactly as instructed."
)
def build_prompt(sentence: str) -> str:
return (
"### Value definitions\n"
f"{DEFS_BLOCK}\n\n"
"### Task\n"
"Identify which of the above values the SENTENCE relates to. "
"Return **only** a JSON array of the matching value names.\n\n"
f"SENTENCE: {sentence}"
)
def build_chat_text(tokenizer, sys_prompt: str, user_prompt: str) -> str:
"""
Robust chat formatting:
1) Try system+user (works for models that support system role)
2) If system role unsupported (e.g., Gemma template), fold system into user
3) If no chat template, fall back to plain concatenation
"""
msgs_sys_user = [
{"role": "system", "content": sys_prompt},
{"role": "user", "content": user_prompt},
]
try:
return tokenizer.apply_chat_template(msgs_sys_user, tokenize=False, add_generation_prompt=True)
except Exception:
msgs_user_only = [{"role": "user", "content": sys_prompt + "\n\n" + user_prompt}]
try:
return tokenizer.apply_chat_template(msgs_user_only, tokenize=False, add_generation_prompt=True)
except Exception:
return sys_prompt + "\n\n" + user_prompt
def _last_balanced_span(s: str, open_ch: str, close_ch: str):
start = -1
depth = 0
last = None
for i, ch in enumerate(s):
if ch == open_ch:
if depth == 0:
start = i
depth += 1
elif ch == close_ch and depth > 0:
depth -= 1
if depth == 0 and start != -1:
last = (start, i + 1)
return last
def extract_last_json(text: str):
"""
Extract the last valid JSON array/object from generated text.
Works even if the model adds extra text around JSON.
"""
s = text.strip()
span = _last_balanced_span(s, "{", "}") or _last_balanced_span(s, "[", "]")
if not span:
raise ValueError(f"No JSON object/array found in model output:\n{text}")
a, b = span
frag = s[a:b]
return json.loads(frag)
def predict(sentence: str):
user_prompt = build_prompt(sentence)
prompt = build_chat_text(tokenizer, SYS, user_prompt)
toks = tokenizer(prompt, return_tensors="pt").to(model.device)
with torch.inference_mode():
out = model.generate(
**toks,
max_new_tokens=200,
do_sample=False,
pad_token_id=tokenizer.eos_token_id,
eos_token_id=tokenizer.eos_token_id,
)
gen = tokenizer.decode(out[0, toks["input_ids"].shape[1]:], skip_special_tokens=True).strip()
return extract_last_json(gen)
example = "We must do more to protect the environment and future generations."
print(predict(example))
Note: Make sure you have requested access to the model google/gemma-2-9b-it, as it is restricted, and that you have stored the variable HF_TOKEN for authentication.
This will return a JSON object like:
{
"Self-direction: thought": 0.0,
"Self-direction: action": 0.0,
"Stimulation": 0.0,
"Hedonism": 0.0,
...
"Universalism: nature": 1.0,
...
}
2. Reproducing paper-style evaluation
In the paper, the LLM is prompted to output structured JSON and then evaluated as a multi-label classifier.
If you want probabilities, you can:
- run multiple stochastic samples (do_sample=True) and average,
- or use your existing pipeline that converts sets into 0/1 predictions.
(Optional) SBERT “hard gate” (retrofit hierarchy)
Some configurations use a presence gate (SBERT + Logistic Regression) to decide whether any value is present; if the gate rejects a sentence, the downstream value outputs are hard-masked to all zeros.
This repository does not include the gate artifact by default (because it is not part of the LoRA adapters).
Training data
Adapters were trained on the English, machine-translated portion of the ValueEval’24 / ValuesML dataset:
- Domain: news articles and political manifestos
- Unit of analysis: individual sentences
- Labels: 19 refined Schwartz values
- Original attained/constrained annotations collapsed into a single binary label per value
Important: the dataset is distributed under a restricted Data Usage Agreement. You must obtain it separately and respect its license.
Training setup (QLoRA)
- Base model: google/gemma-2-9b-it
- Method: QLoRA (4-bit NF4 quantization + LoRA adapters)
- Task format: instruction-style prompting with JSON outputs
- LoRA target modules: attention projections (q_proj, k_proj, v_proj, o_proj)
- Typical hyperparameters (may vary by run):
- r: 16
- alpha: 32
- epochs: 3
- learning rate: 2e-4
- gradient accumulation: 8
- max length: 512
Performance (paper reference)
On the English ValueEval’24 sentence-level splits used in the papers, this QLoRA-based LLM detector is reported as an LLM baseline and compared against:
- DeBERTa fine-tuned baselines
- presence-gated hierarchies
- feature-augmented DeBERTa models
- few-shot / prompt-only LLM variants
For full metrics (macro–F1, thresholds, and per-label behavior), refer to the papers:
Human Values in a Single Sentence: Moral Presence, Hierarchies, and Transformer Ensembles on the Schwartz Continuum Víctor Yeste, Paolo Rosso (2026), arXiv:2601.14172
Do Schwartz Higher-Order Values Help Sentence-Level Human Value Detection? When Hard Gating Hurts Víctor Yeste, Paolo Rosso (2026), arXiv:2602.00913
Limitations and bias
- Trained on news and political texts; may not generalize to:
- social media
- casual conversation
- ther genres or languages
- Rare values remain challenging due to label sparsity.
- LLM outputs may occasionally:
- include invalid JSON,
- include extra text,
- omit labels.
- Use robust parsing and post-processing for evaluation.
- No systematic bias/fairness auditing has been conducted.
Do not use this model for profiling individuals or high-stakes decisions.
License
The adapters and code in this repository are released under the Apache License 2.0.
This does not grant rights over the underlying training data (ValueEval/ValuesML). Please obtain and use the dataset under its own license.
Citation
If you use this model or the associated code, please cite:
@misc{yeste2026humanvaluessinglesentence,
title={Human Values in a Single Sentence: Moral Presence, Hierarchies, and Transformer Ensembles on the Schwartz Continuum},
author={Víctor Yeste and Paolo Rosso},
year={2026},
eprint={2601.14172},
archivePrefix={arXiv},
primaryClass={cs.CL},
url={https://arxiv.org/abs/2601.14172}
}
@misc{yeste2026schwartzhigherordervalueshelp,
title={Do Schwartz Higher-Order Values Help Sentence-Level Human Value Detection? When Hard Gating Hurts},
author={Víctor Yeste and Paolo Rosso},
year={2026},
eprint={2602.00913},
archivePrefix={arXiv},
primaryClass={cs.CL},
url={https://arxiv.org/abs/2602.00913},
}
You may also want to cite the ValueEval / ValuesML dataset:
@misc{ValueEval24Zenodo,
author = {{The ValuesML Team}},
title = {Touch{\'e}24{-}ValueEval},
year = {2024},
month = {8},
version = {2024-08-09},
publisher = {Zenodo},
doi = {10.5281/zenodo.13283288},
url = {https://doi.org/10.5281/zenodo.13283288}
}
- Downloads last month
- 18