Emacs + AI 折腾日志
Table of Contents
安装 gptel 获得基本的 emacs gpt 能力 https://github.com/karthink/gptel
基本使用过程
- 使用命令:
gptel
开启一个聊天的 buffer ,直接打文字 - 在 gptel 的 buffer 下,使用命令
gptel-menu
后可以打开命令行,使用 RET 就可以发送事件 或者也可以使用命令C-c RET
直接执行gptel-send
发送指令
gptel 的模式其实就是一个 markdown mode 的模式,然后在这个基础上增加了菜单 这个菜单可以通过切换模型:比如 gpt-3.5-turbo ,然后就可以发命令了
基本使用过程(在 org mode 中指导一个话题)
其实默认的 gptel-mode 下就是一个类似 org-mode 的方式进行消息发送。
在 org mode 下最简单的方式也可以直接 gptel-send
一个例子,我写如下一段话,然后直接调用 gptel-send :
我在使用 emacs 以及使用了 gptel 这个插件来调用 openai 的 api ,我怎样简单的把这个工具集成到 org-mode 中让他指导我的文档写作
gptel 能给我直接返回:
To integrate gptel into org-mode for guiding document writing: 1. Use 'gptel-send' in gptel-mode or org-mode to interact with OpenAI's API for guidance. 2. Consider customizing gptel for org-mode to streamline the integration.
增加额外的 context 信息,则需要使用 gptel-menu
来增加。
另外也可以使用 C-c u
放在 gptel-send
之前,就能定制某次发送的特殊字段,包括
- 选择使用 gpt model
- 只应用在下一次 send 时的指令
- 从另处读取 prompt 或把结果输出到别的地方
- 直接把 prompt 替换为 response 的操作
另外默认上下文是包含全部上下文的,在 gptel-menu
中我可以设置只附加几条,我设成了4
快速尝试
如果我需要解释一段代码的作用,我可以先选中代码,使用 C-u M-x gptel-send
,设置 System prompt 为 "请帮我解释如下代码:" ,并把 prompt from 改成 minibuffer ,把 response to 改成了 echo ,回车后, gptel 帮我完成了解释
如果不使用 minibuffer 作为 prompt from 的选项,则他会直接发送
在 org mode 中使用
在 org-mode 中的话,可以通过 gptel-org-set-topic
的方式,把话题限制在当前 org head 中
把 gptel 添加到 embark 指令中
基本想法:在一些常见的 embark 模式中,比如 embark-expression-map 中,绑定一些函数,这些函数主动触发 gptel 的方法,以实现查询
https://github.com/karthink/gptel/wiki/Defining-custom-gptel-commands
(defun gptel-explain-code (bounds &optional directive)
"Send the selected code from expression to GPT for explanation."
(interactive
(list
(cond
;; if it's a region
((use-region-p) (cons (region-beginning) (region-end)))
;; if it's in text mode, get sentence at point
((derived-mode-p 'text-mode)
(list (bounds-of-thing-at-point 'sentence)))
;; otherwise get the line
(t (cons (line-beginning-position) (line-end-position))))
(and current-prefix-arg
(read-string "ChatGPT Directive: "
"请帮我总结和解释这段代码的作用。"))))
(gptel-request
(buffer-substring-no-properties (car bounds) (cdr bounds)) ;the prompt
:system (or directive "请帮我总结和解释这段代码的作用。")
:buffer (current-buffer)
:context (cons (set-marker (make-marker) (car bounds))
(set-marker (make-marker) (cdr bounds)))
:callback
(lambda (response info)
(if (not response)
(message "ChatGPT response failed with: %s" (plist-get info :status))
(with-current-buffer (get-buffer-create "*gptel-lookup*")
(let ((inhibit-read-only t))
(erase-buffer)
(insert response))
(special-mode)
(display-buffer (current-buffer)
`((display-buffer-in-side-window)
(side . bottom)
(window-height . ,#'fit-window-to-buffer)))))))
)
然后把这个方法绑定,比如
(define-key embark-region-map (kbd "0") 'gptel-explain-code)
例子里还有其他代码,包括如何解析一个 url 并总结他的内容,都是值得学习的。
项目: https://github.com/kamushadenes/gptel-extensions.el 有许多实现也可以作为学习对象
TODO 调整实现,只对 prog 模式启用,在其他模式下不启用
TODO 学习 gptel-quick 使用 postframe 显示提示内容
TODO 增加多个 buffer 或 region 以帮助分析代码作用
TODO 试试其他模型,比如 claude
可以使用 openRouter https://openrouter.ai/anthropic/claude-3.5-haiku-20241022:beta
使用 ai 做编程指导
如何交互式的去优化一段代码,比如说,我先选中一段代码,问 gpt 他的作用,然后在上下文中,继续追问我要如何修改,以达到我的某种目的,然后逐渐完善我的代码,最好问答记录都能存下来,以便我反复的问同一段代码
使用 elysium 写代码
https://github.com/lanceberge/elysium
快速使用:
打开任何一个代码文件,可以选中需要调整的部分,也可以不选则为整个 buffer ,然后调用 elysium-query
输入要求,就能自动生成修改。
生成修改后,可以用 smerge-keep-upper
或者 smerge-keep-lower
来选择使用哪个版本的代码。
代码都可以开启 smerge-mode
这样会有高亮。
使用 magit 自动生成 commit 信息
https://github.com/douo/magit-gptcommit 这个库不好用,因为依赖外部库,而 emacs 的依赖处理不好,无法做到我的依赖只依赖我的版本, gptel 本身一升级, magit-gptcommit 就不能用了
后来换成了 https://github.com/ywkim/gpt-commit 用起来就比较简单好用,不需要复杂的配置。本身 commit 信息的生成任务比编码要简单,这里就用一个独立的库而不是依赖 gptel 来使用
这个自动总结的 commit 信息还是有点啰嗦,后续可以看一下如何优化
使用 ai 指导做一个博客自动发布流程的 el 脚本
参考过程 https://emacs-china.org/t/org-mode-ox-publish/13869 https://emacs-china.org/t/advice-ox-publish-org-roam/26973
这个过程也可以引入到: 一个笔记系统的思考
实现功能:
- 本地图片会放在一个固定文件夹下,使用 org-download 这样的机制
- 在 ox publish 时,扫描当前 page ,提取出所有图片,并上传 cdn ,在最终文件中替换成 cdn 地址
- 如果某个文件已经被上传过,或 hash 没改变,则不上传
- 添加 ga 信息,生成索引文件和 rss 文件
将文件发布到 github 上
以上处理只针对带有 blog 和 publish tag 的帖子
我创建一个
my-ox-publish.el
文件,让 elysium 按我的描述反复修改和生成这个代码