bittensor.core.dendrite#

Attributes#

Classes#

Dendrite

The Dendrite class represents the abstracted implementation of a network client module.

DendriteMixin

The Dendrite class represents the abstracted implementation of a network client module.

Functions#

call(self, *args, **kwargs)

Module Contents#

bittensor.core.dendrite.BaseModel: bittensor.utils.registration.torch.nn.Module | object#
bittensor.core.dendrite.DENDRITE_DEFAULT_ERROR = ('422', 'Failed to parse response')#
bittensor.core.dendrite.DENDRITE_ERROR_MAPPING: dict[Type[Exception], tuple]#
class bittensor.core.dendrite.Dendrite(wallet=None)#

Bases: DendriteMixin, BaseModel

The Dendrite class represents the abstracted implementation of a network client module.

In the brain analogy, dendrites receive signals from other neurons (in this case, network servers or axons), and the Dendrite class here is designed to send requests to those endpoint to receive inputs.

This class includes a wallet or keypair used for signing messages, and methods for making HTTP requests to the network servers. It also provides functionalities such as logging network requests and processing server responses.

Parameters:
  • keypair (Option[Union[bittensor_wallet.Wallet, substrateinterface.Keypair]]) – The wallet or keypair used for signing messages.

  • external_ip (str) – The external IP address of the local system.

  • synapse_history (list) – A list of Synapse objects representing the historical responses.

  • wallet (Optional[Union[bittensor_wallet.Wallet, bittensor_wallet.Keypair]])

__str__()#

Returns a string representation of the Dendrite object.

Return type:

str

__repr__()#

Returns a string representation of the Dendrite object, acting as a fallback for __str__().

Return type:

str

query(self, *args, **kwargs) Synapse | list[Synapse]#

Makes synchronous requests to one or multiple target Axons and returns responses.

Return type:

list[Union[AsyncGenerator[Any, Any], bittensor.core.synapse.Synapse, bittensor.core.stream.StreamingSynapse]]

forward(self, axons, synapse=Synapse(), timeout=12, deserialize=True, run_async=True, streaming=False) Synapse#

Asynchronously sends requests to one or multiple Axons and collates their responses.

Parameters:
Return type:

list[Union[AsyncGenerator[Any, Any], bittensor.core.synapse.Synapse, bittensor.core.stream.StreamingSynapse]]

call(self, target_axon, synapse=Synapse(), timeout=12.0, deserialize=True) Synapse#

Asynchronously sends a request to a specified Axon and processes the response.

Parameters:
Return type:

bittensor.core.synapse.Synapse

call_stream(self, target_axon, synapse=Synapse(), timeout=12.0, deserialize=True) AsyncGenerator[Synapse, None]#

Sends a request to a specified Axon and yields an AsyncGenerator that contains streaming response chunks before finally yielding the filled Synapse as the final element.

Parameters:
Return type:

AsyncGenerator[Any, Any]

preprocess_synapse_for_request(self, target_axon_info, synapse, timeout=12.0) Synapse#

Preprocesses the synapse for making a request, including building headers and signing.

Parameters:
Return type:

bittensor.core.synapse.Synapse

process_server_response(self, server_response, json_response, local_synapse)#

Processes the server response, updates the local synapse state, and merges headers.

Parameters:
close_session(self)#

Synchronously closes the internal aiohttp client session.

aclose_session(self)#

Asynchronously closes the internal aiohttp client session.

Note

When working with async aiohttp client sessions, it is recommended to use a context manager.

Example with a context manager:

async with dendrite(wallet = bittensor_wallet.Wallet()) as d:
    print(d)
    d( <axon> ) # ping axon
    d( [<axons>] ) # ping multiple
    d( Axon(), Synapse )

However, you are able to safely call dendrite.query() without a context manager in a synchronous setting.

Example without a context manager:

d = dendrite(wallet = bittensor_wallet.Wallet() )
print(d)
d( <axon> ) # ping axon
d( [<axons>] ) # ping multiple
d( bittensor.core.axon.Axon, bittensor.core.synapse.Synapse )

Initializes the Dendrite object, setting up essential properties.

Parameters:

wallet (Optional[Union[bittensor_wallet.Wallet, substrateinterface.Keypair]]) – The user’s wallet or keypair used for signing messages. Defaults to None, in which case a new bittensor_wallet.Wallet().hotkey() is generated and used.

class bittensor.core.dendrite.DendriteMixin(wallet=None)#

The Dendrite class represents the abstracted implementation of a network client module.

In the brain analogy, dendrites receive signals from other neurons (in this case, network servers or axons), and the Dendrite class here is designed to send requests to those endpoint to receive inputs.

This class includes a wallet or keypair used for signing messages, and methods for making HTTP requests to the network servers. It also provides functionalities such as logging network requests and processing server responses.

