Blog

  • Hello World

    Hi

    偶尔想起来了什么,这里就会多点东西

    太阳

    每个人都是那么闪耀

    如同一片星海

    而太阳,与其说它照亮了万物

    倒不如说它遮住了星空

    但是人吧,不得不向前看

    所以也就少有抬头看的机会

    不过终有一天

    星星会铺满这片天空

    3.12.2021

    外婆

    昨天的这个时候

    你突然邀请我

    观看这场烟与火的表演

    秸秆燃烧的味道

    跟小时候一模一样

    也许在你眼中

    我还是一个孩子模样

    多么希望被子里塞的是枕头

    而你躲在床底下偷着乐

    这一切都只是你的一个恶作剧

    1.8.2022

  • 这个东西我不太想说,但它真的能解决我的 API token 焦虑

    最近习惯 vibe coding 的盆友肯定会有这样的焦虑,不管是用 CC、OpenCode等coding agent,还是养龙虾:

    💸 API 额度烧得太快了,快到有点离谱

    尤其是这种场景:

    • 长对话 Agent(多轮上下文)
    • tool calling
    • prompt 调优 + debug
    • 类似“龙虾对话”这种长上下文聊天

    基本状态就是:

    一边跑 demo,一边看 token 余额心跳加速


    然后最近我发现一个比较“野”的方案:

    直接把 Gemini 的 Web 对话包一层,变成 OpenAI API 来用

    仓库在这:

    👉 https://github.com/Sophomoresty/gemini-web2api


    ⚙️ 它是怎么工作的(很简单)

    本质就一句话:

    用 Gemini 网页版 + cookie 登录 → 模拟请求 → 转 OpenAI API

    正常你写代码的 agent 调用的还是 OpenAI 那套,但底层模型其实换成了 Gemini Web。


    🚀 怎么部署(直接上手)

    1️⃣ 启动服务

    git clone https://github.com/Sophomoresty/gemini-web2api
    cd gemini-web2api
    python gemini_web2api.py

    Base URL默认地址:

    http://localhost:8081/v1

    2️⃣ OpenAI SDK 调用

    from openai import OpenAI
    
    client = OpenAI(
        base_url="http://localhost:8081/v1",
        api_key="sk-anything"
    )
    
    resp = client.chat.completions.create(
        model="gemini-3.5-flash",
        messages=[
            {"role": "user", "content": "写一个贪吃蛇游戏"}
        ]
    )
    
    print(resp.choices[0].message.content)

    3️⃣ curl 测试

    看能不能正常返回,有返回说明部署成功了

    curl http://localhost:8081/v1/chat/completions \
      -H "Content-Type: application/json" \
      -H "Authorization: Bearer sk-your-key" \
      -d '{"model":"gemini-3.5-flash","messages":[{"role":"user","content":"Hello!"}]}'

    4️⃣ 配置文件

    可以参考 config.example.json,创一个config.json文件,可对这些参数做修改

    field value
    Base URL http://localhost:8081/v1
    API Key 随便自己创
    Model gemini默认模型

    🍪 gemini-3.1-pro:Cookie 怎么拿(核心步骤)

    要稳定跑 gemini-3.1-pro 的话,就需要靠 cookie。

    1️⃣ 登录 Gemini

    打开:

    👉 https://gemini.google.com

    用 Google 账号登录(前提需要有pro订阅)


    2️⃣ 打开开发者工具

    F12 → Application → Cookies:

    https://gemini.google.com

    3️⃣ 复制这些字段

    重点:

    • SID
    • HSID
    • SSID
    • APISID
    • SAPISID
    • __Secure-1PSID

    4️⃣ 写成 cookie.txt

    创建一个cookie.txt文件,按下面填空即可

    SID=xxx; HSID=xxx; SSID=xxx; APISID=xxx; SAPISID=xxx; __Secure-1PSID=xxx

    5️⃣ 启动时加载

    python gemini_web2api.py --cookie-file cookie.txt

    ⚠️ 需要注意的点

    这个方案本质是 Web 层模拟,所以:

    • ❌ 不稳定(Google 改页面可能直接失效)
    • ❌ gemini-3.1-pro 模型依赖 cookie
    • ❌ 有风控 / 限流
    • ❌ 不适合生产级依赖

    但它的定位也很清晰:

    👉 本地开发 / Agent 实验非常合适


    🧠 我自己的使用方式

    现在基本是这样用的, picoclaw 机器上跑这个服务,整体体验是“飞起”的, coding agent替换base url跟api无脑蹬:

    直接随便跑,不心疼 token


    🚀 最后说一句

    账号被封得不偿失,目前自己用用还算安全的。所以虽然可以但不建议去做中转。

  • 追一场雨

    想看流星雨🌠,跟一只喵🐰一起。昨晚我们终于一块冲进了山里。

    进山的路很远,路上也没一盏灯,一片漆黑中只有我们这对疯狂的人儿在前行。眼前只有漫无边际的黑,有点害怕的,我自己都不知道前方会出现什么。好在身旁的小喵🐰依旧镇定,她的歌单依旧好听。

    在还没有看到星空前,远处一片路灯先给了我希望。我略带兴奋地告诉小喵🐰山顶要到了,终于我们在山顶下车了。悬着的心终于落下了,路上真怕小喵🐰害怕得要我回头。

    但是这里还是看不到星空,我们决定继续往上走。得亏小喵🐰的建议,我们开车到了一处营地,拍下了这次“追星”途中最完美的一张合照,也是我们第一次合照。
    [wppa type=”photo” photo=”106″]

    从营地往外走的路上我们回到了刚经过的一处空地,这里有一家有趣的人正守着流星。他们已经看到俩颗流星了,因为这天空好像并不作美,我听到有点恍惚地以为这两颗星说的是我跟小喵🐰。
    不过在得到他们确切的情报后我们果断加入了其中。又回去把车子开到了这里拿出了我前段时间刚买的野餐垫铺在了地上,这也是野餐垫第一次登场。我在看手机是否能拍到流星的时候,小喵🐰他们看到了流星,讲真的他们看到流星都不喊的,我都要怀疑他们合起来骗我呢。
    [wppa type=”photo” photo=”105″]

    苦苦等待中没等来流星,但又等来了几波人,他们带来了瓜子。我也从没想过会在半夜在山上在星空下磕着瓜子。在天空被云雾挡住后这群人走上了上山小路,我跟小喵🐰随后也走上了山。
    看得出小喵🐰一开始是不太想上的,但是她越是退缩我却越是想带她上去。路途艰辛真的难为她了,山顶全是水汽雾蒙蒙的,一切都像是梦里一样。但是好爱这种感觉,又回到了之前我来过的地方,这是我很喜欢的地方,给小喵🐰拍个照。
    [wppa type=”photo” photo=”102″]

    看不到流星我们又往回走了,回到空地这次终于看到了一闪而过的流星。我天,像火柴擦亮了这块天空,我真怀疑流星是来看小喵的,每次她一出现流星就随后而至。心满意足,看到第二颗流星后我们走了。
    [wppa type=”photo” photo=”104″]

    回去路上这一切似乎还在眼前,不过都像泡在记忆的雾里。当小喵问我这一切是否是梦的时候我自己都恍惚,然后我便紧紧握住她的手,紧紧的不想跟她分开,感觉我们一分开这地方便开始消失。好在这会儿我们各自都记录下了这次经历。

  • 快速上手百度Apollo开发的一点经验之谈

    本文

    主要面向由ROS快速转向CyberRT框架的开发者,是一份QuickStart手册。因为是从ROS出发,所以需要读者具备一定的ROS基础。

    预备知识

    1. Linux
    2. ROS
    3. C++

    简而言之,会Linux命令行操作,熟悉ROS框架,了解基本C++类对象语法。

    CyberRT v.s. ROS

    CyberRT是参考ROS开发的,所以将他们联系起来看,会比较好地理解和上手apollo的开发。

    基本概念

    首先我们来看下两者在开发相关的一些主要概念上的异同。

    CyberRT ROS Description
    component package 组件/包,都是构建项目的最小单元
    node node 节点,一个组件/包里可包含多个节点
    channel topic 通道/话题名,用于节点间通信,一个节点可包含多个通道/话题
    message message 消息名,定义了数据传输的格式,一个通道/话题对应一种消息
    Reader/Writer Subscriber/Publisher 读写器/发布订阅器,都是实现节点通信的具体接口

    另外 Services 与 Parameters 等概念也类似,因为Service/Client通信模型用的少就不赘述了。

    工程目录

    了解以上概念后,现在我们从两者的工程目录来看,就比较清晰了。

    CyberRT ROS Description
    conf config 配置文件
    dag/launch launch 启动文件
    proto msg 消息文件
    nodes 源码文件
    BUILD CMakeLists.txt 编译文件
    test* test 测试文件

    注: 其中是CyberRT一个组件目录中一些具体节点名,ROS中把他们都放在一个目录nodes里了

    熟悉ROS的朋友可以很明显看出两者其实非常类似,差异主要有这两点:

    1. Apollo引入了google的protobuf取代了ROS原有的msg消息定义
    2. Apollo采用Bazel编译工具来管理C++依赖环境,而不是Cmake

    所以从一个ROS开发者切换到CyberRT下,需要简单了解下google的gflags、glog、gtest以及protobuf用法,还有就是Bazel的基本语法,为此我在本文最后梳理了一份参考资料供大家阅读。

    开发工具

    最后在开发工具上,Apollo其实也准备了许多ROS中比较常用的工具。因为开发必然会用到,所以我也简单提下。

    CyberRT ROS Description
    cyber_visualizer Rviz 用于消息的可视化
    cyber_monitor rostopic/rqt 查看实时消息数据
    cyber_recorder rosbag 录制/回放消息数据

    参考资料

    1. 官方关于CyberRT的README,其中 ‘Quickstart’、 ‘API’ 与 ‘DeveloperTools’ 这三个是必看,也最好跟着做下,可以很快的了解CyberRT框架。
    2. google关于protobuf的Guide,其中’Defining A Message Type’这段内容是必读的,其他消息嵌套等用法可以等用到了再来查阅。

      另外我们可以结合apollo开放平台文档里的’数据格式’那栏内容来加深我们对Apollo消息格式的理解。
    3. 关于gflags的简介,这篇说明是比较简俗的,内容不多可以看完。
    4. 关于glog的简介 ,可以先简单浏览下。日志输出在后期调试还是比较重要的,完整的说明到时用到了,可在google的github仓库里找到glog的README细看。
    5. gtest的入门手册,其中’Googletest Primer’必看,其他内容可到时再查。
  • Autoware调试心得-astar_avoid的避障实现

    简介

    网上有关 astar_avoid 模块的源码分析挺多的,我这里就不对它用到的 AStar 算法做过多赘述了。不过知道它的实现原理跟实际调试还是存在很大出入,因为 AStar 算法在实际应用时需要跟Autoware的其他模块所结合,为此了解其实际避障逻辑尤为重要,这也是本文的由来。

    准备工作

    1. 实车或仿真环境
    2. 已部署成功 Autoware
    3. 一个可被检测到的障碍物

    避障逻辑

    因为我看到 astar_avoid 模块里的源码用到了有限状态机(Finite State Machine)来应对各种可能遇到的环境,所以我就以期望的避障状态出发绘制了下面两张时序图。

    成功避障

    下图是我们最期望看到的,一次成功的避障会经历的各个状态的切换过程。
    [wppa type=”photo” photo=”86″]

    没有避障

    而实际调试中没有避障成功的话,那就大概率是卡在下图的某一环节里了。
    [wppa type=”photo” photo=”87″]

    这两图放一起应该很清晰就能认识 astar_avoid 模块的避障逻辑了。

  • 我,北京,故宫

    初见

    年轻的人们,热情地向我,介绍着他们,与这座城市。

    [wppa type=”photo” photo=”88″]

    这是我对北京的第一印象,他们真的说了很多,但我似乎有点听不过来。

    故宫

    我想我应该看看,所以我去了静静的,已经过去很久远的故宫。

    [wppa type=”photo” photo=”89″]

    不过这好像也是他们跟我说的,一定要去故宫转转。

    [wppa type=”photo” photo=”90″]

    进场总是这里,世界人民大团结,一切都是那么地美好。

    [wppa type=”photo” photo=”91″]

    [wppa type=”photo” photo=”92″]

    进来发现,这里砖瓦很多,色彩在建筑上的表现是最为丰富的,尤其在过渡区:楼层与楼层、楼层与屋顶。重复与对称似乎是色彩的骨架,填充起了这些过渡区。

    [wppa type=”photo” photo=”93″]

    最夸张的莫过于这个穹顶了,一度让我联想到米开朗琪罗在西斯廷教堂上的壁画。

    [wppa type=”photo” photo=”94″]

    延禧宫,中西结合的风格,甚是喜欢这里,着实漂亮的设计。

    北京

    不知道是不是故宫东西太多了,我看得有些累了。

    [wppa type=”photo” photo=”95″]

    我想我该回去听听北京的故事了。

  • 抽象的艺术

    关于此文

    • 抽象的 艺术
    • 抽象 的艺术

    何为抽象?


    在阅读下文前,先不妨思考一会会儿,眼前这个问题。


    从无到有

    看完下图后,我确信,你对它应该有了点思绪。

    [wppa type=”photo” photo=”96″]

    这是一个有趣的创造过程!

    一种映射

    还是这张图,稍微做了点改变。
    当然我们关注的重点还是这图左右之间的变化,不是上下两图的变化。

    [wppa type=”photo” photo=”97″]

    这里请务必将图中的两个‘抽象’区分为动词和名词(从上往下)对待。

    映射:就像站在太阳底下,被太阳映射出来的影子保留了我们最原始的线条。

    重在简化

    抽象的意义在于简化,只保留我们需要的线条就够了。

    [wppa type=”photo” photo=”98″]
    当然简化后我们依然能看到它大致的样子。

    何为艺术?


    先不妨再思考一会会儿,眼前这个问题。


    发现

    [wppa type=”photo” photo=”99″]

    使用

    [wppa type=”photo” photo=”100″]

    各类工具,综合(除上图之外的)多种方法来

    创造

    [wppa type=”photo” photo=”101″]

    所以抽象

    1. 美在哪?
      • 简化
    2. 如何使用工具?
      • 去建立映射

    这其中包含了两个创造过程,有时你会发现某些不太美的抽象的东西,可能它只包含了一个。