Files
lingma-openai-gateway/README.md
GitHub Actions d9dffbb8ba docs: restructure README + add DESIGN.md (二开白盒手册)
README 重写为分层结构:架构速览 + 快速开始 + 按主题分组的配置表 +
API 参考 + 常用场景 + 升级注意 + 故障排查 + 二开入口。相比旧版:
更好导航,破坏性改动显式标注升级路径,故障排查能覆盖生产常见坑。

DESIGN.md 是全新的工程手册,覆盖:项目目标/非目标、组件数据流、
模块职责表、6 个核心流程的 ASCII 图解(启动、非流式/流式 chat、
子进程 + LSP、bundle、自动登录、关闭)、11 条关键设计决策
(每条带问题/方案/权衡/未选其他方案原因)、扩展指引(常见需求 → 改哪些文件)、
已知问题 / TODO、完整迭代历程(M1~M4 + M3 性能 bug 根因)、
Lingma LSP 协议速查。

目标:新成员或几个月后的自己能在一天内理清全项目。

Made-with: Cursor
2026-04-18 10:36:17 +08:00

16 KiB
Raw Blame History

Lingma OpenAI Gateway

把本地 Lingma 插件封装成 OpenAI 兼容接口。任何能调 OpenAI 的客户端Cursor、Dify、LangChain、curl…都能直接接入。

支持: GET /v1/models / POST /v1/chat/completions(含 SSE 流式) / Bearer 鉴权 / Prometheus / 多账号实例池 / 会话复用 / 免浏览器登录态注入。

想看架构、模块划分、设计决策、二开路线图 → 直接读 DESIGN.md


架构速览

 ┌─────────────┐   OpenAI 协议    ┌─────────────────────────────────────────┐
 │  任意客户端  │  ───────────▶    │  FastAPI (app/main.py)                  │
 │  (curl/     │                  │  ├─ auth_guard / admin_guard            │
 │   Cursor/   │                  │  ├─ chat_guard (InFlightGuard 背压)     │
 │   Dify…)    │                  │  ├─ SessionCache (LRU+TTL, KV 复用)     │
 └─────────────┘                  │  └─ StatsCollector + Prometheus         │
                                  └────────────────┬────────────────────────┘
                                                   │ 选实例 (least-in-flight + affinity)
                                  ┌────────────────▼────────────────────────┐
                                  │  LingmaPool (app/lingma_pool.py)        │
                                  │  ├─ inst-0  inst-1  inst-N …            │
                                  │  └─ 启动前自动 restore session bundle   │
                                  └────────────────┬────────────────────────┘
                                                   │
                           ┌───────────────────────┼───────────────────────┐
                           ▼                       ▼                       ▼
                ┌────────────────────┐  ┌────────────────────┐  ┌────────────────────┐
                │ LingmaGatewayClient│  │        …           │  │        …           │
                │ (LSP over WS)      │  │                    │  │                    │
                │ ├─ Popen (PID管理) │  │                    │  │                    │
                │ ├─ reconnect loop  │  │                    │  │                    │
                │ └─ ws://:PORT      │  │                    │  │                    │
                └──────────┬─────────┘  └────────────────────┘  └────────────────────┘
                           │ spawn + ws
                ┌──────────▼─────────┐
                │   Lingma 二进制     │
                │   --workDir /…     │
                └────────────────────┘

一、快速开始

git clone <repo>
cd lingma-openai-gateway
cp .env.example .env
# 至少填 API_KEYS + LINGMA_USERNAME + LINGMA_PASSWORD或 session bundle
mkdir -p data secrets
docker compose up -d --build
docker compose logs -f   # 看到 "Uvicorn running on..." 就 OK

冒烟测试:

API_KEY=$(grep '^API_KEYS=' .env | cut -d= -f2 | cut -d, -f1)
curl -s http://127.0.0.1:8317/healthz
curl -s http://127.0.0.1:8317/v1/models -H "Authorization: Bearer $API_KEY"
curl -s http://127.0.0.1:8317/v1/chat/completions \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"org_auto","messages":[{"role":"user","content":"hi"}]}'

二、配置参考

.env.example 是权威说明,这里按主题分组。

2.1 核心

