Downloads · 30 days
5
10% of all-time downloads
VictorYeste/human-value-detection-gemma2-9b-qlora
human-value-detection-gemma2-9b-qlora is a machine learning model from VictorYeste. Use it for the machine learning task on the model card, and read the license before you ship it in a product. It is set up for peft. The card lists the license as apache-2.0.
This repository provides QLoRA / LoRA adapters for Gemma 2 9B Instruct, trained for sentence-level human value detection as described in:
Downloads · 30 days
5
10% of all-time downloads
All-time downloads
50
Public
Repo size
106 MB
Likes
0
Public
Click a slice to open those files.
.safetensors71.6 MB · 68%
From the Hugging Face model README
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.
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).
The adapters were trained using QLoRA (4-bit quantization + LoRA fine-tuning), keeping the memory footprint compatible with a single consumer GPU.
Not trained or audited for safety-critical or high-stakes decision-making.
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: toleranceNote: 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.
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,
...
}
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:
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).
Adapters were trained on the English, machine-translated portion of the ValueEval’24 / ValuesML dataset:
Important: the dataset is distributed under a restricted Data Usage Agreement. You must obtain it separately and respect its license.
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:
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
Do not use this model for profiling individuals or high-stakes decisions.
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.
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}
}