NexusMind Inference 是面向算法岗位的在线推理工程项目:把项目一的
Qwen3-0.6B SFT+DPO 客服模型与项目二的金融研报 RAG 接入同一个 FastAPI
网关,并围绕缓存、限流、超时/OOM 降级、引用、guardrail、指标和可复现证据
建立完整工程闭环。GitHub Pages 提供无需后端的只读证据视图;/demo 保留为
本地完整交互工作台。
python -m build 生成的 wheel 用于源码快照、元数据与基础工具模块分发;完整服务
仍依赖显式配置的项目一模型资产、项目二 RAG 数据以及可选 Redis/vLLM 运行时,
不能把 wheel 描述为自带模型与数据的独立部署包。
| 证据 | 结果 | 边界 |
|---|---|---|
| Windows 本地模型,8-token,32 并发 | P95 10.742s,QPS 2.774 |
瓶颈为单模型锁排队,不是生产 SLA |
| 热点缓存,32 并发 | P95 27.318ms,QPS 1012.745 |
仅网关缓存路径,不能代表生成延迟 |
| WSL2 vLLM 0.8.5 Base | 5/5 完整,P95 790.871ms |
单序列 Base smoke,不是 adapter 质量 |
| 项目一 rank-16 DPO LoRA | 1 条 HTTP 200,8/8 serving 断言 | 只证明 adapter serving 路径 |
| Windows CPU 动态 INT8 | 1.0629s -> 0.4620s,约 2.301x |
输出变化、RSS 未下降,未评估质量 |
| 轻量自动化测试 | 123/123 PASS |
mock/合成契约,不加载模型或真实流量 |
123/123 是发布前冻结的核心服务契约基线。公开副本另新增 10/10 发布边界审计;
当前执行上面的全量发现命令会得到 133/133 PASS。发布审计不应冒充模型质量或
线上稳定性测试。
公开仓库只保留聚合报告、冻结标识和机器可读契约;完整 holdout、逐请求回答、 原始服务日志、模型权重及本机路径留在私人权威证据归档中。
本项目复现“项目一客服模型 + 项目二金融研报 RAG 的在线推理服务部署”。当前机器以 Windows 为主,并通过 WSL2 补齐 Linux CUDA 实验:
- Windows 可落地实测:
Transformers + 项目一 SFT+DPO 合并模型 + FastAPI/in-process 压测。 - Linux/WSL 真实实测:
vLLM 0.8.5 + Qwen3-0.6B已完成 Base 5 请求冒烟;另以 512-token、单序列、0.55 显存利用率真实加载项目一 rank-16 DPO LoRA,并完成 1 条 OpenAI-compatible adapter 请求。AWQ/GPTQ 仍未实测。
推荐为本仓库创建独立的 Python 3.10 虚拟环境。启动脚本会优先选择项目内 .venv,因此不依赖当前工作区的共享解释器。
该路径不加载本地大模型,适合先验证页面、API 网关、缓存、限流和降级契约:
cd NexusMind-Inference
py -3.10 -m venv .venv
.\.venv\Scripts\python.exe -m pip install --upgrade pip setuptools wheel
.\.venv\Scripts\python.exe -m pip install -e ".[test,serve]"
.\.venv\Scripts\python.exe -m pip install torch==2.2.1 --index-url https://download.pytorch.org/whl/cpu
.\.venv\Scripts\python.exe -m pip install -e ".[retrieval,local-model]"
.\scripts\probe_compatible_python.ps1
.\run_service_safe.ps1浏览器打开 http://127.0.0.1:8013/demo。当前完整回归命令为:
.\.venv\Scripts\python.exe -B -m unittest discover -s tests -p "test_*.py"其中 123 项是冻结核心契约,新增 10 项验证公开身份、单根历史、文件大小、模型/
原始证据排除及凭据/本机路径边界。也可单独运行
.\.venv\Scripts\python.exe -B scripts\verify_public_release.py。
需要运行项目一合并模型时,把上面的 CPU PyTorch 安装命令替换为:
.\.venv\Scripts\python.exe -m pip install torch==2.2.1+cu118 --index-url https://download.pytorch.org/whl/cu118随后运行 .\run_model_artifact_check.ps1,确认 models/qwen3_06b_ecom_sft_dpo_merged 的大小和 SHA-256 均通过,再使用 .\run_windows_local_model_smoke.ps1。CUDA 驱动、2.22 GiB 模型权重和项目一/二数据不由 pip 安装,必须按模型 manifest 与项目数据说明单独准备。
requirements.txt 是可安装的直接依赖区间;requirements-windows-tested.txt 是本机已验证版本的证据记录。后者包含带 CUDA 构建标记的 PyTorch,不能脱离对应 PyTorch 包源直接当作通用安装命令。
客服链路严格使用项目一训练后的模型,而不是通用 Ollama:
- Base model:
Qwen/Qwen3-0.6B - 项目一最终 LoRA:
<WORKSPACE_ROOT>/项目一/experiments/ecommerce_customer_service/outputs/trl_qwen3_06b_lora_dpo_rank16_beta01_200steps/checkpoint-200 - 训练顺序:项目一 SFT adapter 作为 DPO 初始化,因此该 checkpoint 是
SFT + DPO后的最终 LoRA。 - Windows 合并模型(随工作区交付):
models/qwen3_06b_ecom_sft_dpo_merged - 服务模型名:
ecom-customer-sft-dpo-merged
模型解析顺序为:显式 LOCAL_MODEL_DIR > 工作区 models/qwen3_06b_ecom_sft_dpo_merged > manifest 中的兼容回退。换电脑时不依赖原机器的绝对路径。
已检查本地 项目三/vllm-main,但 vLLM CUDA serving 不作为 Windows 原生运行方案。2026-07-21 已在 F 盘 WSL2 Ubuntu 24.04 中真实安装 vLLM 0.8.5、torch 2.6.0+cu124,以 FP16/1024-token/单序列模式启动 Qwen3-0.6B Base:/health 返回 200,5/5 请求非空且完整结束,Mean/P95 为 473.400/790.871 ms。加载后 GPU 总占用约 3,834/4,096 MiB,已接近显存上限;该实验没有加载项目一 adapter,也没有验证高并发、长上下文或生产质量。详见 reports/vllm_wsl_real_experiment_20260721.md。
2026-07-24 的独立 post-Final 工程冒烟没有改写上述 Base 历史证据:冻结 Base revision 与 adapter SHA 后,vLLM /v1/models 同时列出 Base 和 project1-dpo-beta01-r16,服务日志确认 LoRA 加载;随后 /v1/chat/completions 返回 HTTP 200,响应 model 精确等于 adapter alias,8/8 请求断言通过。服务随即关闭并确认显存归零。该单请求只证明 adapter serving 路径可运行,不证明业务质量、吞吐、长上下文或生产就绪。证据见 reports/project1_adapter_vllm_evidence.md。
所有正式启动脚本统一使用 src.app:app。该 canonical 入口默认加载已严格评测的 Dense + 文档多样化、引用增强和金融证据 guardrail;未经验证优于 Dense 的 Hybrid/RRF 默认关闭,仅能通过 FINANCE_RAG_ENABLE_HYBRID_RRF=1 作为 experimental 模式显式启用。模型权重仍在首次请求时延迟加载。
页面页眉提供 TRACE-Rec 与 ForgeSight-AD 两个已发布的独立作品入口。它们只用于作品集导航,不进入项目一至三的模型、数据、请求调用链或 readiness,也不能描述为多项目全链路。
不加载本地大模型,验证 API 网关、缓存、限流、降级、metrics:
cd <WORKSPACE_ROOT>\项目三\online_inference_service
.\run_service_safe.ps1可访问:
GET http://127.0.0.1:8013/healthGET http://127.0.0.1:8013/metricsPOST http://127.0.0.1:8013/api/askGET http://127.0.0.1:8013/demoPOST http://127.0.0.1:8013/api/deploy/ask
推荐用这个入口验证项目一最终模型,因为它不启动长驻服务,避免窗口闪退:
cd <WORKSPACE_ROOT>\项目三\online_inference_service
.\run_windows_local_model_smoke.ps1本地运行会生成完整样例;公共仓库不发布 prompt/answer 原文,只保留聚合证据。
历史并发基准使用 8-token 短输出、no-cache,并按 1/4/8/16/32 并发运行;它适合定位排队瓶颈,不代表完整回答体验:
cd <WORKSPACE_ROOT>\项目三\online_inference_service
.\run_windows_local_model_benchmark.ps1输出到 reports/benchmarks/ 下带唯一 run ID 的 JSON/CSV/Markdown,不覆盖历史结果。
完整回答口径使用独立 128-token 串行 profile:
cd <WORKSPACE_ROOT>\项目三\online_inference_service
.\run_windows_local_model_benchmark_128.ps1该脚本采用 128-token、no-cache,并启用 --require-raw-model-completion。报告严格拆分三种口径:served_complete 表示最终对用户返回的答案结构完整,raw_model_complete 只表示原始生成非空且未截断,unassisted_complete 还要求没有由 trusted SOP 接管;三者不能互相替代。
2026-07-13 的最新真实运行 20260713_224112_21364 使用并发 1/2/4/8、每档请求数等于并发数,共 15 个请求:服务成功、served 完整和 raw 结构完整均为 15/15,截断与触顶均为 0;但 15/15 全部触发客服 SOP,unassisted_model_passed=false。因此它证明服务与护栏可用,不证明原始模型业务质量提升。并发 8 时 QPS=0.741、完整 P95=10795.713 ms、模型排队 P95=9619.668 ms、模型执行 P95=2098.268 ms。原始报告:
reports/benchmarks/real_local_model_customer_128_guardrail_20260713_224112_21364.md
2026-07-21 使用 offline-only 直接生成契约评测 merged 模型,trusted SOP 只审计、不替换 raw answer。同提示词最终对照:默认无检索为 33/36 结构完整、2/36 自动严格通过;显式高置信项目一检索为 32/36 结构完整、3/36 自动严格通过,14/36 注入证据;两组均有 6/36 会由生产 SOP 接管。差异方向混合且尚无人工盲评,不能宣称检索提升。
生产服务因此默认 CUSTOMER_RETRIEVAL_ENABLED=0。设为 1 只会启用经过源类型过滤、IDF、场景路由和证据预算约束的实验检索,不代表已批准上线。完整结论见 reports/unassisted_evaluation/UNASSISTED_EVAL_FINDINGS_20260721.md。
如果必须启动独立服务,使用已改造的脚本。即使 Python 进程退出,窗口也会保留错误信息:
cd <WORKSPACE_ROOT>\项目三\online_inference_service
.\run_project1_merged_server.ps1日志:logs/project1_merged_server.debug.log。
客服链路走项目一客服能力,金融链路走项目二 FAISS RAG;默认不调用本地 LLM,金融检索强制 CPU,避免 Windows GPU 风险:
cd <WORKSPACE_ROOT>\项目三\online_inference_service
.\run_full_chain_smoke.ps1输出:本地原始 JSON 与公共聚合报告 reports/full_chain_smoke.md。
- 项目二严格标题隐藏评测的全量事后诊断中,Dense Recall@5 为 0.1833;每篇文档最多保留 1 个 chunk 后为 0.2417(+5.84pp)。固定主 gold 文档 Dev/Test 后,锁定策略在 Test 上为 0.1791→0.2239(+4.48pp),但两种分组 bootstrap 95% CI 下界均为 0,不能宣称稳定显著提升。
- 项目三已把同一文档多样化策略接入 canonical 在线金融链路,默认
FINANCE_RAG_ENABLE_DOC_DIVERSITY=1、FINANCE_RAG_MAX_CHUNKS_PER_DOC=1、FINANCE_RAG_CANDIDATE_MULTIPLIER=2、FINANCE_RAG_ENABLE_HYBRID_RRF=0;缓存键包含模型、生成和检索策略,引用保留doc_id/chunk_id/page。 - 本地模型默认
LOCAL_REPETITION_PENALTY=1.12;Local Transformers、Ollama 和 OpenAI-compatible 后端均传播finish_reason/truncated。截断回答不会写入缓存,旧截断/损坏缓存会绕过并重新生成。 - deploy API 对本地模型缺失、Ollama 服务/模型不可用返回 machine-readable 503 code;推理超时、WinError 1455/CUDA OOM 返回 200 降级结果,并显式设置
degraded=true、error_code和outcome。 - 客服 trusted-SOP guardrail v2 统一覆盖 LLM、热点答案、项目一样例检索和 fallback;支持尺码、少件、破损、物流及多意图拆分,暴露 reason/intent/policy metrics,并把 policy revision 纳入 core/deploy cache key。项目一检索因最终消融结果方向混合而默认关闭。缓存命中会把本次
model_executed标为 false,同时保留来源执行信息。 - 当前完整轻量验收
python -B -m unittest discover -s tests -p 'test_*.py':123/123 PASS;测试使用 mock/合成候选且不加载模型。故障用例打印的 Redis/OOM/timeout 堆栈是主动注入,不是验收失败。当前记录见reports/lightweight_test_results_20260724.md;112 项、97 项和 80 项历史记录原样保留。
.\scripts\probe_compatible_python.ps1选择器会一次性导入 FastAPI/Uvicorn/Pydantic/HTTPX/Requests/Redis/FAISS/PyTorch/Transformers/FlagEmbedding,并要求 transformers==4.51.3。当前机器实测版本记录在 requirements-windows-tested.txt;它是 observed evidence lock,不是跨机器通用安装锁,尤其 torch==2.2.1+cu118 需要匹配 CUDA 11.8 的 PyTorch 包源。
模型 readiness 会按 models/model_artifact_manifest.json 校验必要文件的精确大小与 SHA-256,并暴露锁定的 Base revision;哈希结果按 resolved path、size、mtime 缓存在进程内。Git 只跟踪 manifest 和 digest,2.22 GiB 权重仍保持忽略。
| concurrency | requests | success | error | qps | p50_latency_ms | p95_latency_ms | avg_latency_ms | cache_hit_rate |
|---|---|---|---|---|---|---|---|---|
| 1 | 4 | 4 | 0 | 0.218 | 2768.726 | 11722.005 | 4595.682 | 0.0 |
下表绑定 reports/concurrency_benchmark.csv:每档固定 32 请求、100% 缓存命中。
首页使用的 27.318 ms / 1012.745 QPS 来自另一份冻结的 unique run
reports/benchmarks/gateway_cache_20260711_180145_16692.md,两组结果不合并。
| concurrency | requests | success | error | qps | p50_latency_ms | p95_latency_ms | avg_latency_ms | cache_hit_rate |
|---|---|---|---|---|---|---|---|---|
| 1 | 32 | 32 | 0 | 767.741 | 1.147 | 1.726 | 1.256 | 1.0 |
| 4 | 32 | 32 | 0 | 912.414 | 3.626 | 4.300 | 3.732 | 1.0 |
| 8 | 32 | 32 | 0 | 1015.567 | 6.564 | 6.905 | 6.524 | 1.0 |
| 16 | 32 | 32 | 0 | 1092.915 | 11.891 | 12.353 | 11.805 | 1.0 |
| 32 | 32 | 32 | 0 | 858.337 | 31.980 | 32.961 | 31.724 | 1.0 |
- 第 1 周:模型口径校验、项目一 SFT+DPO LoRA 合并、vLLM 可行性评估、量化模板与 runbook。
- 第 2 周:FastAPI 在线服务、OpenAI-compatible/local backend、缓存、限流、并发压测、KV cache 分析。
- 第 3 周:超时降级、OOM fallback、限流保护、BadCase/故障手册。
- 第 4 周:架构图、最终报告、验收清单、简历描述、Windows 复现实验入口。
可以写进简历的是:在 Windows 上完成项目一 SFT+DPO 合并模型的本地推理接入、服务化封装、缓存/限流/降级和并发压测;并在 WSL2/Linux CUDA 上真实完成 Qwen3-0.6B Base 冒烟和项目一 rank-16 DPO LoRA 的单条 vLLM OpenAI-compatible 请求。不能写“Windows 原生 vLLM 已实测”“adapter 业务质量已验证”“高并发生产部署”或“AWQ/GPTQ 提升倍数已实测”。
本节仍是 Windows 主服务链的权威历史证据;WSL adapter-vLLM 的当前状态以 2026-07-24 post-Final addendum 为准,两者不合并改写。
最新 E2E 通过 src.app:app 的 /api/deploy/ask 在同进程 ASGI 中完成,固定 max_tokens=128、repetition_penalty=1.12,两条 case 均满足 model_executed=true、llm_backend=local_transformers、outcome=ok、cached=false:
| 链路 | 状态 | Served source | Guardrail | 检索与引用 |
|---|---|---|---|---|
| 客服 local merged LLM | PASS | llm_guardrail_sop |
trusted SOP 接管;raw/served 分离 | 不适用 |
| 金融 CPU BGE/FAISS → local LLM | PASS | project2_rag_llm |
未触发客服 SOP | dense_docdiv_m1、Hybrid off、2 citations/2 doc_id |
这只证明真实本地模型执行、检索/引用存在和结构完整;客服 SOP 不能计作 raw 模型质量提升,金融答案也没有做人工语义评分。公共报告:reports/real_llm_e2e_smoke.md。
- guardrail v2 是面向已知客服场景的确定性规则系统,没有人工标注集上的 precision/recall,不能宣传为通用安全分类器。
- trusted SOP 上线前仍需业务负责人审批;公开 API 中的 raw/pre-guardrail 字段在公网部署时应改为仅内部诊断可见。
- 当前实测是单机
httpx.ASGITransport,不包含反向代理、真实 TCP/公网、长稳和多机调度。
运行时固定为 Python 3.10、PyTorch 2.2.1+cu118、Transformers 4.51.3;解决了新版 Transformers 在 Windows 加载 Qwen3 时的原生崩溃,以及 FlagEmbedding 1.4 的 dtype 兼容问题。
| 链路 | 状态 | 完整延迟 | 模型执行 | 检索延迟 | 证据 |
|---|---|---|---|---|---|
| 客服:FastAPI → 项目一样例 → SFT+DPO 模型 | PASS | 8424.281 ms | 1748.748 ms | - | - |
| 金融:FastAPI → BGE/FAISS → SFT+DPO 模型 | PASS | 4057.035 ms | 1446.171 ms | 978.524 ms | 3 条引用(历史) |
客服完整延迟包含约 6.7 秒冷启动;真实 Redis 严格模式已验证,失败时不允许静默 回退内存缓存。该 3 引用结果已被上方 2026-07-13 canonical E2E 的 2 citations/2 doc_id 覆盖,不用于当前简历表述。
已预热模型,固定 8-token 短输出,每档请求数等于并发数:
| 并发 | 成功 | QPS | 完整 P95 | 模型执行 P95 | 模型排队 P95 |
|---|---|---|---|---|---|
| 1 | 1/1 | 2.765 | 361.394 ms | 357.650 ms | 0.002 ms |
| 4 | 4/4 | 2.716 | 1472.009 ms | 381.579 ms | 1093.506 ms |
| 8 | 8/8 | 2.657 | 3009.036 ms | 402.992 ms | 2594.314 ms |
| 16 | 16/16 | 2.768 | 5424.321 ms | 388.725 ms | 5035.960 ms |
| 32 | 32/32 | 2.774 | 10741.975 ms | 382.759 ms | 6784.789 ms |
单次模型执行 P95 保持在约 0.4 秒,32 并发完整 P95 上升到 10.74 秒,瓶颈是当前单模型锁串行排队。热点缓存 32 并发 P95 为 27.318 ms、QPS 为 1012.745。生产化应迁移到 Linux/vLLM continuous batching;不能把缓存网关延迟冒充真实生成延迟。
公共产物:reports/real_llm_e2e_smoke.md、reports/benchmarks/real_local_model_customer_20260711_193934_33360.md。
PyTorch 动态量化成功替换 197/197 个 Linear,固定 8-token、预热后重复 3 次:
| 运行时 | 中位延迟 | 三次延迟 | 阶段后 RSS |
|---|---|---|---|
| FP32 CPU | 1.0629 s | 1.0625/1.0846/1.0629 s | 2780 MB |
| Dynamic INT8 CPU | 0.4620 s | 0.4620/0.4729/0.4560 s | 3365 MB |
中位延迟约提升 2.301 倍,但两个 8-token 输出不完全一致,且该进程口径下 RSS 未下降。因此只能写成 Windows CPU 动态 INT8 延迟冒烟通过;不能据此宣称精度损失小于 1%、内存下降或等价于 AWQ/GPTQ。公共产物:reports/dynamic_int8_smoke.md、reports/quantization_raw_measurements.json。