ISA #3: answer confidence/star badge (mobile-safe markdown)
Browse files
app.py
CHANGED
|
@@ -59,6 +59,24 @@ except Exception:
|
|
| 59 |
|
| 60 |
CONTEXT_TURNS = 5 # matches the Streamlit app's last-5-messages window
|
| 61 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 62 |
|
| 63 |
def answer(question: str, history: list[dict]) -> str:
|
| 64 |
"""Run one question through the tool pipeline. Mirrors the Streamlit flow."""
|
|
@@ -72,9 +90,11 @@ def answer(question: str, history: list[dict]) -> str:
|
|
| 72 |
except Exception:
|
| 73 |
keywords = []
|
| 74 |
|
|
|
|
| 75 |
try:
|
| 76 |
match = tool_matcher.match_tool(keywords, question, conversation_context=context)
|
| 77 |
tool = match["tool_name"]
|
|
|
|
| 78 |
except Exception:
|
| 79 |
logger.exception("Tool matching failed; falling back to the label tool")
|
| 80 |
tool = "cdms_label"
|
|
@@ -92,7 +112,12 @@ def answer(question: str, history: list[dict]) -> str:
|
|
| 92 |
return result.get(
|
| 93 |
"llm_response", "I couldn't find that in my label set."
|
| 94 |
)
|
| 95 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 96 |
|
| 97 |
|
| 98 |
def on_submit(question: str, history: list[dict], user: dict | None):
|
|
|
|
| 59 |
|
| 60 |
CONTEXT_TURNS = 5 # matches the Streamlit app's last-5-messages window
|
| 61 |
|
| 62 |
+
_TOOL_LABELS = {
|
| 63 |
+
"cdms_label": "CDMS label", "cdms": "CDMS label", "pesticide_label": "CDMS label",
|
| 64 |
+
"rag": "CDMS label", "documentation": "CDMS label",
|
| 65 |
+
"weather": "weather", "soil": "soil", "agriculture_web": "agriculture web", "ag_web": "agriculture web",
|
| 66 |
+
}
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
def _confidence_badge(tool: str, confidence: float) -> str:
|
| 70 |
+
"""Answer confidence/star badge (ISA feedback #3, ported from the Streamlit UI).
|
| 71 |
+
|
| 72 |
+
Plain-markdown so it renders cleanly on mobile — the Streamlit version's badge
|
| 73 |
+
was CSS-clipped on phones. `confidence` is the tool-router's match score (0-1).
|
| 74 |
+
"""
|
| 75 |
+
stars = max(1, min(5, round((confidence or 0.0) * 5)))
|
| 76 |
+
bar = "★" * stars + "☆" * (5 - stars)
|
| 77 |
+
label = _TOOL_LABELS.get(tool, tool)
|
| 78 |
+
return f"\n\n---\n`{bar}` · **{confidence:.0%} confidence** · answered via *{label}*"
|
| 79 |
+
|
| 80 |
|
| 81 |
def answer(question: str, history: list[dict]) -> str:
|
| 82 |
"""Run one question through the tool pipeline. Mirrors the Streamlit flow."""
|
|
|
|
| 90 |
except Exception:
|
| 91 |
keywords = []
|
| 92 |
|
| 93 |
+
confidence = 0.3
|
| 94 |
try:
|
| 95 |
match = tool_matcher.match_tool(keywords, question, conversation_context=context)
|
| 96 |
tool = match["tool_name"]
|
| 97 |
+
confidence = float(match.get("confidence", 0.3) or 0.3)
|
| 98 |
except Exception:
|
| 99 |
logger.exception("Tool matching failed; falling back to the label tool")
|
| 100 |
tool = "cdms_label"
|
|
|
|
| 112 |
return result.get(
|
| 113 |
"llm_response", "I couldn't find that in my label set."
|
| 114 |
)
|
| 115 |
+
reply = result.get("llm_response", "I couldn't process that request.")
|
| 116 |
+
# Show a confidence/star rating with real answers. Not on an abstention — a
|
| 117 |
+
# confidence score on "I don't have that label" would be misleading.
|
| 118 |
+
if "don't have the label" not in reply:
|
| 119 |
+
reply += _confidence_badge(tool, confidence)
|
| 120 |
+
return reply
|
| 121 |
|
| 122 |
|
| 123 |
def on_submit(question: str, history: list[dict], user: dict | None):
|