deployment.md 21 KB

部署操作指南

F160(2026-10-22)交付包为 output/talent-update-20261022.zip,包含当前运行代码所需更新、人才137条完整知识和操作手册;精简步骤见 output/人才客服部署操作手册-20261022.txt,包内同为 操作手册.txt。依赖文件与既有离线项目包一致,不需要重新安装依赖,沿用服务器配置和模型。

sh deploy-offline.sh --env-file-only check-milvus 现在按已发布清单检查营商库,并在人才准备目录存在时额外检查人才三库。输出 agents.business、agents.talent 各自的数据库名、索引记录及内容分段计数、差异和快照;新增总计为 expected_total_all_agents / indexed_total_all_agents。旧顶层 libraries / expected_total / indexed_total 仍表示营商结果。人才部分缺失或不匹配时整体失败,不隐藏营商结果;未导入人才且没有该目录的旧安装仍只检查营商库。各库计数以本机清单为准,不能用一组库的成功代替另一组库验证。

人才客服知识包使用 sh deploy-offline.sh import-knowledge /transfer/talent-knowledge-snapshot.zip --agent talent 导入。该参数同时选择人才准备目录和前缀,跨Agent包会在写库前拒绝;营商旧命令保持。完整及单库流程见人才知识说明。

重启缺少pidfd接口(F152,2026-10-15)

148现场重启在环境检查后报Deployment failed: AttributeError,确认Python的os.pidfd_open及signal.pidfd_send_signal均不存在。旧脚本在停止旧进程时抛错,后续新进程不会启动;磁盘文件已替换不表示运行进程已更新。F152只需替换scripts/deploy.py,沿用F151最新版src/step4_api/memory.py,按用户要求不打包、不改.env。

新脚本优先使用两项pidfd接口;缺少任一接口或内核返回ENOSYS/ENOTSUP时,使用传统PID信号。每次发送前再次核对工作目录、解释器、模块、PID启动时间及boot ID;身份已改变/进程已退出则不发送,权限或其他异常仍停止部署。先SIGTERM等待,未退出才复核后SIGKILL,旧服务确认退出后才启动新服务。兼容模式不能提供pidfd的原子身份固定保障,最终核对到信号发送之间仍有很小的PID复用窗口,不宣称完全消除该竞态。

在项目目录执行原命令sh deploy-offline.sh --env-file-only restart。缺少接口时先显示API stop mode: checked PID signals (pidfd unavailable).,正常后台部署应随后出现API stopped (only this checkout).和API ready. PID=...;systemd托管显示对应的Memory-isolated API ready (systemd).。出现Deployment failed则整次重启未完成,不应继续假定新版本已生效。重启成功后运行sh deploy-offline.sh status,再复测原curl并检查最终SSE结果。

依据:Python 3.14 os.pidfd_open、pidfd_send_signal。本地为合成进程/信号验证,未在148实际停启服务。

DMS详细只读诊断

2026-10-15更新:DMS_BASE_URL为主机(末尾斜杠可选),同时设置AUTH_PORT和DMS_PORT时, 正式客户端自动使用认证端口的/oauth/api/user/login和数据端口的/dms。 现有线上.env无需修改,check-dms、企业查询、会话处理及鉴权刷新共用该规则。 显式/proxy_dms仍使用旧代理路径;其他配置规则见DMS配置。 更新正式dms.py及deploy文件后运行sh deploy-offline.sh --env-file-only check-dms, 通过后运行sh deploy-offline.sh --env-file-only restart和sh deploy-offline.sh status。 栏目元数据检查不代表业务读写验收,还须从前端验证企业查询与会话保存。

