
Getting Started With AI Agents
Description of Getting Started With AI Agents
Introduction
What the heck is an Agent?
Concepts related to Agents and LLMs
ReAct (Reason + Act): Synergizing Reasoning and Acting in Language Models (Github)
Think about the Prompt and Do something about it (or not?).
Self-Refine: Iterative Refinement with Self-Feedback (Github)
Upon receiving a prompt, iteratively take an action, inspect its results and take further actions as needed to improve results until no further improvements is needed or some other constraint is met to force a stop, then return the final result.
Flow Engineering: Code Generation with AlphaCodium: From Prompt Engineering to Flow Engineering (Github)
A test-based, multi-stage, code-oriented iterative flow, that improves the performances of LLMs on code problems.
Agent Frameworks
CrewAI: AI Agents for real use cases
Most AI agent frameworks are hard to use. We provide power with simplicity. Automate your most important workflows quickly.
LangChain: Agents
Build the right cognitive architecture for your application. Identify and implement the best prompting strategies 
and architectures so that your LLMs perform as intended.
Let's build an Agent
What's needed to build an LLM Powered Agent?
Context: Information for the Agent (Role, Goal, Initial Data etc)
Prompt: Message in Natural language to address the Agent (Text, Audio etc)
Python: Code the magic using Instructor
Read: Do more reading to learn more about Agents and code away
Information Retrieval vs Data Generation vs Function Calling with the Python Instructor library
So far, we have been using Instructor for both Information Retrieval and Data Generation as Structured Data. We will now dig deeper into the more advanced Function Calling Capabilities of the Python Instructor library. For scratpad, we'll use Marimo Notebooks.
So where's the A?
An agent is anything that can be viewed as perceiving its environment through sensors and Sensor acting upon that environment through actuators -- Stuart Russel and Peter Norvig.
Borrowed from Artificial Intelligence: A Modern Approach Fourth Edition
Percepts
class SystemMessage(BaseModel): role: Literal["system"] = "system" content: str class UserMessage(BaseModel): role: Literal["user"] = "user" content: str class AssistantMessage(BaseModel): role: Literal["assistant"] = "assistant" content: str percept_seq: List[Union[SystemMessage, UserMessage, AssistantMessage]] = []
Table of actions
class DefaultFunc(OpenAISchema): response: str def run(self): msg = f"DefaultFunc->run: {self.response}" return msg class UserFunc(OpenAISchema): name: str age: int def run(self): msg = f"UserFunc->run: User's name is {self.name} and age is {self.age}" return msg toolbox = [DefaultFunc, UserFunc]
Actions and Actuator
def actuate(self, tool_call: ChatCompletionMessageToolCall): Func = next(iter([func for func in toolbox if func.__name__ == tool_call.function.name])) if not Func: available_function_names = [func.__name__ for func in toolbox] err_msg = f"Error: Function {tool_call.function.name} not found. Available functions: {available_function_names}" console.error(err_msg) return err_msg try: console.log(f"Tool Call -> {tool_call.function.name} ->with {tool_call.function.arguments} of type {type(tool_call.function.arguments)}", style="bold blue") args = from_json(tool_call.function.arguments) console.log(f"Args -> {args} of type {type(args)}", style="bold blue") func = Func.model_validate(args) console.log(f"Func -> {repr(func)}", style="bold blue") output = func.run() return output except Exception as e: return f"Error: {e}"
An attempt at Agent Design
This diagram helps visualize the flow of actions and thoughts through the agents, ensuring a structured and iterative approach to reaching the final outcome.
graph TD A[Start: Think about the prompt] --> B[Derive inputs] B --> T1{Toolbox} T1 -->|Tool 1| T2[Think about results of Tool 1] T1 -->|Tool 2| T3[Think about results of Tool 2] T1 -->|Tool 3| T4[Think about results of Tool 3] T1 -->|Tool 4| T5[Think about results of Tool 4] T1 -->|Tool 5| T6[Think about results of Tool 5] T2 --> T7{Toolbox} T3 --> T7 T4 --> T7 T5 --> T7 T6 --> T7 T7 -->|Tool 1| T8[Think about results of Tool 1] T7 -->|Tool 2| T9[Think about results of Tool 2] T7 -->|Tool 3| T10[Think about results of Tool 3] T7 -->|Tool 4| T11[Think about results of Tool 4] T7 -->|Tool 5| T12[Think about results of Tool 5] T8 --> T13{Toolbox} T9 --> T13 T10 --> T13 T11 --> T13 T12 --> T13 T13 -->|Tool 1| T14[Final result from Tool 1] T13 -->|Tool 2| T15[Final result from Tool 2] T13 -->|Tool 3| T16[Final result from Tool 3] T13 -->|Tool 4| T17[Final result from Tool 4] T13 -->|Tool 5| T18[Final result from Tool 5] T14 --> F[Final Result] T15 --> F T16 --> F T17 --> F T18 --> F style A fill:#f9f,stroke:#333,stroke-width:2px; style B fill:#bbf,stroke:#333,stroke-width:2px; style T1 fill:#bfb,stroke:#333,stroke-width:2px; style T2 fill:#ff9,stroke:#333,stroke-width:2px; style T3 fill:#ff9,stroke:#333,stroke-width:2px; style T4 fill:#ff9,stroke:#333,stroke-width:2px; style T5 fill:#ff9,stroke:#333,stroke-width:2px; style T6 fill:#ff9,stroke:#333,stroke-width:2px; style T7 fill:#bfb,stroke:#333,stroke-width:2px; style T8 fill:#ff9,stroke:#333,stroke-width:2px; style T9 fill:#ff9,stroke:#333,stroke-width:2px; style T10 fill:#ff9,stroke:#333,stroke-width:2px; style T11 fill:#ff9,stroke:#333,stroke-width:2px; style T12 fill:#ff9,stroke:#333,stroke-width:2px; style T13 fill:#bfb,stroke:#333,stroke-width:2px; style T14 fill:#f99,stroke:#333,stroke-width:2px; style T15 fill:#f99,stroke:#333,stroke-width:2px; style T16 fill:#f99,stroke:#333,stroke-width:2px; style T17 fill:#f99,stroke:#333,stroke-width:2px; style T18 fill:#f99,stroke:#333,stroke-width:2px; style F fill:#9f9,stroke:#333,stroke-width:2px;
Explanation
Start: Think about the prompt: The process begins with the agent considering the given prompt.
Derive inputs: The agent derives the necessary inputs to decide which tool(s) to use from the toolbox.
Toolbox: The agent has access to a toolbox containing 5 different tools. Based on the derived inputs, the agent selects a tool.
Think about results of Tool: After using the first tool, the agent thinks about the results it obtained.
Sequential tool invocation: The agent may decide to invoke a second and even a third tool based on the intermediate results.
Final result: Eventually, the agent yields the final result after processing through the necessary tools and intermediate thinking steps.
#+begin_src python
from instructor import OpenAISchema
from getting_started_with_ai_agents.agents.club_bouncer import ( ClubBouncer, Person, Guest, ) from getting_started_with_ai_agents.llm import gen_client, SystemMessage, UserMessage
client = gen_client()
class ClubSecurity(OpenAISchema): """ Security agent for Club UbuntuTechHive. Helps the bouncer manage the line and check the guest list following the club's rules. if the person is at least 21 years old and has at least $20 in cash, they can enter the club. if the person is on the guest list, they can enter the club. if the person is a VIP, they must have at least $1000 in cash to get table service. """
name: str # name of the person age: int # age of the person cash: float # amount of cash the person has is_on_guest_list: bool # whether the person is on the guest list
def run(self): person = Person( name=self.name, age=self.age, cash=self.cash, is_on_guest_list=self.is_on_guest_list, ) return person
class ClubHost(OpenAISchema): """ Hostess for Club UbuntuTechHive. Collects the cover charge and assigns tickets to guests. Checks the guest list and assigns guests to the VIP line. Manages the VIPs and table service. Accepts VIPs with at least $1000 in cash and table service requests. Accepts payment for table service and assigns tables to VIPs. if the person has money for a ticket, let them buy the ticket and mark them as having a ticket using a wristband. if guest is on the guest list, mark them as present on the club's copy of the guest list and let them in. if guest has $1000 in cash, they are a VIP, mark them as VIP, then lead them to a free table. """
name: str # name of the person age: int # age of the person cash: float # amount of cash the person has has_ticket: bool = False # whether the person has a ticket is_on_guest_list: bool = False # whether the person is on the guest list is_vip: bool = False # whether the person is a VIP
def run(self): guest = Guest( name=self.name, age=self.age, cash=self.cash, has_ticket=self.has_ticket, is_on_guest_list=self.is_on_guest_list, is_vip=self.is_vip, ) return guest
bouncer = ClubBouncer( context=[ SystemMessage( content=""" Welcome to Club UbuntuTechHive! I am the Club Bouncer. I will be managing the line tonight for the club tonight. I will be deciding who can enter the club. My decisions are based on the following criteria:
The person must be at least 21 years old.
The person must have at least $20 in cash.
The person must have a ticket or be on the guest list.
There will be a $20 cover charge for those without a ticket or not on the guest list.
VIPs must have at least $1000 in cash to get table service.
Table service is available for VIPs only if there are a limited number of tables available.
When no tables are available, VIPs must wait on the VIP line for a table to become available. """ ) ], capacity=100, table_count=10, client=client, toolbox=[ClubSecurity, ClubHost],
)
if name == "__main__": bouncer.manage_line( UserMessage( content=""" The person is John Doe and is 25 years old with $50 in cash. They on the guest list. """ ) )
bouncer.manage_line( UserMessage( content=""" Lambert is 21 years old with $20 in cash. They want to purchase a ticket. """ ) )
#+end_src
Conclusion
This field is moving fast and there are few experts. Don't be afraid to read and learn and code to gain understanding. Then decide for yourself wether to adopt a library that suits your needs or make up your own!
References
ReAct (Reason + Act): Synergizing Reasoning and Acting in Language Models (Github)
Self-Refine: Iterative Refinement with Self-Feedback (Github)
Flow Engineering: Code Generation with AlphaCodium: From Prompt Engineering to Flow Engineering (Github)