我通过参考https://emacs-china.org/t/tabnine/9988/40自己实现了一下,你可以稍微改改。
现在的效果是:前5个为company-tabnine按概率排序补全结果,后3个为company-ctags补全结果,最后2个为company-yasnippet补全结果。 现在有一个不足是:会忽略company-tabnine补全结果中detail值为空的项。

(defun company-tabnine-sort-by-detail (candidates)
"Sort tabnine response by detail value"
(sort candidates
(lambda (c1 c2)
(let ((d1 (get-text-property 0 'detail c1))
(d2 (get-text-property 0 'detail c2)))
;; 默认忽略type
(or d1 (setq d1 "1%"))
(or d2 (setq d2 "1%"))
(>= (string-to-number d1) (string-to-number d2))))))
(defun company-sort-by-tabnine-and-ctags (candidates)
"sort company backends response"
(when (or (functionp company-backend)
(not (and (listp company-backend)
(memq 'company-tabnine company-backend))))
candidates)
(let (candidates-tabnine candidates-ctags candidates-yas)
(setq candidates-max-length (min (length candidates) 20))
(dolist (candidate candidates)
(setq backend-property (get-text-property 0 'company-backend candidate))
(cond
((eq backend-property 'company-ctags)
(push candidate candidates-ctags))
((eq backend-property 'company-yasnippet)
(push candidate candidates-yas))
(t (push candidate candidates-tabnine))))
;; (setq candidates-tabnine (nreverse candidates-tabnine))
(setq candidates-tabnine (company-tabnine-sort-by-detail candidates-tabnine))
(setq candidates-ctags (nreverse candidates-ctags))
(setq candidates-yas (nreverse candidates-yas))
(setq candidates (nconc (seq-take candidates-tabnine 5)
(seq-take candidates-ctags 3)
(seq-take candidates-yas 2)))
(setq candidates-other (nconc (seq-drop candidates-tabnine 5)
(seq-drop candidates-ctags 3)
(seq-drop candidates-yas 2)))
(let ((len (length candidates)))
(when (< len candidates-max-length)
(setq candidates (nconc candidates (seq-take candidates-other (- candidates-max-length len))))))
candidates))
;; (add-to-list 'company-transformers 'company-sort-by-tabnine-and-ctags t)
;; (add-to-list 'company-backends '(company-tabnine :separate company-etags))