一个面向多上游、多协议、多认证形态的统一 LLM 接入层。
LLM_Proxy 把模型服务、鉴权方式、协议转换和后台运维收敛到同一个 Flask + gevent 服务中,对下游提供 OpenAI Chat Completions、OpenAI Responses 和 Claude Messages 兼容接口。它既支持常规 Provider 代理,也支持 Codex / Claude OAuth 账号文件代理,并内置 Provider 管理、Auth Group 凭据池、白名单控制、日志统计、请求调试和 Hook 扩展能力。
它的定位不是“再做一个 API 转发器”,而是把代理、协议适配、认证管理和运维入口放到同一层统一处理。客户端只需要记住一个地址;服务端可以集中维护模型路由、Key 池、OAuth 账号、访问控制和统计信息。
- 统一接入多种上游协议:同一个代理服务可同时对接 OpenAI Chat Completions、OpenAI Responses、Claude Messages 和 Codex 风格接口
- 多下游兼容内建:同一个 Provider 不需要额外配置下游格式,默认即可同时服务
/v1/chat/completions、/v1/responses和/v1/messages - OAuth 账号文件代理:内置 Codex / Claude 登录、认证文件管理、模型目录维护、Codex 配额查看、账号状态记录和账号候选切换
- Hook 扩展机制:用于补充 Header、请求护栏和成功响应清洗
- 多 Key 池化调度:
auth_group支持并发限制、429 冷却、分钟/日请求配额、分钟/日 Token 配额 - 控制平面模型测试:Provider 编辑页可按当前表单快照直接测试模型可用性、首字延迟和 TPS
- 后台可直接运维:内置 Provider 管理、Auth Group 管理、OAuth 管理、系统设置、白名单管理、日志和统计面板
- 请求调试可开关:支持将下游请求、上游请求、上游响应和下游响应写入独立 trace 日志
- 对下游保持稳定接口:支持
POST /v1/chat/completions、POST /v1/responses、POST /v1/messages、GET /v1/models
pip install flask gevent requests pyyaml urllib3创建 config.yaml,下面是一份最小可运行配置:
server:
host: 127.0.0.1
port: 8080
# chat:
# whitelist_enabled: false
# admin:
# username: admin
# password: admin123
# oauth:
# enabled: false
# proxy_mode: direct
# proxy: ""
# verify_ssl: false
providers:
- name: openai-chat
# enabled: false # 可选;默认 true;禁用后不会出现在 /v1/models
api: https://api.openai.com/v1/chat/completions
source_format: openai_chat
api_key: sk-your-openai-key
force_upstream_stream: false
verify_ssl: false
model_list:
- gpt-4.1
- gpt-4.1-mini
hidden_model_list:
- gpt-4.1-mini也可以直接从 config.sample.yaml 开始裁剪。
注意:下游调用时的模型名不是裸模型名,而是 provider/model,例如 openai-chat/gpt-4.1。
如果未配置 providers[].enabled,默认就是启用状态。
python main.py或者显式指定配置文件:
python main.py --config path/to/config.yaml访问Web: http://127.0.0.1:8080
查询模型列表:
curl http://127.0.0.1:8080/v1/models发送第一条聊天请求:
curl http://127.0.0.1:8080/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "openai-chat/gpt-4.1",
"messages": [
{"role": "user", "content": "你好,帮我用一句话介绍 LLM_Proxy"}
],
"stream": false
}'后台页面始终可访问;如果配置了 admin.username 和 admin.password,访问后台时需要先登录;不配置则后台无需登录:
/login:登录页/:默认进入 Provider / Auth Group 管理/statistics:统计与日志面板/users:用户与白名单管理/providers:Provider / Auth Group 管理/oauth:Codex / Claude OAuth 认证文件与模型管理;开启oauth.enabled后会显示在后台导航中/settings:系统、登录、日志和 OAuth 网络设置
把服务部署在 NAS、小主机或团队内网服务器上,让桌面客户端、脚本、自动化任务统一走一个地址访问模型。客户端不需要再分别维护不同厂商的 API 地址和鉴权方式。
同时接入 OpenAI、Anthropic、私有网关或自建兼容层,对外仍然提供统一接口。业务侧只关心模型名,不需要感知每个上游的差异。
当一个上游需要多个 Key 分摊压力时,可以把多个 Header 凭据放进 auth_group,由代理统一处理并发、配额、冷却和禁用状态。
当上游不是标准 OpenAI 格式时,优先通过 source_format 和当前路由对应的内置下游协议做转换。如果还需要补充 Cookie、自定义 Header、特殊字段,或者对成功响应做额外清洗,再用 Hook 在代理层补充这部分逻辑。
上游已经切到 Responses,但客户端还在走 Chat Completions;或者一部分客户端走 Claude Messages,另一部分走 OpenAI 风格接口。这类迁移期混合场景正适合由代理层统一兜住。
| 路由 | 说明 | 下游协议 | 支持模型来源 |
|---|---|---|---|
POST /v1/chat/completions |
OpenAI Chat Completions 兼容接口 | openai_chat |
Provider、Codex / Claude OAuth |
POST /v1/responses |
OpenAI Responses / Codex 风格接口 | openai_responses |
Provider、Codex / Claude OAuth |
POST /v1/messages |
Claude Messages 兼容接口 | claude_chat |
Provider、Codex / Claude OAuth |
GET /v1/models |
返回当前已注册模型列表 | 不适用 | Provider、Codex / Claude OAuth |
常规 Provider 返回的模型 ID 形如:
openai-chat/gpt-4.1responses-upstream/gpt-4.1claude-messages/claude-sonnet-4-5
也就是说,Provider 模型需要使用 provider/model 格式。代理转发给上游前只移除最前面的 provider/ 前缀,真实模型名剩余部分会原样保留。
OAuth 模型是一个例外:模型 ID 直接使用 OAuth 模型目录里的裸模型名,例如 gpt-5.4 或 claude-sonnet-4-5。只有在存在对应类型的认证文件,并且该模型已添加到 /oauth 页面模型目录后,它才会出现在 GET /v1/models 中。
server.host:监听地址,默认127.0.0.1server.port:监听端口,默认8080chat.whitelist_enabled:是否启用聊天白名单admin.username/admin.password:配置后开启后台登录功能,用于提升后台访问安全性;不配置则后台无需登录auth_groups:凭据池配置providers:上游模型入口配置database.path:SQLite 数据库路径,默认data/requests.dblogging.path:日志目录,默认logslogging.level:日志级别,例如INFO、DEBUGlogging.llm_request_debug_enabled:是否把下游/上游请求与响应写入logs/llm_request_trace.logoauth.enabled:是否在后台导航显示 OAuth 管理入口oauth.proxy:OAuth 登录、Codex 配额查询和 OAuth 上游请求使用的代理地址,留空表示不使用代理oauth.verify_ssl:OAuth 网络请求是否校验证书,默认false
name:Provider 名称,必须唯一;下游模型名会以它作为前缀enabled:是否启用;默认true。设为false后该 Provider 不参与运行时注册,也不会出现在GET /v1/modelsapi:上游接口地址,支持http://、https://source_format:上游真实协议格式api_key:单 Provider 直接使用的凭据auth_group:绑定一个凭据池;和api_key二选一,不能同时使用proxy:上游代理地址timeout_seconds:上游请求超时,默认1200max_retries:一次 Provider 上游操作允许的最大尝试次数,包含首次尝试;默认3,设为1时只尝试一次verify_ssl:是否校验证书;代码默认值为false,公网 HTTPS 建议显式设为trueforce_upstream_stream:是否在下游非流式请求时强制使用上游流式请求;默认false。启用后代理会聚合上游流式事件,再以非流式响应返回下游model_list:当前 Provider 可路由的模型列表hidden_model_list:不出现在下游GET /v1/models的模型列表;模型路由、测试和权限配置保持可用hook:相对hooks/目录的 Hook 文件路径,文件中需要导出名为Hook的类
旧配置中如果残留 transport 字段,启动加载配置时会自动删除并写回配置文件;上游传输固定由内部 HTTP executor 处理。
支持的协议格式:
openai_chatopenai_responsesclaude_chat
如何理解 source_format:
source_format描述上游实际上接受什么协议- 一般按上游真实接口来选,例如
/v1/chat/completions对应openai_chat /v1/responses对应openai_responses/v1/messages对应claude_chatclaude_chat上游如果请求体里已经带有 Claude Code billing header /cch,代理会在转发前重签已有cch,但不会主动生成 billing header
name:认证组名称,必须唯一strategy:当前支持least_inflightcooldown_seconds_on_429:组级默认冷却时间entries[]:凭据条目列表,至少包含一个条目
entries[] 支持:
id:条目标识enabled:是否启用headers:发往上游时注入的 Header 集合,例如Authorizationmax_concurrency:单条目最大并发cooldown_seconds_on_429:条目级 429 冷却时间request_quota_per_minute/request_quota_per_day:请求数配额token_quota_per_minute/token_quota_per_day:Token 配额
运行时行为:
- 遇到
429时,会优先参考Retry-After,只让当前条目进入冷却 - 遇到
401时,当前条目会被标记为不可用,直到后台手动恢复 - 后台支持清除冷却、启用、禁用、恢复、重置分钟用量、重置运行时状态
providers:
- name: openai-chat
api: https://api.openai.com/v1/chat/completions
source_format: openai_chat
api_key: ${OPENAI_API_KEY}
verify_ssl: true
model_list:
- gpt-4.1
- gpt-4.1-miniproviders:
- name: responses-upstream
api: https://api.openai.com/v1/responses
source_format: openai_responses
api_key: ${OPENAI_API_KEY}
verify_ssl: true
model_list:
- gpt-4.1providers:
- name: openai-shared
api: https://api.openai.com/v1/chat/completions
source_format: openai_chat
api_key: ${OPENAI_API_KEY}
verify_ssl: true
model_list:
- gpt-4.1这个 Provider 保存后,客户端可以分别走:
POST /v1/chat/completionsPOST /v1/responsesPOST /v1/messages
auth_groups:
- name: openai-shared
strategy: least_inflight
cooldown_seconds_on_429: 60
entries:
- id: key-a
headers:
Authorization: Bearer sk-key-a
max_concurrency: 3
request_quota_per_minute: 60
- id: key-b
headers:
Authorization: Bearer sk-key-b
max_concurrency: 2
providers:
- name: openai-chat
api: https://api.openai.com/v1/chat/completions
source_format: openai_chat
auth_group: openai-shared
verify_ssl: true
model_list:
- gpt-4.1providers:
- name: custom-gateway
api: https://example.com/v1/chat/completions
source_format: openai_chat
model_list:
- my-model
hook: example_hook.py完整样例见:
OAuth 代理是独立于常规 Provider 的运行时能力。它不需要在 providers[] 中配置 API Key,而是通过后台 OAuth 登录生成本地认证文件,再把下游 OpenAI/Claude 兼容请求转换后转发到 Codex Responses 或 Claude Messages 上游。
可以在 /settings 页面开启,也可以直接写入配置:
oauth:
enabled: true
proxy_mode: direct
proxy: ""
verify_ssl: false开启后,后台导航会显示 /oauth 页面。proxy_mode 支持 direct、system、custom;只有 custom 会读取 proxy,但 custom 下 proxy 为空时会按直连执行。这里的 proxy 是服务端访问 OAuth token、配额查询和 OAuth 上游模型接口时使用的出站代理,不是下游客户端访问本服务的入口代理。认证文件未提供 proxy_url 时,proxy_mode 和 proxy 决定 Codex 配额查询的网络出口;verify_ssl 继续控制 HTTPS 证书校验。自定义代理 URL 中的账号密码会由系统规范化转义。旧配置缺少 proxy_mode 时,启动加载会按是否存在 proxy 自动回写为 custom 或 direct。
在 /oauth 页面点击“刷新授权链接”,用浏览器完成登录后,将完整回调 URL 粘贴回页面提交。服务会把认证信息写入:
data/oauth/codex/*.json:Codex 认证文件data/oauth/codex/models.json:手动维护的 Codex 模型目录data/oauth/codex/.state/auth_files.json:认证文件启停状态、最近状态、配额快照和错误信息data/oauth/claude/*.json:Claude 认证文件data/oauth/claude/models.json:手动维护的 Claude 模型目录data/oauth/claude/.state/auth_files.json:Claude 认证文件启停状态、最近状态和错误信息
这些文件包含账号认证信息,请不要提交到版本库,也不要暴露给不可信用户。
Codex / Claude OAuth 模型需要在 /oauth 页面手动添加。添加后,如果至少有一个对应类型的认证文件,GET /v1/models 会返回这些模型。Codex 模型示例:
{
"id": "gpt-5.4",
"provider_name": "codex",
"source_format": "openai_responses",
"target_formats": ["openai_chat", "openai_responses", "claude_chat"]
}调用时直接使用裸模型名:
curl http://127.0.0.1:8080/v1/responses \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-5.4",
"input": "用一句话介绍 LLM_Proxy",
"stream": false
}'Claude OAuth 模型同样使用裸模型名,例如 claude-sonnet-4-5,并会以 provider_name=claude、source_format=claude_chat 暴露。
- 上游固定访问
https://chatgpt.com/backend-api/codex/responses - 每次请求都会重新构建候选列表;默认按认证文件修改时间倒序排列,但最近一次真实请求成功的认证文件会被提升到候选首位
- 候选筛选会跳过人工禁用、认证失败、当前进程内配额冷却中、token 刷新失败或缺少
access_token的文件 - 只要最近成功的认证文件仍通过筛选,后续请求会继续优先使用它;其它文件冷却结束不会抢回顺序
- 前端旧配额快照显示“配额已耗尽”不会单独阻止数据面候选选择;真正的可用性主要由直接请求 Codex 上游决定
- 手动配额刷新直接使用认证文件当前的 access token 查询
wham/usage,不触发 OAuth token 刷新 - 认证文件包含
proxy_url时,手动配额刷新优先使用该账号代理;其后使用全局 OAuth 代理设置 - 数据面请求前如果 access token 已过期且存在 refresh token,会自动刷新认证文件
- 数据面不会先调用 usage / quota 判断是否可用;选到候选后会直接请求上游
- 如果某个账号真实返回
429 usage_limit_reached,系统会只冷却当前认证文件,并在同一次请求里继续尝试下一个候选 - 冷却时间优先使用上游
Retry-After,其次使用响应体里的resets_in_seconds/resets_at;都没有时默认 60 秒,最少 1 秒 - 冷却只保存在当前进程内;时间到后下一次构建候选列表会自动解除,服务重启也会丢失冷却状态
- 手动刷新配额或成功请求后的过期快照刷新,如果显示额度已恢复,会清掉该认证文件的内存冷却
- 请求成功后,如果当前使用的认证文件已有配额快照,且 Codex 窗口
reset_at已经过期,会最佳努力刷新这个文件的前端配额快照;刷新失败不会影响本次模型响应 - 遇到代理风险确认页时,会自动确认一次并重试原请求;自动确认失败或重试后仍被拦截时,向下游返回
proxy_warning_required和确认 URL - Codex 上游当前按流式响应处理;下游仍可以请求非流式响应,代理会聚合后返回
- Codex 流式响应以首个非空目标协议编码字节为提交边界;提交前的 transport 失败会尝试下一个可用认证文件
- Codex 流提交后的 transport 失败会记录当前认证文件失败,按下游协议发送错误事件并结束当前流
- Codex 流只有收到
response.completed或response.done才记录成功;缺少该终止事件的 EOF 按未完成流处理 - Codex 流被客户端取消时会关闭上游响应,不触发成功完成统计,也不更新认证文件成功或失败状态
/oauth页面支持逐个启用或禁用认证文件;禁用文件以灰态显示,可通过顶部“禁用”筛选快速定位,并且不参与后续请求调度- 禁用状态作用于后续请求的候选选择,已经发往上游的请求继续完成
/oauth页面支持查看配额、筛选认证文件,以及批量启用、批量禁用、批量刷新额度和批量删除认证文件
Claude OAuth 的账号候选和错误记录逻辑与 Codex 类似:每次请求重新构建候选列表,默认按认证文件修改时间倒序排列,但最近一次真实请求成功的认证文件会被提升到候选首位;人工禁用、认证失败、token 刷新失败或缺少 access_token 的文件会被跳过;选到候选后直接请求 Anthropic Messages 上游,失败时记录当前认证文件状态并尝试下一个候选。
Claude OAuth 当前没有 Codex 这套 usage 配额查询、前端配额快照和配额冷却机制。因此 Claude 的“可不可用”主要来自 token 刷新结果和真实上游请求结果,而不是调用 usage 接口预判。
- Claude 流式响应以首个非空目标协议编码字节为提交边界;提交前的 transport 失败会尝试下一个可用认证文件
- Claude 流提交后的 transport 失败会记录当前认证文件失败,按下游协议发送错误事件并结束当前流
- Claude 流只有收到
message_stop才记录成功;缺少该终止事件的 EOF 按未完成流处理 - Claude 流被客户端取消时会关闭上游响应,不触发成功完成统计,也不更新认证文件成功或失败状态
- 按请求里的
model自动选择对应 Provider - 支持流式和非流式响应
- Provider 支持开启上游强制流式:下游非流式请求会由代理聚合上游流式事件后返回完整响应,下游流式请求保持流式输出
- 自动识别 SSE、NDJSON 等 HTTP 上游返回形态
- 流式响应以首个非空、已经完成目标协议编码的下游字节为提交边界
- 普通 Provider 提交前的 transport 异常会在
max_retries定义的最大尝试次数范围内重新执行上游请求;尝试次数耗尽后返回结构化502错误响应 - Codex / Claude OAuth 提交前的 transport 异常会记录当前认证文件失败并尝试下一个候选认证文件
- 提交后的 transport 异常会按当前下游协议发送错误事件并结束流,当前请求不执行透明重试
- OpenAI Chat 使用 error JSON data block 和
[DONE],OpenAI Responses 使用response.failed,Claude Messages 使用event: error - 目标协议终止事件已经发出时,后续 HTTP framing 异常保持当前流的逻辑完成状态
- 客户端取消会关闭上游响应,不触发成功完成统计
- 内置 translator 会在 OpenAI Chat
reasoning_effort、OpenAI Responsesreasoning.effort和 Claudethinking之间转换思考意图;无法精确映射的档位会使用xhigh - OpenAI Chat 上游响应里的
reasoning_content和reasoning_details会按下游协议转换为 Claude thinking 或 OpenAI Responses reasoning 输出 GET /v1/models会返回当前已启用 Provider 中允许公开的模型和 Codex / Claude OAuth 模型列表,以及provider_name、source_format等元信息
- Provider 增删改查
- 支持行内启用 / 禁用,以及批量启用 / 禁用 / 删除
- 支持复制单个 Provider;复制项会插入到源 Provider 下方
- 支持按选中 Provider 导出 JSON;导出包包含 Provider、引用到的 Auth Group、Auth Entry 运行态和用量桶表项
- 支持导入 Provider JSON;同名 Provider 和 Auth Group 会追加数字后缀,Provider 的
auth_group引用会同步使用导入后的 Auth Group 名称 - Provider JSON 导入会按 Auth Group 重命名结果同步写入 Auth Entry 运行态和用量桶表项;相同主键使用导入值更新
- 拉取上游模型列表并辅助填充
model_list - Provider 表单使用表格方式维护
model_list,支持底部+行新增模型,并通过行内和表头眼睛按钮控制模型在下游GET /v1/models中的可见性 - Provider 表单支持单个或多个模型测试可用性、首字延迟与 TPS
- Auth Group 增删改查
- YAML 批量导入 Auth Entries
- 查看 Auth Group 运行时状态
- 对单个条目执行清冷却、禁用、启用、恢复、重置等运维动作
补充说明:
- “拉取模型” 属于控制平面预览请求;当 Provider 绑定
auth_group时,必须显式选择一个Auth Entry发起请求 - “拉取模型” 会使用当前 Provider 表单快照中的 Hook;Hook 返回模型列表时使用该结果,Hook 返回
None时继续使用内置模型端点探测 - “测试模型” 也属于控制平面请求,要求显式选择一个
Auth Entry - 模型测试不会进入正式运行态调度,不会写入 Auth Group 的冷却、并发和配额状态
Provider 编辑页的模型测试基于当前表单快照执行,不要求先保存 Provider,适合在接入新上游时先做联通性和基础性能确认。
- 支持单个模型测试,也支持多选模型批量测试
- 返回模型是否可用、首字延迟和 TPS
- 兼容
legacy api_key和auth_group + auth_entry_id - 会复用当前 Provider 的
source_format、proxy、timeout_seconds、verify_ssl和 Hook 配置 - 如果上游支持 usage 返回,测试链路会主动请求 usage,用于计算 TPS
- 批量测试时会先锁定本次选中的目标行,再按顺序逐条请求
- 每个模型一拿到结果就会立即回填到表格,不需要等待整批结束
当前行为边界:
- 模型测试只走 request side Hook:
header_hook、request_guard - 不会调用
response_guard - 如果使用
auth_group,测试固定走显式选择的Auth Entry - 即使测试成功,也不会修改正式代理链路里的 Provider 运行态或 Auth Group 运行态
- 批量测试属于当前页面会话内行为;如果刷新页面或离开当前页面,尚未开始的后续测试不会继续执行
- 登录页:
/login - Provider / Auth Group 管理:
/、/providers - 统计与日志面板:
/statistics - 用户管理:
/users - OAuth 管理:
/oauth - 系统设置:
/settings - 白名单按 IP 控制
- 当
chat.whitelist_enabled=true时,只有已登记且启用白名单权限的用户 IP 才能访问代理接口 - 用户管理支持用户迁移 JSON 导出、JSON 导入和批量删除;导出包包含用户表配置
- 用户迁移 JSON 导入按 IP 写入用户;IP 已存在时更新用户配置,IP 不存在时创建用户
- 应用日志写入
logs/app.log - 访问日志写入
logs/access.log - 请求明细和每日聚合统计写入 SQLite
- 流式 transport 失败和客户端取消不触发成功完成统计
- 后台支持按日期、用户名、模型过滤统计和日志数据
- 统计面板支持按当前筛选条件导出和导入统计迁移 JSON
- 统计迁移 JSON 包含
request_logs请求明细和daily_request_stats日聚合统计 - 请求明细导入按 IP、请求模型、响应模型、Token 数、开始时间和结束时间识别重复行;重复行跳过,新行插入
- 日聚合统计导入按日期、IP、请求模型、响应模型写入;相同维度累加请求数和 Token 数,不存在的维度插入新行
Hook 文件需要导出一个名为 Hook 的类。通常继承 BaseHook,也可以直接实现同名方法:
from src.hooks import BaseHook, HookContext可选扩展点有 4 个:
header_hook(ctx, headers) -> headersrequest_guard(ctx, body) -> bodyresponse_guard(ctx, body) -> bodyfetch_models(ctx, payload) -> models | payload | None
职责边界先说明白:
- 标准协议转换由
source_format和对应接口协议的 translator 完成 - Hook 不是协议转换层,不负责定义
openai_chat、openai_responses、claude_chat之间的标准映射 - Hook 负责的是请求进入上游前后的定制化处理,例如补 Header、做请求护栏、调整局部字段、清洗成功响应
触发顺序如下:
-
header_hook- 每次请求尝试都会调用一次,包括重试
- 调用时默认
content-type: application/json已经写入 - 如果 Provider 绑定了
auth_group或api_key,对应认证头也已经注入 - 适合补充或覆盖 Header、Cookie、Token 等信息
-
request_guard- 在协议转换之后、发送上游之前调用
- 拿到的是翻译给上游后的请求体,
body["model"]为真实上游模型 ID - 适合改写上游请求字段、补充 Provider 私有参数、调整
stream,或者做请求校验与护栏 - 返回
None时,代理会保留当前上游请求体
-
response_guard- 在协议转换之后调用
- 处理的是“已经翻译成下游协议的数据”,不是原始上游响应
- 非流式响应下,拿到的是完整的下游响应 payload
- 流式响应下,会对每个下游 chunk 的 payload 调用一次;终止 chunk 不经过这个 Hook
- 返回
None时,代理会保留原内容
-
fetch_models- 在 Provider 编辑页点击“拉取模型”时调用
payload包含api、api_key、headers、request_headers、candidate_urls、provider_name、source_format、auth_group、auth_entry_id、proxy_mode、proxy、timeout_seconds和verify_ssl- 返回模型名列表,或返回包含
data/models列表的 OpenAI 风格 payload - 返回
None时,系统继续使用内置/v1/models//models端点探测
当前行为边界:
response_guard可以改写成功响应,但不会处理上游HTTP >= 400的错误响应;这类错误会按当前代理逻辑直接返回- 已经提交的流式响应中,
response_guard异常会按当前下游协议发送错误事件并结束流 - 如果
request_guard改写了body.stream,后续请求与响应流程会按新的流式设置继续执行 - Provider 编辑页里的模型拉取使用
fetch_models,不会调用header_hook、request_guard或response_guard - Provider 编辑页里的模型测试只会复用
header_hook和request_guard,不会调用response_guard - Hook 按配置路径懒加载,不扫描
hooks/目录;每次调用 Hook 扩展点前都会检查对应 Hook 文件签名 - Hook 文件新增、删除或内容变化后,下一次使用该 Hook 路径时会按当前文件重新加载
- Hook 缓存弱引用实际 Hook 实例;没有 Provider 或控制平面临时对象引用时,实例可由运行时回收
适合用于:
- 注入额外 Header / Cookie / Token
- 在请求转发前做字段补充、删改和请求护栏
- 对成功响应做字段清洗、补全或内容改写
- 通过
HookAbortError主动中止当前请求
内置上游思考参数 Hook:
openai_reasoning_compat.py:汇总 Hook,按真实上游模型名和请求体model自动匹配 MiniMax、DeepSeek、GLM / Z.AI、Qwen / DashScopeminimax_openai_compat.py:MiniMax 专用 Hookdeepseek_openai_compat.py:DeepSeek 专用 Hookglm_openai_compat.py:GLM / Z.AI 专用 Hookqwen_openai_compat.py:Qwen / DashScope 专用 Hook
这些 Hook 只处理 OpenAI Chat 风格上游请求,会把 reasoning_effort、Responses 风格 reasoning.effort、Claude 风格 thinking 和 enable_thinking 规整成对应厂商参数:
- MiniMax:
reasoning_split=true;MiniMax-M3 使用thinking.type - DeepSeek V4:
thinking.type,开启思考时使用reasoning_effort=high|max - GLM / Z.AI:
thinking.type,开启思考时使用reasoning_effort=high|max,历史 assistant 消息含reasoning_content时设置clear_thinking=false - Qwen / DashScope:
enable_thinking、thinking_budget,历史 assistant 消息含reasoning_content时设置preserve_thinking=true
HookContext 会提供这些上下文信息:
retry:当前是第几次尝试,从0开始provider_namerequest_model:下游请求里的模型名,通常是provider/modelupstream_model:真正发往上游的模型名provider_source_formattransport:当前固定为httpstreamauth_group_nameauth_entry_idlast_status_codelast_error_type
其中:
- 首次尝试时,
last_status_code和last_error_type都是None - 如果上一轮重试失败是 HTTP 状态码导致的,例如
429,下一轮会看到last_status_code - 如果上一轮失败是本地传输错误,例如超时或连接错误,下一轮会看到
last_error_type - 流式响应提交后不产生新的 Provider 尝试,该阶段的失败不会进入下一轮
HookContext
- 配置文件:
config.yaml - 配置样例:
config.sample.yaml - Hook 目录:
hooks/ - Codex OAuth 认证目录:
data/oauth/codex/ - Claude OAuth 认证目录:
data/oauth/claude/ - SQLite 默认库:
data/requests.db - 日志目录:
logs/ - 请求调试日志:
logs/llm_request_trace.log - 架构文档:docs/architecture-4plus1.md
- 公网 HTTPS 上游建议显式设置
verify_ssl: true - 新增 Provider 时,先用后台“拉取模型”确认接口可达,再用模型表格里的“测试”确认目标模型可用性后再保存
model_list - 多 Key 场景优先使用
auth_group,不要把轮询和限流逻辑下放到客户端 - OAuth 场景先在
/settings开启 OAuth,再到/oauth完成登录、添加模型;Codex 可按需刷新配额 - OAuth 认证文件属于敏感文件,只应保存在受控机器本地
- 如果只是简单直连代理,不需要启用 Hook;只有在协议不兼容或鉴权不一致时再增加扩展逻辑
Hook 和认证扩展能力的设计目标是支持合法授权前提下的协议兼容与私有集成。请仅在拥有访问权限的前提下使用相关能力,并遵守上游服务的产品条款、访问策略和安全要求。