GitHub - luohongyin/LangCode: LangCode - Improving alignment and reasoning of large language models (LLMs) with natural language embedded program (NLEP). (original) (raw)

LangCode - Enable NLEP Reasoning for LLMs

Respresenting the Language of Thought

Hongyin Luo @ MIT [hyluo at mit dot edu]

NLEP: Natural Language Embedded Programming

The auto-regressive large language models (LLMs) generate natural and programming languages by scoring the next tokens, sampling flexible but undeterministic texts.

The Python interpreter reads structured source code and output mostly deterministic results, ensuring the mathematical correctness in reasoning and computation based on the given Python code.

NLEP is an end-to-end, hybrid language-symbolic framework with an LLM and a code interpreter.

NLEP can deal with natural language, math, symbolic, and programming tasks.

Game of 24 Example

Step 1: Import necessary built-in libraries

import itertools import operator

Step 2: Define necessary functions that generally solve this type of problem

def find_expression(numbers, target): operations = [operator.add, operator.sub, operator.mul, operator.truediv] ops = {operator.add: '+', operator.sub: '-', operator.mul: '*', operator.truediv: '/'}

for permutation in itertools.permutations(numbers):
    for ops_combo in itertools.product(operations, repeat=len(numbers)-1):
        expression = f"({permutation[0]} {ops[ops_combo[0]]} {permutation[1]})"
        for i in range(2, len(numbers)):
            expression = f"({expression} {ops[ops_combo[i-1]]} {permutation[i]})"
        try:
            if eval(expression) == target:
                return expression.replace("/", "//")
        except ZeroDivisionError:
            continue
return None

Step 3: Define constant variables for the task

numbers = [4, 9, 10, 13] target = 24

Step 4: Print an answer in natural language.

expression = find_expression(numbers, target) if expression: print(f"The correct mathematical expression that results in 24 is {expression}.") else: print("There is no correct mathematical expression that results in 24 using these numbers.")

Step 1: Import necessary built-in libraries

No need to import

Step 2: Define necessary functions that generally solve this type of problem

def calculate_keystrokes(number): keystrokes = 0 for i in range(1, number + 1): keystrokes += len(str(i)) return keystrokes

Step 3: Define constant variables for the task

number = 104892

Step 4: Print an answer in natural language.

keystrokes = calculate_keystrokes(number) print(f"To type the numbers from 1 to {number}, {keystrokes} keystrokes are needed.")

Step 1: Import necessary built-in libraries

import torch import torch.nn as nn import torch.nn.functional as F

Step 2: Define necessary classes that generally solve this type of problem

class MultiLayerPerceptron(nn.Module): def init(self, input_size, hidden_size1, hidden_size2, num_classes, dropout_rate): super(MultiLayerPerceptron, self).init() self.fc1 = nn.Linear(input_size, hidden_size1) self.fc2 = nn.Linear(hidden_size1, hidden_size2) self.fc3 = nn.Linear(hidden_size2, num_classes) self.dropout = nn.Dropout(dropout_rate)

def forward(self, x):
    out = F.relu(self.fc1(x))
    out = self.dropout(out)
    out = F.relu(self.fc2(out))
    out = self.dropout(out)
    out = self.fc3(out)
    return out

Step 3: Define constant variables for the task

input_size = 784 # 28x28 pixels for MNIST dataset hidden_size1 = 500 hidden_size2 = 100 num_classes = 10 # 10 digits for MNIST dataset dropout_rate = 0.5

Step 4: Instantiate the network

net = MultiLayerPerceptron(input_size, hidden_size1, hidden_size2, num_classes, dropout_rate)

Print out the network architecture

print(net)

MultiLayerPerceptron(
  (fc1): Linear(in_features=784, out_features=500, bias=True)
  (fc2): Linear(in_features=500, out_features=100, bias=True)
  (fc3): Linear(in_features=100, out_features=10, bias=True)
  (dropout): Dropout(p=0.5, inplace=False)
)

Multi-turn conversation example

Step 1: Import necessary built-in libraries

No need to import

Step 2: Define necessary functions that generally solve this type of problem

No need to define a function

Step 3: Define constant variables for the task

