--- title: p5jsAi API emoji: 🚀 colorFrom: blue colorTo: purple sdk: docker pinned: false --- # p5js.ai 2 API [English](#english) | [中文](#中文) --- ## p5js.ai 2 API — 将 p5js.ai 免费接口包装为 Anthropic / OpenAI 兼容 API `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 格式的 `` 提示词注入实现伪工具调用,并自动将响应中的 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 ``` ### 快速开始 #### 本地运行 ```bash ./start.sh ``` 首次运行会自动创建 `venv` 并安装依赖,然后在 `http://127.0.0.1:18185` 监听。 #### Docker 部署 ```bash # 直接构建 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,任意非空字符串均可通过认证。 ### 使用示例 #### Claude Code(Anthropic 协议) ```bash 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 claude ``` #### OpenAI Python SDK ```python from 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) ``` #### 第三方工具(Chatbox / NextChat / LobeChat / one-api / Cherry Studio 等) - **Base URL / API 地址**: `http://127.0.0.1:18185/v1` - **API Key**: 任意非空字符串(如 `sk-dummy`) - **模型名**: 填写上方「支持的模型」中的任一项 #### curl ```bash # 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 | DISABLED` - `X-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 修复 │ │ └─ 双层缓存 │ ``` 1. **协议转换**:将 Anthropic 或 OpenAI 格式的请求转换为 p5js.ai 上游格式(`messages` + `provider` + `model` + `deviceId` + `sessionId`) 2. **Tool Use 仿真**:将工具定义注入系统提示词为 XML 格式,将上游文本响应中的 `` XML 块解析回标准 `tool_use` / `tool_calls` 3. **噪声过滤**:检测并剥离上游自动注入的 p5.js 助手问候语、标题、尾缀推荐 4. **SSE 修复**:上游输出的畸形 `ddata:` / `ata:` 前缀自动修正为标准 `data:` 5. **缓存**:完整响应缓存,流式和非流式共用,支持 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 接口可用性,上游变更可能影响使用 ### 致谢 - 感谢 [小辣椒的临时邮箱](https://vip.215.im) 提供注册支持 ### 许可证 MIT License --- ## p5js.ai 2 API — Wrap p5js.ai Free Chat as Anthropic / OpenAI Compatible API `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. ### Key Features - **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 `` prompt and parses the XML back into proper `tool_use` / `tool_calls` format - **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_URL` or standard `HTTP_PROXY` / `HTTPS_PROXY` env vars ### Project Structure ``` 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 ``` ### Quick Start #### Local ```bash ./start.sh ``` The first run automatically creates a `venv`, installs dependencies, and listens on `http://127.0.0.1:18185`. #### Docker ```bash # 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 --build ``` The default compose config spins up a local Redis instance. Port is controlled via the `P5JS2API_PORT` env var (default `18185`). ### Supported Models | 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 | ### API Endpoints | 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. ### Usage Examples #### Claude Code (Anthropic Protocol) ```bash 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 claude ``` #### OpenAI Python SDK ```python from 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) ``` #### Third-party Tools (Chatbox / NextChat / LobeChat / one-api / Cherry Studio etc.) - **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 #### curl ```bash # 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"}]}' ``` ### Caching The service enables full-response caching by default: - In-process memory cache first (LRU, default 256 entries) - Configure `RESPONSE_CACHE_REDIS_URL` to upgrade to **memory + Redis** two-tier caching - Concurrent identical cache misses are **in-flight deduplicated** — followers wait for the leader - `stream=true` and `stream=false` share the same completion cache #### Environment Variables 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 | #### Response Headers - `X-Proxy-Cache: HIT | MISS | BYPASS | DISABLED` - `X-Proxy-Cache-Source: memory | redis | inflight | live` #### Bypass Cache Either of: - Request header `X-Proxy-Cache: bypass` - Request header `Cache-Control: no-cache` ### Proxy Configuration 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. ### How It Works ``` ┌─────────────┐ ┌──────────────────┐ ┌─────────────┐ │ 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 │ ``` 1. **Protocol translation**: Converts Anthropic or OpenAI format requests into the p5js.ai upstream format (`messages` + `provider` + `model` + `deviceId` + `sessionId`) 2. **Tool use emulation**: Injects tool definitions as XML into the system prompt, parses `` XML blocks from upstream text responses back into standard `tool_use` / `tool_calls` 3. **Noise filtering**: Detects and strips p5.js assistant greetings, headings, and trailing recommendations auto-injected by the upstream 4. **SSE fix-up**: Auto-corrects malformed `ddata:` / `ata:` prefixes to standard `data:` 5. **Caching**: Full-response caching shared between streaming and non-streaming, with in-flight deduplication ### Caveats - The upstream p5js.ai injects a p5.js assistant prompt when no `system` field is present. Passing `system` (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=0` to remove the limit. - This service depends on p5js.ai availability. Upstream changes may affect functionality. ### Acknowledgements - Special thanks to [小辣椒的临时邮箱 (Xiaolajiao Temp Mail)](https://vip.215.im) for registration support ### License MIT License