在终端优雅的集成 llm
展示图:
OpenRouter:
最近用习惯了 warp 后常常调用它自带的 llm。但是很不好用,每次返回的内容都不太符合预期,并且它的免费额度也比较少,所以最后被我弃用了。而最近恰巧又在看 jyy 的操作系统课,每次看到他在终端直接调用 deepseek 等模型行云流水,于是动起了自己在终端集成 llm 的念头。
但这想法一开始没落实。因为 api 的选择方面使人犯难:国内的如果只用 deepseek,便宜是便宜,但是未免太单调,并且由于众所周知的原因,deepseek 会过滤一些回复的内容;国外的 api 呢,经常是又贵又不好用(是的,我说的就是你,gfw),并且一般都需要国外信用卡,很不方便。基于以上的因素,这个想法被我搁置了好几周。
直到这周,订阅的 blog 和一位学长不约而同的推荐了 OpenRouter 。里面可调用的模型种类不仅完备——最重要的是不同模型的 api 接口是相同的!只需要更改调用模型名字的变量。这极大的简化了终端中调用所需要的设计。除此之外,Openrouter 支持链上支付,具有良好的匿名性,巧妙的避开了国外信用卡这一环(填写账单部分,地址随机生成器糊弄下就够了,反正也不可能让它有机会给我寄…),再加上这周赶上新币上市做多小赚了一笔😎(虽然大概率是被割韭菜前的小甜头),趁此机会就购买了它的 api,另外非常棒的一点是,只要你充了 10$,里面的免费模型的 api 都是随便调的,官方似乎说的是每天限量 1500次,这已经完全够使用了。
里面官方文档对于 api 的调用讲的很详细,也有关于 mcp 的介绍,算是不错的官方文档(这里我要点名批评 nginx ,官方文档真是够简陋的…)。
说干就干,于是今天让 ai 写了小的脚本,我从旁辅助调了一会儿 bug,一个名为 ag 的小玩具就诞生了😁。
ag:
对应的一键安装放在 github 上了,非常轻量的小玩具,也不需要 py 的环境基础,仅仅是 SHELL 脚本。
ag 这个名字来自于 jyy 的指令😂。看着他用习惯了,我就把它命名为 ag,后面才发现与一个文件搜索工具的指令撞了。但命好名了我也懒得改,如果真在系统中下载了对应的搜索工具,那直接把它卸载就完了,可以考虑更改对应脚本中的名字。
ag 的主要工作原理就是用 curl 请求,同时用 while 不断循环读取然后在内用 jq 处理输出,并且由于启用了 stream 流式传输便于阅读,所以每次请求其实是分成小段,因为流式传输是遵循 SSE 规范的,所以每次收到的响应行就像这样:
1 |
|
然后通过 echo “$json_chunk” | jq -r: 将提取到的 JSON 数据块通过管道传给 jq。 -r 标志告诉 jq 输出原始字符串结果,而不是带引号的 JSON 字符串,从而解析出返回的内容,营造出打字机的感觉(其实就是平常在网站上直接请求的感觉😂)。
原理非常简单,只需要 curl 和 jq 就可以完成,同时由于我很喜欢 fish,就顺便集成了 fish,也方便我每次在服务器上的初始配置,不然每次配环境都得浪费一段时间(这才是主要目的)。估计用 py 中的 json 解析实现可能会高效,但我 py 写的太少了… SHELL 脚本至少之前搭梯子的时候还研究过一小段时间,至少能看懂,这也是为什么直接选择用 curl 和 jq 解析的原因。
另外还支持对话记录,同样是以 json 的方式,将每次返回的 json 格式存储在本地的 json 文件里,在再次调用的时候可以将其发送过去,达到”伪记录“的作用。这里参考了 utool 里的模型本地存储设计,存储在本地也保证了自己的数据隐私,这在这个时代是非常难得的东西…
里面还有很多可以自定义修改的地方,譬如系统提示词,我默认给其设定了不要以 md 的语法输出到终端,不然会显得很杂乱。遗憾的是,这个提示词并不是特别有效,有些模型就是不听劝,硬要输出也没办法。
小插曲:
一键安装脚本文件基本是 gemini 在写,但是它一直不能正确的将本地的脚本文件结合到安装配置里,总是会出现奇奇怪怪的错误,最后还是亲自动手改了配置后才成功的,这再次告诉我们,尽信 ai 不如没有 ai😓。
其实我一开始还打算集成 glow 或者 rich-cli ,能在终端直接解析 md 格式以及导出 md 文件,但最后集成下来的效果还是不太好,似乎是每次分段请求不能让这些终端 md 解析器渲染的很好,具体的原因没有过度深究,因为我最后发现真要写代码这种需要代码块格式的,我估计还是在 copilot 或者 cursor 上写。并且导出 md 文件也没啥用,还不如直接在网站上问,这种命令行基本也是在 linux 这类不怎么使用图形界面的地方使用,md 的格式还得导到平常用的 windows 上,实在是多此一举。
感想:
这种类似的小玩具网上也有不少,而且现在有了 ai 后基本只要能看懂对应使用的语言,熟悉语法,就能比较方便的自己 diy,似乎重复造轮子显得意义不大,也没什么用,但其实真正做下来,也是一件很有趣的事,至少它是我造出来的第一件玩具,有着不同寻常的意义。
类似的心情,大概就是小时候搭积木建成第一个有模有样的小玩具差不多吧。这也是我将本篇归到”小玩具“中的原因。
毕竟编程,其实也就是用编程语言这种小积木,一步一步的搭成自己的小玩具😜
希望自己未来可以搭出一些更有意思的,独一无二的小玩具,现在的小玩具更像是中国制造,夹杂抄的成分太多了…努力学习的动力又多了一分呢hhh