Spaces:
Sleeping
Sleeping
| # core/aggregator.py | |
| # Combines BERT score + stylometric score into a final probability. | |
| from core.stylometrics import compute_stylometric_score | |
| from core.explainer import find_ai_phrases, generate_explanation | |
| from config.settings import settings | |
| def aggregate_scores( | |
| bert_result: dict, | |
| text: str, | |
| sentence_scores: list[dict], | |
| ) -> dict: | |
| """ | |
| Two-signal hybrid: | |
| - BERT (70%): neural, trained on Wikipedia pairs | |
| - Stylometrics (30%): model-agnostic structural features | |
| """ | |
| stylo_result = compute_stylometric_score(text) | |
| stylo_score = stylo_result["stylometric_ai_score"] | |
| bert_prob = bert_result["ai_probability"] | |
| bert_weight = 0.70 | |
| stylo_weight = 0.30 | |
| final_probability = ( | |
| bert_prob * bert_weight + | |
| stylo_score * stylo_weight | |
| ) | |
| final_probability = round(max(0.0, min(1.0, final_probability)), 4) | |
| ai_phrases = find_ai_phrases(text) | |
| explanation = generate_explanation( | |
| ai_probability=final_probability, | |
| stylometric_data=stylo_result, | |
| sentence_scores=sentence_scores, | |
| ai_phrases=ai_phrases, | |
| ) | |
| is_ai = final_probability >= settings.CONFIDENCE_THRESHOLD | |
| return { | |
| "ai_probability": final_probability, | |
| "is_ai": is_ai, | |
| "verdict": explanation["verdict"], | |
| "confidence_threshold": settings.CONFIDENCE_THRESHOLD, | |
| "scores": { | |
| "bert_score": bert_prob, | |
| "stylometric_score": round(stylo_score, 4), | |
| "bert_weight": bert_weight, | |
| "stylometric_weight": stylo_weight, | |
| }, | |
| "stylometric_features": stylo_result["features"], | |
| "sentence_scores": sentence_scores, | |
| "explanation": explanation, | |
| "chunks_analyzed": bert_result.get("chunks_analyzed", 1), | |
| } |