In Half 1 of this tutorial sequence, we launched AI Brokers, autonomous packages that carry out duties, make selections, and talk with others.
Brokers carry out actions via Instruments. It’d occur {that a} Device doesn’t work on the primary strive, or that a number of Instruments have to be activated in sequence. Brokers ought to have the ability to set up duties right into a logical development and alter their methods in a dynamic setting.
To place it merely, the Agent’s construction have to be strong, and the conduct have to be dependable. The commonest manner to do this is thru:
- Iterations – repeating a sure motion a number of instances, usually with slight adjustments or enhancements in every cycle. Each time would possibly contain the Agent revisiting sure steps to refine its output or attain an optimum answer.
- Chains – a sequence of actions which can be linked collectively in a sequence. Every step within the chain depends on the earlier one, and the output of 1 motion turns into the enter for the following.
On this tutorial, I’m going to point out the way to use iterations and chains for Brokers. I’ll current some helpful Python code that may be simply utilized in different related instances (simply copy, paste, run) and stroll via each line of code with feedback so as to replicate this instance (hyperlink to full code on the finish of the article).
Setup
Please seek advice from Half 1 for the setup of Ollama and the primary LLM.
import Ollama
llm = "qwen2.5"
We’ll use the YahooFinance public APIs with the Python library (pip set up yfinance==0.2.55
) to obtain monetary knowledge.
import yfinance as yf
inventory = "MSFT"
yf.Ticker(ticker=inventory).historical past(interval='5d') #1d,5d,1mo,3mo,6mo,1y,2y,5y,10y,ytd,max
Let’s embed that right into a Device.
import matplotlib.pyplot as plt
def get_stock(ticker:str, interval:str, col:str):
knowledge = yf.Ticker(ticker=ticker).historical past(interval=interval)
if len(knowledge) > 0:
knowledge[col].plot(coloration="black", legend=True, xlabel='', title=f"{ticker.higher()} ({interval})").grid()
plt.present()
return 'okay'
else:
return 'no'
tool_get_stock = {'kind':'perform', 'perform':{
'identify': 'get_stock',
'description': 'Obtain inventory knowledge',
'parameters': {'kind': 'object',
'required': ['ticker','period','col'],
'properties': {
'ticker': {'kind':'str', 'description':'the ticker image of the inventory.'},
'interval': {'kind':'str', 'description':"for 1 month enter '1mo', for six months enter '6mo', for 1 12 months enter '1y'. Use '1y' if not specified."},
'col': {'kind':'str', 'description':"considered one of 'Open','Excessive','Low','Shut','Quantity'. Use 'Shut' if not specified."},
}}}}
## take a look at
get_stock(ticker="msft", interval="1y", col="Shut")
Furthermore, taking the code from the earlier article as a reference, I shall write a normal perform to course of the mannequin response, akin to when the Agent desires to make use of a Device or when it simply returns textual content.
def use_tool(agent_res:dict, dic_tools:dict) -> dict:
## use instrument
if "tool_calls" in agent_res["message"].keys():
for instrument in agent_res["message"]["tool_calls"]:
t_name, t_inputs = instrument["function"]["name"], instrument["function"]["arguments"]
if f := dic_tools.get(t_name):
### calling instrument
print('🔧 >', f"x1b[1;31m{t_name} -> Inputs: {t_inputs}x1b[0m")
### tool output
t_output = f(**tool["function"]["arguments"])
print(t_output)
### last res
res = t_output
else:
print('🤬 >', f"x1b[1;31m{t_name} -> NotFoundx1b[0m")
## don't use tool
if agent_res['message']['content'] != '':
res = agent_res["message"]["content"]
t_name, t_inputs = '', ''
return {'res':res, 'tool_used':t_name, 'inputs_used':t_inputs}
Let’s begin a fast dialog with our Agent. For now, I’m going to make use of a easy generic immediate.
immediate = '''You're a monetary analyst, help the person utilizing your out there instruments.'''
messages = [{"role":"system", "content":prompt}]
dic_tools = {'get_stock':get_stock}
whereas True:
## person enter
strive:
q = enter('🙂 >')
besides EOFError:
break
if q == "stop":
break
if q.strip() == "":
proceed
messages.append( {"position":"person", "content material":q} )
## mannequin
agent_res = ollama.chat(mannequin=llm, messages=messages,
instruments=[tool_get_stock])
dic_res = use_tool(agent_res, dic_tools)
res, tool_used, inputs_used = dic_res["res"], dic_res["tool_used"], dic_res["inputs_used"]
## last response
print("👽 >", f"x1b[1;30m{res}x1b[0m")
messages.append( {"role":"assistant", "content":res} )
As you can see, I started by asking an “easy” question. The LLM already knows that the symbol of Microsoft stock is MSFT, therefore the Agent was able to activate the Tool with the right inputs. But what if I ask something that might not be included in the LLM knowledge base?
Seems that the LLM doesn’t know that Facebook changed its name to META, so it used the Tool with the wrong inputs. I will enable the Agent to try an action several times through iterations.
Iterations
Iterations refer to the repetition of a process until a certain condition is met. We can let the Agent try a specific number of times, but we need to let it know that the previous parameters didn’t work, by adding the details in the message history.
max_i, i = 3, 0
while res == 'no' and i < max_i:
comment = f'''I used tool '{tool_used}' with inputs {inputs_used}. But it didn't work, so I must try again with different inputs'''
messages.append( {"role":"assistant", "content":comment} )
agent_res = ollama.chat(model=llm, messages=messages,
tools=[tool_get_stock])
dic_res = use_tool(agent_res, dic_tools)
res, tool_used, inputs_used = dic_res["res"], dic_res["tool_used"], dic_res["inputs_used"]
i += 1
if i == max_i:
res = f'I attempted {i} instances however one thing is flawed'
## last response
print("👽 >", f"x1b[1;30m{res}x1b[0m")
messages.append( {"role":"assistant", "content":res} )
The Agent tried 3 times with different inputs but it couldn’t find a solution because there is a gap in the LLM knowledge base. In this case, the model needed human input to understand how to use the Tool.
Next, we’re going to enable the Agent to fill the knowledge gap by itself.
Chains
A chain refers to a linear sequence of actions where the output of one step is used as the input for the next step. In this example, I will add another Tool that the Agent can use in case the first one fails.
We can use the web-searching Tool from the previous article.
from langchain_community.tools import DuckDuckGoSearchResults
def search_web(query:str) -> str:
return DuckDuckGoSearchResults(backend="news").run(query)
tool_search_web = {'type':'function', 'function':{
'name': 'search_web',
'description': 'Search the web',
'parameters': {'type': 'object',
'required': ['query'],
'properties': {
'question': {'kind':'str', 'description':'the subject or topic to look on the net'},
}}}}
## take a look at
search_web(question="fb inventory")
Up to now, I’ve all the time used very generic prompts because the duties had been comparatively easy. Now, I wish to guarantee that the Agent understands the way to use the Instruments in the proper order, so I’m going to put in writing a correct immediate. That is how a immediate ought to be finished:
- The objective of the Agent
- What it should return (i.e. format, content material)
- Any related warnings which may have an effect on the output
- Context dump
immediate = '''
[GOAL] You're a monetary analyst, help the person utilizing your out there instruments.
[RETURN] It's essential to return the inventory knowledge that the person asks for.
[WARNINGS] With the intention to retrieve inventory knowledge, it's worthwhile to know the ticker image of the corporate.
[CONTEXT] First ALWAYS attempt to use the instrument 'get_stock'.
If it would not work, you should utilize the instrument 'search_web' and search 'firm identify inventory'.
Get details about the inventory and deduct what's the proper ticker image of the corporate.
Then, you should utilize AGAIN the instrument 'get_stock' with the ticker you bought utilizing the earlier instrument.
'''
We will merely add the chain to the iteration loop that we have already got. This time the Agent has two Instruments, and when the primary fails, the mannequin can determine whether or not to retry or to make use of the second. Then, if the second Device is used, the Agent should course of the output and be taught what’s the proper enter for the primary Device that originally failed.
max_i, i = 3, 0
whereas res in ['no',''] and that i < max_i:
remark = f'''I used instrument '{tool_used}' with inputs {inputs_used}. Nevertheless it did not work, so I have to strive a special manner.'''
messages.append( {"position":"assistant", "content material":remark} )
agent_res = ollama.chat(mannequin=llm, messages=messages,
instruments=[tool_get_stock, tool_search_web])
dic_res = use_tool(agent_res, dic_tools)
res, tool_used, inputs_used = dic_res["res"], dic_res["tool_used"], dic_res["inputs_used"]
## chain: output of earlier instrument = enter of subsequent instrument
if tool_used == 'search_web':
question = q+". It's essential to return simply the compay ticker.nContext: "+res
llm_res = ollama.generate(mannequin=llm, immediate=question)["response"]
messages.append( {"position":"person", "content material":f"strive ticker: {llm_res}"} )
print("👽 >", f"x1b[1;30mI can try with {llm_res}x1b[0m")
agent_res = ollama.chat(model=llm, messages=messages, tools=[tool_get_stock])
dic_res = use_tool(agent_res, dic_tools)
res, tool_used, inputs_used = dic_res["res"], dic_res["tool_used"], dic_res["inputs_used"]
i += 1 if i == max_i: res = f'I attempted {i} instances however one thing is flawed'
## last response
print("👽 >", f"x1b[1;30m{res}x1b[0m")
messages.append( {"position":"assistant", "content material":res} )
As anticipated, the Agent tried to make use of the primary Device with the flawed inputs, however as an alternative of attempting the identical motion once more as earlier than, it determined to make use of the second Device. By consuming data, it ought to perceive the answer with out the necessity for human enter.
In abstract, the AI tried to do an motion however failed as a consequence of a spot in its data base. So it activated Instruments to fill that hole and ship the output requested by the person… that’s certainly the true essence of AI Brokers.
Conclusion
This text has lined extra structured methods to make Brokers extra dependable, utilizing iterations and chains. With these constructing blocks in place, you’re already outfitted to start out creating your individual Brokers for various use instances.
Keep tuned for Half 3, the place we’ll dive deeper into extra superior examples.
Full code for this text: GitHub
I hope you loved it! Be happy to contact me for questions and suggestions or simply to share your attention-grabbing tasks.
👉 Let’s Join 👈