Spaces:
Running
Running
Commit
·
9c64352
1
Parent(s):
c13609c
Link to WML + UI improvements
Browse files- .gitignore +4 -1
- README.md +2 -2
- app.py +11 -21
- executor.py +41 -49
- requirements.txt +3 -2
- static/text/header.md +1 -1
- static/text/sec1.md +1 -1
.gitignore
CHANGED
@@ -1 +1,4 @@
|
|
1 |
-
.DS_Store
|
|
|
|
|
|
|
|
1 |
+
.DS_Store
|
2 |
+
.env
|
3 |
+
scratch.py
|
4 |
+
__pycache__
|
README.md
CHANGED
@@ -1,10 +1,10 @@
|
|
1 |
---
|
2 |
title: Risk Atlas Nexus
|
3 |
-
emoji:
|
4 |
colorFrom: purple
|
5 |
colorTo: green
|
6 |
sdk: gradio
|
7 |
-
sdk_version: 5.
|
8 |
app_file: app.py
|
9 |
pinned: false
|
10 |
license: apache-2.0
|
|
|
1 |
---
|
2 |
title: Risk Atlas Nexus
|
3 |
+
emoji: 🛡️
|
4 |
colorFrom: purple
|
5 |
colorTo: green
|
6 |
sdk: gradio
|
7 |
+
sdk_version: 5.18.0
|
8 |
app_file: app.py
|
9 |
pinned: false
|
10 |
license: apache-2.0
|
app.py
CHANGED
@@ -30,7 +30,7 @@ class UI:
|
|
30 |
with gr.Row():
|
31 |
gr.Markdown(content)
|
32 |
|
33 |
-
with gr.Row(
|
34 |
with gr.Column(variant="compact", scale=1):
|
35 |
self.usecase = gr.TextArea(
|
36 |
label="Intent",
|
@@ -60,34 +60,24 @@ class UI:
|
|
60 |
)
|
61 |
self.risk_execute = gr.Button("Submit")
|
62 |
|
63 |
-
with gr.Column(
|
64 |
|
65 |
-
gr.Markdown(
|
66 |
-
|
67 |
-
)
|
68 |
-
self.assessed_risks = gr.Dataset(label=None)
|
69 |
-
# gr.DataFrame(
|
70 |
-
# headers=["name", "description", "concern"],
|
71 |
-
# datatype=["str", "str", "str"],
|
72 |
-
# label="Risks",
|
73 |
-
# visible=True,
|
74 |
-
# wrap=True,
|
75 |
-
# show_copy_button=True,
|
76 |
-
# show_search="filter",
|
77 |
-
# type='pandas')
|
78 |
|
79 |
gr.Markdown(
|
80 |
-
"""<h2
|
81 |
Select a potential risk above to check for related risks.
|
82 |
"""
|
83 |
)
|
84 |
-
|
|
|
85 |
|
86 |
gr.Markdown(
|
87 |
-
"""<h2
|
88 |
Select a potential risk to determine possible mitigations. """
|
89 |
)
|
90 |
-
self.mitigations = gr.
|
91 |
|
92 |
gr.Markdown("---")
|
93 |
gr.Markdown("<br>")
|
@@ -100,7 +90,7 @@ class UI:
|
|
100 |
def layout(self):
|
101 |
"""Assemble the overall layout"""
|
102 |
|
103 |
-
with gr.Blocks(theme=gr.themes.Default()) as demo:
|
104 |
|
105 |
self.header_block()
|
106 |
self.risks = gr.State()
|
@@ -116,7 +106,7 @@ class UI:
|
|
116 |
self.model_name_or_path,
|
117 |
self.taxonomy
|
118 |
],
|
119 |
-
outputs=[self.risks, self.assessed_risks],
|
120 |
api_name="risk_identifier"
|
121 |
)
|
122 |
self.assessed_risks.select(
|
|
|
30 |
with gr.Row():
|
31 |
gr.Markdown(content)
|
32 |
|
33 |
+
with gr.Row():
|
34 |
with gr.Column(variant="compact", scale=1):
|
35 |
self.usecase = gr.TextArea(
|
36 |
label="Intent",
|
|
|
60 |
)
|
61 |
self.risk_execute = gr.Button("Submit")
|
62 |
|
63 |
+
with gr.Column(scale=2):
|
64 |
|
65 |
+
self.assessment_sec = gr.Markdown()
|
66 |
+
self.assessed_risks = gr.Dataset(label=None, visible=False)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
67 |
|
68 |
gr.Markdown(
|
69 |
+
"""<h2> Related Risks </h2>
|
70 |
Select a potential risk above to check for related risks.
|
71 |
"""
|
72 |
)
|
73 |
+
rrtb = gr.Markdown()
|
74 |
+
self.relatedrisks = gr.Dataset(components=[rrtb], label=None, visible=False)
|
75 |
|
76 |
gr.Markdown(
|
77 |
+
"""<h2> Mitigations </h2>
|
78 |
Select a potential risk to determine possible mitigations. """
|
79 |
)
|
80 |
+
self.mitigations = gr.DataFrame(label=None, visible=False)
|
81 |
|
82 |
gr.Markdown("---")
|
83 |
gr.Markdown("<br>")
|
|
|
90 |
def layout(self):
|
91 |
"""Assemble the overall layout"""
|
92 |
|
93 |
+
with gr.Blocks(theme=gr.themes.Default()) as demo: # type: ignore
|
94 |
|
95 |
self.header_block()
|
96 |
self.risks = gr.State()
|
|
|
106 |
self.model_name_or_path,
|
107 |
self.taxonomy
|
108 |
],
|
109 |
+
outputs=[self.assessment_sec, self.risks, self.assessed_risks],
|
110 |
api_name="risk_identifier"
|
111 |
)
|
112 |
self.assessed_risks.select(
|
executor.py
CHANGED
@@ -4,6 +4,7 @@ load_dotenv(override=True)
|
|
4 |
|
5 |
import re
|
6 |
import os
|
|
|
7 |
import json
|
8 |
from typing import List, Dict, Any
|
9 |
import pandas as pd
|
@@ -17,7 +18,7 @@ from risk_atlas_nexus.library import RiskAtlasNexus
|
|
17 |
from functools import lru_cache
|
18 |
|
19 |
# Load the taxonomies
|
20 |
-
ran = RiskAtlasNexus()
|
21 |
|
22 |
|
23 |
@lru_cache
|
@@ -25,53 +26,42 @@ def risk_identifier(usecase: str,
|
|
25 |
model_name_or_path: str = "ibm/granite-20b-code-instruct",
|
26 |
taxonomy: str = "ibm-risk-atlas"): # -> List[Dict[str, Any]]: #pd.DataFrame:
|
27 |
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
# Translate LLM output to Risk catalog
|
50 |
-
out = []
|
51 |
-
try:
|
52 |
-
risks = json.loads(risks)
|
53 |
-
except json.JSONDecodeError:
|
54 |
-
|
55 |
-
# Fallback to regex - will skip any partial categories
|
56 |
-
risks = re.findall(r'"(.*?)"', risks)
|
57 |
-
|
58 |
-
for risk in risks:
|
59 |
-
k = list(filter(lambda r: r.name == risk, ran._ontology.risks)) # type: ignore
|
60 |
-
out+= ([i.model_dump() for i in k])
|
61 |
-
|
62 |
-
elif isinstance(risks, List):
|
63 |
-
# FIXME: assumes that the output is structured - not sure if that's correct.
|
64 |
-
out = risks
|
65 |
-
|
66 |
-
#out_df = pd.DataFrame(out)
|
67 |
|
68 |
#return out_df
|
69 |
-
return gr.State(
|
70 |
-
sample_labels=
|
|
|
71 |
|
72 |
|
73 |
@lru_cache
|
74 |
-
def mitigations(riskid: str, taxonomy: str) -> tuple[gr.Dataset, gr.
|
|
|
|
|
|
|
|
|
|
|
|
|
75 |
|
76 |
related_risk_ids = ran.get_related_risk_ids_by_risk_id(riskid)
|
77 |
action_ids = []
|
@@ -96,19 +86,21 @@ def mitigations(riskid: str, taxonomy: str) -> tuple[gr.Dataset, gr.Dataset]:
|
|
96 |
samples = None
|
97 |
sample_labels = None
|
98 |
else:
|
99 |
-
label = "
|
100 |
samples = related_risk_ids
|
101 |
-
sample_labels = [i.name for i in ran.get_related_risks_by_risk_id(riskid)]
|
102 |
|
103 |
if not action_ids:
|
104 |
alabel = "No mitigations found."
|
105 |
asamples = None
|
106 |
asample_labels = None
|
|
|
107 |
else:
|
108 |
-
alabel = ""
|
109 |
asamples = action_ids
|
110 |
-
asample_labels = [ran.get_action_by_id(i).description for i in
|
111 |
-
|
|
|
112 |
|
113 |
return (gr.Dataset(samples=samples, label=label, sample_labels=sample_labels, visible=True),
|
114 |
-
gr.
|
|
|
4 |
|
5 |
import re
|
6 |
import os
|
7 |
+
import pandas as pd
|
8 |
import json
|
9 |
from typing import List, Dict, Any
|
10 |
import pandas as pd
|
|
|
18 |
from functools import lru_cache
|
19 |
|
20 |
# Load the taxonomies
|
21 |
+
ran = RiskAtlasNexus() # type: ignore
|
22 |
|
23 |
|
24 |
@lru_cache
|
|
|
26 |
model_name_or_path: str = "ibm/granite-20b-code-instruct",
|
27 |
taxonomy: str = "ibm-risk-atlas"): # -> List[Dict[str, Any]]: #pd.DataFrame:
|
28 |
|
29 |
+
inference_engine = WMLInferenceEngine(
|
30 |
+
model_name_or_path= model_name_or_path,
|
31 |
+
credentials={
|
32 |
+
"api_key": os.environ["WML_API_KEY"],
|
33 |
+
"api_url": os.environ["WML_API_URL"],
|
34 |
+
"project_id": os.environ["WML_PROJECT_ID"],
|
35 |
+
},
|
36 |
+
parameters=WMLInferenceEngineParams(
|
37 |
+
max_new_tokens=150, decoding_method="greedy", repetition_penalty=1
|
38 |
+
), # type: ignore
|
39 |
+
)
|
40 |
+
|
41 |
+
risks = ran.identify_risks_from_usecases( # type: ignore
|
42 |
+
usecases=[usecase],
|
43 |
+
inference_engine=inference_engine,
|
44 |
+
taxonomy=taxonomy,
|
45 |
+
)[0]
|
46 |
+
|
47 |
+
sample_labels = [r.name if r else r.id for r in risks]
|
48 |
+
|
49 |
+
out_sec = gr.Markdown("""<h2> Potential Risks </h2> """)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
50 |
|
51 |
#return out_df
|
52 |
+
return out_sec, gr.State(risks), gr.Dataset(samples=[r.id for r in risks],
|
53 |
+
sample_labels=sample_labels,
|
54 |
+
samples_per_page=50, visible=True, label="Estimated by an LLM.")
|
55 |
|
56 |
|
57 |
@lru_cache
|
58 |
+
def mitigations(riskid: str, taxonomy: str) -> tuple[gr.Dataset, gr.DataFrame]:
|
59 |
+
"""
|
60 |
+
For a specific risk (riskid), returns
|
61 |
+
(a) related risks - as a dataset
|
62 |
+
(b) mitigations
|
63 |
+
|
64 |
+
"""
|
65 |
|
66 |
related_risk_ids = ran.get_related_risk_ids_by_risk_id(riskid)
|
67 |
action_ids = []
|
|
|
86 |
samples = None
|
87 |
sample_labels = None
|
88 |
else:
|
89 |
+
label = f"Risks from other taxonomies related to {riskid}"
|
90 |
samples = related_risk_ids
|
91 |
+
sample_labels = [i.name for i in ran.get_related_risks_by_risk_id(riskid)] #type: ignore
|
92 |
|
93 |
if not action_ids:
|
94 |
alabel = "No mitigations found."
|
95 |
asamples = None
|
96 |
asample_labels = None
|
97 |
+
mitdf = pd.DataFrame()
|
98 |
else:
|
99 |
+
alabel = f"Mitigation actions related to risk {riskid}."
|
100 |
asamples = action_ids
|
101 |
+
asample_labels = [ran.get_action_by_id(i).description for i in asamples] # type: ignore
|
102 |
+
asample_name = [ran.get_action_by_id(i).name for i in asamples] #type: ignore
|
103 |
+
mitdf = pd.DataFrame({"Mitigation": asample_name, "Description": asample_labels})
|
104 |
|
105 |
return (gr.Dataset(samples=samples, label=label, sample_labels=sample_labels, visible=True),
|
106 |
+
gr.DataFrame(mitdf, wrap=True, show_copy_button=True, show_search="search", label=alabel, visible=True))
|
requirements.txt
CHANGED
@@ -1,4 +1,5 @@
|
|
1 |
-
gradio==5.
|
2 |
linkml==1.8.6
|
3 |
linkml_runtime==1.8.3
|
4 |
-
|
|
|
|
1 |
+
gradio==5.18.0
|
2 |
linkml==1.8.6
|
3 |
linkml_runtime==1.8.3
|
4 |
+
ibm_watsonx_ai==1.2.8
|
5 |
+
risk-atlas-nexus [wml] @ git+https://github.com/IBM/risk-atlas-nexus
|
static/text/header.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
|
2 |
|
3 |
<img src="/gradio_api/file=static/images/Risk_Atlas_Nexus_vector.png" width=300 style="display:block;margin:0 auto;">
|
4 |
-
<h1 style='text-align: center;
|
5 |
|
6 |
|
7 |
Risk Atlas Nexus aims to provide tooling to help bring together disparate resources related to governance of foundation models. We support a community driven approach to curating and cataloguing resources such as datasets, benchmarks and mitigations. Our goal is to turn abstract risk definitions into actionable workflows that streamline AI governance processes. By connecting fragmented resources, Risk Atlas Nexus seeks to fill a critical gap in AI governance, enabling stakeholders to build more robust, transparent, and accountable systems. Risk Atlas Nexus builds on the [IBM AI Risk Atlas](https://www.ibm.com/docs/en/watsonx/saas?topic=ai-risk-atlas) making this educational resource a nexus of governance assets and tooling. An AI System's Knowledge Graph is used to provide a unified structure that links and contextualize the very heterogeneous domain data.
|
|
|
1 |
|
2 |
|
3 |
<img src="/gradio_api/file=static/images/Risk_Atlas_Nexus_vector.png" width=300 style="display:block;margin:0 auto;">
|
4 |
+
<h1 style='text-align: center;'> Risk Atlas Nexus </h1>
|
5 |
|
6 |
|
7 |
Risk Atlas Nexus aims to provide tooling to help bring together disparate resources related to governance of foundation models. We support a community driven approach to curating and cataloguing resources such as datasets, benchmarks and mitigations. Our goal is to turn abstract risk definitions into actionable workflows that streamline AI governance processes. By connecting fragmented resources, Risk Atlas Nexus seeks to fill a critical gap in AI governance, enabling stakeholders to build more robust, transparent, and accountable systems. Risk Atlas Nexus builds on the [IBM AI Risk Atlas](https://www.ibm.com/docs/en/watsonx/saas?topic=ai-risk-atlas) making this educational resource a nexus of governance assets and tooling. An AI System's Knowledge Graph is used to provide a unified structure that links and contextualize the very heterogeneous domain data.
|
static/text/sec1.md
CHANGED
@@ -1,3 +1,3 @@
|
|
1 |
-
<h1 style='text-align: left;
|
2 |
|
3 |
Assess potential risks for a use case description based on risk taxonomies.
|
|
|
1 |
+
<h1 style='text-align: left;'> Risk assessment based on intent </h1>
|
2 |
|
3 |
Assess potential risks for a use case description based on risk taxonomies.
|