• Stars
    star
    1,197
  • Rank 38,867 (Top 0.8 %)
  • Language
    Python
  • License
    MIT License
  • Created over 1 year ago
  • Updated 3 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A tiny library for coding with large language models.

A tiny library for coding with large language models. Check out the MiniChain Zoo to get a sense of how it works.

Coding

  • Code (math_demo.py): Annotate Python functions that call language models.
@prompt(OpenAI(), template_file="math.pmpt.tpl")
def math_prompt(model, question):
    "Prompt to call GPT with a Jinja template"
    return model(dict(question=question))

@prompt(Python(), template="import math\n{{code}}")
def python(model, code):
    "Prompt to call Python interpreter"
    code = "\n".join(code.strip().split("\n")[1:-1])
    return model(dict(code=code))

def math_demo(question):
    "Chain them together"
    return python(math_prompt(question))
  • Chains (Space): MiniChain builds a graph (think like PyTorch) of all the calls you make for debugging and error handling.

show(math_demo,
     examples=["What is the sum of the powers of 3 (3^i) that are smaller than 100?",
               "What is the sum of the 10 first positive integers?"],
     subprompts=[math_prompt, python],
     out_type="markdown").queue().launch()
...
Question:
A robe takes 2 bolts of blue fiber and half that much white fiber. How many bolts in total does it take?
Code:
2 + 2/2

Question:
{{question}}
Code:
  • Installation
pip install minichain
export OPENAI_API_KEY="sk-***"

Examples

This library allows us to implement several popular approaches in a few lines of code.

It supports the current backends.

  • OpenAI (Completions / Embeddings)
  • Hugging Face 🤗
  • Google Search
  • Python
  • Manifest-ML (AI21, Cohere, Together)
  • Bash

Why Mini-Chain?

There are several very popular libraries for prompt chaining, notably: LangChain, Promptify, and GPTIndex. These library are useful, but they are extremely large and complex. MiniChain aims to implement the core prompt chaining functionality in a tiny digestable library.

Tutorial

Mini-chain is based on annotating functions as prompts.

image

@prompt(OpenAI())
def color_prompt(model, input):
    return model(f"Answer 'Yes' if this is a color, {input}. Answer:")

Prompt functions act like python functions, except they are lazy to access the result you need to call run().

if color_prompt("blue").run() == "Yes":
    print("It's a color")

Alternatively you can chain prompts together. Prompts are lazy, so if you want to manipulate them you need to add @transform() to your function. For example:

@transform()
def said_yes(input):
    return input == "Yes"

image

@prompt(OpenAI())
def adjective_prompt(model, input):
    return model(f"Give an adjective to describe {input}. Answer:")
adjective = adjective_prompt("rainbow")
if said_yes(color_prompt(adjective)).run():
    print("It's a color")

We also include an argument template_file which assumes model uses template from the Jinja language. This allows us to separate prompt text from the python code.

@prompt(OpenAI(), template_file="math.pmpt.tpl")
def math_prompt(model, question):
    return model(dict(question=question))

Visualization

MiniChain has a built-in prompt visualization system using Gradio. If you construct a function that calls a prompt chain you can visualize it by calling show and launch. This can be done directly in a notebook as well.

show(math_demo,
     examples=["What is the sum of the powers of 3 (3^i) that are smaller than 100?",
              "What is the sum of the 10 first positive integers?"],
     subprompts=[math_prompt, python],
     out_type="markdown").queue().launch()

Memory

MiniChain does not build in an explicit stateful memory class. We recommend implementing it as a queue.

image

Here is a class you might find useful to keep track of responses.

@dataclass
class State:
    memory: List[Tuple[str, str]]
    human_input: str = ""

    def push(self, response: str) -> "State":
        memory = self.memory if len(self.memory) < MEMORY_LIMIT else self.memory[1:]
        return State(memory + [(self.human_input, response)])

See the full Chat example. It keeps track of the last two responses that it has seen.

Tools and agents.

