feat(llm): 五层重试的次数与间隔可配
一次模型调用的失败由内到外经过五层重试:建连(SDK)、空响应(SDK)、同 provider 安全窗口、轮询熔断、意图重跑。此前五层的次数与间隔全是写死的常量,遇到脾气各异 的中转站只能改代码。现在都能在 LLM 页配置,不配就是原来的默认值。 配置语义五层统一(db.RetryRule):次数 0=内置默认 / -1=关掉这层 / >0=该值; 间隔 0=原本的指数退避 / >0=改用固定间隔。0 被"未配置"占用,故关闭用 -1。 写库前夹紧到 次数 [-1,20]、间隔 [0,1h],DB 另有 CHECK 兜底。 粒度按层的性质分:前三层跟着端点走,可在每个模型配置里逐字段覆盖全局默认(只钉 间隔的仍继承全局次数);熔断与意图重跑是进程级语义,只有全局一份。 生效路径:①②是 provider 构建参数,保存后重建缓存;③随每次 hooks.current() 解析,故障转移换配置时重试节奏跟着换;④在失败路径上每次都要读,由 applyRetryPolicy 推给 llmpool.Registry;⑤每条意图收尾读一次。全部热生效,无需重启。 连接测试刻意不带这些参数——它有 30s 硬超时,叠上用户配的重试只会把本来能用的 端点测成超时失败。 norma 升 v0.3.5(llm.Config 新增 RetryInterval / EmptyResponseRetries / EmptyResponseInterval)。旧库升级后行为逐字节不变:新列默认 0,settings 键不 存在即全默认。设计见 docs/LLM重试设计.md。
This commit is contained in:
1 parent
377ccc7e5a
commit
a50bf02428
21 files changed
+1216
-146
No files matched your search
@@ -74,6 +74,29 @@ type Config struct {
|
||||
// 空 = 不发送。值由 transcript.WithSessionID 挂在请求 context 上,由 RoundTripper
|
||||
// 读取填入,因此同一共享 provider 也能按会话发出不同的头值。
|
||||
SessionHeaderKey string
|
||||
// Retry 是该配置解析后的重试参数(profile 覆盖 → 全局策略 → 内置默认,由
|
||||
// server 侧解析)。三层的含义见 RetryConfig;零值 = 完全沿用内置默认。
|
||||
Retry RetryConfig
|
||||
}
|
||||
|
||||
// RetryConfig 是随一个 LLM 配置走的重试参数。每层的「次数」统一语义:
|
||||
// 0 = 用内置默认次数;负数 = 关闭该层重试;>0 = 用该值。每层的「间隔」:
|
||||
// 0 = 用该层原本的指数退避;>0 = 改用这个固定间隔。
|
||||
type RetryConfig struct {
|
||||
// ConnectAttempts/ConnectInterval:SDK 建连重试(连接重置/超时/429/5xx,流开始前),
|
||||
// 直接映射为 llm.Config.MaxRetries / RetryInterval。默认 3 次、0.5s 起指数(封顶 8s)。
|
||||
ConnectAttempts int
|
||||
ConnectInterval time.Duration
|
||||
// EmptyAttempts/EmptyInterval:SDK 空响应重试(完成但无 content block,仅 openai
|
||||
// 格式),映射为 llm.Config.EmptyResponseRetries / EmptyResponseInterval。
|
||||
// 默认 2 次、同一条指数梯度。
|
||||
EmptyAttempts int
|
||||
EmptyInterval time.Duration
|
||||
// StreamAttempts/StreamInterval:同 provider 安全窗口重试——本项目在 SDK 之上补的
|
||||
// 一层,只在「还没向调用方交付任何输出」时重放断流/过载/流内 429。SDK 看不到它,
|
||||
// 由 server/task_llm.go 消费。默认 2 次、0.5s 起指数(封顶 4s)。
|
||||
StreamAttempts int
|
||||
StreamInterval time.Duration
|
||||
}
|
||||
|
||||
// compaction window resolution bounds (in K tokens). Below the floor the
|
||||
@@ -249,6 +272,11 @@ func (c Config) NewProvider() (llm.Provider, error) {
|
||||
// 输出上限的字段名选择(空 = 用 max_tokens)。上限的「值」不在这里:它每轮随
|
||||
// agentcore.Options.MaxTokens 走,provider 只决定把它塞进哪个键。
|
||||
lc.MaxTokensField = c.MaxTokensField
|
||||
// 重试参数与 SDK 同语义(次数 0=默认/负=关闭,间隔 0=指数退避/>0=固定),原样透传。
|
||||
lc.MaxRetries = c.Retry.ConnectAttempts
|
||||
lc.RetryInterval = c.Retry.ConnectInterval
|
||||
lc.EmptyResponseRetries = c.Retry.EmptyAttempts
|
||||
lc.EmptyResponseInterval = c.Retry.EmptyInterval
|
||||
if c.RatePerSecond > 0 || c.RatePerMinute > 0 {
|
||||
lc.RateLimit = &llm.RateLimit{PerSecond: c.RatePerSecond, PerMinute: c.RatePerMinute}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user