# Using SmartHub

## Overview

The primary function of the SmartHub is to connect multiple SmartAdapters and offer a centralized location for managing the events from these associated adapters. It provides intuitive design-time UI editors that enable developers to easily select and incorporate endpoints and adapters into the container currently being designed.

Furthermore, a SmartHub automatically scans its container for methods that are marked with the `[SmartTool.Tool]` attribute. These methods are seamlessly integrated as tools into the SmartAdapters associated with the SmartHub. The tools that are imported from the container operate within the context of the container itself. Consequently, there is no need to invoke the UseTools or UseTool methods in this scenario.

## How to Use

To utilize a SmartHub instance, you have two options: you can either drag and drop it from the toolbox onto a design surface (refer to the [Getting Started](/ai/concepts/getting-started.md) page for more details) or you can instantiate the component programmatically. When creating the SmartHub instance through code, you have the option to specify a container for the component, although this is not mandatory. This flexibility allows developers to integrate the SmartHub instance into their applications in a manner that best fits their workflow and project structure.

{% tabs %}
{% tab title="C#" %}

```csharp
var smartHub = new SmartHub();
// or var smartHub = new SmartHub(container);
smartHub.Endpoint = new OpenAIEndpoint { ApiKey = "..." };
```

{% endtab %}

{% tab title="VB.NET" %}

```vbnet
Dim smartHub As New SmartHub()
' or Dim smartHub As New SmartHub(container)
smartHub.Endpoint = New OpenAIEndpoint With {.ApiKey = "..."}
```

{% endtab %}
{% endtabs %}

Using a SmartHub is required only when using one of the adapters. Otherwise, you can access all Wisej.AI features without setting up a SmartHub. It is entirely possible to instantiate and utilize any the SmartPrompt or SmartSession classes independently of a SmartHub.

However, if your project requires centralized management of certain events, monitoring the utilization of AI providers from a unified location, or the automatic importation of tools defined in a container, the SmartHub class becomes particularly useful.

In addition to offering a centralized hub for multiple adapters, the SmartHub class provides advanced functionality designed to streamline the processes of document ingestion and embedding. This includes the capability to perform similarity queries and calculate similarity scores between vectors with ease.

The following code snippet illustrates the simplest method to convert, vectorize, and store a document into a vector database. This streamlined process is achieved with just a single line of code, powered by the Wisej.AI services.

{% tabs %}
{% tab title="C#" %}

```csharp
var embeddedDoc = await smartHub.IngestDocumentAsync(
    Application.MapPath("Files\\Q4-FinancialReport.pdf"),
    "Financials\\Q4\\Report.pdf");
```

{% endtab %}

{% tab title="VB.NET" %}

```vbnet
Dim embeddedDoc = Await smartHub.IngestDocumentAsync(
    Application.MapPath("Files\Q4-FinancialReport.pdf"),
    "Financials\Q4\Report.pdf")
```

{% endtab %}
{% endtabs %}

This line of code involves several services that work together in a sequence to convert and store a PDF document as a an [EmbeddedDocument](/ai/components/api/embeddings/wisej.ai.embeddings.embeddeddocument.md). First, the `IDocumentConversionService` is used to convert the PDF document into a text format, allowing for easier manipulation and processing of its contents. Next, the `ITextSplitterService` takes over to divide the converted text into overlapping chunks. These chunks assist in maximizing context and relevance when the text is later analyzed or queried. Following this, the `IEmbeddingGenerationService` processes these text chunks, transforming them into vectors via embedding, which is a numerical representation that captures the semantic meaning of the text. Finally, the `IEmbeddingStorageService` saves these generated vectors, accompanying text chunks, and associated metadata into a vector database. This storage format facilitates efficient retrieval and utilization of the document's content in future operations.

Once documents are ingested, they become accessible to all components of Wisej.AI through the `DocumentSearchTools` object. This integration ensures that any part of the Wisej.AI framework that requires access to the processed documents can retrieve and utilize them as needed.

## Properties

