ORM integration
This guide demonstrates how to configure an AEA to interact with a database using python-sql
objects.
Discussion
Object-relational-mapping (ORM) is the idea of being able to write SQL queries, using the object-oriented paradigm of your preferred programming language. The scope of the specific demo is to demonstrate how to create an easy configurable AEA that reads data from a database using ORMs.
- We assume, that you followed the guide for the thermometer-skills.
- We assume, that we have a database
genericdb.db
with table namedata
. This table contains the following columnstimestamp
andthermometer
- We assume, that we have a hardware thermometer sensor that adds the readings in the
genericdb
database (although you can follow the guide without having access to a sensor).
Since the AEA framework enables us to use third-party libraries hosted on PyPI we can directly reference the external dependencies. The aea install
command will install each dependency that the specific AEA needs and which is listed in the skill's YAML file.
Communication
This diagram shows the communication between the various entities as data is successfully sold by the seller AEA to the buyer.
Preparation instructions
Dependencies
Follow the Preliminaries and Installation sections from the AEA quick start.
Demo instructions
A demo to run a scenario with a true ledger transaction on Fetch.ai testnet
network or Ethereum ropsten
network. This demo assumes the buyer trusts the seller AEA to send the data upon successful payment.
Create the seller AEA
First, fetch the seller AEA, which will provide data:
aea fetch fetchai/thermometer_aea:0.18.0 --alias my_thermometer_aea
cd my_thermometer_aea
aea install
aea build
Alternatively, create from scratch.
The following steps create the seller from scratch:
aea create my_thermometer_aea
cd my_thermometer_aea
aea add connection fetchai/p2p_libp2p:0.14.0
aea add connection fetchai/soef:0.15.0
aea add connection fetchai/ledger:0.12.0
aea add skill fetchai/thermometer:0.18.0
aea install
aea build
aea config set agent.default_connection fetchai/p2p_libp2p:0.14.0
aea config set --type dict agent.default_routing \
'{
"fetchai/ledger_api:0.9.0": "fetchai/ledger:0.12.0",
"fetchai/oef_search:0.12.0": "fetchai/soef:0.15.0"
}'
Create the buyer client
In another terminal, fetch the AEA that will query the seller AEA.
aea fetch fetchai/thermometer_client:0.19.0 --alias my_thermometer_client
cd my_thermometer_client
aea install
aea build
Alternatively, create from scratch.
The following steps create the car data client from scratch:
aea create my_thermometer_client
cd my_thermometer_client
aea add connection fetchai/p2p_libp2p:0.14.0
aea add connection fetchai/soef:0.15.0
aea add connection fetchai/ledger:0.12.0
aea add skill fetchai/thermometer_client:0.18.0
aea install
aea build
aea config set agent.default_connection fetchai/p2p_libp2p:0.14.0
aea config set --type dict agent.default_routing \
'{
"fetchai/ledger_api:0.9.0": "fetchai/ledger:0.12.0",
"fetchai/oef_search:0.12.0": "fetchai/soef:0.15.0"
}'
Add keys for the thermometer AEA
First, create the private key for the thermometer AEA based on the network you want to transact. To generate and add a private-public key pair for Fetch.ai AgentLand
use:
aea generate-key fetchai
aea add-key fetchai fetchai_private_key.txt
Next, create a private key used to secure the AEA's communications:
aea generate-key fetchai fetchai_connection_private_key.txt
aea add-key fetchai fetchai_connection_private_key.txt --connection
Finally, certify the key for use by the connections that request that:
aea issue-certificates
Add keys and generate wealth for the thermometer client AEA
The thermometer client needs to have some wealth to purchase the thermometer information.
First, create the private key for the thermometer client AEA based on the network you want to transact. To generate and add a private-public key pair for Fetch.ai use:
aea generate-key fetchai
aea add-key fetchai fetchai_private_key.txt
Then, create some wealth for your car data buyer based on the network you want to transact with. On the Fetch.ai AgentLand
network:
aea generate-wealth fetchai
Next, create a private key used to secure the AEA's communications:
aea generate-key fetchai fetchai_connection_private_key.txt
aea add-key fetchai fetchai_connection_private_key.txt --connection
Then, create some wealth for your thermometer client based on the network you want to transact with. On the Fetch.ai testnet
network:
aea generate-key fetchai
Update the seller and buyer AEA skill configurations
In my_thermometer_aea/vendor/fetchai/skills/thermometer/skill.yaml
, replace the data_for_sale
with your data:
models:
...
strategy:
args:
currency_id: FET
data_for_sale:
temperature: 26
has_data_source: false
is_ledger_tx: true
ledger_id: fetchai
location:
latitude: 51.5194
longitude: 0.127
service_data:
key: seller_service
value: thermometer_data
service_id: thermometer_data
unit_price: 10
class_name: Strategy
dependencies:
SQLAlchemy: {}
data_model
and the service_data
are used to register the service in the SOEF search node and make your agent discoverable. The name of each attribute must be a key in the service_data
dictionary.
In my_thermometer_client/vendor/fetchai/skills/thermometer_client/skill.yaml
) ensure you have matching data.
models:
...
strategy:
args:
currency_id: FET
is_ledger_tx: true
ledger_id: fetchai
location:
latitude: 51.5194
longitude: 0.127
max_negotiations: 1
max_tx_fee: 1
max_unit_price: 20
search_query:
constraint_type: ==
search_key: seller_service
search_value: thermometer_data
search_radius: 5.0
service_id: thermometer_data
class_name: Strategy
After changing the skill configuration files you should run the following command for both agents to install each dependency:
aea install
Modify the seller's strategy
Before being able to modify a package we need to eject it from vendor:
aea eject skill fetchai/thermometer:0.18.0
This will move the package to your skills
directory and reset the version to 0.1.0
and the author to your author handle.
Open the strategy.py
(in my_thermometer_aea/skills/thermometer/strategy.py
) with your IDE and modify the following.
Import the newly installed library to your strategy.
import sqlalchemy as db
__init__
function to match the following code:
class Strategy(GenericStrategy):
"""This class defines a strategy for the agent."""
def __init__(self, **kwargs) -> None:
"""
Initialize the strategy of the agent.
:param register_as: determines whether the agent registers as seller, buyer or both
:param search_for: determines whether the agent searches for sellers, buyers or both
:return: None
"""
self._db_engine = db.create_engine("sqlite:///genericdb.db")
self._tbl = self.create_database_and_table()
self.insert_data()
super().__init__(**kwargs)
At the end of the file modify the collect_from_data_source
function :
def collect_from_data_source(self) -> Dict[str, str]:
"""Implement the logic to collect data."""
connection = self._db_engine.connect()
query = db.select([self._tbl])
result_proxy = connection.execute(query)
data_points = result_proxy.fetchall()
return {"data": json.dumps(list(map(tuple, data_points)))}
def create_database_and_table(self):
"""Creates a database and a table to store the data if not exists."""
metadata = db.MetaData()
tbl = db.Table(
"data",
metadata,
db.Column("timestamp", db.Integer()),
db.Column("temprature", db.String(255), nullable=False),
)
metadata.create_all(self._db_engine)
return tbl
def insert_data(self):
"""Insert data in the database."""
connection = self._db_engine.connect()
for _ in range(10):
query = db.insert(self._tbl).values( # nosec
timestamp=time.time(), temprature=str(random.randrange(10, 25))
)
connection.execute(query)
After modifying the skill we need to fingerprint it:
aea fingerprint skill {YOUR_AUTHOR_HANDLE}/thermometer:0.1.0
Run both AEAs
Run both AEAs from their respective terminals.
First, run the thermometer AEA:
aea run
Once you see a message of the form To join its network use multiaddr 'SOME_ADDRESS'
take note of the address. (Alternatively, use aea get-multiaddress fetchai -c -i fetchai/p2p_libp2p:0.14.0 -u public_uri
to retrieve the address.)
This is the entry peer address for the local agent communication network created by the thermometer AEA.
Then, in the thermometer client, run this command (replace SOME_ADDRESS
with the correct value as described above):
aea config set --type dict vendor.fetchai.connections.p2p_libp2p.config \
'{
"delegate_uri": "127.0.0.1:11001",
"entry_peers": ["SOME_ADDRESS"],
"local_uri": "127.0.0.1:9001",
"log_file": "libp2p_node.log",
"public_uri": "127.0.0.1:9001"
}'
Then run the thermometer client AEA:
aea run
You will see that the AEAs negotiate and then transact using the configured testnet.
Delete the AEAs
When you're done, go up a level and delete the AEAs.
cd ..
aea delete my_thermometer_aea
aea delete my_thermometer_client