This is a tutorial for how to use pen.el
.
The following command starts pen.el
. You
only need to have docker installed and an
OpenAI GPT-3
key to try this out.
docker run --rm -ti --entrypoint= semiosis/pen.el:latest ./run.sh
# And to update the image
docker pull semiosis/pen.el:latest
# For windows
docker.exe run --rm -ti --entrypoint= semiosis/pen.el:latest ./run.sh
# You may need winpty
git clone https://github.com/rprichard/winpty
winpty docker.exe run --rm -ti --entrypoint= semiosis/pen.el:latest ./run.sh
- Project code
- https://github.com/semiosis/pen.el/
- Join discord
- https://discord.gg/JwKGbAdNHR
For GPT-neo
, GPT-2
and booste
support,
and latest updates, please install from master
branch. Docker support coming. GPT-j
also in
the works.
These are enabled by default with the docker image.
kb | |
---|---|
Alt-p | Open the prompts directory in dired |
Alt-t | Start writing in an empty file |
Alt-s | Save file |
Alt-r | Running a prompt function like this will not insert text or replace it. |
Alt-TAB | This completes the current line. |
Alt-l (little L) | Multiline (long) completion. |
Alt-g | This reloads the prompt functions. |
Alt-m | Right click menu |
Select text then Alt-f | This filters the text through a prompt function specifically designed for this. |
Spacebar | When text is selected, will run with that text as first argument. |
kb | f | |
---|---|---|
H-. | global-pen-acolyte-minor-mode | This toggles Acolyte mode. |
H-TAB g | pen-generate-prompt-functions | This reloads the prompt functions. |
H-TAB r | pen-run-prompt-function | Running a prompt function like this will not insert text or replace it. |
M-1 | pen-company-filetype | This completes the current line. |
H-TAB s | pen-filter-with-prompt-function | This filters the text through a prompt function specifically designed for this. |
H-TAB c | pen-company-complete | Select a prompt function as the completer for company-mode and complete with it. |
SPC | pen-run-prompt-function | When text is selected, will run with that text as first argument. |
H-TAB l | pen-complete-long | This is a multiline completion. |
H
is the Hyper key, which works similar to Escape, Meta, Alt, Control or Shift that is present on the Space Cadet Keyboard.
pen.el
emulates a Hyper key (H-
) with C-M-\
.
I like Hyper
because you’re writing hyperreality
.
hyperreality
[#semiotics]
[#postmodernism]
An inability of consciousness to
distinguish reality from a simulation of
reality, especially in technologically
advanced postmodern societies.
- Imagining
Pen.el
- Imagery for Pen.el with CLIP and inspired from Myst: The Book of Atrus // Bodacious Blog
- For mac users
- Select some text, tap
Esc
, holdCtrl
and press\
, release and tapr
. - For everyone else
- Select some text, hold
Ctrl Alt \
, release and tapr
.
You may also press SPC
while some text is selected to run a prompt function.
You may also use right click
for starting the context menu.
- For mac users
- Select some text, tap
Esc
, holdCtrl
and press\
, release and tapc
. - For everyone else
- Select some text, hold
Ctrl Alt \
, release and tapc
.
More company bindings.
kb | f | |
---|---|---|
H-TAB f | pen-company-complete-choose | Select a single completer. Remove others. |
H-TAB a | pen-company-complete-add | Add other completers to the completer list |
Running pen-generate-prompt-functions
will
load all prompts from the prompts directory,
which is typically located here: ~/.emacs.d/prompts
.
Running pen-run-prompt-function
will run a prompt function.
You may also press SPC
while some text is selected to run a prompt function.
title: Get language
version: 1
doc: This prompt detects the language
notes:
- "It appears that combining ### with Input: Output: has no improvement"
prompt: |+
Given some text, return the language.
Input: Hello
Output: English
Input: Bon anniversaire !
Output: French
Input: printf -- "%s\n" "$lang"
Output: bash
Input: Zdravstvuyte
Output: Russian
Input: <1>
Output:
engine: davinci
temperature: 0.3
max-tokens: 200
top-p: 1
stop-sequences:
- "\n"
vars:
- text-or-code
examples:
- Happy birthday
preprocessors:
- "sed -z 's/\\n/\\\\n/g'"
aliases:
- detect-language
This is a prompt which, given text selected will output the language that text is in.
It works for both world languages and for code.
The title
of the prompt will be
slugified and used as the name of
the prompt function.
doc
and notes
will both go into the
documentation for the function.
The prompt is using the Input
Output
pattern.
engine
is the name of a language model.
An API such as the OpenAI API
(GPT-3
) may serve
several different models.
- Some alternative models for
GPT-3
:- babbage
- content-filter-alpha-c4
- content-filter-dev
- curie
- cursing-filter-v6
- davinci
- instruct-curie-beta
- instruct-davinci-beta
vars
is a list of variable names. Each
variable is substituted into the prompt if it
has a corresponding template placeholder.
For example, the <1>
in the prompt
corresponds to where the first variable
(text-or-code
) will be substituted.
examples
is a list with the same number of
elements as vars
. The values in examples
may be suggested as initial input when
running the prompt function and may be used in
test cases. They also serve as documentation
for the user.
preprocessors
are a list of shell
pipelineable commands (stream filters) which
expect both input and output and can be used
to preprocess the variables before they are
substituted into the prompt template.
This prompt doesn’t have a postprocessor
,
but if it did it would postprocess the
returned completions in a similar fashion to
how the variables are preprocessed.
Finally, aliases
is a list of alternative
function names for this prompt.
git checkout "https://github.com/semiosis/pen.el"
cd pen.el/src
# Careful with setup script.
# Run the commands manually as this is designed for root user, intended for a Docker container.
./setup.sh
Demo of running the script on a vanilla VPS.
Or make the additions / adjustments to your own emacs config.
Take the parts you need from the init.el
and place inside your own ~/.emacs
.
If you don’t have an init file of your own then run this.
ln -sf ~/.emacs.d/pen.el/init.el ~/.emacs
Ensure you have the prompts repository in place.
git checkout "https://github.com/semiosis/prompts/tree/master/prompts" ~/.emacs.d/prompts
Install OpenAI API key.
mkdir -p ~/.pen
touch ~/.pen/openai_api_key
vim ~/.pen/openai_api_key
- Setup
- Install
prompt
snippet into yasnippet. - M-x
yas/reload-all
- M-x
yas-insert-snippet
- Install
- Prompt design
- 1. Come up with a task. Let’s call it “Negate sentence”
- 2. Insert the prompt snippet into a new prompt file.
- 3. Remove keys from prompts file which we don’t need.
- 4.
var-defaults
is an advanced usage of prompts- But we will remove them
- 5. Now load the prompt with
M-x pen-generate-prompt-functions
- 6. Now look at the prompt function documentation
- The binding
C-h C-f
is used to bring up help for a function
- The binding
- 7. Looks like we made an error: “The Mars is very far away.”
- Change it and update the version of the prompt
- 8. Reload functions
Test it out.
I want to eat dinner now.
It didn’t work. hurm.
Well, here is the basic process anyway. I’ll try and debug this.
Maori isn’t a very prominent language on the web, but it still managed to capture the idea of a welcome message, which I think is amazing! I am Maori, so I appreciate this!
I want to demonstrate the usage of two more .prompt
keys.
- The technical jargon
var-defaults
overrides the default behaviour of the(interactive)
form in emacs.
By specifying var-defaults
, you can change
what functions or expressions are run to
acquire the values for the parameters to the
prompt.
The prompt here captures the selected text and
puts it into the second placeholder, <2>
.
By default, that would go into the first one, <1>
.
var-defaults:
- "(read-string \"language: \")"
- "(pen-selected-text)"
---
title: Translate from English to
prompt-version: 2
doc: This prompt translates English text to any world langauge
issues:
- I think the unicode characters may be multibyte causing issues with completion
prompt: |
###
# English: Hello
# Russian: Zdravstvuyte
# Italian: Salve
# Japanese: Konnichiwa
# German: Guten Tag
# French: Bonjour
# Spanish: Hola
###
# English: Happy birthday!
# French: Bon anniversaire !
# German: Alles Gute zum Geburtstag!
# Italian: Buon compleanno!
# Indonesian: Selamat ulang tahun!
###
# English: <2>
# <1>:
engine: davinci
temperature: 0.5
max-tokens: 200
top-p: 1
stop-sequences:
- "#"
vars:
- language
- phrase
# ascification of the prompt is not ideal
prompt-filter: pen-c ascify
examples:
- French
- Goodnight
var-defaults:
- "(read-string \"language: \")"
- "(pen-selected-text)"
prompt-filter: pen-c ascify
The prompt-filter
is a final filter script
to transform the prompt before sending to the
API
/ LM
for completion.
---
title: Translate from world language X to Y
version: 2
doc: This prompt translates English text to any world langauge
issues:
- I think the unicode characters may be multibyte causing issues with completion
prompt: |
###
# English: Hello
# Russian: Zdravstvuyte
# Italian: Salve
# Japanese: Konnichiwa
# German: Guten Tag
# French: Bonjour
# Spanish: Hola
###
# English: Happy birthday!
# French: Bon anniversaire !
# German: Alles Gute zum Geburtstag!
# Italian: Buon compleanno!
# Indonesian: Selamat ulang tahun!
###
# <1>: <3>
# <2>:
engine: davinci
temperature: 0.5
max-tokens: 200
top-p: 1
stop-sequences:
- "#"
vars:
- from-language
- to-language
- phrase
# ascification of the prompt is not ideal
prompt-filter: pen-c ascify
examples:
- English
- French
- Goodnight
var-defaults:
- "(read-string \"From language: \")"
- "(read-string \"To language: \")"
- "(pen-selected-text)"
Prompt functions automatically ‘curry’ when you leave out their arguments.
Here is an example, pf-translate-from-world-language-x-to-y/3
:
pf-translate-from-world-language-x-to-y/3 is an interactive function
defined in pen-example-config.el.
Signature
(pf-translate-from-world-language-x-to-y/3 &optional FROM-LANGUAGE TO-LANGUAGE PHRASE)
Documentation
Translate from world language X to Y
This prompt translates English text to any world langauge
path:
- /home/shane/source/git/spacemacs/prompts/prompts/translate-world-languages.prompt
examples:
- English
- French
- Goodnight
preprocessors:
- cat
- cat
- sed -z 's/\n/\\n/g'
var-defaults:
- (read-string-hist "Pen From language: ")
- (read-string-hist "Pen To language: ")
- (pen-selected-text)
prompt-filter:
- pen-c ascify
If this function is run without a selection
then pen-selected-text
will resort to asking
the user for input.
;; Leave out all arguments to be prompted for each argument
(pf-translate-from-world-language-x-to-y/3)
The following default functions / expressions
(i.e. var-defaults
) are run when called
interactively or to acquire the values of
optional parameters that were left out of the
call to the prompt function.
var-defaults:
- "(read-string-hist \"Pen From language: \")"
- "(read-string-hist \"Pen To language: \")"
- "(pen-selected-text)"
The following invocation supplies "French"
as the first parameter, but the others will be
requested.
(pf-translate-from-world-language-x-to-y/3 "French")
烤面包
I’m trying to do something a little more ambitious than simply having a single completion function.
There will be infinitely many completion functions that you can select from.
kb | f | |
---|---|---|
H-TAB c | pen-company-complete | pen-map |
Mark Watson in his book “Practical Artificial Intelligence Programming With Clojure” uses spaCy and the HuggingFace transformers library from Clojure. I would like to connect to HuggingFace’s transformers library in this way.
See “https://markwatson.com/”.
https://github.com/samrawal/emacs-secondmate/
Thank you @Samin
and @erik
for the
booste
API support in integrating a free to
use GPT-2.
Please visit https://www.booste.io/ to get your key.
Currently working on a way to integrate this.