272 lines
12 KiB
Org Mode
272 lines
12 KiB
Org Mode
#+title: kagi.el README
|
|
#+author: Bram Schoenmakers
|
|
#+macro: issue [[https://codeberg.org/bram85/kagi.el/issues/$1][issue #$1]]
|
|
#+macro: pr [[https://codeberg.org/bram85/kagi.el/pulls/$1][PR #$1]]
|
|
|
|
#+begin_export html
|
|
<a href="https://melpa.org/#/kagi"><img alt="MELPA" src="https://melpa.org/packages/kagi-badge.svg"/></a>
|
|
<a href="https://stable.melpa.org/#/kagi"><img alt="MELPA Stable" src="https://stable.melpa.org/packages/kagi-badge.svg"/></a>
|
|
#+end_export
|
|
|
|
* Introduction
|
|
|
|
This Emacs package provides the following functionalities from the [[https://www.kagi.com][Kagi search engine]]:
|
|
|
|
- FastGPT :: Kagi's open source LLM offering, as a shell inspired by [[https://github.com/xenodium/chatgpt-shell][xenodium's chatgpt-shell]].
|
|
- Universal Summarizer :: Summarizes texts, webpages, videos and more.
|
|
|
|
Both functions are accessed through Kagi's [[https://help.kagi.com/kagi/api/overview.html][APIs]]. Before a call can be made, some setup should be done on the Kagi website (see below).
|
|
|
|
[[file:img/fastgpt.png]]
|
|
|
|
* Commands and functions
|
|
|
|
** FastGPT
|
|
|
|
- =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. This function can also be used from Lisp code.
|
|
|
|
kagi.el has some functions that use FastGPT to perform certain operations on text:
|
|
|
|
- =kagi-translate= :: Translates strings or complete buffers to another language (including programming languages).
|
|
- =kagi-proofread= :: Proofread a string or buffer.
|
|
|
|
** Universal Summarizer
|
|
|
|
- =kagi-summarize-buffer= :: Summarizes the content of a 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= :: 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;
|
|
- choose which summary format to use (prose or bullet list);
|
|
- opt-out from caching at Kagi for confidential content.
|
|
|
|
Note that texts submitted to Kagi are subject to their [[https://kagi.com/privacy#Summarizer][Privacy Policy]].
|
|
|
|
* Installation and configuration
|
|
|
|
kagi.el is available on [[https://melpa.org/#/kagi][MELPA]] and [[https://stable.melpa.org/#/kagi][MELPA Stable]].
|
|
|
|
To install from Git, clone with:
|
|
|
|
: git clone https://codeberg.org/bram85/kagi.el.git /path/to/kagi.el
|
|
|
|
Note that kagi.el has a dependency on the [[https://melpa.org/#/shell-maker][shell-maker package]], which is available on MELPA.
|
|
|
|
You may want to load and configure the package with ~use-package~, for example put the following in your Emacs init file:
|
|
|
|
#+begin_src elisp
|
|
(use-package kagi
|
|
:ensure t
|
|
:custom
|
|
(kagi-api-token "ABCDEF")
|
|
;; or use a function, e.g. with the password-store package:
|
|
(kagi-api-token (lambda () (password-store-get "Kagi/API")))
|
|
|
|
;; Universal Summarizer settings
|
|
(kagi-summarizer-engine "cecil")
|
|
(kagi-summarizer-default-language "EN")
|
|
(kagi-summarizer-cache t)
|
|
:custom-face
|
|
;; kagi-code defaults to fixed-pitch, but can be overridden as
|
|
;; follows:
|
|
(kagi-code ((t (:inherit org-verbatim))))
|
|
|
|
;; likewise for kagi-bold:
|
|
(kagi-bold ((t (:inherit modus-themes-bold)))))
|
|
#+end_src
|
|
|
|
The token can be supplied directly as a string, but you could write a lambda to retrieve the token from a more secure location (e.g. with the combination of [[https://passwordstore.org/][pass(1)]] and the /password-store/ package that comes with it).
|
|
|
|
** Kagi API setup
|
|
|
|
1. Create a Kagi account if you haven't done so already. An account is free, and comes with 100 trial searches.
|
|
2. In [[https://kagi.com/settings?p=billing_api][your account settings]], put a balance for the API part (note that this is a separate balance than the subscription). The recommendation is to start with a one-time charge of $5. Check the pricing for the [[https://help.kagi.com/kagi/api/fastgpt.html#pricing][FastGPT API]] and the [[https://help.kagi.com/kagi/api/summarizer.html#pricing][Summarizer API]] for for the actual costs.
|
|
3. In [[https://kagi.com/settings?p=api][the API portal]], create an API token. Put the result in ~kagi-api-token~ (or write a function to access it securely).
|
|
|
|
** Configuration settings
|
|
|
|
#+begin_src emacs-lisp :exports results :results table :colnames '("Custom variable" "Description")
|
|
(let ((rows))
|
|
(mapatoms
|
|
(lambda (symbol)
|
|
(when (and (string-match "\\_<kagi"
|
|
(symbol-name symbol))
|
|
(custom-variable-p symbol))
|
|
(push `(,symbol
|
|
,(car
|
|
(split-string
|
|
(or (get (indirect-variable symbol)
|
|
'variable-documentation)
|
|
(get symbol 'variable-documentation)
|
|
"")
|
|
"\n")))
|
|
rows))))
|
|
(sort rows (lambda (item1 item2)
|
|
(string< (car item1) (car item2)))))
|
|
#+end_src
|
|
|
|
#+RESULTS:
|
|
| Custom variable | Description |
|
|
|----------------------------------------+---------------------------------------------------------|
|
|
| kagi-api-token | The Kagi API token. |
|
|
| kagi-fastgpt-api-url | The Kagi FastGPT API entry point. |
|
|
| kagi-fastgpt-prompts | Prompts to choose for a buffer, text or region. |
|
|
| kagi-summarizer-api-url | The Kagi Summarizer API entry point. |
|
|
| kagi-summarizer-cache | Determines whether the Summarizer should cache results. |
|
|
| kagi-summarizer-default-language | Default target language of the summary. |
|
|
| kagi-summarizer-default-summary-format | The summary format that should be returned. |
|
|
| kagi-summarizer-engine | Which summary engine to use. |
|
|
|
|
*** COMMENT Attribution :noexport:
|
|
|
|
The code to generate the table of configuration items was inspired by an idea of [[https://xenodium.com/generating-elisp-org-docs/][Álvaro Ramírez]] (a.k.a. xenodium).
|
|
|
|
** Embark integration
|
|
|
|
The kagi.el package can be integrated with [[https://github.com/oantolin/embark][Embark]]. Use it to easily summarize, translate or proofread a buffer, region or a URL. In order to be consistent with all keymaps, and to avoid clashes, the functionality is behind the /K/ prefix key. For example, press /K s/ to invoke the summarize functionality.
|
|
|
|
#+begin_src elisp
|
|
(defmacro embark-kagi-map (name &rest keys)
|
|
"Macro for defining a keymap for accessing Kagi functionality through Embark."
|
|
`(defvar-keymap ,name
|
|
:doc "Keymap for accessing Kagi functionality with Embark."
|
|
:parent nil
|
|
,@keys))
|
|
|
|
(embark-kagi-map embark-kagi-buffer-map
|
|
"p" #'kagi-proofread
|
|
"s" #'kagi-summarize-buffer
|
|
"t" #'kagi-translate)
|
|
(keymap-set embark-buffer-map "K" embark-kagi-buffer-map)
|
|
|
|
(embark-kagi-map embark-kagi-region-map
|
|
"p" #'kagi-proofread
|
|
"s" #'kagi-summarize-region
|
|
"t" #'kagi-translate)
|
|
(keymap-set embark-region-map "K" embark-kagi-region-map)
|
|
|
|
(embark-kagi-map embark-kagi-url-map
|
|
"s" #'kagi-summarize-url)
|
|
(keymap-set embark-url-map "K" embark-kagi-url-map)
|
|
#+end_src
|
|
|
|
** Key bindings
|
|
|
|
Since the FastGPT shell inherits from =comint-mode= indirectly, many key bindings are also inherited. Enter the =help= command in the shell to get more info, or run =describe-keymap= on =fastgpt-shell-mode-map=.
|
|
|
|
One of those bindings is =C-c C-o=, which flushes the last output. However, this binding is used in =org-mode= to open a URL an point. Typical FastGPT results include URLs so one may be tempted to type =C-c C-o= to browse the URL, only to have the output erased.
|
|
|
|
If you recognize this confusion, you may want to add the following line to your configuration file to shadow the =comint-mode= binding with something more appropriate:
|
|
|
|
#+begin_src elisp
|
|
(add-hook 'fastgpt-shell-mode-hook
|
|
(lambda ()
|
|
(keymap-set fastgpt-shell-mode-map "C-c C-o" #'browse-url-at-point)))
|
|
#+end_src
|
|
|
|
Because the =fastgpt-shell-mode-map= only becomes available when =kagi-fastgpt-shell= has been invoked, the keybinding is done in a mode hook.
|
|
|
|
* Development
|
|
|
|
kagi.el comes with some unit tests, written with [[https://github.com/jorgenschaefer/emacs-buttercup/][buttercup]] and can be executed in a controlled [[https://github.com/cask/cask/][Cask]] environment:
|
|
|
|
1. =git clone https://github.com/cask/cask/=
|
|
2. =make -C cask install=
|
|
3. Run =cask= in the kagi.el directory to setup the environment.
|
|
4. Run the tests with =cask exec buttercup -L .=
|
|
|
|
There's also a [[https://github.com/casey/just][justfile]] which allows you to execute =just test= to compile the Emacs Lisp source and run the unit tests afterwards in one go.
|
|
|
|
* Changelog
|
|
|
|
** 0.5pre
|
|
|
|
*** New
|
|
|
|
- =kagi-summarize= has a =no-cache= parameter to opt out from caching at Kagi's side.
|
|
|
|
- =kagi-summarize-buffer= and =kagi-summarize-region= also have a =no-cache= parameter which can be toggled interactively when called with the universal prefix.
|
|
|
|
** 0.4
|
|
|
|
*** Breaking changes
|
|
|
|
- Obsoleted function =kagi-fastgpt= in favor of =kagi-fastgpt-prompt=. To be removed in a next release.
|
|
|
|
*** New
|
|
|
|
- Introduce variable =kagi-summarizer-default-summary-format=, to produce a paragraph summary (default) or a take-away in bullet-list format.
|
|
|
|
- =kagi-proofread= asks FastGPT to proofread the region, a buffer or a text input.
|
|
|
|
- =kagi-summarize-buffer= returns the summary when called non-interactively.
|
|
|
|
- Unit tests added.
|
|
|
|
*** Fixes
|
|
|
|
- Change the prompt for =kagi-translate= to return translations only, without preamble.
|
|
- Added autoload markers where they were missing.
|
|
- Language selection menu for summaries was not formatted properly.
|
|
|
|
** 0.3.1 :noexport:
|
|
|
|
*** Fixes
|
|
|
|
- Fix for displaying a summary in a new buffer.
|
|
- Fix for =kagi-summarize-region= that doesn't need to ask for insert at point.
|
|
|
|
** 0.3 :noexport:
|
|
|
|
*** 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.
|
|
|
|
- =kagi-translate= translates texts or complete buffers to another language (including programming languages).
|
|
|
|
*** Fixes
|
|
|
|
- Fixed language code for Korean summaries.
|
|
- **text** is converted to the =kagi-bold= face.
|
|
- $text$ is converted to the new =kagi-italic= face.
|
|
|
|
** 0.2 :noexport:
|
|
|
|
*** Breaking changes
|
|
|
|
- Some variables were renamed for consistency. The impact is considered low given the infancy of the package, and API URLs are typically not modified anyway.
|
|
|
|
| Old name | New name |
|
|
|---------------------------------+------------------------------------|
|
|
| =kagi-api-fastgpt-url= | =kagi-fastgpt-api-url= |
|
|
| =kagi-api-summarizer-url= | =kagi-summarizer-api-url= |
|
|
| =kagi-summarize-default-language= | =kagi-summarizer-default-language= |
|
|
|
|
*** Fixes
|
|
|
|
- Better error handling for the summarizer
|
|
- Fix bug when the summarizer input contains a URL ({{{issue(2)}}})
|
|
- Check that the summarizer input is at least 50 words ({{{issue(2)}}})
|
|
|
|
*** Misc
|
|
|
|
- Add boolean variable =kagi-stubbed-responses= to enable stubbed responses, to replace actual API calls. Since calls are metered, it's more economic to use stubbed responses for development / debugging purposes.
|
|
|
|
** 0.1 :noexport:
|
|
|
|
Initial release.
|
|
|
|
* References
|
|
|
|
- [[https://help.kagi.com/kagi/api/fastgpt.html][Kagi FastGPT API]]
|
|
- [[https://help.kagi.com/kagi/api/summarizer.html][Kagi Universal Summarizer API]]
|
|
- [[https://github.com/xenodium/chatgpt-shell][xenodium's chatgpt-shell]], which also provides shell-maker required by the FastGPT shell.
|