TextDoctor / agents /reviewer_agent.py
FurqanIshaq's picture
Update agents/reviewer_agent.py
fa64aa5 verified
from typing import Dict, Any
class ReviewerAgent:
"""
Reviewer Agent
- Collects outputs from Grammar, Style, and Clarity agents
- Combines their confidence, number of changes, and readability
- Selects the best final output
- Returns a full explanation + candidate comparison
"""
def __init__(self):
pass
@staticmethod
def _length_score(text: str) -> float:
"""
Simple readability heuristic based on text length.
Penalizes texts that are too short or too long.
"""
words = text.split()
n = len(words)
if n == 0:
return 0.0
# Ideal range: 8–40 words
if n < 8:
return 0.4
if n > 40:
return 0.6
return 1.0
def review(
self,
original: str,
grammar_result: Dict[str, Any],
style_result: Dict[str, Any],
clarity_result: Dict[str, Any],
) -> Dict[str, Any]:
"""
Decide which version is best and explain the decision.
Returns:
{
"final_text": ...,
"candidates": [...],
"decision_explanation": "..."
}
"""
candidates = []
# -----------------------
# 1) Original Input
# -----------------------
orig_score = 0.3
candidates.append({
"name": "original",
"text": original,
"score": round(orig_score, 3),
"notes": "Raw user input; no improvements applied."
})
# -----------------------
# 2) Grammar Agent Output
# -----------------------
g_text = grammar_result["corrected"]
g_changes = len(grammar_result.get("changes", []))
g_conf = grammar_result.get("confidence", 0.7)
g_score = (0.4 * g_conf) + (0.3 + min(g_changes, 5) * 0.05)
g_score *= self._length_score(g_text)
candidates.append({
"name": "grammar",
"text": g_text,
"score": round(g_score, 3),
"notes": f"Grammar agent fixed {g_changes} issue(s)."
})
# -----------------------
# 3) Style Agent Output
# -----------------------
s_text = style_result["styled"]
s_changes = len(style_result.get("changes", []))
s_conf = style_result.get("confidence", 0.75)
s_score = (0.4 * s_conf) + (0.35 + min(s_changes, 5) * 0.04)
s_score *= self._length_score(s_text)
candidates.append({
"name": "style",
"text": s_text,
"score": round(s_score, 3),
"notes": f"Style agent applied {s_changes} improvements."
})
# -----------------------
# 4) Clarity Agent Output
# -----------------------
c_text = clarity_result["clarified"]
c_changes = len(clarity_result.get("changes", []))
c_conf = clarity_result.get("confidence", 0.8)
c_score = (0.4 * c_conf) + (0.4 + min(c_changes, 5) * 0.03)
c_score *= self._length_score(c_text)
candidates.append({
"name": "clarity",
"text": c_text,
"score": round(c_score, 3),
"notes": f"Clarity agent rewrote {c_changes} part(s) for readability."
})
# -----------------------
# Decide the winner
# -----------------------
best = max(candidates, key=lambda c: c["score"])
explanation = (
f"The reviewer selected the final output from the '{best['name']}' agent "
f"because it achieved the highest overall quality score ({best['score']}). "
"Scores are based on: (1) the agent’s confidence, (2) number of improvements, "
"(3) readability via length heuristic. This ensures the final text is "
"clear, professional, and client-ready."
)
return {
"final_text": best["text"],
"candidates": candidates,
"decision_explanation": explanation
}