diff --git a/dictionaries/custom_dict.txt b/dictionaries/custom_dict.txt index 4d405af88..84251b6f8 100644 --- a/dictionaries/custom_dict.txt +++ b/dictionaries/custom_dict.txt @@ -655,3 +655,4 @@ Agentic GPT codegroup SenderAgent +uvicorn diff --git a/pages/examples/intermediate/agent-and-function-api.mdx b/pages/examples/intermediate/agent-and-function-api.mdx index 3171f1e32..83f6fb787 100644 --- a/pages/examples/intermediate/agent-and-function-api.mdx +++ b/pages/examples/intermediate/agent-and-function-api.mdx @@ -1,3 +1,5 @@ +import { CodeGroup } from "../../../components/code" + # Agents and Functions Creation using APIs ## Introduction @@ -26,48 +28,113 @@ This example provides details on how to create Agents and respective Agent Funct - Open terminal and create a directory `agents` using `mkdir agents`. - Create a python file `agent.py` in this directory and include the following sample script in the Python file. -```python copy filename = 'agent.py' -import requests -from ai_engine import UAgentResponse, UAgentResponseType + + ```python copy filename="local-agent.py" + import requests + from ai_engine import UAgentResponse, UAgentResponseType -class Coordinates(Model): - location: str + class Coordinates(Model): + location: str -location_protocol = Protocol("Location Coordinates") + # First generate a secure seed phrase (e.g. https://pypi.org/project/mnemonic/) + SEED_PHRASE = "put_your_seed_phrase_here" + # Now go to https://agentverse.ai, register your agent in the Mailroom by providing the address you just copied. + # Then, copy the agent's mailbox key and insert it here below inline + AGENT_MAILBOX_KEY = "put_your_AGENT_MAILBOX_KEY_here" -async def location_coordinates(latitude, longitude): - url = "https://geocoding-by-api-ninjas.p.rapidapi.com/v1/reversegeocoding" - querystring = {"lat": latitude, "lon": longitude} + # Now your agent is ready to join the agentverse! + location_agent = Agent( + name="location_agent", + seed=SEED_PHRASE, + mailbox=f"{AGENT_MAILBOX_KEY}@https://agentverse.ai", + ) - headers = { - "X-RapidAPI-Key": "YOUR_API_KEY", - "X-RapidAPI-Host": "geocoding-by-api-ninjas.p.rapidapi.com", - } + fund_agent_if_low(location_agent.wallet.address()) - response = requests.get(url, headers=headers, params=querystring) + # Copy the address shown below + print(f"Your agent's address is: {location_agent.address}") - data = response.json()[0]["name"] + location_protocol = Protocol("Location Coordinates") - return data + async def location_coordinates(latitude, longitude): + url = "https://geocoding-by-api-ninjas.p.rapidapi.com/v1/reversegeocoding" + querystring = {"lat": latitude, "lon": longitude} -@location_protocol.on_message(model=Coordinates, replies=UAgentResponse) -async def location_coordinates_calculator(ctx: Context, sender: str, msg: Coordinates): - ctx.logger.info(msg.location) - latitude, longitude = map(str.strip, msg.location.split(",")) - city = location_coordinates(latitude, longitude) - ctx.logger.info(city) - message = city - await ctx.send( - sender, UAgentResponse(message=message, type=UAgentResponseType.FINAL) - ) + headers = { + "X-RapidAPI-Key": "YOUR_API_KEY", + "X-RapidAPI-Host": "geocoding-by-api-ninjas.p.rapidapi.com", + } + response = requests.get(url, headers=headers, params=querystring) -agent.include(location_protocol) -``` + data = response.json()[0]["name"] + + return data + + + @location_protocol.on_message(model=Coordinates, replies=UAgentResponse) + async def location_coordinates_calculator(ctx: Context, sender: str, msg: Coordinates): + ctx.logger.info(msg.location) + latitude, longitude = map(str.strip, msg.location.split(",")) + city = location_coordinates(latitude, longitude) + ctx.logger.info(city) + message = city + await ctx.send( + sender, UAgentResponse(message=message, type=UAgentResponseType.FINAL) + ) + + + location_agent.include(location_protocol) + + location_agent.run() + ``` + + ```python copy filename="hosted-agent.py" + import requests + from ai_engine import UAgentResponse, UAgentResponseType + + + class Coordinates(Model): + location: str + + + location_protocol = Protocol("Location Coordinates") + + + async def location_coordinates(latitude, longitude): + url = "https://geocoding-by-api-ninjas.p.rapidapi.com/v1/reversegeocoding" + querystring = {"lat": latitude, "lon": longitude} + + headers = { + "X-RapidAPI-Key": "YOUR_API_KEY", + "X-RapidAPI-Host": "geocoding-by-api-ninjas.p.rapidapi.com", + } + + response = requests.get(url, headers=headers, params=querystring) + + data = response.json()[0]["name"] + + return data + + + @location_protocol.on_message(model=Coordinates, replies=UAgentResponse) + async def location_coordinates_calculator(ctx: Context, sender: str, msg: Coordinates): + ctx.logger.info(msg.location) + latitude, longitude = map(str.strip, msg.location.split(",")) + city = location_coordinates(latitude, longitude) + ctx.logger.info(city) + message = city + await ctx.send( + sender, UAgentResponse(message=message, type=UAgentResponseType.FINAL) + ) + + agent.include(location_protocol) + ``` + - Create a python file with name `agent_create.py`. diff --git a/pages/examples/intermediate/agents-interval-task.mdx b/pages/examples/intermediate/agents-interval-task.mdx index c0e6241ac..2d5426423 100644 --- a/pages/examples/intermediate/agents-interval-task.mdx +++ b/pages/examples/intermediate/agents-interval-task.mdx @@ -17,7 +17,7 @@ This example shows how to use the uAgents Framework library to set up an interva ### The agent - + ```py copy filename="local-interval-task.py" from uagents import Agent, Context diff --git a/pages/examples/intermediate/coin-toss.mdx b/pages/examples/intermediate/coin-toss.mdx index 16c3c30fd..70fe3a2d5 100644 --- a/pages/examples/intermediate/coin-toss.mdx +++ b/pages/examples/intermediate/coin-toss.mdx @@ -1,3 +1,5 @@ +import { CodeGroup } from "../../../components/code" + # Register a coin toss agent as a Function ## Introduction @@ -25,7 +27,62 @@ To enable this on [DeltaV ↗️](/concepts/ai-engine/deltav) you will need to c ### The agent -```python copy filename="agent.py" + + +```python copy filename="local-agent.py" +import random +from uagents import Agent, Context, Model, Field, Protocol +from uagents.setup import fund_agent_if_low +from ai_engine import UAgentResponse, UAgentResponseType + + +class CoinToss(Model): + choice: str = Field(description="The choice. Must be heads or tails.") + +# First generate a secure seed phrase (e.g. https://pypi.org/project/mnemonic/) +SEED_PHRASE = "put_your_seed_phrase_here" + +# Now go to https://agentverse.ai, register your agent in the Mailroom by providing the address you just copied. +# Then, copy the agent's mailbox key and insert it here below inline +AGENT_MAILBOX_KEY = "put_your_AGENT_MAILBOX_KEY_here" + +# Now your agent is ready to join the agentverse! +coin_toss_agent = Agent( + name="coin_toss_agent", + seed=SEED_PHRASE, + mailbox=f"{AGENT_MAILBOX_KEY}@https://agentverse.ai", +) + +fund_agent_if_low(coin_toss_agent.wallet.address()) + +# Copy the address shown below +print(f"Your agent's address is: {coin_toss_agent.address}") + +coin_toss_protocol = Protocol("CoinToss") + + +@coin_toss_protocol.on_message(model=CoinToss, replies={UAgentResponse}) +async def toss_coin(ctx: Context, sender: str, msg: CoinToss): + random_number = random.randint(0, 1) + if random_number == 0: + coin_tossed = "heads" + else: + coin_tossed = "tails" + if coin_tossed == msg.choice: + message = "You won!" + else: + message = "You lost!" + await ctx.send( + sender, UAgentResponse(message=message, type=UAgentResponseType.FINAL) +) + +coin_toss_agent.include(coin_toss_protocol, publish_manifest=True) + +if __name__ == "__main__": + coin_toss_agent.run() +``` + +```python copy filename="hosted-agent.py" import random # third party modules used in this example from uagents import Field @@ -55,3 +112,4 @@ async def toss_coin(ctx: Context, sender: str, msg: CoinToss): agent.include(coin_toss_protocol, publish_manifest=True) ``` + diff --git a/pages/examples/intermediate/dice-roll.mdx b/pages/examples/intermediate/dice-roll.mdx index 6f78a6903..dc94f18d7 100644 --- a/pages/examples/intermediate/dice-roll.mdx +++ b/pages/examples/intermediate/dice-roll.mdx @@ -1,3 +1,5 @@ +import { CodeGroup } from "../../../components/code" + # Register a dice roll agent as a Function ## Introduction @@ -25,7 +27,54 @@ To enable this on [DeltaV ↗️](/concepts/ai-engine/deltav) you will need to c ### The agent -```py copy filename="agent.py" + +```py copy filename="local-agent.py" +import random +from uagents import Agent, Context, Model, Field, Protocol +from uagents.setup import fund_agent_if_low +from ai_engine import UAgentResponse, UAgentResponseType + + +class DiceRoll(Model): + num_rolls: int = Field(description="Number of rolls.") + +# First generate a secure seed phrase (e.g. https://pypi.org/project/mnemonic/) +SEED_PHRASE = "put_your_seed_phrase_here" + +# Now go to https://agentverse.ai, register your agent in the Mailroom by providing the address you just copied. +# Then, copy the agent's mailbox key and insert it here below inline +AGENT_MAILBOX_KEY = "put_your_AGENT_MAILBOX_KEY_here" + +# Now your agent is ready to join the agentverse! +dice_roll_agent = Agent( + name="dice_roll_agent", + seed=SEED_PHRASE, + mailbox=f"{AGENT_MAILBOX_KEY}@https://agentverse.ai", +) + +fund_agent_if_low(dice_roll_agent.wallet.address()) + +# Copy the address shown below +print(f"Your agent's address is: {dice_roll_agent.address}") + +dice_roll_protocol = Protocol("DiceRoll") + + +@dice_roll_protocol.on_message(model=DiceRoll, replies={UAgentResponse}) +async def roll_dice(ctx: Context, sender: str, msg: DiceRoll): + result = ", ".join([str(random.randint(1, 6)) for _ in range(msg.num_rolls)]) + message = f"Dice roll results: {result}" + await ctx.send( + sender, UAgentResponse(message=message, type=UAgentResponseType.FINAL) +) + +dice_roll_agent.include(dice_roll_protocol, publish_manifest=True) + +if __name__ == "__main__": + dice_roll_agent.run() +``` + +```py copy filename="hosted-agent.py" import random # third party modules used in this example from uagents import Field @@ -48,3 +97,4 @@ async def roll_dice(ctx: Context, sender: str, msg: DiceRoll): agent.include(dice_roll_protocol, publish_manifest=True) ``` + diff --git a/pages/examples/intermediate/hugging-face-agent.mdx b/pages/examples/intermediate/hugging-face-agent.mdx index a6f65d2ec..47df01e01 100644 --- a/pages/examples/intermediate/hugging-face-agent.mdx +++ b/pages/examples/intermediate/hugging-face-agent.mdx @@ -1,3 +1,5 @@ +import { CodeGroup } from "../../../components/code" + # Hugging face API agent as a Function ## Introduction @@ -21,7 +23,62 @@ This system shows how to integrate the Hugging Face API with an Agentverse Agent ### The agents #### Hugging Face System Agent - ```python copy filename="agent.py" + + + ```python copy filename="local-agent.py" + # Here we demonstrate how we can create a hugging face system agent that is compatible with DeltaV. + + # Importing required libraries. + import requests + from uagents import Agent, Context, Model, Field, Protocol + from uagents.setup import fund_agent_if_low + from ai_engine import UAgentResponse, UAgentResponseType + + # Define a model class for the Hugging Face agent's expected message format. + class HF(Model): + response : str # This class has a single attribute 'response' that holds the string response from the subtask. + + # First generate a secure seed phrase (e.g. https://pypi.org/project/mnemonic/) + SEED_PHRASE = "put_your_seed_phrase_here" + + # Now go to https://agentverse.ai, register your agent in the Mailroom by providing the address you just copied. + # Then, copy the agent's mailbox key and insert it here below inline + AGENT_MAILBOX_KEY = "put_your_AGENT_MAILBOX_KEY_here" + + # Now your agent is ready to join the agentverse! + hf_agent = Agent( + name="hf_agent", + seed=SEED_PHRASE, + mailbox=f"{AGENT_MAILBOX_KEY}@https://agentverse.ai", + ) + + fund_agent_if_low(hf_agent.wallet.address()) + + # Copy the address shown below + print(f"Your agent's address is: {hf_agent.address}") + + # Create a protocol for the Hugging Face (HF) agent, specifying its communication protocol. + hf_protocol = Protocol("Hugging Face") + + # Define a handler for the Hugging face protocol. + @hf_protocol.on_message(model=HF, replies = UAgentResponse) + async def on_hf_request(ctx: Context, sender: str, msg: HF): + + # Log the receipt of a response, including the sender and the message prompt. + ctx.logger.info(f"Received hugging face request from {sender} with prompt: {msg.response}") + + # Format a response message incorporating the received message. + message = f'Response to your query from model is \n {msg.response}' + # Asynchronously send a response back to the sender with the processed message. + await ctx.send(sender, UAgentResponse(message = message, type = UAgentResponseType.FINAL)) + + # Include the Hugging Face protocol in your agent. + hf_agent.include(hf_protocol) + + hf_agent.run() + ``` + + ```python copy filename="hosted-agent.py" # Here we demonstrate how we can create a hugging face system agent that is compatible with DeltaV. # After running this agent, it can be registered to DeltaV on Agentverse. For registration you will have to use the agent's address. @@ -52,10 +109,13 @@ This system shows how to integrate the Hugging Face API with an Agentverse Agent # Include the Hugging Face protocol in your agent. agent.include(hf_protocol) ``` + #### Hugging Face Request Agent - ```python copy filename="agent.py" + + + ```python copy filename="local-agent.py" # Here we demonstrate how we can create a hugging face request agent that is compatible with DeltaV. # After running this agent, it can be registered to DeltaV on Agentverse. For registration you will have to use the agent's address. @@ -63,6 +123,8 @@ This system shows how to integrate the Hugging Face API with an Agentverse Agent # Importing required libraries. import requests import json + from uagents import Agent, Context, Model, Field, Protocol + from uagents.setup import fund_agent_if_low from ai_engine import UAgentResponse, UAgentResponseType # Define a model class for the Hugging Face Request agent's expected message format. @@ -81,6 +143,25 @@ This system shows how to integrate the Hugging Face API with an Agentverse Agent # Make request to hugging face API with model_id and query. response = requests.post(API_URL, headers=headers, json=query).json() return response + + # First generate a secure seed phrase (e.g. https://pypi.org/project/mnemonic/) + SEED_PHRASE = "put_your_seed_phrase_here" + + # Now go to https://agentverse.ai, register your agent in the Mailroom by providing the address you just copied. + # Then, copy the agent's mailbox key and insert it here below inline + AGENT_MAILBOX_KEY = "put_your_AGENT_MAILBOX_KEY_here" + + # Now your agent is ready to join the agentverse! + hf_request_agent = Agent( + name="hf_request_agent", + seed=SEED_PHRASE, + mailbox=f"{AGENT_MAILBOX_KEY}@https://agentverse.ai", + ) + + fund_agent_if_low(hf_request_agent.wallet.address()) + + # Copy the address shown below + print(f"Your agent's address is: {hf_request_agent.address}") # Create a protocol for the Hugging Face Request(HF) agent, specifying its communication protocol. hfprotocol = Protocol(name = 'Hugging Face protocol') @@ -99,12 +180,143 @@ This system shows how to integrate the Hugging Face API with an Agentverse Agent await ctx.send(sender, UAgentResponse(message = str(response), type = UAgentResponseType.FINAL)) # Include the Hugging Face protocol in your agent. - agent.include(hfprotocol, publish_manifest = True) + hf_request_agent.include(hfprotocol, publish_manifest = True) + + hf_request_agent.run() ``` + ```python copy filename="hosted-agent.py" + # Here we demonstrate how we can create a hugging face request agent that is compatible with DeltaV. + + # After running this agent, it can be registered to DeltaV on Agentverse. For registration you will have to use the agent's address. + + # Importing required libraries. + import requests + import json + from ai_engine import UAgentResponse, UAgentResponseType + + # Define a model class for the Hugging Face Request agent's expected message format. + class Search(Model): + model_id : str + query : str + + # Define a function to handle query from user using model_id and query provided by user. + async def handle_query(model_id, query): + Model_ID = model_id + API_URL = f'https://api-inference.huggingface.co/models/{Model_ID}' # hugging face url + API_TOKEN = 'YOUR TOKEN HERE' # hugging face API token + + headers = {"Authorization": f"Bearer {API_TOKEN}"} + + # Make request to hugging face API with model_id and query. + response = requests.post(API_URL, headers=headers, json=query).json() + return response + + # Create a protocol for the Hugging Face Request(HF) agent, specifying its communication protocol. + hfprotocol = Protocol(name = 'Hugging Face protocol') + + # Define a handler for the Hugging face request protocol. + @hfprotocol.on_message(model = Search, replies = UAgentResponse) + async def handle_message(ctx: Context, sender: str, msg: Search): + + # Log the model_id and query provided by user. + ctx.logger.info(f'Message sent from {sender} : {msg.model_id}') + ctx.logger.info(f'Message sent from subtask : {msg.query}') + + # Calling handle_query function to get response from API. + response = await handle_query(msg.model_id, msg.query) + # sending response to hugging face agent + await ctx.send(sender, UAgentResponse(message = str(response), type = UAgentResponseType.FINAL)) + + # Include the Hugging Face protocol in your agent. + agent.include(hfprotocol, publish_manifest = True) + ``` + #### Model List Agent - ```python copy filename="agent.py" + + + ```python copy filename="local-agent.py" + # Here we demonstrate how we can create a model list agent that is compatible with DeltaV. + + # Importing required libraries. + import requests + from ai_engine import UAgentResponse, UAgentResponseType + import json + + # Define a model class for the Model List agent's expected message format. + class Search(Model): + search : str # This is a keyword for which user wants to search model + + # First generate a secure seed phrase (e.g. https://pypi.org/project/mnemonic/) + SEED_PHRASE = "put_your_seed_phrase_here" + + # Now go to https://agentverse.ai, register your agent in the Mailroom by providing the address you just copied. + # Then, copy the agent's mailbox key and insert it here below inline + AGENT_MAILBOX_KEY = "put_your_AGENT_MAILBOX_KEY_here" + + # Now your agent is ready to join the agentverse! + model_list_agent = Agent( + name="model_list_agent", + seed=SEED_PHRASE, + mailbox=f"{AGENT_MAILBOX_KEY}@https://agentverse.ai", + ) + + fund_agent_if_low(model_list_agent.wallet.address()) + + # Copy the address shown below + print(f"Your agent's address is: {model_list_agent.address}") + + # Create a protocol for the Model List agent, specifying its communication protocol. + model_list_protocol = Protocol(name = 'Model List protocol') + + # Define a function to handle query from user using search keyword provided by user. + async def handle_query(search): + url = "https://huggingface.co/api/models" + + params = { + "search": search, + "filter": "text-classification", + "sort": "downloads", + "direction": -1, + "limit": 5 + } # Search parameters. + + models = [] # List of models. + + # Make the GET request. + response = requests.get(url, params = params) + + # Append models in list. + for model in response.json(): + models.append(model['id']) + + return models + + # Define a handler for the Model list protocol. + @model_list_protocol.on_message(model = Search, replies = UAgentResponse) + async def handle_message(ctx: Context, sender: str, msg: Search): + # Log search keyword provided by user. + ctx.logger.info(f'Message sent from {sender} : {msg.search}') + + # Call handle_query to get list of models. + options = handle_query(msg.search) + # Log model list responded by hugging face request. + ctx.logger.info(f'Message sent from {sender} : {options}') + + # Format options in dictionary format to provide options to user. + formatted_options = [{'key': i + 1, 'value': value} for i, value in enumerate(options)] + + # Send message to the user. + await ctx.send(sender, UAgentResponse(message = str(formatted_options), type=UAgentResponseType.FINAL)) + + # Include model_list protocol in agent. + model_list_agent.include(model_list_protocol, publish_manifest = True) + + model_list_agent.run() + ``` + + ```python copy filename="hosted-agent.py" # Here we demonstrate how we can create a model list agent that is compatible with DeltaV. # After running this agent, it can be registered to DeltaV on Agentverse. For registration you will have to use the agent's address. @@ -164,3 +376,4 @@ This system shows how to integrate the Hugging Face API with an Agentverse Agent # Include model_list protocol in agent. agent.include(model_list_protocol, publish_manifest = True) ``` + \ No newline at end of file diff --git a/pages/examples/intermediate/langchain-rag.mdx b/pages/examples/intermediate/langchain-rag.mdx index 0e77a1cd5..1f5f2fe9d 100644 --- a/pages/examples/intermediate/langchain-rag.mdx +++ b/pages/examples/intermediate/langchain-rag.mdx @@ -1,3 +1,5 @@ +import { CodeGroup } from "../../../components/code" + # Langchain RAG Agent @@ -272,7 +274,9 @@ if __name__ == "__main__": The agent is designed to ask a predefined question to a RAG agent at regular intervals and handle the responses. -```python copy filename="langchain_rag_user.py" + + +```python copy filename="local-langchain_rag_user.py" from uagents import Agent, Context, Protocol from messages.requests import RagRequest from ai_engine import UAgentResponse @@ -318,6 +322,51 @@ if __name__ == "__main__": ``` +```python copy filename="hosted-langchain_rag_user.py" +from uagents import Agent, Context, Protocol, Field +from ai_engine import UAgentResponse + +QUESTION = "How to install uagents using pip" +URL = "https://fetch.ai/docs/guides/agents/installing-uagent" +DEEP_READ = ( + "no" +) + +class RagRequest(Model): + question: str = Field( + description="The question that the user wants to have an answer for." + ) + url: str = Field(description="The url of the docs where the answer is.") + deep_read: Optional[str] = Field( + description="Specifies weather all nested pages referenced from the starting URL should be read or not. The value should be yes or no.", + default="no", + ) + +RAG_AGENT_ADDRESS = "YOUR_LANGCHAIN_RAG_AGENT_ADDRESS" + +rag_user = Protocol("LangChain RAG user") + + +@agent.on_interval(60, messages=RagRequest) +async def ask_question(ctx: Context): + ctx.logger.info( + f"Asking RAG agent to answer {QUESTION} based on document located at {URL}, reading nested pages too: {DEEP_READ}" + ) + await ctx.send( + RAG_AGENT_ADDRESS, RagRequest(question=QUESTION, url=URL, deep_read=DEEP_READ) + ) + + +@agent.on_message(model=UAgentResponse) +async def handle_data(ctx: Context, sender: str, data: UAgentResponse): + ctx.logger.info(f"Got response from RAG agent: {data.message}") + + +agent.include(rag_user) + +``` + + ```python copy filename="main.py" from uagents import Bureau from agents.langchain_rag_agent import agent diff --git a/pages/examples/intermediate/local-agent-registration.mdx b/pages/examples/intermediate/local-agent-registration.mdx index 3f2a05074..05a660ff6 100644 --- a/pages/examples/intermediate/local-agent-registration.mdx +++ b/pages/examples/intermediate/local-agent-registration.mdx @@ -1,3 +1,5 @@ +import { CodeGroup } from "../../../components/code" + # Register a local agent as a Function ## Introduction @@ -24,7 +26,8 @@ This file can be run on any platform supporting Python, with the necessary insta ### The script -```py copy filename="agent.py" + +```py copy filename="local-agent.py" from uagents.setup import fund_agent_if_low from uagents import Agent, Context, Protocol, Model import random @@ -63,6 +66,33 @@ dungeons.include(dice_roll_protocol, publish_manifest=True) dungeons.run() ``` +```py copy filename="hosted-agent.py" +from uagents import Agent, Context, Protocol, Model +import random +from uagents import Field +from ai_engine import UAgentResponse, UAgentResponseType + +@agent.on_event("startup") +async def hi(ctx: Context): + ctx.logger.info(dungeons.address) + +class Request(Model): + dice_sides: int = Field(description="How many sides does your dice need?") + +dice_roll_protocol = Protocol("DungeonsAndDragonsDiceRoll") + +@agent.on_message(model=Request, replies={UAgentResponse}) +async def roll_dice(ctx: Context, sender: str, msg: Request): + result = str(random.randint(1, msg.dice_sides)) + message = f"Dice roll result: {result}" + await ctx.send( + sender, UAgentResponse(message=message, type=UAgentResponseType.FINAL) + ) + +agent.include(dice_roll_protocol, publish_manifest=True) +``` + + ### Register Agent Function For this step, head to this guide for [registering a local Agent Function on the Agentverse ↗️](/guides/agents/running-locally#register-your-agent-function-on-the-agentverse) for a detailed overview of the registration process. diff --git a/pages/examples/intermediate/local-communication.mdx b/pages/examples/intermediate/local-communication.mdx index 705361601..e0e283d88 100644 --- a/pages/examples/intermediate/local-communication.mdx +++ b/pages/examples/intermediate/local-communication.mdx @@ -1,3 +1,5 @@ +import { CodeGroup } from "../../../components/code" + # Local Network Interaction ## Introduction @@ -14,7 +16,9 @@ This file can be run on any platform supporting Python, with the necessary insta ### Agent 1 -```py copy filename="agent_1.py" + + +```py copy filename="local-agent_1.py" from uagents import Agent, Context, Model # NOTE: Run agent1.py before running agent2.py @@ -40,9 +44,28 @@ if __name__ == "__main__": bob.run() ``` +```py copy filename="hosted-agent_1.py" +from uagents import Agent, Context, Model + +# NOTE: Run agent1.py before running agent2.py + +class Message(Model): + message: str + +@agent.on_message(model=Message) +async def message_handler(ctx: Context, sender: str, msg: Message): + ctx.logger.info(f"Received message from {sender}: {msg.message}") + + # send the response + await ctx.send(sender, Message(message="Hello there alice.")) +``` + + ### Agent 2 -```py copy filename="agent_2.py" + + +```py copy filename="local-agent_2.py" from uagents import Agent, Context, Model class Message(Model): @@ -71,6 +94,26 @@ if __name__ == "__main__": alice.run() ``` +```py copy filename="hosted-agent_2.py" +from uagents import Agent, Context, Model + +class Message(Model): + message: str + +RECIPIENT_ADDRESS = ( + "test-agent://agent1q2kxet3vh0scsf0sm7y2erzz33cve6tv5uk63x64upw5g68kr0chkv7hw50" +) + +@agent.on_interval(period=2.0) +async def send_message(ctx: Context): + await ctx.send(RECIPIENT_ADDRESS, Message(message="Hello there bob.")) + +@agent.on_message(model=Message) +async def message_handler(ctx: Context, sender: str, msg: Message): + ctx.logger.info(f"Received message from {sender}: {msg.message}") +``` + + ### Expected output - Bob: diff --git a/pages/examples/intermediate/name-service.mdx b/pages/examples/intermediate/name-service.mdx index 235ace1b4..6280a67f0 100644 --- a/pages/examples/intermediate/name-service.mdx +++ b/pages/examples/intermediate/name-service.mdx @@ -1,3 +1,5 @@ +import { CodeGroup } from "../../../components/code" + # Agents Name Service ## Introduction @@ -57,7 +59,9 @@ if __name__ == "__main__": ### Agent 2 -```py copy filename="agent_2.py" + + +```py copy filename="local-agent_2.py" from uagents.setup import fund_agent_if_low from uagents import Agent, Context, Model @@ -83,6 +87,20 @@ if __name__ == "__main__": alice.run() ``` +```py copy filename="hosted-agent_2.py" +from uagents import Agent, Context, Model + +class Message(Model): + message: str + +@agent.on_interval(period=5) +async def alice_interval_handler(ctx: Context): + bob_name = "bob-0.agent" + ctx.logger.info(f"Sending message to {bob_name}...") + await ctx.send(bob_name, Message(message="Hello there bob.")) +``` + + ## Expected output - Bob: diff --git a/pages/examples/intermediate/news-reading-system.mdx b/pages/examples/intermediate/news-reading-system.mdx index 3fabd0fff..2a55e0b4e 100644 --- a/pages/examples/intermediate/news-reading-system.mdx +++ b/pages/examples/intermediate/news-reading-system.mdx @@ -1,3 +1,5 @@ +import { CodeGroup } from "../../../components/code" + # Using News API to build network of Primary and Secondary functions ## Introduction @@ -17,7 +19,64 @@ This file can be run on any platform supporting Python, with the necessary insta #### News Reading Agent - ```python copy filename="agent.py" + + + ```python copy filename="local-agent.py" + + # Here we demonstrate how we can create a news reading system agent that is compatible with DeltaV + + # Import required libraries + import requests + import json + from uagents import Agent, Context, Model, Field, Protocol + from uagents.setup import fund_agent_if_low + from ai_engine import UAgentResponse, UAgentResponseType + + # Define News Reading Model + class News(Model): + news : str + + # First generate a secure seed phrase (e.g. https://pypi.org/project/mnemonic/) + SEED_PHRASE = "put_your_seed_phrase_here" + + # Now go to https://agentverse.ai, register your agent in the Mailroom by providing the address you just copied. + # Then, copy the agent's mailbox key and insert it here below inline + AGENT_MAILBOX_KEY = "put_your_AGENT_MAILBOX_KEY_here" + + # Now your agent is ready to join the agentverse! + news_agent = Agent( + name="news_agent", + seed=SEED_PHRASE, + mailbox=f"{AGENT_MAILBOX_KEY}@https://agentverse.ai", + ) + + fund_agent_if_low(news_agent.wallet.address()) + + # Copy the address shown below + print(f"Your agent's address is: {news_agent.address}") + + # Define Protocol for news reading system + news_protocol = Protocol("News System") + + # Define a handler for the News system protocol + @news_protocol.on_message(model=News, replies = UAgentResponse) + async def on_news_request(ctx: Context, sender: str, msg: News): + #splitting the news titles with nnn and enumerating them with line break for visually better results + result_list = msg.news.split(" nnn ") + final_news = '\n'.join([f"{i + 1}. {title}" for i, title in enumerate(result_list)]) + #Printing the news response on logger + ctx.logger.info(f"Received news request from {sender} with prompt: {final_news}") + #sending final response to the DeltaV GUI + await ctx.send(sender, UAgentResponse(message = final_news, type = UAgentResponseType.FINAL)) + + + # Include the Generate News protocol in your agent + news_agent.include(news_protocol) + + news_agent.run() + ``` + + ```python copy filename="hosted-agent.py" # Here we demonstrate how we can create a news reading system agent that is compatible with DeltaV @@ -50,9 +109,89 @@ This file can be run on any platform supporting Python, with the necessary insta # Include the Generate News protocol in your agent agent.include(news_protocol) ``` + #### News Generating Agent - ```python copy filename="agent.py" + + + ```python copy filename="local-agent.py" + # Here we demonstrate how we can create a news generating agent that is compatible with DeltaV. + + # Import required libraries + import requests + import json + from uagents import Agent, Context, Model, Field, Protocol + from uagents.setup import fund_agent_if_low + from ai_engine import UAgentResponse, UAgentResponseType + + # Define News Generating Model. + class GenerateNews(Model): + news_type: str + news : str + + # First generate a secure seed phrase (e.g. https://pypi.org/project/mnemonic/) + SEED_PHRASE = "put_your_seed_phrase_here" + + # Now go to https://agentverse.ai, register your agent in the Mailroom by providing the address you just copied. + # Then, copy the agent's mailbox key and insert it here below inline + AGENT_MAILBOX_KEY = "put_your_AGENT_MAILBOX_KEY_here" + + # Now your agent is ready to join the agentverse! + generate_news_agent = Agent( + name="generate_news_agent", + seed=SEED_PHRASE, + mailbox=f"{AGENT_MAILBOX_KEY}@https://agentverse.ai", + ) + + fund_agent_if_low(generate_news_agent.wallet.address()) + + # Copy the address shown below + print(f"Your agent's address is: {generate_news_agent.address}") + + # Define Generate news protocol. + generate_news_protocol = Protocol("Generate News") + + + # Define a handler for the News generation protocol + @generate_news_protocol.on_message(model=GenerateNews, replies=UAgentResponse) + async def on_generate_news_request(ctx: Context, sender: str, msg: GenerateNews): + try: + # Generate news based on the requested category. + ctx.logger.info('Generating News') + ctx.logger.info(f'User have selected {msg.news_type} category') + + ctx.logger.info(f'Generate News \n {msg.news}') + message = msg.news + + # Send a successful response with the generated news. + await ctx.send( + sender, + UAgentResponse( + message= message, + type=UAgentResponseType.FINAL + ) + ) + + # Handle any exceptions that occur during news generation. + except Exception as exc: + ctx.logger.error(f"Error in generating news: {exc}") + + # Send an error response with details of the encountered error. + await ctx.send( + sender, + UAgentResponse( + message=f"Error in generating news: {exc}", + type=UAgentResponseType.ERROR + ) + ) + + # Include the Generate News protocol in your agent. + generate_news_agent.include(generate_news_protocol) + + generate_news_agent.run() + ``` + + ```python copy filename="hosted-agent.py" # Here we demonstrate how we can create a news generating agent that is compatible with DeltaV. # After running this agent, it can be registered to DeltaV on Agentverse My Agents tab. For registration you will have to use the agent's address. @@ -106,10 +245,94 @@ This file can be run on any platform supporting Python, with the necessary insta # Include the Generate News protocol in your agent. agent.include(generate_news_protocol) ``` + #### Generate Categorical News - ```python copy filename="agent.py" + + + ```python copy filename="local-agent.py" + # Here we demonstrate how we can create a categorical news generating agent that is compatible with DeltaV. + + # Importing libraries + import requests + import json + from uagents import Agent, Context, Model, Field, Protocol + from uagents.setup import fund_agent_if_low + from ai_engine import UAgentResponse, UAgentResponseType + + # Define the Generate News model. + class GenerateNews(Model): + category: str + + # First generate a secure seed phrase (e.g. https://pypi.org/project/mnemonic/) + SEED_PHRASE = "put_your_seed_phrase_here" + + # Now go to https://agentverse.ai, register your agent in the Mailroom by providing the address you just copied. + # Then, copy the agent's mailbox key and insert it here below inline + AGENT_MAILBOX_KEY = "put_your_AGENT_MAILBOX_KEY_here" + + # Now your agent is ready to join the agentverse! + generate_cat_news_agent = Agent( + name="generate_cat_news_agent", + seed=SEED_PHRASE, + mailbox=f"{AGENT_MAILBOX_KEY}@https://agentverse.ai", + ) + + fund_agent_if_low(generate_cat_news_agent.wallet.address()) + + # Copy the address shown below + print(f"Your agent's address is: {generate_cat_news_agent.address}") + + # Define protocol for categorical news generation. + generate_cat_news_protocol = Protocol("Generate Categorical News") + + # Define function to generate news according to category in great britain - GB. + async def generate_news(category): + api_key = 'YOUR_NEWS_API_KEY' + main_url = f"https://newsapi.org/v2/top-headlines?country=gb&category={category}&apiKey={api_key}" + news = requests.get(main_url).json() + #strip the source, get top 10 news and join the list with ' nnn ' to return the news as string and not list (DeltaV compatible type) + titles = [article['title'].split(' - ')[0].strip() for article in news['articles']] + titles = titles[:10] + results = ' nnn '.join([f"{title}" for title in titles]) + + return results + + # Define a handler for the Categorical News generation protocol. + @generate_cat_news_protocol.on_message(model=GenerateNews, replies=UAgentResponse) + async def on_generate_news_request(ctx: Context, sender: str, msg: GenerateNews): + #Logging category of news user wants to read + ctx.logger.info(f"Received ticket request from {sender} with prompt: {msg.category}") + try: + # Generate news based on the requested category. + news = generate_news(msg.category) + #logging news + ctx.logger.info(news) + message = str(news) + # Send a successful response with the generated news. + await ctx.send(sender, UAgentResponse(message = message, type = UAgentResponseType.FINAL)) + + # Handle any exceptions that occur during news generation. + except Exception as exc: + ctx.logger.error(f"Error in generating News: {exc}") + # Send an error response with details of the encountered error. + await ctx.send( + sender, + UAgentResponse( + message=f"Error in generating News: {exc}", + type=UAgentResponseType.ERROR + ) + ) + + + # Include the Generate News protocol in your agent. + generate_cat_news_agent.include(generate_cat_news_protocol) + + generate_cat_news_agent.run() + ``` + + ```python copy filename="hosted-agent.py" # Here we demonstrate how we can create a categorical news generating agent that is compatible with DeltaV. # After running this agent, it can be registered to DeltaV on Agentverse My Agents tab. For registration you will have to use the agent's address. @@ -167,10 +390,107 @@ This file can be run on any platform supporting Python, with the necessary insta # Include the Generate News protocol in your agent. agent.include(generate_cat_news_protocol) ``` + #### Generate Regional News - ```python copy filename="agent.py" + + ```python copy filename="local-agent.py" + # Import libraries + import requests + import json + from uagents import Agent, Context, Model, Field, Protocol + from uagents.setup import fund_agent_if_low + from ai_engine import UAgentResponse, UAgentResponseType + + # Define dictionary with country codes + country_codes = { + "argentina": "ar", "australia": "au", "austria": "at", "belgium": "be", + "bulgaria": "bg", "brazil": "br", "canada": "ca", "china": "cn", + "colombia": "co", "cuba": "cu", "czech republic": "cz", "germany": "de", + "egypt": "eg", "france": "fr", "united kingdom": "gb", "greece": "gr", + "hong kong": "hk", "hungary": "hu", "indonesia": "id", "ireland": "ie", + "israel": "il", "india": "in", "italy": "it", "japan": "jp", + "south korea": "kr", "lithuania": "lt", "latvia": "lv", "morocco": "ma", + "mexico": "mx", "malaysia": "my", "nigeria": "ng", "netherlands": "nl", + "norway": "no", "new zealand": "nz", "philippines": "ph", "poland": "pl", + "portugal": "pt", "romania": "ro", "serbia": "rs", "russia": "ru", + "saudi arabia": "sa", "sweden": "se", "singapore": "sg", "slovenia": "si", + "slovakia": "sk", "thailand": "th", "turkey": "tr", "taiwan": "tw", + "ukraine": "ua", "united states": "us", "venezuela": "ve", "south africa": "za" + } + + # Define the Generate News model + class GenerateNews(Model): + country: str + + # First generate a secure seed phrase (e.g. https://pypi.org/project/mnemonic/) + SEED_PHRASE = "put_your_seed_phrase_here" + + # Now go to https://agentverse.ai, register your agent in the Mailroom by providing the address you just copied. + # Then, copy the agent's mailbox key and insert it here below inline + AGENT_MAILBOX_KEY = "put_your_AGENT_MAILBOX_KEY_here" + + # Now your agent is ready to join the agentverse! + generate_news_reg_agent = Agent( + name="generate_news_reg_agent", + seed=SEED_PHRASE, + mailbox=f"{AGENT_MAILBOX_KEY}@https://agentverse.ai", + ) + + fund_agent_if_low(generate_news_reg_agent.wallet.address()) + + # Copy the address shown below + print(f"Your agent's address is: {generate_news_reg_agent.address}") + + # Define function to generate regional news according to country + async def get_regional_news(country): + api_key = 'YOUR_API_KEY' + main_url = f"https://newsapi.org/v2/top-headlines?country={country_codes.get(country.lower())}&apiKey={api_key}" + news = requests.get(main_url).json() + # Strip the source, get top 10 news and join the list with nnn to return the news as string and not list - DeltaV compatible type + titles = [article['title'].split(' - ')[0].strip()for article in news['articles']] + titles = titles[:10] + results = ' nnn '.join([f"{title}" for title in titles]) + + return results + + # Define protocol for regional news generation Protocol + generate_news_reg_protocol = Protocol("Generate Regional News") + + # Define a handler for the Regional News generation protocol + @generate_news_reg_protocol.on_message(model=GenerateNews, replies=UAgentResponse) + async def on_generate_news_request(ctx: Context, sender: str, msg: GenerateNews): + + ctx.logger.info(f"Received ticket request from {sender} with prompt: {msg.country}") + try: + # Get the country code from the country_code dictionary + country_code = country_codes.get(msg.country.lower()) + # Generate news based on the requested country and log it on agentverse + message = await get_regional_news(msg.country) + ctx.logger.info(f"Message from endpoint: {message}") + # Send a successful response with the generated news + await ctx.send(sender, UAgentResponse(message=message, type=UAgentResponseType.FINAL)) + # Handle any exceptions that occur during news generation + except Exception as exc: + ctx.logger.error(f"Error in generating News: {exc}") + # Send an error response with details of the encountered error + await ctx.send( + sender, + UAgentResponse( + message=f"Error in generating News: {exc}", + type=UAgentResponseType.ERROR + ) + ) + + + # Include the Generate Regional News protocol in your agent + generate_news_reg_agent.include(generate_news_protocol) + + generate_news_reg_agent.run() + ``` + + ```python copy filename="hosted-agent.py" # Import libraries import requests import json @@ -241,10 +561,93 @@ This file can be run on any platform supporting Python, with the necessary insta # Include the Generate Regional News protocol in your agent agent.include(generate_news_protocol) ``` + #### Generate Keyword News - ```python copy filename="agent.py" + + + ```python copy filename="local-agent.py" + # Import libraries + import requests + from uagents import Agent, Context, Model, Field, Protocol + from uagents.setup import fund_agent_if_low + import json + from ai_engine import UAgentResponse, UAgentResponseType + + # Define the Generate News model + class GenerateNews(Model): + keyword: str + + # First generate a secure seed phrase (e.g. https://pypi.org/project/mnemonic/) + SEED_PHRASE = "put_your_seed_phrase_here" + + # Now go to https://agentverse.ai, register your agent in the Mailroom by providing the address you just copied. + # Then, copy the agent's mailbox key and insert it here below inline + AGENT_MAILBOX_KEY = "put_your_AGENT_MAILBOX_KEY_here" + + # Now your agent is ready to join the agentverse! + generate_news_keyw_agent = Agent( + name="generate_news_keyw_agent", + seed=SEED_PHRASE, + mailbox=f"{AGENT_MAILBOX_KEY}@https://agentverse.ai", + ) + + fund_agent_if_low(generate_news_keyw_agent.wallet.address()) + + # Copy the address shown below + print(f"Your agent's address is: {generate_news_keyw_agent.address}") + + # Define protocol for keyword news generation + generate_news_keyw_protocol = Protocol("Generate Keyword News") + + # Define function to generate news according to keyword + async def get_keyword_news(keyword): + + api_key = 'YOUR_API_KEY' + main_url = f"https://newsapi.org/v2/top-headlines?q={keyword}&apiKey={api_key}" + news = requests.get(main_url).json() + # Strip the source, get top 10 news and join the list with nnn to return the news as string and not list - DeltaV compatible type + titles = [article['title'].split(' - ')[0].strip() for article in news['articles']] + titles = titles[:10] + results = ' nnn '.join([f"{title}" for title in titles]) + + # Define a handler for the Keyword News generation protocol + @generate_news_keyw_protocol.on_message(model=GenerateNews, replies=UAgentResponse) + async def on_generate_news_request(ctx: Context, sender: str, msg: GenerateNews): + + ctx.logger.info(f"Received news request from {sender} with prompt: {msg.keyword}") + # Generate news based on the requested keyword + try: + news = get_keyword_news(msg.keyword) + # Send a successful response with the generated news + await ctx.send( + sender, + UAgentResponse( + message=news, + type=UAgentResponseType.FINAL + ) + ) + + # Handle any exceptions that occur during news generation + except Exception as exc: + ctx.logger.error(f"Error in generating News: {exc}") + # Send an error response with details of the encountered error + await ctx.send( + sender, + UAgentResponse( + message=f"Error in generating News: {exc}", + type=UAgentResponseType.ERROR + ) + ) + + # Include the Generate Keyword News protocol in your agent + generate_news_keyw_agent.include(generate_news_keyw_protocol) + + generate_news_keyw_agent.run() + ``` + + ```python copy filename="hosted-agent.py" # Import libraries import requests import json @@ -300,3 +703,4 @@ This file can be run on any platform supporting Python, with the necessary insta # Include the Generate Keyword News protocol in your agent agent.include(generate_news_keyw_protocol) ``` + \ No newline at end of file diff --git a/pages/examples/intermediate/on-query-proxy.mdx b/pages/examples/intermediate/on-query-proxy.mdx index a3339bb57..3e78a1176 100644 --- a/pages/examples/intermediate/on-query-proxy.mdx +++ b/pages/examples/intermediate/on-query-proxy.mdx @@ -1,3 +1,5 @@ +import { CodeGroup } from "../../../components/code" + # Query an agent using a proxy API ## Introduction @@ -15,7 +17,33 @@ This example shows how to query an agent using a proxy API. #### The agent -```py copy filename="agent.py" + +```py copy filename="hosted-agent.py" +from uagents import Agent, Context, Model + +class TestRequest(Model): + message: str + +class Response(Model): + text: str + +@agent.on_event("startup") +async def startup(ctx: Context): + ctx.logger.info(f"Starting up {agent.name}") + ctx.logger.info(f"With address: {agent.address}") + ctx.logger.info(f"And wallet address: {agent.wallet.address()}") + +@agent.on_query(model=TestRequest, replies={Response}) +async def query_handler(ctx: Context, sender: str, _query: TestRequest): + ctx.logger.info("Query received") + try: + # do something here + await ctx.send(sender, Response(text="success")) + except Exception: + await ctx.send(sender, Response(text="fail")) +``` + +```py copy filename="local-agent.py" from uagents import Agent, Context, Model class TestRequest(Model): @@ -49,6 +77,7 @@ async def query_handler(ctx: Context, sender: str, _query: TestRequest): if __name__ == "__main__": agent.run() ``` + The agent is created using the `Agent` class from `uagents` library. It is initialized with a `name`, `seed`, `port`, and `endpoint`. It defines an `on_event` handler for the "startup" event, where it logs information about the agent's initialization. diff --git a/pages/examples/intermediate/on_query_example.mdx b/pages/examples/intermediate/on_query_example.mdx index d0157162b..01cc65569 100644 --- a/pages/examples/intermediate/on_query_example.mdx +++ b/pages/examples/intermediate/on_query_example.mdx @@ -1,4 +1,5 @@ import { Callout } from 'nextra/components' +import { CodeGroup } from "../../../components/code" ## Shopping Assistance Agent using `on_query` @@ -39,7 +40,8 @@ class ShoppingAssistResponse(Model): - **Shopping Assistance Agent :** This code defines a shopping assistant agent using the uAgents framework. The agent listens for incoming `ShoppingRequest` messages, processes them by sending the user's question to OpenAI's GPT-4 API for a response, and then sends the generated response back to the sender as a `ShoppingAssistResponse`. -```py copy filename="agent.py" + +```py copy filename="local-agent.py" from uagents import Agent, Context from uagents.setup import fund_agent_if_low from models import ShoppingAssistResponse, ShoppingRequest @@ -132,6 +134,89 @@ if __name__ == "__main__": ``` +```py copy filename="hosted-agent.py" +from uagents import Agent, Context +import requests +import json + +YOUR_OPEN_AI_API_KEY = "PASTE_YOUR_OPEN_AI_API_KEY" + +class ShoppingRequest(Model): + question: str + + +class ShoppingAssistResponse(Model): + answer: str + +def get_chat_response(messages): + """ + Sends a request to the OpenAI GPT-4 API to generate a chat response. + + Accepts: + - messages: A list of dictionaries representing the conversation history, + where each dictionary contains a 'role' (e.g., 'system' or 'user') + and 'content' (the message text). + + What it does: + - Sends a POST request to the OpenAI API with the conversation history. + - Handles the API response, returning the generated response from the model + or an error message if the request fails. + + Returns: + - A string containing the model's response if the request is successful. + - An error message string if the request fails. + """ + api_url = "https://api.openai.com/v1/chat/completions" + headers = { + "Authorization": f"Bearer {YOUR_OPEN_AI_API_KEY}", + "Content-Type": "application/json", + } + + data = { + "model": "gpt-4", + "messages": messages, + "max_tokens": 150, + "temperature": 0.7, + } + + response = requests.post(api_url, headers=headers, data=json.dumps(data)) + + if response.status_code == 200: + result = response.json() + return result["choices"][0]["message"]["content"].strip() + else: + return f"Error: {response.status_code} - {response.text}" + + +@agent.on_query(model=ShoppingRequest, replies=ShoppingAssistResponse) +async def handler(ctx: Context, sender: str, msg: ShoppingRequest): + """ + Handles incoming queries from other agents, specifically ShoppingRequest messages. + + Accepts: + - ctx: The context object, used for logging and communication. + - sender: A string representing the address of the agent that sent the message. + - msg: A ShoppingRequest object containing the question from the user. + + What it does: + - Logs the received question. + - Prepares a conversation history for the chat model with the role of the assistant and user. + - Sends the conversation history to the get_chat_response function to generate a response. + - Logs the generated response. + - Sends the response back to the sender as a ShoppingAssistResponse. + + Returns: + - None (asynchronous function). + """ + ctx.logger.info(f"Received message from {sender} with question: {msg.question}") + messages = [{"role": "system", "content": "You are a helpful shopping assistant."}] + messages.append({"role": "user", "content": msg.question}) + response = get_chat_response(messages) + ctx.logger.info(f"Question: {msg.question}\nAnswer: {response}") + await ctx.send(sender, ShoppingAssistResponse(answer=response)) + +``` + You need to have an OpenAI API key to run this example. You can get it from [OpenAI ↗️](https://openai.com/) . diff --git a/pages/examples/intermediate/react_example.mdx b/pages/examples/intermediate/react_example.mdx index 8c6c8049c..d5f1bcf5d 100644 --- a/pages/examples/intermediate/react_example.mdx +++ b/pages/examples/intermediate/react_example.mdx @@ -1,4 +1,5 @@ import { Callout } from 'nextra/components' +import { CodeGroup } from "../../../components/code" # React app with agents 'on_query' decorator @@ -162,8 +163,10 @@ In this section we will setup agents and as well as flask app which will respond 2. Agents: - **News and URL agent:** Fetches news articles titles and url for them as well. + + - ```python copy filename="news_agent.py" + ```python copy filename="local-news_agent.py" # Import Required libraries import requests import os @@ -290,6 +293,116 @@ In this section we will setup agents and as well as flask app which will respond NewsAgent.run() ``` + ```python copy filename="hosted-news_agent.py" + # Import Required libraries + import requests + from uagents import Agent, Context, Model + + # Define Request and Response Models + class NewsRequest(Model): + company_name: str + + class UrlRequest(Model): + company_name: str + + class NewsResponse(Model): + news_list : list + + class UrlResponse(Model): + url_list: list + + class ErrorResponse(Model): + error : str + + ALPHA_VANTAGE_API_KEY = "YOUR_ALPHA_VANTAGE_API_KEY" + GNEWS_API_KEY = "YOUR_GNEWS_API_KEY" + + # Define function to get ticker symbol for given company name + async def fetch_symbol(company_name): + url = f"https://www.alphavantage.co/query?function=SYMBOL_SEARCH&keywords={company_name}&apikey={ALPHA_VANTAGE_API_KEY}" + response = requests.get(url) + if response.status_code == 200: + data = response.json() + # Typically, the best match will be the first item in the bestMatches list + if data.get('bestMatches') and len(data['bestMatches']) > 0: + Symbol = data['bestMatches'][0]['1. symbol'] # Return the symbol of the best match + return Symbol + else: + return 'No Symbol found' + else: + return 'No Symbol found' + + async def fetch_news(company_name): # get news urls and description for the given news company or ticker + url = f"https://gnews.io/api/v4/search?q={company_name}&token={GNEWS_API_KEY}&lang=en" + response = requests.get(url) + articles = response.json().get('articles', []) + # Return a list of titles and descriptions with hyperlinks + news_list = [] + for article in articles: + article_url = article.get('url', 'No url') + description = article.get("description", "No Description") + # Create a hyperlink using HTML anchor tag + hyperlink = {"url": article_url, + "title": description} + news_list.append(hyperlink) + return news_list + + async def fetch_url(company_name): # Get the news url's for given company name or symbol + url = f"https://gnews.io/api/v4/search?q={company_name}&token={GNEWS_API_KEY}&lang=en" + response = requests.get(url) + articles = response.json().get('articles', []) + # Return a list of titles and descriptions with hyperlinks + url_list = [] + for article in articles: + article_url = article.get('url', 'No url') + url_list.append(article_url) + return url_list + + # On agent startup printing address + @agent.on_event('startup') + async def agent_details(ctx: Context): + ctx.logger.info(f'Search Agent Address is {NewsAgent.address}') + + # On_query handler for news request + @agent.on_query(model=NewsRequest, replies={NewsResponse}) + async def query_handler(ctx: Context, sender: str, msg: NewsRequest): + try: + ctx.logger.info(f'Fetching news details for company_name: {msg.company_name}') + symbol = await fetch_symbol(msg.company_name) + ctx.logger.info(f' Symbol for company provided is {symbol}') + if symbol != None: #if company symbol fetch successfully getting news using ticker symbol else using the company name itself. + news_list = await fetch_news(symbol) + else: + news_list = await fetch_news(msg.company_name) + ctx.logger.info(str(news_list)) + await ctx.send(sender, NewsResponse(news_list=news_list)) + + except Exception as e: + error_message = f"Error fetching job details: {str(e)}" + ctx.logger.error(error_message) + # Ensure the error message is sent as a string + await ctx.send(sender, ErrorResponse(error=str(error_message))) + + # On_query handler for news_url request + @agent.on_query(model=UrlRequest, replies={UrlResponse}) + async def query_handler(ctx: Context, sender: str, msg: UrlRequest): + try: + ctx.logger.info(f'Fetching news url details for company_name: {msg.company_name}') + symbol = await fetch_symbol(msg.company_name) + ctx.logger.info(f' Symbol for company provided is {symbol}') + if symbol != None: + url_list = await fetch_url(symbol) + else: + url_list = await fetch_url(msg.company_name) + ctx.logger.info(str(url_list)) + await ctx.send(sender, UrlResponse(url_list=url_list)) + except Exception as e: + error_message = f"Error fetching job details: {str(e)}" + ctx.logger.error(error_message) + # Ensure the error message is sent as a string + await ctx.send(sender, ErrorResponse(error=str(error_message))) + ``` + Get your [Alphavantage ↗️](https://www.alphavantage.co/) and [Gnews ↗️](https://gnews.io/) API keys and update it in the virtual environment. diff --git a/pages/examples/intermediate/storage.mdx b/pages/examples/intermediate/storage.mdx index ac3ad2138..aa1f7a1d3 100644 --- a/pages/examples/intermediate/storage.mdx +++ b/pages/examples/intermediate/storage.mdx @@ -1,3 +1,5 @@ +import { CodeGroup } from "../../../components/code" + # Agents storage ## Introduction @@ -11,8 +13,9 @@ This file can be run on any platform supporting Python, with the necessary insta - [Agents storage functions ↗️](/guides/agents/intermediate/storage-function) ### The agent + - ```py copy filename="storage.py" + ```py copy filename="local-storage.py" from uagents import Agent, Context agent = Agent(name="bob") @@ -30,3 +33,18 @@ This file can be run on any platform supporting Python, with the necessary insta if __name__ == "__main__": agent.run() ``` + + ```py copy filename="hosted-storage.py" + from uagents import Agent, Context + + @agent.on_event("startup") + async def initialize_storage(ctx: Context): + ctx.storage.set("count", 0) + + @agent.on_interval(period=1.0) + async def on_interval(ctx: Context): + current_count = ctx.storage.get("count") + ctx.logger.info(f"My count is: {current_count}") + ctx.storage.set("count", current_count + 1) + ``` + \ No newline at end of file diff --git a/pages/examples/intermediate/table-booking-demo.mdx b/pages/examples/intermediate/table-booking-demo.mdx index f4a3de4e9..d5a62b991 100644 --- a/pages/examples/intermediate/table-booking-demo.mdx +++ b/pages/examples/intermediate/table-booking-demo.mdx @@ -1,3 +1,5 @@ +import { CodeGroup } from "../../../components/code" + # Table booking service with Agents ## Introduction @@ -19,7 +21,8 @@ This example shows how to use Agents to create a table booking service at a rest #### Query table - ```py copy filename="query.py" + + ```py copy filename="local-query.py" from typing import List from uagents import Context, Model, Protocol @@ -73,9 +76,66 @@ This example shows how to use Agents to create a table booking service at a rest await ctx.send(sender, TotalQueries(total_queries=total_queries)) ``` + ```py copy filename="hosted-query.py" + from typing import List + + from uagents import Context, Model, Protocol + + class TableStatus(Model): + seats: int + time_start: int + time_end: int + + class QueryTableRequest(Model): + guests: int + time_start: int + duration: int + + class QueryTableResponse(Model): + tables: List[int] + + class GetTotalQueries(Model): + pass + + class TotalQueries(Model): + total_queries: int + query_proto = Protocol() + + @query_proto.on_message(model=QueryTableRequest, replies=QueryTableResponse) + async def handle_query_request(ctx: Context, sender: str, msg: QueryTableRequest): + tables = { + int(num): TableStatus(**status) + for ( + num, + status, + ) in ctx.storage.items() + if isinstance(num, int) + } + available_tables = [] + for number, status in tables.items(): + if ( + status.seats >= msg.guests + and status.time_start <= msg.time_start + and status.time_end >= msg.time_start + msg.duration + ): + available_tables.append(int(number)) + ctx.logger.info(f"Query: {msg}. Available tables: {available_tables}.") + await ctx.send(sender, QueryTableResponse(tables=available_tables)) + total_queries = int(ctx.storage.get("total_queries") or 0) + ctx.storage.set("total_queries", total_queries + 1) + + @query_proto.on_query(model=GetTotalQueries, replies=TotalQueries) + async def handle_get_total_queries(ctx: Context, sender: str, _msg: GetTotalQueries): + total_queries = int(ctx.storage.get("total_queries") or 0) + await ctx.send(sender, TotalQueries(total_queries=total_queries)) + ``` + + #### Book table - ```py copy filename="book.py" + + + ```py copy filename="local-book.py" from uagents import Context, Model, Protocol from .query import TableStatus @@ -112,11 +172,50 @@ This example shows how to use Agents to create a table booking service at a rest await ctx.send(sender, BookTableResponse(success=success)) ``` + ```py copy filename="hosted-book.py" + from uagents import Context, Model, Protocol + from query import TableStatus + + class BookTableRequest(Model): + table_number: int + time_start: int + duration: int + + class BookTableResponse(Model): + success: bool + + book_proto = Protocol() + @book_proto.on_message(model=BookTableRequest, replies=BookTableResponse) + async def handle_book_request(ctx: Context, sender: str, msg: BookTableRequest): + tables = { + int(num): TableStatus(**status) + for ( + num, + status, + ) in ctx.storage.items() + if isinstance(num, int) + } + table = tables[msg.table_number] + if ( + table.time_start <= msg.time_start + and table.time_end >= msg.time_start + msg.duration + ): + success = True + table.time_start = msg.time_start + msg.duration + ctx.storage.set(msg.table_number, table.dict()) + else: + success = False + # send the response + await ctx.send(sender, BookTableResponse(success=success)) + ``` + + ### The Agents #### Restaurant - ```py copy filename="restaurant.py" + + ```py copy filename="local-restaurant.py" from uagents import Agent, Context from uagents.setup import fund_agent_if_low from protocols.book import book_proto @@ -148,9 +247,32 @@ This example shows how to use Agents to create a table booking service at a rest restaurant.run() ``` + ```py copy filename="hosted-restaurant.py" + from uagents import Agent, Context + from book import book_proto + from query import query_proto, TableStatus + + # build the restaurant agent from stock protocols + agent.include(query_proto) + agent.include(book_proto) + + TABLES = { + 1: TableStatus(seats=2, time_start=16, time_end=22), + 2: TableStatus(seats=4, time_start=19, time_end=21), + 3: TableStatus(seats=4, time_start=17, time_end=19), + } + + # set the table availability information in the restaurant protocols + for (number, status) in TABLES.items(): + agent._storage.set(number, status.dict()) + ``` + + #### Customer/user - ```py copy filename="user.py" + + + ```py copy filename="local-user.py" from protocols.book import BookTableRequest, BookTableResponse from protocols.query import ( QueryTableRequest, @@ -218,6 +340,61 @@ This example shows how to use Agents to create a table booking service at a rest user.run() ``` + ```py copy filename="hosted-user.py" + from book import BookTableRequest, BookTableResponse + from query import ( + QueryTableRequest, + QueryTableResponse, + ) + from uagents import Agent, Context + + RESTAURANT_ADDRESS = "agent1qw50wcs4nd723ya9j8mwxglnhs2kzzhh0et0yl34vr75hualsyqvqdzl990" + + table_query = QueryTableRequest( + guests=3, + time_start=19, + duration=2, + ) + + # This on_interval agent function performs a request on a defined period + @agent.on_interval(period=3.0, messages=QueryTableRequest) + async def interval(ctx: Context): + completed = ctx.storage.get("completed") + + if not completed: + await ctx.send(RESTAURANT_ADDRESS, table_query) + + @agent.on_message(QueryTableResponse, replies={BookTableRequest}) + async def handle_query_response(ctx: Context, sender: str, msg: QueryTableResponse): + if len(msg.tables) > 0: + ctx.logger.info("There is a free table, attempting to book one now") + + table_number = msg.tables[0] + + request = BookTableRequest( + table_number=table_number, + time_start=table_query.time_start, + duration=table_query.duration, + ) + + await ctx.send(sender, request) + + else: + + ctx.logger.info("No free tables - nothing more to do") + ctx.storage.set("completed", True) + + @agent.on_message(BookTableResponse, replies=set()) + async def handle_book_response(ctx: Context, _sender: str, msg: BookTableResponse): + if msg.success: + ctx.logger.info("Table reservation was successful") + + else: + ctx.logger.info("Table reservation was UNSUCCESSFUL") + + ctx.storage.set("completed", True) + ``` + ### Expected output - Restaurant: