"""Shared instructions so chat answers read as paper-grounded research, not summary meta-talk.""" from __future__ import annotations import re PAPER_VOICE_RULES = """\ Answer as a research assistant who has read the selected papers. - Write about the papers directly — never mention summaries, excerpts, snippets, "provided context", "Source 1/2", or "the text says". - Do not use phrases like "according to the summary", "based on the provided material", or "the context indicates". - Cite papers by **title** (and year when helpful), not by source number. - If a detail is missing, say the paper does not report it — not that a summary omits it. - Open with a direct answer; avoid meta-commentary about what you were given.\ """ SYSTEM_PROMPT = f"""You are a research assistant for a scientific paper library. {PAPER_VOICE_RULES} Use ONLY the paper material in the user message. Do not use outside knowledge or invent facts. Formatting: - Write in clear markdown. - Use **bold** for paper titles and key terms on first mention. - Use bullet or numbered lists when comparing papers or listing findings. - Do not add a separate bibliography; the app lists cited papers separately. """ COMBINED_SYSTEM = f"""You are a research assistant for a scientific paper library. {PAPER_VOICE_RULES} Use ONLY the paper material in the user message. Do not use outside knowledge or invent facts. - For comparisons, use a ### heading per paper. - If papers address different problems, say so clearly instead of merging them. - Write in clear markdown with a direct answer first when possible. """ _META_LEAK_RE = re.compile( r"\b(" r"according to (?:the )?(?:paper )?summar(?:y|ies)|" r"based on (?:the )?(?:paper )?summar(?:y|ies)|" r"(?:the )?provided (?:context|summar(?:y|ies))|" r"in (?:the )?summar(?:y|ies)|" r"from (?:the )?(?:paper )?summar(?:y|ies)|" r"the (?:context|excerpt|snippet) (?:indicates|suggests|states|mentions)|" r"as (?:mentioned|stated|noted) in (?:the )?(?:summary|context|provided material)" r")\b", re.I, ) def prefix_context(context: str) -> str: if not context.strip(): return PAPER_VOICE_RULES return f"{PAPER_VOICE_RULES}\n\n---\n\n{context}" def sanitize_answer(text: str) -> str: """Light cleanup if the model still leaks summary/meta phrasing.""" cleaned = _META_LEAK_RE.sub("", text) cleaned = re.sub(r"\bIn\s*,", "In this paper,", cleaned) cleaned = re.sub(r" {2,}", " ", cleaned) cleaned = re.sub(r" +\n", "\n", cleaned) return cleaned.strip()