Add strict confidence filtering option
### New Feature: - --strict flag for exact confidence matching - Default: Medium = Medium + High (or better) - Strict: Medium = Medium only (exact match) ### Usage: ./seo category_apply -s mistergeek.net -c Medium # Medium or better ./seo category_apply -s mistergeek.net -c Medium --strict # Medium only ### Example Output: # Default (or better): Filtered to 328 proposals (confidence >= Medium) # Strict mode: Filtered to 156 proposals (confidence = Medium, strict mode) ### Benefits: - More precise control over which posts to update - Can process confidence levels separately - Better for batch processing in stages Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
@@ -92,7 +92,8 @@ class SEOApp:
|
|||||||
return proposer.run(output_file=output)
|
return proposer.run(output_file=output)
|
||||||
|
|
||||||
def category_apply(self, proposals_csv: str, site_name: str,
|
def category_apply(self, proposals_csv: str, site_name: str,
|
||||||
confidence: str = 'Medium', dry_run: bool = False) -> dict:
|
confidence: str = 'Medium', strict: bool = False,
|
||||||
|
dry_run: bool = False) -> dict:
|
||||||
"""
|
"""
|
||||||
Apply AI category proposals to WordPress.
|
Apply AI category proposals to WordPress.
|
||||||
|
|
||||||
@@ -100,6 +101,7 @@ class SEOApp:
|
|||||||
proposals_csv: Path to proposals CSV
|
proposals_csv: Path to proposals CSV
|
||||||
site_name: Site to apply changes to (mistergeek.net, webscroll.fr, hellogeek.net)
|
site_name: Site to apply changes to (mistergeek.net, webscroll.fr, hellogeek.net)
|
||||||
confidence: Minimum confidence level (High, Medium, Low)
|
confidence: Minimum confidence level (High, Medium, Low)
|
||||||
|
strict: If True, only match exact confidence (not "or better")
|
||||||
dry_run: If True, preview changes without applying
|
dry_run: If True, preview changes without applying
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
@@ -112,6 +114,7 @@ class SEOApp:
|
|||||||
proposals_csv=proposals_csv,
|
proposals_csv=proposals_csv,
|
||||||
site_name=site_name,
|
site_name=site_name,
|
||||||
confidence_threshold=confidence,
|
confidence_threshold=confidence,
|
||||||
|
strict=strict,
|
||||||
dry_run=dry_run
|
dry_run=dry_run
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -334,6 +334,7 @@ class CategoryAssignmentProcessor:
|
|||||||
|
|
||||||
def process_proposals(self, proposals: List[Dict], site_name: str,
|
def process_proposals(self, proposals: List[Dict], site_name: str,
|
||||||
confidence_threshold: str = 'Medium',
|
confidence_threshold: str = 'Medium',
|
||||||
|
strict: bool = False,
|
||||||
dry_run: bool = False) -> Dict[str, int]:
|
dry_run: bool = False) -> Dict[str, int]:
|
||||||
"""
|
"""
|
||||||
Process AI category proposals and apply to WordPress.
|
Process AI category proposals and apply to WordPress.
|
||||||
@@ -342,6 +343,7 @@ class CategoryAssignmentProcessor:
|
|||||||
proposals: List of proposal dicts from CSV
|
proposals: List of proposal dicts from CSV
|
||||||
site_name: Site to apply changes to (filters proposals)
|
site_name: Site to apply changes to (filters proposals)
|
||||||
confidence_threshold: Minimum confidence to apply (High, Medium, Low)
|
confidence_threshold: Minimum confidence to apply (High, Medium, Low)
|
||||||
|
strict: If True, only match exact confidence level
|
||||||
dry_run: If True, don't actually make changes
|
dry_run: If True, don't actually make changes
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
@@ -362,6 +364,15 @@ class CategoryAssignmentProcessor:
|
|||||||
logger.info(f"Filtered to {len(proposals)} posts on {site_name} ({filtered_by_site} excluded from other sites)")
|
logger.info(f"Filtered to {len(proposals)} posts on {site_name} ({filtered_by_site} excluded from other sites)")
|
||||||
|
|
||||||
# Filter by confidence
|
# Filter by confidence
|
||||||
|
if strict:
|
||||||
|
# Exact match only
|
||||||
|
filtered_proposals = [
|
||||||
|
p for p in proposals
|
||||||
|
if p.get('category_confidence', 'Medium') == confidence_threshold
|
||||||
|
]
|
||||||
|
logger.info(f"Filtered to {len(filtered_proposals)} proposals (confidence = {confidence_threshold}, strict mode)")
|
||||||
|
else:
|
||||||
|
# Medium or better (default behavior)
|
||||||
confidence_order = {'High': 3, 'Medium': 2, 'Low': 1}
|
confidence_order = {'High': 3, 'Medium': 2, 'Low': 1}
|
||||||
min_confidence = confidence_order.get(confidence_threshold, 2)
|
min_confidence = confidence_order.get(confidence_threshold, 2)
|
||||||
|
|
||||||
@@ -369,7 +380,6 @@ class CategoryAssignmentProcessor:
|
|||||||
p for p in proposals
|
p for p in proposals
|
||||||
if confidence_order.get(p.get('category_confidence', 'Medium'), 2) >= min_confidence
|
if confidence_order.get(p.get('category_confidence', 'Medium'), 2) >= min_confidence
|
||||||
]
|
]
|
||||||
|
|
||||||
logger.info(f"Filtered to {len(filtered_proposals)} proposals (confidence >= {confidence_threshold})")
|
logger.info(f"Filtered to {len(filtered_proposals)} proposals (confidence >= {confidence_threshold})")
|
||||||
|
|
||||||
# Fetch existing categories
|
# Fetch existing categories
|
||||||
@@ -434,6 +444,7 @@ class CategoryAssignmentProcessor:
|
|||||||
|
|
||||||
def run(self, proposals_csv: str, site_name: str,
|
def run(self, proposals_csv: str, site_name: str,
|
||||||
confidence_threshold: str = 'Medium',
|
confidence_threshold: str = 'Medium',
|
||||||
|
strict: bool = False,
|
||||||
dry_run: bool = False) -> Dict[str, int]:
|
dry_run: bool = False) -> Dict[str, int]:
|
||||||
"""
|
"""
|
||||||
Run complete category assignment process.
|
Run complete category assignment process.
|
||||||
@@ -442,6 +453,7 @@ class CategoryAssignmentProcessor:
|
|||||||
proposals_csv: Path to proposals CSV
|
proposals_csv: Path to proposals CSV
|
||||||
site_name: Site to apply changes to
|
site_name: Site to apply changes to
|
||||||
confidence_threshold: Minimum confidence to apply
|
confidence_threshold: Minimum confidence to apply
|
||||||
|
strict: If True, only match exact confidence level
|
||||||
dry_run: If True, preview changes without applying
|
dry_run: If True, preview changes without applying
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
@@ -457,5 +469,6 @@ class CategoryAssignmentProcessor:
|
|||||||
proposals,
|
proposals,
|
||||||
site_name,
|
site_name,
|
||||||
confidence_threshold,
|
confidence_threshold,
|
||||||
dry_run
|
strict=strict,
|
||||||
|
dry_run=dry_run
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ Examples:
|
|||||||
parser.add_argument('--site', '-s', choices=['mistergeek.net', 'webscroll.fr', 'hellogeek.net'],
|
parser.add_argument('--site', '-s', choices=['mistergeek.net', 'webscroll.fr', 'hellogeek.net'],
|
||||||
help='WordPress site for category operations')
|
help='WordPress site for category operations')
|
||||||
parser.add_argument('--description', '-d', help='Category description')
|
parser.add_argument('--description', '-d', help='Category description')
|
||||||
|
parser.add_argument('--strict', action='store_true', help='Strict confidence matching (exact match only)')
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
@@ -160,6 +161,8 @@ def cmd_category_apply(app, args):
|
|||||||
print("Would apply category proposals to WordPress")
|
print("Would apply category proposals to WordPress")
|
||||||
print(f" Site: {args.site}")
|
print(f" Site: {args.site}")
|
||||||
print(f" Confidence: {args.confidence}")
|
print(f" Confidence: {args.confidence}")
|
||||||
|
if args.strict:
|
||||||
|
print(f" Strict mode: Yes (exact match only)")
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
if not args.site:
|
if not args.site:
|
||||||
@@ -180,11 +183,14 @@ def cmd_category_apply(app, args):
|
|||||||
print(f"Applying categories from: {proposals_csv}")
|
print(f"Applying categories from: {proposals_csv}")
|
||||||
print(f"Site: {args.site}")
|
print(f"Site: {args.site}")
|
||||||
print(f"Confidence threshold: {args.confidence}")
|
print(f"Confidence threshold: {args.confidence}")
|
||||||
|
if args.strict:
|
||||||
|
print(f"Strict mode: Yes (exact match only)")
|
||||||
|
|
||||||
stats = app.category_apply(
|
stats = app.category_apply(
|
||||||
proposals_csv=proposals_csv,
|
proposals_csv=proposals_csv,
|
||||||
site_name=args.site,
|
site_name=args.site,
|
||||||
confidence=args.confidence,
|
confidence=args.confidence,
|
||||||
|
strict=args.strict,
|
||||||
dry_run=False
|
dry_run=False
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -307,6 +313,7 @@ Options:
|
|||||||
--confidence, -c Confidence threshold: High, Medium, Low
|
--confidence, -c Confidence threshold: High, Medium, Low
|
||||||
--site, -s WordPress site: mistergeek.net, webscroll.fr, hellogeek.net
|
--site, -s WordPress site: mistergeek.net, webscroll.fr, hellogeek.net
|
||||||
--description, -d Category description
|
--description, -d Category description
|
||||||
|
--strict Strict confidence matching (exact match only, not "or better")
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
seo export
|
seo export
|
||||||
|
|||||||
Reference in New Issue
Block a user