Parameters:
  • keypair (Option[Union[bittensor_wallet.Wallet, substrateinterface.Keypair]]) – The wallet or keypair used for signing messages.

  • external_ip (str) – The external IP address of the local system.

  • synapse_history (list) – A list of Synapse objects representing the historical responses.

  • wallet (Optional[Union[bittensor_wallet.Wallet, bittensor_wallet.Keypair]])

__str__()#

Returns a string representation of the Dendrite object.

Return type:

str

__repr__()#

Returns a string representation of the Dendrite object, acting as a fallback for __str__().

Return type:

str

query(self, *args, **kwargs) Synapse | list[Synapse]#

Makes synchronous requests to one or multiple target Axons and returns responses.

Return type:

list[Union[AsyncGenerator[Any, Any], bittensor.core.synapse.Synapse, bittensor.core.stream.StreamingSynapse]]

forward(self, axons, synapse=Synapse(), timeout=12, deserialize=True, run_async=True, streaming=False) Synapse#

Asynchronously sends requests to one or multiple Axons and collates their responses.

Parameters:
Return type:

list[Union[AsyncGenerator[Any, Any], bittensor.core.synapse.Synapse, bittensor.core.stream.StreamingSynapse]]

call(self, target_axon, synapse=Synapse(), timeout=12.0, deserialize=True) Synapse#

Asynchronously sends a request to a specified Axon and processes the response.

Parameters:
Return type:

bittensor.core.synapse.Synapse

call_stream(self, target_axon, synapse=Synapse(), timeout=12.0, deserialize=True) AsyncGenerator[Synapse, None]#

Sends a request to a specified Axon and yields an AsyncGenerator that contains streaming response chunks before finally yielding the filled Synapse as the final element.

Parameters:
Return type:

AsyncGenerator[Any, Any]

preprocess_synapse_for_request(self, target_axon_info, synapse, timeout=12.0) Synapse#

Preprocesses the synapse for making a request, including building headers and signing.

Parameters:
Return type:

bittensor.core.synapse.Synapse

process_server_response(self, server_response, json_response, local_synapse)#

Processes the server response, updates the local synapse state, and merges headers.

Parameters:
close_session(self)#

Synchronously closes the internal aiohttp client session.

aclose_session(self)#

Asynchronously closes the internal aiohttp client session.

Note

When working with async aiohttp client sessions, it is recommended to use a context manager.

Example with a context manager:

async with dendrite(wallet = bittensor_wallet.Wallet()) as d:
    print(d)
    d( <axon> ) # ping axon
    d( [<axons>] ) # ping multiple
    d( Axon(), Synapse )

However, you are able to safely call dendrite.query() without a context manager in a synchronous setting.

Example without a context manager:

d = dendrite(wallet = bittensor_wallet.Wallet() )
print(d)
d( <axon> ) # ping axon
d( [<axons>] ) # ping multiple
d( bittensor.core.axon.Axon, bittensor.core.synapse.Synapse )

Initializes the Dendrite object, setting up essential properties.

Parameters:

wallet (Optional[Union[bittensor_wallet.Wallet, substrateinterface.Keypair]]) – The user’s wallet or keypair used for signing messages. Defaults to None, in which case a new bittensor_wallet.Wallet().hotkey() is generated and used.

async __aenter__()#

Asynchronous context manager entry method.

Enables the use of the async with statement with the Dendrite instance. When entering the context, the current instance of the class is returned, making it accessible within the asynchronous context.

Returns:

The current instance of the Dendrite class.

Return type:

Dendrite

Usage::
async with Dendrite() as dendrite:

await dendrite.some_async_method()

async __aexit__(exc_type, exc_value, traceback)#

Asynchronous context manager exit method.

Ensures proper cleanup when exiting the async with context. This method will close the aiohttp client session asynchronously, releasing any tied resources.

Parameters:
  • exc_type (Type[BaseException]) – The type of exception that was raised.

  • exc_value (BaseException) – The instance of exception that was raised.

  • traceback (TracebackType) – A traceback object encapsulating the call stack at the point where the exception was raised.

Usage::

import bittensor

wallet = bittensor.Wallet() async with bittensor.Dendrite(wallet=wallet) as dendrite:

await dendrite.some_async_method()

Note

This automatically closes the session by calling __aexit__() after the context closes.

__del__()#

Dendrite destructor.

This method is invoked when the Dendrite instance is about to be destroyed. The destructor ensures that the aiohttp client session is closed before the instance is fully destroyed, releasing any remaining resources.

Note

Relying on the destructor for cleanup can be unpredictable. It is recommended to explicitly close sessions using the provided methods or the async with context manager.

Usage:

