uni2 / README.md
Spooker's picture
Upload 10 files
abb6d23 verified
metadata
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 能力。

架构:

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=fixedcookie 使用;也可手动指定固定会话 ID
LOG_LEVEL 默认 INFO,可设 DEBUG

你如果不设置 PROXY_API_KEY,默认 key 是 sk-change-me。公开 Space 一定要改。

Chat ID 复用说明

这版修复了原始示例里每次请求都随机生成 chatId 的问题。默认:

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

如果客户端支持额外参数,也可以显式固定某个会话:

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 地址:

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 示例

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

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 测试

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

然后访问:

http://localhost:7860/v1/models

调用时加 header:

Authorization: Bearer test-key

注意

  • 这里的 tool calling 是 Toolify 通过提示词和解析实现的“兼容层”,不是 UnlimitedAI 官方原生工具调用。
  • 模型有概率不按格式输出;本项目已启用 Toolify 的函数调用解析失败重试,但仍不能保证 100%。
  • 不要把 Cookie 提交到仓库;只放到 Hugging Face Secrets。
  • 建议把 Space 设置为 Private。
  • 本包包含 Toolify 源码,遵循其 GPL-3.0-or-later 许可证。