SmartPaper / config.py
GuXiaopeng's picture
P0-R7-D-R2 research-material-only reliability closure (#148)
d28ed33
Raw History Blame Contribute Delete
43.6 kB
# -*- coding: utf-8 -*-
import os
import json
def _provider_fallbacks(env_name):
return [part.strip().lower() for part in str(os.environ.get(env_name, "") or "").split(",") if part.strip()]
def _optional_plan_range(prefix):
raw_min = str(os.environ.get(f"{prefix}_WORD_MIN", "") or "").strip()
raw_max = str(os.environ.get(f"{prefix}_WORD_MAX", "") or "").strip()
if not raw_min or not raw_max:
return None
try:
lo, hi = int(raw_min), int(raw_max)
except ValueError:
return None
return [min(lo, hi), max(lo, hi)]
def _plan_model_routes(prefix):
raw = str(os.environ.get(f"{prefix}_MODEL_ROUTES_JSON", "") or "").strip()
if not raw:
return {}
try:
parsed = json.loads(raw)
except Exception:
return {}
return dict(parsed) if isinstance(parsed, dict) else {}
def load_config():
base_config = {
# --- 基础运行参数 ---
"lit_target_papers": int(os.environ.get("LIT_TARGET_PAPERS", "80")),
"lit_per_page": int(os.environ.get("LIT_PER_PAGE", "100")),
"lit_max_workers": int(os.environ.get("LIT_MAX_WORKERS", "5")),
# R3.2.8.2: OpenAlex is primary; Semantic Scholar is a bounded
# authenticated auxiliary source. Every S2 HTTP attempt across all
# endpoints must share one >=1 RPS gate.
"s2_min_interval_seconds": max(1.0, float(os.environ.get("S2_MIN_INTERVAL_SECONDS", "1.10"))),
"s2_result_limit": max(1, min(50, int(os.environ.get("S2_RESULT_LIMIT", "20")))),
"s2_max_logical_searches": max(1, min(6, int(os.environ.get("S2_MAX_LOGICAL_SEARCHES", "3")))),
"citation_planner_batch_size": max(8, min(24, int(os.environ.get("CITATION_PLANNER_BATCH_SIZE", "18")))),
"citation_planner_max_tokens": max(1200, min(3200, int(os.environ.get("CITATION_PLANNER_MAX_TOKENS", "2200")))),
# R14-TQ2-PQ1-R4-R1: pre-draft reasoning is bounded and observable.
# These are diagnostic SLA budgets, not manuscript-failure authorities.
"prewrite_reasoning_max_tokens": {
"literature_synthesis": max(1200, min(3200, int(os.environ.get("PREWRITE_SYNTHESIS_REASONING_MAX_TOKENS", "2400")))),
"qualitative_packet": max(1200, min(3200, int(os.environ.get("PREWRITE_QUAL_PACKET_REASONING_MAX_TOKENS", "2400")))),
},
"prewrite_sla_seconds": {
"literature_synthesis": max(30, int(os.environ.get("PREWRITE_SYNTHESIS_SLA_SECONDS", "90"))),
"research_logic": max(15, int(os.environ.get("PREWRITE_RESEARCH_LOGIC_SLA_SECONDS", "30"))),
"qualitative_packet": max(30, int(os.environ.get("PREWRITE_QUAL_PACKET_SLA_SECONDS", "75"))),
},
"chunk_words_default": int(os.environ.get("CHUNK_WORDS_DEFAULT", "1500")),
"target_words_min": 5000,
"target_words_default": 5000,
"target_words_max": 20000,
"search_max_retries": max(1, int(os.environ.get("SEARCH_MAX_RETRIES", "4"))),
"translation_batch_tokens": max(800, int(os.environ.get("TRANSLATION_BATCH_TOKENS", "2500"))),
"translation_glossary_term_limit": max(10, int(os.environ.get("TRANSLATION_GLOSSARY_TERM_LIMIT", "40"))),
"translation_min_coverage_ratio": float(os.environ.get("TRANSLATION_MIN_COVERAGE_RATIO", "0.25")),
"translation_min_block_ratio_zh": float(os.environ.get("TRANSLATION_MIN_BLOCK_RATIO_ZH", "0.28")),
"translation_min_block_ratio_cyrillic": float(os.environ.get("TRANSLATION_MIN_BLOCK_RATIO_CYRILLIC", "0.65")),
"translation_max_block_ratio": float(os.environ.get("TRANSLATION_MAX_BLOCK_RATIO", "2.20")),
"openalex_email": os.environ.get("OPENALEX_EMAIL", "").strip(),
# --- RAG 与解析配置 ---
"rag_chunk_size": int(os.environ.get("RAG_CHUNK_SIZE", "3000")),
"rag_top_k": int(os.environ.get("RAG_TOP_K", "3")),
"max_extract_chars": int(os.environ.get("MAX_EXTRACT_CHARS", "150000")),
# P0-R7-E1: research-material-only upload policy. File type is owned
# by the selected Research Design capability; app.py owns no format or
# count business literals.
"research_material_upload_policy": {
"version": os.environ.get(
"SMARTPAPER_RESEARCH_MATERIAL_UPLOAD_POLICY_VERSION",
"research-material-upload-policy-v2-template-strict",
).strip() or "research-material-upload-policy-v2-template-strict",
"research_material_file_limit": max(
1,
min(100, int(os.environ.get("SMARTPAPER_RESEARCH_MATERIAL_FILE_LIMIT", "10"))),
),
# P0-R7-E1-R2: application-level byte gates are policy-driven and
# evaluated before any strict parser reads user content.
"research_material_file_max_bytes": max(
1024,
int(os.environ.get("SMARTPAPER_RESEARCH_MATERIAL_FILE_MAX_BYTES", str(2 * 1024 * 1024))),
),
"research_material_total_max_bytes": max(
1024,
int(os.environ.get("SMARTPAPER_RESEARCH_MATERIAL_TOTAL_MAX_BYTES", str(10 * 1024 * 1024))),
),
# Preserve the existing qualitative engine's >100-character
# user-evidence threshold without duplicating it in UI code.
"qualitative_min_combined_chars": max(
1,
int(os.environ.get("SMARTPAPER_QUALITATIVE_MIN_USER_MATERIAL_CHARS", "101")),
),
"quantitative_bundle_max_chars": max(
1000,
int(os.environ.get("SMARTPAPER_QUANTITATIVE_RESEARCH_BUNDLE_MAX_CHARS", "20000")),
),
"qualitative_bundle_max_chars": max(
1000,
int(os.environ.get("SMARTPAPER_QUALITATIVE_RESEARCH_BUNDLE_MAX_CHARS", os.environ.get("MAX_EXTRACT_CHARS", "150000"))),
),
},
# Model requests may legitimately run longer than one Worker lease.
# The independent Executor renews authority continuously; model-token
# activity is observability only and never the liveness authority.
"api_timeouts": {
"standard": (15, 70),
"stream": (15, 70),
"search": 15
},
"deepseek_stream_idle_seconds": max(
20,
min(65, int(os.environ.get("DEEPSEEK_STREAM_IDLE_SECONDS", "60"))),
),
# --- API 节点配置 ---
"deepseek_api_url": os.environ.get(
"DEEPSEEK_API_URL",
"https://api.deepseek.com/chat/completions",
),
# Model names are centralized here and can be upgraded in HF Variables.
# Application and engine code select a task role, never a concrete model.
"deepseek_models": {
"reasoning": os.environ.get(
"DEEPSEEK_MODEL_REASONING",
"deepseek-v4-pro",
),
"writing": os.environ.get(
"DEEPSEEK_MODEL_WRITING",
"deepseek-v4-pro",
),
"translation": os.environ.get(
"DEEPSEEK_MODEL_TRANSLATION",
"deepseek-v4-pro",
),
"fast": os.environ.get(
"DEEPSEEK_MODEL_FAST",
"deepseek-v4-flash",
),
"fallback": os.environ.get(
"DEEPSEEK_MODEL_FALLBACK",
"deepseek-v4-flash",
),
},
"deepseek_task_settings": {
"reasoning": {
"thinking": True,
"reasoning_effort": os.environ.get(
"DEEPSEEK_REASONING_EFFORT",
"high",
),
"allow_fallback": False,
},
"writing": {
"thinking": False,
"reasoning_effort": "high",
"allow_fallback": False,
},
"translation": {
"thinking": False,
"reasoning_effort": "high",
"allow_fallback": False,
},
"fast": {
"thinking": False,
"reasoning_effort": "low",
"allow_fallback": True,
},
},
"deepseek_max_retries": int(
os.environ.get("DEEPSEEK_MAX_RETRIES", "3")
),
"deepseek_show_reasoning": os.environ.get(
"DEEPSEEK_SHOW_REASONING",
"false",
).strip().lower() in {"1", "true", "yes", "on"},
# A2: provider-neutral routing seam. Academic code requests capabilities;
# this table decides which provider adapter owns each capability. The
# current verified production route remains DeepSeek until a trusted plan
# policy explicitly selects another registered provider.
"model_gateway": {
"default_provider": os.environ.get("MODEL_PROVIDER_DEFAULT", "deepseek").strip().lower(),
"capability_routes": {
"reasoning": {"provider": os.environ.get("MODEL_PROVIDER_REASONING", "deepseek"), "provider_role": "reasoning", "fallback_providers": _provider_fallbacks("MODEL_PROVIDER_REASONING_FALLBACKS")},
"writing": {"provider": os.environ.get("MODEL_PROVIDER_WRITING", "deepseek"), "provider_role": "writing", "fallback_providers": _provider_fallbacks("MODEL_PROVIDER_WRITING_FALLBACKS")},
"translation": {"provider": os.environ.get("MODEL_PROVIDER_TRANSLATION", "deepseek"), "provider_role": "translation", "fallback_providers": _provider_fallbacks("MODEL_PROVIDER_TRANSLATION_FALLBACKS")},
"fast": {"provider": os.environ.get("MODEL_PROVIDER_FAST", "deepseek"), "provider_role": "fast", "fallback_providers": _provider_fallbacks("MODEL_PROVIDER_FAST_FALLBACKS")},
"repair": {"provider": os.environ.get("MODEL_PROVIDER_REPAIR", os.environ.get("MODEL_PROVIDER_REASONING", "deepseek")), "provider_role": "reasoning", "fallback_providers": _provider_fallbacks("MODEL_PROVIDER_REPAIR_FALLBACKS")},
"final_review": {"provider": os.environ.get("MODEL_PROVIDER_FINAL_REVIEW", os.environ.get("MODEL_PROVIDER_REASONING", "deepseek")), "provider_role": "reasoning", "fallback_providers": _provider_fallbacks("MODEL_PROVIDER_FINAL_REVIEW_FALLBACKS")},
},
},
# A2: content problems are recoverable by default. These budgets are
# model-policy inputs, not hard-coded academic business rules.
"adaptive_completion": {
"enabled": os.environ.get("ADAPTIVE_COMPLETION_ENABLED", "true").strip().lower() in {"1", "true", "yes", "on"},
"section_repair_passes": max(1, min(4, int(os.environ.get("ADAPTIVE_SECTION_REPAIR_PASSES", "2")))),
"front_matter_repair_passes": max(1, min(4, int(os.environ.get("ADAPTIVE_FRONT_MATTER_REPAIR_PASSES", "2")))),
"translation_fallback_passes": max(1, min(3, int(os.environ.get("ADAPTIVE_TRANSLATION_FALLBACK_PASSES", "1")))),
},
# A2 only freezes a policy interface. Worker/D1 payment and quota logic
# is intentionally unchanged. Concrete prices/entitlements remain
# backend-owned and can be revised without changing manuscript code.
"plan_policy_version": "plan-policy-v1",
"plan_policies": {
"legacy_current": {
"word_range": [5000, 20000],
"paper_limit": None,
"model_routes": {},
"repair_profile": "standard",
},
# A2 deliberately does not invent commercial tier limits. Concrete
# word ranges and provider routes are deployment policy, supplied by
# environment/backend configuration when those products are enabled.
"free": {
"word_range": _optional_plan_range("SMARTPAPER_PLAN_FREE"),
"paper_limit": None,
"model_routes": _plan_model_routes("SMARTPAPER_PLAN_FREE"),
"repair_profile": os.environ.get("SMARTPAPER_PLAN_FREE_REPAIR_PROFILE", "economy"),
},
"standard": {
"word_range": _optional_plan_range("SMARTPAPER_PLAN_STANDARD"),
"paper_limit": None,
"model_routes": _plan_model_routes("SMARTPAPER_PLAN_STANDARD"),
"repair_profile": os.environ.get("SMARTPAPER_PLAN_STANDARD_REPAIR_PROFILE", "standard"),
},
"flagship": {
"word_range": _optional_plan_range("SMARTPAPER_PLAN_FLAGSHIP"),
"paper_limit": None,
"model_routes": _plan_model_routes("SMARTPAPER_PLAN_FLAGSHIP"),
"repair_profile": os.environ.get("SMARTPAPER_PLAN_FLAGSHIP_REPAIR_PROFILE", "maximum"),
},
},
# Citation-semantic audit repairs only affected sentences. Technical
# failures fall back to deterministic single-source recovery and are
# recorded in the audit log instead of terminating the whole paper.
"citation_semantic_audit": {
"enabled": os.environ.get(
"CITATION_SEMANTIC_AUDIT_ENABLED",
"true",
).strip().lower() in {"1", "true", "yes", "on"},
"batch_size": max(
1,
int(os.environ.get("CITATION_SEMANTIC_BATCH_SIZE", "5")),
),
"candidate_limit": max(
3,
int(os.environ.get("CITATION_SEMANTIC_CANDIDATE_LIMIT", "10")),
),
"fail_closed": os.environ.get(
"CITATION_SEMANTIC_FAIL_CLOSED",
"false",
).strip().lower() in {"1", "true", "yes", "on"},
"technical_retries": max(
1,
int(os.environ.get("CITATION_SEMANTIC_TECHNICAL_RETRIES", "2")),
),
"json_repair_retries": max(
0,
int(os.environ.get("CITATION_SEMANTIC_JSON_REPAIR_RETRIES", "1")),
),
},
# R3-Free task execution runs outside Streamlit. The executor renews
# the Worker lease only while real Python/model progress is recent.
"executor_heartbeat_interval_seconds": max(
10,
int(os.environ.get("SMARTPAPER_EXECUTOR_HEARTBEAT_SECONDS", "15")),
),
"executor_activity_grace_seconds": max(
30,
int(os.environ.get("SMARTPAPER_EXECUTOR_ACTIVITY_GRACE_SECONDS", "45")),
),
"executor_bootstrap_timeout_seconds": max(
5,
int(os.environ.get("SMARTPAPER_EXECUTOR_BOOTSTRAP_TIMEOUT_SECONDS", "20")),
),
"executor_bootstrap_poll_ms": max(
50,
int(os.environ.get("SMARTPAPER_EXECUTOR_BOOTSTRAP_POLL_MS", "100")),
),
"manuscript_quality": {
"abstract_max_words": int(os.environ.get("ABSTRACT_MAX_WORDS", "200")),
"abstract_max_numeric_mentions": int(os.environ.get("ABSTRACT_MAX_NUMERIC_MENTIONS", "6")),
"forbidden_phrases": [
"delve into", "intricate", "paramount", "overarching",
"pivotal", "foster", "seamlessly", "multifaceted",
"beacon", "landscape", "underscore", "robust",
"firstly", "secondly", "moreover", "furthermore",
"in conclusion", "to summarize",
],
},
"openalex_api_url": os.environ.get("OPENALEX_API_URL", "https://api.openalex.org/works"),
"s2_api_url": os.environ.get("S2_API_URL", "https://api.semanticscholar.org/graph/v1"),
# --- UI 多语言标签 ---
"ui_labels": {
"中文": {"title": "📊 工商管理论文智能体", "btn_generate": "🚀 生成初稿", "btn_download": "📥 下载文件", "topic_label": "📝 论文名称", "keywords_label": "🔍 关键字", "words_label": "📏 目标总单词数 (5000-20000单词)", "success": "🎉 流水线推演完毕!双语文档已就绪。"},
"English": {"title": "📊 Business Administration Article Agent", "btn_generate": "🚀 Generate Draft", "btn_download": "📥 Download", "topic_label": "📝 Article Title", "keywords_label": "🔍 Keywords", "words_label": "📏 Target Word Count", "success": "🎉 Task complete!"},
"Русский": {"title": "📊 Агент статей по бизнес-администрированию", "btn_generate": "🚀 Черновик", "btn_download": "📥 Скачать", "topic_label": "📝 Тема", "keywords_label": "🔍 Ключевые слова", "words_label": "📏 Количество слов", "success": "🎉 Задача выполнена!"},
"Қазақша": {"title": "📊 Бизнес-басқару жөніндегі ғылыми мақала агенті", "btn_generate": "🚀 Жоба дайындау", "btn_download": "📥 Жүктеу", "topic_label": "📝 Мақала атауы", "keywords_label": "🔍 Түйін сөздер", "words_label": "📏 Мақсатты сөз саны", "success": "🎉 Тапсырма аяқталды!"}
},
"target_lang_map": {
"中文": "Simplified Chinese (简体中文)",
"English": "Simplified Chinese (简体中文)",
"Русский": "Russian (Русский)",
"Қазақша": "Kazakh (Қазақша)"
},
"workspace_dir": ".workspace",
"docx_styles": {
"font_name": "Times New Roman",
"font_size_pt": 12,
"code_font": "Courier New",
"code_size_pt": 11
},
"blacklists": {
"meta_sections": [
"abstract", "keyword", "keywords", "摘要", "关键词", "关键字",
"reference", "references", "reference list", "参考文献",
"acknowledgment", "acknowledgements", "致谢",
"аннотация", "ключевые слова", "аңдатпа", "түйіндеме",
"түйін сөздер", "түйінді сөздер", "кілт сөздер",
"appendix", "附录", "приложение", "қосымша"
]
},
# =====================================================================
# Canonical manuscript structures. Top-level titles are deterministic:
# the model may write content, but it may not rename, remove, or reorder
# required sections.
# =====================================================================
"amj_schema": [
{
"section_id": "introduction",
"section": "Introduction",
"weight": 0.11,
"subsections": [],
},
{
"section_id": "theory",
"section": "Theoretical Background and Hypotheses",
"weight": 0.25,
"subsections": [
{"subsection_id": "conceptual_background", "title": "Conceptual Background and Research Gap", "share": 0.23},
{"subsection_id": "theoretical_mechanisms", "title": "Theoretical Mechanisms", "share": 0.27},
{"subsection_id": "hypothesis_development", "title": "Hypothesis Development", "share": 0.35},
{"subsection_id": "integrated_model", "title": "Integrated Research Model", "share": 0.15},
],
},
{
"section_id": "methodology",
"section": "Methodology",
"weight": 0.19,
"subsections": [
{"subsection_id": "research_design", "title": "Research Design and Context", "share": 0.18},
{"subsection_id": "sample_data", "title": "Sample and Data Collection", "share": 0.20},
{"subsection_id": "measures", "title": "Measures and Construct Operationalization", "share": 0.25},
{"subsection_id": "analysis_strategy", "title": "Analytical Strategy", "share": 0.22},
{"subsection_id": "validity_bias", "title": "Validity, Bias, and Robustness Procedures", "share": 0.15},
],
},
{
"section_id": "results",
"section": "Results",
"weight": 0.17,
"subsections": [
{"subsection_id": "measurement_results", "title": "Descriptive Statistics and Measurement Assessment", "share": 0.34},
{"subsection_id": "hypothesis_results", "title": "Hypothesis and Association Tests", "share": 0.46},
{"subsection_id": "additional_results", "title": "Additional Analyses and Robustness Checks", "share": 0.20},
],
},
{
"section_id": "discussion",
"section": "Discussion",
"weight": 0.24,
"subsections": [
{"subsection_id": "interpretation", "title": "Interpretation of the Findings", "share": 0.30},
{"subsection_id": "theoretical_contributions", "title": "Theoretical Contributions", "share": 0.30},
{"subsection_id": "practical_implications", "title": "Practical Implications", "share": 0.20},
{"subsection_id": "limitations", "title": "Limitations and Future Research", "share": 0.20},
],
},
{
"section_id": "conclusion",
"section": "Conclusion",
"weight": 0.04,
"subsections": [],
},
],
"asq_schema": [
{
"section_id": "introduction",
"section": "Introduction",
"weight": 0.10,
"subsections": [],
},
{
"section_id": "theoretical_framing",
"section": "Theoretical Framing",
"weight": 0.15,
"subsections": [
{"subsection_id": "phenomenon_puzzle", "title": "Phenomenon and Theoretical Puzzle", "share": 0.35},
{"subsection_id": "conceptual_tension", "title": "Relevant Literature and Conceptual Tension", "share": 0.40},
{"subsection_id": "research_question", "title": "Research Question and Analytical Focus", "share": 0.25},
],
},
{
"section_id": "methods",
"section": "Research Setting and Methods",
"weight": 0.16,
"subsections": [
{"subsection_id": "research_setting", "title": "Research Setting", "share": 0.24},
{"subsection_id": "data_collection", "title": "Data Sources and Collection", "share": 0.28},
{"subsection_id": "analytic_procedure", "title": "Analytical Procedure", "share": 0.30},
{"subsection_id": "trustworthiness", "title": "Trustworthiness, Ethics, and Reflexivity", "share": 0.18},
],
},
{
"section_id": "findings",
"section": "Findings",
"weight": 0.34,
"dynamic_subsections": "qualitative_themes",
"subsections": [
{"subsection_id": "emergent_model", "title": "Emergent Process Model", "share": 0.18},
],
},
{
"section_id": "discussion",
"section": "Discussion",
"weight": 0.22,
"subsections": [
{"subsection_id": "interpretation", "title": "Interpretation of the Emergent Findings", "share": 0.30},
{"subsection_id": "theoretical_contributions", "title": "Theoretical Contributions", "share": 0.30},
{"subsection_id": "boundaries", "title": "Boundary Conditions and Transferability", "share": 0.20},
{"subsection_id": "practical_implications", "title": "Practical Implications", "share": 0.20},
],
},
{
"section_id": "conclusion",
"section": "Conclusion",
"weight": 0.03,
"subsections": [],
},
{
"section_id": "appendix",
"section": "Appendix: Data Structure and Evidence",
"weight": 0.0,
"exclude_from_word_budget": True,
"subsections": [],
},
],
"manuscript_validation": {
# Word counts are planning/quality diagnostics only. They must never
# independently fail an otherwise complete manuscript.
"minimum_total_ratio": 0.97,
"maximum_total_ratio": 1.03,
"total_short_notice_ratio": 0.70,
"total_topic_review_ratio": 0.50,
"minimum_section_words": 120,
"minimum_conclusion_words": 120,
"section_short_notice_ratio": 0.60,
"section_topic_review_ratio": 0.40,
"minimum_qualitative_themes": 3,
"minimum_qualitative_quotes": 8,
},
"word_budget": {
"front_matter_words": 220,
"target_min_ratio": 0.97,
"target_max_ratio": 1.03,
"section_min_ratio": 0.92,
"section_max_ratio": 1.08,
},
"evidence_integrity_contract": """[EVIDENCE & INTEGRITY CONTRACT]
1. Treat the frozen research evidence packet as the only source of truth for the study setting, sample, measures, qualitative material, analysis, numerical results, and empirical findings.
2. Retrieved literature may support external theoretical or methodological claims, but it must never be used as evidence for this study's own sample, coefficients, events, quotations, or findings.
3. Do not invent a country, organization, university, sample characteristic, instrument, software package, coefficient, p-value, confidence interval, R-squared, fit index, robustness test, interview count, quotation, event, or date that is absent from the frozen evidence.
4. Theoretical inference is allowed only when it is explicitly framed as interpretation rather than as a new empirical fact.
5. Causal language must match the design. Association, mediation estimates, temporal process evidence, and experimental identification are not interchangeable.
6. If evidence is absent, narrow the claim instead of filling the gap with a plausible detail.
""",
"section_reasoning_profiles": {
"amj": {
"introduction": "Move from an important management problem to a precise theoretical tension, show why the prevailing explanation is incomplete, state the research move, and preview the bounded contribution. Do not front-load results or generic importance claims.",
"theory": "Define constructs precisely, develop the mechanism step by step, identify boundaries only when supported, and derive hypotheses from the mechanism. Each paragraph must advance one theoretical job.",
"methodology": "Report frozen design facts, justify actual analytical choices, identify validity threats, and state only mitigations or robustness procedures that are present in the evidence packet.",
"results": "Report this study's empirical facts without literature decoration. State uncertainty and hypothesis implications. Do not interpret an association as causal identification.",
"discussion": "Start from a validated finding, compare it with the prior theoretical expectation, explain the mechanism or boundary that accounts for the pattern, and state the specific theoretical revision. Separate theoretical and practical implications.",
"conclusion": "Answer the research question and summarize the bounded theoretical change using only conclusions already established in Results and Discussion. Introduce no new evidence.",
},
"asq": {
"introduction": "Open with the organizational puzzle, establish why existing explanations are insufficient, state the research question, and preview the emergent theoretical payoff without pre-solving the puzzle.",
"theoretical_framing": "Use prior theory as sensitizing concepts and a source of tension. Define what remains unexplained without forcing hypotheses or predicting the findings.",
"methods": "Describe the frozen setting, data, and analytic design. Describe trustworthiness, ethics, or reflexivity procedures only when those procedures are explicitly present in the frozen Study Evidence Ledger; never infer or invent member checking, peer debriefing, audit trails, field journals, consent/approval procedures, positionality, or other study-owned procedures. The analytic method must match the selected qualitative design rather than default to Gioia.",
"findings": "Move from concrete episode, quotation, or observation to recurring pattern, temporal/process relationship, and emergent mechanism. Keep informant or field evidence central and include deviant evidence when available.",
"discussion": "Explain how the emergent mechanism changes, qualifies, or extends prior theory. Distinguish what is grounded in this setting from what may transfer beyond it.",
"conclusion": "Resolve the organizational puzzle and state the bounded theoretical contribution without introducing new data, quotations, or claims.",
"appendix": "Present the frozen data structure and evidence compactly. Do not use the appendix to add new claims to the manuscript argument.",
},
},
"journal_voice_profiles": {
"amj": "Use direct, theoretically dense, broadly intelligible management scholarship. Prefer precise verbs and explicit mechanisms over evaluative adjectives. Avoid contribution-counting templates, generic topic sentences, and repeated summaries.",
"asq": "Use coherent phenomenon-driven prose with concrete evidence, temporal continuity, and theoretical depth. Preserve one central argument; avoid formulaic contribution lists, decorative narration, and generic sensemaking language unsupported by the data.",
},
"top_journal_critic_profiles": {
"amj": ["management_problem", "theoretical_tension", "mechanism", "hypothesis_logic", "empirical_fidelity", "theoretical_contribution", "evidence_strength_wording", "citation_support", "concision"],
"asq": ["organizational_puzzle", "evidence_richness", "process_logic", "negative_or_deviant_evidence", "mechanism", "theory_data_fit", "theoretical_revision", "coherence"],
},
"prompt_templates": {
"meta_extract": """You are an expert academic data extractor. Read the provided text and extract the core metadata.
CRITICAL: You MUST output ONLY a valid JSON object. Do not include markdown formatting or explanations.
{
"paper_title": "<String: Exact title>",
"core_theory": "<String: Max 5 words, e.g., 'Social Exchange Theory'>",
"variables": {
"IV": "<String: Independent Variables>",
"DV": "<String: Dependent Variables>",
"Mediators": "<String or 'N/A'>",
"Moderators": "<String or 'N/A'>"
},
"methodology": {
"sample_size": "<Integer or 'N/A'>",
"context": "<String: Max 10 words, e.g., 'US Tech Industry'>",
"analysis_tool": "<String: e.g., 'SEM, PLS, OLS'>"
},
"key_findings": "<String: Strict ONE-SENTENCE summary using causal language only when the design identifies causality>",
"future_gaps": "<String: Explicit limitations or future directions>"
}""",
"synthesis_system": "You are a top-tier academic researcher in Business Administration.",
"synthesis_user": """Topic: {topic}{user_injection}
Literature Metadata:
<LIT_DATA>
{refs_text}
</LIT_DATA>
[SYNTHESIS MANDATE: THEMATIC INTEGRATION]
1. You MUST NOT summarize papers sequentially (e.g., "A found X. B found Y.").
2. Synthesize by THEME or THEORETICAL TENSION rather than paper-by-paper summaries.
3. Apply claim-specific citation: each sentence may contain at most one [CITE-XX] tag. Never group multiple sources in one parenthesis or sentence. If sources support different claims, use separate sentences; if they support the same claim, select the single most direct source.
4. Explicitly highlight theoretical conflicts or consensus.
5. Conclude by revealing a specific blind spot that necessitates our current research.
{directive}"""
}
}
# =====================================================================
# 定量引擎 (AMJ 风格) - 保持原样,极致严谨与假设推演
# =====================================================================
amj_prompts = {
"sys_academic_writer": """You are a senior management scholar preparing an AMJ-oriented quantitative manuscript. Prioritize theoretical importance, mechanism precision, empirical fidelity, and a clear bounded contribution over status language or stylistic display.
[CRITICAL LANGUAGE MANDATE]: You MUST generate all responses strictly in ACADEMIC ENGLISH. Even if the user provides topic, data, or context in Chinese or another language, your final output MUST be in English.
[ABSOLUTE ANTI-AI-TONE MANDATES]:
1. CRITICAL: NEVER use these cliché AI words: delve into, intricate, paramount, overarching, pivotal, foster, seamlessly, multifaceted, beacon, landscape, underscore, robust.
2. CRITICAL: NEVER use robotic transition phrases (e.g., Firstly, Moreover, Furthermore, In conclusion, To summarize). Use conceptual bridges instead.
3. NATURAL SYNTAX: Vary sentence structure only where the argument requires it. Avoid artificial short-long sentence alternation and repetitive templates.
4. ACADEMIC HEDGING: Use strategic hedging (e.g., 'This suggests a tendency toward X, bounded by Y').
5. NO SWEEPING GENERALIZATIONS: Every sentence must carry specific theoretical weight or empirical fact.
6. MECHANISM WITHOUT OVERCLAIMING: Articulate the theoretical mechanism precisely, but use causal wording only when the research design and frozen evidence justify causal identification.
7. ACADEMIC REGISTER: Follow CAR: Conciseness, Accuracy, and Rigor. Concepts must be explicit, hierarchy clear, and reasoning logically traceable. Word-count allocations are planning targets, not content quotas: never add repetition, unsupported claims, generic filler, or unnecessary detail merely to hit a target.
8. PROHIBITED RHETORIC: Never use metaphors, analogies, rhetorical questions, literary embellishment, or promotional claims.
9. ABSTRACT DISCIPLINE: In abstracts, report only the minimum numerical evidence needed to convey the main finding; do not crowd the abstract with coefficients or test statistics.
10. STRUCTURAL DISCIPLINE: Cover only the assigned section and subsection. Do not recreate earlier sections, invent alternative headings, or omit required analytical elements.
11. CLAIM-SPECIFIC CITATION: Each sentence may contain at most one [CITE-XX] tag. Never group multiple references in one parenthesis or sentence. Separate distinct source-supported claims into separate sentences; when sources support the same claim, retain only the single most direct source. Every cited sentence must express a claim directly supported by the cited source evidence.
""",
"deep_refinement_directive": "Produce a final, polished section ready for top-tier submission. Ensure flawless logical flow without meta-commentary. Apply claim-specific citation: use at most one [CITE-XX] tag per sentence, never combine sources in one parenthesis, and cite only the single most direct source when multiple sources support the same claim.\n[SELF-REFLECTION]: Before drafting, critically analyze common AI clichés related to this topic and actively suppress them in your output.",
"deep_synthesis_directive": "Structure this synthesis to expose a critical theoretical tension: Consensus vs Paradox, Competing Perspectives, Theoretical Blind Spot.",
"hypothesis_development_directive": "Develop only hypotheses justified by the frozen research design: define the focal constructs, establish the theoretical mechanism, state relevant boundary conditions only when supported, and phrase directional hypotheses without claiming causal identification beyond the design.",
"methodological_defense_directive": "Use defensive methodological precision. Report only frozen design facts; justify the analytical choices actually present; distinguish validity threats from mitigations; do not invent endogeneity tests, robustness checks, software, sample details, or statistics.",
"discussion_depth_directive": "Interpret the validated findings against prior theoretical expectations. Explain why the pattern matters, what mechanism or boundary it clarifies, and exactly which part of prior theory is extended, refined, bounded, or challenged. Do not manufacture counter-intuitive implications.",
"conclusion_anchor_directive": "Derive the conclusion only after the validated Results and Discussion. Restate the research answer, the bounded theoretical change, and the practical implication without introducing new evidence.",
"anchor_generation_directive": "Generate a PROVISIONAL RESEARCH LOGIC CONTRACT, not an expected result or conclusion. Identify the management problem, theoretical tension, research move, evidence boundaries, and questions the study may answer. Do not predict findings. Output only the contract.",
"empirical_data_logic": "Report only empirical values that appear in the frozen evidence packet. Preserve every coefficient, p-value, confidence interval, degree of freedom, effect size, sample count, and model statistic exactly. Never create a value because it would be statistically plausible.",
}
# =====================================================================
# 定性引擎 (ASQ 风格) - 聚焦现象描述、意义建构与语录引用
# =====================================================================
asq_prompts = {
"sys_academic_writer": """You are a senior qualitative management scholar preparing an ASQ-oriented manuscript. The manuscript must be phenomenon-driven, evidence-rich, theoretically consequential, and organized around one central organizational puzzle rather than a generic topic.
[CRITICAL LANGUAGE MANDATE]: You MUST generate all responses strictly in ACADEMIC ENGLISH.
[ABSOLUTE ASQ MANDATES]:
1. FOCUS ON THE PUZZLE: Identify the organizational puzzle or theoretical tension that is actually supported by the frozen evidence. Do not manufacture a paradox merely to make the paper sound surprising.
2. EVIDENCE-RICH DESCRIPTION: Ground claims in concrete setting, event, actor, quotation, comparison, and temporal detail only when those elements exist in the frozen evidence. Do not add decorative or invented description.
3. ACTOR/PROCESS LOGIC: Follow interpretation, action, coordination, sequence, comparison, or change as the selected analytic design and evidence warrant. Do not force a sensemaking lens onto every qualitative study.
4. NO FORMAL HYPOTHESES: Do not use formal hypothesis testing. Use a research question, process/model explanation, or propositions only when the selected qualitative design and evidence warrant them.
5. NO AI CLICHES: Strictly avoid 'delve', 'tapestry', 'multifaceted', 'beacon', 'landscape'.
6. ACADEMIC REGISTER: Follow CAR: Conciseness, Accuracy, and Rigor, with explicit concepts and logically ordered claims. Word-count allocations are planning targets, not content quotas: never add repetition, unsupported claims, generic filler, or unnecessary detail merely to hit a target.
7. PROHIBITED RHETORIC: Never use metaphors, analogies, rhetorical questions, literary embellishment, or promotional claims. Use concrete evidence-based description rather than decorative prose.
8. ABSTRACT DISCIPLINE: Keep numerical details to the minimum needed to communicate the empirical puzzle, main finding, and contribution.
9. CLAIM-SPECIFIC CITATION: Each sentence may contain at most one [CITE-XX] tag. Never group multiple references in one parenthesis or sentence. Separate distinct source-supported claims into separate sentences; when sources support the same claim, retain only the single most direct source. Every cited sentence must express a claim directly supported by the cited source evidence.""",
"deep_refinement_directive": "Ensure logical flow and focus on the emergent theoretical model. Write in continuous, engaging paragraphs. Apply claim-specific citation: use at most one [CITE-XX] tag per sentence, never combine sources in one parenthesis, and cite only the single most direct source when several sources support the same claim.",
"deep_synthesis_directive": "Structure this synthesis to highlight a critical empirical puzzle or theoretical paradox that qualitative investigation can unravel.",
"hypothesis_development_directive": "Develop the theoretical framing. DO NOT use formal hypotheses. Detail the conceptual gaps and frame the overarching research questions or theoretical propositions.",
"methodological_defense_directive": "Describe only the frozen research setting, actor/data-source relations, data, analytic design, and explicitly frozen study procedures. Explain the analytic design actually selected for this study (for example process analysis, comparative case logic, grounded-theory/Gioia-style coding when appropriate). Discuss trustworthiness, ethics, or reflexivity as procedures actually performed only when the frozen Study Evidence Ledger explicitly records them; otherwise do not manufacture such procedures or convert general methodological best practice into a study-owned fact.",
"discussion_depth_directive": "Connect the emergent mechanism or process to prior theory. Show precisely what the evidence changes, qualifies, or newly explains, including negative or deviant evidence when present. Do not force a process-model contrast when the selected qualitative design does not support it.",
"conclusion_anchor_directive": "Derive the conclusion only after validated Findings and Discussion. Resolve the organizational puzzle and state the bounded theoretical change without introducing new evidence or forcing sensemaking language.",
"anchor_generation_directive": "Generate a PROVISIONAL RESEARCH LOGIC CONTRACT, not an expected finding or conclusion. Identify the organizational puzzle, sensitizing theoretical tension, evidence boundaries, and research question while leaving the empirical resolution open. Output only the contract.",
"empirical_data_logic": "Present findings through the selected qualitative analytic design. Integrate frozen representative quotations and other evidence where they directly substantiate a pattern, process, comparison, or mechanism. Do not impose Gioia-style first-order/second-order terminology unless that analytic design was explicitly selected.",
}
generic_prompts = amj_prompts.copy()
return base_config, amj_prompts, asq_prompts, generic_prompts
DEFAULT_CONFIG, AMJ_PROMPTS, ASQ_PROMPTS, GENERIC_PROMPTS = load_config()
APP_CONFIG = DEFAULT_CONFIG.copy()