MiniChain does not provide agents or tools. If you want that functionality you can use the tool_num argument of model which allows you to select from multiple different possible backends. It's easy to add new backends of your own (see the GradioExample).

@prompt([Python(), Bash()])
def math_prompt(model, input, lang):
    return model(input, tool_num= 0 if lang == "python" else 1)

Documents and Embeddings

MiniChain does not manage documents and embeddings. We recommend using the Hugging Face Datasets library with built in FAISS indexing.

image

Here is the implementation.

# Load and index a dataset
olympics = datasets.load_from_disk("olympics.data")
olympics.add_faiss_index("embeddings")

@prompt(OpenAIEmbed())
def get_neighbors(model, inp, k):
    embedding = model(inp)
    res = olympics.get_nearest_examples("embeddings", np.array(embedding), k)
    return res.examples["content"]

This creates a K-nearest neighbors (KNN) prompt that looks up the 3 closest documents based on embeddings of the question asked. See the full Retrieval-Augemented QA example.

We recommend creating these embeddings offline using the batch map functionality of the datasets library.

def embed(x):
    emb = openai.Embedding.create(input=x["content"], engine=EMBEDDING_MODEL)
    return {"embeddings": [np.array(emb['data'][i]['embedding'])
                           for i in range(len(emb["data"]))]}
x = dataset.map(embed, batch_size=BATCH_SIZE, batched=True)
x.save_to_disk("olympics.data")

There are other ways to do this such as sqllite or Weaviate.

Typed Prompts

MiniChain can automatically generate a prompt header for you that aims to ensure the output follows a given typed specification. For example, if you run the following code MiniChain will produce prompt that returns a list of Player objects.

class StatType(Enum):
    POINTS = 1
    REBOUNDS = 2
    ASSISTS = 3

@dataclass
class Stat:
    value: int
    stat: StatType

@dataclass
class Player:
    player: str
    stats: List[Stat]


@prompt(OpenAI(), template_file="stats.pmpt.tpl", parser="json")
def stats(model, passage):
    out = model(dict(passage=passage, typ=type_to_prompt(Player)))
    return [Player(**j) for j in out]

Specifically it will provide your template with a string typ that you can use. For this example the string will be of the following form:

You are a highly intelligent and accurate information extraction system. You take passage as input and your task is to find parts of the passage to answer questions.

You need to output a list of JSON encoded values

You need to classify in to the following types for key: "color":

RED
GREEN
BLUE


Only select from the above list, or "Other".⏎


You need to classify in to the following types for key: "object":⏎

String



You need to classify in to the following types for key: "explanation":

String

[{ "color" : "color" ,  "object" : "object" ,  "explanation" : "explanation"}, ...]

Make sure every output is exactly seen in the document. Find as many as you can.

This will then be converted to an object automatically for you.

More Repositories

1

GPU-Puzzles

Solve puzzles. Learn CUDA.
Jupyter Notebook
5,464
star
2

Tensor-Puzzles

Solve puzzles. Improve your pytorch.
Jupyter Notebook
2,967
star
3

llama2.rs

A fast llama2 decoder in pure Rust.
Rust
998
star
4

Triton-Puzzles

Puzzles for learning Triton
Jupyter Notebook
895
star
5

LLM-Training-Puzzles

What would you do with 1000 H100s...
Jupyter Notebook
797
star
6

annotated-s4

Implementation of https://srush.github.io/annotated-s4
Python
451
star
7

annotated-mamba

Annotated version of the Mamba paper
Jupyter Notebook
438
star
8

Autodiff-Puzzles

Jupyter Notebook
317
star
9

Transformer-Puzzles

Puzzles for exploring transformers
Jupyter Notebook
281
star
10

streambook

Live Python Notebooks with any Editor
Jupyter Notebook
277
star
11

raspy

An interactive exploration of Transformer programming.
Jupyter Notebook
239
star
12

do-we-need-attention

TeX
159
star
13

parallax

Python
157
star
14

GPTWorld

A puzzle to learn about prompting
Jupyter Notebook
104
star
15

awesome-ml-tracking

102
star
16

triton-autodiff

