
Framework de ataque de promoción grupal agéntico impulsado por LLM que manipula las clasificaciones de recomendadores de filtrado colaborativo de caja negra utilizando estrategias adaptativas de múltiples roles mientras evade la detección.
Este es el código oficial del artículo: "An Efficient and Effective Agentic Group Shilling Attack on Recommender Systems". Este artículo presenta AGAS, que es un ataque de shilling impulsado por LLM contra recomendadores de filtrado colaborativo de caja negra. Un Coordinador orquesta un grupo de trabajadores usuarios falsos a lo largo de una secuencia de rondas. En cada ronda, el Coordinador elige una de ocho estrategias y asigna un rol a cada trabajador. Los trabajadores entonces deciden qué ítems calificar usando su propio bucle de razonamiento estilo 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. Resumen del método
AGAS instancia cuatro roles de trabajador (símbolos de artículo en `roles.py`):
| Símbolo | Nombre completo | Qué hace |
|--------|----------------|-------------------------------------------------------------------------|
| `PR` | Profiler | Valoraciones seguras de ítems de relleno para sondear la plataforma y construir grupos puente. |
| `SN` | Sniper | Rol de carga útil; empuje directo al objetivo o promoción de ítem puente. |
| `CA` | Camouflageur | Rol de sigilo; reconstruye la confianza con actividad de apariencia benigna. |
| `IN` | Inactive | Sin acción esta ronda (enfriamiento o cuarentena). |
Cada ronda el Coordinador elige exactamente una de ocho estrategias de
`strategies.py` (ver `method_strategies.tex`):
1. **Victim Probe** (`S1_VICTIM_PROBE`)
2. **Bridge Building** (`S2_BRIDGE_BUILDING`, solo víctimas de 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`)
El Coordinador impulsa esas decisiones a partir de dos grupos de señales (`signals.py`):
* **Señales de trabajador** `τ_{t,w}, γ_{t,w}, φ_{t,w}` — confianza, riesgo y un
validador estructural. Las ecuaciones de actualización coinciden exactamente con `method_coordinator.tex`
(`eq:trust_update`, `eq:risk_update`, `eq:risk_decay`,
`eq:profile_validator`).
* **Señales de entorno** `ρ^{(t)}, Δρ^{(t)}, η_t, ξ_t = (q_t, s_t), a_t` —
rango, movimiento de rango, tasa de aceptación, señal de supresión, indicador de alerta. La
puntuación de sospecha `q_t` es la suma ponderada por 0.2 de los cinco términos
normalizados `(d̂_t, δ̂_t, m̂_t, ŝ_t, g_t)` de `eq:round_suppression_terms` y
`eq:round_suppression_score`.
### Bucle de ronda (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*)}]
El bucle externo está implementado en src/agas/simulation/episode.py y refleja
algorithms/agas_end_to_end.tex.
| Componente | Requisito | Probado con |
|---|---|---|
| Python | ≥ 3.10 | 3.13.5 |
| PyTorch | ≥ 2.1 (solo targets) | 2.11.0+cu128 |
| CUDA | opcional | 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 |
PyTorch y CUDA solo son necesarios para los modelos víctima de aprendizaje profundo (extra [targets]). El bucle central de AGAS y las rutas basadas en reglas / sustitutas se ejecutan en CPU sin dependencia de GPU.
pip install -e .
pip install -e '.[targets]'
Variables de entorno requeridas:
| Variable | Propósito | Predeterminado |
|--------------------|---------------------------------------------------------------|--------------------------|
| `OPENAI_API_KEY` | Clave de la API de OpenAI Responses para el Coordinador / LLMs trabajadores. | *(sin establecer → respaldo)* |
| `OPENAI_MODEL` | Nombre del modelo pasado a OpenAI. | `gpt-5.1` |
## 4. Conjuntos de datos
El artículo evalúa en seis benchmarks públicos de CF (ver `experiment.tex`):
| Nombre corto | Fuente | Usuarios | Ítems | Interacciones | Descarga | Colocar archivos sin procesar en |
|-------------|---------------------------|----------:|-------:|-------------------:|-------------------------------------------------------------------|---------------------|
| 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 (limitado) | [GroupLens](https://grouplens.org/datasets/movielens/tag-genome-2021/) | `data/genome2021/` |
| Netflix | Netflix Prize | 342,445 | 17,434 | 2,000,000 (limitado) | [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 (limitado) | [UCSD](https://nijianmo.github.io/amazon/index.html) | `data/amazon/` |