Files
group_fqcd_jr/start.ps1
T
lzf_0626 bfd3964ef8 feat(demo): 演示数据一键准备、启动脚本与演示流程文档
交付"别人能自己把系统跑起来做演示"所需的四件东西:

- tools/seed_demo_data.py      演示数据一键准备:10 步按依赖排序
  (此前散在 10 个脚本里,没人知道该跑哪些、按什么顺序跑,且知识库那步
  根本没有脚本、靠手工调接口)
- tools/seed_knowledge_demo.py 知识库演示素材灌入,幂等(先删同 source_file 再灌)
- start.ps1                    启动 API + Worker,含依赖检查与**自动刷新行情**
- docs/44-演示流程.md           8 个主线场景的照读流程 + 排障表 + 账号/命令速查

两条硬约束同时写进了脚本和文档:

1. **Worker 必须常驻**:没有它客服对话一直停在 queued(前端只显示"超时")、
   新知识不进 Milvus 且**没有任何报错**。
2. **行情有效期仅 15 分钟**(`trade_service.MAX_QUOTE_AGE`):超时后所有委托
   直接 503「行情已过期」,而系统**没有自动刷新机制**。故 start.ps1 启动时刷一次,
   文档另给"演示中途 503 时补刷、无需重启服务"的处置方法(已实测)。

实测证据:
- start.ps1 在 8099 完整启动,`/docs` 与 `/portal/` 均 HTTP 200(测试进程已清理)
- `tools/e2e_smoke_test.py` → 40/40 通过
- `tools/seed_demo_data.py --dry-run` → 10 步全部正常列出
- 文档中的下单命令实跑:510300 成交价 4.579、金额 457.90、手续费 0.05
2026-09-13 21:56:27 +08:00

