Skip to content

Match Quality

matchminer_ai.matching.rerank

Match quality scoring helpers.

score_match_quality

score_match_quality(candidate_pairs: DataFrame, *, config: MMAIConfig | None = None, filter_low_quality: bool = True, return_metadata: bool = False) -> pd.DataFrame | tuple[pd.DataFrame, dict]

Evaluate the clinical match quality of each candidate patient-trial pair.

Parameters:

Name Type Description Default
candidate_pairs DataFrame

DataFrame of candidate patient-trial pairs.

Expected columns

patient_id : str Patient identifier. space_trial_id : str Trial-space identifier. cancer_history_summary : str Patient summary text. clinical_space_summary : str Trial clinical-space summary text.

required
config MMAIConfig

MMAI configuration containing match quality checker settings. Uses default preset when omitted.

None
filter_low_quality bool

If True, only return rows where match_quality_pass evaluates to True.

True
return_metadata bool

When True, also return a metadata dict containing the config snapshot and model metadata for this run.

False

Returns:

Type Description
DataFrame

Derived output table containing:

Columns

patient_id : str Patient identifier. space_trial_id : str Trial-space identifier. match_quality_score : float Model-generated confidence score for clinical match quality. match_quality_pass : bool Whether the match quality score meets the configured cutoff.

tuple[DataFrame, dict]

When return_metadata is True, returns the DataFrame plus a metadata dict.

Source code in src/matchminer_ai/matching/rerank.py
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
def score_match_quality(
    candidate_pairs: pd.DataFrame,
    *,
    config: MMAIConfig | None = None,
    filter_low_quality: bool = True,
    return_metadata: bool = False,
) -> pd.DataFrame | tuple[pd.DataFrame, dict]:
    """
    Evaluate the clinical match quality of each candidate patient-trial pair.

    Parameters
    ----------
    candidate_pairs : pd.DataFrame
        DataFrame of candidate patient-trial pairs.

        Expected columns
        ----------------
        patient_id : str
            Patient identifier.
        space_trial_id : str
            Trial-space identifier.
        cancer_history_summary : str
            Patient summary text.
        clinical_space_summary : str
            Trial clinical-space summary text.

    config : MMAIConfig, optional
        MMAI configuration containing match quality checker settings.
        Uses default preset when omitted.
    filter_low_quality : bool, default True
        If True, only return rows where ``match_quality_pass`` evaluates to True.
    return_metadata : bool, default False
        When True, also return a metadata dict containing the config snapshot
        and model metadata for this run.

    Returns
    -------
    pd.DataFrame
        Derived output table containing:

        Columns
        -------
        patient_id : str
            Patient identifier.
        space_trial_id : str
            Trial-space identifier.
        match_quality_score : float
            Model-generated confidence score for clinical match quality.
        match_quality_pass : bool
            Whether the match quality score meets the configured cutoff.
    tuple[pd.DataFrame, dict]
        When return_metadata is True, returns the DataFrame plus a metadata dict.
    """
    # Validate that candidate pair rows contain the text + ids needed for checker prompts.
    required = [
        "patient_id",
        "space_trial_id",
        "cancer_history_summary",
        "clinical_space_summary",
    ]
    missing = [col for col in required if col not in candidate_pairs.columns]
    if missing:
        raise ValueError(
            f"candidate_pairs is missing required columns: {', '.join(missing)}"
        )

    # Resolve run config and build checker prompts from the configured template.
    resolved_config = config or load_default_preset()
    checker_config = dict(resolved_config.raw.get("match_quality", {}))
    prompt_file = str(checker_config["prompt_file"]).strip()
    score_cutoff = float(checker_config.get("score_cutoff", 0.2))

    template = _load_match_quality_template(prompt_file)
    prompts = _build_match_quality_prompts(candidate_pairs, template=template)

    # Run the backend text-classification model over all prompts.
    predictions, model_metadata = run_checker(
        prompts,
        checker_config=checker_config,
        model_metadata_cache_dir=resolved_config.model_metadata_cache_dir,
    )

    if len(predictions) != len(candidate_pairs):
        raise ValueError(
            "Checker returned a different number of predictions than input rows."
        )

    # Convert model outputs into a compact, derived result table.
    output = candidate_pairs[["patient_id", "space_trial_id"]].copy()
    confidence_scores = [
        float(torch.sigmoid(torch.tensor(float(prediction["score"]))).item())
        for prediction in predictions
    ]
    output["match_quality_score"] = confidence_scores
    output["match_quality_pass"] = [
        score >= score_cutoff for score in confidence_scores
    ]

    # Optionally keep only matches that pass the quality threshold.
    if filter_low_quality:
        keep_rows = output["match_quality_pass"]
        output = output.loc[keep_rows].copy()
    output = output.reset_index(drop=True)

    # Optionally return metadata for reproducibility/debugging.
    if return_metadata:
        metadata_payload = {
            "package": package_metadata(),
            "config_snapshot": config_snapshot(resolved_config),
            "model_metadata": {
                "match_quality_checker": model_metadata,
            },
        }
        return output, metadata_payload
    return output

matchminer_ai.matching.llm_checks

LLM-based match quality and exclusion screening helpers.

score_match_quality_with_llm

