e QA."""
 q_lower = question.lower()
 return any(p in q_lower for p in _SELF_REF_PHRASES)

def _count_citation_lines(answer: str) -> int:
 return sum(len(p.findall(answer)) for p in _CITATION_PATTERNS)

async def _api_call(client, system_prompt, user_prompt, cfg, section_id):
 for attempt in range(cfg.retry_attempts):
 try:
 response = await client.chat.completions.create(
 model=cfg.model,
 temperature=cfg.temperature,
 max_tokens=cfg.max_tokens_response,
 messages=[
 {"role": "system", "content": system_prompt},
 {"role": "user", "content": user_prompt},
 ],
 )
 raw = response.choices[0].message.content.strip()
 raw = re.sub(r'^(?:json)?\s', '', raw, flags=re.MULTILINE)
 raw = re.sub(r'\s$', '', raw, flags=re.MULTILINE)
 pairs = json.loads(raw)
 if not isinstance(pairs, list):
 raise ValueError("Response is not a JSON array")
 usage = response.usage
 usage_data = {
 "prompt_tokens": getattr(usage, "prompt_tokens", 0) or 0,
 "completion_tokens": getattr(usage, "completion_tokens", 0) or 0,
 "total_tokens": getattr(usage, "total_tokens", 0) or 0,
 }
 return pairs, usage_data
 except json.JSONDecodeError as e:
 logging.warning(f"JSON parse error [{section_id}] attempt {attempt+1}: { e}")
 await asyncio.sleep(cfg.retry_delay (attempt + 1))
 except Exception as e:
 logging.warning(f"API error [{section_id}] attempt {attempt+1}: {e}")
 await asyncio.sleep(cfg.retry_delay (attempt + 1))
 return None

def _distribute_tokens(total_tokens: int, n_items: int) -> list:
 if n_items 1:
 logging.warning(
 f"Filtered answer with multiple citation lines in [{section['chunk_id']}]"
 )
 continue

 if has_citation and citation_lines != 1:
 logging.warning(
 f"Filtered citation-flag mismatch in [{section['chunk_id']}]"
 )
 continue

 if (not has_citation) and citation_lines != 0:
 logging.warning(
 f"Filtered non-citation answer containing citation line in [{section['chunk_id']}]"
 )
 continue

 # Track question type diversity (soft warning only — don't drop)
 if question_type in seen_question_types:
 logging.debug(
 f"Duplicate question_type '{question_type}' in [{section['chunk_id']}]"
 )
 seen_question_types.add(question_type)

 records.append({
 "question": q,
 "answer": a,
 "has_citation": has_citation,
 "question_type": question_type,
 })

 # Require exactly requested pairs for stable downstream dataset shape.
 if len(records) != n_pairs:
 logging.warning(
 f"Invalid pair count [{section['chunk_id']}]: expected {n_pairs}, got {len(records)}"
 )
 return [], {
 "section_id": section["chunk_id"],
 "law_name": section["law_name"],
 "error": f"invalid_pair_count_expected_{n_pairs}_got_{len(records)}",
 }

 # Enforce exactly one citation flag in accepted records.
 if records:
 cited_idx = next((i for i, r in enumerate(records) if r.get("has_citation")), None)
 for r in records:
 r["has_citation"] = False
 records[cited_idx if cited_idx is not None else 0]["has_citation"] = True

 # Normalize answer text to match citation-flag policy.
 for i, r in enumerate(records):
 answer = r["answer"]
 if r["has_citation"]:
 if _count_citation_lines(answer) == 0:
 if section["language"] == "ne":
 answer += (
 "\n\n> 📌 कानूनी सन्दर्भ: "
 f"{section['law_name']}, {section.get('section_id', 'N/A')}"
 )
 else:
 answer += (
 "\n\n> 📌 Citation: "
 f"{section['law_name']}, {section.get('section_id', 'N/A')}"
 )
 else:
 lines = answer.splitlines()
 cleaned_lines = [
 ln for ln in lines if not any(p.search(ln) for p in _CITATION_PATTERNS)
 ]
 answer = "\n".join(cleaned_lines).strip()
 records[i]["answer"] = answer

 prompt_per_pair = _distribute_tokens(usage.get("prompt_tokens