测试了下gemini,
错误:minuet-complete-with-minibuffer: Minuet provider gemini is not available
测试openroute:
错误:minuet-complete-with-minibuffer: Minuet provider openai-compatible is not available
minuet-20250510.439
测试了下gemini,
错误:minuet-complete-with-minibuffer: Minuet provider gemini is not available
测试openroute:
错误:minuet-complete-with-minibuffer: Minuet provider openai-compatible is not available
minuet-20250510.439
你的环境变量没有配置对。注意 README 里的 API keys 这一章有写 api key 要怎么配置。
现在不报错误了,大力支持,两点意见
老实说我就没用起来,调用任何补全命令没反应,可能是:
哪里配置有误
我是老一代程序员,只用过基本的补全功能(例如lsp提供的功能),不知补全和AI结合该怎么用,但是gptel我是用得很溜的
其实你提到的这些问题,我在 README 里面都写了。如果不想看英文的,现在的 AI 这么强大了,直接把 README 扔给 AI 问一下应该都能有解答的。
- 有任何错误和重要步骤信息,建议直接打印在message buffer或日志buffer里面(按q可直接不显示buffer,即c-x 0),这样用户有潜力自己解决问题,同时也知道package在干什么(例如有性能问题可直接发现)
日志都显示在 *minuet* 这个 buffer里面。
老实说我就没用起来,调用任何补全命令没反应
大概率是你用的 AI 模型时长超时了。默认的超时时限是 3 秒钟。你去看一下 *minuet* 的 buffer 里的日志。minuet 虽然支持 stream output,但是如果你用的模型在超时之前一个 token 都没输出,那么就是看不到任何的东西。
我在 README 里面有一节 troubleshooting 的 section,你可以去看一下这一节 section 里有写的。如果遇到访问超时了,该如何调整。
另外我在 Selecting a Provider or Model/ Understanding Model Speed 这一节里也写了,选择本地模型或者云端模型时应该参考什么 metric,也给了一些查询这些 metric 的资源。
建议像gptel那样出个视频
copilot 咋用,这个就咋用啊。交互形式是完全照着 copilot 来的。视频也没什么好做的,因为交互是很简单的形式,不像 gptel 那样提供了很多交互命令。
主要的问题还是配置模型以及心理预期问题。不管你怎么配置模型,本地模型或者通过 public AI API 访问的模型通常都很难像 copilot 那样快。copilot 是部署的自己的私有模型和服务,基本上是 1s 以内出结果。但是使用任何的 public AI API 都没有办法像 copilot 那样这么快的。使用最快的模型 (gemini-flash 或者 codestral)也要 2s 左右才出结果。我在 Selecting a Provider or Model/ Understanding Model Speed 这一节里也写了,该如何根据 metrics 对模型的生成速度有一个大概的评估。
可以用了,感觉不错,
速度也快, 对我来说设置 (setq minuet-context-window 500) 就够用了
看了 *minuet* 这个 buffer里面的信息,马上知道原因了,原来是public Ai API key的值copy错了。
一直觉得这个包设置key的方式怪怪的..
是的。这个是我一开始的设计失误。但是不想做没有必要的破坏性更新了。
配置key的实现,感觉用auth-source实现很合适,gpg加密。
试用了下:
- 补全,在不同的llm中,表现可能不一致。应该还是系统提示词的问题,同样的问题一字不差的情况下。
这个也是没有办法的事情嘛。LLM 会返回什么结果不是我能控制的事情。我在 selecting provider or model 里有写推荐的模型。本地用 qwen-2.5-coder 云端用 codestral 或者 gemini-2.0-flash。这三个是我测试过后表现较好的。你可以看一下项目里的 prompt.md,里面详细介绍了自定义提示词的方式。
- minibuffer 感觉不适合用来做代码补全,还是应该向cursor一样,开一个buffer专门显示处理补全和结果的选择操作等。
- 多个结果下minibuffer由于显示问题,并不能很好的确认到底该选择那个结果。
建议使用基于 overlay 的显示方式 (minuet-show-suggestion)。如果你要用 minibuffer,建议使用 vertigo+consult 补全框架,我有做专门针对 consult 的适配,这样在 minibuffer 显示的时候会有插入文本预览的效果。我不用 ivy 和 helm ,想要做对他们的适配欢迎 PR。
- token消耗问题,有时候并不需要不全,或者没有响应任何结果,但是有消耗token,感觉这样有点遭不住
这个有什么很好的思路去解决吗?目前你可以加函数到 minuet-auto-suggestion-block-functions 这个 hook 里面,当条件不满足时就不会自动触发补全请求。你也可以调整 throttle 和 delay 这两个选项,把它们两个调高一些,降低补全的频率。
此外当用户移动光标或者键入了新的字符导致正在进行的补全无效的时候,minuet 会终止所有正在运行的 curl 进程,根据我对 openai 文档的说明,当 streaming request 被中断的时候,openai 会停止文本生成,也不会继续 bill 剩余的 token。
贴下自己的配置,没有任何保证,仅供参考
我平常用 codestral, 仅在非 emacs-lisp-mode 下使用补全
(require 'minuet)
(fun-my-bind-key-global "C-c p Z" #'minuet-configure-provider)
(fun-my-bind-key-keymap prog-mode-map "M-i" #'minuet-show-suggestion)
(fun-my-bind-key-keymap prog-mode-map "M-s-i" #'minuet-complete-with-minibuffer)
(fun-my-bind-key-keymap minuet-active-mode-map "M-i" #'minuet-accept-suggestion)
(fun-my-bind-key-keymap minuet-active-mode-map "M-p" #'minuet-previous-suggestion)
(fun-my-bind-key-keymap minuet-active-mode-map "M-n" #'minuet-next-suggestion)
(fun-my-bind-key-keymap minuet-active-mode-map "M-a" #'minuet-accept-suggestion-line)
(fun-my-bind-key-keymap minuet-active-mode-map "M-e" #'minuet-dismiss-suggestion)
(fun-my-bind-key-keymap minuet-active-mode-map "C-g" #'minuet-dismiss-suggestion)
(defun fun-my-record-buffer-modified-tick (&optional start end len)
"Add to `after-change-functions'. This function should only be used in minuet-auto-suggestion-mode."
(setq-local var-my-buffer-modified-tick (buffer-modified-tick (current-buffer)))
(if (timerp var-my-timer-buffer-modified-tick)
(cancel-timer var-my-timer-buffer-modified-tick)
)
(setq-local var-my-timer-buffer-modified-tick
;; ensure time delay here is greater than `minuet-auto-suggestion-throttle-delay' + `minuet-auto-suggestion-debounce-delay'
(run-with-timer 6 nil
#'(lambda (buf)
(when (buffer-live-p buf)
(with-current-buffer buf
(setq-local var-my-buffer-modified-tick 0)
(setq-local var-my-timer-buffer-modified-tick nil)
)
)
)
(current-buffer)
)
)
)
(defun fun-my-special-hook-for-minuet-auto-suggestion-mode ()
"Hook function when enabling or disabling `minuet-auto-suggestion-mode'"
(if minuet-auto-suggestion-mode
(progn
(defvar-local var-my-buffer-modified-tick nil
"buffer-local variable to store result of `buffer-modified-tick'"
)
(defvar-local var-my-timer-buffer-modified-tick nil
"timer to reset `var-my-buffer-modified-tick' to zero, which means buffer is not changed for a some time."
)
(add-to-list 'after-change-functions #'fun-my-record-buffer-modified-tick)
)
(setq-local after-change-functions (delq #'fun-my-record-buffer-modified-tick after-change-functions))
)
)
(add-hook 'minuet-auto-suggestion-mode-hook #'fun-my-special-hook-for-minuet-auto-suggestion-mode)
(defun fun-my-minuet-block-auto-suggest-p ()
(cond
(view-mode
t
)
(buffer-read-only
t
)
((not (buffer-modified-p))
t
)
((equal var-my-buffer-modified-tick 0)
t
)
(t
nil)
)
)
(add-to-list 'minuet-auto-suggestion-block-functions #'fun-my-minuet-block-auto-suggest-p)
;; default provider
(setq minuet-provider 'codestral
minuet-auto-suggestion-throttle-delay 1.2
minuet-auto-suggestion-debounce-delay 0.6
)
;; gemini
(plist-put minuet-gemini-options :model var-my-llm-model-gemini-code-completion)
(plist-put minuet-gemini-options :api-key (fun-my-authinfo-get-entry "gemini" "apikey" t))
(minuet-set-optional-options minuet-gemini-options
:generationConfig
'(:maxOutputTokens 256
:topP 0.9
;; disable thinking for faster completion retrieval.
;; :thinkingConfig (:thinkingBudget 0)
))
(minuet-set-optional-options minuet-gemini-options
:safetySettings
[(:category "HARM_CATEGORY_DANGEROUS_CONTENT"
:threshold "BLOCK_NONE")
(:category "HARM_CATEGORY_HATE_SPEECH"
:threshold "BLOCK_NONE")
(:category "HARM_CATEGORY_HARASSMENT"
:threshold "BLOCK_NONE")
(:category "HARM_CATEGORY_SEXUALLY_EXPLICIT"
:threshold "BLOCK_NONE")])
;; openrouter
(plist-put minuet-openai-compatible-options :end-point "https://openrouter.ai/api/v1/chat/completions")
(plist-put minuet-openai-compatible-options :api-key (fun-my-authinfo-get-entry "openrouter.ai" "apikey" t))
(plist-put minuet-openai-compatible-options :model var-my-llm-model-openrouter-code-completion)
;; optional settings
;; (minuet-set-optional-options minuet-openai-compatible-options :max_tokens 256)
;; (minuet-set-optional-options minuet-openai-compatible-options :top_p 0.9))
;; codestral
(plist-put minuet-codestral-options :api-key (fun-my-authinfo-get-entry "codestral" "apikey" t))
;; optional settings
;; (minuet-set-optional-options minuet-codestral-options :stop ["\n\n"])
;; (minuet-set-optional-options minuet-codestral-options :max_tokens 256)
(defvar var-my-llm-model-expensive (list var-my-llm-model-gemini-code-completion))
(defun fun-my--minute-provider-is-expensive ()
(let* ((provider (symbol-name minuet-provider))
(popts (symbol-value (intern (format "minuet-%s-options" provider))))
)
(if (member (plist-get popts :model) var-my-llm-model-expensive)
t
nil)
)
)
(defun fun-my-special-hook-for-enable-minuet ()
"Do not enable auto suggest mode if using expensive/slow models."
(if (derived-mode-p 'emacs-lisp-mode)
(minuet-auto-suggestion-mode -1)
(if (not (fun-my--minute-provider-is-expensive))
(minuet-auto-suggestion-mode 1)
(minuet-auto-suggestion-mode -1)
(setq-local minuet-request-timeout 10)
)
)
)
(add-hook 'prog-mode-hook #'fun-my-special-hook-for-enable-minuet)