Package: minichain
A tiny library for coding withlargelanguage models. Check out theMiniChain Zooto get a sense of how it works.CodingCode (math_demo.py): Annotate Python functions that call language models.@prompt(OpenAI(),template_file="math.pmpt.tpl"defmath_prompt(model,question):"Prompt to call GPT with a Jinja template"returnmodel(dict(question=question))@prompt(Python(),template="import math\n{{code}}")defpython(model,code):"Prompt to call Python interpreter"code="\n".join(code.strip().split("\n")[1:-1])returnmodel(dict(code=code))defmath_demo(question):"Chain them together"returnpython(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()Template (math.pmpt.tpl): Prompts are separated from code....
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:InstallationpipinstallminichainexportOPENAI_API_KEY="sk-***"ExamplesThis library allows us to implement several popular approaches in a few lines of code.Retrieval-Augmented QAChat with memoryInformation ExtractionInterleaved Code (PAL)-(Gao et al 2022)Search Augmentation (Self-Ask)-(Press et al 2022)Chain-of-Thought-(Wei et al 2022)It supports the current backends.OpenAI (Completions / Embeddings)Hugging Face 🤗Google SearchPythonManifest-ML (AI21, Cohere, Together)BashWhy Mini-Chain?There are several very popular libraries for prompt chaining,
notably:LangChain,Promptify, andGPTIndex.
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.TutorialMini-chain is based on annotating functions as prompts.@prompt(OpenAI())defcolor_prompt(model,input):returnmodel(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 callrun().ifcolor_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()defsaid_yes(input):returninput=="Yes"@prompt(OpenAI())defadjective_prompt(model,input):returnmodel(f"Give an adjective to describe{input}. Answer:")adjective=adjective_prompt("rainbow")ifsaid_yes(color_prompt(adjective)).run():print("It's a color")We also include an argumenttemplate_filewhich assumes model uses template from theJinjalanguage.
This allows us to separate prompt text from the python code.@prompt(OpenAI(),template_file="math.pmpt.tpl")defmath_prompt(model,question):returnmodel(dict(question=question))VisualizationMiniChain has a built-in prompt visualization system usingGradio.
If you construct a function that calls a prompt chain you can visualize it
by callingshowandlaunch. 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()MemoryMiniChain does not build in an explicit stateful memory class. We recommend implementing it as a queue.Here is a class you might find useful to keep track of responses.@dataclassclassState:memory:List[Tuple[str,str]]human_input:str=""defpush(self,response:str)->"State":memory=self.memoryiflen(self.memory)<MEMORY_LIMITelseself.memory[1:]returnState(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 provideagentsortools. If you want that functionality you can use thetool_numargument 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()])defmath_prompt(model,input,lang):returnmodel(input,tool_num=0iflang=="python"else1)Documents and EmbeddingsMiniChain does not manage documents and embeddings. We recommend using
theHugging Face Datasetslibrary with
built in FAISS indexing.Here is the implementation.# Load and index a datasetolympics=datasets.load_from_disk("olympics.data")olympics.add_faiss_index("embeddings")@prompt(OpenAIEmbed())defget_neighbors(model,inp,k):embedding=model(inp)res=olympics.get_nearest_examples("embeddings",np.array(embedding),k)returnres.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 fullRetrieval-Augemented QAexample.We recommend creating these embeddings offline using the batch map functionality of the
datasets library.defembed(x):emb=openai.Embedding.create(input=x["content"],engine=EMBEDDING_MODEL)return{"embeddings":[np.array(emb['data'][i]['embedding'])foriinrange(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 assqlliteorWeaviate.Typed PromptsMiniChain 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 ofPlayerobjects.classStatType(Enum):POINTS=1REBOUNDS=2ASSISTS=3@dataclassclassStat:value:intstat:StatType@dataclassclassPlayer:player:strstats:List[Stat]@prompt(OpenAI(),template_file="stats.pmpt.tpl",parser="json")defstats(model,passage):out=model(dict(passage=passage,typ=type_to_prompt(Player)))return[Player(**j)forjinout]Specifically it will provide your template with a stringtypthat 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.