Spaces:
Running
Running
U1-R2C Two-Design Research UI Simplification
#128
by GuXiaopeng - opened
- app.py +27 -21
- core/advanced_method_registry.py +92 -116
- i18n.py +21 -83
app.py
CHANGED
|
@@ -795,11 +795,7 @@ def _process_pending_launch(lang_code: str) -> None:
|
|
| 795 |
):
|
| 796 |
st.session_state["sp_pending_launch"] = None
|
| 797 |
reason = str(preflight.get("block_reason") or "method_preflight_changed")
|
| 798 |
-
|
| 799 |
-
method_label = tr(lang_code, f"method_{resolved_family}")
|
| 800 |
-
st.warning(tr(lang_code, "method_not_supported", method=method_label))
|
| 801 |
-
else:
|
| 802 |
-
st.warning(tr(lang_code, "method_resolution_invalid"))
|
| 803 |
return
|
| 804 |
|
| 805 |
projection = get_product_ui_projection()
|
|
@@ -1506,24 +1502,30 @@ def render_workspace_controls(user):
|
|
| 1506 |
}
|
| 1507 |
method_signature = ""
|
| 1508 |
else:
|
| 1509 |
-
# U1-
|
| 1510 |
-
#
|
| 1511 |
-
#
|
| 1512 |
-
#
|
|
|
|
| 1513 |
auto_preflight, method_signature = _current_method_preflight(confirmed_method_family="")
|
| 1514 |
auto_family = str(auto_preflight.get("method_family") or "qualitative").strip().casefold()
|
| 1515 |
if auto_family not in METHOD_FAMILIES:
|
| 1516 |
auto_family = "qualitative"
|
|
|
|
| 1517 |
|
| 1518 |
stored = str(st.session_state.get("sp_method_confirmation") or "").strip().casefold()
|
| 1519 |
stored_sig = str(st.session_state.get("sp_method_confirmation_signature") or "").strip()
|
| 1520 |
-
selected_default =
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1521 |
|
| 1522 |
# A changed Title/Keywords signature invalidates a previous manual
|
| 1523 |
-
# override
|
| 1524 |
-
#
|
| 1525 |
selector_sig = str(st.session_state.get("sp_method_selector_signature") or "").strip()
|
| 1526 |
-
if selector_sig != method_signature:
|
| 1527 |
st.session_state["sp_method_confirmation"] = ""
|
| 1528 |
st.session_state["sp_method_confirmation_signature"] = ""
|
| 1529 |
st.session_state["sp_method_selector"] = auto_family
|
|
@@ -1538,10 +1540,14 @@ def render_workspace_controls(user):
|
|
| 1538 |
index=list(METHOD_FAMILIES).index(selected_default),
|
| 1539 |
format_func=lambda family: tr(lang_code, f"method_{family}"),
|
| 1540 |
key="sp_method_selector",
|
| 1541 |
-
disabled=active,
|
| 1542 |
)
|
| 1543 |
selected = str(selected or auto_family).strip().casefold()
|
| 1544 |
-
if
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1545 |
st.session_state["sp_method_confirmation"] = selected
|
| 1546 |
st.session_state["sp_method_confirmation_signature"] = method_signature
|
| 1547 |
else:
|
|
@@ -1560,8 +1566,11 @@ def render_workspace_controls(user):
|
|
| 1560 |
st.caption(tr(lang_code, "method_detection_explanation"))
|
| 1561 |
|
| 1562 |
block_reason = str(preflight.get("block_reason") or "")
|
| 1563 |
-
|
| 1564 |
-
|
|
|
|
|
|
|
|
|
|
| 1565 |
elif not active:
|
| 1566 |
st.info(tr(lang_code, "method_supported", method=method_label))
|
| 1567 |
|
|
@@ -1655,10 +1664,7 @@ def render_workspace_controls(user):
|
|
| 1655 |
)
|
| 1656 |
if not bool(click_preflight.get("can_start_generation")):
|
| 1657 |
reason = str(click_preflight.get("block_reason") or "")
|
| 1658 |
-
|
| 1659 |
-
st.warning(tr(lang_code, "method_not_supported", method=method_label))
|
| 1660 |
-
else:
|
| 1661 |
-
st.warning(tr(lang_code, "method_resolution_invalid"))
|
| 1662 |
else:
|
| 1663 |
resolved_family = str(click_preflight.get("method_family") or "").strip().casefold()
|
| 1664 |
resolved_mode = str(click_preflight.get("legacy_policy_lane") or "").strip().lower()
|
|
|
|
| 795 |
):
|
| 796 |
st.session_state["sp_pending_launch"] = None
|
| 797 |
reason = str(preflight.get("block_reason") or "method_preflight_changed")
|
| 798 |
+
st.warning(tr(lang_code, "method_resolution_invalid"))
|
|
|
|
|
|
|
|
|
|
|
|
|
| 799 |
return
|
| 800 |
|
| 801 |
projection = get_product_ui_projection()
|
|
|
|
| 1502 |
}
|
| 1503 |
method_signature = ""
|
| 1504 |
else:
|
| 1505 |
+
# U1-R2C: SmartPaper intentionally supports only two reader-visible
|
| 1506 |
+
# research designs. No cue defaults to qualitative. Specialized-method
|
| 1507 |
+
# cues (panel/meta/fsQCA/bibliometric-review) are advisory-only and pin
|
| 1508 |
+
# the current topic to the qualitative framework rather than exposing
|
| 1509 |
+
# or blocking on an unsupported method family.
|
| 1510 |
auto_preflight, method_signature = _current_method_preflight(confirmed_method_family="")
|
| 1511 |
auto_family = str(auto_preflight.get("method_family") or "qualitative").strip().casefold()
|
| 1512 |
if auto_family not in METHOD_FAMILIES:
|
| 1513 |
auto_family = "qualitative"
|
| 1514 |
+
specialized_redirect = bool((auto_preflight.get("resolution") or {}).get("specialized_method_detected"))
|
| 1515 |
|
| 1516 |
stored = str(st.session_state.get("sp_method_confirmation") or "").strip().casefold()
|
| 1517 |
stored_sig = str(st.session_state.get("sp_method_confirmation_signature") or "").strip()
|
| 1518 |
+
selected_default = (
|
| 1519 |
+
auto_family
|
| 1520 |
+
if specialized_redirect
|
| 1521 |
+
else (stored if stored_sig == method_signature and stored in METHOD_FAMILIES else auto_family)
|
| 1522 |
+
)
|
| 1523 |
|
| 1524 |
# A changed Title/Keywords signature invalidates a previous manual
|
| 1525 |
+
# override. Specialized topics also clear any prior override so they
|
| 1526 |
+
# cannot be silently converted into an ordinary survey manuscript.
|
| 1527 |
selector_sig = str(st.session_state.get("sp_method_selector_signature") or "").strip()
|
| 1528 |
+
if selector_sig != method_signature or specialized_redirect:
|
| 1529 |
st.session_state["sp_method_confirmation"] = ""
|
| 1530 |
st.session_state["sp_method_confirmation_signature"] = ""
|
| 1531 |
st.session_state["sp_method_selector"] = auto_family
|
|
|
|
| 1540 |
index=list(METHOD_FAMILIES).index(selected_default),
|
| 1541 |
format_func=lambda family: tr(lang_code, f"method_{family}"),
|
| 1542 |
key="sp_method_selector",
|
| 1543 |
+
disabled=active or specialized_redirect,
|
| 1544 |
)
|
| 1545 |
selected = str(selected or auto_family).strip().casefold()
|
| 1546 |
+
if specialized_redirect:
|
| 1547 |
+
selected = "qualitative"
|
| 1548 |
+
st.session_state["sp_method_confirmation"] = ""
|
| 1549 |
+
st.session_state["sp_method_confirmation_signature"] = ""
|
| 1550 |
+
elif selected != auto_family:
|
| 1551 |
st.session_state["sp_method_confirmation"] = selected
|
| 1552 |
st.session_state["sp_method_confirmation_signature"] = method_signature
|
| 1553 |
else:
|
|
|
|
| 1566 |
st.caption(tr(lang_code, "method_detection_explanation"))
|
| 1567 |
|
| 1568 |
block_reason = str(preflight.get("block_reason") or "")
|
| 1569 |
+
specialized_redirect = bool((preflight.get("resolution") or {}).get("specialized_method_detected"))
|
| 1570 |
+
if specialized_redirect and not active:
|
| 1571 |
+
st.warning(tr(lang_code, "specialized_method_redirect"))
|
| 1572 |
+
elif block_reason:
|
| 1573 |
+
st.warning(tr(lang_code, "method_resolution_invalid"))
|
| 1574 |
elif not active:
|
| 1575 |
st.info(tr(lang_code, "method_supported", method=method_label))
|
| 1576 |
|
|
|
|
| 1664 |
)
|
| 1665 |
if not bool(click_preflight.get("can_start_generation")):
|
| 1666 |
reason = str(click_preflight.get("block_reason") or "")
|
| 1667 |
+
st.warning(tr(lang_code, "method_resolution_invalid"))
|
|
|
|
|
|
|
|
|
|
| 1668 |
else:
|
| 1669 |
resolved_family = str(click_preflight.get("method_family") or "").strip().casefold()
|
| 1670 |
resolved_mode = str(click_preflight.get("legacy_policy_lane") or "").strip().lower()
|
core/advanced_method_registry.py
CHANGED
|
@@ -1,13 +1,14 @@
|
|
| 1 |
# -*- coding: utf-8 -*-
|
| 2 |
-
"""Deterministic
|
| 3 |
|
| 4 |
-
U1-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
|
|
|
| 11 |
"""
|
| 12 |
from __future__ import annotations
|
| 13 |
|
|
@@ -15,61 +16,34 @@ import os
|
|
| 15 |
import re
|
| 16 |
from typing import Any, Iterable
|
| 17 |
|
| 18 |
-
METHOD_RESOLVER_VERSION = "smartpaper-auto-method-resolver-
|
| 19 |
-
METHOD_CAPABILITY_REGISTRY_VERSION = "smartpaper-method-capability-registry-
|
| 20 |
|
|
|
|
|
|
|
| 21 |
METHOD_FAMILIES = (
|
| 22 |
-
"survey_path",
|
| 23 |
"qualitative",
|
| 24 |
-
"
|
| 25 |
-
"meta_analysis",
|
| 26 |
-
"panel_econometrics",
|
| 27 |
-
"bibliometric_integrative_review",
|
| 28 |
)
|
| 29 |
|
| 30 |
-
# Capability status is executable U1-R2 preflight authority. Advanced methods
|
| 31 |
-
# remain BLOCKED until their dedicated engines are implemented.
|
| 32 |
_METHOD_CAPABILITIES: dict[str, dict[str, Any]] = {
|
| 33 |
-
"survey_path": {
|
| 34 |
-
"legacy_policy_lane": "amj",
|
| 35 |
-
"capability_status": "production_supported",
|
| 36 |
-
"evidence_timing": "pre_literature",
|
| 37 |
-
"engine_family": "quantitative_engine",
|
| 38 |
-
},
|
| 39 |
"qualitative": {
|
| 40 |
"legacy_policy_lane": "asq",
|
| 41 |
"capability_status": "production_supported",
|
| 42 |
"evidence_timing": "pre_literature",
|
| 43 |
"engine_family": "qualitative_engine",
|
| 44 |
},
|
| 45 |
-
"
|
| 46 |
-
"legacy_policy_lane": "amj",
|
| 47 |
-
"capability_status": "blocked_pending_engine",
|
| 48 |
-
"evidence_timing": "pre_literature",
|
| 49 |
-
"engine_family": "fsqca_engine_pending",
|
| 50 |
-
},
|
| 51 |
-
"meta_analysis": {
|
| 52 |
-
"legacy_policy_lane": "amj",
|
| 53 |
-
"capability_status": "blocked_pending_engine",
|
| 54 |
-
"evidence_timing": "post_literature",
|
| 55 |
-
"engine_family": "meta_analysis_engine_pending",
|
| 56 |
-
},
|
| 57 |
-
"panel_econometrics": {
|
| 58 |
"legacy_policy_lane": "amj",
|
| 59 |
-
"capability_status": "
|
| 60 |
"evidence_timing": "pre_literature",
|
| 61 |
-
"engine_family": "
|
| 62 |
-
},
|
| 63 |
-
"bibliometric_integrative_review": {
|
| 64 |
-
"legacy_policy_lane": "amj",
|
| 65 |
-
"capability_status": "blocked_pending_engine",
|
| 66 |
-
"evidence_timing": "post_literature",
|
| 67 |
-
"engine_family": "review_engine_pending",
|
| 68 |
},
|
| 69 |
}
|
| 70 |
|
| 71 |
-
#
|
| 72 |
-
|
|
|
|
| 73 |
(
|
| 74 |
"fsqca",
|
| 75 |
(
|
|
@@ -84,19 +58,7 @@ _METHOD_PATTERNS: tuple[tuple[str, tuple[str, ...]], ...] = (
|
|
| 84 |
"meta_analysis",
|
| 85 |
(
|
| 86 |
r"\bmeta[- ]analysis\b", r"\bmeta[- ]analytic\b", r"\bmeta analysis\b",
|
| 87 |
-
r"元分析", r"荟萃分析",
|
| 88 |
-
r"мета[- ]?анализ", r"метааналитическ",
|
| 89 |
-
r"мета[- ]?талдау", r"метааналитикалық",
|
| 90 |
-
),
|
| 91 |
-
),
|
| 92 |
-
(
|
| 93 |
-
"bibliometric_integrative_review",
|
| 94 |
-
(
|
| 95 |
-
r"\bbibliometric\b", r"\bscience\s+mapping\b", r"\bco[- ]citation\b", r"\bco[- ]word\b",
|
| 96 |
-
r"\bintegrative\s+(?:theory\s+)?review\b", r"\btheory\s+review\b", r"\bsystematic\s+literature\s+review\b",
|
| 97 |
-
r"文献计量", r"科学知识图谱", r"共被引", r"共词", r"整合性(?:理论)?综述", r"系统性文献综述",
|
| 98 |
-
r"библиометр", r"научн\w*.{0,8}картирован", r"коцитирован", r"интегративн\w*.{0,8}обзор",
|
| 99 |
-
r"библиометр", r"ғылыми.{0,8}кар��алау", r"бірлескен.{0,8}дәйексөз", r"интегративті.{0,8}шолу",
|
| 100 |
),
|
| 101 |
),
|
| 102 |
(
|
|
@@ -105,10 +67,22 @@ _METHOD_PATTERNS: tuple[tuple[str, tuple[str, ...]], ...] = (
|
|
| 105 |
r"\bpanel\s+data\b", r"\bfirm[- ]year\b", r"\bentity\s+fixed\s+effects?\b", r"\bfixed\s+effects?\b",
|
| 106 |
r"\brandom\s+effects?\b", r"\bpanel\s+econometrics?\b", r"\btwo[- ]way\s+fixed\s+effects?\b",
|
| 107 |
r"面板数据", r"固定效应", r"双向固定效应", r"公司[-—– ]?年度",
|
| 108 |
-
r"панельн\w*.{0,8}данн", r"фиксированн\w*.{0,8}эффект",
|
| 109 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 110 |
),
|
| 111 |
),
|
|
|
|
|
|
|
|
|
|
| 112 |
(
|
| 113 |
"qualitative",
|
| 114 |
(
|
|
@@ -132,14 +106,6 @@ _METHOD_PATTERNS: tuple[tuple[str, tuple[str, ...]], ...] = (
|
|
| 132 |
),
|
| 133 |
)
|
| 134 |
|
| 135 |
-
_MATERIAL_NAME_PATTERNS: tuple[tuple[str, tuple[str, ...]], ...] = (
|
| 136 |
-
("fsqca", (r"fsqca", r"truth[-_ ]?table", r"calibrat", r"condition[-_ ]?outcome")),
|
| 137 |
-
("meta_analysis", (r"meta[-_ ]?analysis", r"effect[-_ ]?size", r"forest[-_ ]?plot", r"study[-_ ]?character")),
|
| 138 |
-
("bibliometric_integrative_review", (r"bibliometric", r"corpus", r"co[-_ ]?citation", r"co[-_ ]?word", r"openalex")),
|
| 139 |
-
("panel_econometrics", (r"panel", r"firm[-_ ]?year", r"entity[-_ ]?year", r"fixed[-_ ]?effect")),
|
| 140 |
-
("qualitative", (r"interview", r"transcript", r"field[-_ ]?note", r"focus[-_ ]?group", r"访谈", r"сұхбат", r"интервью")),
|
| 141 |
-
)
|
| 142 |
-
|
| 143 |
|
| 144 |
def _normalized_text(value: Any) -> str:
|
| 145 |
return re.sub(r"\s+", " ", str(value or "")).strip()
|
|
@@ -175,7 +141,7 @@ def _material_descriptors(materials: Iterable[Any] | None) -> list[dict[str, str
|
|
| 175 |
|
| 176 |
|
| 177 |
def method_capability(method_family: str) -> dict[str, Any]:
|
| 178 |
-
"""Return a copy of versioned capability metadata for one
|
| 179 |
family = str(method_family or "").strip().casefold()
|
| 180 |
row = dict(_METHOD_CAPABILITIES.get(family) or {})
|
| 181 |
if not row:
|
|
@@ -194,45 +160,57 @@ def method_capability(method_family: str) -> dict[str, Any]:
|
|
| 194 |
return row
|
| 195 |
|
| 196 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 197 |
def resolve_method_family(
|
| 198 |
title: Any,
|
| 199 |
keywords: Any,
|
| 200 |
*,
|
| 201 |
materials: Iterable[Any] | None = None,
|
| 202 |
) -> dict[str, Any]:
|
| 203 |
-
"""Resolve one
|
| 204 |
|
| 205 |
-
|
| 206 |
-
|
| 207 |
-
|
| 208 |
-
is selected as the non-blocking default.
|
| 209 |
"""
|
| 210 |
source_title = _normalized_text(title)
|
| 211 |
source_keywords = _keyword_items(keywords)
|
| 212 |
text = " ; ".join([source_title] + source_keywords)
|
| 213 |
-
|
| 214 |
-
hits: list[dict[str, Any]] = []
|
| 215 |
-
chosen = ""
|
| 216 |
-
for family, patterns in _METHOD_PATTERNS:
|
| 217 |
-
matched = [pattern for pattern in patterns if re.search(pattern, text, flags=re.I | re.UNICODE)]
|
| 218 |
-
if matched:
|
| 219 |
-
hits.append({"method_family": family, "source": "title_keywords", "match_count": len(matched)})
|
| 220 |
-
if not chosen:
|
| 221 |
-
chosen = family
|
| 222 |
-
|
| 223 |
descriptors = _material_descriptors(materials)
|
| 224 |
|
| 225 |
-
|
| 226 |
-
|
| 227 |
-
|
| 228 |
-
|
| 229 |
-
|
| 230 |
-
|
| 231 |
-
|
| 232 |
-
|
| 233 |
-
|
| 234 |
-
|
| 235 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 236 |
|
| 237 |
capability = method_capability(chosen)
|
| 238 |
return {
|
|
@@ -241,7 +219,10 @@ def resolve_method_family(
|
|
| 241 |
"method_family": chosen,
|
| 242 |
"confidence": confidence,
|
| 243 |
"reason_codes": reason_codes,
|
| 244 |
-
"title_keyword_hits":
|
|
|
|
|
|
|
|
|
|
| 245 |
"material_hint_families": [],
|
| 246 |
"material_count": len(descriptors),
|
| 247 |
"derived_policy_lane": capability.get("legacy_policy_lane"),
|
|
@@ -250,7 +231,7 @@ def resolve_method_family(
|
|
| 250 |
|
| 251 |
|
| 252 |
def compare_shadow_to_legacy_lane(resolution: dict[str, Any], selected_lane: Any) -> dict[str, Any]:
|
| 253 |
-
"""Compare
|
| 254 |
selected = str(selected_lane or "").strip().casefold()
|
| 255 |
derived = str((resolution or {}).get("derived_policy_lane") or "").strip().casefold()
|
| 256 |
return {
|
|
@@ -268,18 +249,19 @@ def resolve_generation_preflight(
|
|
| 268 |
materials: Iterable[Any] | None = None,
|
| 269 |
confirmed_method_family: Any = None,
|
| 270 |
) -> dict[str, Any]:
|
| 271 |
-
"""Resolve
|
| 272 |
|
| 273 |
-
|
| 274 |
-
|
| 275 |
-
|
| 276 |
-
|
| 277 |
"""
|
| 278 |
resolution = resolve_method_family(title, keywords, materials=materials)
|
| 279 |
-
family = str(resolution.get("method_family") or "").strip().casefold()
|
| 280 |
|
| 281 |
confirmed = str(confirmed_method_family or "").strip().casefold()
|
| 282 |
-
|
|
|
|
| 283 |
family = confirmed
|
| 284 |
capability = method_capability(family)
|
| 285 |
resolution = dict(resolution)
|
|
@@ -290,28 +272,22 @@ def resolve_generation_preflight(
|
|
| 290 |
"capability": capability,
|
| 291 |
"reason_codes": list(resolution.get("reason_codes") or []) + ["user_override_method_family"],
|
| 292 |
})
|
|
|
|
|
|
|
|
|
|
| 293 |
|
| 294 |
capability = method_capability(family)
|
| 295 |
lane = str(capability.get("legacy_policy_lane") or "").strip().casefold() or None
|
| 296 |
status = str(capability.get("capability_status") or "").strip().casefold()
|
| 297 |
-
if family not in METHOD_FAMILIES or not lane:
|
| 298 |
return {
|
| 299 |
"can_start_generation": False,
|
| 300 |
"block_reason": "method_resolution_invalid",
|
| 301 |
"resolution": resolution,
|
| 302 |
-
"method_family": family or "
|
| 303 |
"legacy_policy_lane": None,
|
| 304 |
"capability": capability,
|
| 305 |
}
|
| 306 |
-
if status != "production_supported":
|
| 307 |
-
return {
|
| 308 |
-
"can_start_generation": False,
|
| 309 |
-
"block_reason": "method_capability_blocked",
|
| 310 |
-
"resolution": resolution,
|
| 311 |
-
"method_family": family,
|
| 312 |
-
"legacy_policy_lane": lane,
|
| 313 |
-
"capability": capability,
|
| 314 |
-
}
|
| 315 |
return {
|
| 316 |
"can_start_generation": True,
|
| 317 |
"block_reason": "",
|
|
|
|
| 1 |
# -*- coding: utf-8 -*-
|
| 2 |
+
"""Deterministic two-design resolver and capability preflight for SmartPaper.
|
| 3 |
|
| 4 |
+
U1-R2C intentionally limits production research design to two supported paths:
|
| 5 |
+
qualitative research and survey-based quantitative research. Specialized cues
|
| 6 |
+
such as fsQCA, panel data/econometrics, meta-analysis, and bibliometric/review
|
| 7 |
+
methods are detected only to provide a reader-facing scope notice; they are not
|
| 8 |
+
exposed as selectable method families and are redirected to the qualitative
|
| 9 |
+
framework before task creation.
|
| 10 |
+
|
| 11 |
+
This module never selects providers/models and never rewrites Title/Keywords.
|
| 12 |
"""
|
| 13 |
from __future__ import annotations
|
| 14 |
|
|
|
|
| 16 |
import re
|
| 17 |
from typing import Any, Iterable
|
| 18 |
|
| 19 |
+
METHOD_RESOLVER_VERSION = "smartpaper-auto-method-resolver-v4"
|
| 20 |
+
METHOD_CAPABILITY_REGISTRY_VERSION = "smartpaper-method-capability-registry-v3"
|
| 21 |
|
| 22 |
+
# Reader-visible / task-owning method families. Order is intentional:
|
| 23 |
+
# qualitative is the product default and appears first in the selector.
|
| 24 |
METHOD_FAMILIES = (
|
|
|
|
| 25 |
"qualitative",
|
| 26 |
+
"survey_path",
|
|
|
|
|
|
|
|
|
|
| 27 |
)
|
| 28 |
|
|
|
|
|
|
|
| 29 |
_METHOD_CAPABILITIES: dict[str, dict[str, Any]] = {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
"qualitative": {
|
| 31 |
"legacy_policy_lane": "asq",
|
| 32 |
"capability_status": "production_supported",
|
| 33 |
"evidence_timing": "pre_literature",
|
| 34 |
"engine_family": "qualitative_engine",
|
| 35 |
},
|
| 36 |
+
"survey_path": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
"legacy_policy_lane": "amj",
|
| 38 |
+
"capability_status": "production_supported",
|
| 39 |
"evidence_timing": "pre_literature",
|
| 40 |
+
"engine_family": "quantitative_engine",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 41 |
},
|
| 42 |
}
|
| 43 |
|
| 44 |
+
# Specialized methods are deliberately NOT method families in U1-R2C. They
|
| 45 |
+
# are scope cues only. A hit triggers a notice and a qualitative fallback.
|
| 46 |
+
_SPECIALIZED_METHOD_PATTERNS: tuple[tuple[str, tuple[str, ...]], ...] = (
|
| 47 |
(
|
| 48 |
"fsqca",
|
| 49 |
(
|
|
|
|
| 58 |
"meta_analysis",
|
| 59 |
(
|
| 60 |
r"\bmeta[- ]analysis\b", r"\bmeta[- ]analytic\b", r"\bmeta analysis\b",
|
| 61 |
+
r"元分析", r"荟萃分析", r"мета[- ]?анализ", r"метааналитическ", r"мета[- ]?талдау", r"метааналитикалық",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 62 |
),
|
| 63 |
),
|
| 64 |
(
|
|
|
|
| 67 |
r"\bpanel\s+data\b", r"\bfirm[- ]year\b", r"\bentity\s+fixed\s+effects?\b", r"\bfixed\s+effects?\b",
|
| 68 |
r"\brandom\s+effects?\b", r"\bpanel\s+econometrics?\b", r"\btwo[- ]way\s+fixed\s+effects?\b",
|
| 69 |
r"面板数据", r"固定效应", r"双向固定效应", r"公司[-—– ]?年度",
|
| 70 |
+
r"панельн\w*.{0,8}данн", r"фиксированн\w*.{0,8}эффект", r"панельдік.{0,8}дерек", r"тұрақты.{0,8}әсер",
|
| 71 |
+
),
|
| 72 |
+
),
|
| 73 |
+
(
|
| 74 |
+
"bibliometric_review",
|
| 75 |
+
(
|
| 76 |
+
r"\bbibliometric\b", r"\bscience\s+mapping\b", r"\bco[- ]citation\b", r"\bco[- ]word\b",
|
| 77 |
+
r"\bintegrative\s+(?:theory\s+)?review\b", r"\btheory\s+review\b", r"\bsystematic\s+literature\s+review\b",
|
| 78 |
+
r"文献计量", r"科学知识图谱", r"共被引", r"共词", r"整合性(?:理论)?综述", r"系统性文献综述", r"文献综述",
|
| 79 |
+
r"библиометр", r"научн\w*.{0,8}картирован", r"коцитирован", r"интегративн\w*.{0,8}обзор", r"систематическ\w*.{0,8}обзор",
|
| 80 |
+
r"библиометр", r"ғылыми.{0,8}карталау", r"бірлескен.{0,8}дәйексөз", r"интегративті.{0,8}шолу", r"жүйелі.{0,8}әдебиет.{0,8}шолу",
|
| 81 |
),
|
| 82 |
),
|
| 83 |
+
)
|
| 84 |
+
|
| 85 |
+
_SUPPORTED_METHOD_PATTERNS: tuple[tuple[str, tuple[str, ...]], ...] = (
|
| 86 |
(
|
| 87 |
"qualitative",
|
| 88 |
(
|
|
|
|
| 106 |
),
|
| 107 |
)
|
| 108 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 109 |
|
| 110 |
def _normalized_text(value: Any) -> str:
|
| 111 |
return re.sub(r"\s+", " ", str(value or "")).strip()
|
|
|
|
| 141 |
|
| 142 |
|
| 143 |
def method_capability(method_family: str) -> dict[str, Any]:
|
| 144 |
+
"""Return a copy of versioned capability metadata for one supported family."""
|
| 145 |
family = str(method_family or "").strip().casefold()
|
| 146 |
row = dict(_METHOD_CAPABILITIES.get(family) or {})
|
| 147 |
if not row:
|
|
|
|
| 160 |
return row
|
| 161 |
|
| 162 |
|
| 163 |
+
def _pattern_hits(text: str, pattern_rows: tuple[tuple[str, tuple[str, ...]], ...]) -> list[dict[str, Any]]:
|
| 164 |
+
hits: list[dict[str, Any]] = []
|
| 165 |
+
for family, patterns in pattern_rows:
|
| 166 |
+
matched = [pattern for pattern in patterns if re.search(pattern, text, flags=re.I | re.UNICODE)]
|
| 167 |
+
if matched:
|
| 168 |
+
hits.append({"method_family": family, "source": "title_keywords", "match_count": len(matched)})
|
| 169 |
+
return hits
|
| 170 |
+
|
| 171 |
+
|
| 172 |
def resolve_method_family(
|
| 173 |
title: Any,
|
| 174 |
keywords: Any,
|
| 175 |
*,
|
| 176 |
materials: Iterable[Any] | None = None,
|
| 177 |
) -> dict[str, Any]:
|
| 178 |
+
"""Resolve one of SmartPaper's two supported production research designs.
|
| 179 |
|
| 180 |
+
Title + Keywords remain the design authority. Uploaded Research Materials
|
| 181 |
+
do not alter automatic design selection. Specialized-method cues are kept
|
| 182 |
+
only as an advisory classification and redirect to qualitative research.
|
|
|
|
| 183 |
"""
|
| 184 |
source_title = _normalized_text(title)
|
| 185 |
source_keywords = _keyword_items(keywords)
|
| 186 |
text = " ; ".join([source_title] + source_keywords)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 187 |
descriptors = _material_descriptors(materials)
|
| 188 |
|
| 189 |
+
specialized_hits = _pattern_hits(text, _SPECIALIZED_METHOD_PATTERNS)
|
| 190 |
+
if specialized_hits:
|
| 191 |
+
capability = method_capability("qualitative")
|
| 192 |
+
return {
|
| 193 |
+
"resolver_version": METHOD_RESOLVER_VERSION,
|
| 194 |
+
"shadow_only": False,
|
| 195 |
+
"method_family": "qualitative",
|
| 196 |
+
"confidence": "SPECIALIZED_METHOD_REDIRECT",
|
| 197 |
+
"reason_codes": ["specialized_method_cue_detected", "redirect_to_qualitative"],
|
| 198 |
+
"title_keyword_hits": [],
|
| 199 |
+
"specialized_method_detected": True,
|
| 200 |
+
"specialized_method_families": [row["method_family"] for row in specialized_hits],
|
| 201 |
+
"specialized_method_hits": specialized_hits,
|
| 202 |
+
"material_hint_families": [],
|
| 203 |
+
"material_count": len(descriptors),
|
| 204 |
+
"derived_policy_lane": capability.get("legacy_policy_lane"),
|
| 205 |
+
"capability": capability,
|
| 206 |
+
}
|
| 207 |
+
|
| 208 |
+
supported_hits = _pattern_hits(text, _SUPPORTED_METHOD_PATTERNS)
|
| 209 |
+
chosen = str((supported_hits[0] if supported_hits else {}).get("method_family") or "qualitative")
|
| 210 |
+
confidence = "AUTO_DETECTED" if supported_hits else "DEFAULT_QUALITATIVE"
|
| 211 |
+
reason_codes = ["explicit_title_keyword_method_cue"] if supported_hits else ["no_explicit_method_cue", "default_qualitative"]
|
| 212 |
+
if len(supported_hits) > 1:
|
| 213 |
+
reason_codes.append("lower_priority_method_cues_present")
|
| 214 |
|
| 215 |
capability = method_capability(chosen)
|
| 216 |
return {
|
|
|
|
| 219 |
"method_family": chosen,
|
| 220 |
"confidence": confidence,
|
| 221 |
"reason_codes": reason_codes,
|
| 222 |
+
"title_keyword_hits": supported_hits,
|
| 223 |
+
"specialized_method_detected": False,
|
| 224 |
+
"specialized_method_families": [],
|
| 225 |
+
"specialized_method_hits": [],
|
| 226 |
"material_hint_families": [],
|
| 227 |
"material_count": len(descriptors),
|
| 228 |
"derived_policy_lane": capability.get("legacy_policy_lane"),
|
|
|
|
| 231 |
|
| 232 |
|
| 233 |
def compare_shadow_to_legacy_lane(resolution: dict[str, Any], selected_lane: Any) -> dict[str, Any]:
|
| 234 |
+
"""Compare inferred design with a legacy AMJ/ASQ lane."""
|
| 235 |
selected = str(selected_lane or "").strip().casefold()
|
| 236 |
derived = str((resolution or {}).get("derived_policy_lane") or "").strip().casefold()
|
| 237 |
return {
|
|
|
|
| 249 |
materials: Iterable[Any] | None = None,
|
| 250 |
confirmed_method_family: Any = None,
|
| 251 |
) -> dict[str, Any]:
|
| 252 |
+
"""Resolve the two supported designs before any task/quota creation.
|
| 253 |
|
| 254 |
+
Manual adjustment is available only between qualitative and survey-based
|
| 255 |
+
quantitative research. Specialized-method cues intentionally pin the
|
| 256 |
+
current topic to the qualitative fallback so a user cannot silently turn a
|
| 257 |
+
panel/meta/fsQCA/review topic into an ordinary survey manuscript.
|
| 258 |
"""
|
| 259 |
resolution = resolve_method_family(title, keywords, materials=materials)
|
| 260 |
+
family = str(resolution.get("method_family") or "qualitative").strip().casefold()
|
| 261 |
|
| 262 |
confirmed = str(confirmed_method_family or "").strip().casefold()
|
| 263 |
+
specialized = bool(resolution.get("specialized_method_detected"))
|
| 264 |
+
if not specialized and confirmed in METHOD_FAMILIES and confirmed != family:
|
| 265 |
family = confirmed
|
| 266 |
capability = method_capability(family)
|
| 267 |
resolution = dict(resolution)
|
|
|
|
| 272 |
"capability": capability,
|
| 273 |
"reason_codes": list(resolution.get("reason_codes") or []) + ["user_override_method_family"],
|
| 274 |
})
|
| 275 |
+
elif specialized:
|
| 276 |
+
resolution = dict(resolution)
|
| 277 |
+
resolution["manual_override_locked"] = True
|
| 278 |
|
| 279 |
capability = method_capability(family)
|
| 280 |
lane = str(capability.get("legacy_policy_lane") or "").strip().casefold() or None
|
| 281 |
status = str(capability.get("capability_status") or "").strip().casefold()
|
| 282 |
+
if family not in METHOD_FAMILIES or not lane or status != "production_supported":
|
| 283 |
return {
|
| 284 |
"can_start_generation": False,
|
| 285 |
"block_reason": "method_resolution_invalid",
|
| 286 |
"resolution": resolution,
|
| 287 |
+
"method_family": family or "qualitative",
|
| 288 |
"legacy_policy_lane": None,
|
| 289 |
"capability": capability,
|
| 290 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 291 |
return {
|
| 292 |
"can_start_generation": True,
|
| 293 |
"block_reason": "",
|
i18n.py
CHANGED
|
@@ -276,35 +276,27 @@ TEXTS: dict[str, dict[str, str]] = {
|
|
| 276 |
"download_asq_template": "📥 一键下载 TXT 访谈模板",
|
| 277 |
"start_asq": "🚀 启动 ASQ 模式生成",
|
| 278 |
"research_materials_label": "研究资料(可选)",
|
| 279 |
-
"research_materials_help": "支持 PDF、TXT、DOC、DOCX、CSV、XLS、XLSX。上传资料用于辅助论文生成;研究设计仅根据论文题目和关键词
|
| 280 |
"drop_research_materials": "将研究资料拖到这里",
|
| 281 |
"limit_research_materials": "每个文件最大 1 GB · PDF, TXT, DOC, DOCX, CSV, XLS, XLSX",
|
| 282 |
"material_document_use_label": "如何使用上传的 PDF/DOC/DOCX 文件?",
|
| 283 |
"material_use_reference": "作为参考文献资料",
|
| 284 |
"material_use_research": "作为研究资料",
|
| 285 |
"detected_method_label": "研究设计(自动识别,可调整)",
|
| 286 |
-
"method_detection_explanation": "
|
| 287 |
"method_confirm_label": "调整研究设计",
|
| 288 |
"method_confirm_placeholder": "请选择研究设计",
|
| 289 |
"method_confirmation_required": "研究设计状态异常,请重新选择研究设计。",
|
| 290 |
"method_resolution_invalid": "研究设计状态异常,请重新选择研究设计。",
|
| 291 |
-
|
| 292 |
-
"
|
| 293 |
"method_undetermined": "质性研究(默认)",
|
| 294 |
"method_survey_path": "问卷量化研究",
|
| 295 |
"method_qualitative": "质性研究",
|
| 296 |
-
"method_fsqca": "模糊集定性比较分析(fsQCA)",
|
| 297 |
-
"method_meta_analysis": "元分析",
|
| 298 |
-
"method_panel_econometrics": "面板数据计量分析",
|
| 299 |
-
"method_bibliometric_integrative_review": "文献计量与整合性综述",
|
| 300 |
"adaptive_template_expander": "💡 推荐模板(可选)",
|
| 301 |
"download_research_template": "📥 下载研究资料模板",
|
| 302 |
"template_help_survey_path": "推荐使用变量或统计结果表。若未上传数据,系统会按项目规则生成用于初稿的辅助证据。",
|
| 303 |
"template_help_qualitative": "推荐使用访谈、田野记录或案例材料。若未上传资料,系统会构建匿名的初稿证据包。",
|
| 304 |
-
"template_help_fsqca": "推荐使用条件变量、结果变量及校准信息表。专用 fsQCA 引擎开放后将按此结构处理。",
|
| 305 |
-
"template_help_meta_analysis": "推荐使用研究层面的效应量提取表。真实论文身份与系统辅助效应量必须严格分离。",
|
| 306 |
-
"template_help_panel_econometrics": "推荐使用实体—时间面板数据表,例如企业—年度结构。",
|
| 307 |
-
"template_help_bibliometric_integrative_review": "推荐使用真实文献语料的题名、作者、年份、DOI、期刊和关键词等元数据。",
|
| 308 |
"template_help_undetermined": "确认研究设计后,系统将显示对应的研究资料模板。",
|
| 309 |
"start_generation_unified": "🚀 开始生成",
|
| 310 |
"api_key_missing": "❌ 缺少 DEEPSEEK_API_KEY,请配置API密钥。",
|
|
@@ -518,35 +510,27 @@ TEXTS: dict[str, dict[str, str]] = {
|
|
| 518 |
"download_asq_template": "📥 Download TXT Interview Template",
|
| 519 |
"start_asq": "🚀 Start ASQ Generation",
|
| 520 |
"research_materials_label": "Research Materials (Optional)",
|
| 521 |
-
"research_materials_help": "Supports PDF, TXT, DOC, DOCX, CSV, XLS, and XLSX. Uploaded files support paper generation; Research Design is identified from the Title and Keywords only.",
|
| 522 |
"drop_research_materials": "Drag research materials here",
|
| 523 |
"limit_research_materials": "Up to 1 GB per file · PDF, TXT, DOC, DOCX, CSV, XLS, XLSX",
|
| 524 |
"material_document_use_label": "How should SmartPaper use the uploaded PDF/DOC/DOCX files?",
|
| 525 |
"material_use_reference": "Use as reference literature",
|
| 526 |
"material_use_research": "Use as research materials",
|
| 527 |
"detected_method_label": "Research Design (Auto-detected, Adjustable)",
|
| 528 |
-
"method_detection_explanation": "
|
| 529 |
"method_confirm_label": "Adjust Research Design",
|
| 530 |
"method_confirm_placeholder": "Select a Research Design",
|
| 531 |
"method_confirmation_required": "The Research Design state is invalid. Please select a Research Design again.",
|
| 532 |
"method_resolution_invalid": "The Research Design state is invalid. Please select a Research Design again.",
|
| 533 |
-
|
| 534 |
-
"
|
| 535 |
"method_undetermined": "Qualitative Research (Default)",
|
| 536 |
"method_survey_path": "Survey-Based Quantitative Research",
|
| 537 |
"method_qualitative": "Qualitative Research",
|
| 538 |
-
"method_fsqca": "Fuzzy-Set Qualitative Comparative Analysis (fsQCA)",
|
| 539 |
-
"method_meta_analysis": "Meta-Analysis",
|
| 540 |
-
"method_panel_econometrics": "Panel Data Econometric Analysis",
|
| 541 |
-
"method_bibliometric_integrative_review": "Bibliometric Analysis and Integrative Literature Review",
|
| 542 |
"adaptive_template_expander": "💡 Recommended Template (Optional)",
|
| 543 |
"download_research_template": "📥 Download Research Materials Template",
|
| 544 |
"template_help_survey_path": "A variable-level or statistical-results table is recommended. If no data are uploaded, SmartPaper may construct draft evidence under the project provenance rules.",
|
| 545 |
"template_help_qualitative": "Interview, field-note, or case materials are recommended. If none are uploaded, SmartPaper may construct an anonymous draft evidence packet.",
|
| 546 |
-
"template_help_fsqca": "A table of conditions, outcomes, and calibration information is recommended. The dedicated fsQCA engine will use this structure once enabled.",
|
| 547 |
-
"template_help_meta_analysis": "A study-level effect-size extraction table is recommended. Real paper identities must remain separate from any system-assisted effect-size evidence.",
|
| 548 |
-
"template_help_panel_econometrics": "An entity-time panel table, such as a firm-year structure, is recommended.",
|
| 549 |
-
"template_help_bibliometric_integrative_review": "Use real-corpus metadata such as title, authors, year, DOI, venue, and keywords.",
|
| 550 |
"template_help_undetermined": "Confirm the research design to view the corresponding research-material template.",
|
| 551 |
"start_generation_unified": "🚀 Start Generation",
|
| 552 |
"api_key_missing": "❌ DEEPSEEK_API_KEY is missing. Configure the API key.",
|
|
@@ -760,35 +744,27 @@ TEXTS: dict[str, dict[str, str]] = {
|
|
| 760 |
"download_asq_template": "📥 Скачать TXT-шаблон интервью",
|
| 761 |
"start_asq": "🚀 Запустить формирование в режиме ASQ",
|
| 762 |
"research_materials_label": "Материалы исследования (необязательно)",
|
| 763 |
-
"research_materials_help": "Поддерживаются PDF, TXT, DOC, DOCX, CSV, XLS и XLSX. Загруженные файлы используются как дополнительные исследовательские или справ
|
| 764 |
"drop_research_materials": "Перетащите исследовательские материалы сюда",
|
| 765 |
"limit_research_materials": "До 1 ГБ на файл · PDF, TXT, DOC, DOCX, CSV, XLS, XLSX",
|
| 766 |
"material_document_use_label": "Как использовать загруженные файлы PDF/DOC/DOCX?",
|
| 767 |
"material_use_reference": "Как научные источники",
|
| 768 |
"material_use_research": "Как исследовательские материалы",
|
| 769 |
"detected_method_label": "Дизайн исследования (определяется автоматически, можно изменить)",
|
| 770 |
-
"method_detection_explanation": "
|
| 771 |
"method_confirm_label": "Изменить дизайн исследования",
|
| 772 |
"method_confirm_placeholder": "Выберите дизайн исследования",
|
| 773 |
"method_confirmation_required": "Некорректное состояние дизайна исследования. Выберите дизайн исследования повторно.",
|
| 774 |
"method_resolution_invalid": "Некорректное состояние дизайна исследования. Выберите дизайн исследования повторно.",
|
| 775 |
-
|
| 776 |
-
"
|
| 777 |
"method_undetermined": "Качественное исследование (по умолчанию)",
|
| 778 |
"method_survey_path": "Количественное исследование на основе опроса",
|
| 779 |
"method_qualitative": "Качественное исследование",
|
| 780 |
-
"method_fsqca": "Качественный сравнительный анализ на основе нечётких множеств (fsQCA)",
|
| 781 |
-
"method_meta_analysis": "Метаанализ",
|
| 782 |
-
"method_panel_econometrics": "Эконометрический анализ панельных данных",
|
| 783 |
-
"method_bibliometric_integrative_review": "Библиометрический анализ и интегративный обзор литературы",
|
| 784 |
"adaptive_template_expander": "💡 Рекомендуемый шаблон (необязательно)",
|
| 785 |
"download_research_template": "📥 Скачать шаблон исследовательских материалов",
|
| 786 |
"template_help_survey_path": "Рекомендуется таблица переменных или статистических результатов. При отсутствии данных SmartPaper может сформировать черновые доказательные материалы в рамках правил происхождения данных.",
|
| 787 |
"template_help_qualitative": "Рекомендуются интервью, полевые заметки или материалы кейсов. При их отсутствии SmartPaper может сформировать анонимный черновой пакет доказательств.",
|
| 788 |
-
"template_help_fsqca": "Рекомендуется таблица условий, результата и параметров калибровки. После включения специализированный движок fsQCA будет использовать эту структуру.",
|
| 789 |
-
"template_help_meta_analysis": "Рекомендуется таблица извлечения размеров эффектов на уровне исследований. Реальные публикации нельзя связывать с системно сформированными размерами эффектов.",
|
| 790 |
-
"template_help_panel_econometrics": "Рекомендуется панельная таблица «объект–время», например структура «компания–год».",
|
| 791 |
-
"template_help_bibliometric_integrative_review": "Используйте реальные метаданные корпуса: название, авторов, год, DOI, журнал и ключевые слова.",
|
| 792 |
"template_help_undetermined": "После подтверждения дизайна исследования будет показан соответствующий шаблон материалов.",
|
| 793 |
"start_generation_unified": "🚀 Начать",
|
| 794 |
"api_key_missing": "❌ Не задан DEEPSEEK_API_KEY. Настройте ключ API.",
|
|
@@ -1002,35 +978,27 @@ TEXTS: dict[str, dict[str, str]] = {
|
|
| 1002 |
"download_asq_template": "📥 TXT сұхбат үлгісін жүктеу",
|
| 1003 |
"start_asq": "🚀 ASQ режимінде дайындауды бастау",
|
| 1004 |
"research_materials_label": "Зерттеу материалдары (міндетті емес)",
|
| 1005 |
-
"research_materials_help": "PDF, TXT, DOC, DOCX, CSV, XLS және XLSX форматтары қолдау табады. Жүктелген файлдар қосымша зерттеу немесе анықтамалық материал ретінде пайдаланылады; зерттеу дизайны мақала тақырыбы мен кілт сөздер
|
| 1006 |
"drop_research_materials": "Зерттеу материалдарын осы жерге сүйреп әкеліңіз",
|
| 1007 |
"limit_research_materials": "Әр файлға 1 ГБ дейін · PDF, TXT, DOC, DOCX, CSV, XLS, XLSX",
|
| 1008 |
"material_document_use_label": "Жүктелген PDF/DOC/DOCX файлдарын қалай пайдалану керек?",
|
| 1009 |
"material_use_reference": "Ғылыми дереккөз ретінде",
|
| 1010 |
"material_use_research": "Зерттеу материалы ретінде",
|
| 1011 |
"detected_method_label": "Зерттеу дизайны (автоматты түрде анықталады, өзгертуге болады)",
|
| 1012 |
-
"method_detection_explanation": "
|
| 1013 |
"method_confirm_label": "Зерттеу дизайнын өзгерту",
|
| 1014 |
"method_confirm_placeholder": "Зерттеу дизайнын таңдаңыз",
|
| 1015 |
"method_confirmation_required": "Зерттеу дизайнының күйі жарамсыз. Зерттеу дизайнын қайта таңдаңыз.",
|
| 1016 |
"method_resolution_invalid": "Зерттеу дизайнының күйі жарамсыз. Зерттеу дизайнын қайта таңдаңыз.",
|
| 1017 |
-
|
| 1018 |
-
"
|
| 1019 |
"method_undetermined": "Сапалық зерттеу (әдепкі)",
|
| 1020 |
"method_survey_path": "Сауалнамаға негізделген сандық зерттеу",
|
| 1021 |
"method_qualitative": "Сапалық зерттеу",
|
| 1022 |
-
"method_fsqca": "Бұлыңғыр жиындарға негізделген сапалық салыстырмалы талдау (fsQCA)",
|
| 1023 |
-
"method_meta_analysis": "Мета-талдау",
|
| 1024 |
-
"method_panel_econometrics": "Панельдік деректерді эконометриялық талдау",
|
| 1025 |
-
"method_bibliometric_integrative_review": "Библиометриялық талдау және әдебиеттерге интегративті шолу",
|
| 1026 |
"adaptive_template_expander": "💡 Ұсынылатын үлгі (міндетті емес)",
|
| 1027 |
"download_research_template": "📥 Зерттеу материалдары үлгісін жүктеу",
|
| 1028 |
"template_help_survey_path": "Айнымалылар немесе статистикалық нәтижелер кестесі ұсынылады. Дерек жүктелмесе, SmartPaper жоба ережелеріне сәйкес бастапқы нұсқаға арналған көмекші дәлелдерді құра алады.",
|
| 1029 |
"template_help_qualitative": "Сұхбат, далалық жазба немесе кейс материалдары ұсынылады. Олар болмаса, SmartPaper анонимді бастапқы дәлелдер пакетін құра алады.",
|
| 1030 |
-
"template_help_fsqca": "Шарттар, нәтиже және калибрлеу ақпараты бар кесте ұсынылады. Арнайы fsQCA қозғалтқышы қосылғаннан кейін осы құрылым қолданылады.",
|
| 1031 |
-
"template_help_meta_analysis": "Зерттеу деңгейіндегі әсер мөлшерлерін шығару кестесі ұсынылады. Нақты мақалалардың сәйкестендіргіштері жүйе құрастырған әсер мөлшерлерімен байланыстырылмауы тиіс.",
|
| 1032 |
-
"template_help_panel_econometrics": "Нысан–уақыт панельдік кестесі, мысалы компания–жыл құрылымы ұсынылады.",
|
| 1033 |
-
"template_help_bibliometric_integrative_review": "Нақты әдеби корпус метадеректерін пайдаланыңыз: атауы, авторлары, жылы, DOI, басылымы және түйін сөздері.",
|
| 1034 |
"template_help_undetermined": "Зерттеу дизайнын растағаннан кейін тиісті материал үлгісі көрсетіледі.",
|
| 1035 |
"start_generation_unified": "🚀 Бастау",
|
| 1036 |
"api_key_missing": "❌ DEEPSEEK_API_KEY көрсетілмеген. API кілтін баптаңыз.",
|
|
@@ -1209,7 +1177,7 @@ def get_asq_txt_template(language: str) -> str:
|
|
| 1209 |
|
| 1210 |
|
| 1211 |
def get_research_material_template(language: str, method_family: str) -> dict[str, str]:
|
| 1212 |
-
"""Return
|
| 1213 |
family = str(method_family or "").strip().casefold()
|
| 1214 |
if family == "survey_path":
|
| 1215 |
return {
|
|
@@ -1218,41 +1186,11 @@ def get_research_material_template(language: str, method_family: str) -> dict[st
|
|
| 1218 |
"filename": "Survey_Path_Data_Template.csv",
|
| 1219 |
"mime_type": "text/csv",
|
| 1220 |
}
|
| 1221 |
-
if family == "qualitative":
|
| 1222 |
-
return {
|
| 1223 |
-
"content": get_asq_txt_template(language),
|
| 1224 |
-
"code_language": "text",
|
| 1225 |
-
"filename": "Qualitative_Research_Materials_Template.txt",
|
| 1226 |
-
"mime_type": "text/plain",
|
| 1227 |
-
}
|
| 1228 |
-
advanced = {
|
| 1229 |
-
"fsqca": (
|
| 1230 |
-
"case_id,condition_1,condition_2,condition_3,outcome\n"
|
| 1231 |
-
"CASE001,0.85,0.20,0.70,0.90\n",
|
| 1232 |
-
"fsQCA_Conditions_Outcome_Template.csv",
|
| 1233 |
-
),
|
| 1234 |
-
"meta_analysis": (
|
| 1235 |
-
"study_id,effect_size,standard_error,sample_size,moderator\n"
|
| 1236 |
-
"STUDY001,0.25,0.08,240,context_A\n",
|
| 1237 |
-
"Meta_Analysis_Effect_Size_Template.csv",
|
| 1238 |
-
),
|
| 1239 |
-
"panel_econometrics": (
|
| 1240 |
-
"entity_id,year,outcome,x1,x2,control_1\n"
|
| 1241 |
-
"E001,2025,0.62,0.40,0.71,0.15\n",
|
| 1242 |
-
"Panel_Entity_Time_Template.csv",
|
| 1243 |
-
),
|
| 1244 |
-
"bibliometric_integrative_review": (
|
| 1245 |
-
"title,authors,year,doi,venue,keywords\n"
|
| 1246 |
-
"Real publication title,Author A; Author B,2025,10.xxxx/xxxxx,Journal Name,keyword1; keyword2\n",
|
| 1247 |
-
"Bibliometric_Corpus_Metadata_Template.csv",
|
| 1248 |
-
),
|
| 1249 |
-
}
|
| 1250 |
-
content, filename = advanced.get(family, ("", "SmartPaper_Research_Materials_Template.txt"))
|
| 1251 |
return {
|
| 1252 |
-
"content":
|
| 1253 |
-
"code_language": "
|
| 1254 |
-
"filename":
|
| 1255 |
-
"mime_type": "text/
|
| 1256 |
}
|
| 1257 |
|
| 1258 |
|
|
|
|
| 276 |
"download_asq_template": "📥 一键下载 TXT 访谈模板",
|
| 277 |
"start_asq": "🚀 启动 ASQ 模式生成",
|
| 278 |
"research_materials_label": "研究资料(可选)",
|
| 279 |
+
"research_materials_help": "支持 PDF、TXT、DOC、DOCX、CSV、XLS、XLSX。上传资料用于辅助论文生成;研究设计仅在质性研究与问卷量化研究之间根据论文题目和关键词识别。",
|
| 280 |
"drop_research_materials": "将研究资料拖到这里",
|
| 281 |
"limit_research_materials": "每个文件最大 1 GB · PDF, TXT, DOC, DOCX, CSV, XLS, XLSX",
|
| 282 |
"material_document_use_label": "如何使用上传的 PDF/DOC/DOCX 文件?",
|
| 283 |
"material_use_reference": "作为参考文献资料",
|
| 284 |
"material_use_research": "作为研究资料",
|
| 285 |
"detected_method_label": "研究设计(自动识别,可调整)",
|
| 286 |
+
"method_detection_explanation": "系统根据论文题目和关键词在质性研究与问卷量化研究之间自动识别;未识别时默认质性研究,可手动调整。",
|
| 287 |
"method_confirm_label": "调整研究设计",
|
| 288 |
"method_confirm_placeholder": "请选择研究设计",
|
| 289 |
"method_confirmation_required": "研究设计状态异常,请重新选择研究设计。",
|
| 290 |
"method_resolution_invalid": "研究设计状态异常,请重新选择研究设计。",
|
| 291 |
+
"method_supported": "当前研究设计为“{method}”。系统将按对应研究流程生成论文。",
|
| 292 |
+
"specialized_method_redirect": "您的论文可能涉及面板数据 / 元分析 / fsQCA / 文献计量,我的专长是质性研究和问卷量化研究,并非这些特定方法的精专工具。研究设计的灵魂在于问题意识和逻辑链条,这是我擅长的,为您搭建一套质性研究论文框架。",
|
| 293 |
"method_undetermined": "质性研究(默认)",
|
| 294 |
"method_survey_path": "问卷量化研究",
|
| 295 |
"method_qualitative": "质性研究",
|
|
|
|
|
|
|
|
|
|
|
|
|
| 296 |
"adaptive_template_expander": "💡 推荐模板(可选)",
|
| 297 |
"download_research_template": "📥 下载研究资料模板",
|
| 298 |
"template_help_survey_path": "推荐使用变量或统计结果表。若未上传数据,系统会按项目规则生成用于初稿的辅助证据。",
|
| 299 |
"template_help_qualitative": "推荐使用访谈、田野记录或案例材料。若未上传资料,系统会构建匿名的初稿证据包。",
|
|
|
|
|
|
|
|
|
|
|
|
|
| 300 |
"template_help_undetermined": "确认研究设计后,系统将显示对应的研究资料模板。",
|
| 301 |
"start_generation_unified": "🚀 开始生成",
|
| 302 |
"api_key_missing": "❌ 缺少 DEEPSEEK_API_KEY,请配置API密钥。",
|
|
|
|
| 510 |
"download_asq_template": "📥 Download TXT Interview Template",
|
| 511 |
"start_asq": "🚀 Start ASQ Generation",
|
| 512 |
"research_materials_label": "Research Materials (Optional)",
|
| 513 |
+
"research_materials_help": "Supports PDF, TXT, DOC, DOCX, CSV, XLS, and XLSX. Uploaded files support paper generation; Research Design is identified from the Title and Keywords between Qualitative Research and Survey-Based Quantitative Research only.",
|
| 514 |
"drop_research_materials": "Drag research materials here",
|
| 515 |
"limit_research_materials": "Up to 1 GB per file · PDF, TXT, DOC, DOCX, CSV, XLS, XLSX",
|
| 516 |
"material_document_use_label": "How should SmartPaper use the uploaded PDF/DOC/DOCX files?",
|
| 517 |
"material_use_reference": "Use as reference literature",
|
| 518 |
"material_use_research": "Use as research materials",
|
| 519 |
"detected_method_label": "Research Design (Auto-detected, Adjustable)",
|
| 520 |
+
"method_detection_explanation": "SmartPaper identifies the Research Design from the Title and Keywords using two supported options: Qualitative Research and Survey-Based Quantitative Research. If neither is clearly indicated, Qualitative Research is used by default. You can adjust the selection manually.",
|
| 521 |
"method_confirm_label": "Adjust Research Design",
|
| 522 |
"method_confirm_placeholder": "Select a Research Design",
|
| 523 |
"method_confirmation_required": "The Research Design state is invalid. Please select a Research Design again.",
|
| 524 |
"method_resolution_invalid": "The Research Design state is invalid. Please select a Research Design again.",
|
| 525 |
+
"method_supported": "Current Research Design: {method}. SmartPaper will use the corresponding research workflow.",
|
| 526 |
+
"specialized_method_redirect": "Your paper may involve panel data, meta-analysis, fsQCA, or bibliometric methods. My core strengths are qualitative research and survey-based quantitative research; I am not designed as a specialist tool for those specific methods. The essence of research design lies in a clear research problem and a coherent chain of reasoning—areas in which I am strongest. I will therefore help you build a qualitative research paper framework.",
|
| 527 |
"method_undetermined": "Qualitative Research (Default)",
|
| 528 |
"method_survey_path": "Survey-Based Quantitative Research",
|
| 529 |
"method_qualitative": "Qualitative Research",
|
|
|
|
|
|
|
|
|
|
|
|
|
| 530 |
"adaptive_template_expander": "💡 Recommended Template (Optional)",
|
| 531 |
"download_research_template": "📥 Download Research Materials Template",
|
| 532 |
"template_help_survey_path": "A variable-level or statistical-results table is recommended. If no data are uploaded, SmartPaper may construct draft evidence under the project provenance rules.",
|
| 533 |
"template_help_qualitative": "Interview, field-note, or case materials are recommended. If none are uploaded, SmartPaper may construct an anonymous draft evidence packet.",
|
|
|
|
|
|
|
|
|
|
|
|
|
| 534 |
"template_help_undetermined": "Confirm the research design to view the corresponding research-material template.",
|
| 535 |
"start_generation_unified": "🚀 Start Generation",
|
| 536 |
"api_key_missing": "❌ DEEPSEEK_API_KEY is missing. Configure the API key.",
|
|
|
|
| 744 |
"download_asq_template": "📥 Скачать TXT-шаблон интервью",
|
| 745 |
"start_asq": "🚀 Запустить формирование в режиме ASQ",
|
| 746 |
"research_materials_label": "Материалы исследования (необязательно)",
|
| 747 |
+
"research_materials_help": "Поддерживаются PDF, TXT, DOC, DOCX, CSV, XLS и XLSX. Загруженные файлы используются как дополнительные исследовательские или справ��чные материалы; дизайн исследования определяется по названию статьи и ключевым словам только между качественным исследованием и количественным исследованием на основе опроса.",
|
| 748 |
"drop_research_materials": "Перетащите исследовательские материалы сюда",
|
| 749 |
"limit_research_materials": "До 1 ГБ на файл · PDF, TXT, DOC, DOCX, CSV, XLS, XLSX",
|
| 750 |
"material_document_use_label": "Как использовать загруженные файлы PDF/DOC/DOCX?",
|
| 751 |
"material_use_reference": "Как научные источники",
|
| 752 |
"material_use_research": "Как исследовательские материалы",
|
| 753 |
"detected_method_label": "Дизайн исследования (определяется автоматически, можно изменить)",
|
| 754 |
+
"method_detection_explanation": "SmartPaper определяет дизайн исследования по названию статьи и ключевым словам, выбирая между двумя поддерживаемыми вариантами: качественным исследованием и количественным исследованием на основе опроса. Если явных признаков нет, по умолчанию выбирается качественное исследование. Выбор можно изменить вручную.",
|
| 755 |
"method_confirm_label": "Изменить дизайн исследования",
|
| 756 |
"method_confirm_placeholder": "Выберите дизайн исследования",
|
| 757 |
"method_confirmation_required": "Некорректное состояние дизайна исследования. Выберите дизайн исследования повторно.",
|
| 758 |
"method_resolution_invalid": "Некорректное состояние дизайна исследования. Выберите дизайн исследования повторно.",
|
| 759 |
+
"method_supported": "Текущий дизайн исследования: «{method}». SmartPaper применит соответствующий исследовательский процесс.",
|
| 760 |
+
"specialized_method_redirect": "Ваша статья, возможно, предполагает использование панельных данных, метаанализа, fsQCA или библиометрических методов. Моя основная специализация — качественные исследования и количественные исследования на основе опросов; я не предназначен как узкоспециализированный инструмент для этих конкретных методов. Суть исследовательского дизайна заключается в чёткой постановке исследовательской проблемы и последовательной логике аргументации — именно в этом моя сильная сторона. Поэтому я помогу вам выстроить структуру статьи в рамках качественного исследования.",
|
| 761 |
"method_undetermined": "Качественное исследование (по умолчанию)",
|
| 762 |
"method_survey_path": "Количественное исследование на основе опроса",
|
| 763 |
"method_qualitative": "Качественное исследование",
|
|
|
|
|
|
|
|
|
|
|
|
|
| 764 |
"adaptive_template_expander": "💡 Рекомендуемый шаблон (необязательно)",
|
| 765 |
"download_research_template": "📥 Скачать шаблон исследовательских материалов",
|
| 766 |
"template_help_survey_path": "Рекомендуется таблица переменных или статистических результатов. При отсутствии данных SmartPaper может сформировать черновые доказательные материалы в рамках правил происхождения данных.",
|
| 767 |
"template_help_qualitative": "Рекомендуются интервью, полевые заметки или материалы кейсов. При их отсутствии SmartPaper может сформировать анонимный черновой пакет доказательств.",
|
|
|
|
|
|
|
|
|
|
|
|
|
| 768 |
"template_help_undetermined": "После подтверждения дизайна исследования будет показан соответствующий шаблон материалов.",
|
| 769 |
"start_generation_unified": "🚀 Начать",
|
| 770 |
"api_key_missing": "❌ Не задан DEEPSEEK_API_KEY. Настройте ключ API.",
|
|
|
|
| 978 |
"download_asq_template": "📥 TXT сұхбат үлгісін жүктеу",
|
| 979 |
"start_asq": "🚀 ASQ режимінде дайындауды бастау",
|
| 980 |
"research_materials_label": "Зерттеу материалдары (міндетті емес)",
|
| 981 |
+
"research_materials_help": "PDF, TXT, DOC, DOCX, CSV, XLS және XLSX форматтары қолдау табады. Жүктелген файлдар қосымша зерттеу немесе анықтамалық материал ретінде пайдаланылады; зерттеу дизайны мақала тақырыбы мен кілт сөздер негізінде тек сапалық зерттеу мен сауалнамаға негізделген сандық зерттеу арасынан анықталады.",
|
| 982 |
"drop_research_materials": "Зерттеу материалдарын осы жерге сүйреп әкеліңіз",
|
| 983 |
"limit_research_materials": "Әр файлға 1 ГБ дейін · PDF, TXT, DOC, DOCX, CSV, XLS, XLSX",
|
| 984 |
"material_document_use_label": "Жүктелген PDF/DOC/DOCX файлдарын қалай пайдалану керек?",
|
| 985 |
"material_use_reference": "Ғылыми дереккөз ретінде",
|
| 986 |
"material_use_research": "Зерттеу материалы ретінде",
|
| 987 |
"detected_method_label": "Зерттеу дизайны (автоматты түрде анықталады, өзгертуге болады)",
|
| 988 |
+
"method_detection_explanation": "SmartPaper мақала тақырыбы мен кілт сөздер негізінде екі қолдау көрсетілетін н��сқаның бірін анықтайды: сапалық зерттеу немесе сауалнамаға негізделген сандық зерттеу. Нақты белгі болмаса, әдепкі бойынша сапалық зерттеу таңдалады. Таңдауды қолмен өзгертуге болады.",
|
| 989 |
"method_confirm_label": "Зерттеу дизайнын өзгерту",
|
| 990 |
"method_confirm_placeholder": "Зерттеу дизайнын таңдаңыз",
|
| 991 |
"method_confirmation_required": "Зерттеу дизайнының күйі жарамсыз. Зерттеу дизайнын қайта таңдаңыз.",
|
| 992 |
"method_resolution_invalid": "Зерттеу дизайнының күйі жарамсыз. Зерттеу дизайнын қайта таңдаңыз.",
|
| 993 |
+
"method_supported": "Ағымдағы зерттеу дизайны: «{method}». SmartPaper тиісті зерттеу үдерісін қолданады.",
|
| 994 |
+
"specialized_method_redirect": "Сіздің мақалаңыз панельдік деректерді, мета-талдауды, fsQCA-ны немесе библиометриялық әдістерді қамтуы мүмкін. Менің негізгі мамандануым — сапалық зерттеу және сауалнамаға негізделген сандық зерттеу; бұл нақты әдістерге арналған тар бейінді құрал ретінде жасалмағанмын. Зерттеу дизайнының өзегі — зерттеу мәселесін дәл қою және логикалық тізбекті дәйекті құру, бұл — менің мықты тұсым. Сондықтан сізге сапалық зерттеу мақаласының тұтас құрылымын құруға көмектесемін.",
|
| 995 |
"method_undetermined": "Сапалық зерттеу (әдепкі)",
|
| 996 |
"method_survey_path": "Сауалнамаға негізделген сандық зерттеу",
|
| 997 |
"method_qualitative": "Сапалық зерттеу",
|
|
|
|
|
|
|
|
|
|
|
|
|
| 998 |
"adaptive_template_expander": "💡 Ұсынылатын үлгі (міндетті емес)",
|
| 999 |
"download_research_template": "📥 Зерттеу материалдары үлгісін жүктеу",
|
| 1000 |
"template_help_survey_path": "Айнымалылар немесе статистикалық нәтижелер кестесі ұсынылады. Дерек жүктелмесе, SmartPaper жоба ережелеріне сәйкес бастапқы нұсқаға арналған көмекші дәлелдерді құра алады.",
|
| 1001 |
"template_help_qualitative": "Сұхбат, далалық жазба немесе кейс материалдары ұсынылады. Олар болмаса, SmartPaper анонимді бастапқы дәлелдер пакетін құра алады.",
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1002 |
"template_help_undetermined": "Зерттеу дизайнын растағаннан кейін тиісті материал үлгісі көрсетіледі.",
|
| 1003 |
"start_generation_unified": "🚀 Бастау",
|
| 1004 |
"api_key_missing": "❌ DEEPSEEK_API_KEY көрсетілмеген. API кілтін баптаңыз.",
|
|
|
|
| 1177 |
|
| 1178 |
|
| 1179 |
def get_research_material_template(language: str, method_family: str) -> dict[str, str]:
|
| 1180 |
+
"""Return a template for one of the two supported production designs."""
|
| 1181 |
family = str(method_family or "").strip().casefold()
|
| 1182 |
if family == "survey_path":
|
| 1183 |
return {
|
|
|
|
| 1186 |
"filename": "Survey_Path_Data_Template.csv",
|
| 1187 |
"mime_type": "text/csv",
|
| 1188 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1189 |
return {
|
| 1190 |
+
"content": get_asq_txt_template(language),
|
| 1191 |
+
"code_language": "text",
|
| 1192 |
+
"filename": "Qualitative_Research_Materials_Template.txt",
|
| 1193 |
+
"mime_type": "text/plain",
|
| 1194 |
}
|
| 1195 |
|
| 1196 |
|