Skip to content

Latest commit

 

History

History
573 lines (462 loc) · 19.7 KB

tutorial.org

File metadata and controls

573 lines (462 loc) · 19.7 KB

Pen Tutorial

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

./wizard4.png

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.

Acolyte Mode - Key bindings for emacs noobs

These are enabled by default with the docker image.

kb
Alt-pOpen the prompts directory in dired
Alt-tStart writing in an empty file
Alt-sSave file
Alt-rRunning a prompt function like this will not insert text or replace it.
Alt-TABThis completes the current line.
Alt-l (little L)Multiline (long) completion.
Alt-gThis reloads the prompt functions.
Alt-mRight click menu
Select text then Alt-fThis filters the text through a prompt function specifically designed for this.
SpacebarWhen text is selected, will run with that text as first argument.

Key bindings for emacs wizards (also enabled in docker)

kbf
H-.global-pen-acolyte-minor-modeThis toggles Acolyte mode.
H-TAB gpen-generate-prompt-functionsThis reloads the prompt functions.
H-TAB rpen-run-prompt-functionRunning a prompt function like this will not insert text or replace it.
M-1pen-company-filetypeThis completes the current line.
H-TAB spen-filter-with-prompt-functionThis filters the text through a prompt function specifically designed for this.
H-TAB cpen-company-completeSelect a prompt function as the completer for company-mode and complete with it.
SPCpen-run-prompt-functionWhen text is selected, will run with that text as first argument.
H-TAB lpen-complete-longThis 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

How to run H-TAB r for emacs noobies

For mac users
Select some text, tap Esc, hold Ctrl and press \, release and tap r.
For everyone else
Select some text, hold Ctrl Alt \, release and tap r.

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.

Company-mode

For mac users
Select some text, tap Esc, hold Ctrl and press \, release and tap c.
For everyone else
Select some text, hold Ctrl Alt \, release and tap c.

More company bindings.

kbf
H-TAB fpen-company-complete-chooseSelect a single completer. Remove others.
H-TAB apen-company-complete-addAdd other completers to the completer list

Usage

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.

Demos

Select some text and running a prompt function

Run a prompt function like an M-x interactive command

An exhibition of a .prompt

Prompt file
prompts/get-language.prompt at master semiosis/prompts GitHub
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.

Installation

Install dependencies and compile emacs with --with-modules

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.

Ensure the following or similar file structure

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

OpenAI - Just request a key and place it here

Install OpenAI API key.

mkdir -p ~/.pen
touch ~/.pen/openai_api_key
vim ~/.pen/openai_api_key

Using Pen

Just starting on a vanilla installation

Prompt Engineering Workflow

  • Setup
    • Install prompt snippet into yasnippet.
    • M-x yas/reload-all
    • M-x yas-insert-snippet
  • 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
    • 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.

Another .prompt exhibition

I create a new prompt here for translating between any world language

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)"

Original prompt

---
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)"

I create this prompt

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)"

Using prompt functions in your code

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")
烤面包

An assistant for any major mode

Current Development

company-mode

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.

kbf
H-TAB cpen-company-completepen-map

HuggingFace transformers

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/”.

GPT-neo

https://github.com/samrawal/emacs-secondmate/

GPT-2

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.

GPT-j

Currently working on a way to integrate this.