dendrite = Dendrite()
# ... some operations ...
del dendrite  # This will implicitly invoke the __del__ method and close the session.
__repr__()#

Returns a string representation of the Dendrite object, acting as a fallback for __str__().

Returns:

The string representation of the Dendrite object in the format dendrite(<user_wallet_address>)().

Return type:

str

__str__()#

Returns a string representation of the Dendrite object.

Returns:

The string representation of the Dendrite object in the format dendrite(<user_wallet_address>)().

Return type:

str

_get_endpoint_url(target_axon, request_name)#

Constructs the endpoint URL for a network request to a target axon.

This internal method generates the full HTTP URL for sending a request to the specified axon. The URL includes the IP address and port of the target axon, along with the specific request name. It differentiates between requests to the local system (using ‘0.0.0.0’) and external systems.

Parameters:
  • target_axon – The target axon object containing IP and port information.

  • request_name – The specific name of the request being made.

Returns:

A string representing the complete HTTP URL for the request.

Return type:

str

_log_incoming_response(synapse)#

Logs information about incoming responses for debugging and monitoring.

Similar to _log_outgoing_request(), this method logs essential details of the incoming responses, including the size of the response, synapse name, axon details, status code, and status message. This logging is vital for troubleshooting and understanding the network interactions in Bittensor.

Parameters:

synapse (bittensor.core.synapse.Synapse) – The synapse object representing the received response.

_log_outgoing_request(synapse)#

Logs information about outgoing requests for debugging purposes.

This internal method logs key details about each outgoing request, including the size of the request, the name of the synapse, the axon’s details, and a success indicator. This information is crucial for monitoring and debugging network activity within the Bittensor network.

To turn on debug messages, set the environment variable BITTENSOR_DEBUG to 1, or call the bittensor debug method like so:

Example:

import bittensor
bittensor.debug()
Parameters:

synapse (bittensor.core.synapse.Synapse) – The synapse object representing the request being sent.

_session: aiohttp.ClientSession | None = None#
async aclose_session()#

Asynchronously closes the internal aiohttp client session.

This method is the asynchronous counterpart to the close_session() method. It should be used in asynchronous contexts to ensure that the aiohttp client session is closed properly. The method releases resources associated with the session, such as open connections and internal buffers, which is essential for resource management in asynchronous applications.

Example

Usage::

When finished with dendrite in an asynchronous context await dendrite_instance.aclose_session().

Example

Usage::
async with dendrite_instance:

# Operations using dendrite pass

# The session will be closed automatically after the above block

async call(target_axon, synapse=Synapse(), timeout=12.0, deserialize=True)#

Asynchronously sends a request to a specified Axon and processes the response.

This function establishes a connection with a specified Axon, sends the encapsulated data through the Synapse object, waits for a response, processes it, and then returns the updated Synapse object.

Parameters:
Returns:

The Synapse object, updated with the response data from the Axon.

Return type:

bittensor.core.synapse.Synapse

async call_stream(target_axon, synapse=Synapse(), timeout=12.0, deserialize=True)#

Sends a request to a specified Axon and yields streaming responses.

Similar to call, but designed for scenarios where the Axon sends back data in multiple chunks or streams. The function yields each chunk as it is received. This is useful for processing large responses piece by piece without waiting for the entire data to be transmitted.

Parameters:
Yields:

object – Each yielded object contains a chunk of the arbitrary response data from the Axon. bittensor.core.synapse.Synapse: After the AsyncGenerator has been exhausted, yields the final filled Synapse.

Return type:

AsyncGenerator[Any, Any]

close_session()#

Closes the internal aiohttp client session synchronously.

This method ensures the proper closure and cleanup of the aiohttp client session, releasing any resources like open connections and internal buffers. It is crucial for preventing resource leakage and should be called when the dendrite instance is no longer in use, especially in synchronous contexts.

Note

This method utilizes asyncio’s event loop to close the session asynchronously from a synchronous context. It is advisable to use this method only when asynchronous context management is not feasible.

Usage:

When finished with dendrite in a synchronous context dendrite_instance.close_session().

external_ip#
async forward(axons, synapse=Synapse(), timeout=12, deserialize=True, run_async=True, streaming=False)#

Asynchronously sends requests to one or multiple Axons and collates their responses.

This function acts as a bridge for sending multiple requests concurrently or sequentially based on the provided parameters. It checks the type of the target Axons, preprocesses the requests, and then sends them off. After getting the responses, it processes and collates them into a unified format.

When querying an Axon that sends a single response, this function returns a Synapse object containing the response data. If multiple Axons are queried, a list of Synapse objects is returned, each containing the response from the corresponding Axon.

For example:

