A Task-based agentic framework building on StrictJSON outputs by LLM agents
Project description
TaskGen v0.0.4
A Task-based agentic framework building on StrictJSON outputs by LLM agents
- Related Repositories: StrictJSON (https://github.com/tanchongmin/strictjson)
TaskGen functionalities
- Task-based Agents which will break down tasks into subtasks and solve them in bite-sized portions
- Agents with registered functions as skills
- Hierarchical Agents which can call other Agents as functions
- Shared Variables between functions to handle non-text modalities as well as very long text
Upcoming Agent Functionalities (coming soon!)
- Retrieval Augmented Generation (RAG) - based selection of functions (to be added)
- RAG-based selection of memory of few-shot examples of how to use functions and how to perform task based on similar tasks done in the past (to be added)
Benefits of JSON messaging over agentic frameworks using conversational free-text like AutoGen
- JSON format helps do Chain-of-Thought prompting naturally and is less verbose than free text
- JSON format allows natural parsing of multiple output fields by agents
- StrictJSON helps to ensure all output fields are there and of the right format required for downstream processing
Tutorials and Community Support
- Created: 17 Feb 2024 by John Tan Chong Min
- Collaborators welcome
- Discussion Channel (my discord - John's AI Group): discord.gg/bzp87AHJy5
How do I use this?
- Download package via command line
pip install taskgen-ai
- Set up your OpenAPI API Key
- Import the required functions from
taskgen
and use them!
Agent Basics
- Create an agent by entering your agent's name and description
- Agents are task-based, so they will help generate subtasks to fulfil your main task
- Agents are made to be non-verbose, so they will just focus only on task instruction (Much more efficient compared to conversational-based agentic frameworks like AutoGen)
Example Agent Creation
my_agent = Agent('Helpful assistant', 'You are a generalist agent')
Example Agent Task Running - Split the assigned task into subtasks and execute each of them
output = my_agent.run('Give me 5 words rhyming with cool, and make a 4-sentence poem using them')
Subtask identified: Find 5 words that rhyme with 'cool'
Getting LLM to perform the following task: Find 5 words that rhyme with 'cool'
pool, rule, fool, tool, school
Subtask identified: Compose a 4-sentence poem using the words 'pool', 'rule', 'fool', 'tool', and 'school'
Getting LLM to perform the following task: Compose a 4-sentence poem using the words 'pool', 'rule', 'fool', 'tool', and 'school'
In the school, the golden rule is to never be a fool. Use your mind as a tool, and always follow the pool.
Task completed successfully!
Example Agent Reply to User - Reference the subtasks' output to answer the user's query
output = my_agent.reply_user()
Here are 5 words that rhyme with "cool": pool, rule, fool, tool, school. Here is a 4-sentence poem using these words: "In the school, the golden rule is to never be a fool. Use your mind as a tool, and always follow the pool."
Check Agent's Status
my_agent.status()
Agent Name: Helpful assistant
Agent Description: You are a generalist agent
Available Functions: ['use_llm', 'end_task']
Task: Give me 5 words rhyming with cool, and make a 4-sentence poem using them
Subtasks Completed:
Subtask: Find 5 words that rhyme with 'cool'
pool, rule, fool, tool, school
Subtask: Compose a 4-sentence poem using the words 'pool', 'rule', 'fool', 'tool', and 'school'
In the school, the golden rule is to never be a fool. Use your mind as a tool, and always follow the pool.
Is Task Completed: True
Functions
-
Provides a function-like interface for repeated use of modular LLM-based functions (or wraps external functions for use with TaskGen)
-
Use angle brackets <> to enclose input variable names. First input variable name to appear in
fn_description
will be first input variable and second to appear will be second input variable. For example,fn_description = 'Adds up two numbers, <var1> and <var2>'
will result in a function with first input variablevar1
and second input variablevar2
-
(Optional) If you would like greater specificity in your function's input, you can describe the variable after the : in the input variable name, e.g.
<var1: an integer from 10 to 30
. Here,var1
is the input variable andan integer from 10 to 30
is the description. -
Inputs (compulsory):
- fn_description: String. Function description to describe process of transforming input variables to output variables. Variables must be enclosed in <> and listed in order of appearance in function input.
- output_format: String. Dictionary containing output variables names and description for each variable. Refer to StrictJSON-Overview.ipynb for details on type checking for
output_format
-
Inputs (optional):
- examples - Dict or List[Dict]. Examples in Dictionary form with the input and output variables (list if more than one)
- external_fn - Python Function. If defined, instead of using LLM to process the function, we will run the external function.
If there are multiple outputs of this function, we will map it to the keys of
output_format
in a one-to-one fashion - fn_name - String. If provided, this will be the name of the function. Ohterwise, if
external_fn
is provided, it will be the name ofexternal_fn
. Otherwise, we will use LLM to generate a function name from thefn_description
- kwargs - Dict. Additional arguments you would like to pass on to the
strict_json
function
-
Outputs: JSON of output variables in a dictionary
Example Internal LLM-Based Function
# Construct the function: var1 will be first input variable, var2 will be second input variable and so on
sentence_style = Function(fn_description = 'Output a sentence with words <var1> and <var2> in the style of <var3>',
output_format = {'output': 'sentence'})
# Use the function
sentence_style('ball', 'dog', 'happy') #var1, var2, var3
Example Output
{'output': 'The happy dog chased the ball.'}
Example External Function
def binary_to_decimal(x):
return int(str(x), 2)
# an external function with a single output variable, with an expressive variable description
b2d = Function(fn_description = 'Convert input <x: a binary number in base 2> to base 10',
output_format = {'output1': 'x in base 10'},
external_fn = binary_to_decimal)
# Use the function
b2d(10) #x
Example Output
{'output1': 2}
Power Up your Agents - Bring in Functions (aka Tools)
- After creating your agent, use
assign_functions
to assign a list of functions (of class Function) to it - Function names will be automatically inferred if not specified
- Proceed to run tasks by using
run()
my_agent = Agent('Helpful assistant', 'You are a generalist agent')
my_agent.assign_functions([sentence_style, b2d])
output = my_agent.run('Generate me a happy sentence with a number and a ball. The number is 1001 converted to decimal')
Subtask identified: Convert the binary number 1001 to decimal
Calling function binary_to_decimal with parameters {'x': '1001'}
{'output1': 9}
Subtask identified: Generate a happy sentence with the decimal number and a ball
Calling function sentence_with_objects_entities_emotion with parameters {'obj': '9', 'entity': 'ball', 'emotion': 'happy'}
{'output': 'I am so happy with my 9 balls.'}
Task completed successfully!
Inception: Agents within Agents
- You can also create a Meta Agent that uses other Agents (referred to as Inner Agents) as functions
- Create your Meta agent using
Agent()
(Note: No different from usual process of creating Agents - your Meta Agent is also an Agent) - Set up an Inner Agent list and assign it to your Meta agent using
assign_agents(agent_list)
Example Meta Agent Setup
# Define your meta-agent
my_agent = Agent('Menu Creator',
'Creates a menu for a restaurant. Menu item includes Name, Description, Ingredients, Pricing.')
# Define your agent list. Note you can just assign functions to the agent in place using .assign_functions(function_list)
agent_list = [
Agent('Chef', 'Takes in dish names and comes up with ingredients for each of them. Does not generate prices.'),
Agent('Boss', 'Takes in menu items and curates them according to price'),
Agent('Creative Writer', 'Takes in a cuisine type and generates interesting dish names and descriptions. Does not generate prices or ingredients.', max_subtasks = 2),
Agent('Economist', 'Takes in dish names and comes up with fictitious pricing for each of them')
]
my_agent.assign_agents(agent_list)
Run the Meta Agent
- Let us run the agent and see the interactions between the Meta Agent and Inner Agents to solve the task!
output = my_agent.run('Give me 5 menu items with name, description, ingredients and price based on Italian food choices.')
Shared Variables
"Because text is not enough" - Anonymous
shared_variables
is a dictionary, that is initialised in Agent (default empty dictionary), and can be referenced by any function of the agent (including Inner Agents and their functions)- This can be useful for non-text modalitiies (e.g. audio, pdfs, image) and lengthy text modalities, which we do not want to output into
subtasks_completed
directly s_
at the start of the variable names means shared variables- For input, it means we take the variable from
shared_variables
instead of LLM generated input - For output, it means we store the variable into
shared_variables
instead of storing it insubtasks_completed
. Ifsubtasks_completed
output is empty, it will be output as{'Status': 'Completed'}
- For input, it means we take the variable from
- Example shared variables names:
s_sum
,s_total
,s_list_of_words
Example Input
# Function takes in increment (LLM generated) and s_total (retrieves from shared variable dict), and outputs to s_total (in shared variable dict)
add = Function(fn_description = "Add <increment: int> to <s_total>",
output_format = {"s_total": "Modified total"})
# Define the calculator agent and the shared_variables - Note the naming convention of s_ at the start of the names for shared variables
my_agent = Agent('Calculator', 'Does computations', shared_variables = {'s_total': 0}).assign_functions([add])
output = my_agent.run('Increment total by 1')
print('Shared Variables:', my_agent.shared_variables)
Example Output
Subtask identified: Add 1 to the total
Calling function add_int_to_variable with parameters {'increment': 1}
{'Status': 'Completed'}
Task completed successfully!
Shared Variables: {'s_total': 1}
Example External Function Accessing Shared Variables (Advanced)
# Use shared_variables as input to your external function to access and modify the shared variables
def generate_quotes(shared_variables, number_of_quotes: int, category: str):
''' Adds a quote to the quote list '''
# Retrieve from shared variables
my_quote_list = shared_variables['s_quote_list']
### Add your function code here ###
# Store back to shared variables
shared_variables['s_quote_list'] = my_quote_list
generate_quote_fn = Function(fn_description = "Generates <number_of_quotes: int> quotes about <category: str>",
output_format = {},
external_fn = generate_quotes)
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for taskgen_ai-0.0.4-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | aa0fea6007c826bada60bfeb293e52f30792b90674ca8b7fbef477a61d1e0802 |
|
MD5 | eb368ca9bd279580dd34509f0729dedf |
|
BLAKE2b-256 | ce3a0e6eb4fc098bd45e04235fce4f793b7ef6374a7cae9274ba85965025f493 |