This commit is contained in:
sam 2025-10-06 15:13:19 +08:00
parent c45026eff4
commit 8f8e54e0bd
5 changed files with 188 additions and 0 deletions

View File

@ -0,0 +1,31 @@
{
"department_base": {
"name": "部门基础模板",
"description": "审慎分析骨架(数据校验强化版)",
"template": "部门:{title}\n股票代码{ts_code}\n交易日{trade_date}\n\n【角色定位】\n- 角色说明:{description}\n- 行动守则:{instruction}\n\n【数据校验】\n1. 逐条确认提供的数据是否符合 expected schema缺失项需记录在 `risks`。\n2. 如出现冲突数据,请在 `signals` 中说明解决思路,并指出最可信的来源。\n\n【数据边界】\n- 可用字段:\n{data_scope}\n- 核心特征:\n{features}\n- 市场背景:\n{market_snapshot}\n- 追加数据:\n{supplements}\n\n【分析步骤】\n1. 评估数据完整度,必要时建议补充 `fetch_data` 的具体调用参数。\n2. 基于量化证据拆分 2-3 个关键支撑与潜在风险,注明对应字段。\n3. 提炼操作建议并给出可执行的风险对冲或观察指标。\n\n【输出要求】\n仅返回一个 JSON 对象,不要添加额外文本:\n{\n \"action\": \"BUY|BUY_S|BUY_M|BUY_L|SELL|HOLD\",\n \"confidence\": 0-1 之间的小数,\n \"summary\": \"一句话结论\",\n \"signals\": [\"字段+现象\", \"...\"],\n \"risks\": [\"字段+风险\", \"...\"]\n}\n如需说明未完成的数据请求请在 `risks` 中补充。",
"variables": [
"title",
"ts_code",
"trade_date",
"description",
"instruction",
"data_scope",
"features",
"market_snapshot",
"supplements"
],
"max_length": 4000,
"required_context": [
"ts_code",
"trade_date",
"features",
"market_snapshot"
],
"version": "1.1.0",
"metadata": {
"label": "quality_guard",
"notes": "强调数据校验与风险映射。"
},
"activate": false
}
}

View File

@ -0,0 +1,31 @@
{
"department_base": {
"name": "部门基础模板",
"description": "审慎分析骨架(结构化输出版)",
"template": "部门:{title}\n股票代码{ts_code}\n交易日{trade_date}\n\n【角色定位】\n- 研究职责:{description}\n- 执行要点:{instruction}\n\n【量化检查】\n- 数据覆盖:\n{data_scope}\n- 模型特征:\n{features}\n- 市场切片:\n{market_snapshot}\n- 附加观察:\n{supplements}\n\n【分析流程】\n1. 使用事实句描述当前市场位置(包含至少 1 项相对指标)。\n2. 归纳 2-3 条策略信号,每条需关联具体字段并给出方向。\n3. 对每条信号列出对应的风险验证指标与触发阈值。\n4. 最终给出操作建议,并在 `confidence` 中量化判断依据。\n\n【输出格式】\n仅输出 JSON不包含额外文字\n{\n \"action\": \"BUY|BUY_S|BUY_M|BUY_L|SELL|HOLD\",\n \"confidence\": 小数,\n \"summary\": \"一句话\",\n \"signals\": [\n {\n \"statement\": \"现象描述\",\n \"evidence\": \"对应字段或数据来源\",\n \"direction\": \"bullish|bearish|neutral\"\n }\n ],\n \"risks\": [\n {\n \"threat\": \"风险描述\",\n \"monitor\": \"观测指标\",\n \"threshold\": \"触发阈值\"\n }\n ]\n}\n若缺少关键数据请在 `risks` 中新增一项 `monitor` 为 `data_gap`。",
"variables": [
"title",
"ts_code",
"trade_date",
"description",
"instruction",
"data_scope",
"features",
"market_snapshot",
"supplements"
],
"max_length": 4000,
"required_context": [
"ts_code",
"trade_date",
"features",
"market_snapshot"
],
"version": "1.2.0",
"metadata": {
"label": "structured_v2",
"notes": "增加信号与风险的结构化字段。"
},
"activate": true
}
}

View File

@ -0,0 +1,28 @@
{
"momentum_dept": {
"name": "动量研究部门模板",
"description": "多层级动量评估版本",
"template": "部门:动量研究部门\n股票代码{ts_code}\n交易日{trade_date}\n\n【角色定位】\n- 追踪价格与成交量动量的共振与切换。\n- 识别趋势衰减与阶段性反转信号。\n\n【分层动量视角】\n1. 超短线1-3 日)动量:\n{features}\n2. 短线5-10 日)趋势斜率:\n{market_snapshot}\n3. 中线20+ 日)位置与乖离:\n{data_scope}\n\n【执行指引】\n- 对每个时间层给出强度评级strong/weak/neutral。\n- 若评级存在冲突,需在 `risks` 说明优先采信的层级。\n- 必须评估量价背离与成交密集区。\n\n【输出要求】\n仅输出 JSON\n{\n \"action\": \"BUY|BUY_S|BUY_M|BUY_L|SELL|HOLD\",\n \"confidence\": 小数,\n \"summary\": \"一句话\",\n \"signals\": [\"层级+观察\", \"...\"],\n \"risks\": [\"层级+风险\", \"...\"]\n}\n若需进一步数据请在 `risks` 中注明具体字段。",
"variables": [
"ts_code",
"trade_date",
"data_scope",
"features",
"market_snapshot",
"supplements"
],
"max_length": 4000,
"required_context": [
"ts_code",
"trade_date",
"features",
"market_snapshot"
],
"version": "1.1.0",
"metadata": {
"label": "multiframe",
"notes": "分层动量分析,强调评级冲突解释。"
},
"activate": false
}
}

