In this post, I will present the idea of concept prompting and how it can be used to
create a bot that can automate tasks that can be done within a text-based linux
environment.
Introduction - ReAct methodology and function calling
Large Language Models (LLMs) have shown great promise in various natural language
processing tasks, particularly in predicting outputs based on given inputs. These models
have been used in a wide range of applications, including text generation, translation,
summarization, and more.
One of the more interesting applications of LLMs is using them as thought processors for
agents. This usually involves feeding a prompt to the LLM, based on which the LLM
generates a thought process and then acts on it. The LLM can interact with the environment
through function calls. Specifically, after the response is generated, a parser extracts a
specific function call from the response and then executes it. The result is then fed back
to the LLM through a new prompt, and the process can continue.
Below is an example of a prompt, the responses generated by the LLM, and the corresponding
function calls.
Example of ReAct methodology prompt with function calling
You are an agent working in a ReAct mode and you are given a task.
Given a starting point "START" and the task, you generate a thought.
Then, you generate a function call based on the thought. The function
call is then executed and the response is fed back to you. You then
generate a new thought based on the response and the process continues
until the task is completed.
You are given a set of functions to call. The functions are defined as follows:
{
"add": {
"desc": "Add two numbers",
"args": ["num1", "num2"]
}
"sub": {
"desc": "Subtract two numbers",
"args": ["num1", "num2"]
}
"end": {
"desc": "End the task",
"args": []
}
}
You call an action by typing the name of the function and then the arguments
in the following format:
Action: <function_name> <arg1> <arg2> ...
Example of a ReAct process:
\```
Task: "You are given a task to add two numbers: 6 and 8.
START:
Thought: I need to add two numbers: 6 and 8.
Action: add 6 8
Observation: 14
Thought: The sum of 6 and 8 is 14.
Action: end
\```
Below is your task.
Task: "You are given a task to substract two numbers: 456 and 123.
START: // End of prompt
Thought: I need to substract two numbers: 456 and 123. // Generated by the LLM
Action: sub 456 123 // Generated by the LLM
Observation: 333 // Generated by the function call
Thought: The difference between 456 and 123 is 333. // Generated by the LLM
Action: end // Generated by the LLM
The ReAct methodology and function calling is really interesting idea and a big step
towards creating an agent that can automate any task.
Problem with function calling
The function calling employed in the ReAct methodology has several limitations:
The set of functions that can be called is fixed and cannot be modified, which limits
the flexibility of the agent.
Some providers, such as OpenAI, do not expose the function-calling API directly.
Instead, there is a hidden "" prompt that contains the function specifications,
which is not accessible to the user for inspection.
What we aim to achieve is a more flexible system where the agent can call any function
available in the environment, including, for example, Linux commands.
Experience prompting
The idea of experience prompting is to remove the need for predefined function definitions
by instead injecting the prompt given to the LLM with previous experiences related to the
task. These experiences are still formatted in the Thought-Action-Observation (TAO)
structure.
Since the experiences contain the appropriate function calls, the agent can use any action
that was employed in the experiences injected into the prompt. This creates a more
flexible system where the agent can call any function available in the environment.
Youareanassistantwhoperformsvarioustasksfortheuser.Youworkinatextinterfaceandfollowthought,action,observationpattern.Forexample:Task:Createadirectorynamed"test"START:Thought:Ineedtocreateadirectorynamed"test"Action:cmdmkdirtestObservation:Directory"test"hasbeencreated.EXITAnotherexample:Task:Listthefilesinthecurrentdirectory.START:Thought:Ineedtolistthefilesinthecurrentdirectory.Icanusethelscommand.Action:cmdlsObservation:Thefilesinthecurrentdirectoryare:file1file2file3EXITInaddition,youhaveaccesstosimilartaskexamples,thecurrenttask,andthememories.Yourcurrenttaskis:Createafoldernamed'lolapaloza'inthecurrentdirectoryInthepast,youhaveperformedsimilartasks:----------------Task:Tellmethecurrenttime.Taskcontext:Thereisnocontextspecifictothistask.START:Thought:Ineedtofindoutwhatisthecurrenttime.Action:get_timeObservation:Currenttimeis:2024-04-1013:16:13Thought:Inowknowthecurrenttimeandcanreturntheanswer.Action:tell"Current time is 2024-04-10 13:16."Observation:NoneThought:Ihavecompletedthetask.Action:exit----------------Task:Createafoldernamed"Code".Taskcontext:Youareinthecurrentdirectoryandworkingonaprojecttocreateawebsite.START:Thought:Ineedtocreateafoldernamed"Code".Action:cmdmkdirCodeObservation:lukasz@Smith:/mnt/c/Users/luki3/Projects/LS314/Projects/Surycate/SurycateBot/examples$mkdirCodemkdir:cannotcreatedirectory'Code':Fileexistslukasz@Smith:/mnt/c/Users/luki3/Projects/LS314/Projects/Surycate/SurycateBot/examples$Thought:ThefolderexistssoIfinishedthetask.Action:exit----------------Task:Createafoldernamed"Code".Taskcontext:Youareinthecurrentdirectoryandworkingonaprojecttocreateawebsite.START:Thought:Ineedtocreateafoldernamed"Code".Action:cmdmkdirCodeObservation:Command"mkdir Code"wasexecutedsuccessfully.OUTPUT:~STATUS_CODE=0~Thought:Ifinishedthetask.Action:exit----------------Task:Createafoldernamed'lolapaloza'inthecurrentdirectory.Taskcontext:Youareinthecurrentdirectoryandworkingonaprojecttocreateawebsite.START://Endofprompt-restofthepromptisgeneratedbytheLLMandfunctioncallingThought:Ineedtocreateafoldernamed'lolapaloza'inthecurrentdirectory.Action:cmdmkdirlolapalozaObservation:lukasz@Smith:/mnt/c/Users/luki3/Projects/LS314/Projects/Surycate/SurycateBot/examples/task_prompting$mkdirlolapalozalukasz@Smith:/mnt/c/Users/luki3/Projects/LS314/Projects/Surycate/SurycateBot/examples/task_prompting$Thought:Thefolder'lolapaloza'hasbeencreatedsuccessfully.Action:exit
In the example above, the cmd command is used to execute, or rather send, a Linux command
to a bash terminal and return the output.
As we can see, experience prompting is a more flexible system where the agent can call any
function available in the environment.
Experience Injection
How are experiences injected into the prompt? Ideally, we would have a large number of
experiences covering many possible tasks that the agent might perform. However, in
practice, we cannot inject all experiences into the prompt. Instead, we can inject a few
experiences that are relevant to the current task. This is achieved using a
retrieval-based method, where experiences are retrieved based on their similarity to the
current task. In the previous example, the bot retrieved three experiences that were most
similar to the task "Create a folder named 'lolapaloza' in the current directory." The
retrieval method used was FAISS vectorstore, implemented within LangChain. Drawbacks of
Experience Prompting
Experience prompting is a powerful concept, but it has a few drawbacks:
Experience Collection: To achieve greater flexibility for the agent, a large number of
experiences covering many possible tasks is required. Collecting and storing these
experiences can be resource-intensive.
Prompt Length: The prompt can become very long, especially if the experiences are
lengthy. As tasks become more complex, the prompt may become difficult to manage and
could exceed the maximum token length of the LLM model.
The first drawback is a natural consequence of experience prompting and cannot be
avoided—it is the price of flexibility. However, the second drawback is more problematic
as it can limit the complexity of tasks that the agent can handle. Can we address this
issue? Yes, we can use context prompting.
Context Prompting
The idea of context prompting is closely related to experience prompting. However, instead
of injecting full task experiences, we use thoughts (contexts).
What is a thought? A thought represents a single step in a task. It includes the context,
the thought about the action, the action itself, the observation, the thought about the
observation, and the new prompt.
Example from life
Let us take an example from life. Imagine you are working on a website and now you need to
log in to the server and restart the program running the server nginx.
You have a terminal open.
What is your first thought?
Well, "I need to log in to the server. I can do that using ssh."
This leads to the action "ssh user@example.com".
Then, the you observe the terminal asking for the password.
1
Pleaseenterthepassword:
What is the next thought?
"I need to enter the password. The password is 'password'."
This leads to the action "password".
Then, you observe the terminal logging you in and you see the terminal prompt.
1
/home/user$
The thought is "I am logged in. I can now restart the nginx server."
And so on. All these thoughts are separate and are a consequence of the current context.
Ideally, we would add all history to the prompt but this is not feasible. Instead, we can
include the context only and generate new context based on the observation which can be
then used for the next thought generation. This is the idea of context prompting.
Example of a prompt with context prompting
Below is a sample prompt generated by the context prompting.
Youareanagentwithanavailableterminalwhoperformsvarioustasks.Givencontextinformationthatincludesthetask,youshouldgenerateanactionwhichwillresultinanobservation.Giventhepreviouscontext,actionandtheobservation,firstgenerateathoughtabouttheobservation.Then,generateanupdatedcontextwhichcontainsasummaryofpreviousinformationandtheideawhattodonext.Forexample:Context:Iamworkingonaprojecttocreateawebsite.Ialreadyhavecreatedafoldernamed"Website".IwanttocreateamarkdownfilewiththedescriptionofthewebsitebutIamnowintheparentfolderofthe"Website"folder.Ineedtochangethedirectorytothe"Website"folder.Action:cmdcdWebsiteObservation:lukasz@Smith:~/Projects$cdWebsitelukasz@Smith:~/Projects/Website$Thought:Ihavechangedthedirectorytothe"Website"folder.Icannowcreatethemarkdownfile.NewContext:Iamworkingonaprojecttocreateawebsite.Iaminthe"Website"folder.Iwanttocreateamarkdownfilewiththedescriptionofthewebsite.Todothat,Ihavetocreateamarkdownfileinthe"Website"foldercalledREADME.md.Inabove,giventhecontext"I am working on a project to create a website.Ialreadyhavecreatedafoldernamed"Website".IwanttocreateamarkdownfilewiththedescriptionofthewebsitebutIamnowintheparentfolderofthe"Website"folder.Ineedtochangethedirectorytothe"Website"folder."yougenerateanaction"cmd cd Website"whichresultsinanobservation.Thisresultsinanobservation:"lukasz@Smith:~/Projects$ cd Websitelukasz@Smith:~/Projects/Website$"Followingtheobservation,yougenerateathoughtabouttheobservationandhowitrelatestothecontext:"I have changed the directory to the "Website" folder. I can now create the markdown file."Finally,yougenerateanupdatedcontextwhichcontainsasummaryofpreviousinformationandtheideawhattodonext:"I am working on a project to create a website. I am in the "Website" folder.Iwanttocreateamarkdownfilewiththedescriptionofthewebsite.Todothat,Ihavetocreateamarkdownfileinthe"Website"foldercalledREADME.md."Alwaysfollowthispatternwhengeneratingactions,observations,thoughts,andnewcontexts,thatisContext->Action->Observation->Thought->NewContext.Itshouldalwaysbeinthisorderandlooklikefollowing:---Context:<context>Action:<action>Observation:<observation>Thought:<thought>NewContext:<new_context>---Inaddition,youhaveaccesstopastexperiencesandmemoriesintheformofContext,Action,Observation,Thought,andNewContext.Usethisinformation.Pastmemoriessimilartothecurrentcontext:----------------Context:Iamworkingonaprojecttocreateawebsite.IwanttocreateaREADME.mdfilewiththedescriptionofthewebsiteandIthinkthatIamintheproject's directory called "WebsitePersonal". I want to create a markdown file with the description of the website.Action:cmdtouchREADME.mdObservation:lukasz@Smith:~/Projects/WebsitePersonal$touchREADME.mdlukasz@Smith:~/Projects/WebsitePersonal$Thought:IhavecreatedtheREADME.mdfile.Icannowstartwritingthedescriptionofthewebsite.NewContext:Iamworkingonaprojecttocreateawebsite.Iaminthe"WebsitePersonal"folder.IhavecreatedamarkdownfilewiththedescriptionofthewebsitecalledREADME.md.IcannowstartwritingthedescriptionofthewebsiteintheREADME.mdfile.TheREADME.mdfileshouldcontainthedescriptionofthewebsiteandthepurposeofthewebsite.----------------Context:Iamworkingonaprojecttocreateawebsite.IhavetocreateafolderfortheprojectintheProjectsdirectory.Iwanttocreateafoldernamed"WebsitePersonal"butIamnotsurewhetherIamintheProjectsdirectory.IneedtochangedirectorytotheProjectsdirectory.Iknowthatitisinthehomedirectory.Action:cmdcd~/ProjectsObservation:lukasz@Smith:~$cd~/Projectslukasz@Smith:~/Projects$Thought:IhavechangedthedirectorytotheProjectsdirectory.Icannowcreatethefolderfortheproject.NewContext:Iamworkingonaprojecttocreateawebsite.IamintheProjectsdirectory.Iwanttocreateafolderfortheprojectnamed"WebsitePersonal".Todothat,IhavetocreateafolderintheProjectsdirectorynamed"WebsitePersonal".Afterwards,Icancontinuewiththeproject.----------------Context:Mytasknowistoupdatethepackagesontheserver.First,IwillhavetoconnecttotheserversinceIamnotconnectedyet.Iwillthenupdatethepackages.Iknowthattheserverislocatedatls314.comandIhavethecredentialstoconnecttoit.Ihavetoconnecttotheservertoupdatethepackages.Myloginis"lukasz".Action:cmdsshlukasz@ls314.comObservation:lukasz@Smith:/mnt/c/Users/luki3/Projects/LS314/Projects/Surycate/SurycateBot$sshlukasz@ls314.comWelcometoUbuntu20.04LTS(GNU/Linux5.4.0-33-genericx86_64)Documentation:https://help.ubuntu.comManagement:https://landscape.canonical.com...Newrelease'22.04.3 LTS'available.Run'do-release-upgrade'toupgradetoit.Lastlogin:SatAug1021:29:082024from31.94.20.79lukasz@ls314:~$Thought:Ihavesuccessfullyconnectedtotheserver.Icannowupdatethepackagesontheserver.NewContext:Mytasknowistoupdatethelinuxpackagesonmyserver.Ihavesuccessfullyconnectedtotheserver.Icannowupdatethepackagesontheserver.Ihavetorunthecommand"apt list --upgradable"toseethelistofpackagesthatcanbeupdated.Icanthenrunthecommand"sudo apt upgrade"toupdatethepackages.IhavetomakesurethatIupdatethesecurityupdatesfirst.Icanthenupgradethesystemtothenewrelease'22.04.3 LTS'byrunningthecommand"do-release-upgrade".----------------Yourcurrentcontextisfollowing:MytaskistoupdatethepackagesonmyLinuxmachinelocatedatls314.com.Ihavesuccessfullyconnectedtotheserver.Thereisanewrelease'22.04.3 LTS'available,andasystemrestartisrequired.Ineedtoupdatethepackagesfirstusing"apt list --upgradable"andthenrun"sudo apt upgrade"toupdatethem.Afterupdatingthepackages,Ishouldperformthesystemupgradebyrunning"do-release-upgrade".Finally,IwillneedtorestartAction:cmdsshlukasz@ls314.comObservation:lukasz@Smith:/mnt/c/Users/luki3/Projects/LS314/Projects/Surycate/SurycateBot/examples/context_prompting$sshlukasz@ls314.comWelcometoUbuntu20.04LTS(GNU/Linux5.4.0-33-genericx86_64)*Documentation:https://help.ubuntu.com*Management:https://landscape.canonical.com...Newrelease'22.04.3 LTS'available.Run'do-release-upgrade'toupgradetoit.***Systemrestartrequired***Lastlogin:TueAug2711:52:152024from192.41.114.228lukasz@ls314:~$Thought:Ihavesuccessfullyconnectedtotheserveratls314.com.Icanseethatthereisanewrelease'22.04.3 LTS'availableandasystemrestartisrequired.Ishouldupdatethepackagesandthenperformthesystemupgrade.NewContext:MytaskistoupdatethepackagesonmyLinuxmachinelocatedatls314.com.Ihavesuccessfullyconnectedtotheserver.Thereisanewrelease'22.04.3 LTS'available,andasystemrestartisrequired.Ineedtoupdatethepackagesfirstusing"apt list --upgradable"andthenrun"sudo apt upgrade"toupdatethem.Afterupdatingthepackages,Ishouldperformthesystemupgradebyrunning"do-release-upgrade".Finally,Iwillneedtorestart.
Conclusions and next steps
In this post, I presented the concept of context prompting and how it can be used to
create a bot capable of automating tasks within a text-based Linux environment. Unlike
function-calling methods, context prompting offers greater flexibility in the agent's
actions, making it possible to automate any task within the environment.
I believe context prompting is a promising idea for creating more adaptable agents.
However, it does come with its challenges. The main drawback is the need to create new
prompts continuously. Additionally, these prompts must somehow incorporate short-term
memory information about the projects. In its current form, the context has to include all
relevant information about the project, which is not practical.
The next steps should involve developing a system that enables learning from experiences.
Additionally, this new system should handle context information more efficiently so that
it’s not necessary to include all project details within each prompt.
I hope you enjoyed this post. Feel free to reach out at lukasz@ls314.com.