Experiment of using Tangent to autodiff triton
Python
66
star
17

torch-queue

Python
64
star
18

LLM-Talk

45
star
19

torch-golf

Silly twitter torch implementations.
Python
44
star
20

PyDecode

A dynamic programming toolkit.
C++
39
star
21

VirtualTeaching

DIY setup for virtual teaching on ubuntu
39
star
22

mamba-primer

34
star
23

learns-dex

33
star
24

text2table

Python
31
star
25

jax-lda

Python
31
star
26

ProbTalk

HTML
29
star
27

Hierarchical-Bayes-Compiler

Hal Daume's hbc
Haskell
20
star
28

g9py

HTML
18
star
29

drop7

Jupyter Notebook
18
star
30

Tensor-Puzzles-Penzai

HTML
17
star
31

mamba-scans

Blog post
16
star
32

anynp

Proof-of-concept of global switching between numpy/jax/pytorch in a library.
Python
16
star
33

transformers-bet

HTML
11
star
34

relax-decode

Java
10
star
35

aima-arguments

7
star
36

torch-mechanics

Amateur experiments with autodiff mechanics simulators
7
star
37

minitorch-rust

7
star
38

cs5781

Machine Learning Engineering
6
star
39

postgres-provanence

C
6
star
40

PowerEdit

A super-minimal Python-based video editor ⚡
Python
6
star
41

SemiRings

Holder for a bunch of semirings used in ChartParsing
Haskell
6
star
42

DiffRast

HTML
6
star
43

MRF-LM

Shell
5
star
44

TextBook

Command-line Facebook
Haskell
5
star
45

hsNLP-

Combined repo for nlp libs
Haskell
4
star
46

provenance

4
star
47

icfp2009

when I was 4 years old I was maimed by a giant pig
Haskell
4
star
48

configure

some configuration file
Emacs Lisp
3
star
49

clustering

C++
3
star
50

annotated-transformer.github.io

Annotated Transformer Blog Post
3
star
51

BT-AI

Jupyter Notebook
3
star
52

srush-blog

Haskell
2
star
53

Eisner-Parser

An implementation of the Eisner Parser (described in "Bilexical Grammars and a Cubic-time parsing algorithm" ) in Haskell
Haskell
2
star
54

FSM

Finite State Machine lib for haskell
Haskell
2
star
55

hplay

2
star
56

opennmt-gen

Shell
2
star
57

PhraseDep

C++
2
star
58

triton

2
star
59

srush-wiki

2
star
60

tf-fork

Python
2
star
61

icfp2003

Race Car
Haskell
2
star
62

icfp2008

2
star
63

hypergraph

Hypergraph specification
Python
2
star
64

learns-triton

2
star
65

Training

Haskell
1
star
66

bipartite-sampler

Implementation of Huber-Law rejection sampling for bipartite graphs
C
1
star
67

ezTVM

1
star
68

test_grade

Python
1
star
69

Chart-Parsing-

haskell library for basic chart parsers
Haskell
1
star
70

blog-twitter

1
star
71

sigmoidfit

Jupyter Notebook
1
star
72

evernote

Command line bindings for evernote
1
star
73

prof8

Experimental paper writing linter.
TeX
1
star
74

transforest

transforest
Python
1
star
75

decoding-methods

1
star
76

blog

Jupyter Notebook
1
star
77

nlp-course

Go
1
star
78

beamer-animation

Create animations for LaTeX Beamer presentations.
Python
1
star
79

Duel

Python
1
star
80

nlp

1
star
81

twitter-simmons-sports

1
star
82

monadnack-project

Art project for monadnack
1
star
83

peoplesounds

Python
1
star
84

CutParse

C++
1
star
85

Lattice

lattice protobuffer
Python
1
star
86

Penn-Treebank

Haskell library for the penn treebank management
1
star
87

icfp2020

Python
1
star
88

twittersports

1
star
89

ProbDist

Tools for probabality distributions focusing on estimation, conditioning, and smoothing
Haskell
1
star
90

osgai

JavaScript
1
star