Expose capability discovery plus admin-only config and request inspection endpoints so clients and operators can understand gateway behavior without reading code. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
252 lines
6.6 KiB
Markdown
252 lines
6.6 KiB
Markdown
# Lingma OpenAI Gateway
|
||
|
||
将 Lingma 封装为 OpenAI / Anthropic 兼容网关,便于现有客户端直接接入。
|
||
|
||
- OpenAI:`/v1/models`、`/v1/chat/completions`(含 stream)
|
||
- Anthropic:`/v1/messages`、`/v1/messages/count_tokens`(含 stream)
|
||
- 能力探测:`/capabilities`、`/v1/capabilities`
|
||
- 内省端点:`/internal/effective-config`、`/internal/debug/requests`
|
||
- 内置:多实例池、会话复用、Prometheus 指标、登录态 bundle 注入
|
||
- 工具事件桥接:Lingma 上游返回 `tool` 事件时,网关会输出为 OpenAI `tool_calls`(stream/non-stream)和 Anthropic `tool_use` / `tool_result`(stream/non-stream);请求侧 `tools` / `tool_choice` 仅在 `TOOL_FORWARD_ENABLED=true` 时透传(默认开启,可显式关闭)
|
||
- 工具模拟回退:当 Lingma 未稳定外显原生 `tool/*` 事件时,网关会把注入后的 `json action` / `#Tool Call` 等动作文本归一化为 OpenAI `tool_calls`,并支持 tool result continuation
|
||
- 多模态降级:OpenAI `image_url` / `input_image` 转 `[image]`,`input_audio` 转 `[audio]`;Anthropic `image` 转 `[image]`
|
||
|
||
> 架构设计与二开细节请看 [`DESIGN.md`](./DESIGN.md)。
|
||
|
||
---
|
||
|
||
## 目录
|
||
|
||
1. [5 分钟启动](#5-分钟启动)
|
||
2. [常用命令](#常用命令)
|
||
3. [最小 API 示例](#最小-api-示例)
|
||
4. [部署与更新](#部署与更新)
|
||
5. [排障速查](#排障速查)
|
||
6. [文档入口](#文档入口)
|
||
|
||
---
|
||
|
||
## 5 分钟启动
|
||
|
||
### 1) 准备配置
|
||
|
||
```bash
|
||
git clone <repo>
|
||
cd lingma-openai-gateway
|
||
cp .env.example .env
|
||
```
|
||
|
||
至少配置这些变量(在 `.env`):
|
||
|
||
- `API_KEYS`
|
||
- `LINGMA_USERNAME` / `LINGMA_PASSWORD`(或 `LINGMA_SESSION_BUNDLE(_FILE)`)
|
||
|
||
### 2) Docker 启动(推荐)
|
||
|
||
```bash
|
||
mkdir -p data secrets
|
||
docker compose up -d --build
|
||
docker compose logs -f
|
||
```
|
||
|
||
### 3) 冒烟检查
|
||
|
||
```bash
|
||
PORT=$(grep '^PORT=' .env | cut -d= -f2)
|
||
API_KEY=$(grep '^API_KEYS=' .env | cut -d= -f2 | cut -d, -f1)
|
||
|
||
curl -s "http://127.0.0.1:${PORT}/healthz"
|
||
curl -s "http://127.0.0.1:${PORT}/v1/models" \
|
||
-H "Authorization: Bearer ${API_KEY}"
|
||
curl -s "http://127.0.0.1:${PORT}/capabilities"
|
||
```
|
||
|
||
---
|
||
|
||
## 常用命令
|
||
|
||
### 本地开发运行
|
||
|
||
```bash
|
||
pip install -r requirements.txt
|
||
uvicorn app.main:app --reload --port 8317
|
||
```
|
||
|
||
### Docker 常用
|
||
|
||
```bash
|
||
docker compose up -d --build
|
||
docker compose logs -f
|
||
docker compose ps
|
||
docker compose down
|
||
```
|
||
|
||
### 测试
|
||
|
||
```bash
|
||
# 重点回归套件
|
||
python3 -m unittest tests/test_tool_call_bridge.py
|
||
|
||
# 全量 unittest
|
||
python3 -m unittest discover -s tests -p "test_*.py"
|
||
|
||
# Docker 端到端工具调用冒烟
|
||
bash scripts/smoke_tool_calls.sh
|
||
```
|
||
|
||
---
|
||
|
||
## 最小 API 示例
|
||
|
||
先取 key:
|
||
|
||
```bash
|
||
PORT=$(grep '^PORT=' .env | cut -d= -f2)
|
||
API_KEY=$(grep '^API_KEYS=' .env | cut -d= -f2 | cut -d, -f1)
|
||
```
|
||
|
||
### OpenAI:非流式
|
||
|
||
```bash
|
||
curl -s "http://127.0.0.1:${PORT}/v1/chat/completions" \
|
||
-H "Authorization: Bearer ${API_KEY}" \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"model": "org_auto",
|
||
"messages": [{"role": "user", "content": "hi"}],
|
||
"stream": false
|
||
}'
|
||
```
|
||
|
||
### OpenAI:流式
|
||
|
||
```bash
|
||
curl -N "http://127.0.0.1:${PORT}/v1/chat/completions" \
|
||
-H "Authorization: Bearer ${API_KEY}" \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"model": "org_auto",
|
||
"messages": [{"role": "user", "content": "say hi"}],
|
||
"stream": true
|
||
}'
|
||
```
|
||
|
||
### Anthropic:非流式
|
||
|
||
```bash
|
||
curl -s "http://127.0.0.1:${PORT}/v1/messages" \
|
||
-H "x-api-key: ${API_KEY}" \
|
||
-H "anthropic-version: 2023-06-01" \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"model": "claude-3-5-sonnet-20241022",
|
||
"max_tokens": 256,
|
||
"messages": [{"role": "user", "content": "hi"}],
|
||
"stream": false
|
||
}'
|
||
```
|
||
|
||
### Anthropic:流式
|
||
|
||
```bash
|
||
curl -N "http://127.0.0.1:${PORT}/v1/messages" \
|
||
-H "x-api-key: ${API_KEY}" \
|
||
-H "anthropic-version: 2023-06-01" \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"model": "claude-3-5-sonnet-20241022",
|
||
"max_tokens": 256,
|
||
"messages": [{"role": "user", "content": "say hi"}],
|
||
"stream": true
|
||
}'
|
||
```
|
||
|
||
### Anthropic:count_tokens
|
||
|
||
```bash
|
||
curl -s "http://127.0.0.1:${PORT}/v1/messages/count_tokens" \
|
||
-H "x-api-key: ${API_KEY}" \
|
||
-H "anthropic-version: 2023-06-01" \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"model": "claude-3-5-sonnet-20241022",
|
||
"max_tokens": 64,
|
||
"messages": [{"role": "user", "content": "count me"}]
|
||
}'
|
||
```
|
||
|
||
### 能力探测
|
||
|
||
```bash
|
||
curl -s "http://127.0.0.1:${PORT}/capabilities"
|
||
|
||
curl -s "http://127.0.0.1:${PORT}/v1/capabilities" \
|
||
-H "x-api-key: ${API_KEY}" \
|
||
-H "anthropic-version: 2023-06-01"
|
||
```
|
||
|
||
### 内省端点(admin)
|
||
|
||
如果配置了 `ADMIN_TOKEN`,以下端点需要使用该 token;否则会回退复用 `API_KEYS`。
|
||
|
||
```bash
|
||
ADMIN_TOKEN=${ADMIN_TOKEN:-$API_KEY}
|
||
|
||
curl -s "http://127.0.0.1:${PORT}/internal/effective-config" \
|
||
-H "Authorization: Bearer ${ADMIN_TOKEN}"
|
||
|
||
curl -s "http://127.0.0.1:${PORT}/internal/debug/requests?limit=5" \
|
||
-H "Authorization: Bearer ${ADMIN_TOKEN}"
|
||
```
|
||
|
||
> `internal/debug/requests` 会对 token、session bundle、data URL 图片和超长工具参数做脱敏/截断。
|
||
|
||
---
|
||
|
||
## 部署与更新
|
||
|
||
### 服务器更新到最新 main
|
||
|
||
```bash
|
||
cd /root/lingma-openai-gateway
|
||
git fetch origin
|
||
git checkout -B main origin/main
|
||
git reset --hard origin/main
|
||
git clean -fd
|
||
docker compose up -d --build
|
||
docker compose ps
|
||
```
|
||
|
||
### 健康检查
|
||
|
||
```bash
|
||
PORT=$(grep '^PORT=' .env | cut -d= -f2)
|
||
curl -s "http://127.0.0.1:${PORT}/healthz"
|
||
```
|
||
|
||
---
|
||
|
||
## 排障速查
|
||
|
||
| 现象 | 常见原因 | 处理 |
|
||
|---|---|---|
|
||
| `/v1/*` 返回 401 | 缺失或错误 API key | 检查 `Authorization: Bearer` 或 `x-api-key` |
|
||
| `healthz` 正常但请求失败 | 用错端口 | 以 `.env` 的 `PORT` 为准,`docker compose ps` 再确认 |
|
||
| `git pull` 提示 not on a branch | 处于 detached HEAD | 执行 `git checkout -B main origin/main` |
|
||
| 自动登录不稳定 | 浏览器流程波动 | 优先使用 `LINGMA_SESSION_BUNDLE(_FILE)` |
|
||
| 日志出现 `extension main js path not found` / `ExtensionApi executor not inited` | Lingma 扩展运行时未完整提取,MCP/工具执行器未初始化 | 重启容器触发 bootstrap 自愈;确认 `data/bin/<version>/extension/main.js` 已存在 |
|
||
| 工具调用未触发 | 模型未选择工具或当前协议路径不支持合成回退 | OpenAI 可配合 `tool_choice` 强制并约束输出 JSON;Anthropic 当前仅 non-stream 支持合成 `tool_use` / `tool_result` 回退 |
|
||
|
||
---
|
||
|
||
## 文档入口
|
||
|
||
- 配置权威:[`/.env.example`](./.env.example)
|
||
- 架构/模块边界/设计决策:[`/DESIGN.md`](./DESIGN.md)
|
||
- 主要入口代码:[`/app/main.py`](./app/main.py)
|
||
- 测试:[`/tests/test_tool_call_bridge.py`](./tests/test_tool_call_bridge.py)
|
||
|
||
## License
|
||
|
||
MIT
|