Spaces:
Sleeping
Sleeping
| """Deterministic preferred-name/form-of-address extraction. "I am X" is | |
| deliberately excluded: it matches too many non-name sentences ("I am | |
| confused", "I am working on..."). Patterns use a lookahead rather than an | |
| end-of-string anchor so a name followed by more sentence content ("My name | |
| is Anshuman, and I'm studying robotics") still matches. See | |
| docs/commit-memory-adaptation-architecture.md. | |
| """ | |
| from __future__ import annotations | |
| import re | |
| _NAME_SIGNAL_PATTERNS = ( | |
| re.compile( | |
| r"\bmy name is\s+([A-Za-z][A-Za-z .'-]{0,48}?)(?=\s+(?:and|but)\b|[,.;!?\n]|$)", | |
| re.IGNORECASE, | |
| ), | |
| re.compile( | |
| r"\b(?:please\s+)?call me\s+([A-Za-z][A-Za-z .'-]{0,48}?)(?=\s+(?:and|but)\b|[,.;!?\n]|$)", | |
| re.IGNORECASE, | |
| ), | |
| re.compile( | |
| r"\byou can call me\s+([A-Za-z][A-Za-z .'-]{0,48}?)(?=\s+(?:and|but)\b|[,.;!?\n]|$)", | |
| re.IGNORECASE, | |
| ), | |
| re.compile( | |
| r"\bi go by\s+([A-Za-z][A-Za-z .'-]{0,48}?)(?=\s+(?:and|but)\b|[,.;!?\n]|$)", | |
| re.IGNORECASE, | |
| ), | |
| ) | |
| def extract_preferred_name(text: str) -> str | None: | |
| for pattern in _NAME_SIGNAL_PATTERNS: | |
| match = pattern.search(text or "") | |
| if not match: | |
| continue | |
| name = re.sub(r"\s+", " ", match.group(1)).strip(" .'-") | |
| if 1 < len(name) <= 80: | |
| return name | |
| return None | |