--- 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 许可证。