This commit is contained in:
@@ -1,18 +1,15 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from datetime import timedelta
|
||||
from typing import Any
|
||||
|
||||
from django.db import transaction
|
||||
from django.utils import timezone
|
||||
|
||||
from apps.jobs.models import Application, Feedback, JobPosting, ScoreRun
|
||||
from apps.jobs.models import Feedback, JobPosting, ScoreRun
|
||||
from apps.jobs.services.applications import apply_application_on_feedback
|
||||
from apps.profiles.models import SearchProfile
|
||||
from apps.profiles.services import apply_feedback_delta
|
||||
|
||||
|
||||
LEARNING_MIN_SAMPLES = 2
|
||||
LEARNING_DELTA_BY_ACTION = {
|
||||
Feedback.Action.INTERESTING: 1.0,
|
||||
@@ -47,15 +44,21 @@ def _latest_score_run(profile: SearchProfile, job: JobPosting) -> ScoreRun | Non
|
||||
|
||||
|
||||
def _best_signal_feature(score_run: ScoreRun | None) -> str:
|
||||
if score_run is None:
|
||||
return "content"
|
||||
components = {
|
||||
key: value for key, value in (score_run.components or {}).items() if key in LEARNING_FEATURES
|
||||
key: value
|
||||
for key, value in (score_run.components or {}).items()
|
||||
if key in LEARNING_FEATURES
|
||||
}
|
||||
if not components:
|
||||
return "content"
|
||||
return max(components, key=components.get)
|
||||
|
||||
|
||||
def _classify_hide_signal(profile: SearchProfile, score_run: ScoreRun | None, reason: str) -> _LearningSignal:
|
||||
def _classify_hide_signal(
|
||||
profile: SearchProfile, score_run: ScoreRun | None, reason: str
|
||||
) -> _LearningSignal:
|
||||
normalized = _normalize_reason_text(reason)
|
||||
if not normalized:
|
||||
return _LearningSignal(
|
||||
@@ -71,7 +74,9 @@ def _classify_hide_signal(profile: SearchProfile, score_run: ScoreRun | None, re
|
||||
reason_code="non_learning_title",
|
||||
learnable=False,
|
||||
)
|
||||
if any(token in normalized for token in ("afstand", "afstands", "km", "locatie", "verplaatsing")):
|
||||
if any(
|
||||
token in normalized for token in ("afstand", "afstands", "km", "locatie", "verplaatsing")
|
||||
):
|
||||
return _LearningSignal(
|
||||
feature="",
|
||||
delta=0.0,
|
||||
@@ -128,7 +133,9 @@ def _learning_signal_count(profile: SearchProfile, feature: str) -> int:
|
||||
return count
|
||||
|
||||
|
||||
def _apply_learning_metadata(feedback: Feedback, signal: _LearningSignal, *, samples: int, applied: bool) -> None:
|
||||
def _apply_learning_metadata(
|
||||
feedback: Feedback, signal: _LearningSignal, *, samples: int, applied: bool
|
||||
) -> None:
|
||||
metadata: dict[str, Any] = dict(feedback.metadata or {})
|
||||
metadata["learning"] = {
|
||||
"status": "applied" if applied else "queued",
|
||||
@@ -187,7 +194,11 @@ def record_feedback(
|
||||
action=action,
|
||||
reason=reason[:200],
|
||||
)
|
||||
signal = _classify_learning_signal(profile=profile, job=job, action=action, reason=reason) if profile else None
|
||||
signal = (
|
||||
_classify_learning_signal(profile=profile, job=job, action=action, reason=reason)
|
||||
if profile
|
||||
else None
|
||||
)
|
||||
if signal:
|
||||
_evaluate_learning(profile=profile, feedback=feedback, signal=signal)
|
||||
if action == Feedback.Action.APPLIED:
|
||||
|
||||
Reference in New Issue
Block a user