February 3, 2025
By: Kevin

emacs上的LLM交互工具gptel介绍

  1. GPTEL介绍和基本使用
    1. gptel 的特性与优势
    2. 安装与配置

GPTEL介绍和基本使用

近年来.大型语言模型(LLM)的发展日新月异.它们在文本生成,代码编写,语言翻译,问答系统等领域展现出了惊人的能力.

像OpenAI 的 ChatGPT,Google 的 Gemini,Anthropic 的 Claude.以及本地运行的Ollama,Llama.cpp 等模型.都成为了开发者和内容创作者的强大工具.

而像 GitHub Copilot 和 Cursor 这样的 IDE 集成.更是将 LLM 的能力直接带入了代码编辑器.极大地提升了开发效率.

作为 Emacs 用户.我们自然也希望能在 Emacs 中充分利用 LLM 的强大功能.虽然已经有一些 Emacs LLM 客户端.但它们往往局限于特定的交互方式(如 shell 模式或 Org-mode 的 babel 块).

而我们今天要介绍的 gptel.则是一款与众不同的 LLM 客户端.它将 LLM 的能力无缝融入 Emacs 的日常使用中.让你可以随时随地.在任何 buffer 中与 AI 交互.

gptel 的设计理念与 Emacs 的精神高度契合:高度可定制,可扩展.并且与 Emacs 的工作流程完美融合.它不仅仅是一个简单的聊天窗口.更是一个强大的工具.可以帮助你完成各种各样的任务.

gptel 的特性与优势

gptel 的强大之处在于它的灵活性和可定制性.它不仅支持多个 LLM后端.还提供了丰富的选项和钩子.让你可以根据自己的需求进行深度定制.

  1. 异步与流式响应: gptel 的所有操作都是异步的.

    这意味着在等待 LLM 响应时. 仍然可以继续使用Emacs. 而且, gptel 支持流式响应(如果 LLM 后端支持). 可以实时看到 LLM 生成的内容.无需等待整个回复完成.

  2. 广泛的 LLM 后端支持: gptel 支持多种主流的 LLM 服务.包括:

    • ChatGPT
    • Gemini
    • DeepSeek
    • Claude
    • Ollama
    • Llama.cpp
    • GPT4All
    • Kagi (FastGPT & Summarizer)
    • Azure
    • Groq
    • Perplexity
    • OpenRouter
    • together.ai
    • Anyscale
    • PrivateGPT
    • DeepSeek
    • Cerebras
    • Github Models
    • Novita AI
    • xAI

    更重要的是.gptel 支持兼容 OpenAI API 的任何 LLM 服务, 可以轻松地使用各种本地模型或自定义服务.

  3. 深度 Emacs 集成:

    • 可在任何 buffer 中使用: 无论是在编写代码,撰写文档,编辑配置文件. 还是在 shell 中执行命令. 都可以随时随地调用 gptel.让 LLM 为你提供帮助.
    • 与 Emacs 工作流无缝融合:gptel 的操作方式与 Emacs 的其他命令一样自然.
    • 支持区域(region)操作:可以方便地处理代码,文本片段.
  4. 强大的 Org-mode 集成: gptel 为 Org-mode 用户提供了特别的优化:

    • gptel-org-branching-context: 开启此选项后.每个 Org 标题下的内容将构成一个独立的对话分支.这使得在同一个文件中进行多个独立的对话成为可能.
    • gptel-org-set-topic: 将当前对话的上下文限制在当前 Org 标题下.
    • gptel-org-set-properties: 将 gptel 的配置(如模型,后端,温度等)保存为 Org 属性.实现"可复现"的对话.
    • 自动将 LLM 返回的 Markdown 格式转换为 Org 格式.
  5. 灵活的上下文管理: 除了当前 buffer 的内容. 可以使用 gptel-add 命令将任意区域, buffer 或文件添加到 gptel 的上下文中.

    可以轻松地让 LLM 参考项目中的其他文件, 代码片段或外部文档. 使用gptel-context--buffer-setup可以查看上下文. 使用gptel-use-context控制如何使用这些上下文.

  6. 实验性工具调用 (Tool Use): gptel 支持调用外部工具.允许 LLM 直接和 Emacs 以及外部世界交互.你可以定义自己的工具.实现更多可能.

  7. 可定制性:

    • 通过 gptel-directives 自定义 system prompt, 支持函数动态生成 prompt.

      (setq gptel-directives
            '((rewrite . gptel--rewrite-directive-default)
              (calc . "你是一个数学计算机, 仅仅给出最终的结果就行, 不要其他任何其他输出")
              (poet . "你是一个中国古代诗人, 擅长唐诗宋词")
              (clj-dart-expert . read-dart-expert-prompt)
              (emacs-expert . read-emacs-expert-prompt)
              (translation . "你是一个翻译, 把文本翻译为中文, 输出中使用英文标点, 而不是中文标点.")
              (default . "You are a large language model living in Emacs and a helpful assistant. Respond concisely, use english punctuation.")
              (programming . "You are a large language model and a careful programmer. Provide code and only code as output without any additional text, prompt or note.")
              (writing . "You are a large language model and a writing assistant. Respond concisely.")
              (chat . "You are a large language model and a conversation partner. Respond concisely.")))
      

      其中read-dart-expert-prompt 是一个函数

      (defun read-prompt-from-file (file)
        "Read the content of FILE and return it as a string."
        (with-temp-buffer
          (insert-file-contents file)
          (buffer-string)))
      
      (defun read-emacs-expert-prompt ()
        "Emacs expert."
        (read-prompt-from-file "~/.emacs.d/prompts/emacs-expert.md"))
      
      (defun read-dart-expert-prompt ()
        "Clj dart expert."
        (read-prompt-from-file "~/.emacs.d/prompts/clj-dart-expert.md"))
      
    • 通过 gptel-request 构建自定义命令.

    • 丰富的钩子 (hook): gptel-pre-response-hook, gptel-post-response-functions, gptel-post-stream-hook 等.

    • gptel-expert-commands, 用于打开菜单中的专家模式.

