Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -141,21 +141,18 @@ with col1:
|
|
| 141 |
st.markdown("<span class='step-num'>4</span> <b>Agent Strictness Controls</b>", unsafe_allow_html=True)
|
| 142 |
doc_match_threshold = st.slider("Document Match Strictness (Semantic Similarity)", 0.5, 0.95, 0.65, 0.01,
|
| 143 |
help="How closely a field or file must match the checklist requirement. Higher = stricter.")
|
| 144 |
-
mandatory_doc_pct = st.slider("Mandatory Document Strictness (%)",
|
| 145 |
help="Minimum percentage of mandatory docs required for onboarding.")
|
| 146 |
field_value_strict = st.slider("Field Value Strictness (0=Any, 1=Only Files/Numbers)", 0, 1, 0, 1,
|
| 147 |
help="Require files/formal values (1) or allow 'Yes', 'N/A', etc. (0).")
|
| 148 |
compliance_strict = st.slider("Compliance Registry Strictness (0=Allow, 1=Reject)", 0, 1, 1, 1,
|
| 149 |
help="Reject if company not found in Canada registry (1), or allow with warning (0).")
|
| 150 |
|
| 151 |
-
st.markdown("<span class='step-num'>5</span> <b>Agent Instructions
|
| 152 |
-
user_editable_instructions = """
|
| 153 |
-
|
| 154 |
-
- For each compliance requirement, you are provided the best-matching (key, value) field pair from the supplier's data (determined by AI semantic similarity, not just spelling).
|
| 155 |
- If the value is a file (e.g., .pdf or .docx), treat this as strong evidence and DO NOT mark as missing unless there is a clear reason.
|
| 156 |
-
- Only mark as missing if nothing plausible is provided anywhere in the data, or if the evidence is clearly invalid.
|
| 157 |
-
"""
|
| 158 |
-
agent_instruction = st.text_area("Edit agent instruction prompt (business logic only):", value=user_editable_instructions, height=170, key="agent_instruction")
|
| 159 |
|
| 160 |
with col2:
|
| 161 |
st.markdown("<span class='step-num'>6</span> <b>Run Supplier Onboarding Agent</b>", unsafe_allow_html=True)
|
|
@@ -232,7 +229,6 @@ with col2:
|
|
| 232 |
best_match_text = supplier_pairs[best_idx]
|
| 233 |
best_score = sim_scores[best_idx]
|
| 234 |
is_provided = best_score >= doc_match_threshold
|
| 235 |
-
# Field value strictness: Only accept files/numbers if slider is at 1
|
| 236 |
if field_value_strict == 1:
|
| 237 |
file_like = bool(re.search(r'\.(pdf|docx?|xls|csv|jpg|jpeg|png)$', str(best_match_text).lower()))
|
| 238 |
numeric_like = bool(re.match(r'^\d+(\.\d+)?$', str(best_match_text)))
|
|
@@ -250,7 +246,6 @@ with col2:
|
|
| 250 |
"status": "Provided" if is_provided else "Missing"
|
| 251 |
})
|
| 252 |
|
| 253 |
-
# Pre-Lens: Strictness logic before LLM
|
| 254 |
n_mandatory = sum(1 for f in findings if f["mandatory"])
|
| 255 |
n_mandatory_provided = sum(1 for f in findings if f["mandatory"] and f["status"] == "Provided")
|
| 256 |
pct_mandatory = 100 * n_mandatory_provided / n_mandatory if n_mandatory else 100
|
|
@@ -280,16 +275,8 @@ with col2:
|
|
| 280 |
early_reject = True
|
| 281 |
reasons.append("Company not found in Corporations Canada registry.")
|
| 282 |
|
| 283 |
-
|
| 284 |
-
|
| 285 |
-
"decision": "REJECTED",
|
| 286 |
-
"reason": "; ".join(reasons),
|
| 287 |
-
"red_flags": reasons,
|
| 288 |
-
"missing_documents": [f["document"] for f in findings if f["mandatory"] and f["status"] == "Missing"],
|
| 289 |
-
"next_steps": ["Request all missing mandatory documents and registry proof before proceeding."]
|
| 290 |
-
}
|
| 291 |
-
else:
|
| 292 |
-
llm_return_format = """
|
| 293 |
Return JSON:
|
| 294 |
{
|
| 295 |
"decision": "ONBOARDED" | "REJECTED" | "PENDING",
|
|
@@ -299,7 +286,17 @@ Return JSON:
|
|
| 299 |
"next_steps": [ ... ]
|
| 300 |
}
|
| 301 |
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 302 |
llm_prompt = f"""
|
|
|
|
| 303 |
{agent_instruction}
|
| 304 |
|
| 305 |
Supplier main info: {json.dumps(main_info, indent=2)}
|
|
|
|
| 141 |
st.markdown("<span class='step-num'>4</span> <b>Agent Strictness Controls</b>", unsafe_allow_html=True)
|
| 142 |
doc_match_threshold = st.slider("Document Match Strictness (Semantic Similarity)", 0.5, 0.95, 0.65, 0.01,
|
| 143 |
help="How closely a field or file must match the checklist requirement. Higher = stricter.")
|
| 144 |
+
mandatory_doc_pct = st.slider("Mandatory Document Strictness (%)", 20, 100, 100, 1,
|
| 145 |
help="Minimum percentage of mandatory docs required for onboarding.")
|
| 146 |
field_value_strict = st.slider("Field Value Strictness (0=Any, 1=Only Files/Numbers)", 0, 1, 0, 1,
|
| 147 |
help="Require files/formal values (1) or allow 'Yes', 'N/A', etc. (0).")
|
| 148 |
compliance_strict = st.slider("Compliance Registry Strictness (0=Allow, 1=Reject)", 0, 1, 1, 1,
|
| 149 |
help="Reject if company not found in Canada registry (1), or allow with warning (0).")
|
| 150 |
|
| 151 |
+
st.markdown("<span class='step-num'>5</span> <b>Agent Instructions</b>", unsafe_allow_html=True)
|
| 152 |
+
user_editable_instructions = """- For each compliance requirement, you are provided the best-matching (key, value) field pair from the supplier's data (determined by AI semantic similarity, not just spelling).
|
|
|
|
|
|
|
| 153 |
- If the value is a file (e.g., .pdf or .docx), treat this as strong evidence and DO NOT mark as missing unless there is a clear reason.
|
| 154 |
+
- Only mark as missing if nothing plausible is provided anywhere in the data, or if the evidence is clearly invalid."""
|
| 155 |
+
agent_instruction = st.text_area("Edit agent instruction prompt:", value=user_editable_instructions, height=130, key="agent_instruction")
|
|
|
|
| 156 |
|
| 157 |
with col2:
|
| 158 |
st.markdown("<span class='step-num'>6</span> <b>Run Supplier Onboarding Agent</b>", unsafe_allow_html=True)
|
|
|
|
| 229 |
best_match_text = supplier_pairs[best_idx]
|
| 230 |
best_score = sim_scores[best_idx]
|
| 231 |
is_provided = best_score >= doc_match_threshold
|
|
|
|
| 232 |
if field_value_strict == 1:
|
| 233 |
file_like = bool(re.search(r'\.(pdf|docx?|xls|csv|jpg|jpeg|png)$', str(best_match_text).lower()))
|
| 234 |
numeric_like = bool(re.match(r'^\d+(\.\d+)?$', str(best_match_text)))
|
|
|
|
| 246 |
"status": "Provided" if is_provided else "Missing"
|
| 247 |
})
|
| 248 |
|
|
|
|
| 249 |
n_mandatory = sum(1 for f in findings if f["mandatory"])
|
| 250 |
n_mandatory_provided = sum(1 for f in findings if f["mandatory"] and f["status"] == "Provided")
|
| 251 |
pct_mandatory = 100 * n_mandatory_provided / n_mandatory if n_mandatory else 100
|
|
|
|
| 275 |
early_reject = True
|
| 276 |
reasons.append("Company not found in Corporations Canada registry.")
|
| 277 |
|
| 278 |
+
persona_instruction = "You are a senior supplier onboarding analyst.\n\n"
|
| 279 |
+
llm_return_format = """
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 280 |
Return JSON:
|
| 281 |
{
|
| 282 |
"decision": "ONBOARDED" | "REJECTED" | "PENDING",
|
|
|
|
| 286 |
"next_steps": [ ... ]
|
| 287 |
}
|
| 288 |
"""
|
| 289 |
+
if early_reject:
|
| 290 |
+
agent_json = {
|
| 291 |
+
"decision": "REJECTED",
|
| 292 |
+
"reason": "; ".join(reasons),
|
| 293 |
+
"red_flags": reasons,
|
| 294 |
+
"missing_documents": [f["document"] for f in findings if f["mandatory"] and f["status"] == "Missing"],
|
| 295 |
+
"next_steps": ["Request all missing mandatory documents and registry proof before proceeding."]
|
| 296 |
+
}
|
| 297 |
+
else:
|
| 298 |
llm_prompt = f"""
|
| 299 |
+
{persona_instruction}
|
| 300 |
{agent_instruction}
|
| 301 |
|
| 302 |
Supplier main info: {json.dumps(main_info, indent=2)}
|