bryan-stearns
commited on
Commit
·
2ca6dd2
1
Parent(s):
fc8607f
Adding description labels and content filters
Browse files- Inspect_Logic.py +55 -7
- smem_obj.py +38 -3
Inspect_Logic.py
CHANGED
|
@@ -21,6 +21,8 @@ def get_smem_root_from_file(smem_file):
|
|
| 21 |
parser.parse_file(tokens)
|
| 22 |
return parser.get_context_root()
|
| 23 |
|
|
|
|
|
|
|
| 24 |
if "col_obj_list" not in st.session_state:
|
| 25 |
st.session_state["col_obj_list"] = None
|
| 26 |
|
|
@@ -37,13 +39,26 @@ if file is not None:
|
|
| 37 |
else:
|
| 38 |
st.session_state["col_obj_list"] = None
|
| 39 |
|
| 40 |
-
# inpath = "/Users/bstearn1/Documents/Projects/OptumGitHub/Intelligent-Solutions/AICarePlan/agent/D-RULES_082222_smem.soar"
|
| 41 |
-
# inpath = "SMEM Generator/test_pim_smem.soar"
|
| 42 |
-
# st.session_state.col_obj_list[0] = get_smem_root_from_file(inpath)
|
| 43 |
-
|
| 44 |
if st.session_state.col_obj_list is None:
|
| 45 |
st.stop()
|
| 46 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 47 |
def add_col(index, obj):
|
| 48 |
st.session_state.col_obj_list = st.session_state.col_obj_list[:index+1]
|
| 49 |
st.session_state.col_obj_list.append(obj)
|
|
@@ -62,10 +77,20 @@ def get_header_str(obj_type):
|
|
| 62 |
else:
|
| 63 |
return " "
|
| 64 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 65 |
st.subheader("Click the buttons below to select conditions and to inspect resulting actions.")
|
| 66 |
|
| 67 |
cols = st.columns(max(MIN_COLS,len(st.session_state.col_obj_list)))
|
| 68 |
-
|
| 69 |
for i,col in enumerate(cols):
|
| 70 |
try:
|
| 71 |
if st.session_state.col_obj_list[i] == None:
|
|
@@ -85,17 +110,40 @@ for i,col in enumerate(cols):
|
|
| 85 |
col.text(obj_str)
|
| 86 |
if obj_desc != None:
|
| 87 |
col.markdown("*"+obj_desc+"*")
|
|
|
|
|
|
|
| 88 |
for j,sub in enumerate(sub_objs):
|
| 89 |
sub_str,sub_label,sub_desc = sub.to_string()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 90 |
if sub.obj_type == ObjType.OP:
|
| 91 |
subsub = list(sub.get_child_objects(compact=True))[0]
|
| 92 |
_,group_string,_ = subsub.to_string()
|
| 93 |
group_string = "\n * "+str(group_string).replace("AND", "\n * ")
|
| 94 |
col.markdown(group_string)
|
| 95 |
-
if col.button(
|
| 96 |
add_col(i,sub)
|
| 97 |
elif sub.obj_type == ObjType.ACT_GROUP:
|
| 98 |
col.markdown("*Output Details:* ")
|
| 99 |
col.markdown("\n * "+str(sub_str).replace(") AND", ")\n * "))
|
| 100 |
-
elif col.button(
|
| 101 |
add_col(i,sub)
|
|
|
|
| 21 |
parser.parse_file(tokens)
|
| 22 |
return parser.get_context_root()
|
| 23 |
|
| 24 |
+
## DEFINE THE FILE UPLOADER ELEMENT
|
| 25 |
+
|
| 26 |
if "col_obj_list" not in st.session_state:
|
| 27 |
st.session_state["col_obj_list"] = None
|
| 28 |
|
|
|
|
| 39 |
else:
|
| 40 |
st.session_state["col_obj_list"] = None
|
| 41 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 42 |
if st.session_state.col_obj_list is None:
|
| 43 |
st.stop()
|
| 44 |
|
| 45 |
+
|
| 46 |
+
## DEFINE THE CONTENT FILTERS
|
| 47 |
+
@st.cache(show_spinner=False, hash_funcs={SMEM_Obj: id})
|
| 48 |
+
def get_filter_features_dict(root_obj):
|
| 49 |
+
return root_obj.get_referenced_features()
|
| 50 |
+
|
| 51 |
+
# Get the content to filter on
|
| 52 |
+
features_dict = get_filter_features_dict(st.session_state.col_obj_list[0])
|
| 53 |
+
filters_expander = st.expander(label="Filters")
|
| 54 |
+
filters_cols = filters_expander.columns(len(features_dict))
|
| 55 |
+
filters_dict = {}
|
| 56 |
+
for key, col in zip(features_dict, filters_cols):
|
| 57 |
+
filters_dict[key] = col.multiselect(label=key, options=["(none)"]+sorted(features_dict[key]))
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
## DEFINE THE KNOWLEDGE INSPECTOR COLUMNS
|
| 61 |
+
|
| 62 |
def add_col(index, obj):
|
| 63 |
st.session_state.col_obj_list = st.session_state.col_obj_list[:index+1]
|
| 64 |
st.session_state.col_obj_list.append(obj)
|
|
|
|
| 77 |
else:
|
| 78 |
return " "
|
| 79 |
|
| 80 |
+
def get_tested_wmes_from_obj_str(obj_str):
|
| 81 |
+
attr_list = []
|
| 82 |
+
val_list = []
|
| 83 |
+
clauses = str(obj_str).split(" AND ")
|
| 84 |
+
for clause in clauses:
|
| 85 |
+
attr,val = clause.replace("(","").replace(")","").split(" is ", maxsplit=1)
|
| 86 |
+
attr_list += [attr]
|
| 87 |
+
val_list += [val]
|
| 88 |
+
return attr_list, val_list
|
| 89 |
+
|
| 90 |
st.subheader("Click the buttons below to select conditions and to inspect resulting actions.")
|
| 91 |
|
| 92 |
cols = st.columns(max(MIN_COLS,len(st.session_state.col_obj_list)))
|
| 93 |
+
# Iteratively build the columns of navigable knowlege elements
|
| 94 |
for i,col in enumerate(cols):
|
| 95 |
try:
|
| 96 |
if st.session_state.col_obj_list[i] == None:
|
|
|
|
| 110 |
col.text(obj_str)
|
| 111 |
if obj_desc != None:
|
| 112 |
col.markdown("*"+obj_desc+"*")
|
| 113 |
+
|
| 114 |
+
# Print the child objects of this object as the items in this column
|
| 115 |
for j,sub in enumerate(sub_objs):
|
| 116 |
sub_str,sub_label,sub_desc = sub.to_string()
|
| 117 |
+
if sub_desc != None:
|
| 118 |
+
button_text = sub_desc
|
| 119 |
+
else:
|
| 120 |
+
button_text = sub_label
|
| 121 |
+
# Check filters
|
| 122 |
+
if sub.obj_type == ObjType.COND_PRIM or sub.obj_type == ObjType.COND_CONJ:
|
| 123 |
+
# Get the feature and value for this sub obj
|
| 124 |
+
keep = True
|
| 125 |
+
attr_list, val_list = get_tested_wmes_from_obj_str(sub_desc)
|
| 126 |
+
# Check each filter key for a match
|
| 127 |
+
for attr in filters_dict:
|
| 128 |
+
if attr not in attr_list:
|
| 129 |
+
# Filter doesn't apply for this object
|
| 130 |
+
continue
|
| 131 |
+
if val_list[attr_list.index(attr)] not in filters_dict[attr] and len(filters_dict[attr]) > 0:
|
| 132 |
+
# Value not present
|
| 133 |
+
keep = False
|
| 134 |
+
break
|
| 135 |
+
if not keep:
|
| 136 |
+
continue
|
| 137 |
+
|
| 138 |
if sub.obj_type == ObjType.OP:
|
| 139 |
subsub = list(sub.get_child_objects(compact=True))[0]
|
| 140 |
_,group_string,_ = subsub.to_string()
|
| 141 |
group_string = "\n * "+str(group_string).replace("AND", "\n * ")
|
| 142 |
col.markdown(group_string)
|
| 143 |
+
if col.button(button_text, key="button"+str(i)+"-"+str(j)):
|
| 144 |
add_col(i,sub)
|
| 145 |
elif sub.obj_type == ObjType.ACT_GROUP:
|
| 146 |
col.markdown("*Output Details:* ")
|
| 147 |
col.markdown("\n * "+str(sub_str).replace(") AND", ")\n * "))
|
| 148 |
+
elif col.button(button_text, key="button"+str(i)+"-"+str(j)):
|
| 149 |
add_col(i,sub)
|
smem_obj.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
|
|
| 1 |
from enum import Enum
|
| 2 |
|
| 3 |
class SMEM_Obj():
|
|
@@ -16,6 +17,8 @@ class SMEM_Obj():
|
|
| 16 |
self.wme_list.append((attr,val))
|
| 17 |
|
| 18 |
def get_class(self):
|
|
|
|
|
|
|
| 19 |
for (attr,val) in self.wme_list:
|
| 20 |
if attr == "^class":
|
| 21 |
self.class_str = val
|
|
@@ -32,6 +35,31 @@ class SMEM_Obj():
|
|
| 32 |
break
|
| 33 |
return self.description
|
| 34 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 35 |
def get_compact_printable_object(self):
|
| 36 |
""" Return this object if printable in compact mode, else return the set of next printable descendants.
|
| 37 |
"""
|
|
@@ -162,17 +190,24 @@ class SMEM_Obj():
|
|
| 162 |
retval_desc = val
|
| 163 |
# if attr == "^supplies-condition":
|
| 164 |
# child_conjs.append(val)
|
| 165 |
-
|
|
|
|
|
|
|
|
|
|
| 166 |
for i,cond in enumerate(parent_conds):
|
| 167 |
if i > 0:
|
| 168 |
retval_long += " \nAND "
|
| 169 |
retval_short += " AND "
|
|
|
|
|
|
|
| 170 |
if cond.obj_type == ObjType.COND_CONJ:
|
| 171 |
-
long, short,
|
| 172 |
else:
|
| 173 |
-
long, short,
|
| 174 |
retval_long += long
|
| 175 |
retval_short += short
|
|
|
|
|
|
|
| 176 |
return retval_long, retval_short, retval_desc
|
| 177 |
|
| 178 |
def get_op_string(self):
|
|
|
|
| 1 |
+
from collections import defaultdict
|
| 2 |
from enum import Enum
|
| 3 |
|
| 4 |
class SMEM_Obj():
|
|
|
|
| 17 |
self.wme_list.append((attr,val))
|
| 18 |
|
| 19 |
def get_class(self):
|
| 20 |
+
if self.class_str != None:
|
| 21 |
+
return self.class_str
|
| 22 |
for (attr,val) in self.wme_list:
|
| 23 |
if attr == "^class":
|
| 24 |
self.class_str = val
|
|
|
|
| 35 |
break
|
| 36 |
return self.description
|
| 37 |
|
| 38 |
+
def get_referenced_features(self, dict_of_values=None):
|
| 39 |
+
# Collect a map of feature fields to possible values, as referenced by descendants from this object
|
| 40 |
+
if not dict_of_values:
|
| 41 |
+
dict_of_values = defaultdict(set)
|
| 42 |
+
children = self.get_child_objects(compact=False)
|
| 43 |
+
for child in children:
|
| 44 |
+
_, short_label, desc = child.to_string()
|
| 45 |
+
# Trim the label based on the object type
|
| 46 |
+
if child.obj_type == ObjType.COND_PRIM:
|
| 47 |
+
if desc:
|
| 48 |
+
str_to_use = desc
|
| 49 |
+
else:
|
| 50 |
+
str_to_use = short_label
|
| 51 |
+
ind = str_to_use.index(" is ")
|
| 52 |
+
feature, value = str_to_use.replace("(","").replace(")","").split(" is ",maxsplit=1)
|
| 53 |
+
dict_of_values[feature].add(value)
|
| 54 |
+
# Merge this dict of sets with results from each branch of children
|
| 55 |
+
child_dict = child.get_referenced_features(dict_of_values)
|
| 56 |
+
for key, val in child_dict.items():
|
| 57 |
+
if key in dict_of_values:
|
| 58 |
+
dict_of_values[key].update(val)
|
| 59 |
+
else:
|
| 60 |
+
dict_of_values[key] = val
|
| 61 |
+
return dict_of_values
|
| 62 |
+
|
| 63 |
def get_compact_printable_object(self):
|
| 64 |
""" Return this object if printable in compact mode, else return the set of next printable descendants.
|
| 65 |
"""
|
|
|
|
| 190 |
retval_desc = val
|
| 191 |
# if attr == "^supplies-condition":
|
| 192 |
# child_conjs.append(val)
|
| 193 |
+
compile_component_descs = (retval_desc == None)
|
| 194 |
+
if compile_component_descs:
|
| 195 |
+
retval_desc = ""
|
| 196 |
+
|
| 197 |
for i,cond in enumerate(parent_conds):
|
| 198 |
if i > 0:
|
| 199 |
retval_long += " \nAND "
|
| 200 |
retval_short += " AND "
|
| 201 |
+
if compile_component_descs:
|
| 202 |
+
retval_desc += " AND "
|
| 203 |
if cond.obj_type == ObjType.COND_CONJ:
|
| 204 |
+
long, short, desc = cond.get_cond_string()
|
| 205 |
else:
|
| 206 |
+
long, short, desc = cond.get_prim_cond_string(negate=is_negation)
|
| 207 |
retval_long += long
|
| 208 |
retval_short += short
|
| 209 |
+
if compile_component_descs:
|
| 210 |
+
retval_desc += "("+desc+")"
|
| 211 |
return retval_long, retval_short, retval_desc
|
| 212 |
|
| 213 |
def get_op_string(self):
|