ComfyUI/custom_nodes/research/review_atomize.py
2026-04-12 18:10:46 +08:00

110 lines
3.9 KiB
Python

# custom_nodes/research/review_atomize.py
"""ReviewAtomize node - split review into atomic items."""
import json
import re
from typing_extensions import override
from comfy_api.latest import ComfyNode, io
class ReviewAtomize(io.ComfyNode):
"""Split review text into atomic feedback items."""
@classmethod
def define_schema(cls) -> io.Schema:
return io.Schema(
node_id="ReviewAtomize",
display_name="Atomize Review",
category="Research",
inputs=[
io.String.Input(
"raw_review",
display_name="Raw Review (JSON)",
default="{}",
multiline=True,
),
io.Int.Input(
"min_severity",
display_name="Min Severity to Extract",
default=1,
min=1,
max=3,
step=1,
),
],
outputs=[
io.String.Output(display_name="Review Items (JSON)"),
],
)
@classmethod
def execute(cls, raw_review: str, min_severity: int) -> io.NodeOutput:
try:
review = json.loads(raw_review) if raw_review else {}
except json.JSONDecodeError:
review = {"original_text": raw_review}
original_text = review.get("original_text", "")
paragraphs = review.get("paragraphs", [])
items = []
item_id = 1
# Common reviewer phrases that indicate feedback
feedback_patterns = [
(r"the (?:paper|method|approach|model|results?|experiments?) (?:is|are|should|could|may|might) (.+)", "methodology"),
(r"(?:it is|this is|there is) (?:not|rarely|insufficiently) (.+)", "gap"),
(r"(?:more|additional|further) (.+) (?:is|are) needed", "missing"),
(r"(?:unclear|confusing|vague|ambiguous) (.+)", "clarity"),
(r"(?:incorrect|inaccurate|wrong|error) (.+)", "error"),
(r"(?:major|significant|critical|important) (.+)", "major"),
(r"(?:minor|small|small) (.+)", "minor"),
(r"see (?:Section|Figure|Table) (\d+)", "reference"),
]
# Split by sentence and extract items
sentences = re.split(r'(?<=[.!?])\s+', original_text)
for sentence in sentences:
sentence = sentence.strip()
if len(sentence) < 20: # Skip very short sentences
continue
# Classify the item
item_type = "general"
severity = 1
sentence_lower = sentence.lower()
if any(w in sentence_lower for w in ["major", "significant", "critical", "important", "must"]):
severity = 3
item_type = "major_concern"
elif any(w in sentence_lower for w in ["minor", "small", "suggestion"]):
severity = 1
item_type = "suggestion"
elif any(w in sentence_lower for w in ["unclear", "confusing", "vague", "ambiguous"]):
severity = 2
item_type = "clarity"
elif any(w in sentence_lower for w in ["error", "incorrect", "wrong", "mistake"]):
severity = 3
item_type = "error"
elif any(w in sentence_lower for w in ["missing", "lacking", "insufficient", "not enough"]):
severity = 2
item_type = "missing_info"
if severity >= min_severity:
items.append({
"id": f"item_{item_id}",
"text": sentence,
"type": item_type,
"severity": severity,
"quoted_claims": [],
})
item_id += 1
result = {
"total_items": len(items),
"items": items,
}
return io.NodeOutput(review_items=json.dumps(result, indent=2))