手把手帮你实现 Xcode 26 具备国产模型开发能力
让你的 Xcode 26 支持阿里云通义千问、MiniMax、智谱 GLM、DeepSeek 等国产大模型,告别 API 兼容性烦恼!
背景
Apple 在 WWDC 2025 发布了 Xcode 26,带来了全新的 AI 编程助手功能。然而,Xcode 默认只支持 Apple Intelligence 和少数几家海外 AI 提供商。当你尝试添加国产模型时,经常会遇到:
-
❌ "Provider is not valid"
-
❌ "Models could not be fetched with the provided account details"
-
❌ API 格式不兼容,无法正常调用
本文将通过一个本地代理服务,帮你突破这些限制,让 Xcode 26 完美支持国产大模型。本文借鉴大佬ShainEli在GitHub开源的代理转发脚本实现,不过做了大调整兼容了阿里云百炼广场模型的使用,适用于公司给开通了百炼平台的无限使用token的用户,这个是借鉴的原始项目
原理简介
Xcode 的 AI 功能遵循 OpenAI API 格式标准。阿里云百炼平台提供了 OpenAI 兼容模式的 API 接口,我们只需搭建一个本地代理服务:
-
接收 Xcode 请求:代理服务监听本地端口(如 3000)
-
模型名称映射:将外部模型名转换为百炼平台实际支持的模型名
-
转发请求:使用统一的
DASHSCOPE_API_KEY调用百炼 API -
返回响应:将百炼的响应原样返回给 Xcode
这样一来,Xcode 认为它在调用标准的 OpenAI API,实际上背后是国产大模型在工作。
本脚本支持的模型
通过本项目,你可以在 Xcode 中使用以下国产模型:
| 模型名称 | 说明 |
|---|---|
qwen3.5-plus | 阿里云通义千问 Plus |
MiniMax-M2.5 | MiniMax 模型 |
glm-5 | 智谱 GLM(通过百炼) |
deepseek-v3.2 | DeepSeek V3 |
提示:所有模型共用同一个
DASHSCOPE_API_KEY,无需分别申请多个 API Key。
准备工作
1. 系统要求
-
macOS 15.0+( Sequoia 或更高版本)
-
Xcode 26(从 Apple Developer 下载)
-
Python 3.8+(macOS 通常自带,或通过 Homebrew 安装)
2. 获取阿里云百炼 API Key
访问 阿里云百炼平台:
-
注册/登录阿里云账号
-
进入百炼控制台
-
点击「API-KEY 管理」
-
创建新的 API Key,复制保存
注意:API Key 是敏感信息,请妥善保管,不要泄露给他人。
3. 安装 Python 依赖
确保你的 Python 版本符合要求:
python --version
# 输出应为 Python 3.8.x 或更高
项目说明
一:项目目录
cd Xcode-AIProxy
最重要的3个文件如下
二:依赖配置文件说明
创建 requirements.txt 文件:
fastapi==0.104.1
uvicorn[standard]==0.24.0
httpx==0.25.2
python-dotenv==1.0.0
python-multipart==0.0.6
pydantic==2.5.0
这些依赖的作用:
-
FastAPI:现代化的 Web 框架,用于构建 API 服务
-
Uvicorn:ASGI 服务器,运行 FastAPI 应用
-
HTTPX:异步 HTTP 客户端,用于调用百炼 API
-
python-dotenv:环境变量管理
-
Pydantic:数据验证和序列化
三:环境变量配置文件说明
# 阿里云百炼 API 密钥
# 获取地址: https://dashscope.aliyuncs.com/
DASHSCOPE_API_KEY=your_dashscope_api_key_here
# 服务器配置
PORT=3000
HOST=0.0.0.0
# 重试配置
MAX_RETRIES=3
RETRY_DELAY=1000
REQUEST_TIMEOUT=60000
编辑 .env 文件,填入你真实的 API Key:
DASHSCOPE_API_KEY=sk-xxxxxxxxxxxxxxxx # 替换为你的真实 Key
四:创建核心代理服务
创建 server_python.py 文件,这是整个项目的核心:
"""
Xcode AI Proxy - Python 版本
使用 FastAPI 的 AI 代理服务,支持阿里云百炼多模型
模型:qwen3.5-plus、MiniMax-M2.5、glm-5、deepseek-v3.2(共用 DASHSCOPE_API_KEY)
"""
import os
import sys
import asyncio
import logging
from datetime import datetime
from typing import Dict, Any, Optional, Union
import json
import httpx
from fastapi import FastAPI, Request, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import StreamingResponse, JSONResponse
from pydantic import BaseModel
from dotenv import load_dotenv
import uvicorn
# 加载环境变量
load_dotenv()
# 配置日志
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[logging.StreamHandler(sys.stdout)]
)
logger = logging.getLogger(__name__)
# 服务器配置
PORT = int(os.getenv('PORT', 3000))
HOST = os.getenv('HOST', '0.0.0.0')
# 重试配置
MAX_RETRIES = int(os.getenv('MAX_RETRIES', 3))
RETRY_DELAY = int(os.getenv('RETRY_DELAY', 1000)) / 1000
REQUEST_TIMEOUT = int(os.getenv('REQUEST_TIMEOUT', 60000)) / 1000
# 检查必需的环境变量
REQUIRED_ENV_VARS = {
'DASHSCOPE_API_KEY': '阿里云百炼多模型 (qwen3.5-plus, MiniMax-M2.5, glm-5, deepseek-v3.2)'
}
for env_var, model_name in REQUIRED_ENV_VARS.items():
if not os.getenv(env_var):
logger.warning(f"⚠️ 缺少环境变量 {env_var} (用于 {model_name}),该模型将不可用")
# API 配置
API_CONFIGS = {}
# 阿里云百炼多模型支持(使用同一个 DASHSCOPE_API_KEY)
DASHSCOPE_API_KEY = os.getenv('DASHSCOPE_API_KEY')
if DASHSCOPE_API_KEY:
# 模型映射:外部请求模型名 -> 实际发送给 API 的模型名
DASHSCOPE_MODEL_MAP = {
'qwen3.5-plus': 'qwen3.5-plus', # 阿里云通义千问 Plus
'MiniMax-M2.5': 'MiniMax-M2.5', # MiniMax 模型
'glm-5': 'glm-5', # 智谱 GLM(通过百炼)
'deepseek-v3.2': 'deepseek-v3.2', # DeepSeek V3
}
for external_model, actual_model in DASHSCOPE_MODEL_MAP.items():
API_CONFIGS[external_model] = {
'api_url': 'https://dashscope.aliyuncs.com/compatible-mode/v1',
'api_key': DASHSCOPE_API_KEY,
'type': 'dashscope',
'name': f'阿里云百炼 {external_model}',
'actual_model': actual_model, # 实际发送给 API 的模型名
}
if not API_CONFIGS:
logger.error("❌ 未配置任何模型API密钥")
sys.exit(1)
logger.info('📋 已加载模型配置:')
for model_id, config in API_CONFIGS.items():
logger.info(f" ✅ {model_id} ({config['name']})")
# FastAPI 应用
app = FastAPI(title="Xcode AI Proxy", version="1.0.1")
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
class ChatCompletionRequest(BaseModel):
model: str
messages: list
stream: bool = False
temperature: Optional[float] = None
max_tokens: Optional[int] = None
top_p: Optional[float] = None
async def with_retry(operation, max_retries=MAX_RETRIES, base_delay=RETRY_DELAY):
"""带重试机制的异步操作"""
last_error = None
for attempt in range(1, max_retries + 1):
try:
logger.info(f"🔄 第{attempt}次尝试")
return await operation()
except Exception as error:
last_error = error
logger.error(f"❌ 第{attempt}次尝试失败: {str(error)}")
if attempt < max_retries:
delay = base_delay * attempt
logger.info(f"⏳ {delay}秒后重试...")
await asyncio.sleep(delay)
logger.error(f"❌ 所有{max_retries}次重试都失败了")
raise last_error
@app.middleware("http")
async def log_requests(request: Request, call_next):
"""请求日志中间件"""
start_time = datetime.now()
logger.info(f"{start_time.isoformat()} - {request.method} {request.url.path}")
response = await call_next(request)
process_time = (datetime.now() - start_time).total_seconds()
logger.info(f"请求处理时间: {process_time:.3f}秒")
return response
@app.get("/health")
async def health_check():
"""健康检查接口"""
return {"status": "ok", "timestamp": datetime.now().isoformat()}
@app.get("/debug/config")
async def debug_config():
"""调试配置接口"""
return {
"available_models": list(API_CONFIGS.keys()),
"config_summary": {
mid: {"name": c["name"], "type": c["type"], "api_url": c["api_url"]}
for mid, c in API_CONFIGS.items()
}
}
@app.get("/v1/models")
async def list_models():
"""模型列表接口(Xcode 会调用此接口验证提供商)"""
model_list = [
{
"id": mid,
"object": "model",
"created": 1677610602,
"owned_by": c["type"],
"name": c.get("name", mid)
}
for mid, c in API_CONFIGS.items()
]
return {"object": "list", "data": model_list}
# ------------------------------
# 阿里云百炼请求处理
# ------------------------------
async def handle_dashscope_request(request_body: dict) -> Union[dict, StreamingResponse]:
"""处理阿里云百炼 API 请求"""
model = request_body.get('model', 'qwen3.5-plus')
config = API_CONFIGS.get(model)
if not config or config['type'] != 'dashscope':
raise HTTPException(status_code=400, detail={"error": {"message": f"不支持的 DashScope 模型: {model}"}})
actual_model = config.get('actual_model', model)
logger.info(f'📡 路由到 阿里云百炼 API,模型: {model} → {actual_model}')
async def make_request():
# 清理空 tools 参数
cleaned = request_body.copy()
if "tools" in cleaned and isinstance(cleaned["tools"], list) and len(cleaned["tools"]) == 0:
logger.info("🧹 阿里云:移除空 tools 参数")
del cleaned["tools"]
# 切换为实际的模型名称
cleaned["model"] = actual_model
async with httpx.AsyncClient(timeout=REQUEST_TIMEOUT) as client:
resp = await client.post(
f"{config['api_url']}/chat/completions",
json=cleaned,
headers={
"Authorization": f"Bearer {config['api_key']}",
"Content-Type": "application/json"
}
)
if resp.status_code >= 400:
logger.error(f"🔴 阿里云错误返回: {resp.text}")
resp.raise_for_status()
return resp
resp = await with_retry(make_request)
logger.info(f'✅ 阿里云 API 响应状态: {resp.status_code}')
# 处理流式响应
if request_body.get('stream', False):
logger.info('🔄 返回流式响应')
headers = dict(resp.headers)
headers.pop('content-length', None)
headers.pop('content-encoding', None)
async def gen():
async for chunk in resp.aiter_bytes(chunk_size=8192):
yield chunk
return StreamingResponse(gen(), status_code=resp.status_code, headers=headers)
else:
logger.info('📦 返回非流式响应')
return resp.json()
# ------------------------------
# 代理分发
# ------------------------------
async def handle_proxy(request_data: dict):
"""请求分发处理"""
model = request_data.get('model')
logger.info(f'🎯 请求模型: {model}')
if not model or model not in API_CONFIGS:
raise HTTPException(status_code=400, detail={"error": {"message": f"不支持模型: {model},支持的模型: {list(API_CONFIGS.keys())}"}})
cfg = API_CONFIGS[model]
if cfg['type'] == 'dashscope':
return await handle_dashscope_request(request_data)
else:
raise HTTPException(status_code=500, detail={"error": {"message": f"未知类型: {cfg['type']}"}})
@app.post("/v1/chat/completions")
async def chat_completions(request: Request):
"""聊天补全接口(核心 API)"""
try:
body = await request.json()
if 'model' not in body or 'messages' not in body:
raise HTTPException(status_code=400, detail={"error": {"message": "缺少 model 或 messages"}})
return await handle_proxy(body)
except json.JSONDecodeError:
raise HTTPException(status_code=400, detail={"error": {"message": "无效 JSON"}})
@app.post("/api/v1/chat/completions")
async def api_chat_completions(request: Request):
"""备用聊天补全接口"""
body = await request.json()
return await handle_proxy(body)
@app.post("/v1/messages")
async def messages(request: Request):
"""消息接口(兼容 Claude API 格式)"""
body = await request.json()
return await handle_proxy(body)
def main():
"""服务启动入口"""
logger.info('🚀 Xcode AI Proxy 启动')
logger.info(f'📡 监听: http://{HOST}:{PORT}')
for m, c in API_CONFIGS.items():
logger.info(f" ✅ {m} → {c['name']}")
uvicorn.run("server_python:app", host=HOST, port=PORT, reload=False)
if __name__ == "__main__":
main()
启动代理服务
# 安装依赖
pip install -r requirements.txt
# 启动服务
python server_python.py
验证服务运行
服务启动后,你应该看到类似输出:
配置 Xcode 26
步骤一:打开 Xcode 设置
-
启动 Xcode 26
-
菜单栏选择 Xcode > Settings(或按
⌘,) -
找到Intelligence 设置页面
步骤二:点击添加模型提供商,按下图配置
第一步:Internet Hosted(互联网托管)
-
点击「Add External Provider」或「+」按钮
-
选择「Internet Hosted」类型
-
填写以下信息:
- Base URL: http://localhost:3000
- API Key: any-string-works(任意字符串即可,代理服务不验证)
- 点击「Connect」或「Verify」
第二步:Locally Hosted(本地托管)
-
选择「Locally Hosted」类型
-
填写以下信息:
- Port: 3000
- 点击「Add」或「Verify」
步骤三:选择模型
配置成功后,Xcode 会显示可用模型列表:
-
qwen3.5-plus -
MiniMax-M2.5 -
glm-5 -
deepseek-v3.2
选择你想要使用的模型,Xcode 会自动验证连接。
步骤四:开始使用
现在你可以在 Xcode 中使用 AI 功能了:
-
代码补全:编写代码时,AI 会给出智能建议
-
代码解释:选中代码片段,请求 AI 解释
-
代码生成:描述需求,AI 生成代码
-
错误修复:遇到错误时,AI 提供修复建议
通过本文的步骤,你已经成功让 Xcode 26 支持国产大模型。核心要点:
-
代理原理:本地服务充当 Xcode 和百炼 API 之间的桥梁
-
统一 Key:一个
DASHSCOPE_API_KEY支持四种模型 -
模型映射:外部模型名与实际 API 模型名的转换
-
OpenAI 兼容:百炼的兼容模式让一切变得简单
现在,你可以用国产大模型在 Xcode 中愉快地编程了!
项目文件结构
最终的项目结构如下:
xcode-ai-proxy/
├── server_python.py # 核心代理服务
├── requirements.txt # Python 依赖
├── .env # 环境变量配置(填入真实 API Key)
├── .env.example # 环境变量模板
├── start_python.sh # 启动脚本
└── README.md # 项目说明
参考资料
如果你在实践过程中遇到任何问题,欢迎在评论区留言讨论!