first_emperor_tang_dynasty = "Emperor Gaozu"

Step 4: Print an answer in natural language.

print(f"The first emperor of the Tang dynasty is {first_emperor_tang_dynasty}.")

Step 1: Import necessary built-in libraries

No need to import

Step 2: Define necessary functions that generally solve this type of problem

No need to define a function

Step 3: Define constant variables for the task

first_emperor_tang_dynasty_info = { "name": "Emperor Gaozu", "born": "566", "died": "635", "reign": "618-626", "full_name": "Li Yuan", "era_name": "Wude", "children": "27, including Emperor Taizong", "notable_events": "founded the Tang dynasty, expanded the empire, implemented policies promoting economic prosperity and cultural innovation" }

Step 4: Print an answer in natural language.

print(f"Emperor Gaozu, born in the year {first_emperor_tang_dynasty_info['born']} and died in the year {first_emperor_tang_dynasty_info['died']}, was the first emperor of the Tang dynasty. His reign, from {first_emperor_tang_dynasty_info['reign']}, is known as the Wude era. His given name was Li Yuan. He had 27 children, including his successor, Emperor Taizong. During his reign, he not only founded the Tang dynasty but also expanded the empire and implemented policies that promoted economic prosperity and cultural innovation.")

Contents

Supported Environments

Customizing NLEP Generation API

By default, we provide an API server that generates NLEPs without saving users' API keys. We will continue improving the prompt strategy and the quality of generated NELPs. However, we provide an option for customized servers.

Please refer to LangCode/server/ for the server setup. We provide complete code and minimal prompt to generate high-quality NLEP for different tasks. Use the following command to switch to the preferred server.

clp.config_api_endpoint()

Then input your server url in the following format:

http://{HOSTNAME}:{PORT}/items/0

Our server timeouts at 30s since the GPT-4 API is not efficient enough, but the custom server we provide does not involve this limitation.

Quick Start with Colab

Installation

Install the LangCode package in the IPython notebook by runing the following command in a code cell.

!pip install langpy-notebook

As an early release, we first deal with the Python programming language and release the LangPy class. We also look forward to LangJulia, LangR, LangGo, etc.

Define LangPy agent

Import the library and define a Langpy agent. The langpy.auto.get_langpy function automatically identify if the backend is Jupyter 6 or Colab.

from langpy.auto import get_langpy

clp: an instance of ColabLangPy

clp = get_langpy( api_key='YOUR-API-KEY', platform='gpt', model='gpt-4' )

The platforms we support are gpt (OpenAI) and palm (Google), and you can select models on these platforms. For example, platform='palm',model='text-bison-001' uses Google's text-bison-001.

Generated code to answer any question

Add the following code to a code cell, and run it to generate a program that answers your question. For example, the Game of 24 task.

mode: control history reading to enable multi-turn programming

hist_mode = 'all' (default) -> read all cell history

hist_mode = 'single' -> only read the current instruction

hist_mode = INTERGER -> Read {INTEGER} history cells.

hist_mode = 0 is equivalent to hist_mode = 'single'

numbers = '{4, 9, 10, 13}' target = 24 clp.generate( f'What is the correct mathematical expression consisting of the numbers {numbers} in any order, along with the parentheses and arithmetic operations that results in {target}?', hist_mode = 'single' )

The generated program would be placed in

Run the generated Code

Run the generated code, you'll get the answer in natural language

We did not use any Game of 24 example to prompt GPT-4, but it still gets the correct answer (4 - 10) * (9 - 13) with only sampling one output! This is more efficient than tree-of-thoughts.

Code Completion

The LangPy agent can also complete code that is not finished yet.Run the code in the upper cell will complete the code in the lower cell, getting the following program

Step 1: Import necessary built-in libraries

import torch import torch.nn as nn

Step 2: Define necessary functions that generally solve this type of problem

class MLP(nn.Module): def init(self): super(MLP, self).init() self.layers = nn.Sequential( nn.Linear(10, 5), nn.ReLU(), nn.Linear(5, 2) )

def forward(self, x):
    x = self.layers(x)
    return x

Step 3: Instantiate the defined class