score_match_quality_with_llm(candidate_pairs: DataFrame, *, config: 'MMAIConfig | None' = None, return_metadata: bool = False) -> pd.DataFrame | tuple[pd.DataFrame, dict]

Score candidate patient-trial matches with the configured LLM prompt.

Parameters:

Name Type Description Default
candidate_pairs DataFrame

DataFrame of candidate patient-trial pairs.

Expected columns

patient_id : str Patient identifier. space_trial_id : str Trial-space identifier. cancer_history_summary : str Patient summary text. clinical_space_summary : str Trial clinical-space summary text.

required
config MMAIConfig

MMAI configuration containing LLM match-quality checker settings. Uses default preset when omitted.

None
return_metadata bool

When True, also return a metadata dict containing the config snapshot and model metadata for this run.

False

Returns:

Type Description
DataFrame

Derived output table containing:

Columns

patient_id : str Patient identifier. space_trial_id : str Trial-space identifier. llm_match_quality_score : int Parsed LLM score from 0 to 5, or -1 when parsing failed. Debug Columns


llm_match_quality_answer_text : str Text the package treated as the LLM answer and used for parsing. Included only when debug_mode is true. llm_match_quality_reasoning_text : str Optional separate reasoning trace returned by the backend or extracted by the configured reasoning parser. Included only when debug_mode is true. llm_match_quality_parse_status : str Whether the package could parse the answer text. Values are parsed, parsed_fallback, or parse_failed. Included only when debug_mode is true.

tuple[DataFrame, dict]

When return_metadata is True, returns the DataFrame plus metadata.

Source code in src/matchminer_ai/matching/llm_checks.py
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
def score_match_quality_with_llm(
    candidate_pairs: pd.DataFrame,
    *,
    config: "MMAIConfig | None" = None,
    return_metadata: bool = False,
) -> pd.DataFrame | tuple[pd.DataFrame, dict]:
    """
    Score candidate patient-trial matches with the configured LLM prompt.

    Parameters
    ----------
    candidate_pairs : pd.DataFrame
        DataFrame of candidate patient-trial pairs.

        Expected columns
        ----------------
        patient_id : str
            Patient identifier.
        space_trial_id : str
            Trial-space identifier.
        cancer_history_summary : str
            Patient summary text.
        clinical_space_summary : str
            Trial clinical-space summary text.

    config : MMAIConfig, optional
        MMAI configuration containing LLM match-quality checker settings.
        Uses default preset when omitted.
    return_metadata : bool, default False
        When True, also return a metadata dict containing the config snapshot
        and model metadata for this run.

    Returns
    -------
    pd.DataFrame
        Derived output table containing:

        Columns
        -------
        patient_id : str
            Patient identifier.
        space_trial_id : str
            Trial-space identifier.
        llm_match_quality_score : int
            Parsed LLM score from 0 to 5, or -1 when parsing failed.
        Debug Columns
        -------------
        llm_match_quality_answer_text : str
            Text the package treated as the LLM answer and used for parsing.
            Included only when debug_mode is true.
        llm_match_quality_reasoning_text : str
            Optional separate reasoning trace returned by the backend or
            extracted by the configured reasoning parser. Included only when
            debug_mode is true.
        llm_match_quality_parse_status : str
            Whether the package could parse the answer text. Values are
            ``parsed``, ``parsed_fallback``, or ``parse_failed``. Included only
            when debug_mode is true.
    tuple[pd.DataFrame, dict]
        When return_metadata is True, returns the DataFrame plus metadata.
    """
    required = [
        "patient_id",
        "space_trial_id",
        "cancer_history_summary",
        "clinical_space_summary",
    ]
    missing = [col for col in required if col not in candidate_pairs.columns]
    if missing:
        raise ValueError(
            f"candidate_pairs is missing required columns: {', '.join(missing)}"
        )

    resolved_config = config or load_default_preset()
    llm_config = dict(resolved_config.llm_match_quality)
    prompt_template = _load_prompt_template(str(llm_config["prompt_file"]).strip())
    messages_list = [
        _build_messages(
            prompt_template.format(
                trial_summary=str(row["clinical_space_summary"]),
                patient_summary=str(row["cancer_history_summary"]),
            )
        )
        for _, row in candidate_pairs.iterrows()
    ]
    responses, reasonings, model_metadata = _run_llm_check(
        candidate_pairs,
        config=resolved_config,
        section_name="llm_match_quality",
        messages_list=messages_list,
    )
    parsed = [_parse_match_quality_score(response) for response in responses]

    output = candidate_pairs[["patient_id", "space_trial_id"]].copy()
    output["llm_match_quality_score"] = [score for score, _ in parsed]
    if resolved_config.debug_mode:
        output["llm_match_quality_answer_text"] = responses
        output["llm_match_quality_reasoning_text"] = reasonings
        output["llm_match_quality_parse_status"] = [
            parse_status for _, parse_status in parsed
        ]
    output = output.reset_index(drop=True)

    if return_metadata:
        metadata_payload = {
            "package": package_metadata(),
            "config_snapshot": config_snapshot(resolved_config),
            "model_metadata": {
                "llm_match_quality_checker": model_metadata,
            },
        }
        return output, metadata_payload
    return output