遇到一个困扰我好几天的问题,使用百度千帆大模型 API 时,用 url-retrieve
结合 after-change-functions
异步处理输出数据,但是中途的输出总是夹杂着奇怪的输出,比如下图中的 1f9
等等,最诡异的是最终的输出却又没了,实在不明白是怎么回事儿。
(defun qianfan-handle-new-content (_ _ old-len)
(when (= old-len 0)
(message "%S"
(decode-coding-string
(buffer-substring-no-properties (point-min) (point-max))
'utf-8))))
(defun qianfan (question)
(interactive "s千帆大模型: ")
(let ((user-buffer (current-buffer)))
(let ((url-request-method "POST")
(url-request-extra-headers '(("Content-Type" . "application/json")))
(url-request-data (encode-coding-string
(json-serialize
`((stream . t)
(messages . [((role . "user")
(content . ,question))])))
'utf-8)))
(with-current-buffer
(url-retrieve
(concat "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/eb-instant?access_token="
"24.b2ecc710a1d00bc3b6bba3f8b90a2a7b.2592000.1708426726.282335-47373095")
(lambda (_)
(remove-hook 'after-change-functions #'qianfan-handle-new-content t))
nil t t)
(add-hook 'after-change-functions #'qianfan-handle-new-content nil t)
(setq qianfan-handle-response
(lambda (json)
(with-current-buffer user-buffer
(let-alist json
(insert .result)))))
(pop-to-buffer-same-window (current-buffer))))))
下面是 curl 输出,方便对照 SSE 的输出格式。可以用我的 Token 测试,过一段时间后我会重置。
➜ ~ curl --json '{"stream": true, "messages":[{"role":"user","content":"请介绍下你自己"}]}' \
'https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/eb-instant?access_token=24.f4b93675c21a394307adb62a97ef8ff9.2592000.1708174840.282335-47373095'
data: {"id":"as-tktpbea4f7","object":"chat.completion","created":1705838053,"sentence_id":0,"is_end":false,"is_truncated":false,"result":"嗨,","need_clear_history":false,"usage":{"prompt_tokens":4,"completion_tokens":0,"total_tokens":4}}
data: {"id":"as-tktpbea4f7","object":"chat.completion","created":1705838053,"sentence_id":1,"is_end":false,"is_truncated":false,"result":"我是百度公司的人工智能语言模型,我叫文心一言。","need_clear_history":false,"usage":{"prompt_tokens":4,"completion_tokens":0,"total_tokens":4}}
data: {"id":"as-tktpbea4f7","object":"chat.completion","created":1705838053,"sentence_id":2,"is_end":false,"is_truncated":false,"result":"我非常善于介绍自己,我的功能就是和用户进行自然、流畅的对话交流,提供帮助和信息,以及回答各种类型的问题。","need_clear_history":false,"usage":{"prompt_tokens":4,"completion_tokens":46,"total_tokens":50}}
data: {"id":"as-tktpbea4f7","object":"chat.completion","created":1705838054,"sentence_id":3,"is_end":false,"is_truncated":false,"result":"无论您有什么需要,都可以向我提问,我很乐意为您解答。","need_clear_history":false,"usage":{"prompt_tokens":4,"completion_tokens":46,"total_tokens":50}}
data: {"id":"as-tktpbea4f7","object":"chat.completion","created":1705838054,"sentence_id":4,"is_end":true,"is_truncated":false,"result":"","need_clear_history":false,"usage":{"prompt_tokens":4,"completion_tokens":59,"total_tokens":63}}
我可以确定百度的 API 是正常的。我对 url.el 的印象一直就不太好,总觉得不大靠谱,不知道是不是我有啥没注意到,因为我试用过 llm.el + OpenAI,它是正常的,我的思路就是来自于此。