コード例 #1
0
ファイル: advisor.py プロジェクト: bayesimpact/bob-emploi
def compute_actions_for_project(
    scoring_project: scoring.ScoringProject, ) -> Iterable[action_pb2.Action]:
    """Compute all actions possible for a project."""

    action_templates = {
        action.action_template_id: action
        for action in _ACTION_TEMPLATES.get_collection(
            scoring_project.database)
    }
    if scoring_project.user.features_enabled.all_modules:
        scores: Mapping[str, float] = {key: 3 for key in action_templates}
    else:
        scores = scoring_project.score_and_explain_all(
            (key, action_template.trigger_scoring_model)
            for key, action_template in action_templates.items()).scores
    sorted_action_templates = sorted(
        action_templates.values(),
        key=lambda m:
        (scores.get(m.action_template_id, 0), m.action_template_id),
        reverse=True)
    deployment = os.getenv('BOB_DEPLOYMENT', 'fr')
    for action_template in sorted_action_templates:
        action_id = action_template.action_template_id
        if not (score := scores.get(action_id)) or score <= 0:
            break
        scoring_project.details.actions.add(
            action_id=action_id,
            title=scoring_project.translate_airtable_string(
                'actionTemplates',
                action_id,
                'title',
                hint=action_template.title,
                is_genderized=True),
            short_description=scoring_project.translate_airtable_string(
                'actionTemplates',
                action_id,
                'short_description',
                hint=action_template.short_description,
                is_genderized=True),
            tags=[
                scoring_project.translate_airtable_string(
                    'actionTemplates', 'tags', tag)
                for tag in action_template.tags
            ],
            duration=action_template.duration,
            status=action_pb2.ACTION_UNREAD,
            advice_id=action_template.advice_id,
            resource_url=scoring_project.translate_airtable_string(
                'actionTemplates',
                action_id,
                'resource_url',
                hint=action_template.resource_url,
                context=deployment),
        )
コード例 #2
0
ファイル: advisor.py プロジェクト: bayesimpact/bob-emploi
def compute_available_methods(
        scoring_project: scoring.ScoringProject,
        method_modules: Iterable[advisor_pb2.AdviceModule],
        scoring_timeout_seconds: float = 3) \
        -> Iterator[Tuple[project_pb2.Advice, frozenset[str]]]:
    """Advise on a user project.

    Args:
        scoring_project: the user's data.
        advice_modules: a list of modules, from which we want to derive the advices.
        scoring_timeout_seconds: how long we wait to compute each advice scoring model.
    Returns:
        an Iterator of recommendations, each with a list of fields that would help improve
        the process.
    """

    ready_modules = {
        module.advice_id: module.trigger_scoring_model
        for module in method_modules
        if module.is_ready_for_prod or scoring_project.features_enabled.alpha
    }

    scores: Mapping[str, float] = {}
    reasons: Mapping[str, tuple[str, ...]] = {}
    missing_fields: Mapping[str, frozenset[str]] = {}

    if scoring_project.user.features_enabled.all_modules:
        scores = {key: 3 for key in ready_modules}
    else:
        scores, reasons, missing_fields = scoring_project.score_and_explain_all(
            ready_modules.items(),
            scoring_timeout_seconds=scoring_timeout_seconds)

    modules = sorted(method_modules,
                     key=lambda m: (scores.get(m.advice_id, 0), m.advice_id),
                     reverse=True)
    incompatible_modules: Set[str] = set()
    has_module = False
    for module in modules:
        score = scores.get(module.advice_id)
        if not score:
            # We can break as others will have 0 score as well.
            break
        if module.airtable_id in incompatible_modules and \
                not scoring_project.user.features_enabled.all_modules:
            continue
        piece_of_advice = project_pb2.Advice(
            advice_id=module.advice_id,
            num_stars=score,
            is_for_alpha_only=not module.is_ready_for_prod)
        piece_of_advice.explanations.extend(
            scoring_project.populate_template(reason)
            for reason in reasons.get(module.advice_id, []))

        incompatible_modules.update(module.incompatible_advice_ids)

        _maybe_override_advice_data(piece_of_advice, module, scoring_project)
        has_module = True
        yield piece_of_advice, missing_fields.get(module.advice_id,
                                                  frozenset())

    if not has_module and method_modules:
        logging.warning(
            'We could not find *any* advice for a project:\nModules tried:\n"%s"\nProject:\n%s',
            '", "'.join(m.advice_id for m in method_modules), scoring_project)