解决Grok API无法在部分服务器的IP中调用的情况,尤其是用腾讯云海外服务器玩酒馆

之前我部署了@snaily 大佬的Gemini轮询工具,好用又好看,爽玩酒馆。
唯一的问题是Gemini的响应速度慢的不行。
裤子都脱了,下一段剧情要等1分钟……

于是我盯上了号称速度最快的grok。
我申请了Grok的API,某宝上买了一张5刀卡通过验证,然后给了150刀每月的额度。
实际使用的时候发现,我在酒馆中填写了https://api.x.ai/v1,结果无法调用。

具体表现是:点击连接后,可用模型无法加载,点击发送测试消息报错,在对话页面也无法使用

翻遍了全网的教程,终于找到原因:我的服务器是腾讯云的海外服务器,Grok拒绝所有腾讯云和阿里云的公网IP(该信息来自SillyTavern贴吧)。
根据服务器返回的命令,我向Grok确认了这一问题,天塌了。

于是根据 @snaily 大佬的启发——我能否在hugging face中创建一个space来转发我的api请求呢?于是在Gork和Deepseek的协助下,完美解决了这个问题。

操作步骤如下:

1,打开Hugging Face并登录。

2,点击右上角三条横线,选 “New Space”

3,如图填写:


记住你的owner和sapce name,后面会用到
填写完成后点击 Catere Space创建

4,在新的页面中点击files

5,点击+ Contribute ,Upload files

6,这里需要上传两个文件:requirements.txtapp.py
你可以在桌面新建这两个文件,代码分别为:
requirements.txt

fastapi==0.115.0
uvicorn==0.30.6
requests==2.32.3
pydantic==2.9.2
python-multipart

app.py

from fastapi import FastAPI, HTTPException, Request, status
from fastapi.responses import StreamingResponse
from pydantic import BaseModel, Field
import requests
from requests.exceptions import RequestException
import os
import logging
import json

# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

app = FastAPI()
XAI_API_BASE = "https://api.x.ai/v1"

class ChatRequest(BaseModel):
    messages: list[dict] = Field(..., description="消息列表")
    model: str = Field(..., description="模型ID")
    max_tokens: int | None = None
    temperature: float | None = None
    top_p: float | None = None
    stream: bool = False
    presence_penalty: float | None = None
    frequency_penalty: float | None = None

async def stream_generator(response, stream):
    try:
        for chunk in response.iter_lines():
            if chunk:
                decoded_chunk = chunk.decode('utf-8')
                if decoded_chunk.startswith("data: "):
                    yield f"data: {decoded_chunk[6:]}\n\n"
                else:
                    yield f"data: {json.dumps({'error': 'Invalid chunk format'})}\n\n"
    except RequestException as e:
        yield f"data: {json.dumps({'error': str(e)})}\n\n"
    finally:
        if stream:
            response.close()

@app.post("/v1/chat/completions")
async def chat_completions(req: ChatRequest, request: Request):
    logger.info(f"收到请求: {req.dict()}")
    api_key = request.headers.get("Authorization", "").replace("Bearer ", "")
    
    if not api_key:
        logger.error("缺少API密钥")
        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="缺少API密钥")

    try:
        headers = {
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json",
            "User-Agent": "SillyTavern-Proxy/1.0",
            "Accept": "text/event-stream" if req.stream else "application/json"
        }

        payload = req.dict(exclude_unset=True)
        filtered_payload = {k: v for k, v in payload.items() if k in ["messages", "model", "max_tokens", "temperature", "top_p", "stream"]}

        logger.info(f"转发到xAI的负载: {filtered_payload}")
        
        response = requests.post(
            f"{XAI_API_BASE}/chat/completions",
            headers=headers,
            json=filtered_payload,
            stream=req.stream,
            timeout=20
        )
        response.raise_for_status()

        if req.stream:
            return StreamingResponse(
                stream_generator(response, req.stream),
                media_type="text/event-stream"
            )
        else:
            try:
                return response.json()
            except json.JSONDecodeError:
                logger.error(f"无效的JSON响应: {response.text}")
                raise HTTPException(status_code=502, detail="上游服务器返回无效响应")

    except RequestException as e:
        error_detail = ""
        if e.response is not None:
            try:
                error_detail = e.response.json().get("error", e.response.text)
            except json.JSONDecodeError:
                error_detail = e.response.text[:500]
            status_code = e.response.status_code
        else:
            error_detail = str(e)
            status_code = 504

        logger.error(f"请求失败: {error_detail}")
        raise HTTPException(
            status_code=status_code,
            detail=f"xAI API错误: {error_detail}"
        )

# 保持原来的模型列表端点
@app.get("/v1/models")
async def get_models(request: Request):
    api_key = request.headers.get("Authorization", "").replace("Bearer ", "")
    if not api_key:
        raise HTTPException(status_code=401, detail="缺少API密钥")
    
    try:
        headers = {
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json"
        }
        response = requests.get(f"{XAI_API_BASE}/models", headers=headers, timeout=10)
        response.raise_for_status()
        return response.json()
    except RequestException as e:
        logger.warning(f"获取模型失败: {str(e)},返回备用数据")
        return {
            "object": "list",
            "data": [
                {"id": "grok-3-beta", "object": "model", "created": 1744681729, "owned_by": "xAI"},
                {"id": "grok-3-mini-beta", "object": "model", "created": 1744681729, "owned_by": "xAI"},
                {"id": "grok-3-fast-beta", "object": "model", "created": 1744681729, "owned_by": "xAI"},
                {"id": "grok-3-mini-fast-beta", "object": "model", "created": 1744681729, "owned_by": "xAI"},
            ]
        }

@app.get("/health")
async def health_check():
    return {"status": "healthy"}

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=7860)

然后将文件拖动上传,其他选项不动,点击Commit changes to main。

7,然后等待部署完成,可点击页面中的 APP按钮查看。
日志中显示以下内容就成功了。


(后面那个404 Not Found不影响使用)

8,可以使用cherry studio测试一下。

9,现在我们回到酒馆中添加,打开API设置页面

10,测试

太快了,我只能说太快了。
使用gemini的时候,差不多的输出内容要等60秒左右,并且流式传输还总是出问题,这个快得不得了,真实体感的话,差不多10秒不到吧,就开始蹭蹭蹭蹭蹭蹭蹭的蹦字啊

11,酒馆,启动

第一次发解决问题的分享,可能部分地方格式不对,请各位佬多多包涵~

另外!求推荐Grok3好用的破限!

14 Likes

佬友太强了,这就酒馆启动! :tieba_087:

佬,你才是我的恩人呐 :face_blowing_a_kiss:

2 Likes

老板,酒馆是什么?有链接吗?看起来有点好玩啊

嗯,我也是 New Api 部署在腾讯云海外服务器,不过我发现失败后直接猜出来它肯定屏蔽 ip 了,好在我还有其它 vps,直接就搞了反代解决了

佬,搞反代是不是更简单一点

更详细的你得问樱佬

@wwow

1 Like

反代非常简单,有一个 nginx 就行了,可以用多个路径转发不同的 AI 服务

太强了,大佬!

太厉害了

学习,但先不启动(

很好啊,刚刚在类脑看到佬了 :face_blowing_a_kiss:

Warp IP 屏蔽了吗?没屏蔽的话套个 Warp 不就好了吗。

搞个oneapi或者用cf的ai gate试试

很好的教程,记得system message要设置, 不然报错 An empty user message was provided., 还有运行后,把app.py中的日志可以去掉

酒馆是啥。

感谢佬,grok 本地调试怎么都不通。按照这个做个中转就可以了

重新传一遍可以用了