2025-06-22 19:43:02
最近在尝试各类 agent 项目,大部分都支持使用任何 OpenAI 兼容 API 格式的模型提供商,但是作为这个流派最著名的 Claude Code 却只能用自家模型。自家模型其实也不错,但是对我这种无法在生产环境使用,只是用来自己探索和 side project 的场景下太贵了。搜了下似乎没有人介绍过如何让 Claude Code 和非官方模型配合使用,于是决定记录下。
这一方法的核心是 Claude Bridge 这个项目。实现上,和任何计算机科学问题的解决方式一样,加了一个中间层。具体而言,是 patch 了 node 的 fetch 方法,拦截所有向 Anthropic 官方的请求,转换成标准的 OpenAI 格式(其实是作者自己的一个统一 format),调用指定的提供商,在流式响应的时候再转换回 Claude 的 SSE 格式。
# 官方的 claude-code
npm install -g @anthropic-ai/claude-code
# claude-bridge
npm install -g @mariozechner/claude-bridge
这一步参考了 Claude Code 的一个 issue How can I use my API key without signing in?,以及这篇文章 Setting up Claude-Code with API Key。
本步骤解决的问题是,Claude Code 默认情况下只能以 Claude 账号的形式登录(重定向到官方登录页),但不能在不登入账号的情况下直接使用 API Key 发起请求。然而实际上有办法绕过这一限制,只需要创建一个 apiKeyHelper
即可。
首先在 ~/.claude/settings.json
中增加如下内容。(文件没有的话可以先创建)
{
"apiKeyHelper": "~/.claude/anthropic_key.sh"
}
然后创建 ~/.claude/anthropic_key.sh
,填入如下内容:
echo "sk_your_anthropic_api_key"
(因为我们会用第三方模型提供商,所以这里可以随便填写)
最后给让这个 shell 脚本可执行。
chmod +x ~/.claude/anthropic_key.sh
用目标提供商和模型替换命令中的参数即可。第一个 openai 参数是提供商格式,也可以换成 gemini 等。详情请参考 Claude Bridge 的 readme 文件。
claude-bridge openai {{model_name}} --baseURL {{base_url}} --apiKey {{api_key}}
当然这一方法也不是万能的,有一些已知限制:
(之后可能会写一篇文章对比不同的 agent,但是得看有没有时间了…)
2025-05-25 23:14:16
大概是高一的时候,某个平凡的课间,我打了个哈欠,然后惊恐的发现右侧的下巴卡住了,完全合不上嘴。从此开始了和颞下颌关节紊乱共存的十年。
前几次发生的时候,每次我都如临大敌,校医对此也束手无策,最后只能叫家长来(跨越半个城市)到附近的医院,找口腔科的医生帮我复位。一般这个过程都很痛苦,医生需要在口腔里使劲和关节搏斗。那会大概一个月会出现一次。比较好笑的是,某一次晚自习脱臼又发生了,家长开车来学校,我上车后迷迷糊糊睡着了,醒来的时候还没到医院,但是我突然发现似乎脱臼自己恢复了,于是就直接掉头又回了学校。
但是总是叫家长去医院也不是个事,于是我开始主动寻找缓解方法。在知乎的一个回答上看到热敷的建议后,我尝试用水壶装满热水靠在关节上,用热量让关节放松(医院红外射灯大概也是这个原理)。这个方法有时有效,但效果并不稳定——就像这个病本身一样难以捉摸。
高二那年,我去图书馆在知网上查阅医学论文,试图找到一些思路。这一次有了新发现:口外复位法。这个方法如此重要且有效,以至于我需要在此原文摘录:
以手指在颧骨稍下方颊部的皮肤上确定喙状突顶部的所在位置,然后将拇指放在上面,向后向下按压就能使脱白复位。
这种口外复位方法的优点是:不需要将手指放入患者口内,在无条件洗手的情况下也能进行,不需要太大的按压力量,不需要助手的帮忙,在坐、站、卧任何体位的情况下都能进行复位。不仅医务工作者容易掌握这一方法,习惯性脱白者亲属也能掌握。
我把这段文字抄到了自己的本子上,并决定在下次脱臼的时候尝试。下次脱臼到来时,我惊喜地发现这是可行的(尽管很痛,会痛到流泪的程度)。至少我现在有了个有效的自救手段。
高三某个晚自习的课间,我打了个哈欠,然后脱臼又发生了。但这次伴随着一个新的突破:当时我刚趴桌睡醒,不知为何决定猛地一仰头,然后关节复位,脱臼消失了!我不太确定这是怎么实现的,可能是加速度让关节冲过了卡点,或者是仰头的操作扩大了移动范围?这个仰头复位的方法,在绝大多数情况下都有效,但是依然有限制:一是必须要在脱臼发生后立刻执行,超过五秒成功率就会大幅下降;二是有的时候不方便仰头(例如落枕了),那就做不到了。
脱臼第一次发生之后,我去看过医生,后面也陆续去过几家不同医院。医生怀疑和我小时候咬合习惯不佳相关(例如只用一侧牙齿咀嚼),但是没有什么好的治疗方式。可以手术,但是风险远高于收益,因此最后还是建议保守治疗,平常自己多注意。家长买过限位头套,但戴着像恐怖分子的造型让我几天后就放弃了。
如今,对我而言脱臼已经变得如此频繁,每天可能发生十几次,医学上称之为"习惯性脱臼"。幸运的是,绝大部分情况下我都能通过仰头自行复位,所以对日常生活的影响比较小。唯一的困扰可能是旁人偶尔会对我突然仰头的动作投来奇怪的目光。那些仰头无法解决的严重情况,我会找个无人的角落,用之前学到的口外复位法自己处理。每次这类无法自动复位的脱臼发生,需要我手动干预时,我会留下记录;前几年的时候情况比较糟糕,大概一个月一次,近期已经有所好转(可能和我拔了智齿相关),大概是每100天会出现一次。
值得庆幸的是,在高考和其他人生重要时刻,这个病都没有给我带来麻烦。现在的我已经完全接受了与它共存的状态,甚至发展出了一套"充电"理论——定期按摩关节区域就像充电,如果等到"电量耗尽",关节就会卡住。
如果你从未听说过这个病,那我衷心祝愿你永远不会有机会了解它。某种程度上说,在现代社会,对疾病知识知道得越少可能意味着越健康?但如果你或身边的人也受此困扰,希望我的经验能提供一些帮助。
2025-05-06 22:25:05
起因是在看推上的日语同人;如果用 LLM 直接翻译的话,无论加了什么prompt,最后翻译出来的顺序也是乱的(可能是因为视觉模型内在的处理顺序问题?),需要脑内重排序,不太爽;正巧之前看到过其他人的博客,说现在视觉模型可以输出边界框了,于是趁着放假 vibe coding 了一把,果然还真可以用;虽然边界框偶尔不太准,但是大部分场景下也足够了。起初用 Python 写了一个版本,但后面意识到其实可以直接用 Web 技术实现,省的用户另外配置环境了。
2025-03-30 21:00:34
对我来说,写文章其实是心理门槛挺高的一件事,会觉得得对某个事物充分了解,完全掌握了,才有动力去下笔。(虽然大概这里的文章并没有达到这样一个状态。)但也有时候,我见到了一个有趣或者有用的事物,可能是一篇论文、一个项目、一条视频,或者只是简单的一个想法,会有分享的欲望。为此写文章有些太大动干戈了,但是不将他们分享出去又有些可惜。现实生活里我有一个小群来分享这些东西,但我认为它们值得被更多人看到。
因此,在我经常阅读的另外两位创作者 Simon Willision 和 Julia Evans 的启发下,去年年底我创建了一个名为 TIL (Today I Learned) 的分类。形态上类似于微博或者 Reddit,基本上都是一个链接 + 一些简短的介绍,意图在于让读者快速了解这些事物是否对 ta 们有帮助,并将流量引导到原作者。
但创建这个分类之后,我发现自己的分享频率并没有显著上升。后来我意识到,虽然有了单独的分类,但是发布行为本身并没有简化。即使我只是想快速分享一个链接,我依然要采用和正式文章完全相同的方式:在编辑器里新建一个 Markdown 文件,写 front matter 和文章正文,预览,推送到 Github 仓库。如果这个新分类的定位类似于微博,那为什么不能像真的发微博那样简单呢?
这个月初,我调整了下 TIL 的发布方式,做法类似于 headless CMS。具体而言,在某个地址有一个简单的页面,里面有一些基本字段(标题、URL)和一个 Markdown 编辑器,还有一个“发布”按钮。在我填充完基本信息,点击“发布”之后,会触发一个云函数,读取请求,调用 Github API 完成 Repo 内新文件的写入。虽然技术上来看这并不复杂,但却极大减少了发布的心理负担。现在当我想分享的时候,只要打开这个页面,快速把内心的感受 dump 进去,点击发布,就算完成了。
当然,考虑到 TIL 形式的分享贴所含的信息量更低,不能排除正常读者会被打扰的可能性。为此,我修改了 Hugo 的 RSS 模板,将 TIL 和正常文章拆分成了两个 RSS 源。TIL 的分享只会在单独的 TIL 订阅源中出现,以确保读者只有在明确想收到这些分享的时候才会收到。(这也是从 Simon Willison 那里学到的,他有一个名为 atom-everything
的订阅入口。)
最后是一些相关链接。希望你也能发现我的 TIL 对你有帮助。感谢阅读!
2025-03-30 15:57:05
我发现自己经常对着一个有趣的 Github Repo 思考:「这看起来真不错!但是究竟是怎么做到的?」。但很多时候我无法满足我的好奇心。要么是这个项目并没有自带一个「How it works / 工作原理」的介绍(在我看来这应该是每个项目 README 的必备),要么是我没有时间或者耐心在层层叠叠的文件树或者错综复杂的调用链里自己找到答案。得益于近来 LLM 的上下文窗口增长,让 LLM 来帮我回答这一问题似乎是个不错的选择。即使 LLM 回答给出的答案可能有错误或者不完整,但至少能给出一些探索方向,让我自己的理解更有效率。然而在通常的对话窗口里复制粘贴代码有些烦人,更别提无法在文件数多的项目里应用了。为此,我(让 LLM)帮我写了一个小工具,让我能更方便的从代码生成发送给 LLM 的 prompt。
具体使用起来很简单:
还有一些其他特性:
2025-03-03 23:23:31
这是一期杂谈,没什么干货。
“The drive to develop” 是早年间喷气式大脑(aka JetBrains)的一句宣传语。虽然目前无论是工作还是自己的项目里我用的都是 VSCode,但是毕竟大学编程的一大半时间都是在 JetBrains 家的各种 IDE 中度过的(毕竟有学生免费),所以对它家印象还是比较深的。第一次见到这句宣传语应该是在某次 ICPC 的直播上(当时 JetBrains 是官方赞助商之一),感觉直击心灵。在学校里的时候虽然有各种课程,但也有一些有趣的课程项目,再加上自己也会写点自己的东西,所以的确是有这种编程的动力的。这样的动力在工作后甚至也延伸了一段时间,上班的时候写公司的代码,下班之后忙自己的项目。
可惜这样的动力并没有延伸太久。随着工作年限增长,工作上要处理的事务也越来越多,虽然也写代码,但是写代码的时间并不是工作时间的大头,因为还有无数的关联任务需要完成(设计文档、代码评审、发布、告警处理…)。即使是到了周末,也会因为周中的工作几乎耗尽了精力,没有动力坐回电脑前写点什么;残存的精力已经只够我在床上躺着刷手机了,各种个人项目也因此停滞了很久。
但各类 AI 代码编辑器(更准确地说,是 LLM-assisted programming?)的出现改变了这一切。虽然 ChatGPT 早在 22 年底就发布了,但是我自己亲自上手体验已经是 23 年初。当时还是刀耕火种的时代,需要自己从网页里复制代码到 IDE 里。后来 Github Copliot 有了对话模式,可以稍微做一些交互式的任务了,但是因为没法自动 apply changes,最多只能 insert,体验还是不太行。再后来试用了 Cursor,第一次体会到了什么叫做 “AI-Native” 的编辑体验,变更大部分时间都可以直接 Apply 进去,不用再自己一个个找了;但是用起来还是感觉有点迟滞,例如因为索引还不太好使,很多时候都得手动指定某一个特定的文件加入上下文才能有比较好的效果。最近我在使用的是 Windsurf,起初不是很习惯(生成过程中看不到进度,和 Cursor 不同),但后来才发现了其 agent 能力的真正作用,多文件修改、代码库索引,再结合自带的联网搜索,真正做到了指哪打哪,信手拈来。
之前之所以空闲时间不太想写代码,并不是因为没有想法,而是虽然有想法,但是具体怎么实现的思路依然很模糊,而且中途还有高度的不确定性和时间成本,例如有的时候配环境就因为一些莫名其妙的依赖调试了两三个小时,或者是因为某一个感觉上很直接但是就是写不对的函数 rage quit。但是有了 LLM 之后,我可以直接对着编辑器说:去,把这个功能给我做出来,然后看着 agent 吭呲吭呲尝试各种方法,自己调试问题。虽然偶尔还是要人介入,但是心态上会好很多,感觉自己仿佛什么都能做。在我最近的一个小项目里,我给一个 Rust 的库实现了一个 web playground link 。虽然我知道步骤是先写一个 wrapper,然后编译 wasm,再写点 js 去调,但是里面有很多细节我是不知道的(需要装什么工具,怎么编译)或者是不想手动做的(例如写胶水前端代码)。于是我把我的思路告诉 LLM,一个小时之后我就有了一个能用的 demo。(其中甚至还包括至少二十分钟在等 rust toolchain 和 wasmpack 编译)这样的效率是之前自己想都不敢想的。
但是我也注意到,AI 代码编辑器的出现,只是帮助让有想法的人走的更快更远;如果一开始就没有想法,即使有这样的工具也不会去用。以我自己为例,AI 音乐/图片/视频生成已经实用化很长时间了,也有各类免费的服务可供选用,但是我却提不太起去用它们创作些什么的兴趣,也没有什么想法。由此推知,可能也有其他人心中有不少想让 AI 画出来的画面,有 the drive to draw,但是面对空白的编辑器窗口却不知道应该发出什么指令,帮助自己做什么事情吧。
最后,无论目标为何,希望大家都能找到自己趁手的工具,完成自己想做的事。