Files
group_fqcd_jr/demo.ps1
T
张胜宇 9675df8453 chore(sync): zsy_developcc 全量同步至 qyqy_develop(W26 口径)
- 分支内容对齐 qyqy_develop b6ec3aa,树完全一致(同步后 git diff 为空)
- 覆盖本轮全部交付:客服 Agent 重构(安全路由 / 五出口 / 记忆与画像 / RAG 全链路)
  + 开发文档 62 份编号体系(D1.1 v1.17 索引)
  + 新增 D2.10-客服Agent端到端答辩文档-2026-09-21.html
- 基线:e239eb7(2026-09-17 品牌口径统一快照),本提交为其直接后继
2026-09-21 21:26:30 +08:00

221 lines
10 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 演示 · 前端一键启动(服务拉起 + 五项自检 + 打开演示页面)
.DESCRIPTION
真正的服务拉起交给同目录的 `start.ps1`(**幂等**:缺什么补什么,重复执行不会起出
第二个 API/Worker)。本脚本在它之上补三件事:
1. **刷新行情** —— 下单要求行情快照落在 **15 分钟**有效期内
(`app/service/trade_service.py` 的 `MAX_QUOTE_AGE`),过期后所有委托直接
503「行情已过期」,而系统**没有自动刷新机制**;所以每次启动都刷一次。
2. **五项自检** —— 口径与 `客服agent\D2.5` §1 一致(容器 / 向量库 / Worker / 行情 / 向量库开关)。
3. **打开前端页面** —— 访客页(客服浮窗主战场)与客户登录页。
⚠️ **登录限流**:`.env` 的 `RATE_LIMIT_*` 是 **10 次 / 60 秒**。演示时不要反复登录 ——
连续登录会让后续用例整片报红,看起来像「客服坏了」,其实是限流。
.PARAMETER Port
API 端口,默认 8000(与 `start.ps1 -Port` 同义)。
.PARAMETER SkipStart
不调 `start.ps1`,只做自检 + 开页面(服务已经在跑时用)。
.PARAMETER NoBrowser
不自动打开浏览器。
.PARAMETER KeepPrices
不刷新行情(只看自检结果时用)。
.EXAMPLE
双击 `启动演示.bat`
powershell -ExecutionPolicy Bypass -File demo.ps1 -SkipStart -NoBrowser
.NOTES
本文件必须保存为 **UTF-8 with BOM**(理由同 `start.ps1`:缺 BOM 时 Windows PowerShell 5.1
按 ANSI 解析,中文会乱码并抛语法错误)。
#>
param(
[int]$Port = 8000,
[switch]$SkipStart,
[switch]$NoBrowser,
[switch]$KeepPrices
)
$ErrorActionPreference = "Continue"
$Root = $PSScriptRoot
Set-Location $Root
$Python = Join-Path $Root ".venv\Scripts\python.exe"
if (-not (Test-Path $Python)) { $Python = "python" }
$Base = "http://127.0.0.1:$Port"
$script:Fails = 0
function Section($text) { Write-Host ""; Write-Host "--- $text ---" -ForegroundColor Cyan }
function Ok($text) { Write-Host " [OK] $text" -ForegroundColor Green }
function Warn($text) { Write-Host " [警告] $text" -ForegroundColor Yellow; $script:Fails++ }
function Bad($text) { Write-Host " [失败] $text" -ForegroundColor Red; $script:Fails++ }
function Test-ApiRunning {
try {
$null = Invoke-WebRequest -Uri "$Base/internal/health/ready" -TimeoutSec 2 -UseBasicParsing -ErrorAction Stop
return $true
} catch { return $false }
}
function Wait-ApiReady {
for ($i = 1; $i -le 30; $i++) {
if (Test-ApiRunning) { return $true }
Start-Sleep -Seconds 1
}
return $false
}
Write-Host "============================================================" -ForegroundColor Cyan
Write-Host " 客服 Agent 演示 · 前端一键启动" -ForegroundColor Cyan
Write-Host "============================================================" -ForegroundColor Cyan
Write-Host "工作目录:$Root"
Write-Host "Python :$Python"
$apiWasRunning = Test-ApiRunning
# ---------------------------------------------------------------- 0. 拉起服务
if ($SkipStart) {
Section "0 服务拉起(-SkipStart:跳过 start.ps1)"
if ($apiWasRunning) { Ok "API 已在跑,直接进入自检" } else { Bad "API 未就绪,且按 -SkipStart 未拉起服务" }
} else {
Section "0 服务拉起(调用 start.ps1,幂等)"
& (Join-Path $Root "start.ps1") -Port $Port -NoBrowser -SkipPriceSync
if ($LASTEXITCODE -eq 1) { Bad "start.ps1 判定依赖缺失(常见:MySQL 未启动)—— 详见上方输出" }
}
Section "等待 API 就绪"
if (Wait-ApiReady) { Ok "API 已就绪:$Base/internal/health/ready" }
else { Bad "等了 30 秒仍未就绪:切到 API 窗口看报错(常见原因是数据库连不上)" }
# ---------------------------------------------------------------- 1~5. 五项自检
Section "自检 1/5 · 容器运行时(Milvus 三件套)"
if (Get-Command docker -ErrorAction SilentlyContinue) {
$containers = @(& docker ps --format "{{.Names}} {{.Status}}" 2>$null)
$milvus = @($containers | Where-Object { $_ -like "*milvus*" })
if ($milvus.Count -ge 3) { Ok "milvus 容器 $($milvus.Count) 个在跑:$($milvus -join " | ")" }
elseif ($milvus.Count -gt 0) { Warn "只看到 $($milvus.Count) 个 milvus 容器(期望 3 个:standalone / etcd / minio)" }
else { Warn "没看到 milvus 容器:知识检索会静默降级,先起 Docker Desktop" }
} else {
Warn "没找到 docker 命令,本项跳过"
}
Section "自检 2/5 · 向量库可查(四个集合计数)"
$probe = @'
import sys
sys.path.insert(0, '.')
from app.core.config import get_settings as g
from pymilvus import MilvusClient
client = MilvusClient(uri=g().resolved_milvus_uri)
for name in ("fin_faq_collection", "fin_product_collection", "fin_policy_collection", "fin_basic_collection"):
print(name, client.query(collection_name=name, filter='', output_fields=['count(*)']))
'@
# 经 stdin 送给 python,不走命令行参数:PowerShell 5.1 传原生命令参数时会吞掉内嵌双引号,
# 而这段探测代码必须保留字符串字面量(集合名与 output_fields)。
$probeOut = $probe | & $Python - 2>&1
if ($LASTEXITCODE -eq 0 -and (($probeOut | Out-String) -like "*count*")) {
Ok "四个集合可查(含 fin_basic_collection 补充语料):"
$probeOut | ForEach-Object { Write-Host " $_" -ForegroundColor DarkGray }
} else {
Warn "向量库探测失败:知识题会走 E5b 兜底(答不出但不会编)"
$probeOut | Select-Object -Last 4 | ForEach-Object { Write-Host " $_" -ForegroundColor DarkGray }
}
Section "自检 3/5 · Agent Worker 在跑"
$pythonProcs = Get-CimInstance Win32_Process -Filter "Name like '%python%'" -ErrorAction SilentlyContinue
$workerProcs = @($pythonProcs | Where-Object { $_.CommandLine -like "*app.worker*" })
if ($workerProcs.Count -gt 0) { Ok "Worker 在跑(PID $($workerProcs[0].ProcessId))" }
else { Bad "没有 Worker:客服对话会一直 queued,前端显示「繁忙 / 超时」" }
Section "自检 4/5 · 行情有效期(下单前置,15 分钟)"
if ($KeepPrices) {
Warn "按 -KeepPrices 跳过刷新:若距上次刷新超过 15 分钟,下单会 503"
} else {
$syncOut = & $Python "tools\sync_market_prices.py" 2>&1
if ($LASTEXITCODE -eq 0) {
Ok "行情已刷新,15 分钟窗口从此刻重新计时"
$syncOut | Where-Object { $_ -like "*落库*" } | ForEach-Object { Write-Host " $_" -ForegroundColor DarkGray }
} else {
Warn "行情刷新失败(退出码 $LASTEXITCODE):下单可能返回 503"
$syncOut | Select-Object -Last 5 | ForEach-Object { Write-Host " $_" -ForegroundColor DarkGray }
}
}
Section "自检 5/5 · 本地向量库开关(应为空:非空会绕过服务端 Milvus)"
$switchOut = & $Python -c "import sys; sys.path.insert(0, '.'); from app.core.config import get_settings as g; print(repr(g().milvus_local_uri)); print(g().resolved_milvus_uri)" 2>&1
if ($LASTEXITCODE -eq 0) {
$localUri = ($switchOut | Select-Object -First 1)
if ($localUri -eq "''") { Ok "milvus_local_uri 为空(符合预期);resolved = $($switchOut | Select-Object -Last 1)" }
else { Warn "milvus_local_uri 不为空:$localUri —— 演示前请清空该开关" }
} else {
Warn "配置读取失败"
$switchOut | Select-Object -Last 4 | ForEach-Object { Write-Host " $_" -ForegroundColor DarkGray }
}
# ---------------------------------------------------------------- 演示入口
$guestUrl = "$Base/portal/guest/home/"
$customerUrl = "$Base/portal/customer/login/"
$staffUrl = "$Base/portal/employee-console/login/"
Section "演示入口"
Write-Host " 访客页(客服浮窗主战场) $guestUrl"
Write-Host " 客户登录 $customerUrl"
Write-Host " 员工登录(风控/运营/管理员)$staffUrl"
Write-Host " 投顾工作台 $Base/portal/employee-advisor/dashboard/"
Write-Host " 接口文档 $Base/docs"
if ($NoBrowser) {
Write-Host " (-NoBrowser:未自动打开浏览器)" -ForegroundColor DarkGray
} elseif (Test-ApiRunning) {
try {
Start-Process $guestUrl | Out-Null
Start-Sleep -Milliseconds 600
Start-Process $customerUrl | Out-Null
Ok "已打开两个页面(访客页 / 客户登录)"
} catch {
Warn "自动打开浏览器失败,请手动访问上面的地址"
}
}
# ---------------------------------------------------------------- 账号与提醒
Section "演示账号(实测可登录)"
Write-Host " 客户 cust_t / 123456"
Write-Host " 风控专员 risk_t / 666666"
Write-Host " 管理员 admin_t / 88888888"
Write-Host " 运营 offsite_t / offsite123"
Write-Host " 投顾 advisor_t / abc12345 (2026-09-20 恢复)"
Write-Host " review_t :登录返回 401 是设计如此(只作权限夹具)" -ForegroundColor DarkGray
Section "开讲前必看"
Write-Host " · 登录限流 10 次 / 60 秒:不要反复登录,否则后续整片报红(假故障)"
Write-Host " · 行情 15 分钟:中途下单报 503 就在新窗口重跑"
Write-Host " & `"$Python`" tools\sync_market_prices.py"
Write-Host " · 演示台词与话术:客服agent\D2.5-客服Agent演示脚本与账号速查-2026-09-19.md"
Write-Host " · 答辩问答准备 :客服agent\D2.6-客服Agent答辩报告-2026-09-19.md"
if ($apiWasRunning -and -not $SkipStart) {
Section "提示:服务已在跑,本次没有新开日志窗口"
Write-Host " 当前 API/Worker 可能是无窗口方式启动的。想要可见日志窗口,先停掉再双击本脚本:"
$stopCmd = @'
Get-CimInstance Win32_Process -Filter "Name like '%python%'" | Where-Object { $_.CommandLine -match 'uvicorn app.main:app|app.worker' } | ForEach-Object { Stop-Process -Id $_.ProcessId -Force }
'@
Write-Host $stopCmd -ForegroundColor DarkGray
}
Write-Host ""
Write-Host "============================================================" -ForegroundColor Cyan
if ($script:Fails -eq 0) {
Write-Host " 五项自检全过,演示环境就绪。" -ForegroundColor Green
} else {
Write-Host " 自检有 $script:Fails 项需要处理,见上方 [警告] / [失败] 行。" -ForegroundColor Yellow
}
Write-Host " 服务在独立窗口里运行,关掉本窗口不影响它们。" -ForegroundColor Cyan
Write-Host "============================================================" -ForegroundColor Cyan
if ($script:Fails -gt 0) { exit 1 } else { exit 0 }