Create a agent
It is now very common to use a Large Language Model is to generate text. An immediate application of this principle is to obtain an answer to a question formulated in natural language, and it has proven to be very effective.
The next step is to leverage the LLM to implement autonomous goal-driven agents.
An LLM agent is meant to not only be able to interact with a user through a human-like conversation, but also to behave according to a given goal. It will impact its tone, its style, its vocabulary, its domain of expertise, or even its opinions.
For the user, it results in a more human-like experience, and it can be extremely useful in many situations, typically a customer support service, or more generally whenever the user is not an expert in a domain and needs guidance.
In this article, we will see how to build an LLM agent with Nuclia.
Implement an agent with the Nuclia Python SDK
Let try to implement a city guide agent. We will use information from Wikipedia to build our agent.
First you need to install the Nuclia Python SDK.
Then, you need a Nuclia account. You can sign up for free.
Once you have an account, you will have a default Knowledge Box, and you can create an API key to access it from your Python script.
Now, let's create a Python script to ingest Wikipedia articles in your Knowledge Box: ingest.py
:
It will start with the authentication part:
from nuclia import sdk
import requests
auth = sdk.NucliaAuth()
auth.kb(
url="https://europe-1.nuclia.cloud/api/v1/kb/<YOUR-KB-ID>",
token="YOUR-API-KEY",
interactive=False
)
Then you will use the Wikipedia API to retrieve the content of the articles and store them in your Nuclia Knowledge Box:
nuclia_resources = sdk.NucliaResource()
wiki_titles = ["Toronto", "Seattle", "Chicago", "Boston", "Houston"]
for title in wiki_titles:
response = requests.get(
"https://en.wikipedia.org/w/api.php",
params={
"action": "query",
"format": "json",
"titles": title,
"prop": "extracts",
"explaintext": True,
},
).json()
page = next(iter(response["query"]["pages"].values()))
wiki_text = page["extract"]
wiki_id = page["pageid"]
nuclia_resources.create(
slug=wiki_id,
icon="text/plain",
texts={
"wikipedia": {
"body": wiki_text,
}
}
)
You can check on your Knowledge Box that the resources have been created. They will not be instantly available for search, because Nuclia needs to process them first. You can check the status of the processing on the Nuclia Dashboard or with the CLI:
nuclia kb list
Once they are fully processed (after few minutes), you have searchable information about 5 different cities. And you would like to use that to deliver specific city guides to your users.
You could go with a very straightforward approach, and just use generative answer feature of Nuclia
search = sdk.NucliaSearch()
answer = search.chat(query="Tell me about the parks in Toronto")
print(answer.answer)
You obtain the following answer:
Toronto has a diverse array of public spaces, from city squares to public parks overlooking ravines. Nathan Phillips Square is the city's main square in downtown, contains the Toronto Sign, and forms the entrance to City Hall. Yonge\xe2\x80\x93Dundas Square, near City Hall, has also gained attention in recent years as one of the busiest gathering spots in the city. Other squares include Harbourfront Square, on the Toronto waterfront, and the civic squares at the former city halls of the defunct Metropolitan Toronto, most notably Mel Lastman Square in North York. The Toronto Public Space Committee is an advocacy group concerned with the city's public spaces. In recent years, Nathan Phillips Square has been refurbished with new facilities, and the central waterfront along Queen's Quay West has been updated recently with a new street architecture and a new square next to Harbourfront Centre.\nThere are many large downtown parks, which include Allan Gardens, Christie Pits, Grange Park, Little Norway Park, Moss Park, Queen's Park, Riverdale Park and Trinity Bellwoods Park. An almost hidden park is the compact Cloud Gardens, which has both open areas and a glassed-in greenhouse, near Queen and Yonge. South of downtown are two large parks on the waterfront: Tommy Thompson Park on the Leslie Street Spit, which has a nature preserve, is open on weekends; and the Toronto Islands, accessible from downtown by ferry.\nIn the winter, Nathan Phillips Square, Harbourfront Centre, and Mel Lastman Square feature popular rinks for public ice-skating. Etobicoke's Colonel Sam Smith Trail opened in 2011 and is Toronto's first skating trail. Centennial Park and Earl Bales Park offer outdoor skiing and snowboarding slopes with a chairlift, rental facilities, and lessons. Several parks have marked cross-country skiing trails.
That's nice, and actually you can change the generative LLM model used by Nuclia to obtain different results:
nuclia_kb = sdk.NucliaKB()
nuclia_kb.set_configuration(generative_model="chatgpt-azure-4o")
# nuclia_kb.set_configuration(generative_model="claude-3-fast")
# nuclia_kb.set_configuration(generative_model="gemini-1-5-pro-vision")
# and there are more…
And check how it affects the answer.
But, that is not enough to build a real agent. Here, for example, you are expecting the user to mention explicitly "Toronto" in their question, if they don't they might get wrong information.
You need to be able to control the answer, and to do that, we need to shape a specific prompt to produce the expected behaviour.
Shaping a good prompt is difficult, and I am lazy (I think engineering is nothing more than the systematization process of laziness), so Nuclia leverages its generative model to do that for us!
Let's create a Python script to build the agent: agent.py
:
- Here again, you start with the authentication part, but this time you need to authenticate both to your Knowledge Box (to perform search against the resources you have created) and to the Nuclia Understanding API service (to generate the agent):
from nuclia import sdk
auth = sdk.NucliaAuth()
auth.kb(
url="https://europe-1.nuclia.cloud/api/v1/kb/<YOUR-KB-ID>",
token="YOUR-API-KEY",
interactive=False
)
nua = auth.nua("europe-1", "NUA-KEY")
nuas = sdk.NucliaNUAS()
nuas.default(nua)
To generate the agent, you use the generate_agent
method, indicating the topic and the domain of expertise of the agent:
nuclia_agent = sdk.NucliaAgent()
toronto_agent = nuclia_agent.generate_agent("Toronto", "city guide")
Now you have a Toronto city guide agent which is fully aware of its mission, and you can ask it questions:
answer = toronto_agent.ask("Tell me about the parks")
print(answer)
Toronto has a diverse array of public spaces, from city squares to public parks overlooking ravines. There are many large downtown parks, which include Allan Gardens, Christie Pits, Grange Park, Little Norway Park, Moss Park, Queen's Park, Riverdale Park and Trinity Bellwoods Park. An almost hidden park is the compact Cloud Gardens, which has both open areas and a glassed-in greenhouse, near Queen and Yonge. South of downtown are two large parks on the waterfront: Tommy Thompson Park on the Leslie Street Spit, which has a nature preserve, is open on weekends; and the Toronto Islands, accessible from downtown by ferry. Large parks in the outer areas managed by the city include High Park, Humber Bay Park, Centennial Park, Downsview Park, Guild Park and Gardens, Sunnybrook Park and Morningside Park. Morningside Park is the largest park managed by the city, which is 241.46 hectares (596.7 acres) in size. In addition to public parks managed by the municipal government, parts of Rouge National Urban Park, the largest urban park in North America, is in the eastern portion of Toronto.
Perfect! It is definitely what I would expect from a Toronto city guide!
Note: the code examples are available in the Nuclia demos repository.
Not a developer? That's fine!
If you are not a developer, you can still build your own agent, using the different tooling Nuclia provides.
First, you can use the Nuclia Dashboard to upload your resources. Instead of usinbg the Wikipedia API, you can just past the links of the pages you want to index and Nuclia will extract their content automatically.
Then, you can use the CLI to generate the agent prompt
nuclia nua agent generate_prompt --text="Toronto" --agent_definition="city guide"
It will return:
Answer the following question based on the provided context:
[START OF CONTEXT]
{context}
[END OF CONTEXT] Question: "Welcome to Toronto! Our city guide is here to help you explore and discover everything this vibrant city has to offer. Whether you're a local looking for hidden gems or a visitor seeking the best attractions, our guide is ready to answer all your questions about Toronto. From must-visit landmarks and neighborhoods to the top-rated restaurants and entertainment options, we've got you covered. Ask us anything about Toronto, and we'll provide you with the most up-to-date information and recommendations to make your experience in the city unforgettable. Let's start exploring Toronto together!" {question}
You can copy this text and use it as custom user prompt in the Nuclia Dashboard widget editor page.
Note: make sure to select the "Answer generation" option.
The HTML snippet you obtain can be inserted directly in your web site or application, and you will have a fully functional agent!
Conclusion
Obviously that is a simple example, based on very small set of data, but you can imagine how powerful it can be with a large set of data, and a more complex agent.