# **AI Server**

*ai-server-sdk* is a python client SDK to connect to the AI Server

## Using this package you can:

 - Inference with Models you have acces to within the server
 - Create Pandas DataFrame from Databases connections
 - Pull Storage objects
 - Run pixel and get the direct output or full json response.
 - Pull data products from an existing insight using REST API.

## **Install**

    pip install ai-server-sdk

or

    pip install ai-server-sdk[full]

  *Note*: The `full` option installs optional dependencies for langchain support.

## **Usage**

To interract with an ai-server instance, import the `ai_server` package and connect via RESTServer.

*Note*: secret and access keys are required


### Setup
```python
>>> from ai_server import ServerClient

# define access keys
>>> loginKeys = {"secretKey":"<your_secret_key>","accessKey":"<your_access_key>"}

# create connection object by passing in the secret key, access key and base url for the api
>>> server_connection = ServerClient(
...     access_key=loginKeys['accessKey'],
...     secret_key=loginKeys['secretKey'],
...     base='<Your deployed server Monolith URL>'
... )
```

### Inference with different Model Engines
```python
# import the model engine class for the ai_server package
>>> from ai_server import ModelEngine

>>> model = ModelEngine(
...     engine_id="2c6de0ff-62e0-4dd0-8380-782ac4d40245", 
...     insight_id=server_connection.cur_insight
... )

# define a question and grab the engine id from the server
>>> model.ask(question = 'What is the capital of France?')
[{'response': 'The capital of France is Paris.',
  'messageId': '0a80c2ce-76f9-4466-b2a2-8455e4cab34a',
  'roomId': '28261853-0e41-49b0-8a50-df34e8c62a19'}]
```

### Interact with a Vector Database by adding document(s), querying, and removing document(s)
```python
# import the vector engine class for the ai_server package
>>> from ai_server import VectorEngine

# initialize the connection to the vector database
>>> vectorEngine = VectorEngine(
...     engine_id="221a50a4-060c-4aa8-8b7c-e2bc97ee3396", 
...     insight_id=server_connection.cur_insight
... )

# Add document(s) that have been uploaded to the insight
>>> vectorEngine.addDocument(file_paths = ['fileName1.pdf', 'fileName2.pdf', ..., 'fileNameX.pdf'])

# Perform a nearest neighbor search on the embedded documents
>>> vectorEngine.nearestNeighbor(search_statement = 'Sample Search Statement', limit = 5)

# List all the documents the vector database currently comprises of
>>> vectorEngine.listDocuments()

# Remove document(s) from the vector database
>>> vectorEngine.removeDocument(file_names = ['fileName1.pdf', 'fileName2.pdf', ..., 'fileNameX.pdf'])
```

### Connect to Databases and execute create, read, and delete operations

#### Run the passed string query against the engine.  The query passed must be in the structure that the specific engine implementation.
```python
# import the database engine class for the ai_server package
>>> from ai_server import DatabaseEngine

# Create an relation to database based on the engine identifier
>>> database = DatabaseEngine(
...     engine_id="4a1f9466-4e6d-49cd-894d-7d22182344cd", 
...     insight_id=server_connection.cur_insight
... )
>>> database.execQuery(query='SELECT PATIENT, HEIGHT, WEIGHT FROM diab LIMIT 4')
```
|    |   PATIENT |   HEIGHT |   WEIGHT |
|---:|----------:|---------:|---------:|
|  0 |     20337 |       64 |      114 |
|  1 |      3750 |       64 |      161 |
|  2 |     40785 |       67 |      187 |
|  3 |     12778 |       72 |      145 |

#### Run the passed string query against the engine as an insert query. Query must be in the structure that the specific engine implementation
```python
>>> database.insertData(query = 'INSERT INTO table_name (column1, column2, column3, ...) VALUES (value1, value2, value3, ...)')
```

#### Run an update query on the database
```python
>>> database.updateData(query = 'UPDATE table_name set column1=value1 where age=19')
```

#### Run a delete query on the database
```python
>>> database.removeData(query='DELETE FROM diab WHERE age=19;')
```

### Run Function Engines
```python
# import the function engine class for the ai_server package
>>> from ai_server import FunctionEngine

# initialize the connection ot the function engine
>>> function = FunctionEngine(
...     engine_id="f3a4c8b2-7f3e-4d04-8c1f-2b0e3dabf5e9", 
...     insight_id=server_connection.cur_insight
... )
>>> function.execute({"lat":"37.540","lon":"77.4360"})
'{"cloud_pct": 2, "temp": 28, "feels_like": 27, "humidity": 20, "min_temp": 28, "max_temp": 28, "wind_speed": 5, "wind_degrees": 352, "sunrise": 1716420915, "sunset": 1716472746}'
```

### Using REST API to pull data product from an Insight
```python
# define the Project ID
>>> projectId = '30991037-1e73-49f5-99d3-f28210e6b95c'

# define the Insight ID
>>> inishgtId = '26b373b3-cd52-452c-a987-0adb8817bf73'

# define the SQL for the data product you want to query within the insight
>>> sql = 'select * FROM DATA_PRODUCT_123'

# if you dont provide one of the following, it will ask you to provide it via prompt
>>> diabetes_df = server_connection.import_data_product(project_id = projectId, insight_id = inishgtId, sql = sql)
>>> diabetes_df.head()
```
|    |   AGE |   PATIENT |   WEIGHT |
|---:|------:|----------:|---------:|
|  0 |    19 |      4823 |      119 |
|  1 |    19 |     17790 |      135 |
|  2 |    20 |      1041 |      159 |
|  3 |    20 |      2763 |      274 |
|  4 |    20 |      3750 |      161 |


### Get the output or JSON response of any pixel
```python
# run the pixel and get the output
>>> server_connection.run_pixel('1+1')
2

# run the pixel and get the entire json response
>>> server_connection.run_pixel('1+1', full_response=True)
{'insightID': '8b419eaf-df7d-4a7f-869e-8d7d59bbfde8',
 'sessionTimeRemaining': '7196',
 'pixelReturn': [{'pixelId': '3',
   'pixelExpression': '1 + 1 ;',
   'isMeta': False,
   'output': 2,
   'operationType': ['OPERATION']}]}
```

---