UP | HOME

▼ 本文更新于 [2026-04-29 周三 14:23]

emacs-在org文件中利用ob-gptel保存调用LLM聊天对话(deepseek为例)

  原文链接

1. 前言

我用AI用得比较少,也就网页白嫖一下Google AI Studio的Gemini,或者玩一玩免费的DeepSeek网页版。最近DeepSeek发布了新版本,在保持低廉价格的同时可用性也仅次于几家闭源大模型了,不得不多用用了。

但是DeepSeek的网页版使用起来,感觉不如谷歌的AI Studio。后者将每场对话当做一个纯文本文件,可以自由编辑删减先前的用户输入、AI输出,而DeepSeek中用户的历史输入和模型的历史输出都是固定的、无法修改的,缺失了很大的灵活性。

幸好,我们有Emacs,可以充分自定义整个体验。

2. 软件配置

首先要安装gptelob-gptel

因为大模型默认以 markdown 格式输出,所以需要安装 markdown-mode

(use-package markdown-mode
  :mode "\\.\\(?:md\\|markdown\\|mkd\\|mdown\\|mkdn\\|mdwn\\|mdx\\)\\'")

3. gptel

配置 gptel 。首先是变量设置环节。我们设置使用外部的 curl 用于发送网络请求。内置的 url-retrieve 总会有一些大大小小的问题。

(use-package gptel :demand t 
  :custom
  (gptel-use-curl t)

gptel-directives 是一整套系统提示词,你可以把需要重复使用的提示词写在里面,在 gptel-menu 中快捷切换。我这边就默认留空了。

  (gptel-directives
    '((default . "")))

设置自动移动光标。如果你在gptel的buffer中对话,默认情况下,模型的输出插入完毕后光标会停留在你发送的位置。通过以下设置自动跳转光标

  :hook
  (gptel-post-response-functions . gptel-end-of-response)

设置模型。首先在windows上,需要专门配置一下 curl

  :config
  (when (eq system-type 'windows-nt)
    (setq gptel-curl-extra-args '("--ssl-no-revoke")))

开始配置deepseek模型。这里配置默认使用 deepseek-v4-pro 模型。记得将 YOUR-DEEPSEEK-KEY 替换为你自己的api密钥。

  (setq gptel-model   "deepseek-v4-pro"
        gptel-backend (gptel-make-openai "DeepSeek"
                        :host "api.deepseek.com"
                        :endpoint "/chat/completions"
                        :stream t
                        :key "YOUR-DEEPSEEK-KEY"
                        :models '("deepseek-v4-flash" "deepseek-v4-pro")))

接下来配置一些预设,可以等会通过 :preset 启用。
这里设置了两个预设, max 用于配置思考深度为max(默认high),而 no-r 用于关闭flash模型的思考。

  (gptel-make-preset 'max
    :request-params '(:reasoning_effort "max"))
  (gptel-make-preset 'no-r
    :request-params '(:thinking '(:type "disabled"))))

4. ob-gptel

配置 ob-gptel 。由于该包还未上melpa,我们只能从对方的repo手动下载了。下面的代码适用于30之后的emacs,我设置了该包在 org 加载完成后立即载入。

(use-package ob-gptel :after org :demand t
  :vc (:url "git@github.com:jwiegley/ob-gptel"
           :rev :newest)

gptel 加入 org-babel 的可执行语言中:

  :config
  (add-to-list 'org-babel-load-languages '(gptel . t))

修复一个小问题:当光标在 end_srcc 之后时,按 C-c C-c 执行代码的时候,会将本代码块重复纳入对话上下文中。解决方法也很简单,直接在寻找session函数前执行一下跳至行首即可。

  (defun my/ob-gptel-exclude-current-block (orig-fun &rest args)
    "Adjust point so that the current block is not included in session history."
    (save-excursion
      (beginning-of-line)
      (apply orig-fun args)))
  (advice-add 'ob-gptel-find-session :around #'my/ob-gptel-exclude-current-block))

5. 使用例

请参考ob-gptel的README。这里举例最基础用法:
基本查询

#+begin_src gptel
What is the capital of France?
#+end_src

#+RESULTS:
The capital of France is Paris.

切换模型

#+begin_src gptel :model deepseek-v4-flash
Write a haiku about Emacs.
#+end_src

:session 参数会收集所有共享相同会话名称的前置代码块。这里启用了 :dry-run yes ,让我们可以先不把内容发送给LLM,而是在 RESULTS 中提前预览一下

#+begin_src gptel :session my-chat
Tell me about Emacs.
#+end_src
#+RESULTS:
假设这是第一个输入的模型回复
#+begin_src gptel :session my-chat :dry-run yes
What about its history?
#+end_src
(:model "deepseek-v4-pro" :messages
        [(:role "user" :content "Tell me about Emacs.")
         (:role "assistant" :content "假设这是第一个输入的模型回复")
         (:role "user" :content "What about its history?")]
        :stream :json-false :temperature 1.0)

如果你已配置了 gptel 预设,可以直接使用它们:

#+begin_src gptel :preset no-r
Explain monads simply.
#+end_src

6. 配置文件

© Published by Emacs 31.0.50 (Org mode 10.0-pre) | RSS Comment