...
import bittensor
wallet = bittensor.Wallet()                     # Initialize a wallet
synapse = bittensor.Synapse(...)                # Create a synapse object that contains query data
dendrite = bittensor.Dendrite(wallet = wallet)  # Initialize a dendrite instance
netuid = ...                                    # Provide subnet ID
metagraph = bittensor.Metagraph(netuid)         # Initialize a metagraph instance
axons = metagraph.axons                         # Create a list of axons to query
responses = await dendrite(axons, synapse)      # Send the query to all axons and await the responses

When querying an Axon that sends back data in chunks using the Dendrite, this function returns an AsyncGenerator that yields each chunk as it is received. The generator can be iterated over to process each chunk individually.

For example:

...
dendrite = bittensor.Dendrite(wallet = wallet)
async for chunk in dendrite.forward(axons, synapse, timeout, deserialize, run_async, streaming):
    # Process each chunk here
    print(chunk)
Parameters:
Returns:

If a single Axon is targeted, returns its response. If multiple Axons are targeted, returns a list of their responses.

Return type:

Union[AsyncGenerator, bittensor.core.synapse.Synapse, list[bittensor.core.synapse.Synapse]]

keypair#
log_exception(exception)#

Logs an exception with a unique identifier.

This method generates a unique UUID for the error, extracts the error type, and logs the error message using Bittensor’s logging system.

Parameters:

exception (Exception) – The exception object to be logged.

Returns:

None

preprocess_synapse_for_request(target_axon_info, synapse, timeout=12.0)#

Preprocesses the synapse for making a request. This includes building headers for Dendrite and Axon and signing the request.

Parameters:
Returns:

The preprocessed synapse.

Return type:

bittensor.core.synapse.Synapse

process_error_message(synapse, request_name, exception)#

Handles exceptions that occur during network requests, updating the synapse with appropriate status codes and messages.

This method interprets different types of exceptions and sets the corresponding status code and message in the synapse object. It covers common network errors such as connection issues and timeouts.

Parameters:
  • synapse (bittensor.core.synapse.Synapse) – The synapse object associated with the request.

  • request_name (str) – The name of the request during which the exception occurred.

  • exception (Exception) – The exception object caught during the request.

Returns:

The updated synapse object with the error status code and message.

Return type:

Synapse (bittensor.core.synapse.Synapse)

Note

This method updates the synapse object in-place.

process_server_response(server_response, json_response, local_synapse)#

Processes the server response, updates the local synapse state with the server’s state and merges headers set by the server.

Parameters:
Raises:

None – But errors in attribute setting are silently ignored.

query(*args, **kwargs)#

Makes a synchronous request to multiple target Axons and returns the server responses.

Cleanup is automatically handled and sessions are closed upon completed requests.

Parameters:
  • axons (Union[list[Union[bittensor.core.chain_data.axon_info.AxonInfo, 'bittensor.core.axon.Axon']], Union['bittensor.core.chain_data.axon_info.AxonInfo', 'bittensor.core.axon.Axon']]) – The list of target Axon information.

  • synapse (Optional[bittensor.core.synapse.Synapse]) – The Synapse object. Defaults to Synapse().

  • timeout (Optional[float]) – The request timeout duration in seconds. Defaults to 12.0 seconds.

Returns:

If a single target axon is provided, returns the response from that axon. If multiple target axons are provided, returns a list of responses from all target axons.

Return type:

Union[bittensor.core.synapse.Synapse, list[bittensor.core.synapse.Synapse]]

property session: aiohttp.ClientSession#

An asynchronous property that provides access to the internal aiohttp client session.

This property ensures the management of HTTP connections in an efficient way. It lazily initializes the aiohttp.ClientSession on its first use. The session is then reused for subsequent HTTP requests, offering performance benefits by reusing underlying connections.

This is used internally by the dendrite when querying axons, and should not be used directly unless absolutely necessary for your application.

Returns:

The active aiohttp client session instance. If no session exists, a new one is created and returned. This session is used for asynchronous HTTP requests within the dendrite, adhering to the async nature of the network interactions in the Bittensor framework.

Return type:

aiohttp.ClientSession

Example usage:

import bittensor                                # Import bittensor
wallet = bittensor.Wallet( ... )                # Initialize a wallet
dendrite = bittensor.Dendrite(wallet=wallet)   # Initialize a dendrite instance with the wallet

async with (await dendrite.session).post(       # Use the session to make an HTTP POST request
    url,                                        # URL to send the request to
    headers={...},                              # Headers dict to be sent with the request
    json={...},                                 # JSON body data to be sent with the request
    timeout=10,                                 # Timeout duration in seconds
) as response:
    json_response = await response.json()       # Extract the JSON response from the server
synapse_history: list = []#
uuid#
async bittensor.core.dendrite.call(self, *args, **kwargs)#