Sync means one after another. For example, calling 3 functions named f1, f2, and f3. Assume f1 performs some I/O operations like a DB query, API request, or file operation. After f1 is completed, f2 and f3 will be executed.
There are some operations that are running on top of the CPU.
E.g.
def add(a, b):
return a + b
When we call this function, it will be executed by the CPU.
And some operations do not utilize the CPU, i.e., I/O operations.
def getweatherdetails():
return request to HTTP API
Here, to send a request, the CPU will be utilized. After sending the request, the CPU will not be used until we get the response from the third party. We need to wait for some time.
In this case, if the main function is calling all 3 functions one by one, we have to wait for f1 to get the response before moving to f2, and so on.
def main():
f1()
f2()
f3()
Here, in Async, after sending the request to the third party, f2 will be performed without waiting for the response from the third party. Async means no waiting (context switching) and will be used only in I/O operations.
Async will be implemented in Python using a package called asyncio.
Here, make_toast() will be called first, and during the waiting time, make_tea() will be called.
By default, the output that comes from the LLM will not be structured. It will be in text format. Either we should structure it by writing code or use a prompt that is fed into the LLM so that the output can be used to take further action.
Python is a dynamically typed language.
age = 12
age = "12"
Here, the data type of the variable age is converted from int to string. Even though there are many benefits to dynamic typing, some problems may arise.
The response from the LLM will be in text format. So, we have to parse it using a regular expression or get the output in the desired format by creating a data structure. So, the LLM must adhere to the format to generate the output.
Example:
Data structure called:
{
"name": "string",
"age": "int"
}
So, we can access the name by using user.name.
Before accessing it, we have to do validation to check the correctness. Data validation will not be applied implicitly to control the data. It will increase the dumb code, which affects the readability and maintainability of the code.
To solve this problem, there is a package called Pydantic. This package will control the data validation. So, we can totally rely on the objects that are produced by Pydantic.
from pydantic import BaseModel, Field
class User(BaseModel):
name: str
age: int = Field(gt=0)
user = User(name="somename", age=30)
print(user)
To add more implicit conditions, we have to import the Field class. Here, we are saying that age should be greater than 0.