Show code
!git clone --depth 1 https://github.com/ljk1228/RAAMoveDiscourse moves in research-article abstracts (8 moves)
What it is. Sentences from research-article abstracts, each labeled with one of 8 rhetorical moves (Background, Gap, Method, Purpose, Result, Conclusion, Contribution, Implication).
Difficulty of the labeling judgment: ★★★ — hard. Telling a Gap from Background needs rhetorical judgment.
License: CC BY 4.0
Cite: Liu et al. (2024), LREC-COLING. github.com/ljk1228/RAAMove
Every dataset in this course is reshaped into the same canonical schema so one notebook works for all of them:
The raw data, though, looks different every time. That difference is the lesson — half of building a gold standard is getting messy real data into a clean, consistent shape.
Clone the GitHub repository. The data is two JSON files (one per discipline area).
Each file is a list of objects with idx (which abstract), text (the sentence), and labels (a short move code, e.g. BAC).
Two decisions:
BAC→Background) and fit {id, text, label}.CODES = {"BAC": "Background", "GAP": "Gap", "MTD": "Method",
"PUR": "Purpose", "RST": "Result", "CLN": "Conclusion",
"CTN": "Contribution", "IMP": "Implication"}
rows = []
for fname in ["RAAMove/Intelligence.json", "RAAMove/Engineering.json"]:
with open(fname, encoding="utf-8") as f:
for r in json.load(f):
rows.append({"text": r["text"].strip(),
"label": CODES.get(r["labels"], r["labels"])})
print("combined sentences:", len(rows))Notice the classes are imbalanced — there are far more Method sentences than Implication. That is why we balance before testing.
We take 8 per move here (8 moves × 8 = 64 items).
# Build a small BALANCED gold set: an equal number of items per label.
# Balance matters so precision/recall/F1 and the confusion matrix are meaningful.
import random
from collections import defaultdict
PER_LABEL = 8 # how many items per label
random.seed(42) # fixed seed = same sample every run (reproducible)
by_label = defaultdict(list)
for item in rows:
by_label[item["label"]].append(item)
gold = []
for label in sorted(by_label):
bucket = by_label[label]
random.shuffle(bucket)
gold.extend(bucket[:PER_LABEL])
random.shuffle(gold)
gold = [{"id": i + 1, "text": x["text"], "label": x["label"]} for i, x in enumerate(gold)]
from collections import Counter
print("items:", len(gold), "| per label:", dict(Counter(x["label"] for x in gold)))You built raamove_moves.json. Use it in the Day 3 tutorial (replicating Kim & Lu).