168 lines
7.8 KiB
PowerShell
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<#
.SYNOPSIS
启动金融 Agent 平台:依赖检查 → API → Agent Worker。
.NOTES
⚠️ 本文件必须保存为 **UTF-8 with BOM**。
Windows PowerShell 5.1 在缺少 BOM 时按系统 ANSI 解析脚本(简体中文下是 GBK),
中文注释与输出会变成乱码并直接抛语法错误(实测报 `Unexpected token '[璀﹀憡]'`)。
用编辑器改完本文件后,务必另存为「UTF-8 带 BOM」。
.DESCRIPTION
平台需要**两个进程**才能完整工作,本脚本把它们一起起在独立窗口里:
· API —— 所有 HTTP 接口与前端页面(/portal/)
· Worker —— 消费队列:Agent 对话、知识向量同步、记忆抽取、风控扫描
**没有 Worker 的后果**(这也是最容易踩的坑):
· 客服对话会一直停在 queued,前端显示"客服繁忙/超时";
· 新灌的知识写不进 Milvus,客服照旧答不上,且**没有任何报错**。
.PARAMETER Port
API 监听端口,默认 8000。
.PARAMETER SkipChecks
跳过依赖端口检查(MySQL / Redis / Milvus)。
.PARAMETER ApiOnly
只起 API,不起 Worker(仅在明确不需要 Agent 能力时使用)。
.PARAMETER SkipPriceSync
跳过启动时的行情刷新。仅在外部数据源不可用、或不想联网时使用。
.EXAMPLE
powershell -ExecutionPolicy Bypass -File start.ps1
powershell -ExecutionPolicy Bypass -File start.ps1 -Port 8100
#>
param(
[int]$Port = 8000,
[switch]$SkipChecks,
[switch]$ApiOnly,
[switch]$SkipPriceSync
)
$ErrorActionPreference = "Stop"
$Root = $PSScriptRoot
Set-Location $Root
Write-Host "=== 金融 Agent 平台 · 启动 ===" -ForegroundColor Cyan
Write-Host "工作目录:$Root"
# ---------------------------------------------------------------- 解释器
# 逐个尝试:项目虚拟环境 → 常见 conda 环境 → PATH 上的 python。
# 不写死任何一个,因为各人机器的环境不同(.venv 被 gitignore,不进仓库)。
$candidates = @(
(Join-Path $Root ".venv\Scripts\python.exe"),
"D:\conda\envs\jr_py313\python.exe",
"python"
)
$Python = $null
foreach ($candidate in $candidates) {
try {
if ($candidate -eq "python") {
$version = & python --version 2>&1
} else {
if (-not (Test-Path $candidate)) { continue }
$version = & $candidate --version 2>&1
}
if ($LASTEXITCODE -eq 0) {
$Python = $candidate
Write-Host "解释器:$candidate($version)" -ForegroundColor Green
break
}
} catch { continue }
}
if (-not $Python) {
Write-Host "[失败] 找不到可用的 Python。请先建虚拟环境,或把解释器路径加进本脚本的候选列表。" -ForegroundColor Red
exit 1
}
# ---------------------------------------------------------------- 依赖检查
if (-not $SkipChecks) {
Write-Host "`n--- 依赖服务检查 ---" -ForegroundColor Cyan
$services = @(
@{ Name = "MySQL"; HostName = "127.0.0.1"; Port = 3306; Required = $true },
@{ Name = "Redis"; HostName = "127.0.0.1"; Port = 6379; Required = $false },
@{ Name = "Milvus"; HostName = "127.0.0.1"; Port = 19530; Required = $false }
)
foreach ($service in $services) {
$reachable = $false
try {
$reachable = (Test-NetConnection -ComputerName $service.HostName -Port $service.Port `
-InformationLevel Quiet -WarningAction SilentlyContinue)
} catch { $reachable = $false }
if ($reachable) {
Write-Host (" [OK] {0,-7} {1}:{2}" -f $service.Name, $service.HostName, $service.Port) -ForegroundColor Green
} elseif ($service.Required) {
Write-Host (" [缺失] {0,-7} {1}:{2} —— 平台起不来,请先启动它" -f $service.Name, $service.HostName, $service.Port) -ForegroundColor Red
exit 1
} else {
Write-Host (" [警告] {0,-7} {1}:{2} 不可达:相关知识检索会降级、Docker 未运行时常见" -f $service.Name, $service.HostName, $service.Port) -ForegroundColor Yellow
}
}
}
# ---------------------------------------------------------------- 刷新行情
# ⚠️ 为什么放在启动流程里:下单要求行情快照落在 **15 分钟**有效期内
# (`app/service/trade_service.py` 的 `MAX_QUOTE_AGE`),超时后**所有委托直接 503
# 「行情已过期」**,而系统**没有任何自动刷新机制** —— 演示时讲到一半下单就会失败。
# 所以默认在启动时刷一次:15 分钟窗口从此刻重新计时。
# 同步是按产品 upsert 的幂等操作;失败只警告不阻断(仍可手动重跑)。
if (-not $SkipPriceSync) {
Write-Host "`n--- 刷新行情(下单前置,有效期 15 分钟)---" -ForegroundColor Cyan
$syncOutput = & $Python "tools\sync_market_prices.py" 2>&1
if ($LASTEXITCODE -eq 0) {
Write-Host " [OK] 行情已刷新,15 分钟内可正常下单" -ForegroundColor Green
} else {
Write-Host " [警告] 行情刷新失败(退出码 $LASTEXITCODE):下单可能返回 503" -ForegroundColor Yellow
Write-Host " 可手动重跑:$Python tools\sync_market_prices.py" -ForegroundColor Yellow
$syncOutput | Select-Object -Last 8 | ForEach-Object { Write-Host " $_" -ForegroundColor DarkGray }
}
}
# ---------------------------------------------------------------- 启动进程
# 用独立窗口起,方便分别看两边的日志(Worker 的日志是排查问题的第一现场)。
function Start-PlatformWindow {
param([string]$Title, [string[]]$Arguments)
$shell = if (Get-Command pwsh -ErrorAction SilentlyContinue) { "pwsh" } else { "powershell" }
$command = "`$host.UI.RawUI.WindowTitle = '$Title'; & '$Python' " + ($Arguments -join " ")
Start-Process -FilePath $shell -ArgumentList "-NoExit", "-Command", $command | Out-Null
}
Write-Host "`n--- 启动进程 ---" -ForegroundColor Cyan
Start-PlatformWindow -Title "平台 API :$Port" -Arguments @(
"-m", "uvicorn", "app.main:app", "--host", "127.0.0.1", "--port", "$Port"
)
Write-Host " [已启动] API 窗口(uvicorn,端口 $Port)" -ForegroundColor Green
if (-not $ApiOnly) {
Start-PlatformWindow -Title "平台 Agent Worker" -Arguments @("-m", "app.worker")
Write-Host " [已启动] Worker 窗口(Agent 对话 / 知识向量 / 记忆抽取)" -ForegroundColor Green
} else {
Write-Host " [跳过] Worker(-ApiOnly):客服对话会一直 queued、新知识不会进 Milvus" -ForegroundColor Yellow
}
# ---------------------------------------------------------------- 访问入口
Start-Sleep -Seconds 3
Write-Host "`n=== 访问入口 ===" -ForegroundColor Cyan
Write-Host " 门户首页 http://127.0.0.1:$Port/portal/"
Write-Host " 访客页 http://127.0.0.1:$Port/portal/guest/home/"
Write-Host " 客户登录 http://127.0.0.1:$Port/portal/customer/login/ (cust_t / 123456)"
Write-Host " 员工登录 http://127.0.0.1:$Port/portal/employee-console/login/(见下)"
Write-Host " 接口文档 http://127.0.0.1:$Port/docs"
Write-Host "`n=== 演示账号 ===" -ForegroundColor Cyan
Write-Host " 客户 cust_t / 123456"
Write-Host " 风控专员 risk_t / 666666"
Write-Host " 管理员 admin_t / 88888888"
Write-Host " 投顾 advisor_t / abc12345"
Write-Host " 运营 offsite_t / offsite123"
Write-Host "`n提示:" -ForegroundColor Yellow
Write-Host " · 首次使用先准备数据:python tools/seed_demo_data.py"
Write-Host " · 行情有效期只有 15 分钟:演示中途下单若报 503,在新窗口重跑"
Write-Host " python tools/sync_market_prices.py (立即生效,无需重启服务)"
Write-Host " · 体检:python tools/e2e_smoke_test.py"
Write-Host " · 演示流程见 docs/44-演示流程.md"