uni2 / README.md
Spooker's picture
Upload 10 files
abb6d23 verified
---
title: UnlimitedAI ToolCall Proxy
emoji: 🛠️
colorFrom: blue
colorTo: purple
sdk: docker
app_port: 7860
pinned: false
---
# UnlimitedAI ToolCall Proxy for Hugging Face Spaces
这个 Space 对外提供 OpenAI 兼容接口,并通过 Toolify 给不原生支持函数调用的上游模型模拟 `tools` / `tool_calls` 能力。
架构:
```text
OpenAI SDK / Cherry Studio / 你的应用
↓ /v1/chat/completions, tools
Toolify, port 7860,对外暴露
↓ 内部 OpenAI 兼容请求
UnlimitedAI upstream proxy, 127.0.0.1:9000
https://app.unlimitedai.chat/api/chat
```
## 上传到 Hugging Face
1. 新建 Hugging Face Space,SDK 选择 **Docker**
2. 上传本项目全部文件。
3. 在 Space 的 **Settings → Secrets** 添加:
| Secret | 必填 | 说明 |
| --- | --- | --- |
| `UAI_COOKIES` | 是 | 浏览器 Network 里 `/api/chat` 请求的完整 Cookie,不要带 `cookie:` 前缀 |
| `UAI_DEVICE_ID` | 是 | Cookie 里的 `u_device_id` 值 |
| `PROXY_API_KEY` | 强烈建议 | 客户端调用这个代理时使用的 API Key |
| `DEFAULT_MODEL` | 否 | 默认 `chat-model-reasoning` |
| `ALLOWED_MODELS` | 否 | 逗号分隔,例如 `chat-model-reasoning,my-model` |
| `UAI_LOCALE` | 否 | 默认 `zh` |
| `TARGET_API` | 否 | 默认 `https://app.unlimitedai.chat/api/chat` |
| `CHAT_ID_STRATEGY` | 否 | 默认 `stable`,让同一段 OpenAI 历史消息复用同一个 UnlimitedAI `chatId` |
| `UAI_CHAT_ID` | 否 | 配合 `CHAT_ID_STRATEGY=fixed``cookie` 使用;也可手动指定固定会话 ID |
| `LOG_LEVEL` | 否 | 默认 `INFO`,可设 `DEBUG` |
> 你如果不设置 `PROXY_API_KEY`,默认 key 是 `sk-change-me`。公开 Space 一定要改。
## Chat ID 复用说明
这版修复了原始示例里每次请求都随机生成 `chatId` 的问题。默认:
```text
CHAT_ID_STRATEGY=stable
```
网关会根据 OpenAI 消息历史里的第一条 `user` 消息生成稳定 UUID,所以第一次工具调用请求和后续带 `role=tool` 结果的请求会复用同一个 UnlimitedAI 上游会话。
可选策略:
| 值 | 行为 |
| --- | --- |
| `stable` | 默认;根据第一条用户消息稳定生成 `chatId`,推荐用于 tool calling |
| `cookie` | 优先使用 Cookie 里的 `home_chat_id`,没有则回退到 `stable` |
| `fixed` / `static` | 固定使用 `UAI_CHAT_ID`,所有请求共享一个上游会话 |
| `random` | 老行为;每次请求生成新的上游会话,不推荐 tool calling |
如果客户端支持额外参数,也可以显式固定某个会话:
```python
resp = client.chat.completions.create(
model="chat-model-reasoning",
messages=[{"role": "user", "content": "查一下上海天气"}],
tools=tools,
tool_choice="auto",
extra_body={"chat_id": "my-weather-session-001"},
)
```
显式 `chat_id` 会被转换成稳定 UUID,优先级高于 `CHAT_ID_STRATEGY`
## OpenAI SDK 调用
把 base_url 改成你的 Space 地址:
```python
from openai import OpenAI
client = OpenAI(
base_url="https://YOUR-SPACE.hf.space/v1",
api_key="你的 PROXY_API_KEY",
)
resp = client.chat.completions.create(
model="chat-model-reasoning",
messages=[{"role": "user", "content": "你好"}],
)
print(resp.choices[0].message.content)
```
## Tool Call 示例
```python
from openai import OpenAI
client = OpenAI(
base_url="https://YOUR-SPACE.hf.space/v1",
api_key="你的 PROXY_API_KEY",
)
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "获取城市天气",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "城市名"}
},
"required": ["city"]
}
}
}
]
resp = client.chat.completions.create(
model="chat-model-reasoning",
messages=[{"role": "user", "content": "查一下上海天气"}],
tools=tools,
tool_choice="auto",
)
msg = resp.choices[0].message
print(msg.tool_calls)
```
如果返回了 `tool_calls`,你的客户端需要执行对应函数,然后把结果作为 `role='tool'` 消息继续发回模型。这和标准 OpenAI tool calling 流程一致。
## 流式 Tool Call
```python
stream = client.chat.completions.create(
model="chat-model-reasoning",
messages=[{"role": "user", "content": "查一下北京天气"}],
tools=tools,
tool_choice="auto",
stream=True,
)
for chunk in stream:
print(chunk)
```
## 本地 Docker 测试
```bash
docker build -t uai-toolcall-proxy .
docker run --rm -p 7860:7860 \
-e UAI_COOKIES='你的完整 Cookie' \
-e UAI_DEVICE_ID='你的 device id' \
-e PROXY_API_KEY='test-key' \
uai-toolcall-proxy
```
然后访问:
```text
http://localhost:7860/v1/models
```
调用时加 header:
```text
Authorization: Bearer test-key
```
## 注意
- 这里的 tool calling 是 Toolify 通过提示词和解析实现的“兼容层”,不是 UnlimitedAI 官方原生工具调用。
- 模型有概率不按格式输出;本项目已启用 Toolify 的函数调用解析失败重试,但仍不能保证 100%。
- 不要把 Cookie 提交到仓库;只放到 Hugging Face Secrets。
- 建议把 Space 设置为 Private。
- 本包包含 Toolify 源码,遵循其 GPL-3.0-or-later 许可证。