背景
看到apple发布了新版的xcode,并且自带ai功能,楼主兴致冲冲的第一时间就先更新了电脑又更新了xcode,搞了大半天终于完事,打开新版xcode打算尝鲜, 发现ai的设置里,已经自动支持claude了,只需要注册登录就好,因为claude 不支持国内注册,楼主费了一番功夫,还花费了几十大洋找了个接码平台,注册成功登录成功,然后绑定xcode时候,显示:“非会员用户不可用” em。。。 然后不死心的我又绑定了openai的apikey,然后结果仍然是开会员才可以用。
。。。好吧 经过一番搜索,好像这种api的接入方式,除非本地部署大模型,那么都是需要收费的,主要是楼主本人开发的需求量平时并不多,开claude 和 openai的会员肯定是不划算的,而本地部署我的16g的电脑显而易见也不太行,权衡之下我就想着接入deepseek,毕竟deepseek是按量计费的,对于大众来说还是比较划算的。
但是随后又遇到了另一个坑,填入deepseek的apikey,还充值了十块钱,结果在xcode使用时候频繁报错,发现原因应该是 xcode内置的大模型请求参数上 没有兼容deepseek的要求。
主要有两大坑
1.Invalid 'tools': empty array. Expected an array with minimum length 1, but got an empty array instead.
deepseek要求tools里不能为空,但是xcode默认会传一个 tools:[] 的字段
2.Failed to deserialize the JSON body into the target type: messages[8]: invalid type: sequence, expected a string at line 1 column 6236
deepseek需要的其中的content字段是一个字符串类型,而xcode自带ai的请求传参是一个数组
本来楼主想着,既然参数的问题那么用charles 拦截请求参数 rewrite 参数就可以么。经过一番尝试 1 的问题把tools:[]替换成"tools":[{"type":"function","function"{"name":"noop","description":"no-op placeholder","parameters":{"type":"object","properties":{},"additionalProperties":false}}}] 是可以解决的
但是2就不行,因为xcode在ai请求传参时候,为了兼容上下文,会有多个content,而charles 只能更改单一的参数,无法批量遍历做修改处理,一番周折最终openai 给出了一个解决方案,亲测有效~
1.用Node.js开启一个本地的服务,做上面1和2的处理
1)建一个名为deepseek-proxy.js 的文件
const bodyParser = require('body-parser');
const fetch = require('node-fetch');
const https = require('https');
const app = express();
app.use(bodyParser.json({ limit: '10mb' }));
const httpsAgent = new https.Agent({ rejectUnauthorized: false });
function flattenMessages(messages) {
if (!Array.isArray(messages)) return '';
return messages.map(msg => {
if (typeof msg === 'string') return msg;
if (msg.text) return msg.text;
if (Array.isArray(msg.content)) return flattenMessages(msg.content);
return '';
}).join('\n');
}
app.post('/v1/chat/completions', async (req, res) => {
try {
const body = { ...req.body };
if (body.messages && Array.isArray(body.messages)) {
body.messages = [{
role: 'user',
content: flattenMessages(body.messages)
}];
}
body.tools = [{
type: 'function',
function: {
name: 'noop',
description: 'no-op placeholder',
parameters: { type: 'object', properties: {}, additionalProperties: false }
}
}];
// 打印最终请求 body
console.log('Forwarding request body to DeepSeek:\n', JSON.stringify(body, null, 2));
const response = await fetch('https://api.deepseek.com/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': req.headers['authorization'] || ''
},
body: JSON.stringify(body),
agent: httpsAgent
});
// 打印响应 status 和 headers
console.log('Response status:', response.status);
console.log('Response headers:', JSON.stringify([...response.headers.entries()], null, 2));
const text = await response.text(); // 先拿文本
try {
const data = JSON.parse(text); // 再尝试解析
res.status(response.status).json(data);
} catch (err) {
console.error('Non-JSON response from DeepSeek:', text);
res.status(response.status).send(text);
}
} catch (error) {
console.error(error);
res.status(500).json({ error: error.message });
}
});
app.listen(3000, () => {
console.log('Local DeepSeek proxy running on http://localhost:3000');
});
2)打开终端
下载依赖
npm install express@4 body-parser@1 node-fetch@2
启动代理
node deepseek-proxy.js
2.开启charles ,菜单栏 Tools -> Map Remote,将目标接口api.deepseek.com/v1/chat/com… 映射到本地的代理服务器http://localhost:3000/v1/chat/completions ,然后通过本地服务的处理tools为空和遍历content转为字符串的问题后去请求deepseek
流程图:
Xcode 内置 AI 请求
│
▼
Charles 抓包 + Map Remote
│
▼
本地 Node.js 代理 (自动content处理 + tools替换)
│
▼
DeepSeek API 返回响应
如图已经可以正常问答,至于效果好不好,还没具体用多少,不过初步感觉有点卡 害