标签归档:kimi

sed

kimi还有一个破毛病,喜欢用sed来编辑脚本。

出了几次反复修改改错代码的问题。我终于忍不住问DeepSeek为什么。

这是一个很敏锐的观察。AI(比如我)在生成 `sed` 命令时确实容易出错,主要原因可以归结为以下几点:

### 1. 分隔符冲突
`sed` 默认使用 `/` 作为分隔符,但 AI 常常忽略目标字符串中也包含 `/` 的情况。

-   **错误例子**:你想把路径 `/bin/bash` 改成 `/usr/bin/zsh`。AI 直接生成 `sed ‘s//bin/bash//usr/bin/zsh/’` —— 这会导致语法错误,因为 `/` 提前结束了模式。
-   **正确做法**:需要转义 `/`(`\/`),或者改用其他分隔符,比如 `#` 或 `|`:`sed ‘s#/bin/bash#/usr/bin/zsh#’`。AI 常常忘记处理这种冲突。

### 2. 特殊字符未转义
`sed` 中的很多字符有特殊含义:`.`、`*`、`[`、`]`、`^`、`$`、`\`、`&` 等。

-   **错误例子**:你想替换 `IP地址:192.168.0.1` 中的 IP。AI 可能会写 `sed ‘s/192.168.0.1/new_ip/’` —— 但这里的 `.` 会匹配**任意字符**,而不是字面上的点。
-   **后果**:它可能匹配到 `192X168Y0Z1` 这样的奇怪组合,或者替换失败。AI 自动生成时往往忽略对这些元字符的转义(应该写成 `192\.168\.0\.1`)。

### 3. 分组和反向引用的跨平台差异
在 `sed` 中,使用 `()` 进行分组时:

-   **GNU sed(Linux)**:需要用 `\(` 和 `\)` 来转义,反向引用是 `\1`。
-   **BSD sed(macOS、FreeBSD)**:基本 POSIX 模式下,`(` 和 `)` 也必须转义才能作为分组符,不过 `\1` 用法类似。
-   **更混乱的**:有些脚本想用 `-E` 选项(扩展正则)来避免转义,但 AI 生成的命令常常**混用**两种风格,或者不加 `-E` 却用了无需转义的正则写法,导致报错或静默失败。

例如:想交换两个单词 `Hello World` → `World Hello`。正确的 GNU 写法是 `sed ‘s/\(Hello\) \(World\)/\2 \1/’`。如果 AI 忘记转义括号,写成 `sed ‘s/(Hello) (World)/\2 \1/’`,则完全无效。

### 4. `-i` 选项的平台差异
`sed -i`(原地修改文件)的行为在 Linux 和 macOS 上不同:

-   **Linux**:`sed -i ‘s/old/new/’ file`
-   **macOS**:`sed -i ‘’ ‘s/old/new/’ file` —— 必须为备份后缀提供一个空字符串参数,否则会报错。

AI 经常默认用 Linux 语法,导致在 macOS 上运行时出现奇怪的 `sed: -i may not be used with stdin` 或 `undefined label` 错误。

### 5. 边界条件与文件格式
-   **缺少换行符**:如果文件最后一行没有换行符,某些 `sed` 命令(如 `$` 地址匹配)可能表现异常。
-   **Windows 换行符(CRLF)**:`sed` 默认把 `\r` 当作普通字符,导致模式匹配失败(比如你搜 `foo$` 匹配不到 `foo\r\n`)。
-   **空文件**:一些 `sed` 脚本在空文件上会直接报错退出。

AI 在生成命令时,默认假设一个整洁的 POSIX 文本文件,但现实中并不总是如此。

### 6. AI 的“统计学习”问题
大模型的训练数据里包含大量 **错误的、过时的、不兼容的** `sed` 示例。比如:

-   来自 Stack Overflow 上某个未被采纳的答案。
-   来自个人博客里随意测试的片段。
-   来自混合了不同 shell 环境的历史脚本。

模型学会了“最常见”的写法,而不是“在所有情况下都正确”的写法。对于小众边缘情况(如处理路径、JSON、XML),模型更容易编造一个看起来合理但实际错误的命令。

### 7. 对上下文理解不足
用户往往只说“帮我改一下这个配置文件里的 IP”,但不提供文件的具体格式、是否有特殊符号、使用的是哪种 `sed` 版本。AI 只能盲目猜测,而猜测的结果就是容易出错。

### 如何减少错误?
-   **先测试**:运行 `sed` 前,先用 `sed ‘s/pattern/replacement/’ file`(不加 `-i`)看看输出是否正确。
-   **告诉 AI 更多信息**:明确说明“我的文件路径包含斜杠”“我用的是 macOS”“IP 地址里有小数点”。
-   **换工具**:对于结构化的文本(JSON、YAML、XML、CSV),用专门的解析器(`jq`、`yq`、`xq`、`awk`)而不是 `sed`。AI 生成的 `awk` 或 `perl` 命令有时比 `sed` 更可靠,因为语法更一致。
-   **加上 `--debug`**:如果 `sed` 版本支持(如 GNU sed 4.8+),用 `sed --debug` 看它是如何解释命令的。

总的来说,不是 AI 能力不足,而是 `sed` 本身是一个非常“挑剔”、充满历史包袱和平台差异的工具。AI 擅长的是统计规律,而不是绝对正确的语法和边界条件。对于关键的文件操作,**永远不要盲目信任 AI 生成的 `sed` 命令**。

明白了,于是让Kimi把不用sed写到AGENTS.md里。

自以为是的CLI

在调试过程中,我让kimi帮我checkout回git的最新版本。

然后发现它给我git clean了,于是一大堆untracked的目录被干掉了。骂了它十几句。

得到的结果就是我以为,对不起,有没有Time Machine,很废。

于是我告诉它不要用git了,除非我命令它用。

好在前两天都及时git commit过了,损失不算大,就是10美元额度能追回的事情。

有点心理阴影,还是让codex去恢复/重做这些untracked的事情了。

与kimi cli的开发反思

更多的是我在反思,让kimi看看它跟我的理念的差异,造成了一些不顺畅以及技术债务。

节选一下:

## 对 AI 的提示

在后续开发中,当遇到以下信号时,应主动质疑而不是默认实现:

1. 某个功能不在 `ROADMAP.md`、设计文档或用户明确指令中

2. 功能的加入理由是 “xxx 软件也有”

3. 修复一个边缘 bug 需要引入复杂的条件分支

4. 功能在复杂架构下语义不清

5. 正在解决的问题与之前已解决的问题高度相似

6. 同一个模块/功能反复出现相似 bug

此时应优先向用户确认:

> “这个功能不在当前设计范围内,且边界较复杂。建议是 A) 简化实现 B) 直接删除 C) 排期设计。您的偏好是?”

当遇到实现困难时,应优先执行以下检查清单:

1. **搜索当前代码库**:是否有同一模块中已解决的相似问题?

2. **搜索历史修改记录**:CHANGELOG / git history 中是否有相关修复?

3. **查看原始参考**:`xxxxxx/` 原始 C++ 代码中是否有对应逻辑?

4. **检查可复用组件**:是否有公共函数、工具类、或已有模式可以直接套用?

5. 只有在上述四步都没有找到答案时,才允许从零实现。

**注意**:第 1-4 步的参考价值**高于**第 5 步中你可能想到的”通用最佳实践”。参考代码包含了本项目的具体约束和验证过的边界条件。

当脑海中浮现”我知道一个更好的方案”时,应问自己:

1. 这个”更好的方案”是**当前项目真正需要的**,还是**我知识库中恰好有的**

2. 如果用一个简单方案实现 80% 的价值,**剩下 20% 是否值得引入额外的复杂度**

3. 这个方案如果被证明过度设计,**是否容易拆除**

4. 手头的参考代码(第三方源码或项目内已有实现)是否已经给出了**更适合当前约束的答案**

vibe coding

搭了一个moodle网站,上传了一些小学数学的视频课程,算是把这个项目固化下来,持续改进,也给自己的小孩一个记录学习的地方。当然了,其中也加了一些编程工作和自动化:

视频中提取音频,音频识别文本,文本提取出课程总结。用了deepseek和腾讯 asr的SDK。

然后可以继续AI编程了。

用群里分享的Kimi code开发了一个黑白棋的web游戏。

1.不注重上下文的话,频限(token)用得很快,4个小时的频限大概一个小时就能用完。Andante的周用量一天已经43%了。

2.把简单的需求给到deepseek,deepseek给出完整的需求prompt,复制到Kimi Cli环境中让它执行。这样也省了Kimi的token消耗。

3.按照群里的看法,就是不要看它的代码,坚决只看展示和测试结果,报bugs,也不用骂它。

4.context一高,消耗得就快,要及时/compact一下。

5.不满意的地方还是要F12看浏览器报错信息,一开始不肯做这个,Kimi Cli就自己去检查代码,效果并不好,反反复复检查,它还把变量名设成eval,不知道从哪里学的烂技术,好在它自己也知道这是不对的。

黑白棋用起来还可以,不算太差,如果用作个人网站的游戏,算可以了。