edangx100 commited on
Commit
7efdd64
Β·
verified Β·
1 Parent(s): 34c6d48

Redeploy: sync repo updates (exclude RLM docs)

Browse files
Files changed (2) hide show
  1. README.md +23 -23
  2. explorer/prompts.py +26 -16
README.md CHANGED
@@ -12,40 +12,43 @@ pinned: false
12
 
13
  # AI Incident Explorer
14
 
15
- > An autonomous agentic tool that continuously mines the [AI Incident Database (AIID)](https://incidentdatabase.ai) to surface, classify, and triage real-world AI failures and attacks β€” mapping each one to **MITRE ATLAS** adversarial-ML techniques via an **LLM-as-a-Judge** classifier, with **full agent observability**.
16
-
17
- ### πŸ”— Live demo β†’ **[AI Incident Explorer on Hugging Face Spaces](https://huggingface.co/spaces/edangx100/aiid-explorer)**
18
-
19
- > ⏱️ **It's a slow agentic search, not an instant lookup** β€” a round can take **up to ~9 min** on
20
- > the free Basic-CPU Space ([why](#why-the-search-takes-minutes-not-seconds)). Leave the tab open.
21
 
22
  ---
23
 
24
  ## Why This Project Exists
25
 
26
- **Agents that run over a long horizon predictably hit two failure modes:** **context rot** (their context fills with stale tool output until they forget the goal and degrade) and **query narrowing** (they tunnel on a few lines of inquiry and go blind to the rest of the problem space).
27
 
28
  **This project is a demonstration of how both can be addressed β€” context rot with a [Recursive Language Model (RLM)](https://arxiv.org/html/2512.24601v3) architecture, and query narrowing with [LDA](https://www.ibm.com/think/topics/topic-modeling)-based topic steering** β€” using **AI Incident Explorer** as the use case.
29
 
30
- > **What's an RLM?** A *Recursive Language Model* keeps the agent's working state in a sandboxed Python REPL instead of stuffing every tool result back into the prompt. The model writes and runs code to inspect, filter, and summarize its own data, so the context window stays small and clean no matter how many rounds it runs. See [RLM paper](https://arxiv.org/html/2512.24601v3)
31
 
32
  > **What's LDA topic steering?** *Latent Dirichlet Allocation* is a [topic-modeling](https://www.ibm.com/think/topics/topic-modeling) technique that discovers the recurring themes hidden in a set of documents. Here it runs over the agent's *own past search queries* to reveal which themes it keeps circling β€” so the next round can be steered toward the topics it hasn't explored yet.
33
 
34
  | Problem | Symptom | How this project solves it |
35
  |---|---|---|
36
- | **Context rot** | Over many search rounds the agent's context fills with stale tool output and it forgets its goal, repeats work, and degrades. | The agent keeps its working notes in a separate scratchpad (a Python workspace) instead of letting them pile up in its memory. Each round it pulls back only a short summary of what it's found so far, so its attention stays focused. |
37
- | **Query narrowing** | Left alone, the agent re-issues near-identical searches and tunnels on one or two ATLAS techniques, leaving the rest of the threat surface blind. | The app spots when the agent keeps searching the same themes, then points it toward the threat types and industries it hasn't looked at yet β€” so it covers the wider landscape instead of circling a few corners. |
 
 
38
 
39
- As a use case, AI Incident Explorer answers questions like β€” *"What MITRE ATLAS techniques are being used against LLMs in finance/healthcare/consumer products right now?"* β€” by autonomously searching the public record of AI incidents over many rounds and returning a structured, technique-tagged, severity-rated result set.
40
 
41
- Under the hood it is an **RLM agent**: an outer agent writes and runs Python in a sandboxed REPL to search and triage β€” keeping state in the REPL rather than the prompt (the context-rot fix) β€” while an inner **LLM-as-a-Judge** agent classifies each incident against the MITRE ATLAS taxonomy. After seeding rounds, an **LDA** model clusters the agent's own past searches and steers it toward unexplored techniques (the query-narrowing fix).
 
 
 
42
 
43
  ---
44
 
45
  ## What AI Incident Explorer does
46
 
47
- - **Autonomous, multi-round search** β€” give it one natural-language query; it runs up to *N* search/triage rounds on its own. One search only scratches the surface: the incidents are scattered under many different wordings, so a single query misses most of them. Each round lets the agent learn from what it just found and follow up with sharper, broader searches β€” building a fuller picture than any one-shot lookup could.
48
- - **MITRE ATLAS classification** β€” every relevant incident is tagged with one or more adversarial-ML technique IDs (e.g. `AML.T0051` LLM Prompt Injection, `AML.T0043` deepfakes, `AML.T0047` model evasion).
 
 
 
49
  - **LLM-as-a-Judge triage** β€” an inner agent decides *security attack vs. safety failure vs. reliability issue* and assigns a harm-severity rating.
50
 
51
  Everything it finds shows up in a sortable table. Click any incident's **title** to open its full write-up on the AI Incident Database, and use the type and severity filters to focus on just the cases you care about.
@@ -56,28 +59,26 @@ Everything it finds shows up in a sortable table. Click any incident's **title**
56
 
57
  ![System architecture](images/architecture.png)
58
 
59
- *Core context-rot mitigation β€” the outer agent orchestrates; the inner agent judges. State lives in the REPL, not the prompt.*
60
 
61
  ---
62
 
63
  ## Implementation Notes
64
 
65
- - **RLM / Code-Mode agent.** Instead of cramming hundreds of incidents into one context window, the outer agent writes Python that searches and triages in a persistent sandboxed REPL powered by [Pydantic AI Harness **CodeMode**](https://github.com/pydantic/pydantic-ai-harness/tree/main/pydantic_ai_harness/code_mode). The agent is prompted with Recursive Language Model strategies β€” *PEEK* (glance at a few examples before diving in), *GREP* (skim for the relevant ones instead of reading everything), *PARTITION+MAP* (break a big pile into smaller batches and work through them), and *SUMMARIZE* (boil long text down to the key point).
66
 
67
  ![Recursive Language Model strategies β€” PEEK, GREP, PARTITION+MAP, SUMMARIZE](images/RLM_strategy.png)
68
 
69
  *The RLM strategies the outer agent uses to inspect and shrink data inside the REPL β€” keeping only what matters in context. Diagram source: [Daily Dose of Data Science β€” Recursive Language Models](https://blog.dailydoseofds.com/p/recursive-language-models).*
70
 
71
- - **LLM-as-a-Judge classifier.** A second inner LLM agent acts as a reviewer that the app can call on for each incident. For every case it reads, it hands back the relevant ATLAS technique IDs and a triage category (how the incident should be sorted). This reviewer is set up separately from the main app, so you can drop in a cheaper or faster model for the job without changing anything else.
72
  - **LDA topic steering.** Once a few rounds have run, the app looks back at the agent's own past search terms and groups them into recurring themes (using gensim's LDA topic modeling). Seeing which themes the agent keeps circling, it then nudges the next search toward the areas it hasn't explored yet β€” so coverage keeps widening instead of tunneling on the same few topics.
73
 
74
- ![LDA topic steering widens coverage by nudging the agent toward unexplored themes](images/widen_coverage.png)
75
-
76
  ---
77
 
78
  ## What the User Sees
79
 
80
- With all of those pieces working together, here's what it looks like to the user in the Gradio interface β€” note the MITRE ATLAS classifications shown along the bottom of the table:
81
 
82
  ![ATLAS-tagged results with type + severity filters applied](images/atlas-filters.png)
83
 
@@ -105,12 +106,11 @@ With all of those pieces working together, here's what it looks like to the user
105
 
106
  **β–Ά [Open the live demo](https://huggingface.co/spaces/edangx100/aiid-explorer)**
107
 
108
- 1. Type a short keyword in **Query** (one or two words works best).
109
- 2. Click **Search** and **leave the tab open** β€” a round can take **up to ~9 minutes** on the free
110
  Basic-CPU Space. The status banner shows live progress and a time estimate.
111
  3. Use the **type** and **severity** filters to slice the results once they arrive.
112
 
113
- > If the backend is unavailable the app falls back to bundled demo data so the table is never blank.
114
 
115
  #### Why the search takes minutes, not seconds
116
 
 
12
 
13
  # AI Incident Explorer
14
 
15
+ > An autonomous agentic tool that mines the [AI Incident Database (AIID)](https://incidentdatabase.ai) to surface, classify, and triage real-world AI failures and attacks β€” mapping each one to **MITRE ATLAS** adversarial-ML techniques via an **LLM-as-a-Judge** classifier, with **agent observability**.
 
 
 
 
 
16
 
17
  ---
18
 
19
  ## Why This Project Exists
20
 
21
+ **Agents operating over long horizons can degrade in two predictable ways**: Long‑horizon agents can experience **context rot**, and those engaged in long agentic search may additionally drift into **query narrowing** .
22
 
23
  **This project is a demonstration of how both can be addressed β€” context rot with a [Recursive Language Model (RLM)](https://arxiv.org/html/2512.24601v3) architecture, and query narrowing with [LDA](https://www.ibm.com/think/topics/topic-modeling)-based topic steering** β€” using **AI Incident Explorer** as the use case.
24
 
25
+ > **What's an RLM?** A *Recursive Language Model* runs an LLM in a loop where each round's output is fed back as input to the next round. The model writes and runs Python code to search, filter, and classify data; at the end of each round it prints a structured `historical_results` block that the loop re-injects into the next round's prompt β€” so the agent accumulates memory across rounds without stuffing every raw tool result into context. See [RLM paper](https://arxiv.org/html/2512.24601v3)
26
 
27
  > **What's LDA topic steering?** *Latent Dirichlet Allocation* is a [topic-modeling](https://www.ibm.com/think/topics/topic-modeling) technique that discovers the recurring themes hidden in a set of documents. Here it runs over the agent's *own past search queries* to reveal which themes it keeps circling β€” so the next round can be steered toward the topics it hasn't explored yet.
28
 
29
  | Problem | Symptom | How this project solves it |
30
  |---|---|---|
31
+ | **Context rot** | Over many search rounds the agent's context fills with stale tool output and it forgets its goal, repeats work, and degrades. | RLM keeps the context lean by having the agent write Python code that searches, filters, and classifies inside a sandboxed REPL β€” so raw tool output never lands in the prompt. At the end of each round the agent prints only a compact `historical_results` summary, which the loop re-injects into the next round's prompt as the agent's memory. The REPL itself is stateless across rounds; state lives in that re-injected summary, not in the interpreter. |
32
+ | **Query narrowing** | Left alone, the agent re-issues near-identical searches and tunnels on one or two recurring themes, leaving the rest of the threat surface blind. | The app spots when the agent keeps searching the same themes, then points it toward the threat types and industries it hasn't looked at yet β€” so it covers the wider landscape instead of circling a few corners. |
33
+
34
+ ![LDA topic steering widens coverage by nudging the agent toward unexplored themes](images/widen_coverage.png)
35
 
36
+ As a use case, AI Incident Explorer answers questions like β€” *β€œWhat MITRE ATLAS techniques are being used against LLMs in finance, healthcare, or consumer products right now?”* β€” by taking a user query as the starting point, searching [AI Incident Database (AIID)](https://incidentdatabase.ai), and returning a structured result set tagged by technique and severity.
37
 
38
+ Under the hood of AI Incident Explorer:
39
+ - an outer agent writes and runs Python in a sandboxed REPL to search and triage β€” at the end of each round it prints a compact `historical_results` summary that the loop re-injects into the next round's prompt, keeping context lean rather than accumulating raw tool output (the context-rot fix)
40
+ - while an inner **LLM-as-a-Judge** agent classifies each incident against the MITRE ATLAS taxonomy.
41
+ - After the initial seeding rounds, an **LDA** model within the search-loop orchestrator clusters the agent’s previous searches and steers it toward unexplored techniques to improve query narrowing.
42
 
43
  ---
44
 
45
  ## What AI Incident Explorer does
46
 
47
+ - **Autonomous, multi-round search** β€” give it one natural-language query; it runs up to *N* search/triage rounds on its own. One search scratches the surface: the incidents are scattered under many different wordings, so a single query misses most of them. Each round lets the agent learn from what it just found and avoid re-treading it; once topic steering kicks in (round 5 by default), the loop actively steers searches toward themes it hasn't explored yet β€” building a fuller picture than any one-shot lookup could.
48
+
49
+ > **Example.** You type *"prompt injection in healthcare"*. The agent doesn't search that whole phrase β€” the database looks for keywords inside incident text, so it splits your words into short searches like `prompt injection`, `healthcare`. The first few rounds stay close to your words and remember what they've already found. Then the agent notices it keeps searching the same two ideas, so it tries new ones it hasn't looked at yet β€” a different kind of attack (like `data leakage`) or a related area (like `medical imaging` or `pharmacy`). This way it covers far more ground than searching once.
50
+
51
+ - **MITRE ATLAS classification** β€” every relevant incident is tagged with one or more ATLAS technique IDs (e.g. `AML.T0051` LLM Prompt Injection, `AML.T0054` LLM Jailbreak, `AML.T0015` Evade AI Model).
52
  - **LLM-as-a-Judge triage** β€” an inner agent decides *security attack vs. safety failure vs. reliability issue* and assigns a harm-severity rating.
53
 
54
  Everything it finds shows up in a sortable table. Click any incident's **title** to open its full write-up on the AI Incident Database, and use the type and severity filters to focus on just the cases you care about.
 
59
 
60
  ![System architecture](images/architecture.png)
61
 
62
+ *Core context-rot mitigation β€” the outer agent orchestrates; the inner agent judges. State carries across rounds via re-injected `historical_results`, not REPL persistence (the REPL resets each round).*
63
 
64
  ---
65
 
66
  ## Implementation Notes
67
 
68
+ - **RLM / Code-Mode agent.** Instead of cramming hundreds of incidents into one context window, the outer agent writes Python that searches and triages in a sandboxed REPL powered by [Pydantic AI Harness **CodeMode**](https://github.com/pydantic/pydantic-ai-harness/tree/main/pydantic_ai_harness/code_mode). The agent is prompted with Recursive Language Model strategies β€” *PEEK* (glance at a few examples before diving in), *GREP* (skim for the relevant ones instead of reading everything), *PARTITION+MAP* (break a big pile into smaller batches and work through them), and *SUMMARIZE* (boil long text down to the key point).
69
 
70
  ![Recursive Language Model strategies β€” PEEK, GREP, PARTITION+MAP, SUMMARIZE](images/RLM_strategy.png)
71
 
72
  *The RLM strategies the outer agent uses to inspect and shrink data inside the REPL β€” keeping only what matters in context. Diagram source: [Daily Dose of Data Science β€” Recursive Language Models](https://blog.dailydoseofds.com/p/recursive-language-models).*
73
 
74
+ - **LLM-as-a-Judge classifier.** A second inner LLM agent acts as a reviewer that the app can call on for each incident. For every case it reads, it hands back the relevant ATLAS technique IDs and a triage category (how the incident should be sorted). This reviewer is set up separately from the main app, so you can use a cheaper or faster model for the job.
75
  - **LDA topic steering.** Once a few rounds have run, the app looks back at the agent's own past search terms and groups them into recurring themes (using gensim's LDA topic modeling). Seeing which themes the agent keeps circling, it then nudges the next search toward the areas it hasn't explored yet β€” so coverage keeps widening instead of tunneling on the same few topics.
76
 
 
 
77
  ---
78
 
79
  ## What the User Sees
80
 
81
+ With all of those pieces working together, here's what it looks like to the user in the Gradio interface β€” note the MITRE ATLAS classifications shown along the bottom of the table (within red-dotted box):
82
 
83
  ![ATLAS-tagged results with type + severity filters applied](images/atlas-filters.png)
84
 
 
106
 
107
  **β–Ά [Open the live demo](https://huggingface.co/spaces/edangx100/aiid-explorer)**
108
 
109
+ 1. Type a short keyword in **Query**.
110
+ 2. Click **Search** and **leave the tab open** β€” a round can take **up to ~9 minutes** on the HuggingFace
111
  Basic-CPU Space. The status banner shows live progress and a time estimate.
112
  3. Use the **type** and **severity** filters to slice the results once they arrive.
113
 
 
114
 
115
  #### Why the search takes minutes, not seconds
116
 
explorer/prompts.py CHANGED
@@ -5,7 +5,7 @@
5
  #
6
  # Two guidance sections in the prompt below were added to fix a real "0 results" failure
7
  # we observed (e.g. searching "healthcare" returned nothing). They are plain English aimed
8
- # at steering the model, not Python logic β€” a beginner can read them like instructions:
9
  # 1. "Search query format" β€” aiid_search() matches the query as a REGEX against incident
10
  # title/description, so a multi-word phrase like "healthcare AI incidents" matches
11
  # almost nothing. The section tells the agent to search with SHORT keywords (and to
@@ -22,10 +22,26 @@ HISTORICAL_RESULTS_START: str = "HISTORICAL_RESULTS_START"
22
  HISTORICAL_RESULTS_END: str = "HISTORICAL_RESULTS_END"
23
 
24
  INNER_AGENT_SYSTEM_PROMPT: str = (
25
- "You are a concise MITRE ATLAS adversarial-ML technique classifier. "
26
- "When asked to classify an AI incident, identify the most relevant ATLAS "
27
- "technique ID(s) in the format AML.TXXXX and explain briefly. "
28
- "Answer in one to three sentences."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  )
30
 
31
  OUTER_AGENT_SYSTEM_PROMPT: str = f"""You are an autonomous AI security research agent that mines the AI Incident Database (AIID) for real-world AI failures and attacks.
@@ -86,26 +102,20 @@ AIID Search: <next search query>
86
  - **The `<technique_id>` MUST be a real MITRE ATLAS ID in the form `AML.TXXXX`** (e.g. `AML.T0051`), determined by classifying the incident with `llm_query`. **NEVER** write `TBD`, `none`, `N/A`, `unknown`, or the search keyword in place of the ID β€” a starred line whose technique is not a real `AML.TXXXX` is invalid. If you cannot map an incident to a real ATLAS technique, mark it `-- not relevant` rather than starring it with a placeholder.
87
  - To keep IDs valid even under your tight code-block budget, you may map an obvious incident directly to one of the common techniques listed below; use `llm_query` whenever you are unsure or for less-obvious cases.
88
  - The `⭐` prefix is the only signal the harness uses to detect forward progress. Every new incident you classify as relevant **must** have a star or it will not be counted.
 
89
 
90
  ### Common MITRE ATLAS techniques (use the real ID β€” never a placeholder)
91
  - `AML.T0051` LLM Prompt Injection
92
  - `AML.T0054` LLM Jailbreak
93
  - `AML.T0057` LLM Data Leakage
94
  - `AML.T0043` Craft Adversarial Data
95
- - `AML.T0040` ML Model Inference API Access
96
- - `AML.T0024` Exfiltration via ML Inference API
97
  - `AML.T0020` Poison Training Data
98
- - `AML.T0031` Erode ML Model Integrity
99
  - `AML.T0048` External Harms
100
- - `AML.T0046` Spamming ML System with Chaff Data
101
- - `found_with` is implicitly the `AIID Search:` query on the line immediately preceding the result block β€” do not repeat it on the starred line itself.
102
-
103
- ### Incident type values (use exactly)
104
- - `security_attack` β€” adversarial input, prompt injection, model theft, data poisoning, etc.
105
- - `safety_failure` β€” unintended harmful output, alignment failure, value misalignment
106
- - `reliability_issue` β€” system crash, availability failure, accuracy degradation
107
 
108
- ### Severity values (use exactly): `critical`, `high`, `medium`, `low`
109
 
110
  ## Emergent Strategies
111
 
 
5
  #
6
  # Two guidance sections in the prompt below were added to fix a real "0 results" failure
7
  # we observed (e.g. searching "healthcare" returned nothing). They are plain English aimed
8
+ # at steering the model, not Python logic:
9
  # 1. "Search query format" β€” aiid_search() matches the query as a REGEX against incident
10
  # title/description, so a multi-word phrase like "healthcare AI incidents" matches
11
  # almost nothing. The section tells the agent to search with SHORT keywords (and to
 
22
  HISTORICAL_RESULTS_END: str = "HISTORICAL_RESULTS_END"
23
 
24
  INNER_AGENT_SYSTEM_PROMPT: str = (
25
+ "You are a concise AI incident classifier. Given an AI incident, you perform two jobs:\n\n"
26
+ "1. **MITRE ATLAS technique** β€” identify the most relevant technique ID(s) in the form AML.TXXXX.\n"
27
+ "2. **Triage** β€” classify the incident type and assign a harm-severity rating.\n\n"
28
+ "Answer in one to three sentences. Be direct; skip preamble.\n\n"
29
+ "### Common MITRE ATLAS techniques (use the real ID β€” never a placeholder)\n"
30
+ "- `AML.T0051` LLM Prompt Injection\n"
31
+ "- `AML.T0054` LLM Jailbreak\n"
32
+ "- `AML.T0057` LLM Data Leakage\n"
33
+ "- `AML.T0043` Craft Adversarial Data\n"
34
+ "- `AML.T0040` AI Model Inference API Access\n"
35
+ "- `AML.T0024` Exfiltration via AI Inference API\n"
36
+ "- `AML.T0020` Poison Training Data\n"
37
+ "- `AML.T0031` Erode AI Model Integrity\n"
38
+ "- `AML.T0048` External Harms\n"
39
+ "- `AML.T0046` Spamming AI System with Chaff Data\n\n"
40
+ "### Incident type (use exactly one)\n"
41
+ "- `security_attack` β€” adversarial input, prompt injection, model theft, data poisoning, etc.\n"
42
+ "- `safety_failure` β€” unintended harmful output, alignment failure, value misalignment\n"
43
+ "- `reliability_issue` β€” system crash, availability failure, accuracy degradation\n\n"
44
+ "### Severity (use exactly one): `critical`, `high`, `medium`, `low`\n"
45
  )
46
 
47
  OUTER_AGENT_SYSTEM_PROMPT: str = f"""You are an autonomous AI security research agent that mines the AI Incident Database (AIID) for real-world AI failures and attacks.
 
102
  - **The `<technique_id>` MUST be a real MITRE ATLAS ID in the form `AML.TXXXX`** (e.g. `AML.T0051`), determined by classifying the incident with `llm_query`. **NEVER** write `TBD`, `none`, `N/A`, `unknown`, or the search keyword in place of the ID β€” a starred line whose technique is not a real `AML.TXXXX` is invalid. If you cannot map an incident to a real ATLAS technique, mark it `-- not relevant` rather than starring it with a placeholder.
103
  - To keep IDs valid even under your tight code-block budget, you may map an obvious incident directly to one of the common techniques listed below; use `llm_query` whenever you are unsure or for less-obvious cases.
104
  - The `⭐` prefix is the only signal the harness uses to detect forward progress. Every new incident you classify as relevant **must** have a star or it will not be counted.
105
+ - `found_with` is implicitly the `AIID Search:` query on the line immediately preceding the result block β€” do not repeat it on the starred line itself.
106
 
107
  ### Common MITRE ATLAS techniques (use the real ID β€” never a placeholder)
108
  - `AML.T0051` LLM Prompt Injection
109
  - `AML.T0054` LLM Jailbreak
110
  - `AML.T0057` LLM Data Leakage
111
  - `AML.T0043` Craft Adversarial Data
112
+ - `AML.T0040` AI Model Inference API Access
113
+ - `AML.T0024` Exfiltration via AI Inference API
114
  - `AML.T0020` Poison Training Data
115
+ - `AML.T0031` Erode AI Model Integrity
116
  - `AML.T0048` External Harms
117
+ - `AML.T0046` Spamming AI System with Chaff Data
 
 
 
 
 
 
118
 
 
119
 
120
  ## Emergent Strategies
121