scripts/test_dms_connection.py须放在完整项目scripts目录,复用正式DMS配置/登录/鉴权刷新契约, 读取服务器自己的.env与config/dms_schema.json,不覆盖这两个文件。 默认输出通过/失败/未检查栏目数,仅展开失败栏目、异常字段及相关请求;加--verbose才打印下述全部过程与正常字段。 运行.venv/bin/python scripts/test_dms_connection.py --env-file-only --timeout 20检查五栏目。 --column records|sessions|demands|basic|honor可只检查一个栏目;严格范围不允许时在请求前拒绝。 连接前打印实际API/登录地址、端口、超时和配置来源,逐次打印POST参数(id/modelId等)及响应状态; 栏目结果列出名称/父级/模型,以及每个映射字段的期望类型、实际类型、missing/type_mismatch/matched。 Token、账号、密码脱敏,不输出业务记录、登录返回正文或任意错误正文;只读元数据,不测试写入权限。 默认urllib与正式客户端一致,保留环境HTTP代理。若怀疑环境代理,可再加--no-env-proxy对比, 该选项仅改变诊断请求,不修改正式服务。网络错误区分DNS、连接拒绝、TLS、超时,HTTP状态单独显示。 进度输出到stderr,最终报告输出到stdout;需完整保存时在命令后加> dms-diagnostic.log 2>&1。

DeepSeek与企查查代理更新(2026-10-15)