mlp = MLP()

Step 4: Print an answer in natural language.

print(f"A multi-layer perceptron (MLP) has been defined. It consists of an input layer, a hidden layer with 5 neurons activated by ReLU function, and an output layer with 2 neurons. The input layer has 10 neurons, representing the dimension of the input vectors.")

Note that both the code and comment in the generated cell can be edited for another completion, enabling more flexible and direct instructions.

CSV File Processing

As an early release, we provide basic CSV file processing ability. Running the following code,

clp.preview_data(file_name = 'example_data.csv', data_type = 'csv)

a new code cell will be inserted:

First three rows of the input file:

placeName,placeDcid,xDate,xValue-DifferenceRelativeToBaseDate2006_Max_Temperature_RCP45,yDate,yValue-Percent_Person_WithCoronaryHeartDisease,xPopulation-Count_Person,yPopulation-Count_Person

"Autauga County, AL",geoId/01001,2050-06,-1.15811100000001,2020,6.3,59095,56145

"Baldwin County, AL",geoId/01003,2050-06,-1.073211,2020,5.9,239294,229287

...

file_name = 'example_data.csv' input_file = open(file_name)

Running this code snipet, you can further analyze the data in the csv file using LangCode. For example, asking LangCode to generate code for visualization:

hist_mode = 'all' allows LangCode to read previous cells

clp.generate('Visualize the correlation of xData and yData of Alabama in the file.', hist_mode = 'all')

The generated code and execution results are shown below.

Chat with Python Through Code Generation

We currently offer three parameters for LangPy.generate(instruction, mode = 'all', http = 'optional')

Hirarchical Instruction Following Through Code Completion

In the previous example we have shown,LangCode implemented a Multi-layer perceptron (MLP) with Pytorch using the following code

Step 1: Import necessary built-in libraries

import torch import torch.nn as nn

Step 2: Define necessary functions that generally solve this type of problem

class MLP(nn.Module): def init(self): super(MLP, self).init() self.layers = nn.Sequential( nn.Linear(10, 5), nn.ReLU(), nn.Linear(5, 2) )

def forward(self, x):
    x = self.layers(x)
    return x

Step 3: Instantiate the defined class

mlp = MLP()

Step 4: Print an answer in natural language.

print(f"A multi-layer perceptron (MLP) has been defined. It consists of an input layer, a hidden layer with 5 neurons activated by ReLU function, and an output layer with 2 neurons. The input layer has 10 neurons, representing the dimension of the input vectors.")

Unlike ChatGPT that requires user to write a good instruction at once, LangCode allows adding multiple instructions in different places for one task. Editting the code for completion can guide model to generate different code. For example,

Step 1: Import necessary built-in libraries

import torch import torch.nn as nn

Step 2: Define a multi-layer perceptron that has three linear layers and uses tanh activation function.

The code completion result would be

Step 1: Import necessary built-in libraries

import torch import torch.nn as nn

Step 2: Define a multi-layer perceptron that has three linear layers and uses tanh activation function.

Python program:

class MultiLayerPerceptron(nn.Module): def init(self, input_size, hidden_size, output_size): super(MultiLayerPerceptron, self).init() self.layer1 = nn.Linear(input_size, hidden_size) self.layer2 = nn.Linear(hidden_size, hidden_size) self.layer3 = nn.Linear(hidden_size, output_size) self.tanh = nn.Tanh()

def forward(self, x):
    x = self.tanh(self.layer1(x))
    x = self.tanh(self.layer2(x))
    x = self.layer3(x)
    return x

Step 3: Print an answer in natural language.

print("A multi-layer perceptron is a type of artificial neural network. It has an input layer, one or more hidden layers, and an output layer. In each layer, the inputs are multiplied by weights, summed, and passed through an activation function. In this implementation, the activation function is the hyperbolic tangent function (tanh).")

Besides the comments, you can also control the direction of the generated code by modifying the imported libraries. For example, changing import torch to import tensorflow.keras as keras. Your are encourged to explore more possibilities!

Contact

If there is any question, feel free to post an issue or contact Hongyin Luo at hyluo [at] mit [dot] edu.