<table><thead><tr><th width="223">Name</th><th>Description</th></tr></thead><tbody><tr><td>ContainerControl</td><td>Control associated with the SmartHub. Can be a Page, a Form or any ContainerControl in Wisej.NET.</td></tr><tr><td>Culture</td><td>Overrides the default language of the application. If you want your AI to speak a particular language without changing the application's culture, use this property.</td></tr><tr><td>DataSource</td><td>Optional data source object that can be used to resolve parameters in prompts. Parametere are delimited by {{}}. I.e. {{UserName}}</td></tr><tr><td>Endpoint</td><td>Endpoint used by the adapters associated to the SmartHub.</td></tr></tbody></table>

## Examples

Below are some examples demonstrating some of the functionalities offered by the SmartHub component:

1. **Simple Logging Example:** This example illustrates a straightforward approach, which involves logging all usage reported by the AI provider.
2. **Advanced Tool Processing Example:** This example is more complex, enabling the SmartHub to either pre-process or post-process tool invocations.
3. **Quick Similarity Score:** Calculates similarity between a query and an an array of text strings using smartHub’s async embedding-based similarity function.

{% code title="Simple Logging Example" %}

```csharp
this.smartHub1.AfterResponseReceive += (s, e) => {
    // the last message is the assistant response and contains the reported usage
    var usage = e.Messages.Last().Usage;
    LogUsage(usage.InputTokens, usage.OutputTokens);
}

// Or, if you like to use markup code

this.smartHub1.OnAfterResponseReceive(e => {
    // the last message is the assistant response and contains the reported usage
    var usage = e.Messages.Last().Usage;
    LogUsage(usage.InputTokens, usage.OutputTokens);
});

```

{% endcode %}

{% code title="Advanced Tool Processing Example" %}

```csharp
this.smartHub1.OnBeforeInvokeTool(e => {

    var context = e.ToolContext;
    var tool = e.ToolContext.Tool;
    if (tool.Name == "read_sales")
    {
        // if the AI is trying to read the sales from
        // a table named "Secret", block it.
        if (tool.Parameters[0].Name == "TableName" &&
            Object.Equals(context.Arguments["TableName"], "Secret"))
        {
            // set our return value.
            // it can be a concrete value or you may also return
            // a Task for asynchronous operations.
            context.ReturnValue = "You are not allowed to read this data.";

            // prevent Wisej.AI from calling the tool.
            e.Handled = true;
        }
    }
});

this.smartHub1.OnAfterInvokeTool(e => {

    var context = e.ToolContext;
    var tool = e.ToolContext.Tool;
    if (tool.Name == "run_scada_command")
    {
        Log($"Executed SCACA command: {context.Arguments[tool.Parameters[0].Name]}");
        Log($"  >> Result: {context.ReturnValue}");
    }
});
```

{% endcode %}

<pre class="language-csharp" data-title=""><code class="lang-csharp">var smartHub = new SmartHub {
    Endpoint = new OpenAIEndpoint { ApiKey = "..."}
};

<strong>var score = await smartHub.SimilarityScoreAsync(
</strong>    "Tell me about machine learning and computer science.",
    [
        "The quick brown fox jumps over the lazy dog.",
        "Artificial Intelligence is transforming the world.",
        "I love to play piano in my free time.",
        "Space exploration is a fascinating subject.",
        "Python is a popular programming language."
    ]);
    
Console.WriteLine(String.Join("\n", score.Select(s => s.ToString())));

// Output
/*
0.08265121
0.3526109
0.1460542
0.2151319
0.1906273
*/
</code></pre>

{% hint style="warning" %}
When generating embeddings with the default `IEmbeddingGenerationService`, ensure the correct `ApiKey` is available to the service’s endpoint—either set as an environment variable or specified in the [`ApiKeys.json`](https://docs.wisej.com/ai/components/pages/ZKRA5LS0XtSW01P9zy6k#apikeys.json-file) file.
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.wisej.com/ai/components/hub.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