正式QCC支持原HTTPS直连地址及带servertype、proxyToken的HTTP(S)代理地址。 代理路径不自动追加,原query编码保留;业务参数只追加一次并URL编码,URL配置不能预含key/searchKey/keyword/pageIndex/pageSize。 三接口代理均使用GET/http.client/Connection: keep-alive/Accept: */*,不走环境HTTP代理,不跟随重定向。 每次请求实时生成MD5大写Token和Unix秒级Timespan;服务器须持续同步可靠时间源。 公司身份核验、荣誉分页及完整性检查保留;荣誉为空可成功,分页达到上限仍标为不完整。 check-qcc使用正式QccClient,要求搜索第一页中有唯一同名企业,再核对工商身份并查询荣誉分页。 115现在以安全错误码qcc_auth_failed报告;检查时钟、Key/Secret配对与头透传,不能当作无结果。

更新代码后在项目根目录依次执行(检查会实际调用外部接口):

sh deploy-offline.sh --env-file-only check-deepseek
sh deploy-offline.sh --env-file-only check-qcc "用于联调的企业完整名称"
sh deploy-offline.sh --env-file-only restart
sh deploy-offline.sh status

--env-file-only必须放在动作之前,供deploy.sh和deploy-offline.sh共用:仅清除继承的QCC API配置 (含超时/荣誉页数)、DEEPSEEK_API_KEY/BASE_URL/MODEL,以及DMS_BASE_URL/LOGIN_URL、AUTH_PORT、DMS_PORT、 DMS_USERNAME/PASSWORD/TOKEN,使它们从根.env读取。DMS栏目ID、严格作用域等配置不受此选项影响。 此选项对本次检查/启动生效;后续重启也应带上。自行使用systemd启动时,应同时清理unit中冲突的环境变量。 离线服务器用deploy-offline.sh,不运行会同步依赖的在线deploy.sh restart;无需重装依赖或导入知识。 DeepSeek普通/流式及部署检查使用共享传输,完整chat/completions地址不会重复拼接;实际配置不进入替换包。

企查查代理独立诊断

现场建议使用.venv/bin/python scripts/test_qcc_proxy.py --env-file-only --mode proxy --api search --company '准确企业全称' --timeout 30, 显式只读取项目根.env,避免旧环境变量覆盖凭据或URL;默认仍兼容环境变量优先,并输出覆盖字段名,不输出值。 每次请求实时生成Unix秒级Timespan和MD5大写Token,不复用固定签名。 输出request_time_utc、response_date_minus_request_seconds(响应Date减签名时间)和clock_skew_suspected。 Date缺失、重复或非法时不作偏差判断;偏差大于请求耗时加60秒仅提示核对时钟,60秒不是供应商签名有效期。 Date可能由中间代理或缓存生成,不能据此自动校时或改签名。115时检查运行机器时钟、凭据配对与鉴权头透传。

同一脚本可用--mode direct --api search测试本地.env里的无query直连地址;默认--mode proxy 仍要求servertype/proxyToken。两种模式的GET业务参数、签名、http.client、keep-alive和Accept保持一致, 仅代理模式保留配置中已有的路由参数。不要将本地真实凭据或公司正文复制到对比记录。

在项目根目录运行env -u QCC_SEARCH_URL -u QCC_BASIC_URL -u QCC_HONOR_URL .venv/bin/python scripts/test_qcc_proxy.py --company '准确企业全称'。 脚本只需标准库,读取根.env的三个URL及QCC_KEY/QCC_SECRET_KEY,其余环境变量仍优先。 URL须单行,代理参数名精确为servertype和proxyToken;路由值按实际配置原样发送,不自动纠正大小写。 使用GET、http.client、keep-alive及现有QCC Token/Timespan签名,原query后追加业务参数,不追加接口路径。 默认三个接口各请求一次,搜索和荣誉只测第一页;可用--api search|basic|honor单测及--timeout 30。 输出HTTP/业务状态及记录数、无query的endpoint、路由值和参数名称;HTTP200不等于业务成功。 失败时增加error_body_preview(脱敏后最多2000字符)、error_body_truncated及白名单响应头 (响应类型、Server、传输头、Date与请求追踪ID,重复头保留为列表)。支持HTML错误页及业务Message; 已知密钥、代理Token、签名和查询公司名称脱敏,JSON Result/Data省略,成功响应不打印资料正文。 搜索201单独判为无匹配,荣誉无记录可成功;不代表三接口企业身份关联或全量分页已验收。 独立探针只检查单接口协议;正式适配与联合检查见上节,不以探针代替正式服务验证。

DeepSeek固定代理入口独立诊断

使用固定聊天代理时,可在项目根目录执行:

.venv/bin/python scripts/test_deepseek_proxy.py

该脚本读取根目录.env中的完整DEEPSEEK_BASE_URL,系统同名变量优先。查询参数名为 servertype和proxyToken,其中servertype=deepseek;URL须写在同一行,不添加转义反斜杠。 脚本默认POST完整URL,不追加/chat/completions;已配置的/chat/completions/会去掉末尾斜杠。 servertype和proxyToken保留在URL中, model和messages等聊天参数放在JSON请求体中。可加--method GET仅诊断入口连通性。 Bearer密钥存在时发送,未配置则不伪造鉴权;响应中的凭据脱敏。无需额外安装python-dotenv。 输出HTTP状态、响应摘要及错误分类,http_ok仅表示HTTP为2xx;只有完整且有效非空聊天响应 才ok=true/退出0。GET拿到普通代理响应不能证明聊天生成可用,需代理提供聊天请求转发协议。 chat_payload_sent指示本次是否发送聊天JSON,GET为false。 响应提前结束时保留脱敏片段及response_complete=false、received_bytes、content_length、 transfer_encoding;HTTP500仍显示http_error,不能把接收不完整的HTTP200报成功。 此脚本绕过系统HTTP代理,不跟随重定向;真实代理是否可用须在服务器运行确认, 独立测试不替代正式服务的端到端验证。 独立脚本使用标准库http.client发送Connection: keep-alive,输出 transport=http.client和request_connection=keep-alive供确认版本;单次请求结束后主动关闭连接。 该脚本为普通JSON测试(stream=false)。独立流式诊断使用 env -u DEEPSEEK_BASE_URL .venv/bin/python scripts/test_deepseek_proxy_stream.py --timeout 60, 同样采用http.client和keep-alive,发送stream=true及Accept: */*以兼容代理内容协商。 流式成功需code=stream_success、完整HTTP响应、非空正文、finish_reason=stop及done_received=true。 输出首段/末段时间、内容段数及前100段到达时间,不输出推理字段;时间仅辅助判断缓冲, 单次短回答不证明始终实时透传。

正式摘要、问答、流式及sh deploy-offline.sh check-deepseek共用DeepSeek地址解析。 DEEPSEEK_BASE_URL支持HTTP(S)基础地址或完整聊天地址:基础路径只追加一次 /chat/completions,完整聊天路径去掉末尾斜杠且不重复追加,查询字符串原样保留。 例如http://gateway.example:10011/proxy/chat/completions?servertype=deepseek&proxyToken=<TOKEN>。 model、messages等使用POST JSON,API Key使用Authorization头;包含上述代理参数时 普通与流式均使用http.client、Connection: keep-alive和Accept: */*,绕过系统HTTP代理。 每次请求独立连接并在完成、失败或取消后关闭,不自动跟随重定向;流式逐段读取并检查HTTP及SSE结束。 直连API配置仍沿用原urllib及系统代理行为。禁止URL内嵌用户名密码、片段和空白。 check-deepseek复用正式普通传输,输出预算128与已验证探针对齐。 部署检查不输出URL或凭据,响应传输不完整报告response_incomplete。 替换正式代码后需重启服务;代理的SSE透传及实际线上问答仍须验证。