安装与配置

  • 通过 MELPA 安装 (推荐):

    1. 确保你的 Emacs 配置中已经添加了 MELPA 源.
    2. 执行 M-x package-install RET gptel RET.
    3. (可选) 如果你需要 Markdown 支持.可以安装 markdown-mode.
  • 基本配置 (以 ChatGPT 为例):

    1. 从 OpenAI 官网获取你的 API 密钥.

    2. 在 Emacs 配置文件中设置 gptel-api-key 变量.为了安全起见.推荐使用 auth-source:

      • ~/.authinfo 文件中添加一行:

        machine api.openai.com login apikey password YOUR_API_KEY
        
      • 在 Emacs 配置文件中添加:

        (setq gptel-api-key #'gptel-api-key-from-auth-source)
        

      你也可以直接设置 gptel-api-key 变量.但请注意保护好你的密钥:

      (setq gptel-api-key "YOUR_API_KEY")
      

    或者更安全地, 将其设置为一个返回 key 的函数:

    (setq gptel-api-key (lambda () "YOUR_API_KEY"))
    

    如果你不设置, 在你第一次使用gptel时, 它会提示你输入.

  • 其他 LLM 后端的配置:

    gptel 通过 gptel-make-openai, gptel-make-gemini, gptel-make-anthropic, gptel-make-ollama 等函数支持其他多种模型, 详细配置, 请参考gptel 源码中对应函数的文档.

    这里提供一个常用模型的配置示例:

    ;; OPTIONAL configuration
    (setq
     gptel-model 'gpt-3.5-turbo
     gptel-backend (gptel-make-azure "Azure-1"
                     :protocol "https"
                     :host "YOUR_RESOURCE_NAME.openai.azure.com"
                     :endpoint "/openai/deployments/YOUR_DEPLOYMENT_NAME/chat/completions?api-version=2023-05-15"
                     :stream t
                     :key #'gptel-api-key
                     :models '(gpt-3.5-turbo gpt-4)))
    
  • 进阶配置

    1. gptel-directives: 自定义系统提示, 可以是字符串, 也可以是返回字符串的函数, 让你可以根据上下文动态生成prompt, 比如加入代码评审规范, 或者特定语言的文档
    2. (setq gptel-expert-commands t) 打开专家模式

实战演练 (详细的使用示例):

  • 基本对话:

    • 在任意 buffer 中使用 gptel-send
    • 使用 C-u gptel-send (或 gptel-menu) 打开 transient 菜单.调整模型,温度等参数.
  • 专用聊天 buffer:

    • M-x gptel 创建新的聊天 buffer.
    • 使用 C-c RET (gptel-send) 发送 prompt.
    • 如何保存和恢复聊天会话 (开启 gptel-mode).
  • 上下文管理:

    • 使用 gptel-add 将区域.buffer.文件添加到上下文.
    • 使用 gptel-context--buffer-setup 查看和管理当前上下文. 演示如何用不同的上下文让LLM 完成不同的任务
  • Org-mode 专属功能:

    • 演示 gptel-org-set-topicgptel-org-branching-context.
    • 演示 gptel-org-set-properties.
  • 编辑和修改历史消息:

  • 区域重写/重构 (gptel-rewrite):

    • 选中区域.
    • M-x gptel-rewrite.
    • 使用 C-c C-a 接受,C-c C-d 查看 diff,C-c C-e 使用 ediff.

    添加中文标点替换的例子.

    (defun my/gptel-replace-chinese-punctuation (start end)
       "Replace Chinese punctuation with English punctuation in the region from START to END."
       (interactive "r")
       (save-excursion
         (let ((chinese-punctuation '("." "." ";" ":" "?" "!" "(" ")" "<" ">" "," "'" "'" """ """))
               (english-punctuation '("." "." ";" ":" "?" "!" "(" ")" "<" ">" "," "'" "'" "\"" "\"")))
           (goto-char start)
           (while (search-forward-regexp "[..;:?!,()<>,''""]" end t)
             (let* ((cchar (match-string-no-properties 0))
                    (pos (cl-position cchar chinese-punctuation :test #'string=)))
               (when pos
                 (replace-match (nth pos english-punctuation) t t)))))))
    
     (add-hook 'gptel-post-response-functions #'my/gptel-replace-chinese-punctuation)
    
  • 工具调用示例 (待补充):

    • 展示一个简单的工具定义 (如获取当前 buffer 名称).
    • 演示如何在 prompt 中触发工具调用.
  • 编写自己的命令 使用 gptel-request

    展示已经add的commit message 例子

    (defun get-staged-diff ()
        "Get the diff of staged files in the current Git repository."
        (string-trim
         (shell-command-to-string "git diff --cached")))
    
      (defun gptel-commit-message ()
        "Insert a generated commit message at point using GPT."
        (interactive)
        (let ((diff (get-staged-diff)))
          (message "正在生成提交信息...")
          (gptel-request
              (concat "请直接生成中文的commit message, 要求如下
          1. 使用中文
          2. 使用英文半角标点, 比如`:\",`等
          3. 提交信息简洁明了
          4. 提交标题必须以下前缀之一开头:
             - [feat] 用于新功能
             - [bug] 用于修复bug
             - [ref] 用于代码重构
             - [doc] 用于文档更新
             - [wip] 用于进行中的工作
           5. 有列表详细描述改动的具体内容
          " diff)
            :stream t
            )))
    

总结

gptel 是一个强大而灵活的 Emacs LLM 客户端.它将 LLM 的能力无缝融入到你的 Emacs 工作流中.通过丰富的选项,钩子和与其他 Emacs 工具的深度集成.gptel 可以帮助你提高工作效率,激发创造力.并探索 LLM 的无限潜力.

Tags: emacs