4e1f09d231
ARCHITECTURE 7.8 gains the pool resource semantics, the two-sentence failure verdict and the two config keys; the ownership rule lands in a new 4.5 because it is a cross-subsystem discipline, not a telemetry convention. CHANGELOG leads with the three items downstream must read first: the 3.12 floor, the connection count going from 10 per client to on demand, and aclose no longer closing injected components.
161 lines
13 KiB
Bash
161 lines
13 KiB
Bash
# PolyGateway 工程配置模板(复制为 .env 使用;.env 不提交)。
|
||
# 键名清单 = M1 设计文档 §8 定稿;缺关键配置直接报错,不做默认值兜底。
|
||
|
||
# ══ 多源配置: {SCOPE}__{PROVIDER}__{N}__{FIELD} ══
|
||
# PROVIDER 必须是注册表键(qwen/deepseek/openai,或 register_provider 注册后经 registry 传入)。
|
||
# 必填: BASE_URL / API_KEY / MODEL / TIMEOUT_S(或用平铺 LLM_TIMEOUT 作缺省)。
|
||
LLM__QWEN__1__BASE_URL=
|
||
LLM__QWEN__1__API_KEY=
|
||
LLM__QWEN__1__MODEL=
|
||
LLM__QWEN__1__TIMEOUT_S=120
|
||
# 可选(0 = 该闸不启用):
|
||
# LLM__QWEN__1__MAX_CONCURRENCY=8
|
||
# LLM__QWEN__1__RPM=60
|
||
# LLM__QWEN__1__TPM=100000
|
||
# LLM__QWEN__1__EST_TOKENS=2000 # 可选调优覆盖: TPM 入场预扣量;未填则库按 tpm//60 派生
|
||
# LLM__QWEN__1__TTFT_TIMEOUT_S=30 # 须与 INTER_TOKEN 成对;0 < inter < ttft < timeout
|
||
# LLM__QWEN__1__INTER_TOKEN_TIMEOUT_S=15
|
||
# LLM__QWEN__1__ENABLE_THINKING=true # 三态: 缺省=不注入 / true=注入开启 / false=注入关闭
|
||
# LLM__QWEN__1__MISSING_DONE=retry # SSE 缺 [DONE]: retry(默认) | salvage
|
||
# LLM__QWEN__1__TRUST_ENV=true # false = 绕过本地代理(LAN 直连)
|
||
# LLM__QWEN__1__EXTRA_BODY={"temperature":0} # 本源恒定的采样参数(JSON 对象串)
|
||
# 并入请求体,优先级低于 chat(overlay=...);受控实验固定解码用它,免得漏传
|
||
# 禁用键 model/messages/stream/stream_options(会击穿治理),配了直接报错
|
||
# OCR/EMBED scope 不消费该键: 配了会被忽略并 warning(见 issue #4 决策 G)
|
||
|
||
# ══ scope 级全局闸(跨源合计;0/缺省 = 不启用)══
|
||
# LLM__GLOBAL__MAX_CONCURRENCY=8
|
||
# LLM__GLOBAL__RPM=120
|
||
# LLM__GLOBAL__TPM=200000
|
||
|
||
# ══ 韧性参数(平铺键 = 单 scope 简写,沿用三项目习惯;scope 键优先)══
|
||
LLM_MAX_RETRIES=3 # 总尝试次数(含首次);或 LLM__RETRY__MAX_ATTEMPTS
|
||
LLM_RETRY_BASE_DELAY=2.0 # 或 LLM__RETRY__BACKOFF_BASE_S
|
||
LLM_RETRY_MAX_DELAY=30.0 # 或 LLM__RETRY__BACKOFF_MAX_S
|
||
LLM_CIRCUIT_BREAKER_THRESHOLD=5 # 连续失败通道;有效阈值取 max(此值, 源级并发×2);或 LLM__BREAKER__FAIL_THRESHOLD
|
||
LLM_CIRCUIT_BREAKER_COOLDOWN=60 # 或 LLM__BREAKER__COOLDOWN_S
|
||
# LLM_TIMEOUT=120 # 源缺 TIMEOUT_S 时的缺省
|
||
# LLM_TTFT_TIMEOUT=30 # 平铺看门狗缺省(成对生效)
|
||
# LLM_INTER_TOKEN_TIMEOUT=15
|
||
# LLM__BREAKER__PROBE_TTL_S=240 # 缺省派生: max(2×最大源超时, cooldown, 最大源超时+5);显式值须 ≥ 最大源超时+5
|
||
# LLM__BACKPRESSURE__STALL_WINDOW_S=300 # stall 双条件判死窗口;只计非生产性等待(429 退避/配额轮询/熔断冷却),与 TIMEOUT_S 无耦合,无需按 timeout×retries 放大
|
||
# LLM__BACKPRESSURE__POLL_INTERVAL_S=0.05
|
||
# LLM__SELECTOR=health_aware # health_aware(默认,M2.5) | round_robin | least_inflight
|
||
# ── M2.5 失败率熔断通道(可选,缺省即生产推荐值)──
|
||
# LLM__BREAKER__MIN_CALLS=10 # 率通道最小样本(防低流量误判)
|
||
# LLM__BREAKER__FAIL_RATE=0.6 # 窗口失败率阈值(429 不计入)
|
||
# LLM__BREAKER__WINDOW_S=60 # 失败率窗口(双 30s 桶)
|
||
# LLM__BREAKER__MAX_COOLDOWN_S=300 # 开路指数退避封顶(缺省 max(300, cooldown))
|
||
# ── AIMD 自适应并发(M2.5,库常量非 env 键): 每源初始 8,429 ×0.5,成功 +1/limit,
|
||
# ── ceiling = max(64, 源级 MAX_CONCURRENCY);禁用需构造函数注入自定义 pacer ──
|
||
# LLM__QUOTA_FULL=wait # 配额满: wait(默认) | fail_fast
|
||
# ── 熔断全拒时的处置(issue #14)。单源 scope 建议 wait: 只有一个源时
|
||
# ── "停用这个源"等于"整个 scope 停服",fail_fast 会让开路期间的每次调用
|
||
# ── 在几毫秒内死掉且 MAX_ATTEMPTS 一格用不上。wait 不削弱保护(等待期照样
|
||
# ── 不发请求),只是把最坏墙钟拉长到 BACKPRESSURE__STALL_WINDOW_S ──
|
||
# LLM__CIRCUIT_OPEN=fail_fast # 熔断开路: fail_fast(默认) | wait
|
||
|
||
# ══ 装配选择(PGW_*)══
|
||
PGW_LIMITER_BACKEND=memory # memory | redis(redis 需 REDIS_URL;多进程 worker 必须 redis)
|
||
PGW_BREAKER_BACKEND=memory # memory | redis
|
||
PGW_CACHE_BACKEND=none # redis | memory | none(必填,显式优于隐式)
|
||
PGW_TELEMETRY_BACKEND=none # sqlite | postgres | none(必填)
|
||
# PGW_TELEMETRY_SQLITE_PATH=logs/telemetry.db # sqlite 时必填
|
||
# PGW_TELEMETRY_SCHEMA_MODE=manual # auto | manual;三态: 不设 = 按后端派生(sqlite→auto、postgres→manual),
|
||
# # 显式设置则两侧都可覆盖。auto = 库给已存在的旧表自动 ALTER 补列;
|
||
# # manual = 库不发 ALTER,只 warning 点名缺列并打印可执行 SQL,
|
||
# # 按现有列裁剪 INSERT 继续写(遥测不会因缺列而全线丢失)。
|
||
# # 缺省为何不对称: postgres 是共享生产表,ALTER 取 ACCESS EXCLUSIVE 锁,
|
||
# # 会排在长事务后阻塞该表其后的所有查询,而遥测是业务路径上的内联 await;
|
||
# # 且这类部署有 DBA、有迁移工具、讲最小权限,DDL 该由他们择时执行。
|
||
# # sqlite 则是下游自己的本地文件(runs/*.db):没有 DBA、没有迁移工具、
|
||
# # 没有第二个系统碰它,ALTER 是毫秒级元数据操作,强加手工 SQL 步骤是净损失。
|
||
# PGW_TELEMETRY_PG_DSN=postgresql://user:pass@host:5432/polygateway # postgres 时必填;严禁指向在用业务库(实验室约定: 专用库 polygateway)
|
||
# PGW_TELEMETRY_PG_POOL_MAX=4 # postgres 遥测池的连接上限,须 >= 1;缺省 4。**闲时占 0 条**——
|
||
# # 池按需建连(min_size=0),不预占;这一格是忙时的天花板,不是常驻量。
|
||
# # 调参口径(以实测为准,不要按 pool_max/RTT 估算):跨内网 RTT ≈ 123ms 的
|
||
# # 实验室 PG 上,pool_max=4 实测约 **15.6 行/秒**(50 行并发批耗时 3.2s),
|
||
# # 即每条连接约 4 行/秒 —— 一次 INSERT 的实际往返比一次 `SELECT 1` 重一倍,
|
||
# # 按单次 RTT 估会乐观一倍。要放大就按这个实测值线性折算(pool_max=8 ≈ 31 行/秒)。
|
||
# # 缺省 4 在缺省 5s 预算下能吞下约 50 行的突发(余量约 1.5 倍);超预算的行被丢弃
|
||
# # 并计入 telemetry_status.dropped_rows —— 丢一条遥测好过拖垮业务调用。
|
||
# # 什么时候该调大: 单进程遥测写入并发经常超过 4(高频短调用、批量并发),
|
||
# # 或多个 client 显式共享同一个 recorder(并发在这里汇聚,应按 client 数放大)。
|
||
# PGW_TELEMETRY_PG_WRITE_TIMEOUT_S=5.0 # 一次遥测写入的硬预算(秒),须 > 0;缺省 5.0。同时用作建连、
|
||
# # acquire 与「准备 + 取连接 + 执行」整段的上界:超时即丢弃该行,
|
||
# # 绝不让遥测无界地挂在业务路径上。实测参考: 稳态写入 123ms、
|
||
# # 首次写入含建连 513ms —— 5s 对正常路径是极宽松的上限,它防的是
|
||
# # 池满排队与后端假死这类"不会自己结束"的等待。
|
||
# # 与之配套的两个不可配内部常量: 连接释放上界 1s(超时即 terminate)、
|
||
# # 环境级降级的冷却期 60s(到期自动重试一次,成功即恢复)。
|
||
# PGW_TELEMETRY_TEXT_CAP=2000 # 遥测落库正文的字符上限,须 > 0;**不设 = 不截断**(缺省,逐字节留全文)。
|
||
# # 作用于 messages 的每条文本 content、多模态 text part、response 与 thinking;
|
||
# # 超出部分头部保留、尾部换成 `…(略 N 字)`。多模态 image_url 的 sha256 摘要不受影响。
|
||
# # 缺省为何是"不截断": 遥测被下游当**审计证据**用——出了问题要回答"当时到底发了什么",
|
||
# # 也要能拿原样的请求复现与重放;截断后这两件事都做不成,而既有下游正依赖这一行为。
|
||
# # 反面同样要看清: 不截断意味着客户合同、标书全文无限期留在 llm_calls 里,
|
||
# # 多租户下还混在同一张表。真在意留存面的部署应显式设一个上限,并配保留期与访问控制。
|
||
# PGW_PRICING_PATH=config/prices.json # 可选: {"<model>": {"input_per_1m": x, "output_per_1m": y}};缺省 cost 恒 None
|
||
# # 可选第三档 "cached_input_per_1m": z —— 供应商 prompt cache 命中部分的单价;
|
||
# # 不填即命中部分也按 input 全额计(库不猜折扣率),cost 会偏高
|
||
# PGW_CACHE_NAMESPACE=<项目名或租户前缀> # 缓存启用时必填(防跨项目毒化)
|
||
# PGW_CACHE_TTL_S=604800 # 缓存启用时必填,须 > 0
|
||
# PGW_STRUCTURED_MAX_RETRIES=2 # 缺省 2(M2.5);0 = 解析失败不重问(CHS 策略)
|
||
# PGW_LEASE_TTL_S=1500 # permit 租约;须 ≥ 最大源 timeout
|
||
|
||
# ══ Redis(缓存 + 分布式限流/熔断)══
|
||
# 实验室纪律: 共享实例的 db0 有在用键,PolyGateway 一律用专用 db3(soak 会 FLUSHDB!)
|
||
# REDIS_URL=redis://:password@host:6379/3
|
||
|
||
# ══ Embedding scope(M2;EmbeddingClient.from_env 装配)══
|
||
# EMBED__QWEN__1__BASE_URL=
|
||
# EMBED__QWEN__1__API_KEY=
|
||
# EMBED__QWEN__1__MODEL=text-embedding-v3
|
||
# EMBED__QWEN__1__TIMEOUT_S=60
|
||
# EMBED__RETRY__MAX_ATTEMPTS=3
|
||
# EMBED__RETRY__BACKOFF_BASE_S=1.0
|
||
# EMBED__RETRY__BACKOFF_MAX_S=10.0
|
||
# EMBED__BREAKER__FAIL_THRESHOLD=5
|
||
# EMBED__BREAKER__COOLDOWN_S=60
|
||
# EMBED__BATCH_SIZE=64 # 必填: 每批条数(分批是行为关键,不设默认)
|
||
# EMBED__NORMALIZE=false # 可选: true = 库内 L2 归一化(VT 语义)
|
||
# EMBED__EXPECTED_DIM=768 # 可选: 维度校验,不符抛 ResultInvalid
|
||
|
||
# ══ SOAK scope(压测 harness 专用;tools/soak/run_soak.py --scope SOAK)══
|
||
# 网关保护(设计 §8.1 签字值,run_soak 强制: 必配且 ≤ 100/600,否则拒跑)
|
||
# SOAK__GLOBAL__MAX_CONCURRENCY=100
|
||
# SOAK__GLOBAL__RPM=600
|
||
# 健康源 + 故障源混编(findings §3): 坏 key 源 / 黑洞源 / 紧看门狗源 / 紧闸源
|
||
# SOAK__MINIMAX__1__BASE_URL= # 健康源(真实网关)
|
||
# SOAK__MINIMAX__1__API_KEY=
|
||
# SOAK__MINIMAX__1__MODEL=
|
||
# SOAK__MINIMAX__1__TIMEOUT_S=180
|
||
# SOAK__MINIMAX__2__BASE_URL= # 坏凭据源: 真实网关 + 错误 API_KEY → 401
|
||
# SOAK__MINIMAX__2__API_KEY=sk-wrong-key-on-purpose
|
||
# SOAK__MINIMAX__3__BASE_URL=http://10.255.255.1/v1 # 黑洞源: 防火墙 DROP → 连接超时
|
||
# SOAK__MINIMAX__4__RPM=5 # 紧闸源: 真实源 + rpm=5 / 并发 1
|
||
# SOAK__MINIMAX__4__MAX_CONCURRENCY=1
|
||
|
||
# ══ OCR scope(M3;MonkeyOCR 自建 LAN 服务,无鉴权故 API_KEY 填占位 "none")══
|
||
# CHS 单源写法:
|
||
# OCR__MONKEY__1__BASE_URL=http://10.77.0.20:7866
|
||
# OCR__MONKEY__1__API_KEY=none # 占位惯例: 服务无鉴权,SourceConfig 非空校验用
|
||
# OCR__MONKEY__1__MODEL=monkey-ocr
|
||
# OCR__MONKEY__1__TIMEOUT_S=300 # /parse 两段协议较慢,给足
|
||
# OCR__MONKEY__1__MAX_CONCURRENCY=4
|
||
# OCR__MONKEY__1__RPM=120
|
||
# VT 双实例写法(原 MONKEY_OCR_URLS 逗号列表拆多源;LAN 直连绕代理配 TRUST_ENV=false):
|
||
# OCR__MONKEY__2__BASE_URL=http://10.77.0.20:7867
|
||
# OCR__MONKEY__2__API_KEY=none
|
||
# OCR__MONKEY__2__MODEL=monkey-ocr
|
||
# OCR__MONKEY__2__TIMEOUT_S=300
|
||
# OCR__MONKEY__2__TRUST_ENV=false
|
||
# OCR__RETRY__MAX_ATTEMPTS=3 # per-scope 韧性键与 LLM scope 同一套
|
||
|
||
# ══ SOAK_OCR scope(P7 OCR 压测;tools/soak/run_soak.py --scenario P7 --scope SOAK_OCR)══
|
||
# 双真实实例 + 黑洞(连接超时)+ 坏端口(连接拒绝)故障池;
|
||
# SOAK_OCR_FAULT_SOURCES 供记分板"坏源吸流占比"不变量归因
|
||
# SOAK_OCR__GLOBAL__MAX_CONCURRENCY=16
|
||
# SOAK_OCR__GLOBAL__RPM=300
|
||
# SOAK_OCR_FAULT_SOURCES=monkey_3,monkey_4
|