9021425875
The behaviour section described round trips that only ever existed inside the branch. Verified every claim against `git show 6ec9ec7:<file>` plus a 300-combo side-by-side run (4 old provider slots x 25 models x three ENABLE_THINKING states); exactly two differences exist. - glm-5.3 / glm-5.3-flash / gemini-3.1-pro are newly registered as unable to stop reasoning. They were unregistered in 1.3.2, so ENABLE_THINKING=false passed; now it fails at assembly. That is the one change that breaks an existing config, so it leads the table. - The openai slot moves from "shape unknown, refuse at assembly" to the standard OpenAI shapes in both directions. Neither openai nor anthropic nor google ever injected medium; minimax did and still does, byte for byte. - kimi-k3 was never registered before, so it changes nothing for anyone. Moved to new capabilities as a first registration. - Both keyword and positional ThinkingCapability construction break, not just positional; spell out the migration form. .env.example: name all eight registry slots, and say that "on" injects nothing on the three slots whose on_base is empty.
177 lines
14 KiB
Bash
177 lines
14 KiB
Bash
# PolyGateway 工程配置模板(复制为 .env 使用;.env 不提交)。
|
||
# 键名清单 = M1 设计文档 §8 定稿;缺关键配置直接报错,不做默认值兜底。
|
||
|
||
# ══ 多源配置: {SCOPE}__{PROVIDER}__{N}__{FIELD} ══
|
||
# PROVIDER 必须是注册表键(八段: qwen/deepseek/zhipu/moonshot/minimax/openai/anthropic/google,
|
||
# 或 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=要求关闭
|
||
# 本键是 REASONING_EFFORT 的语法糖: true ≡ auto、false ≡ none、缺省 ≡ 不表态
|
||
# "要求开启"注入什么随 provider 段而定: openai/anthropic/google 三段的开启形态是
|
||
# on_base={}——一个字节都不注入,走模型自己的默认档(该默认档若不推理,本键不会报错
|
||
# 也不会开推理,见 CHANGELOG 1.3.3「已知限制」/ issue #21);要确保开启请配 REASONING_EFFORT
|
||
# LLM__QWEN__1__REASONING_EFFORT=low # 本源默认推理档位;缺省=不表态(随模型自己的默认档)
|
||
# 八档(封闭词汇): none | auto | minimal | low | medium | high | xhigh | max
|
||
# none = 要求不推理(与"缺省不表态"是两回事);auto = 要求推理但不指定强度
|
||
# 与 ENABLE_THINKING 语义矛盾会在装配期报错(如 true + none、false + low),
|
||
# 不做"后者赢"的静默兜底——两个键说同一件事,矛盾就是配置错误
|
||
# 模型不支持所配档位时报错并列出它真正支持的档(库带能力表,含出处与实测日期)
|
||
# LLM__QWEN__1__EFFORT_FALLBACK=error # 档位打空时: error(默认,报错) | nearest(映射到最近的档)
|
||
# 默认报错的理由是钱: 静默的 medium→max 在部分模型上是数倍账单;nearest 等距取弱侧
|
||
# 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 —— 丢一条遥测好过拖垮业务调用。
|
||
# # 注意告警口径: 池饱和丢的行走**行级丢弃**,telemetry_status.degraded 保持
|
||
# # False(后端并没有挂,是本进程并发超了),只有 dropped_rows 增长。只按
|
||
# # degraded 告警会完全看不见这一类丢行 —— 对账要两个字段一起看。
|
||
# # 什么时候该调大: 单进程遥测写入并发经常超过 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
|