变量 默认 说明
HOST / PORT 0.0.0.0 / 8317 网关监听地址与端口
API_KEYS Bearer key多个逗号分隔留空则 /v1/* 无鉴权,启动会 warn
LOG_LEVEL INFO DEBUG/INFO/WARNING/ERROR,日志为结构化 JSONrequest_id
DEFAULT_MODEL org_auto 模型无法映射时兜底
DEFAULT_ASK_MODE chat chatagent(传 model: "agent" 时自动切)
DEDICATED_DOMAIN_URL 企业专属域(可空)

2.2 权限分层(生产建议全配)

变量 默认 说明
ADMIN_TOKEN /internal/* 专属 token未配置时 fallback 到 API_KEYS(兼容);都为空 → 503
METRICS_TOKEN /metrics 专属 token未配置时 fallback 到 API_KEYS
METRICS_PUBLIC false 显式公开 /metrics(仅用于私网采集器)

ADMIN_TOKEN / METRICS_TOKEN / API_KEYS 三者都为空时,/metrics/internal/* 会返回 503拒绝裸奔

2.3 并发与背压

变量 默认 说明
GATEWAY_MAX_IN_FLIGHT 4 并发上限;<=0 表示不限
GATEWAY_QUEUE_TIMEOUT_SEC 30 排队超时;超时直接返回 429 + Retry-After

2.4 Lingma 进程

变量 默认 说明
LINGMA_BIN /app/data/bin/Lingma 容器内二进制路径
LINGMA_SOURCE_TYPE marketplace marketplacevsix
LINGMA_MARKETPLACE_PUBLISHER Alibaba-Cloud Marketplace 发布者
LINGMA_MARKETPLACE_EXTENSION tongyi-lingma Marketplace 扩展名
LINGMA_VSIX_URL 官方地址 兜底 VSIX 下载地址
LINGMA_BOOTSTRAP_ALWAYS true 启动时总是尝试刷新二进制
LINGMA_FORCE_REFRESH false 强制忽略本地缓存重新下载
LINGMA_WORK_DIR /app/data/.lingma/vscode/sharedClientCache 登录态/缓存所在目录
LINGMA_SOCKET_PORT 36510 单实例模式下的 Lingma WS 端口
LINGMA_STARTUP_TIMEOUT 40 启动超时秒
LINGMA_RPC_TIMEOUT 30 单次 RPC 超时秒

2.5 多账号 / 多实例池

变量 默认 说明
LINGMA_ACCOUNTS u1:p1,u2:p2 或 JSON 数组;配置后每个账号 = 一个独立 Lingma 子进程
LINGMA_INSTANCE_COUNT 账号数 显式指定实例数;不足账号循环复用并打 warn
LINGMA_USERNAME / LINGMA_PASSWORD 单实例兼容模式(仅 LINGMA_ACCOUNTS 为空时生效)

2.6 会话复用KV cache 优化)

变量 默认 说明
SESSION_REUSE_ENABLED true 多轮对话命中时只发增量 user 消息 + 复用上游 sessionId
SESSION_CACHE_MAX_ENTRIES 256 LRU 容量
SESSION_CACHE_TTL_SEC 1800 TTL避免命中已回收的 session

2.7 登录态注入(跳过 Playwright

变量 默认 说明
LINGMA_SESSION_BUNDLE base64 格式的 bundleinline适合短字符串
LINGMA_SESSION_BUNDLE_FILE bundle 文件路径(推荐,避免 env 过长)

2.8 自动登录

变量 默认 说明
AUTO_LOGIN_ENABLED true 未登录时自动启 Playwright
AUTO_LOGIN_HEADLESS true 无头浏览器
AUTO_LOGIN_TIMEOUT 180 登录超时秒
AUTO_LOGIN_MAX_RETRY 2 登录失败重试次数

三、API 参考

3.1 公共(API_KEYS

方法 路径 说明
GET /healthz 免鉴权;返回 ok / pool_size / pool_ready / 每实例状态
GET /v1/models OpenAI 兼容;id 是 Lingma 原 keyname 是可读名
POST /v1/chat/completions OpenAI 兼容;stream=true 走 SSEmodel: "agent" 切 agent 模式

chat 请求示例(非流式)

curl -s http://127.0.0.1:8317/v1/chat/completions \
  -H "Authorization: Bearer $API_KEY" -H "Content-Type: application/json" \
  -d '{"model":"dashscope_qmodel","messages":[{"role":"user","content":"你好"}]}'

chat 请求示例(流式 + usage

curl -N http://127.0.0.1:8317/v1/chat/completions \
  -H "Authorization: Bearer $API_KEY" -H "Content-Type: application/json" \
  -d '{
    "model":"dashscope_qmodel",
    "stream":true,
    "stream_options":{"include_usage":true},
    "messages":[{"role":"user","content":"介绍一下你自己"}]
  }'

3.2 观测(METRICS_TOKENAPI_KEYS

方法 路径 说明
GET /metrics Prometheus 文本;含池每实例 gauge、并发、session cache 命中率、token 计数

3.3 管理(ADMIN_TOKEN 或 fallback 到 API_KEYS

方法 路径 说明
GET /internal/stats JSONstats + concurrency + pool + session_cache
GET /internal/auto-login/status 每实例登录态与 auto_login 状态
POST /internal/auto-login/start?instance=inst-0 主动触发某实例登录(可不传,由 pool.pick 选)
POST /internal/session/export?instance=inst-0 把已登录实例的 cache 打包成 base64 bundle
GET /internal/models/raw?instance=inst-0 Lingma 原始 config/queryModels 响应displayName / isReasoning / isVl 等)

四、常用场景

4.1 多账号池

LINGMA_ACCOUNTS=user1:pass1,user2:pass2,user3:pass3
# LINGMA_INSTANCE_COUNT=3   # 不写默认=账号数
  • 每个账号一个独立 Lingma 子进程 + 独立 workDirdata/.lingma/pool/inst-<i>/)。
  • 路由:同 user 字段或同 system prompt 的请求粘性分到同一实例;其他按最小在途分配。
  • 一个实例挂掉不影响整体,/healthz.pool_ready 下降,自动重连。

4.2 跳过 Playwrightsession bundle

从已登录实例导出:

curl -sS -X POST \
  -H "Authorization: Bearer $ADMIN_TOKEN" \
  "http://host:port/internal/session/export" \
  | jq -r '.bundle_b64' > secrets/lingma-session.b64
chmod 600 secrets/lingma-session.b64

在新部署注入(选一种):

# 文件注入(推荐)—— 需要在 docker-compose.yml 挂载 secrets 目录
LINGMA_SESSION_BUNDLE_FILE=/secrets/lingma-session.b64

# 或 inline适合小 bundle
LINGMA_SESSION_BUNDLE=H4sIAAAA...

# 多账号 JSON 模式,每账号独立 bundle
LINGMA_ACCOUNTS=[
  {"username":"u1","password":"p1","session_bundle_file":"/secrets/u1.b64"},
  {"username":"u2","password":"p2","session_bundle":"H4sIAAAA..."}
]

行为保证:

  • 只在目标 workDir 空(cache/user 不存在或 empty时才注入不会覆盖活跃登录态。
  • 注入失败(损坏/权限)自动 fallback 到 Playwright。
  • bundle 只含 cache/{id,user,quota,config.json} 4 个文件;大小上限 4 MiB实际通常 < 10 KB。
  • bundle 等同于密钥,落盘需 chmod 600,不要进 git。

4.3 Prometheus 接入

# prometheus scrape_configs 片段
- job_name: lingma-gateway
  bearer_token: <METRICS_TOKEN>
  static_configs: [{targets: ['host:8317']}]
  metrics_path: /metrics

关键指标:

指标 类型 意义
gateway_in_flight / gateway_queued gauge 并发 / 排队
gateway_rejected_total counter 背压拒绝429累计
gateway_pool_instance_ready{name} gauge 每实例是否就绪0/1
gateway_pool_instance_in_flight{name} gauge 每实例在途
gateway_session_cache_hit_total / _miss_total counter 会话复用命中率原料
gateway_chat_requests_success / _error counter chat 成功率

五、升级注意事项

从旧版本升级时注意破坏性变更(每一项都有 fallback默认不会炸但建议显式配置

版本 变更 应对
v0.3 /metrics 裸奔时(无 token / 无 key由公开改为 503 显式配 METRICS_PUBLIC=trueMETRICS_TOKEN
v0.3 /internal/* 引入 ADMIN_TOKEN 未配置自动 fallback 到 API_KEYS,生产建议单独配
v0.2 默认会话复用(多轮对话只发增量) 如果你的客户端裁剪了历史导致语义不连续,设 SESSION_REUSE_ENABLED=false
v0.2 Chat 请求走 JSON-RPC notify 而非 request(修复 30s TTFB bug 无需行动
v0.2 多实例池(LINGMA_ACCOUNTS 存在时启用) 不配则保持单实例行为

六、故障排查FAQ

症状 排查方向
/healthz 返回 ok=false / pool_ready=0 docker logs,关键字 lingma spawned / state ... -> ready;若卡在 starting → Lingma 二进制或 workDir 权限问题
返回 401 且带 Invalid admin token 你用了 API_KEYS 去打 /internal/*,但服务端已设了 ADMIN_TOKEN;用 ADMIN_TOKEN 或清空 ADMIN_TOKEN
返回 503 metrics scraping disabled 三个 env 全空,按 "权限分层" 章节配任一
返回 429 Too many in-flight 并发超过 GATEWAY_MAX_IN_FLIGHT;增大或客户端加重试
首 token 延迟 2-3 秒 Lingma 侧常态;多轮对话第二轮起,会话复用命中后 TTFB 明显降低(看 gateway_session_cache_hit_total
Playwright 登录失败 导出一个已登录 bundle 注入(见 4.2),彻底跳过浏览器
容器重启后 Lingma 要重新登录 data/ 没挂在卷上或被清过;确认 ./data:/app/data 挂载 + bundle fallback
升级后 /metrics 返回 503 v0.3 默认严格;按表格 5.1 配置

LOG_LEVEL=DEBUG 可以看到 Lingma 子进程的 stderr 输出,便于定位 native 崩溃。


七、开发与二开

项目本身是单仓 FastAPI3400 行 Python。推荐阅读路径

  1. 先读 DESIGN.md —— 架构、模块职责、关键设计决策、二开指引。
  2. 再按需读对应模块:
    • 想改请求入口 / 路由 → app/main.py
    • 想加实例调度策略 → app/lingma_pool.py::pick()
    • 想改 Lingma 通信协议 → app/lingma_client.py
    • 想扩展会话复用 → app/session_cache.py + main.py 的 reuse 块
    • 想做认证改造 → app/auth.py + main.py::*_guard
  3. 本地跑:pip install -r requirements.txt && uvicorn app.main:app --reload

八、目录结构

lingma-openai-gateway/
├── app/                        # 主代码(见 DESIGN.md 模块一览)
│   ├── main.py                 # FastAPI 入口 + 路由
│   ├── lingma_pool.py          # N 实例池
│   ├── lingma_client.py        # LSP over WS + 子进程管理
│   ├── session_cache.py        # 多轮对话 sessionId 复用
│   ├── session_bundle.py       # 登录态 export/import
│   ├── concurrency.py          # InFlightGuard 背压
│   ├── auto_login.py           # Playwright 登录
│   ├── auth.py                 # Bearer / admin / metrics 三档鉴权
│   ├── config.py               # 环境变量 → dataclass
│   ├── model_map.py            # 模型 key ↔ displayName
│   ├── openai_schema.py        # OpenAI 请求/响应 Pydantic
│   ├── stats.py                # StatsCollector + Prometheus
│   ├── logging_config.py       # 结构化 JSON log + request_id 上下文
│   └── bootstrap_lingma.py     # 启动时下载/提取 Lingma 二进制
├── data/                       # 持久化Lingma 二进制 + workDir不进 git
├── secrets/                    # 注入的 bundle 等敏感文件,不进 git
├── Dockerfile                  # Playwright base + HEALTHCHECK
├── docker-compose.yml
├── .env.example                # 配置权威文档
├── requirements.txt
├── README.md                   # 本文件
└── DESIGN.md                   # 架构与二开手册

License

内部使用,按需调整。