|
|
|
|
|
|
|
|
|
|
|
;;; package --- gptel |
|
|
|
|
|
;;; Commentary: |
|
|
|
|
|
;;; A simple LLM client for Emacs. |
|
|
|
|
|
;;; https://github.com/karthink/gptel |
|
|
|
|
|
;;; Code: |
|
|
|
|
|
|
|
|
|
|
|
(use-package gptel |
|
|
|
|
|
:ensure t |
|
|
|
|
|
:defer t |
|
|
|
|
|
:config |
|
|
|
|
|
;; Major mode used for chat buffers: 'org-mode or 'markdown-mode. |
|
|
|
|
|
(setq gptel-default-mode 'org-mode) |
|
|
|
|
|
|
|
|
|
|
|
;; API keys: each backend below uses #'gptel-api-key-from-auth-source, |
|
|
|
|
|
;; which looks up the backend's host with login "apikey" in auth-source. |
|
|
|
|
|
;; Add these lines to ~/.authinfo.gpg: |
|
|
|
|
|
;; |
|
|
|
|
|
;; machine openrouter.ai login apikey password <OPENROUTER-KEY> |
|
|
|
|
|
;; machine api.venice.ai login apikey password <VENICE-KEY> |
|
|
|
|
|
;; |
|
|
|
|
|
;; (Create keys at https://openrouter.ai/keys and |
|
|
|
|
|
;; https://venice.ai/settings/api-key respectively.) |
|
|
|
|
|
;; |
|
|
|
|
|
;; Note: OpenCode cannot be used as a gptel backend: its HTTP API is |
|
|
|
|
|
;; for driving agent sessions, not an OpenAI-compatible LLM endpoint, |
|
|
|
|
|
;; and its own provider authenticates with an account, not an API key. |
|
|
|
|
|
|
|
|
|
|
|
;; OpenRouter (default backend): OpenAI-compatible gateway to many |
|
|
|
|
|
;; providers. Model IDs can be browsed at https://openrouter.ai/models |
|
|
|
|
|
(setq gptel-backend |
|
|
|
|
|
(gptel-make-openai "OpenRouter" |
|
|
|
|
|
:host "openrouter.ai" |
|
|
|
|
|
:endpoint "/api/v1/chat/completions" |
|
|
|
|
|
:key #'gptel-api-key-from-auth-source |
|
|
|
|
|
:stream t |
|
|
|
|
|
:models '(anthropic/claude-sonnet-5.5 |
|
|
|
|
|
anthropic/claude-haiku-5.5 |
|
|
|
|
|
openai/gpt-6.1-sol |
|
|
|
|
|
google/gemini-4-argon |
|
|
|
|
|
z-ai/glm-5.3-prime |
|
|
|
|
|
z-ai/glm-5.3-flashx |
|
|
|
|
|
z-ai/glm-5.3-flash |
|
|
|
|
|
z-ai/glm-5.2 |
|
|
|
|
|
deepseek/deepseek-v4.1-flash |
|
|
|
|
|
qwen/qwen3.8-max-prime |
|
|
|
|
|
x-ai/grok-4.7 |
|
|
|
|
|
moonshotai/kimi-k3.1-pro)) |
|
|
|
|
|
;; Change the default model here, or per-session with the menu |
|
|
|
|
|
;; (C-u C-c RET in a gptel buffer, then -m). |
|
|
|
|
|
gptel-model 'z-ai/glm-5.3-prime) |
|
|
|
|
|
|
|
|
|
|
|
;; Venice (https://venice.ai): privacy-oriented, OpenAI-compatible |
|
|
|
|
|
;; API with uncensored models. Registered but not the default: pick |
|
|
|
|
|
;; it per-session with `M-x gptel-venice' (below) or the menu |
|
|
|
|
|
;; (C-u C-c RET, then -m), or make it the default: |
|
|
|
|
|
;; |
|
|
|
|
|
;; (setq gptel-backend (gptel-get-backend "Venice") |
|
|
|
|
|
;; gptel-model 'zai-org-glm-5) |
|
|
|
|
|
(gptel-make-openai "Venice" |
|
|
|
|
|
:host "api.venice.ai" |
|
|
|
|
|
:endpoint "/api/v1/chat/completions" |
|
|
|
|
|
:key #'gptel-api-key-from-auth-source |
|
|
|
|
|
:stream t |
|
|
|
|
|
:models '(zai-org-glm-5 ;Venice's default model |
|
|
|
|
|
z-ai-glm-5-3 |
|
|
|
|
|
z-ai-glm-5-3-flash |
|
|
|
|
|
venice-uncensored-1-2 |
|
|
|
|
|
claude-sonnet-5-5 |
|
|
|
|
|
claude-opus-5-5 |
|
|
|
|
|
deepseek-v4-1-flash |
|
|
|
|
|
kimi-k3-1-pro)) |
|
|
|
|
|
|
|
|
|
|
|
;; In org chat buffers, only send the current heading's tree as |
|
|
|
|
|
;; context instead of the whole buffer: |
|
|
|
|
|
;; |
|
|
|
|
|
;; (setq gptel-org-branching-context t) |
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
;; Start or switch to a chat on a specific backend, without touching |
|
|
|
|
|
;; the global default. An existing chat buffer keeps its chosen |
|
|
|
|
|
;; model; a new chat gets MODEL. |
|
|
|
|
|
(defun gptel--backend-chat (backend-name model) |
|
|
|
|
|
"Start or switch to a gptel chat using BACKEND-NAME and MODEL. |
|
|
|
|
|
The global default backend is not changed." |
|
|
|
|
|
(let* ((backend (gptel-get-backend backend-name)) |
|
|
|
|
|
(buffer (gptel (concat "*" backend-name "*")))) |
|
|
|
|
|
(with-current-buffer buffer |
|
|
|
|
|
(setq-local gptel-backend backend) |
|
|
|
|
|
(unless (memq gptel-model (gptel-backend-models backend)) |
|
|
|
|
|
(setq-local gptel-model model))) |
|
|
|
|
|
(display-buffer buffer gptel-display-buffer-action) |
|
|
|
|
|
buffer)) |
|
|
|
|
|
|
|
|
|
|
|
(defun gptel-openrouter () |
|
|
|
|
|
"Start or switch to a gptel chat using OpenRouter." |
|
|
|
|
|
(interactive) |
|
|
|
|
|
(require 'gptel) ;deferred by use-package above |
|
|
|
|
|
(gptel--backend-chat "OpenRouter" 'z-ai/glm-5.3-prime)) |
|
|
|
|
|
|
|
|
|
|
|
(defun gptel-venice () |
|
|
|
|
|
"Start or switch to a gptel chat using Venice." |
|
|
|
|
|
(interactive) |
|
|
|
|
|
(require 'gptel) |
|
|
|
|
|
(gptel--backend-chat "Venice" 'zai-org-glm-5)) |
|
|
|
|
|
|
|
|
|
|
|
;; Usage: |
|
|
|
|
|
;; M-x gptel start a dedicated chat buffer (default backend) |
|
|
|
|
|
;; M-x gptel-openrouter start or switch to a chat on OpenRouter |
|
|
|
|
|
;; M-x gptel-venice start or switch to a chat on Venice |
|
|
|
|
|
;; M-x gptel-send send the region (or text up to point) from any buffer |
|
|
|
|
|
;; M-x gptel-rewrite rewrite/refactor the selected region |
|
|
|
|
|
;; C-c RET send the query |
|
|
|
|
|
;; C-u C-c RET menu: switch backend/model with -m, etc. |
|
|
|
|
|
;; |
|
|
|
|
|
;; Uncomment for global shortcuts: |
|
|
|
|
|
;; (global-set-key (kbd "C-c g") #'gptel) |
|
|
|
|
|
;; (global-set-key (kbd "C-c o") #'gptel-openrouter) |
|
|
|
|
|
;; (global-set-key (kbd "C-c v") #'gptel-venice) |
|
|
|
|
|
|
|
|
|
|
|
(provide 'init-gptel) |
|
|
|
|
|
|
|
|
|
|
|
;;; init-gptel.el ends here |