使用 gptel-request 封装一个翻译方法

最近用 LLM 挺多的,尝试用英文写 prompt,但有时我不知道怎么写(英文比较菜)就想着翻译一下。
当然 Emacs 中的翻译的工具很多 1,写这个函数只是分享一下 gptel-request
的一种实现2。
- 找到当前选中区域,或者基于当前 point 获取对应的行/段落,作为要翻译的内容。
- 绑定一些本地变量,如 model,backend,因为翻译只需要一个快速便宜的模型。
- 调用
gptel-request
,写一个翻译的 prompt,发起请求,得到响应后覆盖第 1 步选中的内容。
更新:
- 偶尔碰到 openai 的模型会失效,Google 的相对稳定一点,设置一个 fallback 的模型,如果失效了就调用 fallback 模型重试。
- 支持自定义 prompt,有时可能需要翻译成别的语言可能有用。
(defun spike-leung/translate-region (prompt) "Translate the selected region (default to English) replace it. If no region is active, try to guess the sentence or paragraph at point. With prefix argument, PROMPT is used as the translation prompt." (interactive (list (when current-prefix-arg (read-string "Translation prompt: " "Translate the following text to English:")))) (require 'gptel) (let* ((has-region (use-region-p)) (bounds (cond (has-region (cons (region-beginning) (region-end))) ((use-region-p) (cons (region-beginning) (region-end))) ((and (fboundp 'bounds-of-thing-at-point)) (or (bounds-of-thing-at-point 'sentence) (bounds-of-thing-at-point 'paragraph) (bounds-of-thing-at-point 'line) (cons (point) (point)))) (t (cons (point) (point))))) (start (car bounds)) (end (cdr bounds)) (text (buffer-substring-no-properties start end)) (prompt-text (or prompt "Translate the following text to English:"))) (if (string-blank-p text) (user-error "No text to translate") (let ((openrouter-backend (gptel-make-openai "OpenRouter" :host "openrouter.ai" :endpoint "/api/v1/chat/completions" :stream t :key (spike-leung/get-openrouter-api-key) :models spike-leung/openrouter-models)) (primary-model 'openai/gpt-4.1-nano) (fallback-model 'google/gemini-2.0-flash-001)) (cl-labels ((do-translate (model) (let ((gptel-backend openrouter-backend) (gptel-model model) (gptel-use-tools nil) (gptel-use-context nil)) (gptel-request (format "%s\n\n%s" prompt-text text) :callback (lambda (response _) (if (and response (not (string-blank-p response))) (save-excursion (delete-region start end) (goto-char start) (insert response)) (if (eq model primary-model) (progn (message "Primary model failed, retrying with fallback model...") (do-translate fallback-model)) (message "Translation failed with both models.")))))))) (do-translate primary-model))))))
利用 gptel-request
,封装一些 prompt,可以方便地解决平时一些重复的、可以使用 LLM 解决的任务。
脚注:
1
Manatee LazyCat 的英文翻译 里还有更多的工具介绍。
2
在 Emacs China 的讨论 中,其他人还有别的实现方法。Emacs 中同一件事情可以有很多实现,也是折腾 Emacs 的乐趣之一吧。
3
源码可以看 init-gptel。
4
Folo 感觉有个 bug,设置里开启了行内样式渲染,代码块会使用 style 的颜色,但是我默认是浅色背景,Folo 的代码块默认是黑色背景,就会导致我的代码块很刺眼。目前先都统一成 dark mode 了。