麒麟 V10 断网部署(ARM64 / CPU)

交付offline-release-kylin-20260929-r3.zip(项目、.env、知识和模型,仅限受控传输)、offline-env-arm64-cpu-20260929-r2.zip(uv 和依赖)及对应的offline-checksums-20260929-r3.txt。不要混用旧项目包。目标机需先安装标准 CPython 3.14;目前尚未在目标机完成安装验证。

1. 采集环境

Python 安装后,将scripts/collect-offline-env.sh单独传至服务器并运行:

sh collect-offline-env.sh > offline-env.txt 2>&1

把offline-env.txt发回。确认输出为aarch64、glibc不低于2.28、Python 3.14;任一项不符,先暂停部署。F152后pidfd可用时优先使用,缺失时采用上述核对身份的PID信号兼容路径;应先更新scripts/deploy.py。若脚本退出1,仍请发回输出。当前只准备CPU依赖,不使用CUDA。

2. 校验并解包

将两个ZIP和校验文件上传至服务器同一目录,进入该目录后执行:

sha256sum -c offline-checksums-20260929-r3.txt
python3.14 offline-release-kylin-20260929-r3.zip verify offline-release-kylin-20260929-r3.zip
python3.14 offline-release-kylin-20260929-r3.zip extract offline-release-kylin-20260929-r3.zip /srv/business-assistant
python3.14 -m zipfile -t offline-env-arm64-cpu-20260929-r2.zip
python3.14 -m zipfile -e offline-env-arm64-cpu-20260929-r2.zip /srv/business-assistant/offline-env

使用全新部署目录;解包器拒绝覆盖同名文件。任一步失败即停止,保留报错供补包。

3. 安装环境

在项目.env中将EMBEDDING_DEVICE设为cpu,并核对各服务地址;DMS使用DMS_BASE_URL的主机、AUTH_PORT登录取token、DMS_PORT访问数据。勿把凭据写入日志。然后执行:

sh /srv/business-assistant/offline-env/install_offline_env.sh /srv/business-assistant

Python 不在PATH时,在命令前加PYTHON_BIN=/绝对路径/python3.14。安装脚本只用包内wheel,创建全新的.venv,并检查依赖和本地模型;已有.venv时会停止,不会覆盖。

4. 政务网内检查DMS、恢复知识并启动

确认已更新F152重启兼容脚本、.env配置及 Milvus/Redis 等服务可达后,在可访问政务网的部署机先执行只读DMS检查,再恢复知识和启动:

cd /srv/business-assistant
sh deploy-offline.sh check-dms
sh deploy-offline.sh import-knowledge
sh deploy-offline.sh deploy
sh deploy-offline.sh status
sh deploy-offline.sh check-milvus
sh deploy-offline.sh check-redis
sh deploy-offline.sh check-deepseek
sh deploy-offline.sh check-qcc "用于联调的企业完整名称"

上述命令各自的作用如下;除deploy外,单项诊断不会启动或重启API。

命令 作用与结果
check-dms 只读登录并核验五个DMS栏目的ID、名称、父栏目和模型字段;不读取业务记录。失败要区分网络、认证、权限和模型不匹配。
import-knowledge [ZIP路径 [库名]] 校验并导入指定全量包或单库包,回读成功后切换清单并备份旧目录;不启动或重启API。不传路径时读取项目下output/knowledge-snapshot.zip。
deploy 检查现有.venv、本地模型及知识清单;准备完成后停止本项目旧API并启动新API,等待/health就绪。首次部署或需要完整部署检查时使用。
status 显示本项目API进程、健康状态和日志路径;进程不存在或不健康时返回非零退出码。
check-milvus 只读核对发布清单对应的Milvus六库、集合和记录数量。
check-redis 对当前Redis执行一次PING并关闭连接。
check-deepseek 发起一次很短的真实模型请求,验证接口可调用;可能产生费用。
check-qcc "企业完整名称" 用指定名称验证企查查886搜索;仅有唯一精确匹配时继续验证410详情和1001荣誉,可能产生费用。

