加密、Tor 与 I2P 端点
该 API 也以 Tor onion 服务和 I2P eepsite 的形式发布。路由相同,密钥相同;只有基础 URL 和代理不同。
基础 URL
有四个地址通向同一个 API。请使用适合你网络的那个,API 密钥和请求都相同。
| 网络 | 基础 URL | 访问方式 |
|---|---|---|
| 明网 | https://api.shannon-ai.com/v1 | 直接访问,通过 HTTPS。 |
| 加密镜像 | https://api-encrypted.shannon-ai.com/v1 | 直接访问,通过 HTTPS。同一个 API 的第二个主机名。 |
| Tor(onion 服务) | http://shannonmd773o5vxz75byha5rkea7nzr3srotw46uwythq3pjl6y4cad.onion/v1 | 通过 Tor 客户端:SOCKS5 代理,默认位于 127.0.0.1:9050。 |
| I2P(eepsite) | http://acvnvkdea4xaczzjap7chysqqi4kkvp2eorfwkasindzmjpa47da.b32.i2p/v1 | 通过 I2P 路由器:HTTP 代理,默认位于 127.0.0.1:4444。 |
- OpenAI SDK 按所示使用基础 URL,带
/v1。Anthropic SDK 使用不带/v1的基础 URL。 - 要核对地址,请读取
https://api.shannon-ai.com的回复标头:Onion-Location带有 onion 地址,X-I2P-Location带有 I2P 地址。onion 地址以shannon开头。
哪些路由可用
每个 /v1 路由在四个地址上都能响应:
POST /v1/chat/completionsPOST /v1/responsesPOST /v1/messagesPOST /v1/messages/count_tokensPOST /v1/tokenizeGET /v1/models
GET /v1/models 不需要密钥,因此可以用来快速测试你的代理能否访问 API。
哪些相同,哪些不同
| 项目 | 是否相同? | 详情 |
|---|---|---|
| 路由、请求字段、回复、错误 | 相同 | 在每个地址上都相同。没有任何路由会因主机名不同而表现不同。 |
| API 密钥 | 相同 | 一个密钥在每个地址上都有效,可作为 Authorization: Bearer 或 x-api-key 发送。/v1 上从不读取 Cookie。 |
| 余额与限额 | 相同 | 余额相同,每分钟 120 个请求的限额也相同。两者都按账户计,而不是按地址计。 |
| 请求大小 | 相同 | 每个请求体最大 32 MiB。 |
| 协议 | 不同 | 明网和镜像使用 https://。.onion 和 .b32.i2p 地址使用 http://,因为网络本身会对连接进行端到端加密。 |
| 代理 | 不同 | 明网无需代理。Tor 使用 SOCKS5 代理,I2P 使用 HTTP 代理。域名必须由代理解析,而不是由你的机器解析。 |
| 速度 | 不同 | 两个网络都会给每个字节增加延迟。I2P 是其中较慢的一个。 |
余额与限额在专门的页面中说明。 限制与余额
通过 Tor 使用 cURL
在你的机器上运行 Tor 客户端。它在 127.0.0.1:9050 上提供 SOCKS5 代理。--socks5-hostname 会把 .onion 域名交给该代理。
cURL · Tor
# 1. Is the onion service reachable? No key needed.
curl --socks5-hostname 127.0.0.1:9050 http://shannonmd773o5vxz75byha5rkea7nzr3srotw46uwythq3pjl6y4cad.onion/v1/models
# 2. A streamed chat call. -N prints the stream as it arrives.
curl -N --socks5-hostname 127.0.0.1:9050 http://shannonmd773o5vxz75byha5rkea7nzr3srotw46uwythq3pjl6y4cad.onion/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "shannon-3",
"stream": true,
"messages": [{"role": "user", "content": "Hello over Tor"}]
}' 通过 I2P 使用 cURL
在你的机器上运行 I2P 路由器。它在 127.0.0.1:4444 上提供 HTTP 代理,该代理会原样接受 .b32.i2p 域名。
cURL · I2P
# 1. Is the eepsite reachable? No key needed.
curl --proxy http://127.0.0.1:4444 http://acvnvkdea4xaczzjap7chysqqi4kkvp2eorfwkasindzmjpa47da.b32.i2p/v1/models
# 2. A streamed chat call.
curl -N --proxy http://127.0.0.1:4444 http://acvnvkdea4xaczzjap7chysqqi4kkvp2eorfwkasindzmjpa47da.b32.i2p/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "shannon-3",
"stream": true,
"messages": [{"role": "user", "content": "Hello over I2P"}]
}' SDK 基础 URL
SDK 需要两处改动:该网络的基础 URL,以及一个经由代理的 HTTP 客户端。在 Python 中,两个官方 SDK 都接受 httpx 客户端。对于 SOCKS 代理,请安装 httpx[socks]。
# pip install openai "httpx[socks]"
import httpx
from openai import OpenAI
client = OpenAI(
api_key="YOUR_API_KEY",
base_url="http://shannonmd773o5vxz75byha5rkea7nzr3srotw46uwythq3pjl6y4cad.onion/v1",
http_client=httpx.Client(proxy="socks5h://127.0.0.1:9050", timeout=600),
)
stream = client.chat.completions.create(
model="shannon-3",
messages=[{"role": "user", "content": "Hello over Tor"}],
stream=True,
)
for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True) # pip install openai
import httpx
from openai import OpenAI
client = OpenAI(
api_key="YOUR_API_KEY",
base_url="http://acvnvkdea4xaczzjap7chysqqi4kkvp2eorfwkasindzmjpa47da.b32.i2p/v1",
http_client=httpx.Client(proxy="http://127.0.0.1:4444", timeout=600),
)
stream = client.chat.completions.create(
model="shannon-3",
messages=[{"role": "user", "content": "Hello over I2P"}],
stream=True,
)
for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True) # pip install anthropic "httpx[socks]"
import anthropic
import httpx
client = anthropic.Anthropic(
api_key="YOUR_API_KEY",
base_url="http://shannonmd773o5vxz75byha5rkea7nzr3srotw46uwythq3pjl6y4cad.onion",
http_client=httpx.Client(proxy="socks5h://127.0.0.1:9050", timeout=600),
)
with client.messages.stream(
model="shannon-1.6-lite",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello over Tor"}],
) as stream:
for text in stream.text_stream:
print(text, end="", flush=True) 慢速链路上的流式传输与保活
两个网络上都可以使用流式传输。当流已打开而模型暂无内容可发送时,API 会发送保活信号,这样代理或你的客户端就不会认为连接已断开。
| 端点 | 打开的流上的保活 | 适用于 |
|---|---|---|
/v1/chat/completions | 每 15 秒一行注释(以 : 开头)。 | 所有模型 |
/v1/messages | 每 15 秒一个 event: ping 或一行注释。 | 所有模型 |
/v1/responses | 每 15 秒一行注释。 | 托管开源权重模型 |
- 发送
"stream": true。流式回复在模型写出内容的同时就开始到达,保活信号表明请求仍在处理中。非流式回复要等整个答案准备好才会发送任何内容。 - 给客户端设置较长的读取超时。示例使用 600 秒。短于 15 秒的超时可能会在两次保活之间中断流。
- 让你的 SSE 读取器跳过注释行和
ping事件。各 SDK 已经这样做了。 - 不要在连接一断开时就立刻重发请求。已到达 API 的请求会运行到结束并被计费,即使连接已经消失。
- 请先用
GET /v1/models测试这条路径。它不需要密钥,返回一个简短的 JSON 列表。
连接问题
| 症状 | 原因与解决办法 |
|---|---|
到 127.0.0.1:9050 或 127.0.0.1:4444 的连接被拒绝 | 你的机器上没有运行 Tor 客户端或 I2P 路由器,或者它监听的是另一个端口。Tor Browser 的 SOCKS 代理在 9150 端口上。 |
.onion 域名出现 Could not resolve host | 客户端试图自己解析域名。请在 cURL 中使用 --socks5-hostname,在代理 URL 中使用 socks5h://,让 Tor 客户端来解析。 |
| I2P 代理返回它自己的错误页面 | 路由器尚未找到该地址。路由器启动后需要几分钟。请再试一次。 |
401,消息为 Missing authentication | 请求到达时没有带密钥。请发送与明网相同的标头。 |
其他所有错误都与明网相同。 错误处理
无需 JavaScript 获取密钥
Shannon 还有一个无需 JavaScript 的网站,可通过明网、onion 服务和 eepsite 访问。它的 /keys 页面会显示你的 API 密钥并允许你轮换,因此你无需离开 Tor 或 I2P 就能获得密钥。 encrypted.shannon-ai.com/keys
该网站在三个网络上的地址列在这里: 加密访问