大家好, 在 @carlos-wong 的启发下, 改写了一个chatgpt.el的插件, GitHub - gfgkmn/ChatGPT.el: ChatGPT in Emacs 实现了一些流式输入的功能, 和对日志的保存, 本来只是自己用, 所以没有考虑和他的代码的一致性和对齐的问题. 先感谢并致歉.
现在功能算是还不错, 平时用起来也非常顺手,
但是有一个问题, 目前这个库支持流式输出(carlos-wrong的想法)和并行的一次性输入(最初原作者的实现), 我基本都喜欢流式输出, 有时不需要一次回复完成, 就可以进入下一步操作了.
但是流式输出有一个问题, 就是它会占用光标, 在模型输出的时候, 我就算看到答案已经出来了, 不需要再等了, 也必须等gpt buffer的光标出完, 才能到主buffer中进行处理.
有没有什么办法, 可以让这两个进程完全并行化, 就是一边流式的在gpt buffer产生内容, 一边在主buffer中, 我仍然可以控制光标进行各种操作.
下面是相关的函数.
(defun chatgpt--query-stream (query use-model &optional recursive)
(unless chatgpt-process
(chatgpt-init))
(chatgpt-display)
(lexical-let ((saved-id (if recursive
chatgpt-id
(cl-incf chatgpt-id)))
(query (if recursive
(string-join (nthcdr 1 (split-string query "-")) "-")
query))
(query_with_id (if recursive
query
(format "%s-%s" (org-id-uuid) query)))
(recursive-model use-model))
(if recursive
(setq next-recursive recursive)
(progn
(setq next-recursive nil)
(chatgpt--insert-query query saved-id)))
(deferred:$
(deferred:$
(epc:call-deferred chatgpt-process 'querystream (list query_with_id recursive-model))
(deferred:nextc it
#'(lambda (response)
(with-current-buffer (chatgpt-get-output-buffer-name)
(save-excursion
(if (numberp next-recursive)
(goto-char next-recursive)
(chatgpt--goto-identifier chatgpt-id))
(if (and (stringp response))
(progn
(insert response)
(chatgpt--query-stream query_with_id recursive-model (point)))
(progn
(insert (format "\n\n%s"
(make-string (chatgpt-get-buffer-width-by-char ?=) ?=))))))
(let ((output-window (get-buffer-window (current-buffer))))
(when output-window
(with-selected-window output-window
(goto-char (point-max))
(recenter -1))))))))
(deferred:error it
`(lambda (err)
(message "err is:%s" err))))))
欢迎各位大佬不吝赐教