check-dms先通过认证端口取token,再只读核验配置中五个栏目的名称、父栏目和字段类型;诉求词3043与企业基础信息3037目前有数据,其他栏目无数据不影响元数据检查。成功须退出码为0且报告两组均为usable;失败时先按dms_transport_failed、dms_login_failed、dms_permission_denied、dms_column_mismatch或dms_schema_mismatch区分网络、认证、权限及模型问题。token失效后客户端自动重新登录并最多重试一次。当前开发机无法访问政务网,真实DMS连接仍待本步完成。

5. 后续启动、重启与停止

首次部署已由deploy启动服务。日常操作在项目目录执行:

sh deploy-offline.sh start    # 服务已停止时启动;已健康运行则直接返回
sh deploy-offline.sh restart  # 使用当前代码和现有.venv停止并重新启动API
sh deploy-offline.sh status   # 查看进程和健康状态
sh deploy-offline.sh stop     # 停止本项目API

start只启动服务,不导入知识;restart会先检查环境和配置,再停止本项目API并启动,不重新导入知识。修改代码或.env后使用restart使新进程生效;更新知识则先运行import-knowledge,再restart。status的healthy: true表示API本身就绪,不表示所有外部依赖实时可用。

6. 更新全部知识或指定知识库

知识ZIP必须由本项目的portable export生成,包含原文、摘要、向量与校验清单;普通JSON文件压缩包不能直接导入。库名使用下表短名称,必须与单库包内声明一致。单库包是该库的完整版本,导入后该库只包含包内记录;不执行条目级追加合并,其他五库保持原有内容与集合。

库名 内容
policy 惠企政策
finance 金融产品
qa 问答
article 文章、法规及规范性文件
service_guide 办事指南
service_catalog 六大服务板块
cd /srv/business-assistant
# 全量更新:不写库名;首次部署也用此方式
sh deploy-offline.sh import-knowledge /srv/transfer/knowledge-all.zip

# 只更新文章库:传文章库完整包及article,已有全量知识快照时使用
sh deploy-offline.sh import-knowledge /srv/transfer/knowledge-article.zip article

# 两种更新方式择一执行成功后,核对六库,再按维护窗口重启
sh deploy-offline.sh check-milvus
sh deploy-offline.sh restart
sh deploy-offline.sh status

支持绝对路径及相对于执行命令时所在目录的相对路径;含空格的路径需加引号。首次初始化需导入全量包,再进行单库更新。全量包不能带库名,单库包必须带对应库名;错包、错库、模型不匹配或校验失败会明确停止。仍支持省略ZIP路径的旧命令,但不会自动扫描或选择最新ZIP。

导入不调用摘要服务、不生成新向量,使用包内已生成的向量。全量更新允许替换现有不同版本;单库更新要求与其他库使用相同模型及索引契约。写入新集合并回读全部导入记录、向量后才切换本地清单。旧Milvus集合不删除,旧本地目录保存在knowledge/prepared.previous-<唯一编号>,成功输出backup路径。失败时保留当前清单,远端可能留下未发布的新集合;修复后可重跑。切换目录失败会尝试恢复旧目录;机器在两次目录重命名之间异常断电时,应从保留的旧目录恢复后重试。不要并行运行知识规整、摘要或手工替换文件。

制作后续单库包时,在保存最新知识的机器上执行:

.venv/bin/python -m src.step2_knowledge_ingest.portable export /路径/article新版本.zip --database article
.venv/bin/python -m src.step2_knowledge_ingest.portable verify /路径/article新版本.zip

省略--database导出全量包;旧全量ZIP格式继续兼容。任何导入都不会自动重启在线服务,文件更新不代表目标麒麟服务器已完成联调。

每条诊断独立运行;失败时保留脱敏输出和退出码,不继续宣称部署成功。deploy-offline.sh不下载依赖或模型;离线只指安装资源离线,业务接口仍需连通。内存隔离见内存安全说明,知识恢复细节见知识入库说明。