PYTA Research
多市场 AI 推演引擎
面向投资研究场景的有状态多市场 AI 推演系统。
两种完全独立的分析模式:一级市场(VC/PE 深度尽调)与 二级市场(多 Agent 并行模拟)。
每次推演持久化为 Checkpoint,支持多轮累积、断点恢复、全链路审计。
2市场模式
4层 DAG 执行图
G1-G6加固模块
6+可扩展维度
3收敛停止门控
5级投资决策
5 级决策输出:invest → priority_diligence → monitor → re_evaluate → pass_for_now
↓ 向下滚动开始
1双市场模式
PYTA 支持两条完全独立的分析流水线,通过 MarketModeSelector 在 UI 中一键切换。
一级市场
VC/PE 深度尽调推演
通过 4 层 DAG 执行图进行多轮收敛推演。支持投资人画像驱动分析、参照系对比、Deep Dive 全链路审计。输出结构化 5 级投资决策。
二级市场
多 Agent 并行模拟
输入市场事件后,4 个不同角色的市场参与者 Agent(短线资金、传统机构、外资、散户)同时推演。输出多空博弈面板。
2一级市场:4 层 DAG 引擎
DAG 执行图
Layer 1 — 并行分析
UncertaintyMap
6 维度评估
FounderAnalysis
团队 + 阶段匹配
KeyAssumptions
硬/软假设
FinancialLens
G4 单位经济 + G6 估值
Competitive
G3 竞争格局 + 护城河
↓
Layer 2 — 上下文组装
ContextAssembler
S 曲线推断 · 投资人注入 · 参照系绑定
↓
Layer 3 — Lens 校准
BenchmarkLens
参照系对比 Δ
InvestorFit
投资人适配 shift
DealStructure
交易条款 shift
↓
Verdict — 决策合成
VerdictComposition — 5 级决策 + 理由 + 监控触发器
↓
审计 — Deep Dive
Deep Dive Panel — 8 个 Section 全链路推理轨迹
推演数据流
前端提交公司信息 + 投资人画像 + 参照系
→ POST /api/v1/primary/run-stream (SSE)
→ PrimaryOrchestrator.run()
→ [一次性] CompetitiveLandscapeAgent (G3)
→ [一次性] FounderAnalysis (G2) + KeyAssumptions
→ 第 N 轮循环:
→ 6 维度 Agent (通过 DimensionRegistry)
→ FinancialLens: G4 单位经济 + G6 估值
→ AssumptionChecker → PathForkService
→ ConvergenceJudge (语义三门停止)
→ [可选] HITL Gate (环境修正提案)
→ Checkpoint 持久化
→ L2-L3: 上下文组装 + Lens 校准 + 决策合成
→ SSE 流式推送 → 前端 DAG + Deep Dive
三门停止条件(语义化)
convergence
语义收敛
LLM 判断结论是否内部一致且相比上一轮稳定(替代旧的定量阈值 avg ≥ 0.85)
max_rounds
轮次上限
达到最大轮数(默认 3 轮)
oscillation
震荡停止
连续 N 轮 delta < 0.02
Fast-path:置信度波动 > 0.15 或检测到矛盾标记时跳过 LLM 收敛调用。第一轮始终返回未收敛(无基准线)。
DimensionRegistry(数据驱动,PR #116/#117)
维度通过 DimensionDescriptor 冻结数据类定义在中央注册表中,替代了隐式的枚举遍历。维度 ID 使用纯字符串(非 enum),新增维度只需在 build_default_registry() 中添加一行,无需修改任何 enum 定义。
| 维度 ID | 中文标签 | prompt_focus 摘要 | is_critical | sort | special_outputs |
market_validity | 目标市场是否真实成立 | 市场真实性 + TAM/SAM/SOM 定量 | yes | 0 | market_sizing |
tech_barrier | 技术壁垒强度 | 技术护城河、可替代性、专利壁垒 | — | 1 | — |
team_execution | 团队执行力与背景匹配 | 创始人背景、阶段匹配度、关键人风险 | yes | 2 | — |
commercialization | 商业化路径可行性 | GTM 路径、渠道策略、客户验证 | — | 3 | — |
competition | 竞争格局威胁 | 竞对格局、护城河、大厂进入风险 | — | 4 | — |
burn_cycle | 资金消耗与增长节奏匹配 | Burn rate vs 融资节奏、runway 合理性 | — | 5 | — |
Registry API
查询
get_default_set()
返回所有 default_enabled=True 的维度,按 sort_order 排序。Orchestrator 的 dispatch 循环以此为驱动。
查询
get(dimension_id)
按 ID 查找单个 DimensionDescriptor。Prompt builder 用它读取 label 和 prompt_focus。
反查
dimension_for_output(key)
反查哪个维度拥有某个 special_output。如 "market_sizing" → "market_validity"。
过滤
get_for_context(sector)
按行业过滤维度(applicable_sectors / incompatible_sectors)。Phase 1 等同于 get_default_set()。
special_outputs 机制:当 Orchestrator 需要获取 market_sizing 数据时,通过 registry.dimension_for_output("market_sizing") 反查到 market_validity 维度,无需硬编码维度 ID。
| 字段 | 类型 | 说明 |
dimension_id | str | 唯一标识(如 "market_validity") |
label | str | 中文显示名(如 "目标市场是否真实成立") |
description | str | 详细描述 |
prompt_focus | str | 注入 LLM prompt 的分析侧重说明 |
is_critical | bool | 关键维度失败 → CRITICAL_FAILURE |
default_enabled | bool | 默认是否启用 |
sort_order | int | dispatch 和渲染顺序 |
applicable_sectors | list[str] | 适用行业(空 = 全部) |
incompatible_sectors | list[str] | 不兼容行业 |
special_outputs | frozenset[str] | 该维度拥有的特殊输出(如 {"market_sizing"}) |
2.5V2 推演引擎生命周期
一次 POST /primary/run 的完整生命周期。默认最多 3 轮,每轮串行跑 6 个维度 Agent,然后经过假设验证 → 路径分叉 → 收敛判定。
多轮推演流程
接收请求
POST /primary/run → PrimaryOrchestrator.run_streaming() → SSE: RUN_STARTED
上下文组装
ContextAssembler.assemble(company_info, investor_profile, benchmarks) → S-curve 定位 + 投资人偏好 + 行业基准
维度派发
DimensionRegistry.get_default_set() → 按 sort_order 返回 6 个维度。Orchestrator 遍历此列表串行 dispatch Agent。
Round 循环 — Agent 执行
每个维度 Agent 串行执行:AGENT_STARTED → LLM 调用 → PrimaryAgentOutput → AGENT_DONE。
输出汇总为 UncertaintyMap + FounderAnalysis。
Round 循环 — 验证 & 分叉 & 收敛
AssumptionChecker 验证硬/软假设 → PathForkService 检测 5 种分叉触发 → ConvergenceJudge 判定是否停止。
每轮结束后 _persist_checkpoint() 持久化。
输出报告
_build_report(): BenchmarkLens → InvestorLens → DecisionRecommendation → SSE: REPORT_READY
三个 Abort Gate
每轮结束后按顺序检查,命中任一即停止迭代:
convergence
语义收敛
ConvergenceJudge 调用 LLM 判断本轮与上轮结果是否语义一致。
Fast-path: 置信度波动 > 0.15 或矛盾标记 → 跳过 LLM 调用。第一轮始终返回未收敛。
oscillation
震荡停止
连续 N 轮 avg_confidence 变化 < 0.02。表示系统在相近结论之间来回摆动,继续推演无益。
budget
轮次上限
round ≥ max_rounds(默认 3)。保底停止条件。
Health Check(每轮)
| 状态 | 条件 | 行为 |
| HEALTHY | 所有 Agent 成功 | 继续下一轮 |
| PARTIAL | 非关键维度失败 ≤ 2 | 继续,标记降级 |
| CRITICAL_FAILURE | 任何 is_critical 维度失败 | 终止整个 run |
| DEGRADED_FAILURE | 非关键维度失败 > 2 | 终止整个 run |
PathFork — 5 种分叉触发
PathForkService 在每轮末尾检查以下条件。触发时生成替代路径分叉(scenario_if_holds / scenario_if_fails),记入最终报告。
HARD
hard_assumption_violated
硬假设验证失败(如"市场必须在 18 个月内达到 PMF"被证伪)
STRUCT
structural_divergence
Module 1(维度评估)与 Module 2(创始人)置信度差 > 0.4
MACRO
macro_timing_mismatch
market_validity=HIGH + competition=LOW → 市场窗口与竞争格局冲突
TEAM
team_risk
创始人 stage_fit == MISMATCHED → 人-阶段错位风险
MARKET
market_size_unproven
market_validity=HIGH 不确定性 → 市场有效性尚未验证
HITL Gate(Human-in-the-Loop)
环境修正提案:维度 Agent 可以在输出中提出 EnvUpdateProposal(如"建议将公司阶段从 0_to_1 改为 1_to_10")。Orchestrator 收集后通过 SSE 推送给前端,等用户确认 POST /primary/{id}/confirm-proposals 后再合入环境状态。
Checkpoint & Restore
每轮结束后调用 _persist_checkpoint(),存储 env_state、accumulated_path_forks、max_rounds、active_agent_ids。
Partial Restore(Registry 变更恢复):
- 恢复时,Registry 可能已与原始运行不同(如从 6 维变 7 维)
- 不再存在于当前 Registry 中的旧维度被跳过,记入
restore_skipped_dims
- 含有 skipped dims 的轮次自动跳过 convergence check(避免基于不完整数据误判收敛)
- SSE 推送
DATA_QUALITY_WARNING 事件通知前端
- Report 标记
restore_integrity: "partial" + skipped_dimensions_by_round
3G1-G6 加固模块
6 个结构化分析模块,覆盖从公司画像到估值分析的完整 VC 决策链。
G1
公司基础画像
tagline、核心产品、成立日期、总部、员工数、融资历史、股权结构
G2
核心团队分析
创始人原型、阶段匹配度、团队完整性、互补性、Bus Factor、股权健康度
G3
竞争格局深度分析
竞对列表 + 六维护城河(网络效应/数据/规模/品牌/转换成本/监管)+ 大厂入局风险
G4
单位经济模型
CAC、Payback Period、Magic Number、Burn Multiple、Rule of 40、人均营收
G5
市场规模与时机
TAM/SAM/SOM、市场 CAGR、渗透率、时机窗口(early/optimal/late/closing)+ 催化因素
G6
估值合理性分析
EV/Revenue 倍数、Step-up、稀释影响、MOIC/IRR 回报建模、估值判断(fair/rich/discount)
4Deep Dive 审计层
不是"换个地方展示数据" — 而是推理过程的审计层。
让用户回溯"系统为什么得出这个结论",每一步的输入、推导、校准都可追溯。
定位:投行用它做尽调依据(直接 copy-paste 到 IC Memo);研究者用它找推理漏洞然后调参。
8 个 Section 布局(右侧 slide-over · 单列可折叠)
默认展开
§1 决策摘要
Decision + 置信度/得分路径 + 理由
默认展开
§2 收敛轨迹
Sparkline:6 维度 per-round score 折线 + 矛盾标红
默认展开
§3 Lens 校准链
Benchmark + Investor + Deal notes + 参照系对比
收起
§5 财务审计
顶线指标 + G4 单位经济 + G6 估值分析
收起
§6 市场分析
G5 TAM/SAM/SOM + CAGR + 时机窗口
收起
§7 关键假设 & 路径分叉
PathFork 场景(5 种触发类型)
设计原则
- 单列可折叠纵向流 — 审计文档是线性阅读的,不是 dashboard
- Per-round ReasoningTrace 携带完整 Agent 输出(score、confidence、narrative、signals、矛盾检测)
- 收敛轨迹 Sparkline:每个维度一条横向折线,显示跨轮 score 演化
- 无数据时显示占位符("数据待补充")而不是隐藏 section
- 一键 Markdown 导出完整推理轨迹
5二级市场:Agent 沙盘
单轮并行模拟。输入市场事件后,4 个 Agent 同时推演。
SHORT_TERM_CAPITAL
短线资金
动量驱动、高频交易、关注技术信号与事件套利
TRADITIONAL_INSTITUTION
传统机构
价值导向、关注基本面、行业定位与长期展望
OFFSHORE_CAPITAL
外资
跨市场视角、汇率敏感、全球宏观感知
执行模型
输入:标的 + 市场事件
→ SecondaryOrchestrator.run()
→ 拉取市场数据 (yfinance, DB 缓存)
→ 4 个 Agent 并行推演 (asyncio.gather)
→ 超时/失败:复用上轮视角或注入默认视角
→ 持久化 AgentSnapshot → SandboxEventRecord
→ InteractionResolver: 聚合多空博弈关系
→ 输出:MarketReadingReport + InteractionResolution
6感知层
推演前的信息预处理阶段 — 正式推演开始前的前置准备。
IntakeAgent
数据源接入
ReAct 风格 Agent:identify_provider → fetch_url → generate_spec → validate_api_call → activate。最多 3 次重试,API Key 永不记录日志。
IntakeOrchestrator
任务编排
将感知计划转为可执行任务:connector_fetch、dataset_repair、manual_context_request。支持串行/并行分批。
ConfidenceGate
质量预检
共享验证逻辑:阻断检查(base_url、endpoints),警告(auth 缺失、field_mapping 为空)。
感知状态机
PENDING → IN_PROGRESS → COMPLETE
↓
confidence_gate.check()
↓
通过:进入推演流程
未通过:请求补充数据或用户输入
7数据源接入系统
通过三策略提供商识别实现自动化数据源集成。
ProviderRecognizer
三策略识别
1. 格式启发式 — 正则匹配 API Key 模式(0.75 置信度)
2. 端点探测 — 向已知端点发起 HTTP 请求(0.9 置信度)
3. LLM 推理 — 基于脱敏 Key 模式推理(兜底)
ConnectorCopilot
自动生成接入配置
读取 API 文档 → 自动生成 ConnectorSpec(provider_id、base_url、auth_type、endpoints、field_mapping 映射到 24 个标准字段)。LLM 不可用时走启发式兜底。
8技术栈
后端
Python 3.11 + FastAPI
Poetry 依赖管理 · SQLAlchemy ORM · Alembic(10 个 migration)· SQLite (MVP) / PostgreSQL (生产)
前端
React 19 + TypeScript 5.9
Vite 8 构建 · Tailwind CSS · SSE 实时流 · 无限画布 (pan/zoom)
LLM
OpenAI-Compatible 异步客户端
SandboxLLMClient · MiniMax / Anthropic / OpenAI / Moonshot · Extended Thinking 兼容 · 运行时 DB 配置
测试 & CI
pytest + Playwright + GitHub Actions
34 unit + 35 extensibility + 2 integration 测试 · E2E @critical 门控 · 3-job PR 流水线 + e2e-full on main
工具框架
可扩展 Agent 工具
ToolRegistry 单例 · WebSearchTool + CompanyDataLookupTool · 最多 2 次工具迭代 · 1500 字符结果截断
数据管线
感知 + 接入栈
IntakeAgent (ReAct) · ConnectorCopilot · ProviderRecognizer(三策略)· ConfidenceGate
9系统架构图
+-------------------------------------------------------------+
| Frontend (React 19 + Vite) |
| |
| ResearchCanvasPage |
| +-- MarketModeSelector (Primary / Secondary toggle) |
| +-- CanvasStage (unified canvas for both modes) |
| | |
| +-- Primary Mode |
| | +-- PrimaryCommandConsole (company + investor + ref) |
| | +-- PrimaryDagLayout (4-layer DAG visualization) |
| | +-- DeepDivePanel (8-section audit slide-over) |
| | +-- VerdictCausalityOverlay (decision trace lines) |
| | |
| +-- Secondary Mode |
| +-- CommandConsole (ticker + event input) |
| +-- 4x AgentNode (radial layout) |
| +-- InteractionSummaryPanel (bull-bear panel) |
+----------------------------+--------------------------------+
| HTTP REST + SSE (X-API-Key)
+----------------------------v--------------------------------+
| API Layer (FastAPI, Port 8000) |
| |
| /api/v1/primary /api/v1/sandbox /api/v1/sources |
| /api/v1/perception /api/v1/connectors /api/v1/upload |
| /api/v1/market /api/v1/settings |
+------+----------------------+-------------------------------+
| |
+------v------+ +------v------+
| Primary | | Secondary |
| Orchestrator| | Orchestrator|
| (multi-round| | (single- |
| DAG + HITL)| | round para)|
+------+------+ +------+------+
| |
+------v------+ +------v------+
| Dimension | | Agent |
| Registry | | Templates |
| (N dims, | | (4 roles) |
| extensible) | | |
+------+------+ +------+------+
| |
+------v-----------+----------v------+
| Services: ContextAssembler | |
| ConvergenceJudge | PathFork(5t) |
| AssumptionChecker | HealthCheck |
| CheckpointMgr | Synthesis |
+------+---------------------------+-+
| |
+------v---------------------------v-+
| LLM Client (OpenAI-compat) |
| MiniMax / Anthropic / Moonshot |
+------+-----------------------------+
|
+------v-----------------------------+
| Perception Layer |
| IntakeAgent | IntakeOrchestrator |
| ConfidenceGate | Reflector |
+------+-----------------------------+
|
+------v-----------------------------+
| Connector System |
| ProviderRecognizer | Copilot |
+------+-----------------------------+
|
+------v-----------------------------+
| Data Layer (SQLAlchemy + SQLite)|
| |
| market_snapshot | sandbox_session |
| checkpoint | agent_snapshot |
| source_connector | perception_ds |
| user_settings | 10 Alembic vers. |
+------------------------------------+
10代码地图
开发时 80% 的时间在这些文件。
| 你要做的事 | 去看这个文件 |
| 理解推演流程 | src/sandbox/orchestrator/primary.py |
| 修改/新增数据结构 | src/sandbox/schemas/primary_market.py |
| 修改维度定义 / 扩展维度 | src/sandbox/schemas/dimension_registry.py — build_default_registry() |
| 修改 LLM prompt | src/sandbox/agents/templates/primary_prompts.py |
| 路径分叉触发规则 | src/sandbox/services/path_fork.py — 5 种 trigger |
| 新增 API 端点 | src/api/routers/primary.py |
| 前端状态管理 | frontend/src/hooks/usePrimaryRun.ts |
| 前端 ↔ 后端数据映射 | frontend/src/lib/api/primary.ts |
| 前端类型定义 | frontend/src/lib/types/primaryCanvas.ts |
| 收敛判断(fast-path + LLM 语义) | src/sandbox/services/convergence.py |
| 维度扩展性测试(35 tests) | tests/unit/test_dimension_extensibility.py — 7 维 / 5 维场景 |
| 上下文组装(S 曲线、投资人、参照系) | src/sandbox/services/context_assembler.py |
| 新增 Agent 工具 | src/sandbox/tools/registry.py + base.py |
| 二级市场编排 | src/sandbox/orchestrator/secondary.py |
| 感知/数据摄入 | src/perception/intake_agent.py |
| 测试规范 + testid 清单 | docs/CI-TESTING-GUIDE.md |
目录结构概览
pyta-research/
+-- src/
| +-- api/ # FastAPI 路由层
| | +-- routers/primary.py # 一级市场核心 API
| | +-- routers/sandbox.py # 二级市场 API
| +-- sandbox/ # 推演引擎核心
| | +-- orchestrator/primary.py # DAG 编排器
| | +-- orchestrator/secondary.py# Agent 沙盘
| | +-- agents/templates/ # LLM prompt 模板
| | +-- schemas/ # Pydantic 数据结构
| | | +-- primary_market.py # 核心数据结构
| | | +-- dimension_registry.py# 维度注册表(单一数据源)
| | | +-- investor_profile.py # 投资人配置
| | +-- services/ # 业务逻辑
| | | +-- convergence.py # 语义收敛
| | | +-- context_assembler.py # S 曲线 + 投资人
| | | +-- path_fork.py # 路径分叉(5 触发类型)
| | +-- tools/ # Agent 工具框架
| | +-- llm/client.py # LLM 客户端
| +-- perception/ # 推演前预处理
| | +-- intake_agent.py # ReAct 数据接入
| | +-- intake_orchestrator.py # 任务编排
| | +-- confidence_gate.py # 质量预检
| +-- data/connectors/ # 数据源接入系统
| +-- db/models.py # 数据库表定义
+-- frontend/src/
| +-- pages/ResearchCanvasPage.tsx # 顶层入口
| +-- components/layout/ # 布局组件
| +-- components/canvas/primary/ # 一级市场 UI
| +-- hooks/usePrimaryRun.ts # 一级市场状态管理
| +-- hooks/useSandboxRun.ts # 二级市场状态管理
| +-- lib/api/primary.ts # API 客户端 + 映射
| +-- lib/types/primaryCanvas.ts # 类型定义
+-- tests/ # pytest(34 unit + 35 extensibility + 2 integration)
+-- frontend/tests/ # Playwright E2E
+-- alembic/versions/ # 10 个 DB migration
11开发全流程
从领取任务到代码合并的完整步骤。
领取任务
从 GitHub Issues 或团队沟通中获取任务
创建分支
git checkout main && git pull origin main
git checkout -b feat/你的功能描述
本地开发 + 自测
启动 dev server:./scripts/dev-up.sh
本地跑 CI 检查
前端:tsc --noEmit && npm run lint && npm run build && npm run test:e2e:critical
后端:poetry run pytest -q
Push 到远端
git push -u origin feat/你的功能描述
创建 PR(必须按模板)
按 .github/pull_request_template.md 的 5 个 section 填写
等 CI 全绿
3 个 job 必须通过:backend + frontend + e2e-critical
在 GitHub 页面 Merge
不要用 gh pr merge 自动合并
12分支与命名规范
分支命名
| 前缀 | 用途 | 示例 |
feat/ | 新功能 | feat/g7-industry-analysis |
fix/ | Bug 修复 | fix/sse-timeout-handling |
refactor/ | 重构 / 代码清理 | refactor/schema-cleanup |
Commit 信息规范
Commit message 说清楚做了什么和为什么,方便后续追溯。
feat: 新增 G7 行业分析模块,补全行业周期判断能力
fix: 修复 SSE 超时后前端未重连,导致 DAG 节点卡在 running
refactor: 拆分 primary_market.py 中 200+ 行的 ValuationAnalysis 到独立文件
update code — 太模糊,无法追溯
fix bug — 没说修了什么 bug
wip — 不应该出现在 main 分支
13PR 规范
强制要求:每个 PR 必须按模板填写,不能用自定义格式替代,不能留空。
PR 模板 5 个 Section
| Section | 内容 |
| 变更摘要 | 一句话说清做了什么、为什么做 |
| 变更类型 | 勾选:新功能 / Bug 修复 / 重构 / 文档 / 配置 |
| 关键改动 | 按模块列出核心变更 + 影响范围 |
| 验证方式 | 跑了什么测试、手动验证了什么场景 |
| Checklist | 代码已自测通过 · 无敏感信息提交 |
合并规则
- 等 CI 3 个 job 全绿后,在 GitHub 页面手动 merge
- 不要用
gh pr merge 自动合并
- CI 未通过时不要强行 merge
14CI 流水线
PR 阶段(合并前必须全过)
backend — Alembic upgrade + pytest
frontend — tsc + ESLint + Vite build
e2e-critical — Playwright @critical 纯 UI 测试
Push to main(合并后)
backend — 同上
frontend — 同上
e2e-full — 全量 E2E 回归(软门控)
本地预检命令(Push 前必须跑)
# 前端
cd frontend
npx tsc --noEmit # TypeScript 编译检查
npm run lint # ESLint
npm run build # Vite 构建
npm run test:e2e:critical # E2E critical 测试
# 后端
cd ..
poetry run pytest -q # Python 测试
全部通过后再 push。CI 失败会阻塞合并。
15测试规范
后端测试(pytest)
poetry run pytest # 全量
poetry run pytest tests/unit/test_xxx.py -v # 单文件
poetry run pytest -s # 带输出
异步测试直接用 async def test_xxx(),asyncio_mode = "auto" 已配置。
前端 E2E 测试(Playwright)
cd frontend
npm run test:e2e # 全量
npm run test:e2e:critical # 只跑 @critical
npx playwright test --ui # 调试模式
data-testid 规范(强制)
所有可测试 UI 元素必须加 data-testid。Playwright 测试必须用 getByTestId()。
命名规则: {区域}-{组件}-{元素}
| 前缀 | 适用范围 | 示例 |
primary- | 一级市场控制台 | primary-run-button, primary-company-input |
dag-node- | DAG 节点 | dag-node-uncertainty, dag-node-verdict |
pm- | 一级市场画布全局 | pm-verdict, pm-stale-banner |
verdict- | 决策结果区 | verdict-confidence, verdict-decision |
mode-selector- | 市场模式切换 | mode-selector-primary |
stage- | 画布舞台 | stage-canvas |
选择器对比
// 正确:用 data-testid
page.getByTestId('primary-run-button')
// 禁止:用文本(文案改了就坏)
page.getByText('开始推演')
// 禁止:用 CSS class(样式改了就坏)
page.locator('.run-btn')
@critical 标记
不依赖后端的纯 UI 测试加 @critical,会在每个 PR 中运行:
test.describe('我的纯 UI 测试 @critical', () => {
test('某个 UI 状态', async ({ page }) => {
// ...
})
})
16代码规范
Schema
新字段必须 Optional
已有 Checkpoint 数据不含新字段,required 会导致反序列化报错。所有新增的 Pydantic model 字段必须设为 Optional。
前端
data-testid 全覆盖
新增组件时,给按钮、输入框、面板容器、关键展示元素加 data-testid,并更新 CI-TESTING-GUIDE.md 清单。
UI 语言
中文优先,英文术语保留
按钮和状态文本用中文;产品术语(Agent、Lens、DAG、Verdict、Deep Dive)保留英文。
环境变量
.env 不提交
.env 已在 .gitignore 中。修改 .env.example 来记录新增变量。敏感信息(API Key 等)绝不入库。
数据全链路规范(新增分析模块时)
# 完整链路:后端 → 前端
Python Pydantic schema # 1. 定义数据结构
→ DimensionRegistry # 2. 注册到 Registry(如果是维度)
→ LLM prompt # 3. 要求 LLM 输出对应 JSON
→ TS interface # 4. 前端类型定义
→ PrimaryReportRaw # 5. API 原始响应
→ snake → camelCase # 6. 数据映射
→ DAG Node # 7. DAG 执行图渲染
→ Deep Dive section # 8. 审计层展示
17数据库变更流程
新增 Model
在 src/db/models.py 添加 SQLAlchemy model
生成 Migration
poetry run alembic revision --autogenerate -m "描述"
检查 Migration 文件
在 alembic/versions/ 下检查生成的 migration 是否正确
应用 Migration
poetry run alembic upgrade head
MVP 阶段:FastAPI 启动时自动 create_all,日常开发无需手动跑 migration。Alembic 主要用于 CI 验证和生产部署。当前共 10 个 migration 版本。
关键表
| 分组 | 表 | 用途 |
| 市场数据 | market_snapshot · raw_price · raw_fundamental · raw_macro | 价格 / 基本面 / 宏观数据缓存 |
| 推演持久化 | sandbox_session · checkpoint · report_record · agent_snapshot | 沙盘状态 + 每轮快照 + 推演报告 |
| 数据源 | source_connector · source_event · connector_spec_draft | 外部数据源配置 + 市场事件 |
| 感知 | perception_dataset · prepared_perception_context | 上传数据集 + 预处理后的感知上下文 |
| 用户配置 | user_settings | LLM 配置 + 投资人画像 + 参照系 |
18高风险文件 & 合并注意事项
以下文件被多个模块依赖,修改时需格外小心:
| 文件 | 风险原因 |
src/api/app.py | 路由注册 + 应用 lifespan,改错影响全局 |
src/sandbox/schemas/primary_market.py | 核心数据结构,几乎所有模块依赖 |
src/sandbox/schemas/dimension_registry.py | 维度定义,影响所有维度 Agent |
frontend/src/pages/ResearchCanvasPage.tsx | 顶层页面路由 |
frontend/src/components/layout/CanvasStage.tsx | 画布主舞台(1600+ 行,两种市场模式) |
frontend/src/lib/types/primaryCanvas.ts | 前端类型定义,改动影响所有组件 |
frontend/src/lib/api/primary.ts | API 客户端 + 数据映射 |
合并原则
- 修改前先
git pull origin main 确保最新
- 分支落后且有冲突时,优先从最新 main 重建分支
- 详细冲突处理流程见
docs/BRANCH_CONFLICT_PLAYBOOK.md
- 不要在这些文件上做大范围重构而不提前沟通
19常见开发场景
- 定义 DimensionDescriptor →
dimension_registry.py 的 build_default_registry() 中添加(dimension_id, label, prompt_focus, is_critical, sort_order, special_outputs)
- 定义数据结构 →
primary_market.py 新增 Pydantic model(新字段必须 Optional)
- 如有 special_outputs → 在 descriptor 的
special_outputs 中声明,Orchestrator 通过 dimension_for_output() 自动关联
- 编写 prompt →
primary_prompts.py(prompt_focus 从 registry 读取,无需硬编码)
- 前端类型 →
primaryCanvas.ts 的 KnownDimension(可选 — string escape hatch 已支持动态 ID)
- 前端标签 →
DIMENSION_LABELS 添加中文标签(fallback 到 raw ID)
- 数据映射 →
primary.ts snake → camelCase
- 运行扩展性测试 →
poetry run pytest tests/unit/test_dimension_extensibility.py -v(35 tests 覆盖 7 维 / 5 维场景)
注:Orchestrator 的 dispatch 循环由 registry.get_default_set() 驱动,无需在 orchestrator 中手动注册新维度。
- 修改
src/sandbox/agents/templates/primary_prompts.py
poetry run pytest -q 确认不破坏测试
- 手动运行一次推演验证 LLM 输出质量
- 在
src/api/routers/primary.py 或新建 router 文件添加端点
- 如需新表 →
src/db/models.py + Alembic migration
- 前端对接 →
frontend/src/lib/api/primary.ts
- 添加测试
- 修改对应组件
- 给新增元素加
data-testid
- 更新
docs/CI-TESTING-GUIDE.md 中的 data-testid 清单
npm run test:e2e:critical 确认不破坏现有测试
- 调用
POST /primary/{id}/resume-stream 恢复推演
- 系统比对当前 Registry 与 Checkpoint 中的维度集,跳过不再存在的维度
- 跳过的维度记入
restore_skipped_dims,含 skipped dims 的轮次自动跳过 convergence check
- SSE 推送
DATA_QUALITY_WARNING 事件 → 前端展示数据完整性警告
- 最终 Report 标记
restore_integrity: "partial" + skipped_dimensions_by_round
- 在
src/data/connectors/recognizer.py 中添加格式正则(ProviderRecognizer)
- 添加该提供商的端点探测逻辑
- 验证 ConnectorCopilot 能从提供商 API 文档生成 spec
- 在
src/data/connectors/copilot.py 中添加标准字段映射
- 通过
/api/v1/connectors 端点测试
20快速启动
5 步环境搭建
# 1. 克隆
git clone git@github.com:justicengg/pyta-research.git
cd pyta-research
# 2. 后端依赖
poetry install
# 3. 前端依赖
cd frontend && npm install && cd ..
# 4. 环境变量
cp .env.example .env
# 编辑 .env 或启动后在前端 UI 配置 LLM
# 5. 启动
./scripts/dev-up.sh
常用命令速查
| 场景 | 命令 |
| 启动服务 | ./scripts/dev-up.sh |
| 停止服务 | ./scripts/dev-down.sh |
| 健康检查 | ./scripts/dev-check.sh |
| 后端测试 | poetry run pytest -q |
| 前端全部检查 | cd frontend && npx tsc --noEmit && npm run lint && npm run build |
| E2E critical | cd frontend && npm run test:e2e:critical |
| Swagger 文档 | http://127.0.0.1:8000/docs |
| 数据库 migration | poetry run alembic upgrade head |
服务地址
前端
http://127.0.0.1:5173
后端 API
http://127.0.0.1:8000
Swagger
http://127.0.0.1:8000/docs
LLM 配置
两种方式(UI 优先级更高):
方式 1:.env 文件
设置 LLM_API_KEY、LLM_BASE_URL、LLM_MODEL
方式 2:前端 UI(推荐)
启动后在页面左侧设置面板配置 Base URL、Model、API Key。存储在本地 DB,不出现在请求中。
一级市场核心 API
| 方法 | 端点 | 说明 |
POST | /primary/run-stream | SSE 流式推演(接受 investor_profile + benchmarks) |
GET | /primary/investor-profile | 获取投资人画像 |
PUT | /primary/investor-profile | 更新投资人画像 |
DELETE | /primary/investor-profile | 重置为默认 |
POST | /primary/{id}/confirm-proposals | HITL Gate:确认环境修正提案 |
POST | /primary/{id}/resume-stream | 从 Checkpoint 恢复推演 |
POST | /primary/upload-company-data | CSV 上传(UTF-8 / GBK) |
PYTA Research Team · 系统 Onboarding · 更新于 2026-04