Skip to content

Commit 83f359c

Browse files
committed
Avoid date-as-math detection and fix mock parsing
1 parent 54650a6 commit 83f359c

File tree

3 files changed

+41
-6
lines changed

3 files changed

+41
-6
lines changed

micro_agent/agent.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,10 +163,17 @@ def _normalize_text(q: str) -> str:
163163
.replace("\u2014", "-")
164164
)
165165

166+
def _strip_date_literals(q: str) -> str:
167+
# Remove common date patterns to avoid misclassifying as math (e.g., 2025-12-22).
168+
q = re.sub(r"\b\d{4}[-/]\d{1,2}[-/]\d{1,2}\b", " DATE ", q)
169+
q = re.sub(r"\b\d{1,2}[-/]\d{1,2}[-/]\d{2,4}\b", " DATE ", q)
170+
return q
171+
166172
def needs_math(q: str) -> bool:
167173
qn = _normalize_text(q)
174+
qn_math = _strip_date_literals(qn)
168175
ql = qn.lower()
169-
if re.search(r"[0-9].*[+\-*/%]", qn):
176+
if re.search(r"[0-9].*[+\-*/%]", qn_math):
170177
return True
171178
if re.search(r"\b\d+(?:\.\d+)?\s*(?:x|times|multiplied by)\s*\d+(?:\.\d+)?\b", ql):
172179
return True
@@ -232,7 +239,7 @@ def _accumulate_usage(input_text: str = "", output_text: str = ""):
232239
pass
233240

234241
def _infer_expression(q: str) -> str:
235-
qn = _normalize_text(q)
242+
qn = _strip_date_literals(_normalize_text(q))
236243
ql = qn.lower()
237244
# Handle "divide X by Y" and "subtract X from Y"
238245
m = re.search(r"\bdivide\s+(\d+(?:\.\d+)?)\s+by\s+(\d+(?:\.\d+)?)\b", ql)

micro_agent/config.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,17 +31,23 @@ class _MockLM:
3131
model = "mock/local"
3232
def __call__(self, *, prompt: str, **kwargs):
3333
import re, json as _json
34-
qmatch = re.search(r"Question:\s*(.*)", prompt, re.S)
35-
question = qmatch.group(1).strip() if qmatch else prompt
34+
qmatch = re.search(r"\nQuestion:\s*(.*?)\n\nState:", prompt, re.S)
35+
if qmatch:
36+
question = qmatch.group(1).strip()
37+
else:
38+
qs = re.findall(r"\bQuestion:\s*(.*)", prompt)
39+
question = qs[-1].strip() if qs else prompt
3640
qn = (question
3741
.replace("\u00d7", "x")
3842
.replace("\u00f7", "/")
3943
.replace("\u2212", "-")
4044
.replace("\u2013", "-")
4145
.replace("\u2014", "-"))
46+
qn_math = re.sub(r"\b\d{4}[-/]\d{1,2}[-/]\d{1,2}\b", " DATE ", qn)
47+
qn_math = re.sub(r"\b\d{1,2}[-/]\d{1,2}[-/]\d{2,4}\b", " DATE ", qn_math)
4248
ql = qn.lower()
4349
# heuristic: suggest calculator/now/final
44-
if (re.search(r"[0-9].*[+\-*/%]", qn) or
50+
if (re.search(r"[0-9].*[+\-*/%]", qn_math) or
4551
re.search(r"\b\d+(?:\.\d+)?\s*(?:x|times|multiplied by|plus|minus|add|added to|subtract|subtracted by|divide|divided by|over)\s*\d+(?:\.\d+)?\b", ql) or
4652
(re.search(r"\d", ql) and any(w in ql for w in [
4753
"add","sum","plus","minus","subtract","multiply","divide","total","power","factorial","compute","calculate","!","**","^"
@@ -62,9 +68,13 @@ def __call__(self, *, prompt: str, **kwargs):
6268
m = re.search(r"\b(\d+(?:\.\d+)?)\s*(?:divide|divided by|over)\s*(\d+(?:\.\d+)?)\b", ql)
6369
if m:
6470
expr = f"{m.group(1)}/{m.group(2)}"
71+
if expr is None and ("add" in ql or "sum" in ql):
72+
nums = re.findall(r"\b\d+(?:\.\d+)?\b", qn_math)
73+
if len(nums) >= 2:
74+
expr = "+".join(nums)
6575
# crude expression extraction fallback
6676
if expr is None:
67-
cands = re.findall(r"[0-9\+\-\*/%\(\)\.!\^\s]+", qn)
77+
cands = re.findall(r"[0-9\+\-\*/%\(\)\.!\^\s]+", qn_math)
6878
cands = [c.strip() for c in cands if c.strip()]
6979
expr = max(cands, key=len) if cands else "2+2"
7080
return _json.dumps({"tool": {"name": "calculator", "args": {"expression": expr}}})

tests/test_regressions.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,21 @@ def test_now_local_has_offset():
6666
def test_now_invalid_timezone_validation():
6767
obs = run_tool("now", {"timezone": "pst"})
6868
assert "error" in obs and "validation" in obs["error"]
69+
70+
71+
def test_date_like_not_math(monkeypatch):
72+
monkeypatch.setenv("LLM_PROVIDER", "mock")
73+
configure_lm()
74+
agent = MicroAgent(max_steps=3)
75+
pred = agent("What's the date 2025-12-22 in UTC?")
76+
assert any(step.get("tool") == "now" for step in (pred.trace or []))
77+
assert not any(step.get("tool") == "calculator" for step in (pred.trace or []))
78+
79+
80+
def test_math_with_date_still_math(monkeypatch):
81+
monkeypatch.setenv("LLM_PROVIDER", "mock")
82+
configure_lm()
83+
agent = MicroAgent(max_steps=3)
84+
pred = agent("Add 2 and 2 on 2025-12-22.")
85+
assert any(step.get("tool") == "calculator" for step in (pred.trace or []))
86+
assert "4" in pred.answer

0 commit comments

Comments
 (0)