irregular6612 commited on
Commit
f60d821
·
1 Parent(s): a5d8764

feat(cp2): slim action parser

Browse files
proteus/agents/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ """proteus.agents — slim LLM agent abstraction (no forfeit/stake/risk)."""
proteus/agents/parsing.py ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Extract a single action token from free-form LLM text.
2
+
3
+ Strategy (first match wins):
4
+ 1. The last ``ACTION: <token>`` field (case-insensitive), trailing
5
+ punctuation stripped, if the token is a valid action.
6
+ 2. Fallback: the last valid-action word appearing anywhere in the text.
7
+ 3. ``None`` if no valid action is found.
8
+
9
+ Mirrors the parent project's ``ACTION:`` convention but drops all
10
+ forfeit/stake handling.
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ import re
16
+
17
+ _ACTION_FIELD = re.compile(r"ACTION\s*:\s*([^\n\r]+)", re.IGNORECASE)
18
+ _WORD = re.compile(r"[a-zA-Z]+")
19
+
20
+
21
+ def extract_action(text: str, valid: list[str]) -> str | None:
22
+ """Return the chosen action (one of *valid*) parsed from *text*, or None.
23
+
24
+ Args:
25
+ text: Raw LLM output.
26
+ valid: Allowed action strings (lowercase, e.g. ``["up", ...]``).
27
+
28
+ Returns:
29
+ The matched action string, or ``None`` if none is found.
30
+ """
31
+ valid_set = {v.lower() for v in valid}
32
+
33
+ # Strategy 1: last ACTION: <token> field.
34
+ field_matches = _ACTION_FIELD.findall(text)
35
+ for raw in reversed(field_matches):
36
+ token = raw.strip().strip(".!,;:'\"`").lower()
37
+ # take the first word of the field value
38
+ first = token.split()[0] if token.split() else ""
39
+ if first in valid_set:
40
+ return first
41
+
42
+ # Strategy 2: last valid-action word anywhere.
43
+ words = [w.lower() for w in _WORD.findall(text)]
44
+ for w in reversed(words):
45
+ if w in valid_set:
46
+ return w
47
+
48
+ return None
tests/agents/test_parsing.py ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from proteus.agents.parsing import extract_action
2
+
3
+ VALID = ["up", "down", "left", "right", "stay"]
4
+
5
+
6
+ def test_extracts_action_field_last_occurrence_wins():
7
+ text = "ACTION: left\n...changed my mind...\nACTION: up"
8
+ assert extract_action(text, VALID) == "up"
9
+
10
+
11
+ def test_case_insensitive_and_strips_punctuation():
12
+ assert extract_action("Action: Up.", VALID) == "up"
13
+
14
+
15
+ def test_bare_word_fallback_when_no_action_field():
16
+ assert extract_action("I will move down to escape.", VALID) == "down"
17
+
18
+
19
+ def test_returns_none_when_no_valid_action():
20
+ assert extract_action("no idea", VALID) is None