p5jsai-api / README.md
li2895's picture
Add Hugging Face Spaces metadata
c24475f
|
Raw
History Blame Contribute Delete
18.2 kB
---
title: p5jsAi API
emoji: ๐Ÿš€
colorFrom: blue
colorTo: purple
sdk: docker
pinned: false
---
# p5js.ai 2 API
[English](#english) | [ไธญๆ–‡](#ไธญๆ–‡)
---
<a id="ไธญๆ–‡"></a>
## 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 ๆ ผๅผ็š„ `<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
```
### ๅฟซ้€Ÿๅผ€ๅง‹
#### ๆœฌๅœฐ่ฟ่กŒ
```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 ๆ ผๅผ๏ผŒๅฐ†ไธŠๆธธๆ–‡ๆœฌๅ“ๅบ”ไธญ็š„ `<function_calls>` 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
---
<a id="english"></a>
## 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 `<function_calls>` 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 `<function_calls>` 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