1
0
Fork 0

Merge branch 'translate'

This commit is contained in:
Bram Schoenmakers 2024-01-26 18:02:55 +01:00
commit f9fd1d294a
Signed by: bram
GPG key ID: 0CCD19DFDC63258F
2 changed files with 134 additions and 47 deletions

View file

@ -23,7 +23,10 @@ Both functions are accessed through an [[https://help.kagi.com/kagi/api/overview
** FastGPT
The FastGPT functionality has only one command: =kagi-fastgpt-shell=. This opens a shell buffer in a new window where prompts can be typed. Kagi FastGPT typically returns output based on actual search results. When point is on one of the listed URLs, press =C-c RET= to open it.
- =kagi-fastgpt-shell= :: Opens a shell buffer in a new window where prompts can be typed. This Kagi FastGPT typically returns output based on actual search results. When point is on one of the listed URLs, press =C-c RET= to open it.
- =kagi-fastgpt-prompt= :: Enter a prompt in the minibuffer and show the result in a separate buffer. With a universal prefix (=C-u=), the result is inserted at point.
- =kagi-fastgpt= :: Function to retrieve a FastGPT response, to be used from Lisp code.
- =kagi-translate= :: This command translates strings or complete buffers to another language (including programming languages).
** Universal Summarizer

176
kagi.el
View file

@ -101,42 +101,54 @@ https://help.kagi.com/kagi/api/summarizer.html."
kagi--summarizer-engines))
:group 'kagi)
(defvar kagi--summarizer-languages '(("Document language" . nil)
("Bulgarian [BG]" . "BG")
("Czech [CZ]" . "CZ")
("Danish [DA]" . "DA")
("German [DE]" . "DE")
("Greek [EL]" . "EL")
("English [EN]" . "EN")
("Spanish [ES]" . "ES")
("Estonian [ET]" . "ET")
("Finnish [FI]" . "FI")
("French [FR]" . "FR")
("Hungarian [HU]" . "HU")
("Indonesian [ID]" . "ID")
("Italian [IT]" . "IT")
("Japanese [JA]" . "JA")
("Korean [KO]" . "KO")
("Lithuanian [LT]" . "LT")
("Latvian [LV]" . "LV")
("Norwegian [NB]" . "NB")
("Dutch [NL]" . "NL")
("Polish [PL]" . "PL")
("Portuguese [PT]" . "PT")
("Romanian [RO]" . "RO")
("Russian [RU]" . "RU")
("Slovak [SK]" . "SK")
("Slovenian [SL]" . "SL")
("Swedish [SV]" . "SV")
("Turkish [TR]" . "TR")
("Ukrainian [UK]" . "UK")
("Chinese (simplified) [ZH]" . "ZH"))
(defvar kagi--languages '(("Bulgarian" . "BG")
("Czech" . "CZ")
("Danish" . "DA")
("German" . "DE")
("Greek" . "EL")
("English" . "EN")
("Spanish" . "ES")
("Estonian" . "ET")
("Finnish" . "FI")
("French" . "FR")
("Hungarian" . "HU")
("Indonesian" . "ID")
("Italian" . "IT")
("Japanese" . "JA")
("Korean" . "KO")
("Lithuanian" . "LT")
("Latvian" . "LV")
("Norwegian" . "NB")
("Dutch" . "NL")
("Polish" . "PL")
("Portuguese" . "PT")
("Romanian" . "RO")
("Russian" . "RU")
("Slovak" . "SK")
("Slovenian" . "SL")
("Swedish" . "SV")
("Turkish" . "TR")
("Ukrainian" . "UK")
("Chinese (simplified)" . "ZH"))
"Supported languages by the Kagi LLM.")
(defvar kagi--summarizer-languages (append
'(("Document language" . nil)
kagi--languages))
"Supported languages by the Kagi Universal Summarizer.")
(defvar kagi--language-history nil)
(defcustom kagi-summarizer-default-language nil
"Default target language of the summary."
"Default target language of the summary.
The value should be a string of two characters representing the
language. See variable `kagi--summarizer-languages' for the list
of language codes."
:type (append '(choice)
(mapcar (lambda (lang) `(const :tag ,(car lang) ,(cdr lang)))
(mapcar (lambda (lang)
`(const :tag ,(format "%s [%s]" (car lang) (cdr lang))
,(cdr lang)))
kagi--summarizer-languages))
:group 'kagi)
@ -343,8 +355,7 @@ list of conses."
(defun kagi--display-summary (summary buffer-name)
"Display the SUMMARY in a buffer called BUFFER-NAME."
(with-current-buffer (get-buffer-create buffer-name)
(erase-buffer)
(with-current-buffer (generate-new-buffer-name buffer-name)
(insert summary)
(goto-char 0)
(text-mode)
@ -355,16 +366,23 @@ list of conses."
(save-excursion
(insert (substring-no-properties summary))))
(defun kagi--process-prompt (prompt)
"Submit a PROMPT to FastGPT and process the API response.
Returns a formatted string to be displayed by the shell."
(defun kagi-fastgpt (prompt)
"Submit a PROMPT to FastGPT and return a formatted response string."
(let* ((response (kagi--call-fastgpt prompt))
(parsed-response (json-parse-string response))
(output (kagi--gethash parsed-response "data" "output"))
(references (kagi--gethash parsed-response "data" "references")))
(format "%s\n\n%s" (kagi--format-output output) (kagi--format-references references))))
(defun kagi--fastgpt-display-result (result)
"Display the RESULT of a FastGPT prompt in a new buffer."
(let ((buffer-name (generate-new-buffer-name "*fastgpt-result*")))
(with-current-buffer (get-buffer-create buffer-name)
(save-excursion
(insert result))
(text-mode)
(display-buffer buffer-name))))
(defvar kagi-fastgpt--config
(make-shell-maker-config
:name "FastGPT"
@ -372,7 +390,7 @@ Returns a formatted string to be displayed by the shell."
:execute-command
(lambda (command _history callback error-callback)
(condition-case err
(funcall callback (kagi--process-prompt command) nil)
(funcall callback (kagi-fastgpt-prompt command) nil)
(json-parse-error (funcall error-callback
(format "Could not parse the server response %s" (cdr err))))
(error (funcall error-callback (format "An error occurred during the request %s" (cdr err)))))))
@ -386,6 +404,67 @@ Returns a formatted string to be displayed by the shell."
(interactive)
(shell-maker-start kagi-fastgpt--config))
;;;###autoload
(defun kagi-fastgpt-prompt (prompt &optional insert)
"Feed the given PROMPT to FastGPT.
If INSERT is non-nil, the response is inserted at point.
Otherwise, show the result in a separate buffer."
(interactive "sfastgpt> \nP")
(let ((result (kagi-fastgpt prompt)))
(if (and insert (not buffer-read-only))
(save-excursion
(insert result))
(kagi--fastgpt-display-result result))))
(defun kagi--read-language (prompt)
"Read a language from the minibuffer interactively.
PROMPT is passed to the corresponding parameters of
`completing-read', refer to its documentation for more info."
(completing-read prompt kagi--languages
nil
nil
nil
kagi--language-history
"English"))
(defun kagi-translate (text target-language &optional source-language interactive-p)
"Translate the TEXT to TARGET-LANGUAGE using FastGPT.
With a single universal prefix, also prompt for the SOURCE-LANGUAGE.
When INTERACTIVE-P is nil, the translation is returned as a string.
When non-nil, the translation is shown in the echo area when the
result is short, otherwise it is displayed in a new buffer."
(interactive
(list (if (use-region-p)
(buffer-substring-no-properties (region-beginning) (region-end))
(let ((buffer-or-text (read-buffer (format-prompt "Buffer name or text" nil))))
(cond ((get-buffer buffer-or-text)
(with-current-buffer buffer-or-text
(buffer-string)))
((< 0 (length buffer-or-text)) buffer-or-text)
(t (error "No buffer or text entered")))))
(kagi--read-language (format-prompt "Target language" nil))
(when (equal current-prefix-arg '(4))
(kagi--read-language (format-prompt "Source language" nil)))
t))
(let* ((prompt (format "Translate the following text %sto %s:
%s"
(if source-language
(format "from %s " source-language)
"")
target-language
text))
(result (string-trim (kagi-fastgpt prompt)))
(result-lines (length (string-lines result))))
(cond ((and interactive-p (eql result-lines 1)) (message result))
((and interactive-p (> result-lines 1)) (kagi--fastgpt-display-result result))
(t result))))
;;; Summarizer
(defun kagi--get-domain-name (url)
@ -456,13 +535,18 @@ this when PROMPT-INSERT-P is non-nil."
(y-or-n-p "Insert summary at point?")))
(list
(when (equal current-prefix-arg '(4))
(alist-get
(completing-read (format-prompt "Output language" "")
kagi--summarizer-languages nil t)
kagi--summarizer-languages
(or kagi-summarizer-default-language "EN")
nil
#'string=)))
(let ((language-table (mapcar (lambda (lang)
(cons
(format "%s [%s]" (car lang) (cdr lang))
(cdr lang)))
kagi--summarizer-languages)))
(alist-get
(completing-read (format-prompt "Output language" "")
language-table nil t nil kagi--language-history)
language-table
(or kagi-summarizer-default-language "EN")
nil
#'string=))))
(list
(when (equal current-prefix-arg '(4))
(completing-read (format-prompt "Engine" "")