Merge branch 'interactive-lang-engine-choice'
This commit is contained in:
commit
f054879d37
2 changed files with 200 additions and 75 deletions
23
README.org
23
README.org
|
@ -27,11 +27,16 @@ The FastGPT functionality has only one command: =kagi-fastgpt-shell=. This opens
|
||||||
|
|
||||||
** Universal Summarizer
|
** Universal Summarizer
|
||||||
|
|
||||||
- =kagi-summarize-buffer= :: Summarizes the content of a buffer and displays it in a separate buffer.
|
- =kagi-summarize-buffer= :: Summarizes the content of a buffer.
|
||||||
- =kagi-summarize-region= :: Similarly, the text inside the region is summarized and shown in a separate buffer.
|
- =kagi-summarize-region= :: Similarly, the text inside the region is summarized.
|
||||||
- =kagi-summarize-url= :: Prompts for a URL of which a summary is composed and displayed.
|
- =kagi-summarize-url= :: Prompts for a URL of which a summary is composed and displayed.
|
||||||
- =kagi-summarize= :: Function to retrieve a summary from a text or URL, to be used from Lisp code.
|
- =kagi-summarize= :: Function to retrieve a summary from a text or URL, to be used from Lisp code.
|
||||||
|
|
||||||
|
The summarize commands accept a single universal prefix, which allows you to:
|
||||||
|
- insert the summary at point;
|
||||||
|
- choose a (different) target language;
|
||||||
|
- choose which summary engine to use.
|
||||||
|
|
||||||
Note that texts submitted to Kagi are subject to their [[https://kagi.com/privacy#Summarizer][Privacy Policy]].
|
Note that texts submitted to Kagi are subject to their [[https://kagi.com/privacy#Summarizer][Privacy Policy]].
|
||||||
|
|
||||||
* Installation and configuration
|
* Installation and configuration
|
||||||
|
@ -116,6 +121,8 @@ The code to generate the table of configuration items was inspired by an idea of
|
||||||
|
|
||||||
** Examples of custom functions
|
** Examples of custom functions
|
||||||
|
|
||||||
|
The =kagi-summarize= function allows you to summarize texts or URLs from Emacs Lisp.
|
||||||
|
|
||||||
By overriding a variable with a =let= construct you can (temporarily) deviate from the default / configured value. A few examples are shown below:
|
By overriding a variable with a =let= construct you can (temporarily) deviate from the default / configured value. A few examples are shown below:
|
||||||
|
|
||||||
*** Language override
|
*** Language override
|
||||||
|
@ -129,6 +136,8 @@ To obtain a Dutch summary of a video you may want to define the following functi
|
||||||
(kagi-summarize text-or-url)))
|
(kagi-summarize text-or-url)))
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
|
Note that, when you invoke the summarizer functionality interactively, you can also temporarily choose a different target language with the universal prefix (=C-u=) on one of the =kagi-summarize-*= commands.
|
||||||
|
|
||||||
*** Caching override
|
*** Caching override
|
||||||
|
|
||||||
The [[https://help.kagi.com/kagi/api/summarizer.html][Summarizer API]] comes with the following note:
|
The [[https://help.kagi.com/kagi/api/summarizer.html][Summarizer API]] comes with the following note:
|
||||||
|
@ -184,6 +193,16 @@ If you recognize this confusion, you may want to add the following line to your
|
||||||
|
|
||||||
* Changelog
|
* Changelog
|
||||||
|
|
||||||
|
** 0.3pre
|
||||||
|
|
||||||
|
*** New
|
||||||
|
|
||||||
|
The summarizer commands =kagi-summarize-*= now accept a universal prefix. This allows you to:
|
||||||
|
|
||||||
|
- insert the summary at point (instead of a separate buffer);
|
||||||
|
- choose a different target language;
|
||||||
|
- choose a different summarizer engine.
|
||||||
|
|
||||||
** 0.2
|
** 0.2
|
||||||
|
|
||||||
*** Breaking changes
|
*** Breaking changes
|
||||||
|
|
228
kagi.el
228
kagi.el
|
@ -81,57 +81,63 @@ on dummy data."
|
||||||
:type '(choice string function)
|
:type '(choice string function)
|
||||||
:group 'kagi)
|
:group 'kagi)
|
||||||
|
|
||||||
|
(defvar kagi--summarizer-engines
|
||||||
|
'(("agnes" . "Friendly, descriptive, fast summary.")
|
||||||
|
("cecil" . "Formal, technical, analytical summary.")
|
||||||
|
("daphne" . "Informal, creative, friendly summary.")
|
||||||
|
("muriel" . "Best-in-class summary using Kagi's enterprise-grade model (at different pricing)."))
|
||||||
|
"List of Kagi Summarizer engines.
|
||||||
|
|
||||||
|
See `kagi-summarizer-engine' for a brief description per engine.")
|
||||||
|
|
||||||
(defcustom kagi-summarizer-engine "cecil"
|
(defcustom kagi-summarizer-engine "cecil"
|
||||||
"Which summary engine to use.
|
"Which summary engine to use.
|
||||||
|
|
||||||
- cecil :: Friendly, descriptive, fast summary.
|
|
||||||
- agnes :: Formal, technical, analytical summary.
|
|
||||||
- daphne :: Informal, creative, friendly summary.
|
|
||||||
- muriel :: Best-in-class summary using Kagi's enterprise-grade model.
|
|
||||||
|
|
||||||
Note that the muriel model is enterprise grade and has different
|
Note that the muriel model is enterprise grade and has different
|
||||||
pricing. Refer to the API documentation for more info at
|
pricing. Refer to the API documentation for more info at
|
||||||
https://help.kagi.com/kagi/api/summarizer.html."
|
https://help.kagi.com/kagi/api/summarizer.html."
|
||||||
:type '(choice
|
:type (append '(choice)
|
||||||
(const "agnes")
|
(mapcar (lambda (engine) `(const :doc ,(cdr engine) ,(car engine)))
|
||||||
(const "cecil")
|
kagi--summarizer-engines))
|
||||||
(const "daphne")
|
|
||||||
(const "muriel"))
|
|
||||||
:group 'kagi)
|
: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]" . "KA")
|
||||||
|
("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"))
|
||||||
|
"Supported languages by the Kagi Universal Summarizer.")
|
||||||
|
|
||||||
(defcustom kagi-summarizer-default-language nil
|
(defcustom kagi-summarizer-default-language nil
|
||||||
"Default target language of the summary."
|
"Default target language of the summary."
|
||||||
:type '(choice
|
:type (append '(choice)
|
||||||
(const :tag "Document language" nil)
|
(mapcar (lambda (lang) `(const :tag ,(car lang) ,(cdr lang)))
|
||||||
(const :tag "Bulgarian" "BG")
|
kagi--summarizer-languages))
|
||||||
(const :tag "Czech" "CZ")
|
|
||||||
(const :tag "Danish" "DA")
|
|
||||||
(const :tag "German" "DE")
|
|
||||||
(const :tag "Greek" "EL")
|
|
||||||
(const :tag "English" "EN")
|
|
||||||
(const :tag "Spanish" "ES")
|
|
||||||
(const :tag "Estonian" "ET")
|
|
||||||
(const :tag "Finnish" "FI")
|
|
||||||
(const :tag "French" "FR")
|
|
||||||
(const :tag "Hungarian" "HU")
|
|
||||||
(const :tag "Indonesian" "ID")
|
|
||||||
(const :tag "Italian" "IT")
|
|
||||||
(const :tag "Japanese" "JA")
|
|
||||||
(const :tag "Korean" "KO")
|
|
||||||
(const :tag "Lithuanian" "LT")
|
|
||||||
(const :tag "Latvian" "LV")
|
|
||||||
(const :tag "Norwegian" "NB")
|
|
||||||
(const :tag "Dutch" "NL")
|
|
||||||
(const :tag "Polish" "PL")
|
|
||||||
(const :tag "Portuguese" "PT")
|
|
||||||
(const :tag "Romanian" "RO")
|
|
||||||
(const :tag "Russian" "RU")
|
|
||||||
(const :tag "Slovak" "SK")
|
|
||||||
(const :tag "Slovenian" "SL")
|
|
||||||
(const :tag "Swedish" "SV")
|
|
||||||
(const :tag "Turkish" "TR")
|
|
||||||
(const :tag "Ukrainian" "UK")
|
|
||||||
(const :tag "Chinese (simplified)" "ZH"))
|
|
||||||
:group 'kagi)
|
:group 'kagi)
|
||||||
|
|
||||||
(defcustom kagi-summarizer-cache t
|
(defcustom kagi-summarizer-cache t
|
||||||
|
@ -307,7 +313,6 @@ list of conses."
|
||||||
(when kagi-summarizer-default-language
|
(when kagi-summarizer-default-language
|
||||||
`(("target_language" . ,kagi-summarizer-default-language)))))
|
`(("target_language" . ,kagi-summarizer-default-language)))))
|
||||||
|
|
||||||
|
|
||||||
(defconst kagi--summarizer-min-input-words 50
|
(defconst kagi--summarizer-min-input-words 50
|
||||||
"The minimal amount of words that the text input should have.")
|
"The minimal amount of words that the text input should have.")
|
||||||
|
|
||||||
|
@ -339,6 +344,11 @@ list of conses."
|
||||||
(text-mode)
|
(text-mode)
|
||||||
(display-buffer buffer-name)))
|
(display-buffer buffer-name)))
|
||||||
|
|
||||||
|
(defun kagi--insert-summary (summary)
|
||||||
|
"Insert the SUMMARY at point."
|
||||||
|
(save-excursion
|
||||||
|
(insert (substring-no-properties summary))))
|
||||||
|
|
||||||
(defun kagi--process-prompt (prompt)
|
(defun kagi--process-prompt (prompt)
|
||||||
"Submit a PROMPT to FastGPT and process the API response.
|
"Submit a PROMPT to FastGPT and process the API response.
|
||||||
|
|
||||||
|
@ -397,8 +407,20 @@ Returns a formatted string to be displayed by the shell."
|
||||||
(string-match-p (rx (seq bos "http" (? "s") "://" (+ (not space)) eos)) s))
|
(string-match-p (rx (seq bos "http" (? "s") "://" (+ (not space)) eos)) s))
|
||||||
|
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(defun kagi-summarize (text-or-url)
|
(defun kagi-summarize (text-or-url &optional language engine)
|
||||||
"Return the summary of the given TEXT-OR-URL."
|
"Return the summary of the given TEXT-OR-URL.
|
||||||
|
|
||||||
|
LANGUAGE is a supported two letter abbreviation of the language,
|
||||||
|
as defined in `kagi--summarizer-languages'. When nil, the target
|
||||||
|
is automatically determined.
|
||||||
|
|
||||||
|
ENGINE is the name of a supported summarizer engine, as
|
||||||
|
defined in `kagi--summarizer-engines'."
|
||||||
|
|
||||||
|
(let* ((kagi-summarizer-default-language
|
||||||
|
(upcase (or language kagi-summarizer-default-language)))
|
||||||
|
(kagi-summarizer-engine
|
||||||
|
(downcase (or engine kagi-summarizer-engine))))
|
||||||
(if-let* ((response (if (kagi--url-p text-or-url)
|
(if-let* ((response (if (kagi--url-p text-or-url)
|
||||||
(kagi--call-url-summarizer text-or-url)
|
(kagi--call-url-summarizer text-or-url)
|
||||||
(kagi--call-text-summarizer text-or-url)))
|
(kagi--call-text-summarizer text-or-url)))
|
||||||
|
@ -409,33 +431,111 @@ Returns a formatted string to be displayed by the shell."
|
||||||
(error (format "%s (%s)"
|
(error (format "%s (%s)"
|
||||||
(gethash "msg" firsterror)
|
(gethash "msg" firsterror)
|
||||||
(gethash "code" firsterror)))
|
(gethash "code" firsterror)))
|
||||||
(error "An error occurred while requesting a summary"))))
|
(error "An error occurred while requesting a summary")))))
|
||||||
|
|
||||||
|
(defun kagi--get-summarizer-parameters (&optional prompt-insert-p)
|
||||||
|
"Return a list of interactively obtained summarizer parameters.
|
||||||
|
|
||||||
|
Not all commands need to insert a summary, so only prompt for
|
||||||
|
this when PROMPT-INSERT-P is non-nil."
|
||||||
|
(append
|
||||||
|
(list
|
||||||
|
(and prompt-insert-p
|
||||||
|
(equal current-prefix-arg '(4))
|
||||||
|
(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=)))
|
||||||
|
(list
|
||||||
|
(when (equal current-prefix-arg '(4))
|
||||||
|
(completing-read (format-prompt "Engine" "")
|
||||||
|
kagi--summarizer-engines nil t kagi-summarizer-engine)))))
|
||||||
|
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(defun kagi-summarize-buffer (buffer)
|
(defun kagi-summarize-buffer (buffer &optional insert language engine)
|
||||||
"Summarize the BUFFER's content and show it in a new window."
|
"Summarize the BUFFER's content and show it in a new window.
|
||||||
(interactive "b")
|
|
||||||
(with-current-buffer buffer
|
By default, the summary is shown in a new buffer.
|
||||||
(kagi--display-summary
|
|
||||||
(kagi-summarize (buffer-string))
|
When INSERT is non-nil, the summary will be inserted at point. In
|
||||||
|
case the current buffer is read-only, the summary will be shown
|
||||||
|
in a separate buffer anyway.
|
||||||
|
|
||||||
|
LANGUAGE is a supported two letter abbreviation of the language,
|
||||||
|
as defined in `kagi--summarizer-languages'. When nil, the target
|
||||||
|
is automatically determined.
|
||||||
|
|
||||||
|
ENGINE is the name of a supported summarizer engine, as
|
||||||
|
defined in `kagi--summarizer-engines'.
|
||||||
|
|
||||||
|
With a single universal prefix argument (`C-u'), the user is
|
||||||
|
prompted whether the summary has to be inserted at point, which
|
||||||
|
target LANGUAGE to use and which summarizer ENGINE to use."
|
||||||
|
(interactive (cons
|
||||||
|
(read-buffer (format-prompt "Buffer" "") nil t)
|
||||||
|
(kagi--get-summarizer-parameters t)))
|
||||||
|
(let ((summary (with-current-buffer buffer
|
||||||
|
(kagi-summarize (buffer-string) language engine)))
|
||||||
|
(summary-buffer-name (with-current-buffer buffer
|
||||||
(kagi--summary-buffer-name (buffer-name)))))
|
(kagi--summary-buffer-name (buffer-name)))))
|
||||||
|
(if (and insert (not buffer-read-only))
|
||||||
|
(kagi--insert-summary summary)
|
||||||
|
(kagi--display-summary summary summary-buffer-name))))
|
||||||
|
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(defun kagi-summarize-region (begin end)
|
(defun kagi-summarize-region (begin end &optional language engine)
|
||||||
"Summarize the region's content marked by BEGIN and END positions.
|
"Summarize the region's content marked by BEGIN and END positions.
|
||||||
|
|
||||||
Shows the summary in a new window."
|
The summary is always shown in a new buffer.
|
||||||
(interactive "r")
|
|
||||||
|
LANGUAGE is a supported two letter abbreviation of the language,
|
||||||
|
as defined in `kagi--summarizer-languages'. When nil, the target
|
||||||
|
is automatically determined.
|
||||||
|
|
||||||
|
ENGINE is the name of a supported summarizer engine, as
|
||||||
|
defined in `kagi--summarizer-engines'.
|
||||||
|
|
||||||
|
With a single universal prefix argument (`C-u'), the user is
|
||||||
|
prompted for which target LANGUAGE to use and which summarizer
|
||||||
|
ENGINE to use."
|
||||||
|
(interactive (append
|
||||||
|
(list (region-beginning) (region-end))
|
||||||
|
(kagi--get-summarizer-parameters)))
|
||||||
(kagi--display-summary
|
(kagi--display-summary
|
||||||
(kagi-summarize (buffer-substring-no-properties begin end))
|
(kagi-summarize (buffer-substring-no-properties begin end)
|
||||||
|
language
|
||||||
|
engine)
|
||||||
(kagi--summary-buffer-name (buffer-name))))
|
(kagi--summary-buffer-name (buffer-name))))
|
||||||
|
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(defun kagi-summarize-url (url)
|
(defun kagi-summarize-url (url &optional insert language engine)
|
||||||
"Show the summary of the content behind the given URL.
|
"Show the summary of the content behind the given URL.
|
||||||
|
|
||||||
According to the API documentation, the following media types are
|
By default, the summary is shown in a new buffer.
|
||||||
supported:
|
|
||||||
|
When INSERT is non-nil, the summary will be inserted at point. In
|
||||||
|
case the current buffer is read-only, the summary will be shown
|
||||||
|
in a separate buffer anyway.
|
||||||
|
|
||||||
|
LANGUAGE is a supported two letter abbreviation of the language,
|
||||||
|
as defined in `kagi--summarizer-languages'. When nil, the target
|
||||||
|
is automatically determined.
|
||||||
|
|
||||||
|
ENGINE is the name of a supported summarizer engine, as
|
||||||
|
defined in `kagi--summarizer-engines'.
|
||||||
|
|
||||||
|
With a single universal prefix argument (`C-u'), the user is
|
||||||
|
prompted whether the summary has to be inserted at point, which
|
||||||
|
target LANGUAGE to use and which summarizer ENGINE to use.
|
||||||
|
|
||||||
|
According to the Kagi API documentation, the following media
|
||||||
|
types are supported:
|
||||||
|
|
||||||
- Text web pages, articles, and forum threads
|
- Text web pages, articles, and forum threads
|
||||||
- PDF documents (.pdf)
|
- PDF documents (.pdf)
|
||||||
|
@ -444,10 +544,16 @@ supported:
|
||||||
- Audio files (mp3/wav)
|
- Audio files (mp3/wav)
|
||||||
- YouTube URLs
|
- YouTube URLs
|
||||||
- Scanned PDFs and images (OCR)"
|
- Scanned PDFs and images (OCR)"
|
||||||
(interactive "sURL: ")
|
(interactive
|
||||||
|
(cons
|
||||||
|
(read-string (format-prompt "URL" ""))
|
||||||
|
(kagi--get-summarizer-parameters t)))
|
||||||
|
(let ((summary (kagi-summarize url language engine)))
|
||||||
|
(if (and insert (not buffer-read-only))
|
||||||
|
(kagi--insert-summary summary)
|
||||||
(kagi--display-summary
|
(kagi--display-summary
|
||||||
(kagi-summarize url)
|
summary
|
||||||
(kagi--summary-buffer-name (kagi--get-domain-name url))))
|
(kagi--summary-buffer-name (kagi--get-domain-name url))))))
|
||||||
|
|
||||||
(provide 'kagi)
|
(provide 'kagi)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue