| """ |
| Task: T055, T056, T057, T058 |
| Spec: 011-chatbot-issues-fixes/spec.md - Fuzzy Matching Utilities |
| |
| Utility functions for fuzzy string matching to handle variations in task names. |
| """ |
|
|
| from typing import List, Tuple, Optional |
| from rapidfuzz import fuzz |
| from app.models.task import Task |
|
|
|
|
| def find_closest_task_match(task_name: str, tasks: List[Task], threshold: float = 0.8) -> Optional[Tuple[Task, float]]: |
| """ |
| Find the closest matching task name from a list of tasks using fuzzy matching. |
| |
| Args: |
| task_name: The name to match against |
| tasks: List of tasks to search through |
| threshold: Minimum similarity score (0.0-1.0) required for a match |
| |
| Returns: |
| Tuple of (matching_task, similarity_score) if found, None otherwise |
| """ |
| best_match = None |
| best_score = 0 |
|
|
| for task in tasks: |
| |
| title_score = fuzz.ratio(task_name.lower(), task.title.lower()) / 100.0 |
| desc_score = 0 |
| if task.description: |
| desc_score = fuzz.ratio(task_name.lower(), task.description.lower()) / 100.0 |
|
|
| |
| max_score = max(title_score, desc_score) |
|
|
| if max_score > best_score and max_score >= threshold: |
| best_score = max_score |
| best_match = (task, max_score) |
|
|
| return best_match |
|
|
|
|
| def fuzzy_match_task_by_name(task_name: str, tasks: List[Task]) -> Optional[Task]: |
| """ |
| Find a task by name using fuzzy matching. |
| |
| Args: |
| task_name: The name to match against |
| tasks: List of tasks to search through |
| |
| Returns: |
| Matching task if found, None otherwise |
| """ |
| match = find_closest_task_match(task_name, tasks) |
| return match[0] if match else None |