View File

@ -3,6 +3,7 @@ from __future__ import annotations
import json import json
import logging import logging
from pathlib import Path
from dataclasses import dataclass from dataclasses import dataclass
from typing import Any, Dict, List, Optional, TYPE_CHECKING from typing import Any, Dict, List, Optional, TYPE_CHECKING
@ -633,4 +634,59 @@ def register_default_templates() -> None:
# Auto-register default templates on module import # Auto-register default templates on module import
EXTERNAL_TEMPLATE_DIR = Path(__file__).resolve().parents[1] / "data" / "prompt_templates"
def load_external_template_configs(directory: Path | str = EXTERNAL_TEMPLATE_DIR) -> None:
"""Load additional template versions from JSON files in the given directory."""
directory_path = Path(directory)
if not directory_path.exists() or not directory_path.is_dir():
return
for file_path in sorted(directory_path.glob("*.json")):
try:
raw_data = file_path.read_text(encoding="utf-8")
except OSError:
logging.warning("无法读取提示模板配置文件 %s", file_path)
continue
try:
payload = json.loads(raw_data)
except json.JSONDecodeError as exc:
logging.warning("提示模板配置文件 %s 解析失败:%s", file_path, exc)
continue
enriched_payload = {}
for template_id, cfg in payload.items():
if not isinstance(cfg, dict):
logging.warning(
"提示模板配置文件 %s 中的 %s 配置无效(应为对象)",
file_path,
template_id,
)
continue
metadata = cfg.get("metadata") or {}
if not isinstance(metadata, dict):
metadata = {}
metadata.setdefault("source", file_path.name)
enriched_payload[template_id] = {
**cfg,
"metadata": metadata,
}
if not enriched_payload:
continue
try:
TemplateRegistry.load_from_json(json.dumps(enriched_payload, ensure_ascii=False))
except Exception as exc: # noqa: BLE001
logging.warning(
"注册提示模板配置 %s 失败:%s",
file_path,
exc,
)
register_default_templates() register_default_templates()
load_external_template_configs()

View File

@ -25,6 +25,7 @@ from app.ingest.tushare import run_ingestion
from app.llm.client import run_llm from app.llm.client import run_llm
from app.llm.metrics import reset as reset_llm_metrics from app.llm.metrics import reset as reset_llm_metrics
from app.llm.metrics import snapshot as snapshot_llm_metrics from app.llm.metrics import snapshot as snapshot_llm_metrics
from app.llm.templates import TemplateRegistry
from app.utils import alerts from app.utils import alerts
from app.utils.config import get_config, save_config from app.utils.config import get_config, save_config
from app.utils.tuning import log_tuning_result from app.utils.tuning import log_tuning_result
@ -464,6 +465,47 @@ def render_backtest_review() -> None:
spec_labels.append(f"department:{dept_code}:tool_choice") spec_labels.append(f"department:{dept_code}:tool_choice")
action_values.append(tool_value) action_values.append(tool_value)
template_id = (settings.prompt_template_id or f"{dept_code}_dept").strip()
versions = [ver for ver in TemplateRegistry.list_versions(template_id) if isinstance(ver, str)]
if versions:
active_version = TemplateRegistry.get_active_version(template_id)
default_version = (
settings.prompt_template_version
or active_version
or versions[0]
)
try:
default_index = versions.index(default_version)
except ValueError:
default_index = 0
version_choice = st.selectbox(
"提示模板版本",
versions,
index=default_index,
key=f"{prefix}_template_version",
help="离散动作将按版本列表顺序映射,可用于强化学习优化。",
)
selected_index = versions.index(version_choice)
ratio = (
0.0
if len(versions) == 1
else selected_index / (len(versions) - 1)
)
specs.append(
ParameterSpec(
name=f"dept_prompt_version_{dept_code}",
target=f"department.{dept_code}.prompt_template_version",
values=list(versions),
)
)
spec_labels.append(f"department:{dept_code}:prompt_version")
action_values.append(ratio)
st.caption(
f"激活版本:{active_version or '默认'} 当前选择:{version_choice}"
)
else:
st.caption("当前模板未注册可选提示词版本,继续沿用激活版本。")
if specs: if specs:
st.caption("动作维度顺序:" + "".join(spec_labels)) st.caption("动作维度顺序:" + "".join(spec_labels))