DEV Community

Cover image for C in CRUD in Plang language
Ingi
Ingi

Posted on

C in CRUD in Plang language

This article explores Plang, an intent-based programming language designed to interpret natural language. For more information, visit plang.is

How can you structure a input like this ate sandwich with ham and cheese to fit your database schema, that has 7 columns? That just doesn't add up, right?

What is CRUD

Most developers are very familiar with CRUD (Create, Read, Update, Delete).

The classic way we do this, is by creating a (web)form where we can create new data or update the data. We have list so we can see all the data, there we provide to either edit link to update or delete link to delete the data.

In Plang this can all be different. It is of course possible to provide the same form and list, but why not have it more natural.

Instead of the human adjusting to the computer, having to fill in form according to the 7 column data structure that the required of the project, we allow the user to free form it and let the computer adjust to the user.

Food diary

In this C in CRUD example, I am going to use Food diary app as an example.

In general, Food diary apps are quite strict in their formatting, anyone that has used one has had a list of input to fill inn, selecting from multiple option, often difficult to decide which type of chicken I just ate, because there are 5 version to select from. We also are required to know the weight of what we eat. It's difficult.

Data structure

The project dictates that we want this type of data structure. This of course can be anything that fits you app, in this case for Food diary.

{
  date: datetime
  foods: [{
     name: string, quantity: number, protein: number, fat: number, carbs: number, calories: number
  }, 
  ....
  ]
  total_carbs: number
  total_fat:number,
  total_protein:number,
  total_calories:number
  total_quantity:number
}
Enter fullscreen mode Exit fullscreen mode

The user would have to fill in the name of the food, and either we have a huge database, already defined with all the protein/fat/carbs/calories for every food available in the world or we make the user fill this in.

It's not easy for the user or the service.

LLM to the rescue

Plang has LLM integrated into the language (LLM is like ChatGPT if you don't know). Imagine having a person on the other end working for you, deciding how an input fits a data structure.

So instead of having a form, with multiple fields, the user can simply say:

ate sandwich with ham and cheese
Enter fullscreen mode Exit fullscreen mode

The LLM will take this statement, decide on the ingredients and return us a structured data, that fits our database.

Create in CRUD

Let start on the create, where user inputs new data and we want to save into the database.

If you like to code this on your computer, you need to install Plang

Lets start by setting up the database. Create Setup.goal file in your project folder.

Setup
- create table food_entries, columns:
    date(datetime, not null), foods(json, not null), total_quantity(number), total_carbs(number), total_fat(number), total_protein(number), total_calories(number)
Enter fullscreen mode Exit fullscreen mode

We now have table food_entries, that contains those columns. The database is Sqlite database located on your computer, in your app folder under .db/data.sqlite. No need to setup database. It is simple.

Next lets do the Create part, I am calling this Insert in the plang code because we are going to insert new data into the database

I will start with the whole plang code and explain.
Create Insert.goal file in the project folder

Insert
- read llm/insertSystem.txt, into %system%
- [llm] system: %system%
    user: %userInput%
    scheme: {
        "date": datetime, 
        "foods": [
                {"name": string, "quantity": number, "calories": number, "carbs": number, "fat": number, "protein": number}
            ], 
        "total_carbs": number, 
        "total_quantity": number, 
        "total_fat": number,
        "total_protein": number, 
        "total_calories": number
      }
    write to %foodEntry%
- insert into food_entries 
        %foodEntry.date%, %foodEntry.foods%, 
        %foodEntry.total_quantity%,  
        %foodEntry.total_carbs%, 
        %foodEntry.total_fat%, 
        %foodEntry.total_protein%,  
        %foodEntry.total_calories%
Enter fullscreen mode Exit fullscreen mode

Notice that each step in the program starts with a dash(-).

Lets read the first step of the Insert

- read llm/insertSystem.txt, into %system%
Enter fullscreen mode Exit fullscreen mode

In that first step we read a text file located in the llm folder, named insertSystem.txt and then load the content of that file into %system% variable.

We haven't created the insertSystem.txt file yet, so lets do that. Create a new folder called llm, and inside create insertSystem.txt

In the insertSystem.txt we setup the system command for the LLM. It goes something like this

Act as Nutritional specialist. 
Analyze the food entry from user input for a food diary and break down the macronutrients for each food. 

When user does not specify quantity or weight, always assume it is for one person that fits that meal type. Make up the missing numbers but be realistic.

Use your knowledge as LLM to figure out the macronutrients information about ingredients
Enter fullscreen mode Exit fullscreen mode

Here we have setup the LLM to act as a specialist on food, to break up the user statement and give the macronutrients (protein, fat, carbs, calories). Notice we haven't defined the structure yet.

Next we call the the LLM in plang

- [llm] system: %system%
    user: %userInput%
    scheme: {
        "date": datetime, 
        "foods": [
                {"name": string, "quantity": number, "calories": number, "carbs": number, "fat": number, "protein": number}
            ], 
        "total_carbs": number, 
        "total_quantity": number, 
        "total_fat": number,
        "total_protein": number, 
        "total_calories": number
      }
    write to %foodEntry%
Enter fullscreen mode Exit fullscreen mode

We start the the step with [llm], this is to help the compiler of the plang language, telling it, we would like to use the llm for this step.

We then proceed to set the system variable and the user variable. The system variable is the content from the insertSystem.txt and the user is the input from the user, e.g. ate sandwich with ham and cheese.

Next part of the step, scheme: property, where we define what the response we would like back from the LLM. This means, we now have structured data from the user input

Last part of the step we tell it to load the response into the %foodEntry% variable.

Notice that this is all one step, even though it is multiple lines, because dash (-) defines a step

Now think of this step in this way:

You have a person somewhere on the other end that gets the text sent to him: ate sandwich with ham and cheese and his job is to understand this statement, break down how much macronutrients is in each ingredient, and give us back a JSON response. This person is on the other end typing this in, sweating and working hard. Or it's just an LLM

Looking at it from that perspective, that there is another person on the other end, what can you do in your environment, that you could delegate for almost free? Just a thought.

Next step is easy, just insert into the database

- insert into food_entries 
        %foodEntry.date%, %foodEntry.foods%, 
        %foodEntry.total_quantity%,  
        %foodEntry.total_carbs%, 
        %foodEntry.total_fat%, 
        %foodEntry.total_protein%,  
        %foodEntry.total_calories%
Enter fullscreen mode Exit fullscreen mode

Notice how we are not defining 100% correct SQL. No worries, this is not a new QL language. Plang will figure it out for you and construct 100% valid SQL. You are free to write 100% valid SQL, you just don't need to.

And that is how...

... you take user input ate sandwich with ham and cheese and convert into 7 column structured data.

Validity of data

Your suspicion will be if LLM can give you correct results, for this app, it is close enough. There are cases where it's is not correct, but so is manual input. LLM will only get better, humans will always have error rate.

You can also adjust the system prompt, and tell him, you eat 50% more then a normal person if that is the case. You are very flexible without changing the logic of the program.

For critical data, where it must be correct, it all depends, but you can define exactly what data it can respond and you should validate response when you know what options are available, just like with humans

U in CRUD

Please comment on this article if you are interested in the Update part, where you can say actually, I had 2 sandwiches and it figures it out.

Just so I know there is interest.

Following example is of a Food diary app, available at https://github.com/ingig/FoodDiaryApp. This article is simplified version of it.

Top comments (0)