【声明】本博客所有内容均为个人业余时间创作,所述技术案例均来自公开开源项目(如Github,Apache基金会),不涉及任何企业机密或未公开技术,如有侵权请联系删除
背景
上篇 blog
【Agent】【OpenCode】本地代理(脚本实现)
分析提到了代理的位置决定协议的类型,比如如果选择的是本地代理,则可以用 HTTP 协议进行代理,这意味着 OpenCode 和本地代理之间用的是 HTTP 明文,虽然最终本地代理到 DashScope 是 HTTPS(加密),但至少 OpenCode 到本地代理这一段是明文,而如果是远程代理,可以使用 HTTPS 代理,代理需要持有 HTTPS 证书私钥,得先解密请求,处理后再加密发给 DashScope,比较麻烦,最后给出了一版本地代理的脚本,下面继续分析
OpenCode
上篇 blog 分析到了这里选择 JavaScirpt 脚本是基于开发效率,生态适配和使用场景的综合考虑,下面详细分析下其中原因
- JavaScript 与前端,IDE 插件生态天然契合:VSCode 本身就是用 Electron(JavaScript/TypeScript)构建的,很多 AI 插件的开发者都很熟悉 JS/TS,比如用户如果已经在写 VSCode 插件,那么顺手写个配套代理也是非常自然的
- JSON 处理极其简单 :AI 的 API 请求和响应全是 JSON,而 JavaScript 的
JSON.parse(),JSON.stringify()是原生支持 JSON 解析,代码极简,比如在 Node.js 的代理中修改请求体,只需要 3 行就能搞定
javascript
const body = JSON.parse(rawBody);
body.model = 'qwen-plus';
const newBody = JSON.stringify(body);
注意,这里有个细节,前两行已经完成了修改 request body 的逻辑,body 这个 JavaScript 对象到这里已经是改好的状态,但是 HTTP 请求的 body 必须是字符串(或 Buffer),不能直接发送 JS 对象,所以第三行这里需要先把 JSON 对象先转成字符串,才能发送 HTTP 请求,举个例子,假设 OpenCode 发来
javascript
{ "model": "gpt-3.5-turbo", "messages": [...] }
代码执行的时候,变量转换如下
| 步骤 | 变量 | 值 |
|---|---|---|
| rawBody | 字符串 | '{"model":"gpt-3.5-turbo",...}' |
| body | JS 对象 | { model: "qwen-plus", messages: [...] } |
| newBody | 字符串 | '{"model":"qwen-plus",...}' |
只有 newBody 才能作为合法的 HTTP body 发送给 DashScope,其实也可以省略变量名,直接使用 JSON.stringify(body),无需存到 newBody,这样写成两行即可
javascript
let body = JSON.parse(rawBody);
body.model = 'qwen-plus';
proxyReq.write(JSON.stringify(body));
OK,继续分析本地代理使用 JavaScript 的好处
- 异步 IO 高效处理流式响应 :大模型 API 通常支持流式输出(streaming),而 Node.js 的
stream和pip()可以轻松透传流数据,这些虽然 Go 和 Python 也能做,但 Node.js 在这类 IO 密集型任务上启动快,内存轻 - 零依赖快速启动 :一个 20 行的 Proxy.js 脚本不需要编译,只需要
node proxy.js,无外部依赖(用内置的http/https模块),对比其他语言
| 编程语言 | 依赖表现 |
|---|---|
| Go | 需要编译,生成单文件执行 |
| Python | 需确保环境有 requests 等库 |
| Rust | 编译慢,适合高性能场景 |
对于临时调试,快速原型,JS 是最轻量的选择
上面介绍了本地代理使用 JavaScript 的优势,下面再介绍一些不适合用 JavaScript 的场景
| 场景 | 推荐语言 | 原因 |
|---|---|---|
| 高并发生产环境 | Go,Rust | Node.js 单线程,CPU 密集型任务会发生阻塞 |
| 资源受限设备(比如树莓派) | C,Rust | Node.js 内存炸弄较高(~50MB+) |
| 需要复杂计算(比如 token 统计,加密等) | Python,Rust | JS 数值,科学计算生态弱 |
| 企业级部署(比如监控,日志,熔断等场景) | Java,Go | Spring Cloud 等微服务框架成熟 |
可以看到,所有主流语言都能实现本地代理,选择取决于开发者的熟悉度和需求,没有最好的语言,只有最合适当前场景的工具,如果更熟悉 Python,就用 Python,如果追求极致性能,就用 Go,Rust,如果只是临时调试,JS 是最轻量的选择
OK,本篇先到这里,如有疑问,欢迎评论区留言讨论,祝各位功力大涨,技术更上一层楼!!!更多内容见下篇 blog