Parse a natural-language self-description into a bootstrap profile fragment.
(text: str, use_llm: bool = True)
| 1423 | |
| 1424 | |
| 1425 | def parse_natural_language(text: str, use_llm: bool = True) -> Dict[str, Any]: |
| 1426 | """Parse a natural-language self-description into a bootstrap profile fragment.""" |
| 1427 | normalized_text = re.sub(r"\s+", " ", (text or "").strip()).lower() |
| 1428 | if normalized_text in COLD_START_COMMAND_HINTS: |
| 1429 | return _empty_parsed_profile_fragment() |
| 1430 | |
| 1431 | from config.direction_lexicon import get_lexicon_keywords, resolve_canonical_direction |
| 1432 | |
| 1433 | working_text = str(text or "") |
| 1434 | text_lower = working_text.lower() |
| 1435 | merged_directions = get_lexicon_keywords() |
| 1436 | |
| 1437 | core_directions: Dict[str, float] = {} |
| 1438 | topic_weights: Dict[str, float] = {} |
| 1439 | exact_direction_hits: List[str] = [] |
| 1440 | |
| 1441 | for clause in _split_direction_clauses(working_text): |
| 1442 | resolved = resolve_canonical_direction(clause, include_paper_terms=True) |
| 1443 | if not resolved: |
| 1444 | continue |
| 1445 | direction_key = str(resolved.get("canonical_name") or "").strip() |
| 1446 | if not direction_key: |
| 1447 | continue |
| 1448 | exact_direction_hits.append(direction_key) |
| 1449 | core_directions[direction_key] = max(core_directions.get(direction_key, 0.0), 0.9) |
| 1450 | topic_weights[direction_key] = max(topic_weights.get(direction_key, 0.0), 0.9) |
| 1451 | working_text = _remove_clause_from_text(working_text, clause) |
| 1452 | |
| 1453 | working_text_lower = working_text.lower() |
| 1454 | for direction, keywords in merged_directions.items(): |
| 1455 | match_count = sum(1 for keyword in keywords if keyword and (keyword in working_text_lower or keyword in working_text)) |
| 1456 | if match_count <= 0: |
| 1457 | continue |
| 1458 | weight = min(0.5 + match_count * 0.1, 0.95) |
| 1459 | if direction in core_directions: |
| 1460 | weight = max(weight, core_directions[direction]) |
| 1461 | core_directions[direction] = weight |
| 1462 | topic_weights[direction] = max(topic_weights.get(direction, 0.0), weight) |
| 1463 | |
| 1464 | llm_parse_result: Dict[str, Any] = { |
| 1465 | "canonical_directions": [], |
| 1466 | "pending_candidates": [], |
| 1467 | "explanations": [], |
| 1468 | } |
| 1469 | if use_llm and not core_directions: |
| 1470 | llm_parse_result = _parse_directions_with_llm(text) |
| 1471 | |
| 1472 | llm_directions = list(llm_parse_result.get("canonical_directions", []) or []) |
| 1473 | for direction in llm_directions: |
| 1474 | direction_key = str(direction.get("name") or "").strip() |
| 1475 | if not direction_key: |
| 1476 | continue |
| 1477 | confidence = float(direction.get("confidence", 0.5) or 0.5) |
| 1478 | if direction_key in core_directions: |
| 1479 | existing = core_directions[direction_key] |
| 1480 | if confidence > existing: |
| 1481 | core_directions[direction_key] = confidence |
| 1482 | topic_weights[direction_key] = confidence |
no test coverage detected