
Framework di attacco di group shilling agentico guidato da LLM che manipola i ranking dei sistemi di raccomandazione collaborative-filtering black-box utilizzando strategie adattive multi-ruolo eludendo al contempo il rilevamento.
Questo è il codice ufficiale del paper: "An Efficient and Effective Agentic Group Shilling Attack on Recommender Systems". Questo paper introduce AGAS, che è un attacco shilling guidato da LLM contro recommender collaborative-filtering black-box. Un Coordinator orchestra un pool di worker fake-user attraverso una sequenza di round. In ogni round, il Coordinator sceglie una tra otto strategie e assegna un ruolo a ogni worker. I worker poi decidono quali item valutare utilizzando il proprio ciclo di ragionamento in stile ReAct.
agent_attack_rs/ bash/ # Reviewer-friendly shell scripts (RQ1–RQ5) prompts/ # Coordinator + per-role prompt templates scripts/run_agas.py # Single entry point (--dataset --victim ...) src/agas/ roles.py # Role enum {PR, SN, CA, IN} (paper symbols) signals.py # WorkerSignals (τ, γ, φ) + EnvSignals (ρ, Δρ, η, ξ, a) strategies.py # 8-strategy enum agents/ # Coordinator + Worker policies simulation/ # Episode runner (= AGAS algorithm outer loop) llm/ # OpenAI / Ollama recsys/ # Surrogate + 11-victim backends data/ # Dataset loaders + preprocessing pipeline tests/ # Pytest suite
## 2. Riepilogo del metodo
AGAS istanzia quattro ruoli di worker (simboli del paper in `roles.py`):
| Simbolo | Nome esteso | Cosa fa |
|---------|----------------|-------------------------------------------------------------------------|
| `PR` | Profiler | Valutazioni sicure di filler-item per sondare la piattaforma e costruire bridge pool. |
| `SN` | Sniper | Ruolo di payload; push diretto del target o promozione di bridge-item. |
| `CA` | Camouflageur | Ruolo stealth; ricostruisce la fiducia con attività dall'aspetto benigno. |
| `IN` | Inactive | Nessuna azione in questo round (cool-down o quarantena). |
Ogni round il Coordinator sceglie esattamente una tra otto strategie da
`strategies.py` (vedi `method_strategies.tex`):
1. **Victim Probe** (`S1_VICTIM_PROBE`)
2. **Bridge Building** (`S2_BRIDGE_BUILDING`, solo vittime del grafo)
3. **Warm-up** (`S3_WARM_UP`)
4. **First Push** (`S4_FIRST_PUSH`)
5. **Silent Slowdown** (`S5_SILENT_SLOWDOWN`)
6. **Profile Cleanup** (`S6_PROFILE_CLEANUP`)
7. **Safe Replacement** (`S7_SAFE_REPLACEMENT`)
8. **Main Attack** (`S8_MAIN_ATTACK`)
Il Coordinator guida tali decisioni a partire da due gruppi di segnali (`signals.py`):
* **Segnali dei worker** `τ_{t,w}, γ_{t,w}, φ_{t,w}` — fiducia, rischio e un
validatore strutturale. Le equazioni di aggiornamento corrispondono esattamente
a `method_coordinator.tex` (`eq:trust_update`, `eq:risk_update`, `eq:risk_decay`,
`eq:profile_validator`).
* **Segnali ambientali** `ρ^{(t)}, Δρ^{(t)}, η_t, ξ_t = (q_t, s_t), a_t` —
rank, movimento del rank, tasso di accettazione, segnale di soppressione, flag di allerta. Il
punteggio di sospetto `q_t` è la somma pesata a 0.2 dei cinque termini
normalizzati `(d̂_t, δ̂_t, m̂_t, ŝ_t, g_t)` da `eq:round_suppression_terms` e
`eq:round_suppression_score`.
### Ciclo del round (ASCII)```
┌─────────────────────────────────────────────────┐
t=0…T-1 ──► │ 1. Observe ρ^{(t)}, update memory m_t │
│ 2. Update τ, γ, φ, η, ξ, a │
│ 3. Coordinator picks Strategy ∈ {S1…S8} │
│ and assigns Role ∈ {PR, SN, CA, IN} per worker│
│ 4. Workers act (filler / bridge / target items) │
│ 5. Validate + accept actions → ΔR̃^{(t+1)} │
│ 6. Refit / query victim → ρ^{(t+1)} │
└─────────────────────────────────────────────────┘
│
▼
t* = argmin_t ρ^{(t)}, return R* = [R ; R̃^{(≤t*)}]
Il loop esterno è implementato in src/agas/simulation/episode.py e rispecchia
algorithms/agas_end_to_end.tex.
PyTorch e CUDA sono richiesti solo per i modelli vittima di deep learning (extra [targets]). Il loop AGAS principale e i percorsi basati su regole / surrogati funzionano su CPU senza dipendenze GPU.
pip install -e .
pip install -e '.[targets]'
Variabili d'ambiente richieste:
| Variabile | Scopo | Predefinito |
|--------------------|---------------------------------------------------------------|--------------------------|
| `OPENAI_API_KEY` | Chiave API OpenAI Responses per il Coordinator / worker LLMs. | *(non impostata → fallback)* |
| `OPENAI_MODEL` | Nome del modello passato a OpenAI. | `gpt-5.1` |
## 4. Dataset
Il paper valuta su sei benchmark CF pubblici (vedi `experiment.tex`):
| Nome breve | Fonte | Utenti | Elementi | Interazioni | Download | Posiziona i file grezzi in |
|-------------|---------------------------|----------:|---------:|-------------------:|-------------------------------------------------------------------|---------------------|
| ML-100K | MovieLens 100K | 943 | 1,682 | 100,000 | [GroupLens](https://files.grouplens.org/datasets/movielens/ml-100k.zip) | `data/ml-100k/` |
| ML-1M | MovieLens 1M | 6,040 | 3,706 | 1,000,209 | [GroupLens](https://files.grouplens.org/datasets/movielens/ml-1m.zip) | `data/ml-1m/` |
| Genome 2021 | MovieLens Tag Genome 2021 | 37,941 | 84,661 | 2,000,000 (limitato) | [GroupLens](https://grouplens.org/datasets/movielens/tag-genome-2021/) | `data/genome2021/` |
| Netflix | Netflix Prize | 342,445 | 17,434 | 2,000,000 (limitato) | [Kaggle](https://www.kaggle.com/datasets/netflix-inc/netflix-prize-data) | `data/netflix/` |
| Douban | Douban Movie | 28,057 | 49,176 | 8,085,679 | [HKUST](http://shichuan.org/HIN_dataset.html) | `data/douban/` |
| Amazon | Amazon Reviews 2018 | 998,653 | 30,964 | 2,000,000 (limitato) | [UCSD](https://nijianmo.github.io/amazon/index.html) | `data/amazon/` |
Dopo aver inserito i download grezzi in `data/<dataset>/`, esegui:```bash
python scripts/preprocess_all.py --data-root data --output-root processed
Ogni dataset viene riscritto in file canonici interactions.csv + items.csv
sotto processed/<dataset>/. Gli smoke test utilizzano il campione molto più piccolo
ml-latest-small fornito con MovieLens.
La pipeline di preprocessing non memorizza file di split — esporta l'intero log delle interazioni. Le suddivisioni vengono applicate a runtime:
Questo segue il protocollo standard di valutazione degli attacchi shilling: l'attaccante osserva i ranking della vittima sugli utenti del training set e ottimizza di conseguenza, simulando uno scenario di deployment black-box.
scripts/run_agas.py è l'unico punto di ingresso. I sette flag richiesti dal
protocollo del paper sono:```
python scripts/run_agas.py
--dataset ml-100k
--victim lightgcn
--rounds 18
--seed 42
--n_workers 8
--budget 0.01
--out outputs/agas_ml100k_lightgcn_seed42.json
| Flag | Significato |
|----------------|--------------------------------------------------------------------------------------------------|
| `--dataset` | Uno tra `ml-100k`, `ml-1m`, `genome2021`, `netflix`, `douban`, `amazon`, `ml-latest-small`. |
| `--victim` | Una delle 11 vittime da `experiment.tex` (`mf`, `bpr`, `neumf`, `gmf`, `ncf`, `ngcf`, `lightgcn`, `simgcl`, `xsimgcl`, `egcf`, `lightccf`). |
| `--rounds` | Numero di round AGAS `T` (default del paper `18`). |
| `--seed` | Seme casuale (il paper fa la media su cinque). |
| `--n_workers` | Dimensione del pool di utenti fittizi |
| `--budget` | Budget di interazione per utente `L`, espresso come frazione di. |
| `--out` | Percorso JSON di output per la traccia completa dell'episodio e le metriche di riepilogo. |
### Riprodurre ciascuna domanda di ricerca su un piccolo campione ML-100K```bash
bash bash/run_performance.sh # RQ1
bash bash/run_stealth_and_detect.sh # RQ2 + RQ3
bash bash/run_ablation.sh # RQ4
bash bash/run_efficiency.sh # RQ5
Ogni script stampa quale esperimento sta eseguendo, il percorso di output e una nota che rimanda alla figura/tabella corrispondente nel paper.
Esempio di output atteso sulla console (troncato):``` [RQ1] Performance benchmark — tiny ML-100K sample [RQ1] Output directory: agent_attack_rs/outputs/rq1_performance [RQ1] Map outputs to tables/benchmark_unpopular.tex === ml-latest-small / lightgcn / seed=42 === Round 0 | ρ = 1834 Δρ = +0 strategy = S1_VICTIM_PROBE Round 1 | ρ = 1450 Δρ = +384 strategy = S1_VICTIM_PROBE Round 2 | ρ = 1212 Δρ = +238 strategy = S3_WARM_UP … [RQ1] Done. Expected outputs in agent_attack_rs/outputs/rq1_performance
### Attacco di trasferimento contro LightGCN (in-loop)
Esegue LightGCN sia come modello dell'episodio sia come target di valutazione. La vittima
si riaddestra dopo ogni round, così il Coordinator riceve un feedback reale sul ranking e
adatta di conseguenza i ruoli e la strategia.```bash
agas run-transfer \
--dataset ml-latest-small \
--target-item-id 7114 \
--target-keyword horror \
--num-agents 50 \
--num-steps 10 \
--victim-model-hint lightgcn \
--profiler-bridge-method cooccurrence \
--probe-steps 0 \
--graph-sniper \
--clone-segment-users-to-agents \
--transfer-mode option-b \
--target-models lightgcn \
--target-epochs 50 \
--target-embedding-dim 32 \
--target-lightgcn-layers 3 \
--min-active-fraction 0.5 \
--min-sniper-fraction 0.3 \
--output outputs/optb_warmstart_clean_cooc_50ag_10r.json
| Flag | Significato |
|---|---|
--profiler-bridge-method cooccurrence | Elementi bridge selezionati per co-occorrenza con il cluster di rater del target. |
--graph-sniper | Gli sniper valutano gli elementi bridge e direttamente il target (azione duale). |
Dopo l'esecuzione, i risultati vengono stampati e salvati nel JSON di output:``` Bridge-item selection (cooccurrence): 50 items selected for profiler pool. ... Transfer evaluation saved to outputs/optb_warmstart_clean_cooc.json Option B (in-loop target models): lightgcn: final rank (best in-loop at step , best-seq retrain rank )
## 6. Registrazione dei token, attivazione dei ruoli e monitoraggio della strategia
Ogni chiamata a `run-episode` calcola e registra automaticamente tre tipi di analisi:
### 6a. Utilizzo dei token
I token vengono contati per ogni chiamata LLM e accumulati durante l'episodio per il
coordinatore e per ciascun agente worker separatamente. Vengono stampati sulla
console dopo l'episodio e salvati all'interno del JSON di output sotto
`token_usage`.
**Esempio di output della console:**```
--- Token Usage ---
Coordinator : prompt=20,043 completion=2,526 total=22,569
agent_1 : prompt=1,308 completion=619 total=1,927
agent_2 : prompt=3,930 completion=451 total=4,381
agent_3 : prompt=0 completion=0 total=0
AGGREGATE : prompt=25,281 completion=3,596 total=28,877
-------------------
Struttura JSON (output["token_usage"]):```json
{
"coordinator": {"prompt_tokens": 20043, "completion_tokens": 2526, "total_tokens": 22569},
"by_agent": {"agent_1": {"prompt_tokens": 1308, ...}, ...},
"aggregate": {"prompt_tokens": 25281, "completion_tokens": 3596, "total_tokens": 28877}
}
**Lettura dei conteggi dei token da un'esecuzione salvata:**```python
import json
with open("outputs/my_run.json") as f:
data = json.load(f)
agg = data["token_usage"]["aggregate"]
print(f"Total tokens used: {agg['total_tokens']:,}")
print(f" Prompt : {agg['prompt_tokens']:,}")
print(f" Completion : {agg['completion_tokens']:,}")
# Per-step token usage (inside each worker trace)
for step in data["history"]:
for report in step["reports"]:
tok = (report.get("trace") or {}).get("token_usage") or {}
print(f"Step {step['step']} {report['agent_id']}: {tok.get('total_tokens', 0)} tokens")
Note del provider:
| Provider | Campi letti |
|---|---|
| OpenAI Responses API | response.usage.input_tokens, .output_tokens |
Ollama /api/generate | data["prompt_eval_count"], data["eval_count"] |
Dopo ogni episodio, la CLI conta quante volte ciascun ruolo è stato assegnato
su tutti gli agenti e tutti i passi. Stampato sulla console e salvato in
output["activation_stats"]["role_counts"].
Esempio di output della console:```
--- Role Activations ---
inactive : 10
profiler : 4
--- Role Activations by Agent ---
agent_1 : inactive=3 profiler=1
agent_2 : profiler=3 inactive=2
agent_3 : inactive=5
**Lettura dei conteggi dei ruoli a livello di programmazione:**```python
stats = data["activation_stats"]
print("Most used role:", max(stats["role_counts"], key=stats["role_counts"].get))
print("Role counts:", stats["role_counts"])
print("By agent:", stats["role_counts_by_agent"])
Il pattern di assegnazione dei ruoli del coordinatore viene mappato a una delle otto strategie del paper (S1–S8) a ogni step utilizzando le seguenti regole di inferenza:
Salvato in output["activation_stats"]["strategy_counts"].
Esempio di output della console:``` --- Strategy Activations --- S1_VICTIM_PROBE : 1 S3_WARM_UP : 4
### 6d. Log leggibile per esecuzione
Un file `.log` viene scritto automaticamente accanto a ogni JSON di output
(ad es. `outputs/my_run.log`). Contiene:
- Metadati dell'episodio (dataset, target, numero di agenti, policy)
- Timeline per ogni step: rank, strategia, ruolo di ciascun agente, azioni e conteggio token per chiamata
- Riepilogo dell'utilizzo dei token
- Conteggi delle attivazioni di ruoli e strategie
**Esecuzione della CLI e lettura del log:**```bash
agas run-episode \
--dataset ml-latest-small \
--target-item-id 2571 \
--target-keyword "Matrix" \
--num-agents 3 \
--num-steps 10 \
--coordinator-policy openai \
--worker-policy openai \
--output outputs/run_matrix.json
# Human-readable log is at:
cat outputs/run_matrix.log
# JSON output is at:
python -c "
import json
d = json.load(open('outputs/run_matrix.json'))
print('Token aggregate:', d['token_usage']['aggregate'])
print('Role counts:', d['activation_stats']['role_counts'])
print('Strategy counts:',d['activation_stats']['strategy_counts'])
"
Il Coordinator e ogni worker sono agenti LLM che leggono da
prompts/<role>/{system,user}.txt. Il protocollo completo — cosa il
Coordinator interpola nel suo prompt, quali variabili vedono i worker,
e gli schemi JSON di output attesi — è in
prompts/README.md.
Breve riepilogo:
{"strategy": "S?_…", "assignments": {agent: ROLE}}.{"actions": [{"item_id": …, "rating": …, "reason": …}]}.Tutti i numeri seguenti sono media ± IC al 95 % su 5 seed, scalati di 10³
(cioè, una cella di 40.0±0.2 significa HR@10 = 0.0400 ± 0.0002). Grassetto = migliore,
corsivo = secondo migliore, in accordo con tables/benchmark_unpopular.tex e
tables/detection_mf.tex nel paper.
tables/benchmark_unpopular.tex)Riproduci con:```bash bash bash/run_performance.sh # RQ1; writes outputs/rq1_performance/
**Vittime basate su embedding** (cella = `H@10 / NDCG@10`):
| Metodo | ML-100K·MF(BPR) | ML-100K·NeuMF | ML-1M·GMF | ML-1M·NCF | Amazon·MF(BPR) | Amazon·NCF | Genome·GMF | Genome·NeuMF | Netflix·MF(BPR) | Netflix·NeuMF |
|---|---|---|---|---|---|---|---|---|---|---|
| NoneAttack | 1.8±0.2 / 0.7±0.5 | 2.2±0.2 / 0.9±0.6 | 0.9±0.1 / 0.4±0.3 | 0.8±0.1 / 0.3±0.2 | 0.4±0.1 / 0.1±0.2 | 0.5±0.1 / 0.2±0.2 | 0.2±0.1 / 0.1±0.2 | 0.5±0.1 / 0.2±0.2 | 0.6±0.1 / 0.2±0.2 | 0.7±0.1 / 0.3±0.2 |
| RandomAttack | 4.1±0.3 / 1.6±0.6 | 4.7±0.3 / 1.8±0.6 | 2.4±0.2 / 1.0±0.5 | 2.0±0.2 / 0.8±0.4 | 1.2±0.1 / 0.5±0.3 | 1.3±0.1 / 0.5±0.3 | 0.7±0.1 / 0.3±0.2 | 1.3±0.1 / 0.5±0.3 | 1.8±0.2 / 0.7±0.4 | 2.0±0.2 / 0.8±0.5 |
| BandwagonAttack | 6.2±0.3 / 2.5±0.7 | 6.8±0.3 / 2.7±0.8 | 3.4±0.2 / 1.4±0.6 | 2.9±0.2 / 1.2±0.5 | 2.0±0.1 / 0.8±0.4 | 2.2±0.1 / 0.9±0.4 | 1.2±0.1 / 0.5±0.3 | 2.0±0.1 / 0.8±0.4 | 2.7±0.2 / 1.1±0.5 | 3.0±0.2 / 1.2±0.5 |
| AUSH | 10.6±0.6 / 4.3±1.2 | 10.0±0.5 / 4.1±1.1 | 6.5±0.4 / 2.6±0.9 | 4.3±0.3 / 1.8±0.7 | 3.3±0.3 / 1.3±0.6 | 3.1±0.3 / 1.2±0.6 | 1.9±0.2 / 0.8±0.5 | 2.8±0.3 / 1.1±0.6 | 4.2±0.3 / 1.7±0.7 | 4.5±0.3 / 1.8±0.8 |
| PoisonRec | 13.4±0.7 / 5.3±1.6 | 11.5±0.6 / 4.7±1.5 | 7.6±0.5 / 3.0±1.1 | 5.5±0.4 / 2.1±0.9 | _5.8±0.5_ / _2.3±1.0_ | 4.8±0.3 / 1.9±0.8 | 2.3±0.3 / 0.9±0.6 | 3.2±0.3 / 1.3±0.7 | 5.6±0.4 / 2.2±1.0 | 5.7±0.4 / 2.3±1.0 |
| PGA | 11.5±0.6 / 4.6±1.3 | 12.2±0.6 / 5.0±1.4 | 8.4±0.5 / 3.4±1.1 | 6.0±0.4 / 2.4±0.9 | 4.3±0.3 / 1.7±0.8 | 4.0±0.3 / 1.6±0.7 | 2.8±0.2 / 1.1±0.6 | 3.8±0.3 / 1.5±0.7 | 5.5±0.4 / 2.2±1.0 | 6.0±0.5 / 2.4±1.0 |
| AgentSA | 12.7±0.6 / 5.2±1.4 | _12.5±0.6_ / _5.1±1.4_ | 8.2±0.4 / 3.3±1.0 | _7.2±0.4_ / _2.9±1.0_ | 5.6±0.3 / 2.2±0.9 | 4.9±0.3 / 1.9±0.8 | _2.9±0.2_ / _1.1±0.6_ | 4.2±0.3 / 1.7±0.7 | _6.3±0.4_ / _2.5±1.0_ | 6.5±0.4 / 2.6±1.0 |
| AgentAttack | _13.6±0.7_ / _5.5±1.5_ | 12.1±0.6 / 4.9±1.4 | _8.8±0.5_ / _3.5±1.1_ | 6.8±0.4 / 2.7±1.0 | 5.7±0.3 / 2.2±0.9 | _5.2±0.3_ / _2.0±0.9_ | 2.7±0.2 / 1.0±0.6 | _4.5±0.3_ / _1.8±0.8_ | 6.1±0.4 / 2.4±1.0 | _6.9±0.5_ / _2.8±1.0_ |
| **AGAS (Ours)** | **40.0±0.2 / 16.1±0.3** | **35.0±0.2 / 14.2±0.3** | **22.6±0.1 / 9.0±0.2** | **17.6±0.1 / 7.1±0.2** | **16.1±0.1 / 6.3±0.2** | **15.0±0.1 / 5.9±0.2** | **8.2±0.1 / 3.2±0.2** | **11.5±0.1 / 4.6±0.2** | **18.2±0.1 / 7.3±0.2** | **19.6±0.1 / 7.9±0.2** |
| **Improvement** | **+187.8% / +182.5%** | **+186.9% / +184.0%** | **+162.8% / +164.7%** | **+155.1% / +153.6%** | **+177.6% / +173.9%** | **+172.7% / +168.2%** | **+192.9% / +190.9%** | **+161.4% / +155.6%** | **+198.4% / +192.0%** | **+192.5% / +192.6%** |
**Vittime basate su grafo** (cella = `H@10 / NDCG@10`):
| Metodo | ML-100K·NGCF | ML-100K·LightGCN | ML-1M·SimGCL | ML-1M·XSimGCL | Amazon·EGCF | Amazon·LightCCF | Genome·NGCF | Genome·LightGCN | Douban·NGCF | Douban·LightGCN |
|---|---|---|---|---|---|---|---|---|---|---|
| NoneAttack | 1.9±0.2 / 0.8±0.5 | 2.4±0.2 / 1.0±0.6 | 0.8±0.1 / 0.3±0.2 | 0.9±0.1 / 0.4±0.3 | 0.4±0.1 / 0.2±0.2 | 0.5±0.1 / 0.2±0.2 | 0.2±0.1 / 0.1±0.2 | 0.3±0.1 / 0.1±0.2 | 0.7±0.1 / 0.3±0.2 | 0.6±0.1 / 0.2±0.2 |
| RandomAttack | 4.5±0.3 / 1.8±0.6 | 5.0±0.3 / 2.0±0.7 | 1.8±0.2 / 0.7±0.4 | 2.2±0.2 / 0.9±0.5 | 1.1±0.1 / 0.4±0.3 | 1.2±0.1 / 0.5±0.3 | 0.6±0.1 / 0.2±0.2 | 0.6±0.1 / 0.2±0.2 | 2.0±0.2 / 0.8±0.5 | 1.9±0.2 / 0.7±0.4 |
| BandwagonAttack | 5.9±0.3 / 2.4±0.7 | 6.7±0.3 / 2.7±0.8 | 2.4±0.2 / 1.0±0.5 | 2.9±0.2 / 1.2±0.6 | 1.8±0.2 / 0.7±0.4 | 1.9±0.2 / 0.8±0.4 | 1.1±0.1 / 0.4±0.3 | 1.0±0.1 / 0.4±0.3 | 2.8±0.2 / 1.1±0.6 | 2.7±0.2 / 1.1±0.5 |
| GSPAttack | 11.0±0.6 / 4.5±1.3 | 11.5±0.6 / 4.7±1.3 | 4.8±0.3 / 1.9±0.8 | 5.8±0.4 / 2.3±0.9 | 3.2±0.3 / 1.3±0.6 | 3.4±0.3 / 1.4±0.6 | 2.0±0.2 / 0.8±0.5 | 1.8±0.2 / 0.7±0.5 | 5.0±0.3 / 2.0±0.8 | 4.8±0.3 / 1.9±0.8 |
| TargetedAttack | 11.9±0.6 / 4.8±1.3 | 12.6±0.6 / 5.1±1.4 | 5.4±0.4 / 2.2±0.8 | 6.4±0.4 / 2.5±1.0 | 4.7±0.3 / 1.9±0.7 | 4.5±0.3 / 1.8±0.7 | 2.5±0.2 / 1.0±0.6 | 2.2±0.2 / 0.9±0.5 | 5.4±0.4 / 2.2±0.8 | 5.2±0.3 / 2.1±0.8 |
| CLeaR | 13.1±0.7 / 5.4±1.4 | 13.9±0.7 / 5.7±1.5 | 6.4±0.4 / 2.6±0.9 | 7.7±0.5 / 3.1±1.0 | 4.6±0.3 / 1.8±0.7 | 5.2±0.4 / 2.1±0.8 | 2.9±0.3 / 1.2±0.6 | 2.8±0.2 / 1.1±0.6 | 5.8±0.4 / 2.3±0.9 | 5.5±0.3 / 2.2±0.9 |
| AgentSA | 13.8±0.6 / 5.6±1.4 | _14.2±0.7_ / _5.8±1.5_ | 6.1±0.4 / 2.4±0.8 | _8.4±0.5_ / _3.3±1.0_ | 4.5±0.3 / 1.8±0.7 | _5.4±0.3_ / _2.2±0.8_ | 2.8±0.2 / 1.1±0.6 | _2.9±0.2_ / _1.1±0.6_ | 5.4±0.3 / 2.2±0.8 | _5.8±0.4_ / _2.3±0.9_ |
| AgentAttack | _14.4±0.7_ / _5.9±1.5_ | 14.0±0.7 / 5.6±1.5 | _6.6±0.4_ / _2.6±0.9_ | 8.0±0.5 / 3.1±1.0 | _4.9±0.3_ / _1.9±0.7_ | 5.0±0.3 / 2.0±0.8 | _3.1±0.3_ / _1.2±0.6_ | 2.5±0.2 / 1.0±0.5 | _6.0±0.4_ / _2.4±0.9_ | 5.5±0.3 / 2.2±0.9 |
| **AGAS (Ours)** | **40.0±0.2 / 17.0±0.3** | **40.5±0.2 / 16.5±0.3** | **16.8±0.1 / 6.7±0.2** | **20.7±0.1 / 8.2±0.2** | **13.1±0.1 / 5.2±0.2** | **13.8±0.1 / 5.4±0.2** | **8.9±0.1 / 3.4±0.2** | **7.8±0.1 / 3.1±0.2** | **17.0±0.1 / 6.8±0.2** | **16.9±0.1 / 6.7±0.2** |
| **Improvement** | **+181.7% / +193.1%** | **+189.3% / +194.6%** | **+162.5% / +157.7%** | **+155.6% / +156.2%** | **+178.7% / +173.7%** | **+165.4% / +157.1%** | **+196.7% / +183.3%** | **+178.6% / +181.8%** | **+193.1% / +195.7%** | **+196.5% / +191.3%** |
## 9. Licenza
Licenza MIT.
| Componente | Requisito | Testato con |
|---|
| Python | ≥ 3.10 | 3.13.5 |
| PyTorch | ≥ 2.1 (solo targets) | 2.11.0+cu128 |
| CUDA | opzionale | 12.8 |
| NumPy | ≥ 1.24 | 2.4.2 |
| Pandas | ≥ 2.0 | 3.0.1 |
| SciPy | ≥ 1.10 | 1.17.0 |
| scikit-learn | ≥ 1.3 | 1.8.0 |
| openai SDK | ≥ 1.12 | 2.21.0 |
| Fase | Dati utilizzati | Dettagli |
|---|
| Addestramento | Tutte le interazioni in interactions.csv | Il surrogato (e qualsiasi modello target) viene addestrato sull'insieme completo delle valutazioni storiche. |
| Valutazione dell'attacco | Ranking sugli utenti del segmento | Dopo ogni round, il rank medio dell'item target viene misurato su utenti benigni reali che hanno valutato ≥ 4.0 almeno un item del cluster target (fino a 2 000 utenti). Nessun test set held-out viene scritto su disco. |
| Iniezione fake | Aggiunte in memoria | Le interazioni degli utenti fake vengono aggiunte e il modello viene riaddestrato incrementalmente a ogni round. Non vengono mai mescolate nei file CSV canonici. |
| Condizione | Strategia inferita |
|---|
| Fase di probe / agente diagnostico attivo | S1_VICTIM_PROBE |
Flag di allerta impostato (a_t = 1) | S7_SAFE_REPLACEMENT |
| Punteggio massimo di sospetto ≥ 0.5 | S6_PROFILE_CLEANUP |
| Nessun sniper + discounting visibile | S5_SILENT_SLOWDOWN |
| Nessun sniper + nessun discounting | S3_WARM_UP |
| Sniper attivi | S4_FIRST_PUSH |
| Sniper attivi | S8_MAIN_ATTACK |