p5js.ai 2 API 是一个轻量级的反向代理适配器,将 https://p5js.ai/api/ai-chat 免费聊天接口同时包装成 Anthropic Messages API 和 OpenAI Chat Completions API 兼容接口。
这意味着任何支持 Anthropic 或 OpenAI 协议的工具——Claude Code、Chatbox、NextChat、LobeChat、one-api、Cherry Studio 等——都可以直接接入,就像连接一个真正的 Anthropic 或 OpenAI 端点一样。
- 双协议兼容 — 同时提供
/v1/messages(Anthropic)和/v1/chat/completions(OpenAI)端点 - Tool Use 仿真 — 上游不支持原生 tool_use,本服务通过 XML 格式的
<function_calls>提示词注入实现伪工具调用,并自动将响应中的 XML 解析回标准tool_use/tool_calls格式 - p5.js 噪声过滤 — 自动检测并剥离上游注入的 p5.js 助手问候语、前缀和尾缀
- SSE 修复 — 上游会输出畸形的
ddata:/ata:前缀,本服务自动修正为标准 SSE 格式 - 双层缓存 — 内存缓存 + 可选 Redis 二级缓存,相同请求自动命中,流式/非流式共用同一份完成结果
- In-flight 合并 — 并发相同请求不会重复打上游,follower 等待 leader 结果
- 连接池复用 — 共享 httpx 异步连接池,适合高并发场景
- 代理支持 — 支持
UPSTREAM_PROXY_URL或标准HTTP_PROXY/HTTPS_PROXY环境变量
p5js/
├── main.py # FastAPI 应用入口、路由定义
├── config.py # 常量、环境变量、模型列表、正则模式
├── filters.py # p5.js 噪声过滤、工具感知文本缓冲
├── tools.py # Tool XML 提示词构建、解析、提取
├── translate.py # 协议转换(Anthropic/OpenAI → 上游消息格式)
├── upstream.py # 上游 HTTP 客户端、SSE 解析、实时捕获
├── render.py # Artifact → Anthropic/OpenAI JSON/SSE 渲染
├── stream.py # 实时流处理(带/不带工具,带缓存集成)
├── response_cache.py # 双层缓存系统(内存 + Redis)
├── tests/ # 测试套件
│ ├── test_response_cache.py
│ └── test_filters.py
├── Dockerfile
├── docker-compose.yml
├── requirements.txt
├── start.sh
├── .env.example # 环境变量示例
└── README.md
./start.sh首次运行会自动创建 venv 并安装依赖,然后在 http://127.0.0.1:18185 监听。
# 直接构建
docker build -t p5js2api:latest .
docker run --rm -p 18185:18185 p5js2api:latest
# 或使用 docker compose(自带 Redis)
docker compose up -d --build默认 compose 配置同时启动一个本地 Redis 实例,端口通过 P5JS2API_PORT 环境变量控制(默认 18185)。
| 模型 | 说明 |
|---|---|
claude-opus-4-7 |
最新旗舰 |
claude-opus-4-6 |
|
claude-opus-4-1 / claude-opus-4-1-20250805 |
|
claude-opus-4-20250514 |
|
claude-sonnet-4-6 |
|
claude-sonnet-4-5 / claude-sonnet-4-5-20250929 |
默认模型 |
claude-sonnet-4-20250514 |
|
claude-haiku-4-5 / claude-haiku-4-5-20251001 |
轻量快速 |
| 路径 | 方法 | 说明 |
|---|---|---|
/health |
GET | 健康检查,返回服务状态、缓存统计、上游配置 |
/v1/models |
GET | 模型列表(Anthropic 格式) |
/v1/messages |
POST | Anthropic Messages API,支持 stream |
/v1/chat/completions |
POST | OpenAI Chat Completions API,支持 stream |
服务不校验 API Key,任意非空字符串均可通过认证。
export ANTHROPIC_BASE_URL=http://127.0.0.1:18185
export ANTHROPIC_AUTH_TOKEN=dummy
export ANTHROPIC_MODEL=claude-opus-4-7
export ANTHROPIC_SMALL_FAST_MODEL=claude-haiku-4-5
claudefrom openai import OpenAI
client = OpenAI(
base_url="http://127.0.0.1:18185/v1",
api_key="sk-dummy",
)
resp = client.chat.completions.create(
model="claude-sonnet-4-5",
messages=[{"role": "user", "content": "你好"}],
stream=True,
)
for chunk in resp:
print(chunk.choices[0].delta.content or "", end="", flush=True)- Base URL / API 地址:
http://127.0.0.1:18185/v1 - API Key: 任意非空字符串(如
sk-dummy) - 模型名: 填写上方「支持的模型」中的任一项
# Anthropic 协议
curl http://127.0.0.1:18185/v1/messages \
-H 'content-type: application/json' \
-H 'x-api-key: dummy' \
-d '{"model":"claude-sonnet-4-5","max_tokens":1024,"messages":[{"role":"user","content":"hi"}]}'
# OpenAI 协议
curl http://127.0.0.1:18185/v1/chat/completions \
-H 'content-type: application/json' \
-d '{"model":"claude-sonnet-4-5","messages":[{"role":"user","content":"hi"}]}'服务默认启用完整响应缓存:
- 先走进程内内存缓存(LRU,默认 256 条)
- 配置
RESPONSE_CACHE_REDIS_URL后升级为 内存 + Redis 双层缓存 - 相同请求并发命中 miss 时做 in-flight 合并,避免同时打爆上游
stream=true和stream=false共用同一份完成结果缓存
完整环境变量列表见 .env.example,核心配置:
| 变量 | 默认值 | 说明 |
|---|---|---|
RESPONSE_CACHE_ENABLED |
true |
是否启用缓存 |
RESPONSE_CACHE_TTL_SECS |
300 |
普通请求缓存 TTL(秒) |
RESPONSE_CACHE_TOOL_TTL_SECS |
120 |
带工具请求缓存 TTL(秒) |
RESPONSE_CACHE_MAX_ENTRY_BYTES |
33554432 |
单条缓存最大字节数(0 = 不限) |
RESPONSE_CACHE_REDIS_URL |
— | Redis 连接地址,配置后启用二级缓存 |
X-Proxy-Cache: HIT | MISS | BYPASS | DISABLEDX-Proxy-Cache-Source: memory | redis | inflight | live
任一方式:
- 请求头
X-Proxy-Cache: bypass - 请求头
Cache-Control: no-cache
容器内支持两种代理方式:
- 显式设置
UPSTREAM_PROXY_URL - 标准环境变量
HTTP_PROXY/HTTPS_PROXY/NO_PROXY
/health 里的 upstream.proxy_configured 会显示当前是否检测到代理配置。
┌─────────────┐ ┌──────────────────┐ ┌─────────────┐
│ Client │────▶│ p5js.ai 2 API │────▶│ p5js.ai │
│ (Claude/ │◀────│ (this project) │◀────│ upstream │
│ OpenAI) │ │ │ │ │
└─────────────┘ └──────────────────┘ └─────────────┘
│ ├─ 协议转换 │
│ ├─ Tool XML 注入/解析 │
│ ├─ p5.js 噪声过滤 │
│ ├─ SSE 修复 │
│ └─ 双层缓存 │
- 协议转换:将 Anthropic 或 OpenAI 格式的请求转换为 p5js.ai 上游格式(
messages+provider+model+deviceId+sessionId) - Tool Use 仿真:将工具定义注入系统提示词为 XML 格式,将上游文本响应中的
<function_calls>XML 块解析回标准tool_use/tool_calls - 噪声过滤:检测并剥离上游自动注入的 p5.js 助手问候语、标题、尾缀推荐
- SSE 修复:上游输出的畸形
ddata:/ata:前缀自动修正为标准data: - 缓存:完整响应缓存,流式和非流式共用,支持 in-flight 合并
- 上游 p5js.ai 会在没有 system 字段时注入 p5.js 助手提示词,客户端显式传
system(Anthropic)或{"role":"system"}消息(OpenAI)即可覆盖 - 流式缓存命中时会重新生成新的响应 ID / 时间戳,并按本地协议重新渲染
- 默认缓存上限 32 MiB,超过不会截断返回,只是跳过缓存,在
/health的cache.oversize_skips可见 - 设
RESPONSE_CACHE_MAX_ENTRY_BYTES=0可取消上限 - 本服务依赖 p5js.ai 接口可用性,上游变更可能影响使用
- 感谢 小辣椒的临时邮箱 提供注册支持
MIT License
p5js.ai 2 API is a lightweight reverse-proxy adapter that wraps the free chat endpoint at https://p5js.ai/api/ai-chat into both an Anthropic Messages API and an OpenAI Chat Completions API compatible interface.
This means any tool that speaks either protocol — Claude Code, Chatbox, NextChat, LobeChat, one-api, Cherry Studio, etc. — can connect to it as if it were a real Anthropic or OpenAI endpoint.
- Dual protocol — Serves both
/v1/messages(Anthropic) and/v1/chat/completions(OpenAI) - Pseudo tool use — The upstream doesn't support native tool_use; this service injects an XML-based
<function_calls>prompt and parses the XML back into propertool_use/tool_callsformat - p5.js noise filter — Automatically detects and strips p5.js assistant greetings, headings, and trailing recommendations injected by the upstream
- SSE fix-up — The upstream emits malformed
ddata:/ata:prefixes; this service auto-corrects them to standard SSE - Two-tier caching — In-memory + optional Redis second-level cache; streaming and non-streaming share the same completion cache
- In-flight deduplication — Concurrent identical requests don't hammer the upstream; followers wait for the leader's result
- Connection pooling — Shared httpx async connection pool for high-concurrency scenarios
- Proxy support — Supports
UPSTREAM_PROXY_URLor standardHTTP_PROXY/HTTPS_PROXYenv vars
p5js/
├── main.py # FastAPI app entry point, route definitions
├── config.py # Constants, env vars, model list, regex patterns
├── filters.py # p5.js noise filtering, tool-aware text buffering
├── tools.py # Tool XML prompt building, parsing, extraction
├── translate.py # Protocol translation (Anthropic/OpenAI → upstream format)
├── upstream.py # Upstream HTTP client, SSE parsing, live capture
├── render.py # Artifact → Anthropic/OpenAI JSON/SSE rendering
├── stream.py # Live stream handling (with/without tools, with cache integration)
├── response_cache.py # Two-tier cache system (memory + Redis)
├── tests/ # Test suite
│ ├── test_response_cache.py
│ └── test_filters.py
├── Dockerfile
├── docker-compose.yml
├── requirements.txt
├── start.sh
├── .env.example # Environment variable template
└── README.md
./start.shThe first run automatically creates a venv, installs dependencies, and listens on http://127.0.0.1:18185.
# Build and run
docker build -t p5js2api:latest .
docker run --rm -p 18185:18185 p5js2api:latest
# Or with docker compose (includes Redis)
docker compose up -d --buildThe default compose config spins up a local Redis instance. Port is controlled via the P5JS2API_PORT env var (default 18185).
| Model | Notes |
|---|---|
claude-opus-4-7 |
Latest flagship |
claude-opus-4-6 |
|
claude-opus-4-1 / claude-opus-4-1-20250805 |
|
claude-opus-4-20250514 |
|
claude-sonnet-4-6 |
|
claude-sonnet-4-5 / claude-sonnet-4-5-20250929 |
Default |
claude-sonnet-4-20250514 |
|
claude-haiku-4-5 / claude-haiku-4-5-20251001 |
Lightweight & fast |
| Path | Method | Description |
|---|---|---|
/health |
GET | Health check — returns service status, cache stats, upstream config |
/v1/models |
GET | Model list (Anthropic format) |
/v1/messages |
POST | Anthropic Messages API, supports stream |
/v1/chat/completions |
POST | OpenAI Chat Completions API, supports stream |
The service does not validate API keys — any non-empty string is accepted.
export ANTHROPIC_BASE_URL=http://127.0.0.1:18185
export ANTHROPIC_AUTH_TOKEN=dummy
export ANTHROPIC_MODEL=claude-opus-4-7
export ANTHROPIC_SMALL_FAST_MODEL=claude-haiku-4-5
claudefrom openai import OpenAI
client = OpenAI(
base_url="http://127.0.0.1:18185/v1",
api_key="sk-dummy",
)
resp = client.chat.completions.create(
model="claude-sonnet-4-5",
messages=[{"role": "user", "content": "Hello"}],
stream=True,
)
for chunk in resp:
print(chunk.choices[0].delta.content or "", end="", flush=True)- Base URL:
http://127.0.0.1:18185/v1 - API Key: Any non-empty string (e.g.
sk-dummy) - Model: Pick one from the "Supported Models" table above
# Anthropic protocol
curl http://127.0.0.1:18185/v1/messages \
-H 'content-type: application/json' \
-H 'x-api-key: dummy' \
-d '{"model":"claude-sonnet-4-5","max_tokens":1024,"messages":[{"role":"user","content":"hi"}]}'
# OpenAI protocol
curl http://127.0.0.1:18185/v1/chat/completions \
-H 'content-type: application/json' \
-d '{"model":"claude-sonnet-4-5","messages":[{"role":"user","content":"hi"}]}'The service enables full-response caching by default:
- In-process memory cache first (LRU, default 256 entries)
- Configure
RESPONSE_CACHE_REDIS_URLto upgrade to memory + Redis two-tier caching - Concurrent identical cache misses are in-flight deduplicated — followers wait for the leader
stream=trueandstream=falseshare the same completion cache
See .env.example for the full list. Key settings:
| Variable | Default | Description |
|---|---|---|
RESPONSE_CACHE_ENABLED |
true |
Enable/disable caching |
RESPONSE_CACHE_TTL_SECS |
300 |
Cache TTL for plain requests (seconds) |
RESPONSE_CACHE_TOOL_TTL_SECS |
120 |
Cache TTL for tool-use requests (seconds) |
RESPONSE_CACHE_MAX_ENTRY_BYTES |
33554432 |
Max cache entry size in bytes (0 = unlimited) |
RESPONSE_CACHE_REDIS_URL |
— | Redis URL; set to enable second-level cache |
X-Proxy-Cache: HIT | MISS | BYPASS | DISABLEDX-Proxy-Cache-Source: memory | redis | inflight | live
Either of:
- Request header
X-Proxy-Cache: bypass - Request header
Cache-Control: no-cache
Two proxy options inside the container:
- Explicit
UPSTREAM_PROXY_URL - Standard env vars
HTTP_PROXY/HTTPS_PROXY/NO_PROXY
The /health endpoint's upstream.proxy_configured field shows whether a proxy is detected.
┌─────────────┐ ┌──────────────────┐ ┌─────────────┐
│ Client │────▶│ p5js.ai 2 API │────▶│ p5js.ai │
│ (Claude/ │◀────│ (this project) │◀────│ upstream │
│ OpenAI) │ │ │ │ │
└─────────────┘ └──────────────────┘ └─────────────┘
│ ├─ Protocol translation │
│ ├─ Tool XML inject/parse │
│ ├─ p5.js noise filtering │
│ ├─ SSE fix-up │
│ └─ Two-tier caching │
- Protocol translation: Converts Anthropic or OpenAI format requests into the p5js.ai upstream format (
messages+provider+model+deviceId+sessionId) - Tool use emulation: Injects tool definitions as XML into the system prompt, parses
<function_calls>XML blocks from upstream text responses back into standardtool_use/tool_calls - Noise filtering: Detects and strips p5.js assistant greetings, headings, and trailing recommendations auto-injected by the upstream
- SSE fix-up: Auto-corrects malformed
ddata:/ata:prefixes to standarddata: - Caching: Full-response caching shared between streaming and non-streaming, with in-flight deduplication
- The upstream p5js.ai injects a p5.js assistant prompt when no
systemfield is present. Passingsystem(Anthropic) or a{"role":"system"}message (OpenAI) overrides it. - Cache hits re-generate new response IDs/timestamps and re-render per the local protocol.
- Default cache entry limit is 32 MiB. Oversized entries are not truncated — they're simply not cached. Check
/health→cache.oversize_skips. - Set
RESPONSE_CACHE_MAX_ENTRY_BYTES=0to remove the limit. - This service depends on p5js.ai availability. Upstream changes may affect functionality.
- Special thanks to 小辣椒的临时邮箱 (Xiaolajiao Temp Mail) for registration support
MIT License